From 12876675680a8542e45135124d9c87bf4f41d3ab Mon Sep 17 00:00:00 2001 From: Ares <75481906+ice-ares@users.noreply.github.com> Date: Thu, 11 Jul 2024 03:45:00 +0300 Subject: [PATCH] made logic to share t1 referrals be triggered automatically when user reaches 25 verified t1 referrals as opposed to on user input --- go.mod | 24 ++++++++++----------- go.sum | 48 ++++++++++++++++++++--------------------- miner/contract.go | 5 ++++- miner/miner.go | 19 +++++++++++++++- miner/mining.go | 23 +++++++++++++++++++- miner/mining_test.go | 2 ++ model/model.go | 22 +++++++++++++++++-- tokenomics/contract.go | 4 ++++ tokenomics/kyc.go | 2 +- tokenomics/mining.go | 5 +++-- tokenomics/users.go | 49 +++++++++++++++++++++++++++++++++--------- 11 files changed, 149 insertions(+), 54 deletions(-) diff --git a/go.mod b/go.mod index 12d5dec..3cbdce8 100644 --- a/go.mod +++ b/go.mod @@ -3,14 +3,14 @@ module github.com/ice-blockchain/freezer go 1.22 require ( - github.com/ClickHouse/ch-go v0.61.5 - github.com/alitto/pond v1.9.0 + github.com/ClickHouse/ch-go v0.62.0 + github.com/alitto/pond v1.9.1 github.com/bsm/redislock v0.9.4 github.com/cenkalti/backoff/v4 v4.3.0 github.com/ethereum/go-ethereum v1.14.6 github.com/goccy/go-json v0.10.3 github.com/hashicorp/go-multierror v1.1.1 - github.com/ice-blockchain/eskimo v1.366.0 + github.com/ice-blockchain/eskimo v1.369.0 github.com/ice-blockchain/go-tarantool-client v0.0.0-20230327200757-4fc71fa3f7bb github.com/ice-blockchain/wintr v1.144.0 github.com/imroc/req/v3 v3.43.7 @@ -27,12 +27,12 @@ require ( require ( cloud.google.com/go v0.115.0 // indirect - cloud.google.com/go/auth v0.6.1 // indirect - cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect - cloud.google.com/go/compute/metadata v0.4.0 // indirect + cloud.google.com/go/auth v0.7.0 // indirect + cloud.google.com/go/auth/oauth2adapt v0.2.3 // indirect + cloud.google.com/go/compute/metadata v0.5.0 // indirect cloud.google.com/go/firestore v1.15.0 // indirect - cloud.google.com/go/iam v1.1.10 // indirect - cloud.google.com/go/longrunning v0.5.9 // indirect + cloud.google.com/go/iam v1.1.11 // indirect + cloud.google.com/go/longrunning v0.5.10 // indirect cloud.google.com/go/storage v1.43.0 // indirect cosmossdk.io/math v1.3.0 // indirect dario.cat/mergo v1.0.0 // indirect @@ -209,11 +209,11 @@ require ( golang.org/x/text v0.16.0 // indirect golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.23.0 // indirect - google.golang.org/api v0.187.0 // indirect + google.golang.org/api v0.188.0 // indirect google.golang.org/appengine/v2 v2.0.6 // indirect - google.golang.org/genproto v0.0.0-20240708141625-4ad9e859172b // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240708141625-4ad9e859172b // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240708141625-4ad9e859172b // indirect + google.golang.org/genproto v0.0.0-20240709173604-40e1e62336c5 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240709173604-40e1e62336c5 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240709173604-40e1e62336c5 // indirect google.golang.org/grpc v1.65.0 // indirect google.golang.org/protobuf v1.34.2 // indirect gopkg.in/ini.v1 v1.67.0 // indirect diff --git a/go.sum b/go.sum index a1c116b..bc1190e 100644 --- a/go.sum +++ b/go.sum @@ -1,18 +1,18 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.115.0 h1:CnFSK6Xo3lDYRoBKEcAtia6VSC837/ZkJuRduSFnr14= cloud.google.com/go v0.115.0/go.mod h1:8jIM5vVgoAEoiVxQ/O4BFTfHqulPZgs/ufEzMcFMdWU= -cloud.google.com/go/auth v0.6.1 h1:T0Zw1XM5c1GlpN2HYr2s+m3vr1p2wy+8VN+Z1FKxW38= -cloud.google.com/go/auth v0.6.1/go.mod h1:eFHG7zDzbXHKmjJddFG/rBlcGp6t25SwRUiEQSlO4x4= -cloud.google.com/go/auth/oauth2adapt v0.2.2 h1:+TTV8aXpjeChS9M+aTtN/TjdQnzJvmzKFt//oWu7HX4= -cloud.google.com/go/auth/oauth2adapt v0.2.2/go.mod h1:wcYjgpZI9+Yu7LyYBg4pqSiaRkfEK3GQcpb7C/uyF1Q= -cloud.google.com/go/compute/metadata v0.4.0 h1:vHzJCWaM4g8XIcm8kopr3XmDA4Gy/lblD3EhhSux05c= -cloud.google.com/go/compute/metadata v0.4.0/go.mod h1:SIQh1Kkb4ZJ8zJ874fqVkslA29PRXuleyj6vOzlbK7M= +cloud.google.com/go/auth v0.7.0 h1:kf/x9B3WTbBUHkC+1VS8wwwli9TzhSt0vSTVBmMR8Ts= +cloud.google.com/go/auth v0.7.0/go.mod h1:D+WqdrpcjmiCgWrXmLLxOVq1GACoE36chW6KXoEvuIw= +cloud.google.com/go/auth/oauth2adapt v0.2.3 h1:MlxF+Pd3OmSudg/b1yZ5lJwoXCEaeedAguodky1PcKI= +cloud.google.com/go/auth/oauth2adapt v0.2.3/go.mod h1:tMQXOfZzFuNuUxOypHlQEXgdfX5cuhwU+ffUuXRJE8I= +cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY= +cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= cloud.google.com/go/firestore v1.15.0 h1:/k8ppuWOtNuDHt2tsRV42yI21uaGnKDEQnRFeBpbFF8= cloud.google.com/go/firestore v1.15.0/go.mod h1:GWOxFXcv8GZUtYpWHw/w6IuYNux/BtmeVTMmjrm4yhk= -cloud.google.com/go/iam v1.1.10 h1:ZSAr64oEhQSClwBL670MsJAW5/RLiC6kfw3Bqmd5ZDI= -cloud.google.com/go/iam v1.1.10/go.mod h1:iEgMq62sg8zx446GCaijmA2Miwg5o3UbO+nI47WHJps= -cloud.google.com/go/longrunning v0.5.9 h1:haH9pAuXdPAMqHvzX0zlWQigXT7B0+CL4/2nXXdBo5k= -cloud.google.com/go/longrunning v0.5.9/go.mod h1:HD+0l9/OOW0za6UWdKJtXoFAX/BGg/3Wj8p10NeWF7c= +cloud.google.com/go/iam v1.1.11 h1:0mQ8UKSfdHLut6pH9FM3bI55KWR46ketn0PuXleDyxw= +cloud.google.com/go/iam v1.1.11/go.mod h1:biXoiLWYIKntto2joP+62sd9uW5EpkZmKIvfNcTWlnQ= +cloud.google.com/go/longrunning v0.5.10 h1:eB/BniENNRKhjz/xgiillrdcH3G74TGSl3BXinGlI7E= +cloud.google.com/go/longrunning v0.5.10/go.mod h1:tljz5guTr5oc/qhlUjBlk7UAIFMOGuPNxkNDZXlLics= cloud.google.com/go/storage v1.43.0 h1:CcxnSohZwizt4LCzQHWvBf1/kvtHUn7gk9QERXPyXFs= cloud.google.com/go/storage v1.43.0/go.mod h1:ajvxEa7WmZS1PxvKRq4bq0tFT3vMd502JwstCcYv0Q0= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= @@ -24,8 +24,8 @@ firebase.google.com/go/v4 v4.14.1/go.mod h1:fgk2XshgNDEKaioKco+AouiegSI9oTWVqRaB github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/ClickHouse/ch-go v0.61.5 h1:zwR8QbYI0tsMiEcze/uIMK+Tz1D3XZXLdNrlaOpeEI4= -github.com/ClickHouse/ch-go v0.61.5/go.mod h1:s1LJW/F/LcFs5HJnuogFMta50kKDO0lf9zzfrbl0RQg= +github.com/ClickHouse/ch-go v0.62.0 h1:eXH0hytXeCEEZHgMvOX9IiW7wqBb4w1MJMp9rArbkrc= +github.com/ClickHouse/ch-go v0.62.0/go.mod h1:uzso52/PD9+gZj7tL6XAo8/EYDrx7CIwNF4c6PnO6S0= github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= @@ -38,8 +38,8 @@ github.com/Microsoft/hcsshim v0.12.4 h1:Ev7YUMHAHoWNm+aDSPzc5W9s6E2jyL1szpVDJeZ/ github.com/Microsoft/hcsshim v0.12.4/go.mod h1:Iyl1WVpZzr+UkzjekHZbV8o5Z9ZkxNGx6CtY2Qg/JVQ= github.com/VictoriaMetrics/fastcache v1.12.2 h1:N0y9ASrJ0F6h0QaC3o6uJb3NIZ9VKLjCM7NQbSmF7WI= github.com/VictoriaMetrics/fastcache v1.12.2/go.mod h1:AmC+Nzz1+3G2eCPapF6UcsnkThDcMsQicp4xDukwJYI= -github.com/alitto/pond v1.9.0 h1:B8BrvXyKe97NK9LHuRsQAOmpRnsp6GJ7mCg1Cgitczo= -github.com/alitto/pond v1.9.0/go.mod h1:xQn3P/sHTYcU/1BR3i86IGIrilcrGC2LiS+E2+CJWsI= +github.com/alitto/pond v1.9.1 h1:OfCpIrMyrWJpn34f647DcFmUxjK8+7Nu3eoVN/WTP+o= +github.com/alitto/pond v1.9.1/go.mod h1:xQn3P/sHTYcU/1BR3i86IGIrilcrGC2LiS+E2+CJWsI= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= @@ -300,8 +300,8 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ice-blockchain/eskimo v1.366.0 h1:brqw1rVWXhn7vtYUqzb8HguzjenMc9CSeYxbdidrBwk= -github.com/ice-blockchain/eskimo v1.366.0/go.mod h1:c2Yp7QwFzJvdrcbZSOmM4jY/Li6Wbo1LVnoouJrAe8g= +github.com/ice-blockchain/eskimo v1.369.0 h1:DFguku6xR4rb8G1Ay4LAh0s6qzYPnoKsO28uFJGvAko= +github.com/ice-blockchain/eskimo v1.369.0/go.mod h1:l4MZKGo/Lpq+LFr65HUAGc/SvN4IclA0kpFqXjjQsZ8= github.com/ice-blockchain/go-tarantool-client v0.0.0-20230327200757-4fc71fa3f7bb h1:8TnFP3mc7O+tc44kv2e0/TpZKnEVUaKH+UstwfBwRkk= github.com/ice-blockchain/go-tarantool-client v0.0.0-20230327200757-4fc71fa3f7bb/go.mod h1:ZsQU7i3mxhgBBu43Oev7WPFbIjP4TniN/b1UPNGbrq8= github.com/ice-blockchain/wintr v1.144.0 h1:YQE0olkPdSI6AOlw7r/j5jGI6uLciZQrvXFIkN4C4l4= @@ -676,8 +676,8 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -google.golang.org/api v0.187.0 h1:Mxs7VATVC2v7CY+7Xwm4ndkX71hpElcvx0D1Ji/p1eo= -google.golang.org/api v0.187.0/go.mod h1:KIHlTc4x7N7gKKuVsdmfBXN13yEEWXWFURWY6SBp2gk= +google.golang.org/api v0.188.0 h1:51y8fJ/b1AaaBRJr4yWm96fPcuxSo0JcegXE3DaHQHw= +google.golang.org/api v0.188.0/go.mod h1:VR0d+2SIiWOYG3r/jdm7adPW9hI2aRv9ETOSCQ9Beag= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine/v2 v2.0.6 h1:LvPZLGuchSBslPBp+LAhihBeGSiRh1myRoYK4NtuBIw= @@ -685,12 +685,12 @@ google.golang.org/appengine/v2 v2.0.6/go.mod h1:WoEXGoXNfa0mLvaH5sV3ZSGXwVmy8yf7 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20240708141625-4ad9e859172b h1:dSTjko30weBaMj3eERKc0ZVXW4GudCswM3m+P++ukU0= -google.golang.org/genproto v0.0.0-20240708141625-4ad9e859172b/go.mod h1:FfBgJBJg9GcpPvKIuHSZ/aE1g2ecGL74upMzGZjiGEY= -google.golang.org/genproto/googleapis/api v0.0.0-20240708141625-4ad9e859172b h1:y/kpOWeX2pWERnbsvh/hF+Zmo69wVmjyZhstreXQQeA= -google.golang.org/genproto/googleapis/api v0.0.0-20240708141625-4ad9e859172b/go.mod h1:mw8MG/Qz5wfgYr6VqVCiZcHe/GJEfI+oGGDCohaVgB0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240708141625-4ad9e859172b h1:04+jVzTs2XBnOZcPsLnmrTGqltqJbZQ1Ey26hjYdQQ0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240708141625-4ad9e859172b/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= +google.golang.org/genproto v0.0.0-20240709173604-40e1e62336c5 h1:ORprMx6Xqr56pGwKXMnVEFBI0k7OIcHI0Rx92/rKypo= +google.golang.org/genproto v0.0.0-20240709173604-40e1e62336c5/go.mod h1:FfBgJBJg9GcpPvKIuHSZ/aE1g2ecGL74upMzGZjiGEY= +google.golang.org/genproto/googleapis/api v0.0.0-20240709173604-40e1e62336c5 h1:a/Z0jgw03aJ2rQnp5PlPpznJqJft0HyvyrcUcxgzPwY= +google.golang.org/genproto/googleapis/api v0.0.0-20240709173604-40e1e62336c5/go.mod h1:mw8MG/Qz5wfgYr6VqVCiZcHe/GJEfI+oGGDCohaVgB0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240709173604-40e1e62336c5 h1:SbSDUWW1PAO24TNpLdeheoYPd7kllICcLU52x6eD4kQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240709173604-40e1e62336c5/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= diff --git a/miner/contract.go b/miner/contract.go index 2299fc7..70c1e01 100644 --- a/miner/contract.go +++ b/miner/contract.go @@ -67,14 +67,15 @@ type ( model.LatestDeviceField UpdatedUser model.BalanceSoloPendingField + model.BalanceT1WelcomeBonusPendingField model.BalanceT1PendingField model.BalanceT2PendingField model.PreStakingBonusField model.PreStakingAllocationField model.ExtraBonusField + model.VerifiedT1ReferralsField model.ActiveT1ReferralsField model.ActiveT2ReferralsField - model.T1ReferralsSharingEnabledField } UpdatedUser struct { // This is public only because we have to embed it, and it has to be if so. @@ -92,6 +93,7 @@ type ( model.BalanceT2EthereumPendingField model.KYCQuizDisabledResettableField model.KYCQuizCompletedResettableField + model.WelcomeBonusV2AppliedField model.UserIDField model.DeserializedUsersKey model.IDT0Field @@ -101,6 +103,7 @@ type ( model.BalanceTotalMintedField model.BalanceTotalSlashedField model.BalanceSoloPendingAppliedField + model.BalanceT1WelcomeBonusPendingAppliedField model.BalanceT1PendingAppliedField model.BalanceT2PendingAppliedField model.BalanceSoloField diff --git a/miner/miner.go b/miner/miner.go index 31bebe9..f9f0bec 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -168,6 +168,7 @@ func (m *miner) mine(ctx context.Context, workerNumber int64) { t1ReferralsToIncrementActiveValue, t2ReferralsToIncrementActiveValue = make(map[int64]int32, batchSize), make(map[int64]int32, batchSize) t1ReferralsThatStoppedMining, t2ReferralsThatStoppedMining = make(map[int64]uint32, batchSize), make(map[int64]uint32, batchSize) balanceT1EthereumIncr, balanceT2EthereumIncr = make(map[int64]float64, batchSize), make(map[int64]float64, batchSize) + balanceT1WelcomeBonusIncr = make(map[int64]float64, batchSize) pendingBalancesForTMinus1, pendingBalancesForT0 = make(map[int64]float64, batchSize), make(map[int64]float64, batchSize) referralsThatStoppedMining = make([]*referralThatStoppedMining, 0, batchSize) coinDistributions = make([]*coindistribution.ByEarnerForReview, 0, 4*batchSize) @@ -246,6 +247,9 @@ func (m *miner) mine(ctx context.Context, workerNumber int64) { for k := range t2ReferralsToIncrementActiveValue { delete(t2ReferralsToIncrementActiveValue, k) } + for k := range balanceT1WelcomeBonusIncr { + delete(balanceT1WelcomeBonusIncr, k) + } for k := range balanceT1EthereumIncr { delete(balanceT1EthereumIncr, k) } @@ -362,6 +366,7 @@ func (m *miner) mine(ctx context.Context, workerNumber int64) { if isAdvancedTeamDisabled(usr.LatestDevice) { usr.ActiveT2Referrals = 0 } + beforeWelcomeBonusV2Applied := usr.WelcomeBonusV2Applied == nil || !*usr.WelcomeBonusV2Applied updatedUser, shouldGenerateHistory, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(now, usr, t0Ref, tMinus1Ref) if shouldGenerateHistory { syncQuizUserIDs = append(syncQuizUserIDs, usr.UserID) @@ -409,6 +414,13 @@ func (m *miner) mine(ctx context.Context, workerNumber int64) { if t0Ref != nil && t0Ref.ID != 0 && pendingAmountForT0 != 0 { pendingBalancesForT0[t0Ref.ID] += pendingAmountForT0 } + if afterWelcomeBonusV2Applied := updatedUser.WelcomeBonusV2Applied != nil && *usr.WelcomeBonusV2Applied; t0Ref != nil && t0Ref.ID != 0 && !beforeWelcomeBonusV2Applied && afterWelcomeBonusV2Applied { + idT0 := t0Ref.ID + if idT0 < 0 { + idT0 *= -1 + } + balanceT1WelcomeBonusIncr[idT0] += tokenomics.WelcomeBonusV2Amount + } updatedUsers = append(updatedUsers, &updatedUser.UpdatedUser) } else { if updUsr := updateT0AndTMinus1ReferralsForUserHasNeverMined(usr); updUsr != nil { @@ -553,7 +565,7 @@ func (m *miner) mine(ctx context.Context, workerNumber int64) { var pipeliner redis.Pipeliner var transactional bool - if len(pendingBalancesForTMinus1)+len(pendingBalancesForT0)+len(balanceT1EthereumIncr)+len(balanceT2EthereumIncr)+len(t1ReferralsToIncrementActiveValue)+len(t2ReferralsToIncrementActiveValue)+len(referralsCountGuardOnlyUpdatedUsers)+len(t1ReferralsThatStoppedMining)+len(t2ReferralsThatStoppedMining)+len(extraBonusOnlyUpdatedUsers)+len(referralsUpdated)+len(userGlobalRanks) > 0 { + if len(pendingBalancesForTMinus1)+len(pendingBalancesForT0)+len(balanceT1WelcomeBonusIncr)+len(balanceT1EthereumIncr)+len(balanceT2EthereumIncr)+len(t1ReferralsToIncrementActiveValue)+len(t2ReferralsToIncrementActiveValue)+len(referralsCountGuardOnlyUpdatedUsers)+len(t1ReferralsThatStoppedMining)+len(t2ReferralsThatStoppedMining)+len(extraBonusOnlyUpdatedUsers)+len(referralsUpdated)+len(userGlobalRanks) > 0 { pipeliner = m.db.TxPipeline() transactional = true } else { @@ -615,6 +627,11 @@ func (m *miner) mine(ctx context.Context, workerNumber int64) { return err } } + for idT0, amount := range balanceT1WelcomeBonusIncr { + if err := pipeliner.HIncrByFloat(reqCtx, model.SerializedUsersKey(idT0), "balance_t1_welcome_bonus_pending", amount).Err(); err != nil { + return err + } + } for idT0, amount := range balanceT1EthereumIncr { if amount == 0 { continue diff --git a/miner/mining.go b/miner/mining.go index d09602e..a944d73 100644 --- a/miner/mining.go +++ b/miner/mining.go @@ -5,6 +5,7 @@ package miner import ( "math" + "github.com/ice-blockchain/freezer/model" "github.com/ice-blockchain/freezer/tokenomics" "github.com/ice-blockchain/wintr/time" ) @@ -143,7 +144,7 @@ func mine(now *time.Time, usr *user, t0Ref, tMinus1Ref *referral) (updatedUser * } activeT1Referrals := int32(0) if updatedUser.MiningBoostLevelIndex != nil { - if updatedUser.T1ReferralsSharingEnabled { + if updatedUser.IsVerified() && updatedUser.VerifiedT1Referrals >= 25 { activeT1Referrals = int32((*cfg.miningBoostLevels.Load())[int(*updatedUser.MiningBoostLevelIndex)].MaxT1Referrals) } else { activeT1Referrals = int32(math.Min(float64((*cfg.miningBoostLevels.Load())[int(*updatedUser.MiningBoostLevelIndex)].MaxT1Referrals), float64(updatedUser.ActiveT1Referrals))) @@ -183,6 +184,19 @@ func mine(now *time.Time, usr *user, t0Ref, tMinus1Ref *referral) (updatedUser * } } + if updatedUser.BalanceT1WelcomeBonusPendingApplied < 25*tokenomics.WelcomeBonusV2Amount { + if unAppliedT1WelcomeBonusPending := updatedUser.BalanceT1WelcomeBonusPending - updatedUser.BalanceT1WelcomeBonusPendingApplied; unAppliedT1WelcomeBonusPending == 0 { + updatedUser.BalanceT1WelcomeBonusPending = 0 + updatedUser.BalanceT1WelcomeBonusPendingApplied = 0 + } else { + unAppliedT1Pending += min(unAppliedT1WelcomeBonusPending, 25*tokenomics.WelcomeBonusV2Amount-updatedUser.BalanceT1WelcomeBonusPendingApplied) + updatedUser.BalanceT1WelcomeBonusPendingApplied = min(updatedUser.BalanceT1WelcomeBonusPending, 25*tokenomics.WelcomeBonusV2Amount) + } + } else { + updatedUser.BalanceT1WelcomeBonusPending = 0 + updatedUser.BalanceT1WelcomeBonusPendingApplied = 0 + } + slashedAmount := (updatedUser.SlashingRateSolo + updatedUser.SlashingRateT0) * elapsedTimeFraction updatedUser.BalanceSolo -= updatedUser.SlashingRateSolo * elapsedTimeFraction @@ -238,6 +252,13 @@ func mine(now *time.Time, usr *user, t0Ref, tMinus1Ref *referral) (updatedUser * if usr.BalanceTotalPreStaking+usr.BalanceTotalStandard == 0 { slashedAmount = 0 } + if usr.WelcomeBonusV2Applied == nil || !*usr.WelcomeBonusV2Applied { + updatedUser.BalanceSolo += tokenomics.WelcomeBonusV2Amount - 10 + trueVal := model.FlexibleBool(true) + usr.WelcomeBonusV2Applied = &trueVal + } else { + usr.WelcomeBonusV2Applied = nil + } totalAmount := updatedUser.BalanceSolo + updatedUser.BalanceT0 + updatedUser.BalanceT1 + updatedUser.BalanceT2 updatedUser.BalanceTotalStandard, updatedUser.BalanceTotalPreStaking = tokenomics.ApplyPreStaking(totalAmount, updatedUser.PreStakingAllocation, updatedUser.PreStakingBonus) diff --git a/miner/mining_test.go b/miner/mining_test.go index 6a5dc5f..9808d37 100644 --- a/miner/mining_test.go +++ b/miner/mining_test.go @@ -28,6 +28,8 @@ func newUser() *user { u.CreatedAt = testTime u.MiningSessionSoloStartedAt = timeDelta(-stdlibtime.Hour) u.MiningSessionSoloEndedAt = timeDelta(23 * stdlibtime.Hour) + trueVal := model.FlexibleBool(true) + u.WelcomeBonusV2Applied = &trueVal return u } diff --git a/model/model.go b/model/model.go index 2663afc..67cb1ce 100644 --- a/model/model.go +++ b/model/model.go @@ -178,6 +178,9 @@ type ( BalanceT1PendingField struct { BalanceT1Pending float64 `redis:"balance_t1_pending,omitempty"` } + BalanceT1WelcomeBonusPendingField struct { + BalanceT1WelcomeBonusPending float64 `redis:"balance_t1_welcome_bonus_pending,omitempty"` + } BalanceT2PendingField struct { BalanceT2Pending float64 `redis:"balance_t2_pending,omitempty"` } @@ -187,6 +190,9 @@ type ( BalanceT1PendingAppliedField struct { BalanceT1PendingApplied float64 `redis:"balance_t1_pending_applied,omitempty"` } + BalanceT1WelcomeBonusPendingAppliedField struct { + BalanceT1WelcomeBonusPendingApplied float64 `redis:"balance_t1_welcome_bonus_pending_applied,omitempty"` + } BalanceT2PendingAppliedField struct { BalanceT2PendingApplied float64 `redis:"balance_t2_pending_applied,omitempty"` } @@ -325,8 +331,11 @@ type ( HideRankingField struct { HideRanking bool `redis:"hide_ranking" json:"-"` } - T1ReferralsSharingEnabledField struct { - T1ReferralsSharingEnabled bool `json:"t1ReferralsSharingEnabled" redis:"t1_referrals_sharing_enabled"` + WelcomeBonusV2AppliedField struct { + WelcomeBonusV2Applied *FlexibleBool `redis:"welcome_bonus_v2_applied,omitempty"` + } + VerifiedT1ReferralsField struct { + VerifiedT1Referrals uint64 `json:"verifiedT1ReferralCount,omitempty" redis:"verified_t1_referrals"` } CreatedAtField struct { CreatedAt *time.Time `json:"-" redis:"created_at"` @@ -521,6 +530,15 @@ func CalculateMiningStreak(now, start, end *time.Time, miningSessionDuration std return uint64(now.Sub(*start.Time) / miningSessionDuration) } +func (kyc *KYCState) IsVerified() bool { + return kyc != nil && kyc.KYCStepPassed >= users.LivenessDetectionKYCStep && + kyc.KYCStepsLastUpdatedAt != nil && kyc.KYCStepsCreatedAt != nil && + len(*kyc.KYCStepsCreatedAt) >= int(users.LivenessDetectionKYCStep) && + len(*kyc.KYCStepsLastUpdatedAt) >= int(users.LivenessDetectionKYCStep) && + !(*kyc.KYCStepsCreatedAt)[users.LivenessDetectionKYCStep-1].IsNil() && + !(*kyc.KYCStepsLastUpdatedAt)[users.LivenessDetectionKYCStep-1].IsNil() +} + func (kyc *KYCState) KYCStepPassedCorrectly(kycStep users.KYCStep) bool { kycStepBlocked := kycStep if kycStep == users.QuizKYCStep { diff --git a/tokenomics/contract.go b/tokenomics/contract.go index 1f5a9fb..9b64e80 100644 --- a/tokenomics/contract.go +++ b/tokenomics/contract.go @@ -29,6 +29,10 @@ const ( MaxPreStakingYears = 5 ) +const ( + WelcomeBonusV2Amount = 500.0 +) + const ( PositiveMiningRateType MiningRateType = "positive" NegativeMiningRateType MiningRateType = "negative" diff --git a/tokenomics/kyc.go b/tokenomics/kyc.go index 6381728..752c05f 100644 --- a/tokenomics/kyc.go +++ b/tokenomics/kyc.go @@ -491,9 +491,9 @@ func (r *repository) overrideKYCStateWithEskimoKYCState(ctx context.Context, use model.MiningBlockchainAccountAddressField ReferredBy string `json:"referredBy,omitempty" redis:"-"` model.KYCState + model.VerifiedT1ReferralsField model.DeserializedUsersKey model.HideRankingField - model.T1ReferralsSharingEnabledField KycFaceAvailable bool `json:"kycFaceAvailable" redis:"-"` } if err3 := json.Unmarshal(data, &usr); err3 != nil { diff --git a/tokenomics/mining.go b/tokenomics/mining.go index 42c1d60..9fbb462 100644 --- a/tokenomics/mining.go +++ b/tokenomics/mining.go @@ -174,6 +174,7 @@ func (r *repository) GetMiningSummary(ctx context.Context, userID string) (*Mini model.MiningSessionSoloEndedAtField model.ExtraBonusStartedAtField model.ExtraBonusLastClaimAvailableAtField + model.KYCState model.LatestDeviceField model.UserIDField model.BalanceSoloField @@ -189,13 +190,13 @@ func (r *repository) GetMiningSummary(ctx context.Context, userID string) (*Mini model.PreStakingBonusField model.ExtraBonusField model.PreStakingAllocationField + model.VerifiedT1ReferralsField model.IDT0Field model.ActiveT1ReferralsField model.ActiveT2ReferralsField model.ExtraBonusDaysClaimNotAvailableResettableField model.NewsSeenField model.KYCStepBlockedField - model.T1ReferralsSharingEnabledField }](ctx, r.db, model.SerializedUsersKey(id)) if err != nil || len(ms) == 0 { if err == nil { @@ -221,7 +222,7 @@ func (r *repository) GetMiningSummary(ctx context.Context, userID string) (*Mini maxMiningSessionDuration := r.cfg.maxMiningSessionDuration(ms[0].MiningBoostLevelIndexField) activeT1Referrals := int32(0) if ms[0].MiningBoostLevelIndex != nil { - if ms[0].T1ReferralsSharingEnabled { + if ms[0].IsVerified() && ms[0].VerifiedT1Referrals >= 25 { activeT1Referrals = int32((*r.cfg.MiningBoost.levels.Load())[int(*ms[0].MiningBoostLevelIndex)].MaxT1Referrals) } else { activeT1Referrals = int32(math.Min(float64((*r.cfg.MiningBoost.levels.Load())[int(*ms[0].MiningBoostLevelIndex)].MaxT1Referrals), float64(ms[0].ActiveT1Referrals))) diff --git a/tokenomics/users.go b/tokenomics/users.go index b3e3a6a..463c4fb 100644 --- a/tokenomics/users.go +++ b/tokenomics/users.go @@ -4,6 +4,7 @@ package tokenomics import ( "context" + "fmt" "strconv" "strings" stdlibtime "time" @@ -170,11 +171,11 @@ func (s *usersTableSource) replaceUser(ctx context.Context, usr *users.User) err model.CountryField model.MiningBlockchainAccountAddressField model.BlockchainAccountAddressField + model.VerifiedT1ReferralsField model.DeserializedUsersKey model.KYCStepPassedField model.KYCStepBlockedField model.HideRankingField - model.T1ReferralsSharingEnabledField } readOnlyUser struct { LocalUser @@ -214,16 +215,14 @@ func (s *usersTableSource) replaceUser(ctx context.Context, usr *users.User) err newPartialState.KYCStepsCreatedAt = &val } newPartialState.HideRanking = buildHideRanking(usr.HiddenProfileElements) - if usr.T1ReferralsSharingEnabled != nil { - newPartialState.T1ReferralsSharingEnabled = *usr.T1ReferralsSharingEnabled - } + newPartialState.VerifiedT1Referrals = usr.VerifiedT1ReferralCount if newPartialState.ProfilePictureName != dbUser[0].ProfilePictureName || newPartialState.Username != dbUser[0].Username || !strings.EqualFold(newPartialState.Country, dbUser[0].Country) || newPartialState.MiningBlockchainAccountAddress != dbUser[0].MiningBlockchainAccountAddress || newPartialState.BlockchainAccountAddress != dbUser[0].BlockchainAccountAddress || newPartialState.HideRanking != dbUser[0].HideRanking || - newPartialState.T1ReferralsSharingEnabled != dbUser[0].T1ReferralsSharingEnabled || + newPartialState.VerifiedT1Referrals != dbUser[0].VerifiedT1Referrals || (dbUser[0].CreatedAt.IsNil() || !newPartialState.CreatedAt.Equal(*dbUser[0].CreatedAt.Time)) || !newPartialState.KYCStepsCreatedAt.Equals(dbUser[0].KYCStepsCreatedAt) || !newPartialState.KYCStepsLastUpdatedAt.Equals(dbUser[0].KYCStepsLastUpdatedAt) || @@ -312,6 +311,35 @@ func (r *repository) updateReferredBy(ctx context.Context, id int64, oldIDT0, ol } } } + if localIDT0 := newPartialState.IDT0; localIDT0 != 0 { + if localIDT0 < 0 { + localIDT0 *= -1 + } + results, err4 := r.db.TxPipelined(ctx, func(pipeliner redis.Pipeliner) error { + if innerErr := pipeliner.HIncrBy(ctx, model.SerializedUsersKey(localIDT0), "balance_t1_welcome_bonus_pending", WelcomeBonusV2Amount).Err(); innerErr != nil { + return innerErr + } + + return pipeliner.HSet(ctx, newPartialState.Key(), storage.SerializeValue(newPartialState)...).Err() + }) + if err4 != nil { + return errors.Wrapf(err4, "failed to run TxPipelined for userID:%v", userID) + } + errs := make([]error, 0, len(results)) + for _, result := range results { + if innerErr := result.Err(); innerErr != nil { + errs = append(errs, errors.Wrapf(innerErr, "failed to run `%#v`", result.FullName())) + } + } + if mErrs := multierror.Append(nil, errs...); mErrs.ErrorOrNil() != nil { + return errors.Wrapf(mErrs.ErrorOrNil(), "failed to run TxPipelined for id:%v,id:%v", userID, id) + } + + *oldIDT0 = newPartialState.IDT0 + *oldTMinus1 = newPartialState.IDTMinus1 + + return nil + } *oldIDT0 = newPartialState.IDT0 *oldTMinus1 = newPartialState.IDTMinus1 @@ -413,16 +441,17 @@ elseif set_nx_reply == 0 then end return new_id `) - initUserScript = redis.NewScript(` + initUserScript = redis.NewScript(fmt.Sprintf(` local hlen_reply = redis.call('HLEN', KEYS[1]) if hlen_reply ~= 0 then return redis.error_reply('[2]race condition') end -redis.call('HSETNX', KEYS[1], 'balance_total_standard', 10.0) -redis.call('HSETNX', KEYS[1], 'balance_total_minted', 10.0) -redis.call('HSETNX', KEYS[1], 'balance_solo', 10.0) +redis.call('HSETNX', KEYS[1], 'balance_total_standard', %[1]v) +redis.call('HSETNX', KEYS[1], 'balance_total_minted', %[1]v) +redis.call('HSETNX', KEYS[1], 'balance_solo', %[1]v) +redis.call('HSETNX', KEYS[1], 'welcome_bonus_v2_applied', true) redis.call('HSETNX', KEYS[1], 'user_id', ARGV[1]) -`) +`, strconv.FormatFloat(WelcomeBonusV2Amount, 'f', 1, 64))) ) func GetOrInitInternalID(ctx context.Context, db storage.DB, userID string) (int64, error) {