Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Distribution changes. #225

Merged
merged 3 commits into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@ miner:
t1LimitCount: 2
welcomeBonusV2Amount: 500
t1ReferralsAllowedWithoutAnyMiningBoostLevel: false
dryRunDistribution: false
kyc/quiz:
maxResetCount: 0
maxAttemptsAllowed: 3
Expand Down Expand Up @@ -302,6 +303,16 @@ extra-bonus-notifier:
balance-synchronizer:
workers: 1
batchSize: 100
users: &users
wintr/connectors/storage/v2: &usersdb
runDDL: false
primaryURL: postgresql://root:pass@localhost:5433/eskimo
timeout: 90s
credentials:
user: root
password: pass
replicaURLs:
- postgresql://root:pass@localhost:5433/eskimo
tokenomics_test:
<<: *tokenomics
messageBroker:
Expand Down
26 changes: 16 additions & 10 deletions coin-distribution/DDL.sql
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,10 @@ CREATE TABLE IF NOT EXISTS coin_distributions_by_earner (
user_id text NOT NULL,
earner_user_id text NOT NULL,
eth_address text NOT NULL,
verified boolean NOT NULL DEFAULT FALSE,
PRIMARY KEY(day, user_id, earner_user_id))
WITH (FILLFACTOR = 70);
ALTER TABLE coin_distributions_by_earner ADD COLUMN IF NOT EXISTS verified boolean NOT NULL DEFAULT FALSE;

CREATE TABLE IF NOT EXISTS coin_distributions_pending_review (
created_at timestamp ,
Expand All @@ -77,7 +79,9 @@ CREATE TABLE IF NOT EXISTS coin_distributions_pending_review (
referred_by_username text NOT NULL,
user_id text NOT NULL,
eth_address text NOT NULL,
verified boolean NOT NULL DEFAULT FALSE,
PRIMARY KEY(day, user_id));
ALTER TABLE coin_distributions_pending_review ADD COLUMN IF NOT EXISTS verified boolean NOT NULL DEFAULT FALSE;

CREATE INDEX IF NOT EXISTS coin_distributions_pending_review_internal_id_ix ON coin_distributions_pending_review (internal_id NULLS FIRST);
CREATE INDEX IF NOT EXISTS coin_distributions_pending_review_created_at_ix ON coin_distributions_pending_review (created_at);
Expand Down Expand Up @@ -105,8 +109,9 @@ CREATE TABLE IF NOT EXISTS reviewed_coin_distributions (
eth_address text NOT NULL,
reviewer_user_id text NOT NULL,
decision text NOT NULL,
verified boolean NOT NULL DEFAULT FALSE,
PRIMARY KEY(user_id, day, review_day));

ALTER TABLE reviewed_coin_distributions ADD COLUMN IF NOT EXISTS verified boolean NOT NULL DEFAULT FALSE;
create or replace function approve_coin_distributions(reviewer_user_id text, process_immediately boolean, nested boolean)
returns RECORD
language plpgsql
Expand All @@ -119,8 +124,8 @@ BEGIN
select created_at, internal_id, day, iceflakes, user_id, eth_address
from coin_distributions_pending_review;

insert into reviewed_coin_distributions(reviewed_at, created_at, internal_id, ice, day, review_day, iceflakes, username, referred_by_username, user_id, eth_address, reviewer_user_id, decision)
select now, created_at, internal_id, ice, day, now::date, iceflakes, username, referred_by_username, user_id, eth_address, reviewer_user_id, (case when process_immediately is true then 'approve-and-process-immediately' else 'approve' end) AS reason
insert into reviewed_coin_distributions(reviewed_at, created_at, internal_id, ice, day, review_day, iceflakes, username, referred_by_username, user_id, eth_address, reviewer_user_id, decision, verified)
select now, created_at, internal_id, ice, day, now::date, iceflakes, username, referred_by_username, user_id, eth_address, reviewer_user_id, (case when process_immediately is true then 'approve-and-process-immediately' else 'approve' end) AS reason, verified
from coin_distributions_pending_review;

IF process_immediately is true THEN
Expand Down Expand Up @@ -148,8 +153,8 @@ language plpgsql
declare
now timestamp := current_timestamp;
BEGIN
insert into reviewed_coin_distributions(reviewed_at, created_at, internal_id, ice, day, review_day, iceflakes, username, referred_by_username, user_id, eth_address, reviewer_user_id, decision)
select now, created_at, internal_id, ice, day, now::date, iceflakes, username, referred_by_username, user_id, eth_address, reviewer_user_id, 'deny'
insert into reviewed_coin_distributions(reviewed_at, created_at, internal_id, ice, day, review_day, iceflakes, username, referred_by_username, user_id, eth_address, reviewer_user_id, decision, verified)
select now, created_at, internal_id, ice, day, now::date, iceflakes, username, referred_by_username, user_id, eth_address, reviewer_user_id, 'deny', verified
from coin_distributions_pending_review;

delete from coin_distributions_pending_review where 1=1;
Expand All @@ -175,8 +180,8 @@ declare
BEGIN
delete from coin_distributions_by_earner WHERE balance = 0;

insert into coin_distributions_pending_review(created_at, internal_id, ice, day, iceflakes, username, referred_by_username, user_id, eth_address)
SELECT created_at, internal_id, ice, day, (ice::text||zeros)::uint256 AS iceflakes, username, referred_by_username, user_id, eth_address
insert into coin_distributions_pending_review(created_at, internal_id, ice, day, iceflakes, username, referred_by_username, user_id, eth_address, verified)
SELECT created_at, internal_id, ice, day, (ice::text||zeros)::uint256 AS iceflakes, username, referred_by_username, user_id, eth_address, verified
FROM (select
min (created_at) filter ( where user_id=earner_user_id or internal_id = reward_pool_internal_id) AS created_at,
min (internal_id) filter ( where user_id=earner_user_id or internal_id = reward_pool_internal_id) AS internal_id,
Expand All @@ -185,7 +190,8 @@ BEGIN
string_agg(distinct username,'') AS username,
string_agg(distinct referred_by_username,'') AS referred_by_username,
user_id,
string_agg(distinct eth_address,'') AS eth_address
string_agg(distinct eth_address,'') AS eth_address,
verified
from coin_distributions_by_earner
group by day,user_id) AS X;

Expand All @@ -194,8 +200,8 @@ BEGIN
WITH del as (
DELETE FROM coin_distributions_pending_review WHERE internal_id IS NULL RETURNING *
)
insert into reviewed_coin_distributions(reviewed_at, created_at, internal_id, ice, day, review_day, iceflakes, username, referred_by_username, user_id, eth_address, reviewer_user_id, decision)
select now, COALESCE(created_at,to_timestamp(0)), COALESCE(internal_id,0), ice, day, now::date, iceflakes, username, referred_by_username, user_id, eth_address, 'system', 'deny due to incomplete data'
insert into reviewed_coin_distributions(reviewed_at, created_at, internal_id, ice, day, review_day, iceflakes, username, referred_by_username, user_id, eth_address, reviewer_user_id, decision, verified)
select now, COALESCE(created_at,to_timestamp(0)), COALESCE(internal_id,0), ice, day, now::date, iceflakes, username, referred_by_username, user_id, eth_address, 'system', 'deny due to incomplete data', verified
from del;

IF nested is false THEN
Expand Down
2 changes: 2 additions & 0 deletions coin-distribution/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ type (
EthAddress string `json:"ethAddress" swaggertype:"string" example:"0x43...."`
Ice float64 `json:"ice" db:"-" example:"1000"`
IceInternal int64 `json:"-" db:"ice" swaggerignore:"true"`
Verified bool `json:"verified" db:"verified" swaggerignore:"true"`
}

ByEarnerForReview struct {
Expand All @@ -88,6 +89,7 @@ type (
EthAddress string
InternalID int64
Balance float64
Verified bool
}
)

Expand Down
5 changes: 1 addition & 4 deletions coin-distribution/eligibility.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (

"github.com/ethereum/go-ethereum/common"

"github.com/ice-blockchain/eskimo/users"
"github.com/ice-blockchain/freezer/model"
"github.com/ice-blockchain/wintr/time"
)
Expand Down Expand Up @@ -47,7 +46,6 @@ func IsEligibleForEthereumDistribution(
ethAddress, country string,
distributionDeniedCountries map[string]struct{},
now, collectingEndedAt, miningSessionSoloStartedAt, miningSessionSoloEndedAt, ethereumDistributionEndDate *time.Time,
kycState model.KYCState,
miningSessionDuration, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax stdlibtime.Duration) bool {
var countryAllowed bool
if _, countryDenied := distributionDeniedCountries[strings.ToLower(country)]; len(distributionDeniedCountries) == 0 || (country != "" && !countryDenied) {
Expand All @@ -59,8 +57,7 @@ func IsEligibleForEthereumDistribution(
!miningSessionSoloEndedAt.IsNil() && (miningSessionSoloEndedAt.After(*collectingEndedAt.Time) || AllowInactiveUsers) &&
isEthereumAddressValid(ethAddress) &&
((minEthereumDistributionICEBalanceRequired > 0 && distributedBalance >= minEthereumDistributionICEBalanceRequired) || (minEthereumDistributionICEBalanceRequired == 0 && distributedBalance > 0)) && //nolint:lll // .
model.CalculateMiningStreak(now, miningSessionSoloStartedAt, miningSessionSoloEndedAt, miningSessionDuration) >= minMiningStreaksRequired &&
kycState.KYCStepPassedCorrectly(users.QuizKYCStep)
model.CalculateMiningStreak(now, miningSessionSoloStartedAt, miningSessionSoloEndedAt, miningSessionDuration) >= minMiningStreaksRequired
}

func IsEligibleForEthereumDistributionNow(id int64,
Expand Down
18 changes: 8 additions & 10 deletions coin-distribution/eligibility_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,25 +89,23 @@ func TestFinalDistribution(t *testing.T) {
assert.False(t, IsEligibleForEthereumDistributionNow(5, now, userAlreadyProcessedLastEthereumProcessedAt, coinDistributionStartDate, lastCollectingProcessedAt, 24*stdlibtime.Hour, 24*28*stdlibtime.Hour))

balanceRequired := float64(0)
var kycPassed model.KYCState = buildKYC(true, now)
var kycNotPassed model.KYCState = buildKYC(false, now)
var collectingEndedAt *time.Time
if lastCollectingProcessedAt.IsNil() {
collectingEndedAt = time.New(time.Now().Add(-1 * stdlibtime.Millisecond).Add(20 * stdlibtime.Minute))
}
miningSessionDuration := 24 * stdlibtime.Hour
activeMiningSessionStarted := time.New(stdlibtime.Date(2024, 2, 25, 0, 0, 0, 0, stdlibtime.UTC))
nonActiveMiningSessionEnded := time.New(stdlibtime.Date(2024, 2, 26, 0, 0, 0, 0, stdlibtime.UTC))
assert.True(t, IsEligibleForEthereumDistribution(uint64(0), 0.1, balanceRequired, "skip", "US", make(map[string]struct{}), now, collectingEndedAt, activeMiningSessionStarted, nonActiveMiningSessionEnded, coinDistributionEndDate, kycPassed, miningSessionDuration, 24*stdlibtime.Hour, 24*28*stdlibtime.Hour))
assert.True(t, IsEligibleForEthereumDistribution(uint64(0), 1, balanceRequired, "skip", "US", make(map[string]struct{}), now, collectingEndedAt, activeMiningSessionStarted, nonActiveMiningSessionEnded, coinDistributionEndDate, kycNotPassed, miningSessionDuration, 24*stdlibtime.Hour, 24*28*stdlibtime.Hour))
assert.False(t, IsEligibleForEthereumDistribution(uint64(0), 1, balanceRequired, "bogusInvalidAddress", "US", make(map[string]struct{}), now, collectingEndedAt, activeMiningSessionStarted, nonActiveMiningSessionEnded, coinDistributionEndDate, kycPassed, miningSessionDuration, 24*stdlibtime.Hour, 24*28*stdlibtime.Hour))
assert.False(t, IsEligibleForEthereumDistribution(uint64(0), 1, balanceRequired, "", "US", make(map[string]struct{}), now, collectingEndedAt, activeMiningSessionStarted, nonActiveMiningSessionEnded, coinDistributionEndDate, kycPassed, miningSessionDuration, 24*stdlibtime.Hour, 24*28*stdlibtime.Hour))
assert.True(t, IsEligibleForEthereumDistribution(uint64(0), 0.1, balanceRequired, "skip", "US", make(map[string]struct{}), now, collectingEndedAt, activeMiningSessionStarted, nonActiveMiningSessionEnded, coinDistributionEndDate, miningSessionDuration, 24*stdlibtime.Hour, 24*28*stdlibtime.Hour))
assert.True(t, IsEligibleForEthereumDistribution(uint64(0), 1, balanceRequired, "skip", "US", make(map[string]struct{}), now, collectingEndedAt, activeMiningSessionStarted, nonActiveMiningSessionEnded, coinDistributionEndDate, miningSessionDuration, 24*stdlibtime.Hour, 24*28*stdlibtime.Hour))
assert.False(t, IsEligibleForEthereumDistribution(uint64(0), 1, balanceRequired, "bogusInvalidAddress", "US", make(map[string]struct{}), now, collectingEndedAt, activeMiningSessionStarted, nonActiveMiningSessionEnded, coinDistributionEndDate, miningSessionDuration, 24*stdlibtime.Hour, 24*28*stdlibtime.Hour))
assert.False(t, IsEligibleForEthereumDistribution(uint64(0), 1, balanceRequired, "", "US", make(map[string]struct{}), now, collectingEndedAt, activeMiningSessionStarted, nonActiveMiningSessionEnded, coinDistributionEndDate, miningSessionDuration, 24*stdlibtime.Hour, 24*28*stdlibtime.Hour))

activeMiningSessionEnded := time.New(stdlibtime.Date(2024, 2, 29, 0, 0, 0, 0, stdlibtime.UTC))
assert.True(t, IsEligibleForEthereumDistribution(uint64(0), 0.1, balanceRequired, "skip", "US", make(map[string]struct{}), now, collectingEndedAt, activeMiningSessionStarted, activeMiningSessionEnded, coinDistributionEndDate, kycPassed, miningSessionDuration, 24*stdlibtime.Hour, 24*28*stdlibtime.Hour))
assert.True(t, IsEligibleForEthereumDistribution(uint64(0), 1, balanceRequired, "skip", "US", make(map[string]struct{}), now, collectingEndedAt, activeMiningSessionStarted, activeMiningSessionEnded, coinDistributionEndDate, kycNotPassed, miningSessionDuration, 24*stdlibtime.Hour, 24*28*stdlibtime.Hour))
assert.False(t, IsEligibleForEthereumDistribution(uint64(0), 1, balanceRequired, "bogusInvalidAddress", "US", make(map[string]struct{}), now, collectingEndedAt, activeMiningSessionEnded, nonActiveMiningSessionEnded, coinDistributionEndDate, kycPassed, miningSessionDuration, 24*stdlibtime.Hour, 24*28*stdlibtime.Hour))
assert.False(t, IsEligibleForEthereumDistribution(uint64(0), 1, balanceRequired, "", "US", make(map[string]struct{}), now, collectingEndedAt, activeMiningSessionStarted, activeMiningSessionEnded, coinDistributionEndDate, kycPassed, miningSessionDuration, 24*stdlibtime.Hour, 24*28*stdlibtime.Hour))
assert.True(t, IsEligibleForEthereumDistribution(uint64(0), 0.1, balanceRequired, "skip", "US", make(map[string]struct{}), now, collectingEndedAt, activeMiningSessionStarted, activeMiningSessionEnded, coinDistributionEndDate, miningSessionDuration, 24*stdlibtime.Hour, 24*28*stdlibtime.Hour))
assert.True(t, IsEligibleForEthereumDistribution(uint64(0), 1, balanceRequired, "skip", "US", make(map[string]struct{}), now, collectingEndedAt, activeMiningSessionStarted, activeMiningSessionEnded, coinDistributionEndDate, miningSessionDuration, 24*stdlibtime.Hour, 24*28*stdlibtime.Hour))
assert.False(t, IsEligibleForEthereumDistribution(uint64(0), 1, balanceRequired, "bogusInvalidAddress", "US", make(map[string]struct{}), now, collectingEndedAt, activeMiningSessionEnded, nonActiveMiningSessionEnded, coinDistributionEndDate, miningSessionDuration, 24*stdlibtime.Hour, 24*28*stdlibtime.Hour))
assert.False(t, IsEligibleForEthereumDistribution(uint64(0), 1, balanceRequired, "", "US", make(map[string]struct{}), now, collectingEndedAt, activeMiningSessionStarted, activeMiningSessionEnded, coinDistributionEndDate, miningSessionDuration, 24*stdlibtime.Hour, 24*28*stdlibtime.Hour))

assert.Equal(t, float64(0), CalculateEthereumDistributionICEBalance(0, 24*stdlibtime.Hour, 24*28*stdlibtime.Hour, now, coinDistributionEndDate))
assert.Equal(t, float64(100), CalculateEthereumDistributionICEBalance(100, 24*stdlibtime.Hour, 24*28*stdlibtime.Hour, now, coinDistributionEndDate))
Expand Down
10 changes: 6 additions & 4 deletions coin-distribution/pending_review.go
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ func (r *repository) CollectCoinDistributionsForReview(ctx context.Context, reco
log.Warn(fmt.Sprintf("(%#v) is a duplicate of (%#v)", record, otherRecord))
}
}
const columns = 9
const columns = 10
values := make([]string, 0, len(records))
args := make([]any, 0, len(records)*columns)
ix := 0
Expand All @@ -261,18 +261,20 @@ func (r *repository) CollectCoinDistributionsForReview(ctx context.Context, reco
record.ReferredByUsername,
record.UserID,
record.EarnerUserID,
record.EthAddress)
record.EthAddress,
record.Verified)
ix++
}
sql := fmt.Sprintf(`INSERT INTO coin_distributions_by_earner(created_at,day,internal_id,balance,username,referred_by_username,user_id,earner_user_id,eth_address)
sql := fmt.Sprintf(`INSERT INTO coin_distributions_by_earner(created_at,day,internal_id,balance,username,referred_by_username,user_id,earner_user_id,eth_address,verified)
VALUES %v
ON CONFLICT (day, user_id, earner_user_id) DO UPDATE
SET
created_at = EXCLUDED.created_at,
balance = EXCLUDED.balance,
username = EXCLUDED.username,
referred_by_username = EXCLUDED.referred_by_username,
eth_address = EXCLUDED.eth_address`, strings.Join(values, ",\n"))
eth_address = EXCLUDED.eth_address,
verified = EXCLUDED.verified`, strings.Join(values, ",\n"))
_, err := storage.Exec(ctx, r.db, sql, args...)

return errors.Wrapf(err, "failed to insert into coin_distributions_by_earner [%v]", len(records))
Expand Down
20 changes: 10 additions & 10 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,19 @@ require (
github.com/swaggo/swag v1.16.4
github.com/testcontainers/testcontainers-go v0.34.0
go.uber.org/zap v1.27.0
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f
golang.org/x/exp v0.0.0-20241204233417-43b7b7cde48d
)

require (
cel.dev/expr v0.19.0 // indirect
cloud.google.com/go v0.116.0 // indirect
cloud.google.com/go/auth v0.11.0 // indirect
cloud.google.com/go/auth v0.12.0 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.6 // indirect
cloud.google.com/go/compute/metadata v0.5.2 // indirect
cloud.google.com/go/firestore v1.17.0 // indirect
cloud.google.com/go/iam v1.2.2 // indirect
cloud.google.com/go/iam v1.3.0 // indirect
cloud.google.com/go/longrunning v0.6.3 // indirect
cloud.google.com/go/monitoring v1.21.2 // indirect
cloud.google.com/go/monitoring v1.22.0 // indirect
cloud.google.com/go/storage v1.47.0 // indirect
cosmossdk.io/math v1.4.0 // indirect
dario.cat/mergo v1.0.1 // indirect
Expand Down Expand Up @@ -203,21 +203,21 @@ require (
go.uber.org/mock v0.5.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/arch v0.12.0 // indirect
golang.org/x/crypto v0.29.0 // indirect
golang.org/x/crypto v0.30.0 // indirect
golang.org/x/mod v0.22.0 // indirect
golang.org/x/net v0.31.0 // indirect
golang.org/x/net v0.32.0 // indirect
golang.org/x/oauth2 v0.24.0 // indirect
golang.org/x/sync v0.10.0 // indirect
golang.org/x/sys v0.28.0 // indirect
golang.org/x/text v0.20.0 // indirect
golang.org/x/text v0.21.0 // indirect
golang.org/x/time v0.8.0 // indirect
golang.org/x/tools v0.27.0 // indirect
google.golang.org/api v0.209.0 // indirect
golang.org/x/tools v0.28.0 // indirect
google.golang.org/api v0.210.0 // indirect
google.golang.org/appengine/v2 v2.0.6 // indirect
google.golang.org/genproto v0.0.0-20241202173237-19429a94021a // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20241202173237-19429a94021a // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect
google.golang.org/grpc v1.68.0 // indirect
google.golang.org/grpc v1.68.1 // indirect
google.golang.org/grpc/stats/opentelemetry v0.0.0-20241028142157-ada6787961b3 // indirect
google.golang.org/protobuf v1.35.2 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
Expand Down
Loading
Loading