From a57e240537443f9c39566ca79a27e98652928538 Mon Sep 17 00:00:00 2001 From: Lee ByeongJun Date: Tue, 31 Dec 2024 00:38:19 +0900 Subject: [PATCH] test, fix: api_calculation --- staker/api_calculation_base_data.gno | 431 +++------------------- staker/api_calculation_base_data_test.gno | 127 ++++++- 2 files changed, 180 insertions(+), 378 deletions(-) diff --git a/staker/api_calculation_base_data.gno b/staker/api_calculation_base_data.gno index b056fd5d..0381c63e 100644 --- a/staker/api_calculation_base_data.gno +++ b/staker/api_calculation_base_data.gno @@ -35,206 +35,44 @@ func GetPoolStakedLiquidityUpdates(poolPath string, startHeight, endHeight uint6 return marshal(builder.Node()) } -// func GetPoolRewardUpdates(poolPath string, startHeight, endHeight uint64) string { -// pool, ok := pools.Get(poolPath) -// if !ok { -// return "" -// } - -// // TODO: remove comment -// // if endHeight > pool.lastRewardCacheHeight { -// // poolTier.cacheReward(endHeight) -// // poolTier.cachePoolReward(pool.rewardCache, poolPath, endHeight) -// // } - -// builder := json.Builder().WriteArray("", func(ab *json.ArrayBuilder) { -// pool.rewardCache.Iterate(startHeight, endHeight, func(key uint64, value interface{}) bool { -// ab.WriteObject(func(ob *json.NodeBuilder) { -// ob.WriteString("blockNumber", ufmt.Sprintf("%d", key)) -// ob.WriteString("reward", value.(*u256.Uint).ToString()) -// }) -// return false -// }) -// }) - -// return marshal(builder.Node()) -// } - -// poolsPositions -// func GetPoolsPositions() string { -// en.MintAndDistributeGns() - -// // TODO: find original/modified code and remove comment -// if len(positionsLiquidityRatio) == 0 { -// return "" -// } - -// builder := json.Builder().WriteArray("", func(ab *json.ArrayBuilder) { -// for poolPath, tokenIds := range poolsPositions { -// ab.WriteObject(func(ob *json.NodeBuilder) { -// buildPoolPosition(poolPath, tokenIds, ob) -// }) -// } -// }) - -// return marshal(arrNode) -// } +func GetPoolRewardUpdates(poolPath string, startHeight, endHeight uint64) string { + pool, ok := pools.Get(poolPath) + if !ok { + return "" + } -// func buildTokenIsArray(tokenIds []uint64, ab *json.ArrayBuilder) { -// for _, tokenId := range tokenIds { -// ab.WriteString(ufmt.Sprintf("%d", tokenId)) -// } -// } + builder := json.Builder().WriteArray("", func(ab *json.ArrayBuilder) { + pool.rewardCache.Iterate(startHeight, endHeight, func(key uint64, value interface{}) bool { + ab.WriteObject(func(ob *json.NodeBuilder) { + ob.WriteString("blockNumber", ufmt.Sprintf("%d", key)) + ob.WriteString("reward", value.(*u256.Uint).ToString()) + }) + return false + }) + }) -// func buildPoolPosition(poolPath string, tokenIds []uint64, ob *json.NodeBuilder) { -// ob.WriteString("poolPath", poolPath) -// ob.WriteArray("tokenIds", func(ab *json.ArrayBuilder) { -// buildTokenIsArray(tokenIds, ab) -// }) -// } + return marshal(builder.Node()) +} // consts.Q96 -// func GetQ96() string { -// en.MintAndDistributeGns() - -// return "79228162514264337593543950336" -// } - -// // positionExternal -// func GetPositionExternal() string { -// en.MintAndDistributeGns() - -// if len(positionExternal) == 0 { -// return "" -// } - -// builder := json.Builder().WriteArray("", func(ab *json.ArrayBuilder) { -// for tokenId, externals := range positionExternal { -// ab.WriteObject(func(ob *json.NodeBuilder) { -// ob.WriteString("tokenId", ufmt.Sprintf("%d", tokenId)) -// ob.WriteArray("externals", func(extAb *json.ArrayBuilder) { -// buildPositionExternals(externals, extAb) -// }) -// }) -// } -// }) - -// return marshal(builder.Node()) -// } - -// func buildExternalReward(incentiveId string, reward *externalRewards, ob *json.NodeBuilder) { -// ob.WriteString("incentiveId", incentiveId) -// ob.WriteString("poolPath", reward.poolPath) -// ob.WriteString("tokenPath", reward.tokenPath) -// ob.WriteString("tokenAmountX96", reward.tokenAmountX96.ToString()) -// ob.WriteString("tokenAmountFull", ufmt.Sprintf("%d", reward.tokenAmountFull)) -// ob.WriteString("tokenAmountToGive", ufmt.Sprintf("%d", reward.tokenAmountToGive)) -// } +func GetQ96() string { + en.MintAndDistributeGns() -// func buildPositionExternals(externals map[string]externalRewards, ab *json.ArrayBuilder) { -// for incentiveId, externalRewards := range externals { -// ab.WriteObject(func(ob *json.NodeBuilder) { -// buildExternalReward(incentiveId, &externalRewards, ob) -// }) -// } -// } - -// positionsInternalWarmUpAmount -// func GetPositionsInternalWarmUpAmount() string { -// en.MintAndDistributeGns() - -// if len(positionsInternalWarmUpAmount) == 0 { -// return "" -// } - -// arrNode := json.ArrayNode("", []*json.Node{}) -// for tokenId, internalWarmUpAmount := range positionsInternalWarmUpAmount { -// objNode := json.ObjectNode("", map[string]*json.Node{ -// "tokenId": json.StringNode("tokenId", ufmt.Sprintf("%d", tokenId)), -// "full30": json.StringNode("full30", ufmt.Sprintf("%d", internalWarmUpAmount.full30)), -// "give30": json.StringNode("give30", ufmt.Sprintf("%d", internalWarmUpAmount.give30)), -// "left30": json.StringNode("left30", ufmt.Sprintf("%d", internalWarmUpAmount.left30)), -// "full50": json.StringNode("full50", ufmt.Sprintf("%d", internalWarmUpAmount.full50)), -// "give50": json.StringNode("give50", ufmt.Sprintf("%d", internalWarmUpAmount.give50)), -// "left50": json.StringNode("left50", ufmt.Sprintf("%d", internalWarmUpAmount.left50)), -// "full70": json.StringNode("full70", ufmt.Sprintf("%d", internalWarmUpAmount.full70)), -// "give70": json.StringNode("give70", ufmt.Sprintf("%d", internalWarmUpAmount.give70)), -// "left70": json.StringNode("left70", ufmt.Sprintf("%d", internalWarmUpAmount.left70)), -// "full100": json.StringNode("full100", ufmt.Sprintf("%d", internalWarmUpAmount.full100)), -// }) -// arrNode.AppendArray(objNode) -// } - -// return marshal(arrNode) -// } - -// positionsExternalWarmUpAmount -// func GetPositionsExternalWarmUpAmount() string { -// en.MintAndDistributeGns() - -// if len(positionsExternalWarmUpAmount) == 0 { -// return "" -// } - -// arrNode := json.ArrayNode("", []*json.Node{}) -// for tokenId, externals := range positionsExternalWarmUpAmount { -// for incentiveId, externalWarmUpAmount := range externals { -// objNode := json.ObjectNode("", map[string]*json.Node{ -// "tokenId": json.StringNode("tokenId", ufmt.Sprintf("%d", tokenId)), -// "incentiveId": json.StringNode("incentiveId", incentiveId), -// "full30": json.StringNode("full30", ufmt.Sprintf("%d", externalWarmUpAmount.full30)), -// "give30": json.StringNode("give30", ufmt.Sprintf("%d", externalWarmUpAmount.give30)), -// "left30": json.StringNode("left30", ufmt.Sprintf("%d", externalWarmUpAmount.left30)), -// "full50": json.StringNode("full50", ufmt.Sprintf("%d", externalWarmUpAmount.full50)), -// "give50": json.StringNode("give50", ufmt.Sprintf("%d", externalWarmUpAmount.give50)), -// "left50": json.StringNode("left50", ufmt.Sprintf("%d", externalWarmUpAmount.left50)), -// "full70": json.StringNode("full70", ufmt.Sprintf("%d", externalWarmUpAmount.full70)), -// "give70": json.StringNode("give70", ufmt.Sprintf("%d", externalWarmUpAmount.give70)), -// "left70": json.StringNode("left70", ufmt.Sprintf("%d", externalWarmUpAmount.left70)), -// "full100": json.StringNode("full100", ufmt.Sprintf("%d", externalWarmUpAmount.full100)), -// }) -// arrNode.AppendArray(objNode) -// } -// } - -// return marshal(arrNode) -// } - -// positionsExternalLastCalculatedHeight -// func GetPositionsExternalLastCalculatedHeight() string { -// en.MintAndDistributeGns() - -// if len(positionsExternalLastCalculatedHeight) == 0 { -// return "" -// } - -// arrNode := json.ArrayNode("", []*json.Node{}) -// for tokenId, externals := range positionsExternalLastCalculatedHeight { -// for incentiveId, lastCalculatedHeight := range externals { -// objNode := json.ObjectNode("", map[string]*json.Node{ -// "tokenId": json.StringNode("tokenId", ufmt.Sprintf("%d", tokenId)), -// "incentiveId": json.StringNode("incentiveId", incentiveId), -// "lastCalculatedHeight": json.StringNode("lastCalculatedHeight", ufmt.Sprintf("%d", lastCalculatedHeight)), -// }) -// arrNode.AppendArray(objNode) -// } -// } - -// return marshal(arrNode) -// } + return "79228162514264337593543950336" +} -// // ETC -// func GetHeight() int64 { -// en.MintAndDistributeGns() +// ETC +func GetHeight() int64 { + en.MintAndDistributeGns() -// return std.GetHeight() -// } + return std.GetHeight() +} -// func GetTimeNowUnix() int64 { -// en.MintAndDistributeGns() +func GetTimeNowUnix() int64 { + en.MintAndDistributeGns() -// return time.Now().Unix() -// } + return time.Now().Unix() +} // func GetExternalGnsAmount() uint64 { // en.MintAndDistributeGns() @@ -242,202 +80,41 @@ func GetPoolStakedLiquidityUpdates(poolPath string, startHeight, endHeight uint6 // return externalGnsAmount() // } -// func GetExternalDepositGnsAmount() uint64 { -// en.MintAndDistributeGns() - -// return externalDepositGnsAmount() -// } - -// func GetStakerGnsBalance() uint64 { -// en.MintAndDistributeGns() - -// return gnsBalance(consts.STAKER_ADDR) -// } - -// func GetStakerEmissionGnsBalance() uint64 { -// en.MintAndDistributeGns() - -// return gnsBalance(consts.STAKER_ADDR) - externalGnsAmount() - externalDepositGnsAmount() -// } - -// func GetLastCalculatedBalance() uint64 { -// en.MintAndDistributeGns() - -// return lastCalculatedBalance -// } - -// func GetLastCalculatedHeight() int64 { -// en.MintAndDistributeGns() - -// return lastCalculatedHeight -// } - -// func GetPositionIsInRange(tokenId uint64) bool { -// en.MintAndDistributeGns() - -// return pn.PositionIsInRange(tokenId) -// } - -// func GetPositionLiquidity(tokenId uint64) string { -// en.MintAndDistributeGns() - -// return pn.PositionGetPositionLiquidityStr(tokenId) -// } - -// func GetMintedGnsAmount() uint64 { -// en.MintAndDistributeGns() - -// // not a global variable -// // return mintedGnsAmount - -// // formula: stakerGnsBalance - lastCalculatedBalance -// return gnsBalance(consts.STAKER_ADDR) - GetLastCalculatedBalance() -// } - -// func GetNumPoolTiers() string { -// en.MintAndDistributeGns() - -// tier1, tier2, tier3 := getNumPoolTiers() -// return ufmt.Sprintf("%d*STAKER*%d*STAKER*%d", tier1, tier2, tier3) -// } - -// func GetTiersRatio() string { -// en.MintAndDistributeGns() - -// tier1Ratio, tier2Ratio, tier3Ratio := listTierRatio() -// return ufmt.Sprintf("%d*STAKER*%d*STAKER*%d", tier1Ratio, tier2Ratio, tier3Ratio) -// } - -// func GetTiersAmount(amount uint64) string { -// en.MintAndDistributeGns() - -// tier1Amount, tier2Amount, tier3Amount := getTiersAmount(amount) -// return ufmt.Sprintf("%d*STAKER*%d*STAKER*%d", tier1Amount, tier2Amount, tier3Amount) -// } - -// func GetWarmUpPeriods() string { -// en.MintAndDistributeGns() +func GetStakerGnsBalance() uint64 { + en.MintAndDistributeGns() -// warmUp30 := warmUp[30] -// warmUp50 := warmUp[50] -// warmUp70 := warmUp[70] -// warmUp100 := warmUp[100] - -// return ufmt.Sprintf("%d*STAKER*%d*STAKER*%d*STAKER*%d", warmUp30, warmUp50, warmUp70, warmUp100) -// } - -// // GetNecessary returns the all necessary data for the calculation -// func GetNecessary() string { -// en.MintAndDistributeGns() - -// height := std.GetHeight() -// now := time.Now().Unix() - -// externalGnsBalance := GetExternalGnsAmount() -// externalDepositGnsAmount := GetExternalDepositGnsAmount() - -// gnsBalance := GetStakerGnsBalance() - -// numPoolTiers := GetNumPoolTiers() -// tiersRatio := GetTiersRatio() - -// response := json.ObjectNode("", map[string]*json.Node{ -// "height": json.StringNode("height", ufmt.Sprintf("%d", height)), -// "now": json.StringNode("now", ufmt.Sprintf("%d", now)), -// "blockGenerationInterval": json.StringNode("blockGenerationInterval", ufmt.Sprintf("%d", consts.BLOCK_GENERATION_INTERVAL)), -// "lastCalculatedHeight": json.StringNode("lastCalculatedHeight", ufmt.Sprintf("%d", lastCalculatedHeight)), -// "lastCalculatedBalance": json.StringNode("lastCalculatedBalance", ufmt.Sprintf("%d", lastCalculatedBalance)), -// "externalGnsBalance": json.StringNode("externalGnsBalance", ufmt.Sprintf("%d", externalGnsBalance)), -// "depositGnsAmount": json.StringNode("depositGnsAmount", ufmt.Sprintf("%d", externalDepositGnsAmount)), -// "gnsBalance": json.StringNode("gnsBalance", ufmt.Sprintf("%d", gnsBalance)), -// "numPoolTiers": json.StringNode("numPoolTiers", numPoolTiers), -// "tiersRatio": json.StringNode("tiersRatio", tiersRatio), -// "warmUpPeriods": json.StringNode("warmUpPeriods", GetWarmUpPeriods()), -// // -// "poolGns": json.StringNode("poolGns", b64encode(GetPoolGns())), -// "poolAccuGns": json.StringNode("poolAccuGns", b64encode(GetPoolAccuGns())), -// "poolLastTmpGns": json.StringNode("poolLastTmpGns", b64encode(GetPoolLastTmpGns())), -// // -// "positionGns": json.StringNode("positionGns", b64encode(GetPositionGns())), -// "positionLastGns": json.StringNode("positionLastGns", b64encode(GetPositionLastGns())), -// "positionsInternalWarmUpAmount": json.StringNode("positionsInternalWarmUpAmount", b64encode(GetPositionsInternalWarmUpAmount())), -// // -// "positionExternal": json.StringNode("positionExternal", b64encode(GetPositionExternal())), -// "positionLastExternal": json.StringNode("positionLastExternal", b64encode(GetPositionLastExternal())), -// "positionsExternalWarmUpAmount": json.StringNode("positionsExternalWarmUpAmount", b64encode(GetPositionsExternalWarmUpAmount())), -// "positionsExternalLastCalculatedHeight": json.StringNode("positionsExternalLastCalculatedHeight", b64encode(GetPositionsExternalLastCalculatedHeight())), -// "externalLastCalculatedTimestamp": json.StringNode("externalLastCalculatedTimestamp", b64encode(GetExternalLastCalculatedTimestamp())), -// }) - -// return marshal(response) -// } - -// // GetSingleData returns the single data for the calculation -// func GetSingleData() string { -// height := std.GetHeight() -// now := time.Now().Unix() - -// externalGnsBalance := GetExternalGnsAmount() -// externalDepositGnsAmount := GetExternalDepositGnsAmount() - -// gnsBalance := GetStakerGnsBalance() - -// numPoolTiers := GetNumPoolTiers() -// tiersRatio := GetTiersRatio() + return gnsBalance(consts.STAKER_ADDR) +} -// response := json.ObjectNode("", map[string]*json.Node{ -// "height": json.StringNode("height", ufmt.Sprintf("%d", height)), -// "now": json.StringNode("now", ufmt.Sprintf("%d", now)), -// // -// "blockGenerationInterval": json.StringNode("blockGenerationInterval", ufmt.Sprintf("%d", consts.BLOCK_GENERATION_INTERVAL)), -// "lastCalculatedHeight": json.StringNode("lastCalculatedHeight", ufmt.Sprintf("%d", lastCalculatedHeight)), -// "lastCalculatedBalance": json.StringNode("lastCalculatedBalance", ufmt.Sprintf("%d", lastCalculatedBalance)), -// "externalGnsBalance": json.StringNode("externalGnsBalance", ufmt.Sprintf("%d", externalGnsBalance)), -// "depositGnsAmount": json.StringNode("depositGnsAmount", ufmt.Sprintf("%d", externalDepositGnsAmount)), -// "gnsBalance": json.StringNode("gnsBalance", ufmt.Sprintf("%d", gnsBalance)), -// "numPoolTiers": json.StringNode("numPoolTiers", numPoolTiers), -// "tiersRatio": json.StringNode("tiersRatio", tiersRatio), -// "warmUpPeriods": json.StringNode("warmUpPeriods", GetWarmUpPeriods()), -// }) +func GetPositionIsInRange(tokenId uint64) bool { + en.MintAndDistributeGns() -// return marshal(response) -// } + return pn.PositionIsInRange(tokenId) +} -// // GetPoolGnsData returns the every pool's gns related data for the calculation -// func GetPoolGnsData() string { -// height := std.GetHeight() -// now := time.Now().Unix() +func GetPositionLiquidity(tokenId uint64) string { + en.MintAndDistributeGns() -// response := json.ObjectNode("", map[string]*json.Node{ -// "height": json.StringNode("height", ufmt.Sprintf("%d", height)), -// "now": json.StringNode("now", ufmt.Sprintf("%d", now)), -// // -// "poolGns": json.StringNode("poolGns", b64encode(GetPoolGns())), -// "poolAccuGns": json.StringNode("poolAccuGns", b64encode(GetPoolAccuGns())), -// "poolLastTmpGns": json.StringNode("poolLastTmpGns", b64encode(GetPoolLastTmpGns())), -// }) + return pn.PositionGetPositionLiquidityStr(tokenId) +} -// return marshal(response) -// } +func GetWarmUpPeriods() string { + en.MintAndDistributeGns() -// // GetPositionGnsData returns the every position's gns related data for the calculation -// func GetPositionGnsData() string { -// height := std.GetHeight() -// now := time.Now().Unix() + warmups := InstantiateWarmup(std.GetHeight()) -// response := json.ObjectNode("", map[string]*json.Node{ -// "height": json.StringNode("height", ufmt.Sprintf("%d", height)), -// "now": json.StringNode("now", ufmt.Sprintf("%d", now)), -// // -// "positionGns": json.StringNode("positionGns", b64encode(GetPositionGns())), -// "positionLastGns": json.StringNode("positionLastGns", b64encode(GetPositionLastGns())), -// "positionsInternalWarmUpAmount": json.StringNode("positionsInternalWarmUpAmount", b64encode(GetPositionsInternalWarmUpAmount())), -// }) + result := "" + for i, warmup := range warmups { + if i > 0 { + result += "*STAKER*" + } + result += ufmt.Sprintf("%d", warmup.WarmupRatio) + } -// return marshal(response) -// } + return result +} -// // GetPositionExternalData returns the every position's external related data for the calculation +// GetPositionExternalData returns the every position's external related data for the calculation // func GetPositionExternalData() string { // height := std.GetHeight() // now := time.Now().Unix() diff --git a/staker/api_calculation_base_data_test.gno b/staker/api_calculation_base_data_test.gno index 5069e121..a0d40434 100644 --- a/staker/api_calculation_base_data_test.gno +++ b/staker/api_calculation_base_data_test.gno @@ -1,6 +1,7 @@ package staker import ( + "std" "testing" "gno.land/p/demo/json" @@ -71,4 +72,128 @@ func TestGetPoolStakedLiquidityUpdates(t *testing.T) { uassert.Equal(t, liquidity, expect.liquidity) } }) -} \ No newline at end of file +} + +func TestGetPoolRewardUpdates(t *testing.T) { + pools = NewPools() + + t.Run("not exist pool", func(t *testing.T) { + result := GetPoolRewardUpdates("invalid_pool", 0, 100) + if result != "" { + t.Errorf("not exist pool should return empty string. got: %s", result) + } + }) + + t.Run("valid pool", func(t *testing.T) { + poolPath := "test_pool" + pool := &Pool{ + rewardCache: NewRewardCacheTree(), + } + pools.Set(poolPath, pool) + + testData := []struct { + height uint64 + value string + }{ + {15, "500"}, + {25, "1500"}, + {35, "2500"}, + } + + for _, td := range testData { + pool.rewardCache.Set(td.height, u256.MustFromDecimal(td.value)) + } + + result := GetPoolRewardUpdates(poolPath, 0, 100) + + node, err := json.Unmarshal([]byte(result)) + if err != nil { + uassert.NoError(t, err) + } + + array, err := node.GetKey("") + uassert.NoError(t, err) + uassert.Equal(t, array.Size(), 3) + + expectedData := []struct { + blockNumber string + reward string + }{ + {"15", "500"}, + {"25", "1500"}, + {"35", "2500"}, + } + + for i, expect := range expectedData { + item := array.MustIndex(i) + + blockNum, err := item.MustKey("blockNumber").GetString() + uassert.NoError(t, err) + uassert.Equal(t, blockNum, expect.blockNumber) + + reward, err := item.MustKey("reward").GetString() + uassert.NoError(t, err) + uassert.Equal(t, reward, expect.reward) + } + }) +} + +func TestGetWarmUpPeriods(t *testing.T) { + tests := []struct { + name string + currentHeight int64 + expectedOutput string + }{ + { + name: "normal warm-up period", + currentHeight: 100, + expectedOutput: "30*STAKER*50*STAKER*70*STAKER*100", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := GetWarmUpPeriods() + uassert.Equal(t, result, tt.expectedOutput) + }) + } +} + +func TestGetWarmUpPeriodsWithModifiedTemplate(t *testing.T) { + originalTemplate := make([]Warmup, len(warmupTemplate)) + copy(originalTemplate, warmupTemplate) + + defer func() { + warmupTemplate = originalTemplate + }() + + modifyWarmup(0, 1000) + + result := GetWarmUpPeriods() + expected := "30*STAKER*50*STAKER*70*STAKER*100" + + uassert.Equal(t, result, expected) +} + +func TestGetWarmUpPeriodsEdgeCases(t *testing.T) { + tests := []struct { + name string + expectedOutput string + }{ + { + name: "test 1", + expectedOutput: "30*STAKER*50*STAKER*70*STAKER*100", + }, + { + name: "test 2", + expectedOutput: "30*STAKER*50*STAKER*70*STAKER*100", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := GetWarmUpPeriods() + uassert.Equal(t, result, tt.expectedOutput) + }) + } +}