diff --git a/coin-distribution/eligibility_test.go b/coin-distribution/eligibility_test.go index bf3b879..977f0bc 100644 --- a/coin-distribution/eligibility_test.go +++ b/coin-distribution/eligibility_test.go @@ -8,9 +8,15 @@ import ( "github.com/stretchr/testify/assert" + "github.com/ice-blockchain/eskimo/users" + "github.com/ice-blockchain/freezer/model" "github.com/ice-blockchain/wintr/time" ) +var ( + testTime = time.New(stdlibtime.Date(2023, 1, 2, 10, 45, 5, 6, stdlibtime.UTC)) +) + func TestIsEligibleForEthereumDistributionNow(t *testing.T) { t.Parallel() coinDistributionStartDate := time.New(stdlibtime.Date(2024, 1, 16, 0, 0, 0, 0, stdlibtime.UTC)) @@ -47,3 +53,663 @@ func TestIsEligibleForEthereumDistributionNow(t *testing.T) { assert.True(t, isEligibleForEthereumDistributionNow(4, 24*stdlibtime.Hour, 24*28*stdlibtime.Hour, time.Now(), coinDistributionStartDate, lastCoinDistributionProcessedAt)) assert.True(t, isEligibleForEthereumDistributionNow(5, 24*stdlibtime.Hour, 24*28*stdlibtime.Hour, time.Now(), coinDistributionStartDate, lastCoinDistributionProcessedAt)) } +func TestIsCoinDistributionCollectorEnabled(t *testing.T) { + t.Parallel() + + t.Run("enabled && forced execution", func(t *testing.T) { + t.Parallel() + + now := testTime + ethereumDistributionFrequencyMin := 1 * stdlibtime.Hour + cs := CollectorSettings{ + LatestDate: nil, + StartDate: nil, + EndDate: nil, + StartHour: 0, + Enabled: true, + ForcedExecution: true, + } + assert.True(t, IsCoinDistributionCollectorEnabled(now, ethereumDistributionFrequencyMin, &cs)) + }) + + t.Run("!enabled && forced execution", func(t *testing.T) { + t.Parallel() + + now := testTime + ethereumDistributionFrequencyMin := 1 * stdlibtime.Hour + cs := CollectorSettings{ + LatestDate: nil, + StartDate: nil, + EndDate: nil, + StartHour: 5, + Enabled: false, + ForcedExecution: true, + } + assert.False(t, IsCoinDistributionCollectorEnabled(now, ethereumDistributionFrequencyMin, &cs)) + }) + + t.Run("enabled && !forced execution && now.Hour < cs.StartHour", func(t *testing.T) { + t.Parallel() + + now := testTime + ethereumDistributionFrequencyMin := 1 * stdlibtime.Hour + cs := CollectorSettings{ + LatestDate: testTime, + StartDate: time.New(testTime.Add(-2 * stdlibtime.Hour)), + EndDate: time.New(testTime.Add(2 * stdlibtime.Hour)), + Enabled: true, + ForcedExecution: false, + } + assert.False(t, IsCoinDistributionCollectorEnabled(now, ethereumDistributionFrequencyMin, &cs)) + }) + + t.Run("enabled && !forced execution && now.Hour >= cs.StartHour && now.Before(start)", func(t *testing.T) { + t.Parallel() + + now := testTime + ethereumDistributionFrequencyMin := 1 * stdlibtime.Hour + cs := CollectorSettings{ + LatestDate: nil, + StartDate: time.New(testTime.Add(1 * stdlibtime.Hour)), + EndDate: time.New(testTime.Add(2 * stdlibtime.Hour)), + StartHour: 9, + Enabled: true, + ForcedExecution: false, + } + assert.False(t, IsCoinDistributionCollectorEnabled(now, ethereumDistributionFrequencyMin, &cs)) + }) + + t.Run("enabled && !forced execution && now.Hour >= cs.StartHour && now.After(end)", func(t *testing.T) { + t.Parallel() + now := testTime + ethereumDistributionFrequencyMin := 1 * stdlibtime.Hour + cs := CollectorSettings{ + LatestDate: nil, + StartDate: time.New(testTime.Add(-3 * stdlibtime.Hour)), + EndDate: time.New(testTime.Add(-1 * stdlibtime.Hour)), + StartHour: 9, + Enabled: true, + ForcedExecution: false, + } + assert.False(t, IsCoinDistributionCollectorEnabled(now, ethereumDistributionFrequencyMin, &cs)) + }) + + t.Run("enabled && hour && start < hour < end && latest date is nil", func(t *testing.T) { + t.Parallel() + now := testTime + ethereumDistributionFrequencyMin := 1 * stdlibtime.Hour + cs := CollectorSettings{ + LatestDate: nil, + StartDate: time.New(testTime.Add(-1 * stdlibtime.Hour)), + EndDate: time.New(testTime.Add(1 * stdlibtime.Hour)), + StartHour: 9, + Enabled: true, + ForcedExecution: false, + } + assert.True(t, IsCoinDistributionCollectorEnabled(now, ethereumDistributionFrequencyMin, &cs)) + }) + + t.Run("enabled && hour && start < hour < end && truncate(now ~ latest date)", func(t *testing.T) { + t.Parallel() + now := testTime + ethereumDistributionFrequencyMin := 1 * stdlibtime.Hour + cs := CollectorSettings{ + LatestDate: time.New(testTime.Add(2 * stdlibtime.Hour)), + StartDate: time.New(testTime.Add(-3 * stdlibtime.Hour)), + EndDate: time.New(testTime.Add(3 * stdlibtime.Hour)), + StartHour: 9, + Enabled: true, + ForcedExecution: false, + } + + assert.True(t, IsCoinDistributionCollectorEnabled(now, ethereumDistributionFrequencyMin, &cs)) + }) + + t.Run("enabled && hour && start < hour < end && !truncate(now ~ latest date)", func(t *testing.T) { + t.Parallel() + now := testTime + ethereumDistributionFrequencyMin := 1 * stdlibtime.Hour + cs := CollectorSettings{ + LatestDate: time.New(testTime.Add(-30 * stdlibtime.Minute)), + StartDate: time.New(testTime.Add(-3 * stdlibtime.Hour)), + EndDate: time.New(testTime.Add(3 * stdlibtime.Hour)), + StartHour: 9, + Enabled: true, + ForcedExecution: false, + } + assert.False(t, IsCoinDistributionCollectorEnabled(now, ethereumDistributionFrequencyMin, &cs)) + }) +} + +func TestCalculateEthereumDistributionICEBalance(t *testing.T) { + t.Parallel() + + t.Run("delta < ethereumDistributionFrequencyMax", func(t *testing.T) { + t.Parallel() + standardBalance := 1000.0 + ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax := stdlibtime.Hour, 24*stdlibtime.Hour + now := testTime + ethereumDistributionEndDate := time.New(now.Add(5 * stdlibtime.Hour)) + result := CalculateEthereumDistributionICEBalance(standardBalance, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax, now, ethereumDistributionEndDate) + assert.Equal(t, 1000.0, result) + }) + + t.Run("delta == ethereumDistributionFrequencyMax", func(t *testing.T) { + t.Parallel() + standardBalance := 1000.0 + ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax := stdlibtime.Hour, 24*stdlibtime.Hour + now := testTime + ethereumDistributionEndDate := time.New(now.Add(24 * stdlibtime.Hour)) + result := CalculateEthereumDistributionICEBalance(standardBalance, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax, now, ethereumDistributionEndDate) + assert.Equal(t, 1000.0, result) + }) + + t.Run("delta > ethereumDistributionFrequencyMax", func(t *testing.T) { + t.Parallel() + standardBalance := 1000.0 + ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax := stdlibtime.Hour, 24*stdlibtime.Hour + now := testTime + ethereumDistributionEndDate := time.New(now.Add(48 * stdlibtime.Hour)) + result := CalculateEthereumDistributionICEBalance(standardBalance, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax, now, ethereumDistributionEndDate) + assert.Equal(t, 333.3333333333333, result) + }) +} + +func TestIsEligibleForEthereumDistribution(t *testing.T) { + t.Parallel() + + t.Run("Denied country", func(t *testing.T) { + t.Parallel() + + minMiningStreaksRequired := uint64(0) + standardBalance := 100.0 + minEthereumDistributionICEBalanceRequired := 10.0 + ethAddress := "0x111Fc57e1e4e7687c9195F7856C45227f269323B" + country := "France" + distributionDeniedCountries := map[string]struct{}{ + "France": {}, + "Germany": {}, + } + now := testTime + miningSessionSoloStartedAt, miningSessionSoloEndedAt, ethereumDistributionEndDate := time.Now(), time.New(now.Add(48*stdlibtime.Hour)), time.New(now.Add(48*stdlibtime.Hour)) + collectingEndedAt := time.New(now.Add(24 * stdlibtime.Hour)) + kycState := model.KYCState{ + KYCStepsCreatedAtField: model.KYCStepsCreatedAtField{KYCStepsCreatedAt: &model.TimeSlice{}}, + KYCStepsLastUpdatedAtField: model.KYCStepsLastUpdatedAtField{KYCStepsLastUpdatedAt: &model.TimeSlice{}}, + KYCStepPassedField: model.KYCStepPassedField{KYCStepPassed: users.FacialRecognitionKYCStep}, + KYCStepBlockedField: model.KYCStepBlockedField{KYCStepBlocked: users.NoneKYCStep}, + KYCQuizCompletedField: model.KYCQuizCompletedField{KYCQuizCompleted: true}, + KYCQuizDisabledField: model.KYCQuizDisabledField{KYCQuizDisabled: false}, + } + miningSessionDuration, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax := 24*stdlibtime.Hour, stdlibtime.Hour, 24*stdlibtime.Hour + assert.False(t, IsEligibleForEthereumDistribution(minMiningStreaksRequired, standardBalance, minEthereumDistributionICEBalanceRequired, ethAddress, country, distributionDeniedCountries, now, + collectingEndedAt, miningSessionSoloStartedAt, miningSessionSoloEndedAt, ethereumDistributionEndDate, kycState, miningSessionDuration, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + + country = "france" + assert.False(t, IsEligibleForEthereumDistribution(minMiningStreaksRequired, standardBalance, minEthereumDistributionICEBalanceRequired, ethAddress, country, distributionDeniedCountries, now, + collectingEndedAt, miningSessionSoloStartedAt, miningSessionSoloEndedAt, ethereumDistributionEndDate, kycState, miningSessionDuration, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + + country = "Germany" + assert.False(t, IsEligibleForEthereumDistribution(minMiningStreaksRequired, standardBalance, minEthereumDistributionICEBalanceRequired, ethAddress, country, distributionDeniedCountries, now, + collectingEndedAt, miningSessionSoloStartedAt, miningSessionSoloEndedAt, ethereumDistributionEndDate, kycState, miningSessionDuration, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + + country = "germany" + assert.False(t, IsEligibleForEthereumDistribution(minMiningStreaksRequired, standardBalance, minEthereumDistributionICEBalanceRequired, ethAddress, country, distributionDeniedCountries, now, + collectingEndedAt, miningSessionSoloStartedAt, miningSessionSoloEndedAt, ethereumDistributionEndDate, kycState, miningSessionDuration, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + }) + + t.Run("Positive case", func(t *testing.T) { + t.Parallel() + + minMiningStreaksRequired := uint64(1) + standardBalance := 100.0 + minEthereumDistributionICEBalanceRequired := 10.0 + ethAddress := "0x111Fc57e1e4e7687c9195F7856C45227f269323B" + country := "France" + distributionDeniedCountries := map[string]struct{}{} + now := testTime + miningSessionSoloStartedAt, miningSessionSoloEndedAt, ethereumDistributionEndDate := time.New(now.Add(-25*stdlibtime.Hour)), time.New(now.Add(13*stdlibtime.Hour)), time.New(now.Add(64*stdlibtime.Hour)) + collectingEndedAt := time.New(now.Add(5 * stdlibtime.Hour)) + kycState := model.KYCState{ + KYCStepsCreatedAtField: model.KYCStepsCreatedAtField{KYCStepsCreatedAt: &model.TimeSlice{time.New(now.Add(1 * stdlibtime.Hour)), time.New(now.Add(2 * stdlibtime.Hour)), time.New(now.Add(3 * stdlibtime.Hour)), time.New(now.Add(4 * stdlibtime.Hour))}}, + KYCStepsLastUpdatedAtField: model.KYCStepsLastUpdatedAtField{KYCStepsLastUpdatedAt: &model.TimeSlice{time.New(now.Add(1 * stdlibtime.Hour)), time.New(now.Add(2 * stdlibtime.Hour)), time.New(now.Add(3 * stdlibtime.Hour)), time.New(now.Add(4 * stdlibtime.Hour))}}, + KYCStepPassedField: model.KYCStepPassedField{KYCStepPassed: users.QuizKYCStep}, + KYCStepBlockedField: model.KYCStepBlockedField{KYCStepBlocked: users.NoneKYCStep}, + KYCQuizCompletedField: model.KYCQuizCompletedField{KYCQuizCompleted: true}, + KYCQuizDisabledField: model.KYCQuizDisabledField{KYCQuizDisabled: false}, + } + miningSessionDuration, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax := 24*stdlibtime.Hour, stdlibtime.Hour, 24*stdlibtime.Hour + assert.True(t, IsEligibleForEthereumDistribution(minMiningStreaksRequired, standardBalance, minEthereumDistributionICEBalanceRequired, ethAddress, country, distributionDeniedCountries, now, + collectingEndedAt, miningSessionSoloStartedAt, miningSessionSoloEndedAt, ethereumDistributionEndDate, kycState, miningSessionDuration, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + }) + + t.Run("Wrong eth address", func(t *testing.T) { + t.Parallel() + + minMiningStreaksRequired := uint64(1) + standardBalance := 100.0 + minEthereumDistributionICEBalanceRequired := 10.0 + ethAddress := "1234" + country := "France" + distributionDeniedCountries := map[string]struct{}{} + now := testTime + miningSessionSoloStartedAt, miningSessionSoloEndedAt, ethereumDistributionEndDate := time.New(now.Add(-25*stdlibtime.Hour)), time.New(now.Add(13*stdlibtime.Hour)), time.New(now.Add(64*stdlibtime.Hour)) + collectingEndedAt := time.New(now.Add(5 * stdlibtime.Hour)) + kycState := model.KYCState{ + KYCStepsCreatedAtField: model.KYCStepsCreatedAtField{KYCStepsCreatedAt: &model.TimeSlice{time.New(now.Add(1 * stdlibtime.Hour)), time.New(now.Add(2 * stdlibtime.Hour)), time.New(now.Add(3 * stdlibtime.Hour)), time.New(now.Add(4 * stdlibtime.Hour))}}, + KYCStepsLastUpdatedAtField: model.KYCStepsLastUpdatedAtField{KYCStepsLastUpdatedAt: &model.TimeSlice{time.New(now.Add(1 * stdlibtime.Hour)), time.New(now.Add(2 * stdlibtime.Hour)), time.New(now.Add(3 * stdlibtime.Hour)), time.New(now.Add(4 * stdlibtime.Hour))}}, + KYCStepPassedField: model.KYCStepPassedField{KYCStepPassed: users.QuizKYCStep}, + KYCStepBlockedField: model.KYCStepBlockedField{KYCStepBlocked: users.NoneKYCStep}, + KYCQuizCompletedField: model.KYCQuizCompletedField{KYCQuizCompleted: true}, + KYCQuizDisabledField: model.KYCQuizDisabledField{KYCQuizDisabled: false}, + } + miningSessionDuration, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax := 24*stdlibtime.Hour, stdlibtime.Hour, 24*stdlibtime.Hour + assert.False(t, IsEligibleForEthereumDistribution(minMiningStreaksRequired, standardBalance, minEthereumDistributionICEBalanceRequired, ethAddress, country, distributionDeniedCountries, now, + collectingEndedAt, miningSessionSoloStartedAt, miningSessionSoloEndedAt, ethereumDistributionEndDate, kycState, miningSessionDuration, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + }) + + t.Run("Not enough mining streaks", func(t *testing.T) { + t.Parallel() + + minMiningStreaksRequired := uint64(3) + standardBalance := 100.0 + minEthereumDistributionICEBalanceRequired := 10.0 + ethAddress := "0x111Fc57e1e4e7687c9195F7856C45227f269323B" + country := "France" + distributionDeniedCountries := map[string]struct{}{} + now := testTime + miningSessionSoloStartedAt, miningSessionSoloEndedAt, ethereumDistributionEndDate := time.New(now.Add(-25*stdlibtime.Hour)), time.New(now.Add(13*stdlibtime.Hour)), time.New(now.Add(64*stdlibtime.Hour)) + collectingEndedAt := time.New(now.Add(5 * stdlibtime.Hour)) + kycState := model.KYCState{ + KYCStepsCreatedAtField: model.KYCStepsCreatedAtField{KYCStepsCreatedAt: &model.TimeSlice{time.New(now.Add(1 * stdlibtime.Hour)), time.New(now.Add(2 * stdlibtime.Hour)), time.New(now.Add(3 * stdlibtime.Hour)), time.New(now.Add(4 * stdlibtime.Hour))}}, + KYCStepsLastUpdatedAtField: model.KYCStepsLastUpdatedAtField{KYCStepsLastUpdatedAt: &model.TimeSlice{time.New(now.Add(1 * stdlibtime.Hour)), time.New(now.Add(2 * stdlibtime.Hour)), time.New(now.Add(3 * stdlibtime.Hour)), time.New(now.Add(4 * stdlibtime.Hour))}}, + KYCStepPassedField: model.KYCStepPassedField{KYCStepPassed: users.QuizKYCStep}, + KYCStepBlockedField: model.KYCStepBlockedField{KYCStepBlocked: users.NoneKYCStep}, + KYCQuizCompletedField: model.KYCQuizCompletedField{KYCQuizCompleted: true}, + KYCQuizDisabledField: model.KYCQuizDisabledField{KYCQuizDisabled: false}, + } + miningSessionDuration, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax := 24*stdlibtime.Hour, stdlibtime.Hour, 24*stdlibtime.Hour + assert.False(t, IsEligibleForEthereumDistribution(minMiningStreaksRequired, standardBalance, minEthereumDistributionICEBalanceRequired, ethAddress, country, distributionDeniedCountries, now, + collectingEndedAt, miningSessionSoloStartedAt, miningSessionSoloEndedAt, ethereumDistributionEndDate, kycState, miningSessionDuration, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + }) + + t.Run("Mining session solo ended at is nil", func(t *testing.T) { + t.Parallel() + + minMiningStreaksRequired := uint64(1) + standardBalance := 100.0 + minEthereumDistributionICEBalanceRequired := 10.0 + ethAddress := "0x111Fc57e1e4e7687c9195F7856C45227f269323B" + country := "France" + distributionDeniedCountries := map[string]struct{}{} + now := testTime + miningSessionSoloStartedAt, ethereumDistributionEndDate := time.New(now.Add(-25*stdlibtime.Hour)), time.New(now.Add(64*stdlibtime.Hour)) + collectingEndedAt := time.New(now.Add(5 * stdlibtime.Hour)) + kycState := model.KYCState{ + KYCStepsCreatedAtField: model.KYCStepsCreatedAtField{KYCStepsCreatedAt: &model.TimeSlice{time.New(now.Add(1 * stdlibtime.Hour)), time.New(now.Add(2 * stdlibtime.Hour)), time.New(now.Add(3 * stdlibtime.Hour)), time.New(now.Add(4 * stdlibtime.Hour))}}, + KYCStepsLastUpdatedAtField: model.KYCStepsLastUpdatedAtField{KYCStepsLastUpdatedAt: &model.TimeSlice{time.New(now.Add(1 * stdlibtime.Hour)), time.New(now.Add(2 * stdlibtime.Hour)), time.New(now.Add(3 * stdlibtime.Hour)), time.New(now.Add(4 * stdlibtime.Hour))}}, + KYCStepPassedField: model.KYCStepPassedField{KYCStepPassed: users.QuizKYCStep}, + KYCStepBlockedField: model.KYCStepBlockedField{KYCStepBlocked: users.NoneKYCStep}, + KYCQuizCompletedField: model.KYCQuizCompletedField{KYCQuizCompleted: true}, + KYCQuizDisabledField: model.KYCQuizDisabledField{KYCQuizDisabled: false}, + } + miningSessionDuration, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax := 24*stdlibtime.Hour, stdlibtime.Hour, 24*stdlibtime.Hour + + var miningSessionSoloEndedAt *time.Time + assert.False(t, IsEligibleForEthereumDistribution(minMiningStreaksRequired, standardBalance, minEthereumDistributionICEBalanceRequired, ethAddress, country, distributionDeniedCountries, now, + collectingEndedAt, miningSessionSoloStartedAt, miningSessionSoloEndedAt, ethereumDistributionEndDate, kycState, miningSessionDuration, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + }) + + t.Run("Mining session solo started at is nil", func(t *testing.T) { + t.Parallel() + + minMiningStreaksRequired := uint64(1) + standardBalance := 100.0 + minEthereumDistributionICEBalanceRequired := 10.0 + ethAddress := "0x111Fc57e1e4e7687c9195F7856C45227f269323B" + country := "France" + distributionDeniedCountries := map[string]struct{}{} + now := testTime + miningSessionSoloEndedAt, ethereumDistributionEndDate := time.New(now.Add(-25*stdlibtime.Hour)), time.New(now.Add(64*stdlibtime.Hour)) + collectingEndedAt := time.New(now.Add(5 * stdlibtime.Hour)) + kycState := model.KYCState{ + KYCStepsCreatedAtField: model.KYCStepsCreatedAtField{KYCStepsCreatedAt: &model.TimeSlice{time.New(now.Add(1 * stdlibtime.Hour)), time.New(now.Add(2 * stdlibtime.Hour)), time.New(now.Add(3 * stdlibtime.Hour)), time.New(now.Add(4 * stdlibtime.Hour))}}, + KYCStepsLastUpdatedAtField: model.KYCStepsLastUpdatedAtField{KYCStepsLastUpdatedAt: &model.TimeSlice{time.New(now.Add(1 * stdlibtime.Hour)), time.New(now.Add(2 * stdlibtime.Hour)), time.New(now.Add(3 * stdlibtime.Hour)), time.New(now.Add(4 * stdlibtime.Hour))}}, + KYCStepPassedField: model.KYCStepPassedField{KYCStepPassed: users.QuizKYCStep}, + KYCStepBlockedField: model.KYCStepBlockedField{KYCStepBlocked: users.NoneKYCStep}, + KYCQuizCompletedField: model.KYCQuizCompletedField{KYCQuizCompleted: true}, + KYCQuizDisabledField: model.KYCQuizDisabledField{KYCQuizDisabled: false}, + } + miningSessionDuration, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax := 24*stdlibtime.Hour, stdlibtime.Hour, 24*stdlibtime.Hour + + var miningSessionSoloStartedAt *time.Time + assert.False(t, IsEligibleForEthereumDistribution(minMiningStreaksRequired, standardBalance, minEthereumDistributionICEBalanceRequired, ethAddress, country, distributionDeniedCountries, now, + collectingEndedAt, miningSessionSoloStartedAt, miningSessionSoloEndedAt, ethereumDistributionEndDate, kycState, miningSessionDuration, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + }) + + t.Run("Not enough kyc step", func(t *testing.T) { + t.Parallel() + + minMiningStreaksRequired := uint64(1) + standardBalance := 100.0 + minEthereumDistributionICEBalanceRequired := 10.0 + ethAddress := "0x111Fc57e1e4e7687c9195F7856C45227f269323B" + country := "France" + distributionDeniedCountries := map[string]struct{}{} + now := testTime + miningSessionSoloStartedAt, miningSessionSoloEndedAt, ethereumDistributionEndDate := time.New(now.Add(-25*stdlibtime.Hour)), time.New(now.Add(13*stdlibtime.Hour)), time.New(now.Add(64*stdlibtime.Hour)) + collectingEndedAt := time.New(now.Add(5 * stdlibtime.Hour)) + kycState := model.KYCState{ + KYCStepsCreatedAtField: model.KYCStepsCreatedAtField{KYCStepsCreatedAt: &model.TimeSlice{time.New(now.Add(1 * stdlibtime.Hour))}}, + KYCStepsLastUpdatedAtField: model.KYCStepsLastUpdatedAtField{KYCStepsLastUpdatedAt: &model.TimeSlice{time.New(now.Add(1 * stdlibtime.Hour))}}, + KYCStepPassedField: model.KYCStepPassedField{KYCStepPassed: users.Social1KYCStep}, + KYCStepBlockedField: model.KYCStepBlockedField{KYCStepBlocked: users.NoneKYCStep}, + KYCQuizCompletedField: model.KYCQuizCompletedField{KYCQuizCompleted: true}, + KYCQuizDisabledField: model.KYCQuizDisabledField{KYCQuizDisabled: false}, + } + miningSessionDuration, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax := 24*stdlibtime.Hour, stdlibtime.Hour, 24*stdlibtime.Hour + assert.False(t, IsEligibleForEthereumDistribution(minMiningStreaksRequired, standardBalance, minEthereumDistributionICEBalanceRequired, ethAddress, country, distributionDeniedCountries, now, + collectingEndedAt, miningSessionSoloStartedAt, miningSessionSoloEndedAt, ethereumDistributionEndDate, kycState, miningSessionDuration, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + + kycState = model.KYCState{ + KYCStepsCreatedAtField: model.KYCStepsCreatedAtField{KYCStepsCreatedAt: &model.TimeSlice{time.New(now.Add(1 * stdlibtime.Hour))}}, + KYCStepsLastUpdatedAtField: model.KYCStepsLastUpdatedAtField{KYCStepsLastUpdatedAt: &model.TimeSlice{time.New(now.Add(1 * stdlibtime.Hour))}}, + KYCStepPassedField: model.KYCStepPassedField{KYCStepPassed: users.Social2KYCStep}, + KYCStepBlockedField: model.KYCStepBlockedField{KYCStepBlocked: users.NoneKYCStep}, + KYCQuizCompletedField: model.KYCQuizCompletedField{KYCQuizCompleted: true}, + KYCQuizDisabledField: model.KYCQuizDisabledField{KYCQuizDisabled: false}, + } + assert.False(t, IsEligibleForEthereumDistribution(minMiningStreaksRequired, standardBalance, minEthereumDistributionICEBalanceRequired, ethAddress, country, distributionDeniedCountries, now, + collectingEndedAt, miningSessionSoloStartedAt, miningSessionSoloEndedAt, ethereumDistributionEndDate, kycState, miningSessionDuration, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + + kycState = model.KYCState{ + KYCStepsCreatedAtField: model.KYCStepsCreatedAtField{KYCStepsCreatedAt: &model.TimeSlice{time.New(now.Add(1 * stdlibtime.Hour)), nil}}, + KYCStepsLastUpdatedAtField: model.KYCStepsLastUpdatedAtField{KYCStepsLastUpdatedAt: &model.TimeSlice{time.New(now.Add(1 * stdlibtime.Hour)), nil}}, + KYCStepPassedField: model.KYCStepPassedField{KYCStepPassed: users.Social3KYCStep}, + KYCStepBlockedField: model.KYCStepBlockedField{KYCStepBlocked: users.NoneKYCStep}, + KYCQuizCompletedField: model.KYCQuizCompletedField{KYCQuizCompleted: true}, + KYCQuizDisabledField: model.KYCQuizDisabledField{KYCQuizDisabled: false}, + } + assert.False(t, IsEligibleForEthereumDistribution(minMiningStreaksRequired, standardBalance, minEthereumDistributionICEBalanceRequired, ethAddress, country, distributionDeniedCountries, now, + collectingEndedAt, miningSessionSoloStartedAt, miningSessionSoloEndedAt, ethereumDistributionEndDate, kycState, miningSessionDuration, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + }) + + t.Run("Last updated at is nil", func(t *testing.T) { + t.Parallel() + + minMiningStreaksRequired := uint64(1) + standardBalance := 100.0 + minEthereumDistributionICEBalanceRequired := 10.0 + ethAddress := "0x111Fc57e1e4e7687c9195F7856C45227f269323B" + country := "France" + distributionDeniedCountries := map[string]struct{}{} + now := testTime + miningSessionSoloStartedAt, miningSessionSoloEndedAt, ethereumDistributionEndDate := time.New(now.Add(-25*stdlibtime.Hour)), time.New(now.Add(13*stdlibtime.Hour)), time.New(now.Add(64*stdlibtime.Hour)) + collectingEndedAt := time.New(now.Add(5 * stdlibtime.Hour)) + kycState := model.KYCState{ + KYCStepsCreatedAtField: model.KYCStepsCreatedAtField{KYCStepsCreatedAt: &model.TimeSlice{time.New(now.Add(1 * stdlibtime.Hour)), time.New(now.Add(2 * stdlibtime.Hour)), time.New(now.Add(3 * stdlibtime.Hour)), time.New(now.Add(4 * stdlibtime.Hour))}}, + KYCStepsLastUpdatedAtField: model.KYCStepsLastUpdatedAtField{KYCStepsLastUpdatedAt: nil}, + KYCStepPassedField: model.KYCStepPassedField{KYCStepPassed: users.QuizKYCStep}, + KYCStepBlockedField: model.KYCStepBlockedField{KYCStepBlocked: users.NoneKYCStep}, + KYCQuizCompletedField: model.KYCQuizCompletedField{KYCQuizCompleted: true}, + KYCQuizDisabledField: model.KYCQuizDisabledField{KYCQuizDisabled: false}, + } + miningSessionDuration, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax := 24*stdlibtime.Hour, stdlibtime.Hour, 24*stdlibtime.Hour + assert.False(t, IsEligibleForEthereumDistribution(minMiningStreaksRequired, standardBalance, minEthereumDistributionICEBalanceRequired, ethAddress, country, distributionDeniedCountries, now, + collectingEndedAt, miningSessionSoloStartedAt, miningSessionSoloEndedAt, ethereumDistributionEndDate, kycState, miningSessionDuration, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + }) + + t.Run("Previous kyc last updated at is nil", func(t *testing.T) { + t.Parallel() + + minMiningStreaksRequired := uint64(1) + standardBalance := 100.0 + minEthereumDistributionICEBalanceRequired := 10.0 + ethAddress := "0x111Fc57e1e4e7687c9195F7856C45227f269323B" + country := "France" + distributionDeniedCountries := map[string]struct{}{} + now := testTime + miningSessionSoloStartedAt, miningSessionSoloEndedAt, ethereumDistributionEndDate := time.New(now.Add(-25*stdlibtime.Hour)), time.New(now.Add(13*stdlibtime.Hour)), time.New(now.Add(64*stdlibtime.Hour)) + collectingEndedAt := time.New(now.Add(5 * stdlibtime.Hour)) + kycState := model.KYCState{ + KYCStepsCreatedAtField: model.KYCStepsCreatedAtField{KYCStepsCreatedAt: &model.TimeSlice{time.New(now.Add(1 * stdlibtime.Hour)), nil, time.New(now.Add(3 * stdlibtime.Hour)), time.New(now.Add(4 * stdlibtime.Hour))}}, + KYCStepsLastUpdatedAtField: model.KYCStepsLastUpdatedAtField{KYCStepsLastUpdatedAt: &model.TimeSlice{time.New(now.Add(1 * stdlibtime.Hour)), nil, time.New(now.Add(3 * stdlibtime.Hour)), time.New(now.Add(4 * stdlibtime.Hour))}}, + KYCStepPassedField: model.KYCStepPassedField{KYCStepPassed: users.QuizKYCStep}, + KYCStepBlockedField: model.KYCStepBlockedField{KYCStepBlocked: users.NoneKYCStep}, + KYCQuizCompletedField: model.KYCQuizCompletedField{KYCQuizCompleted: true}, + KYCQuizDisabledField: model.KYCQuizDisabledField{KYCQuizDisabled: false}, + } + miningSessionDuration, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax := 24*stdlibtime.Hour, stdlibtime.Hour, 24*stdlibtime.Hour + assert.False(t, IsEligibleForEthereumDistribution(minMiningStreaksRequired, standardBalance, minEthereumDistributionICEBalanceRequired, ethAddress, country, distributionDeniedCountries, now, + collectingEndedAt, miningSessionSoloStartedAt, miningSessionSoloEndedAt, ethereumDistributionEndDate, kycState, miningSessionDuration, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + }) + + t.Run("KYC blocked > kycStep", func(t *testing.T) { + t.Parallel() + + minMiningStreaksRequired := uint64(1) + standardBalance := 100.0 + minEthereumDistributionICEBalanceRequired := 10.0 + ethAddress := "0x111Fc57e1e4e7687c9195F7856C45227f269323B" + country := "France" + distributionDeniedCountries := map[string]struct{}{} + now := testTime + miningSessionSoloStartedAt, miningSessionSoloEndedAt, ethereumDistributionEndDate := time.New(now.Add(-25*stdlibtime.Hour)), time.New(now.Add(13*stdlibtime.Hour)), time.New(now.Add(64*stdlibtime.Hour)) + collectingEndedAt := time.New(now.Add(5 * stdlibtime.Hour)) + kycState := model.KYCState{ + KYCStepsCreatedAtField: model.KYCStepsCreatedAtField{KYCStepsCreatedAt: &model.TimeSlice{time.New(now.Add(1 * stdlibtime.Hour)), time.New(now.Add(2 * stdlibtime.Hour)), time.New(now.Add(3 * stdlibtime.Hour)), time.New(now.Add(4 * stdlibtime.Hour))}}, + KYCStepsLastUpdatedAtField: model.KYCStepsLastUpdatedAtField{KYCStepsLastUpdatedAt: &model.TimeSlice{time.New(now.Add(1 * stdlibtime.Hour)), time.New(now.Add(2 * stdlibtime.Hour)), time.New(now.Add(3 * stdlibtime.Hour)), time.New(now.Add(4 * stdlibtime.Hour))}}, + KYCStepPassedField: model.KYCStepPassedField{KYCStepPassed: users.QuizKYCStep}, + KYCStepBlockedField: model.KYCStepBlockedField{KYCStepBlocked: users.FacialRecognitionKYCStep}, + KYCQuizCompletedField: model.KYCQuizCompletedField{KYCQuizCompleted: true}, + KYCQuizDisabledField: model.KYCQuizDisabledField{KYCQuizDisabled: false}, + } + miningSessionDuration, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax := 24*stdlibtime.Hour, stdlibtime.Hour, 24*stdlibtime.Hour + assert.False(t, IsEligibleForEthereumDistribution(minMiningStreaksRequired, standardBalance, minEthereumDistributionICEBalanceRequired, ethAddress, country, distributionDeniedCountries, now, + collectingEndedAt, miningSessionSoloStartedAt, miningSessionSoloEndedAt, ethereumDistributionEndDate, kycState, miningSessionDuration, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + }) + + t.Run("Balance less than minimum distribution balance required, delta == ethereumDistributionFrequencyMax", func(t *testing.T) { + t.Parallel() + + minMiningStreaksRequired := uint64(1) + standardBalance := 1000.0 + ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax := stdlibtime.Hour, 24*stdlibtime.Hour + now := testTime + minEthereumDistributionICEBalanceRequired := 1100.0 + ethAddress := "0x111Fc57e1e4e7687c9195F7856C45227f269323B" + country := "France" + distributionDeniedCountries := map[string]struct{}{} + miningSessionSoloStartedAt, miningSessionSoloEndedAt, ethereumDistributionEndDate := time.New(now.Add(-25*stdlibtime.Hour)), time.New(now.Add(13*stdlibtime.Hour)), time.New(now.Add(24*stdlibtime.Hour)) + collectingEndedAt := time.New(now.Add(5 * stdlibtime.Hour)) + kycState := model.KYCState{ + KYCStepsCreatedAtField: model.KYCStepsCreatedAtField{KYCStepsCreatedAt: &model.TimeSlice{time.New(now.Add(1 * stdlibtime.Hour)), time.New(now.Add(2 * stdlibtime.Hour)), time.New(now.Add(3 * stdlibtime.Hour)), time.New(now.Add(4 * stdlibtime.Hour))}}, + KYCStepsLastUpdatedAtField: model.KYCStepsLastUpdatedAtField{KYCStepsLastUpdatedAt: &model.TimeSlice{time.New(now.Add(1 * stdlibtime.Hour)), time.New(now.Add(2 * stdlibtime.Hour)), time.New(now.Add(3 * stdlibtime.Hour)), time.New(now.Add(4 * stdlibtime.Hour))}}, + KYCStepPassedField: model.KYCStepPassedField{KYCStepPassed: users.QuizKYCStep}, + KYCStepBlockedField: model.KYCStepBlockedField{KYCStepBlocked: users.NoneKYCStep}, + KYCQuizCompletedField: model.KYCQuizCompletedField{KYCQuizCompleted: true}, + KYCQuizDisabledField: model.KYCQuizDisabledField{KYCQuizDisabled: false}, + } + miningSessionDuration, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax := 24*stdlibtime.Hour, stdlibtime.Hour, 24*stdlibtime.Hour + assert.False(t, IsEligibleForEthereumDistribution(minMiningStreaksRequired, standardBalance, minEthereumDistributionICEBalanceRequired, ethAddress, country, distributionDeniedCountries, now, + collectingEndedAt, miningSessionSoloStartedAt, miningSessionSoloEndedAt, ethereumDistributionEndDate, kycState, miningSessionDuration, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + }) + + t.Run("Balance less than minimum distribution balance required, delta > ethereumDistributionFrequencyMax", func(t *testing.T) { + t.Parallel() + + minMiningStreaksRequired := uint64(1) + standardBalance := 1000.0 + ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax := stdlibtime.Hour, 24*stdlibtime.Hour + now := testTime + minEthereumDistributionICEBalanceRequired := 1000.0 + ethAddress := "0x111Fc57e1e4e7687c9195F7856C45227f269323B" + country := "France" + distributionDeniedCountries := map[string]struct{}{} + miningSessionSoloStartedAt, miningSessionSoloEndedAt, ethereumDistributionEndDate := time.New(now.Add(-25*stdlibtime.Hour)), time.New(now.Add(13*stdlibtime.Hour)), time.New(now.Add(48*stdlibtime.Hour)) + collectingEndedAt := time.New(now.Add(5 * stdlibtime.Hour)) + kycState := model.KYCState{ + KYCStepsCreatedAtField: model.KYCStepsCreatedAtField{KYCStepsCreatedAt: &model.TimeSlice{time.New(now.Add(1 * stdlibtime.Hour)), time.New(now.Add(2 * stdlibtime.Hour)), time.New(now.Add(3 * stdlibtime.Hour)), time.New(now.Add(4 * stdlibtime.Hour))}}, + KYCStepsLastUpdatedAtField: model.KYCStepsLastUpdatedAtField{KYCStepsLastUpdatedAt: &model.TimeSlice{time.New(now.Add(1 * stdlibtime.Hour)), time.New(now.Add(2 * stdlibtime.Hour)), time.New(now.Add(3 * stdlibtime.Hour)), time.New(now.Add(4 * stdlibtime.Hour))}}, + KYCStepPassedField: model.KYCStepPassedField{KYCStepPassed: users.QuizKYCStep}, + KYCStepBlockedField: model.KYCStepBlockedField{KYCStepBlocked: users.NoneKYCStep}, + KYCQuizCompletedField: model.KYCQuizCompletedField{KYCQuizCompleted: true}, + KYCQuizDisabledField: model.KYCQuizDisabledField{KYCQuizDisabled: false}, + } + miningSessionDuration, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax := 24*stdlibtime.Hour, stdlibtime.Hour, 24*stdlibtime.Hour + assert.False(t, IsEligibleForEthereumDistribution(minMiningStreaksRequired, standardBalance, minEthereumDistributionICEBalanceRequired, ethAddress, country, distributionDeniedCountries, now, + collectingEndedAt, miningSessionSoloStartedAt, miningSessionSoloEndedAt, ethereumDistributionEndDate, kycState, miningSessionDuration, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + }) + + t.Run("Quiz completed is true/false && Quiz disabled is true", func(t *testing.T) { + t.Parallel() + + minMiningStreaksRequired := uint64(1) + standardBalance := 100.0 + minEthereumDistributionICEBalanceRequired := 10.0 + ethAddress := "0x111Fc57e1e4e7687c9195F7856C45227f269323B" + country := "France" + distributionDeniedCountries := map[string]struct{}{} + now := testTime + miningSessionSoloStartedAt, miningSessionSoloEndedAt, ethereumDistributionEndDate := time.New(now.Add(-25*stdlibtime.Hour)), time.New(now.Add(13*stdlibtime.Hour)), time.New(now.Add(64*stdlibtime.Hour)) + collectingEndedAt := time.New(now.Add(5 * stdlibtime.Hour)) + kycState := model.KYCState{ + KYCStepsCreatedAtField: model.KYCStepsCreatedAtField{KYCStepsCreatedAt: &model.TimeSlice{time.New(now.Add(1 * stdlibtime.Hour)), time.New(now.Add(2 * stdlibtime.Hour)), time.New(now.Add(3 * stdlibtime.Hour)), time.New(now.Add(4 * stdlibtime.Hour))}}, + KYCStepsLastUpdatedAtField: model.KYCStepsLastUpdatedAtField{KYCStepsLastUpdatedAt: &model.TimeSlice{time.New(now.Add(1 * stdlibtime.Hour)), time.New(now.Add(2 * stdlibtime.Hour)), time.New(now.Add(3 * stdlibtime.Hour)), time.New(now.Add(4 * stdlibtime.Hour))}}, + KYCStepPassedField: model.KYCStepPassedField{KYCStepPassed: users.QuizKYCStep}, + KYCStepBlockedField: model.KYCStepBlockedField{KYCStepBlocked: users.NoneKYCStep}, + KYCQuizCompletedField: model.KYCQuizCompletedField{KYCQuizCompleted: false}, + KYCQuizDisabledField: model.KYCQuizDisabledField{KYCQuizDisabled: true}, + } + miningSessionDuration, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax := 24*stdlibtime.Hour, stdlibtime.Hour, 24*stdlibtime.Hour + assert.False(t, IsEligibleForEthereumDistribution(minMiningStreaksRequired, standardBalance, minEthereumDistributionICEBalanceRequired, ethAddress, country, distributionDeniedCountries, now, + collectingEndedAt, miningSessionSoloStartedAt, miningSessionSoloEndedAt, ethereumDistributionEndDate, kycState, miningSessionDuration, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + + kycState.KYCQuizCompleted = true + assert.False(t, IsEligibleForEthereumDistribution(minMiningStreaksRequired, standardBalance, minEthereumDistributionICEBalanceRequired, ethAddress, country, distributionDeniedCountries, now, + collectingEndedAt, miningSessionSoloStartedAt, miningSessionSoloEndedAt, ethereumDistributionEndDate, kycState, miningSessionDuration, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + }) +} + +func TestIsEligibleForEthereumDistributionNow1(t *testing.T) { + t.Parallel() + + t.Run("lastEthereumCoinDistributionProcessedAt.IsNil() && today.Equal(ethereumDistributionStartDate)", func(t *testing.T) { + var lastEthereumCoinDistributionProcessedAt *time.Time + now := testTime + coinDistributionStartDate := testTime + latestCoinDistributionCollectingDate := testTime + ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax := stdlibtime.Hour, 24*stdlibtime.Hour + assert.True(t, IsEligibleForEthereumDistributionNow(1, now, lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate, latestCoinDistributionCollectingDate, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + assert.True(t, IsEligibleForEthereumDistributionNow(2, now, lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate, latestCoinDistributionCollectingDate, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + assert.True(t, IsEligibleForEthereumDistributionNow(3, now, lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate, latestCoinDistributionCollectingDate, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + assert.True(t, IsEligibleForEthereumDistributionNow(4, now, lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate, latestCoinDistributionCollectingDate, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + assert.True(t, IsEligibleForEthereumDistributionNow(5, now, lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate, latestCoinDistributionCollectingDate, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + }) + + t.Run("!lastEthereumCoinDistributionProcessedAt.IsNil() && today.Equal(ethereumDistributionStartDate)", func(t *testing.T) { + now := testTime + lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate := testTime, testTime + latestCoinDistributionCollectingDate := testTime + ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax := stdlibtime.Hour, 24*stdlibtime.Hour + assert.False(t, IsEligibleForEthereumDistributionNow(1, now, lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate, latestCoinDistributionCollectingDate, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + assert.False(t, IsEligibleForEthereumDistributionNow(2, now, lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate, latestCoinDistributionCollectingDate, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + assert.False(t, IsEligibleForEthereumDistributionNow(3, now, lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate, latestCoinDistributionCollectingDate, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + assert.False(t, IsEligibleForEthereumDistributionNow(4, now, lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate, latestCoinDistributionCollectingDate, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + assert.False(t, IsEligibleForEthereumDistributionNow(5, now, lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate, latestCoinDistributionCollectingDate, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + }) + + t.Run("lastEthereumCoinDistributionProcessedAt.IsNil() && !today.Equal(ethereumDistributionStartDate) && !latestCoinDistributionCollectingDate.isNil() && now.After(latestCoinDistributionCollectingDay)", func(t *testing.T) { + lastEthereumCoinDistributionProcessedAt, now := testTime, time.New(testTime.Add(48*stdlibtime.Hour)) + coinDistributionStartDate := time.New(testTime.Add(-24 * stdlibtime.Hour)) + ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax := 24*stdlibtime.Hour, 24*28*stdlibtime.Hour + latestCoinDistributionCollectingDate := time.New(testTime.Add(24 * stdlibtime.Hour)) + assert.False(t, IsEligibleForEthereumDistributionNow(1, now, lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate, latestCoinDistributionCollectingDate, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + assert.True(t, IsEligibleForEthereumDistributionNow(2, now, lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate, latestCoinDistributionCollectingDate, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + assert.False(t, IsEligibleForEthereumDistributionNow(3, now, lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate, latestCoinDistributionCollectingDate, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + assert.False(t, IsEligibleForEthereumDistributionNow(4, now, lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate, latestCoinDistributionCollectingDate, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + assert.False(t, IsEligibleForEthereumDistributionNow(5, now, lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate, latestCoinDistributionCollectingDate, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + + lastEthereumCoinDistributionProcessedAt = now + now = time.New(testTime.Add(72 * stdlibtime.Hour)) + latestCoinDistributionCollectingDate = time.New(testTime.Add(48 * stdlibtime.Hour)) + assert.False(t, IsEligibleForEthereumDistributionNow(1, now, lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate, latestCoinDistributionCollectingDate, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + assert.False(t, IsEligibleForEthereumDistributionNow(2, now, lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate, latestCoinDistributionCollectingDate, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + assert.True(t, IsEligibleForEthereumDistributionNow(3, now, lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate, latestCoinDistributionCollectingDate, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + assert.False(t, IsEligibleForEthereumDistributionNow(4, now, lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate, latestCoinDistributionCollectingDate, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + assert.False(t, IsEligibleForEthereumDistributionNow(5, now, lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate, latestCoinDistributionCollectingDate, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + + lastEthereumCoinDistributionProcessedAt = now + now = time.New(testTime.Add(96 * stdlibtime.Hour)) + latestCoinDistributionCollectingDate = time.New(testTime.Add(72 * stdlibtime.Hour)) + assert.False(t, IsEligibleForEthereumDistributionNow(1, now, lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate, latestCoinDistributionCollectingDate, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + assert.False(t, IsEligibleForEthereumDistributionNow(2, now, lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate, latestCoinDistributionCollectingDate, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + assert.False(t, IsEligibleForEthereumDistributionNow(3, now, lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate, latestCoinDistributionCollectingDate, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + assert.True(t, IsEligibleForEthereumDistributionNow(4, now, lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate, latestCoinDistributionCollectingDate, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + assert.False(t, IsEligibleForEthereumDistributionNow(5, now, lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate, latestCoinDistributionCollectingDate, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + }) + + t.Run("lastEthereumCoinDistributionProcessedAt.IsNil() && !today.Equal(ethereumDistributionStartDate) && !latestCoinDistributionCollectingDate.isNil() && now.Before(latestCoinDistributionCollectingDay)", func(t *testing.T) { + lastEthereumCoinDistributionProcessedAt, now := testTime, testTime + coinDistributionStartDate := time.New(testTime.Add(-24 * stdlibtime.Hour)) + ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax := 24*stdlibtime.Hour, 24*28*stdlibtime.Hour + latestCoinDistributionCollectingDate := time.New(testTime.Add(24 * stdlibtime.Hour)) + assert.False(t, IsEligibleForEthereumDistributionNow(1, now, lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate, latestCoinDistributionCollectingDate, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + assert.False(t, IsEligibleForEthereumDistributionNow(2, now, lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate, latestCoinDistributionCollectingDate, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + assert.False(t, IsEligibleForEthereumDistributionNow(3, now, lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate, latestCoinDistributionCollectingDate, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + assert.False(t, IsEligibleForEthereumDistributionNow(4, now, lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate, latestCoinDistributionCollectingDate, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + assert.False(t, IsEligibleForEthereumDistributionNow(5, now, lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate, latestCoinDistributionCollectingDate, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + }) + + t.Run("lastEthereumCoinDistributionProcessedAt.IsNil() && !today.Equal(ethereumDistributionStartDate) && latestCoinDistributionCollectingDate.isNil() && today ~ coinDistributionStartDate", func(t *testing.T) { + lastEthereumCoinDistributionProcessedAt, now := testTime, time.New(testTime.Add(52*stdlibtime.Hour)) + coinDistributionStartDate := time.New(testTime.Add(48 * stdlibtime.Hour)) + ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax := 24*stdlibtime.Hour, 24*28*stdlibtime.Hour + var latestCoinDistributionCollectingDate *time.Time + assert.True(t, IsEligibleForEthereumDistributionNow(1, now, lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate, latestCoinDistributionCollectingDate, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + assert.True(t, IsEligibleForEthereumDistributionNow(2, now, lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate, latestCoinDistributionCollectingDate, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + assert.True(t, IsEligibleForEthereumDistributionNow(3, now, lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate, latestCoinDistributionCollectingDate, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + assert.True(t, IsEligibleForEthereumDistributionNow(4, now, lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate, latestCoinDistributionCollectingDate, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + assert.True(t, IsEligibleForEthereumDistributionNow(5, now, lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate, latestCoinDistributionCollectingDate, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + }) + + t.Run("lastEthereumCoinDistributionProcessedAt.IsNil() && !today.Equal(ethereumDistributionStartDate) && latestCoinDistributionCollectingDate.isNil() && today !~ coinDistributionStartDate", func(t *testing.T) { + lastEthereumCoinDistributionProcessedAt, now := testTime, time.New(testTime.Add(72*stdlibtime.Hour)) + coinDistributionStartDate := time.New(testTime.Add(48 * stdlibtime.Hour)) + ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax := 24*stdlibtime.Hour, 24*28*stdlibtime.Hour + var latestCoinDistributionCollectingDate *time.Time + assert.False(t, IsEligibleForEthereumDistributionNow(1, now, lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate, latestCoinDistributionCollectingDate, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + assert.False(t, IsEligibleForEthereumDistributionNow(2, now, lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate, latestCoinDistributionCollectingDate, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + assert.False(t, IsEligibleForEthereumDistributionNow(3, now, lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate, latestCoinDistributionCollectingDate, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + assert.False(t, IsEligibleForEthereumDistributionNow(4, now, lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate, latestCoinDistributionCollectingDate, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + assert.False(t, IsEligibleForEthereumDistributionNow(5, now, lastEthereumCoinDistributionProcessedAt, coinDistributionStartDate, latestCoinDistributionCollectingDate, ethereumDistributionFrequencyMin, ethereumDistributionFrequencyMax)) + }) +} + +func TestIsEthereumAddressValid(t *testing.T) { + t.Parallel() + + t.Run("Positive case", func(t *testing.T) { + t.Parallel() + ethAddress := "0x111Fc57e1e4e7687c9195F7856C45227f269323B" + assert.True(t, isEthereumAddressValid(ethAddress)) + }) + + t.Run("Empty eth address", func(t *testing.T) { + t.Parallel() + ethAddress := "" + assert.False(t, isEthereumAddressValid(ethAddress)) + }) + + t.Run("Skip", func(t *testing.T) { + t.Parallel() + ethAddress := "skip" + assert.True(t, isEthereumAddressValid(ethAddress)) + }) + + t.Run("Not hex", func(t *testing.T) { + t.Parallel() + ethAddress := "abcdefghi" + assert.False(t, isEthereumAddressValid(ethAddress)) + }) +} diff --git a/go.mod b/go.mod index 28a955c..b04154b 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,7 @@ module github.com/ice-blockchain/freezer go 1.21 -replace github.com/cockroachdb/pebble v1.0.0 => github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 +replace github.com/cockroachdb/pebble v1.1.0 => github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 require ( github.com/ClickHouse/ch-go v0.61.2 @@ -12,7 +12,7 @@ require ( github.com/ethereum/go-ethereum v1.13.11 github.com/goccy/go-json v0.10.2 github.com/hashicorp/go-multierror v1.1.1 - github.com/ice-blockchain/eskimo v1.295.0 + github.com/ice-blockchain/eskimo v1.296.0 github.com/ice-blockchain/go-tarantool-client v0.0.0-20230327200757-4fc71fa3f7bb github.com/ice-blockchain/wintr v1.133.0 github.com/imroc/req/v3 v3.42.3 @@ -24,7 +24,7 @@ require ( github.com/swaggo/swag v1.16.3 github.com/testcontainers/testcontainers-go v0.27.0 go.uber.org/zap v1.26.0 - golang.org/x/exp v0.0.0-20240119083558-1b970713d09a + golang.org/x/exp v0.0.0-20240205201215-2c58cdc269a3 ) require ( @@ -56,7 +56,7 @@ require ( github.com/cloudflare/circl v1.3.7 // indirect github.com/cockroachdb/errors v1.11.1 // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect - github.com/cockroachdb/pebble v1.0.0 // indirect + github.com/cockroachdb/pebble v1.1.0 // indirect github.com/cockroachdb/redact v1.1.5 // indirect github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect github.com/consensys/bavard v0.1.13 // indirect @@ -207,7 +207,7 @@ require ( golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.17.0 // indirect - google.golang.org/api v0.161.0 // indirect + google.golang.org/api v0.162.0 // indirect google.golang.org/appengine v1.6.8 // indirect google.golang.org/appengine/v2 v2.0.5 // indirect google.golang.org/genproto v0.0.0-20240205150955-31a09d347014 // indirect diff --git a/go.sum b/go.sum index 6ee3ae8..25394ee 100644 --- a/go.sum +++ b/go.sum @@ -303,8 +303,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.295.0 h1:cKQ3WUBr4XWy1bjzBL9KdC5xwNOB129HjVBD+TPvmCA= -github.com/ice-blockchain/eskimo v1.295.0/go.mod h1:EXhXoISEc8/jnHAYvuZhbsKhvKRoHvlG7QQ6Bs1XKRA= +github.com/ice-blockchain/eskimo v1.296.0 h1:fkooIr3xKWbwhGYXuV8E5AXv69eWeiwqzSPSOemyZaY= +github.com/ice-blockchain/eskimo v1.296.0/go.mod h1:Hi23aocK2pxiDx/TNb6fNw6xRSaWXmIFYk/Kpqk2oM8= 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.133.0 h1:lmRQQlowBWBKZfAW6vVAtDwYRc4mKvx9MkgPArQgkwU= @@ -574,8 +574,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA= -golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= +golang.org/x/exp v0.0.0-20240205201215-2c58cdc269a3 h1:/RIbNt/Zr7rVhIkQhooTxCxFcdWLGIKnZA4IXNFSrvo= +golang.org/x/exp v0.0.0-20240205201215-2c58cdc269a3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -675,8 +675,8 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= -google.golang.org/api v0.161.0 h1:oYzk/bs26WN10AV7iU7MVJVXBH8oCPS2hHyBiEeFoSU= -google.golang.org/api v0.161.0/go.mod h1:0mu0TpK33qnydLvWqbImq2b1eQ5FHRSDCBzAxX9ZHyw= +google.golang.org/api v0.162.0 h1:Vhs54HkaEpkMBdgGdOT2P6F0csGG/vxDS0hWHJzmmps= +google.golang.org/api v0.162.0/go.mod h1:6SulDkfoBIg4NFmCuZ39XeeAgSHCPecfSUuDyYlAHs0= 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 v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=