diff --git a/proto/dymensionxyz/dymension/iro/query.proto b/proto/dymensionxyz/dymension/iro/query.proto index 50f6f5646..6416459c4 100644 --- a/proto/dymensionxyz/dymension/iro/query.proto +++ b/proto/dymensionxyz/dymension/iro/query.proto @@ -46,6 +46,10 @@ service Query { option (google.api.http).get = "/dymensionxyz/dymension/iro/cost/{plan_id}"; } + rpc QueryTokensForDYM(QueryTokensForDYMRequest) returns (QueryTokensForDYMResponse) { + option (google.api.http).get = "/dymensionxyz/dymension/iro/tokens_for_dym/{plan_id}"; + } + // QueryClaimed retrieves the claimed amount thus far for the specified plan ID. rpc QueryClaimed(QueryClaimedRequest) returns (QueryClaimedResponse) { option (google.api.http).get = @@ -108,6 +112,20 @@ message QueryCostRequest { // QueryCostResponse is the response type for the Query/QueryCost RPC method. message QueryCostResponse { cosmos.base.v1beta1.Coin cost = 1; } + +// QueryTokensForDYMRequest is the request type for the Query/QueryTokensForDYM RPC method. +message QueryTokensForDYMRequest { + string plan_id = 1; + string amt = 2 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", + (gogoproto.nullable) = false + ]; +} + +// QueryTokensForDYMResponse is the response type for the Query/QueryTokensForDYM RPC method. +message QueryTokensForDYMResponse { cosmos.base.v1beta1.Coin tokens = 1; } + + // QueryClaimedRequest is the request type for the Query/QueryClaimed RPC // method. message QueryClaimedRequest { string plan_id = 1; } diff --git a/x/iro/keeper/create_plan.go b/x/iro/keeper/create_plan.go index 7b5bd8ee8..ef3e41298 100644 --- a/x/iro/keeper/create_plan.go +++ b/x/iro/keeper/create_plan.go @@ -106,6 +106,7 @@ func (k Keeper) CreatePlan(ctx sdk.Context, allocatedAmount math.Int, start, pre if err != nil { return "", err } + plan := types.NewPlan(k.GetNextPlanIdAndIncrement(ctx), rollapp.RollappId, allocation, curve, start, preLaunchTime, incentivesParams) if err := plan.ValidateBasic(); err != nil { return "", errors.Join(gerrc.ErrInvalidArgument, err) @@ -129,6 +130,10 @@ func (k Keeper) CreatePlan(ctx sdk.Context, allocatedAmount math.Int, start, pre return "", err } + // charge rollapp token creation fee. Same as DYM creation fee, will be used to open the pool. + tokenFee := math.NewIntWithDecimal(types.TokenCreationFee, int(rollapp.GenesisInfo.NativeDenom.Exponent)) + plan.SoldAmt = tokenFee + // Set the plan in the store k.SetPlan(ctx, plan) diff --git a/x/iro/keeper/query.go b/x/iro/keeper/query.go index 7016cf719..ab92202b6 100644 --- a/x/iro/keeper/query.go +++ b/x/iro/keeper/query.go @@ -65,6 +65,27 @@ func (k Keeper) QueryCost(goCtx context.Context, req *types.QueryCostRequest) (* return &types.QueryCostResponse{Cost: &cost}, nil } +// QueryTokensForDYM implements types.QueryServer. +func (k Keeper) QueryTokensForDYM(goCtx context.Context, req *types.QueryTokensForDYMRequest) (*types.QueryTokensForDYMResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "invalid request") + } + ctx := sdk.UnwrapSDKContext(goCtx) + + plan, found := k.GetPlan(ctx, req.PlanId) + if !found { + return nil, status.Error(codes.NotFound, "plan not found") + } + + tokensAmt, err := plan.BondingCurve.TokensForExactDYM(plan.SoldAmt, req.Amt) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + + tokens := sdk.NewCoin(plan.GetIRODenom(), tokensAmt) + return &types.QueryTokensForDYMResponse{Tokens: &tokens}, nil +} + // QueryPlan implements types.QueryServer. func (k Keeper) QueryPlan(goCtx context.Context, req *types.QueryPlanRequest) (*types.QueryPlanResponse, error) { if req == nil { diff --git a/x/iro/keeper/settle.go b/x/iro/keeper/settle.go index 7cb46e873..d16fd8813 100644 --- a/x/iro/keeper/settle.go +++ b/x/iro/keeper/settle.go @@ -86,8 +86,9 @@ func (k Keeper) Settle(ctx sdk.Context, rollappId, rollappIBCDenom string) error // - Creates a balancer pool with the determined tokens and DYM. // - Uses leftover tokens as incentives to the pool LP token holders. func (k Keeper) bootstrapLiquidityPool(ctx sdk.Context, plan types.Plan) (poolID, gaugeID uint64, err error) { - unallocatedTokens := plan.TotalAllocation.Amount.Sub(plan.SoldAmt) // assumed > 0, as we enforce it in the Buy function - raisedDYM := k.BK.GetBalance(ctx, plan.GetAddress(), appparams.BaseDenom) // assumed > 0, as we enforce it by IRO creation fee + tokenFee := math.NewIntWithDecimal(types.TokenCreationFee, int(plan.BondingCurve.SupplyDecimals())) + unallocatedTokens := plan.TotalAllocation.Amount.Sub(plan.SoldAmt.Sub(tokenFee)) // at least "reserve" amount of tokens (>0) + raisedDYM := k.BK.GetBalance(ctx, plan.GetAddress(), appparams.BaseDenom) // at least IRO creation fee (>0) // send the raised DYM to the iro module as it will be used as the pool creator err = k.BK.SendCoinsFromAccountToModule(ctx, plan.GetAddress(), types.ModuleName, sdk.NewCoins(raisedDYM)) diff --git a/x/iro/keeper/settle_test.go b/x/iro/keeper/settle_test.go index dd17851bc..f97c6e812 100644 --- a/x/iro/keeper/settle_test.go +++ b/x/iro/keeper/settle_test.go @@ -11,7 +11,6 @@ import ( appparams "github.com/dymensionxyz/dymension/v3/app/params" "github.com/dymensionxyz/dymension/v3/testutil/sample" incentivestypes "github.com/dymensionxyz/dymension/v3/x/incentives/types" - keeper "github.com/dymensionxyz/dymension/v3/x/iro/keeper" "github.com/dymensionxyz/dymension/v3/x/iro/types" ) @@ -62,177 +61,116 @@ func (s *KeeperTestSuite) TestSettle() { s.Require().Equal(soldAmt, balance.Amount) } -// Test liquidity pool bootstrap func (s *KeeperTestSuite) TestBootstrapLiquidityPool() { - rollappId := s.CreateDefaultRollapp() - k := s.App.IROKeeper - curve := types.DefaultBondingCurve() - incentives := types.DefaultIncentivePlanParams() - - startTime := time.Now() - allocation := sdk.NewInt(1_000_000).MulRaw(1e18) - maxAmt := sdk.NewInt(1_000_000_000).MulRaw(1e18) - rollappDenom := "dasdasdasdasdsa" - - rollapp := s.App.RollappKeeper.MustGetRollapp(s.Ctx, rollappId) - - // create IRO plan - apptesting.FundAccount(s.App, s.Ctx, sdk.MustAccAddressFromBech32(rollapp.Owner), sdk.NewCoins(sdk.NewCoin(appparams.BaseDenom, k.GetParams(s.Ctx).CreationFee))) - planId, err := k.CreatePlan(s.Ctx, allocation, startTime, startTime.Add(time.Hour), rollapp, curve, incentives) - s.Require().NoError(err) - - // buy some tokens - s.Ctx = s.Ctx.WithBlockTime(startTime.Add(time.Minute)) - buyer := sample.Acc() - buyersFunds := sdk.NewCoins(sdk.NewCoin("adym", maxAmt)) - s.FundAcc(buyer, buyersFunds) - - err = k.Buy(s.Ctx, planId, buyer, sdk.NewInt(1_000).MulRaw(1e18), maxAmt) - s.Require().NoError(err) - - plan := k.MustGetPlan(s.Ctx, planId) - raisedDYM := k.BK.GetBalance(s.Ctx, plan.GetAddress(), appparams.BaseDenom) - preSettleCoins := sdk.NewCoins(raisedDYM, sdk.NewCoin(rollappDenom, allocation.Sub(plan.SoldAmt))) - - // settle should succeed after fund - s.FundModuleAcc(types.ModuleName, sdk.NewCoins(sdk.NewCoin(rollappDenom, allocation))) - err = k.Settle(s.Ctx, rollappId, rollappDenom) - s.Require().NoError(err) - - /* -------------------------- assert liquidity pool ------------------------- */ - // pool created - expectedPoolID := uint64(1) - pool, err := s.App.GAMMKeeper.GetPool(s.Ctx, expectedPoolID) - s.Require().NoError(err) - - // pool price should be the same as the last price of the plan - price, err := pool.SpotPrice(s.Ctx, "adym", rollappDenom) - s.Require().NoError(err) - - plan = k.MustGetPlan(s.Ctx, planId) - lastPrice := plan.SpotPrice() - s.Require().Equal(lastPrice, price) - - // assert incentives - poolCoins := pool.GetTotalPoolLiquidity(s.Ctx) - gauges, err := s.App.IncentivesKeeper.GetGaugesForDenom(s.Ctx, gammtypes.GetPoolShareDenom(expectedPoolID)) - s.Require().NoError(err) - found := false - gauge := incentivestypes.Gauge{} - for _, gauge = range gauges { - if !gauge.IsPerpetual { - found = true - break - } - } - s.Require().True(found) - s.Require().False(gauge.Coins.IsZero()) - - // expected tokens for incentives: - // raisedDYM - poolCoins - // totalAllocation - soldAmt - poolCoins - expectedIncentives := preSettleCoins.Sub(poolCoins...) - s.Assert().Equal(expectedIncentives, gauge.Coins) -} - -func (s *KeeperTestSuite) TestSettleNothingSold() { - rollappId := s.CreateDefaultRollapp() - k := s.App.IROKeeper - curve := types.DefaultBondingCurve() - incentives := types.DefaultIncentivePlanParams() - - startTime := time.Now() - endTime := startTime.Add(time.Hour) - amt := sdk.NewInt(1_000_000).MulRaw(1e18) - rollappDenom := "rollapp_denom" - - rollapp := s.App.RollappKeeper.MustGetRollapp(s.Ctx, rollappId) - _, err := k.CreatePlan(s.Ctx, amt, startTime, endTime, rollapp, curve, incentives) - s.Require().NoError(err) - // planDenom := k.MustGetPlan(s.Ctx, planId).TotalAllocation.Denom - - // Settle without any tokens sold - s.Ctx = s.Ctx.WithBlockTime(endTime.Add(time.Minute)) - s.FundModuleAcc(types.ModuleName, sdk.NewCoins(sdk.NewCoin(rollappDenom, amt))) - err = k.Settle(s.Ctx, rollappId, rollappDenom) - s.Require().NoError(err) - - /* -------------------------- assert liquidity pool ------------------------- */ - // pool created - expectedPoolID := uint64(1) - pool, err := s.App.GAMMKeeper.GetPool(s.Ctx, expectedPoolID) - s.Require().NoError(err) - poolCoins := pool.GetTotalPoolLiquidity(s.Ctx) - poolCoins.AmountOf("adym").Equal(s.App.IROKeeper.GetParams(s.Ctx).CreationFee) - - // incentives expected to have zero coins - gauges, err := s.App.IncentivesKeeper.GetGaugesForDenom(s.Ctx, gammtypes.GetPoolShareDenom(expectedPoolID)) - s.Require().NoError(err) - found := false - gauge := incentivestypes.Gauge{} - for _, gauge = range gauges { - if !gauge.IsPerpetual { - found = true - break - } - } - s.Require().True(found) - s.Require().True(gauge.Coins.IsZero()) -} - -func (s *KeeperTestSuite) TestSettleAllSold() { - rollappId := s.CreateDefaultRollapp() - k := s.App.IROKeeper - // setting curve with fixed price curve := types.BondingCurve{ M: math.LegacyMustNewDecFromStr("0"), N: math.LegacyMustNewDecFromStr("1"), - C: math.LegacyMustNewDecFromStr("0.00001"), + C: math.LegacyMustNewDecFromStr("0.1"), // each token costs 0.1 DYM } - incentives := types.DefaultIncentivePlanParams() startTime := time.Now() - endTime := startTime.Add(time.Hour) - amt := sdk.NewInt(1_000_000).MulRaw(1e18) - rollappDenom := "rollapp_denom" - - rollapp := s.App.RollappKeeper.MustGetRollapp(s.Ctx, rollappId) - planId, err := k.CreatePlan(s.Ctx, amt, startTime, endTime, rollapp, curve, incentives) - s.Require().NoError(err) - - // Buy all possible tokens - s.Ctx = s.Ctx.WithBlockTime(startTime.Add(time.Minute)) - buyer := sample.Acc() - buyAmt := amt.ToLegacyDec().Mul(keeper.AllocationSellLimit).TruncateInt() - s.BuySomeTokens(planId, buyer, buyAmt) - - // Settle - s.Ctx = s.Ctx.WithBlockTime(endTime.Add(time.Minute)) - s.FundModuleAcc(types.ModuleName, sdk.NewCoins(sdk.NewCoin(rollappDenom, amt))) - err = k.Settle(s.Ctx, rollappId, rollappDenom) - s.Require().NoError(err) - - plan := k.MustGetPlan(s.Ctx, planId) + allocation := sdk.NewInt(1_000_000).MulRaw(1e18) + rollappDenom := "dasdasdasdasdsa" - pool, err := s.App.GAMMKeeper.GetPool(s.Ctx, 1) - s.Require().NoError(err) + testCases := []struct { + name string + buyAmt math.Int + expectedDYM math.Int + expectedTokens math.Int + }{ + // for small purchases, the raised dym is the limiting factor: + // - the expected DYM in the pool is the buy amount * 0.1 (fixed price) + 10 DYM creation fee + // for large purchases, the left tokens are the limiting factor: + // - the expected DYM in the pool is the left tokens / 0.1 (fixed price) + { + name: "Small purchase", + buyAmt: math.NewInt(1_000).MulRaw(1e18), + expectedDYM: math.NewInt(110).MulRaw(1e18), + expectedTokens: math.NewInt(1_100).MulRaw(1e18), + }, + { + name: "Large purchase - left tokens are limiting factor", + buyAmt: math.NewInt(800_000).MulRaw(1e18), + expectedDYM: math.NewInt(20_000).MulRaw(1e18), + expectedTokens: math.NewInt(200_000).MulRaw(1e18), + }, + { + name: "Nothing sold - pool contains only creation fee", + buyAmt: math.NewInt(0), + expectedDYM: math.NewInt(10).MulRaw(1e18), // creation fee + expectedTokens: math.NewInt(100).MulRaw(1e18), + }, + { + name: "All sold - pool contains only reserved tokens", + buyAmt: math.NewInt(999_999).MulRaw(1e18), + expectedDYM: math.NewInt(1).MulRaw(1e17), // 0.1 DYM + expectedTokens: math.NewInt(1).MulRaw(1e18), // reserved tokens + }, + } - gauges, err := s.App.IncentivesKeeper.GetGaugesForDenom(s.Ctx, gammtypes.GetPoolShareDenom(1)) - s.Require().NoError(err) - found := false - gauge := incentivestypes.Gauge{} - for _, gauge = range gauges { - if !gauge.IsPerpetual { - found = true - break - } + for _, tc := range testCases { + s.Run(tc.name, func() { + s.SetupTest() // Reset the test state for each test case + rollappId := s.CreateDefaultRollapp() + rollapp := s.App.RollappKeeper.MustGetRollapp(s.Ctx, rollappId) + k := s.App.IROKeeper + + // Create IRO plan + apptesting.FundAccount(s.App, s.Ctx, sdk.MustAccAddressFromBech32(rollapp.Owner), sdk.NewCoins(sdk.NewCoin(appparams.BaseDenom, k.GetParams(s.Ctx).CreationFee))) + planId, err := k.CreatePlan(s.Ctx, allocation, startTime, startTime.Add(time.Hour), rollapp, curve, types.DefaultIncentivePlanParams()) + s.Require().NoError(err) + reservedTokens := k.MustGetPlan(s.Ctx, planId).SoldAmt + + // Buy tokens + if tc.buyAmt.GT(math.ZeroInt()) { + s.Ctx = s.Ctx.WithBlockTime(startTime.Add(time.Minute)) + buyer := sample.Acc() + s.BuySomeTokens(planId, buyer, tc.buyAmt) + } + + plan := k.MustGetPlan(s.Ctx, planId) + raisedDYM := k.BK.GetBalance(s.Ctx, plan.GetAddress(), appparams.BaseDenom) + unallocatedTokensAmt := allocation.Sub(plan.SoldAmt).Add(reservedTokens) + + // Settle + s.FundModuleAcc(types.ModuleName, sdk.NewCoins(sdk.NewCoin(rollappDenom, allocation))) + err = k.Settle(s.Ctx, rollappId, rollappDenom) + s.Require().NoError(err) + + // Assert liquidity pool + poolId := uint64(1) + pool, err := s.App.GAMMKeeper.GetPool(s.Ctx, poolId) + s.Require().NoError(err) + + poolCoins := pool.GetTotalPoolLiquidity(s.Ctx) + s.Require().Equal(tc.expectedDYM, poolCoins.AmountOf("adym")) + s.Require().Equal(tc.expectedTokens, poolCoins.AmountOf(rollappDenom)) + + // Assert pool price + lastIROPrice := plan.SpotPrice() + price, err := pool.SpotPrice(s.Ctx, "adym", rollappDenom) + s.Require().NoError(err) + s.Require().Equal(lastIROPrice, price) + + // Assert incentives + gauges, err := s.App.IncentivesKeeper.GetGaugesForDenom(s.Ctx, gammtypes.GetPoolShareDenom(poolId)) + s.Require().NoError(err) + found := false + var gauge incentivestypes.Gauge + for _, g := range gauges { + if !g.IsPerpetual { + found = true + gauge = g + break + } + } + s.Require().True(found) + + // expected tokens for incentives: + // raisedDYM - poolCoins + // unallocatedTokens - poolCoins + expectedIncentives := sdk.NewCoins(raisedDYM, sdk.NewCoin(rollappDenom, unallocatedTokensAmt)).Sub(poolCoins...) + s.Assert().Equal(expectedIncentives, gauge.Coins) + }) } - s.Require().True(found) - - // only few RA tokens left, so the pool should be quite small - // most of the dym should be as incentive - s.T().Log("Pool coins", pool.GetTotalPoolLiquidity(s.Ctx)) - s.T().Log("Gauge coins", gauge.Coins) - s.Require().True(pool.GetTotalPoolLiquidity(s.Ctx).AmountOf("adym").LT(gauge.Coins.AmountOf("adym"))) - s.Require().Equal(pool.GetTotalPoolLiquidity(s.Ctx).AmountOf(plan.SettledDenom), amt.Sub(buyAmt)) } diff --git a/x/iro/keeper/trade.go b/x/iro/keeper/trade.go index 49163f533..03be14053 100644 --- a/x/iro/keeper/trade.go +++ b/x/iro/keeper/trade.go @@ -14,8 +14,6 @@ import ( "github.com/dymensionxyz/dymension/v3/x/iro/types" ) -var AllocationSellLimit = math.LegacyNewDecWithPrec(999, 3) // 99.9% - // Buy implements types.MsgServer. func (m msgServer) Buy(ctx context.Context, req *types.MsgBuy) (*types.MsgBuyResponse, error) { buyer, err := sdk.AccAddressFromBech32(req.Buyer) @@ -68,9 +66,7 @@ func (k Keeper) Buy(ctx sdk.Context, planId string, buyer sdk.AccAddress, amount } // validate the IRO have enough tokens to sell - // protocol will apply max limit (99.9%) to enforce initial token liquidity - maxSellAmt := plan.TotalAllocation.Amount.ToLegacyDec().Mul(AllocationSellLimit).TruncateInt() - if plan.SoldAmt.Add(amountTokensToBuy).GT(maxSellAmt) { + if plan.SoldAmt.Add(amountTokensToBuy).GT(plan.TotalAllocation.Amount) { return types.ErrInsufficientTokens } @@ -140,7 +136,10 @@ func (k Keeper) BuyExactSpend(ctx sdk.Context, planId string, buyer sdk.AccAddre } // calculate the amount of tokens possible to buy with the amount to spend - tokensOutAmt := plan.BondingCurve.TokensForExactDYM(plan.SoldAmt, toSpendMinusTakerFeeAmt) + tokensOutAmt, err := plan.BondingCurve.TokensForExactDYM(plan.SoldAmt, toSpendMinusTakerFeeAmt) + if err != nil { + return err + } // Validate expected out amount if tokensOutAmt.LT(minTokensAmt) { @@ -148,9 +147,7 @@ func (k Keeper) BuyExactSpend(ctx sdk.Context, planId string, buyer sdk.AccAddre } // validate the IRO have enough tokens to sell - // protocol will apply max limit (99.9%) to enforce initial token liquidity - maxSellAmt := plan.TotalAllocation.Amount.ToLegacyDec().Mul(AllocationSellLimit).TruncateInt() - if plan.SoldAmt.Add(tokensOutAmt).GT(maxSellAmt) { + if plan.SoldAmt.Add(tokensOutAmt).GT(plan.TotalAllocation.Amount) { return types.ErrInsufficientTokens } diff --git a/x/iro/keeper/trade_test.go b/x/iro/keeper/trade_test.go index 7d0b0fd5f..eb62d5723 100644 --- a/x/iro/keeper/trade_test.go +++ b/x/iro/keeper/trade_test.go @@ -1,7 +1,6 @@ package keeper_test import ( - "fmt" "time" "cosmossdk.io/math" @@ -10,7 +9,6 @@ import ( "github.com/osmosis-labs/osmosis/v15/x/txfees" "github.com/dymensionxyz/dymension/v3/testutil/sample" - "github.com/dymensionxyz/dymension/v3/x/iro/keeper" "github.com/dymensionxyz/dymension/v3/x/iro/types" ) @@ -27,6 +25,10 @@ func (s *KeeperTestSuite) TestBuy() { rollapp, _ := s.App.RollappKeeper.GetRollapp(s.Ctx, rollappId) planId, err := k.CreatePlan(s.Ctx, totalAllocation, startTime, startTime.Add(time.Hour), rollapp, curve, incentives) s.Require().NoError(err) + + plan := k.MustGetPlan(s.Ctx, planId) + reservedTokens := plan.SoldAmt + s.Assert().True(reservedTokens.GT(sdk.ZeroInt())) s.Ctx = s.Ctx.WithBlockTime(startTime.Add(time.Minute)) buyer := sample.Acc() @@ -34,13 +36,13 @@ func (s *KeeperTestSuite) TestBuy() { s.FundAcc(buyer, buyersFunds) buyAmt := sdk.NewInt(1_000).MulRaw(1e18) + expectedCost := curve.Cost(plan.SoldAmt, plan.SoldAmt.Add(buyAmt)) // buy before plan start - should fail err = k.Buy(s.Ctx.WithBlockTime(startTime.Add(-time.Minute)), planId, buyer, buyAmt, maxAmt) s.Require().Error(err) // cost is higher than maxCost specified - should fail - expectedCost := curve.Cost(math.ZeroInt(), buyAmt) err = k.Buy(s.Ctx, planId, buyer, buyAmt, expectedCost.SubRaw(1)) s.Require().Error(err) @@ -53,8 +55,8 @@ func (s *KeeperTestSuite) TestBuy() { s.Require().Error(err) // assert nothing sold - plan, _ := k.GetPlan(s.Ctx, planId) - s.Assert().Equal(sdk.NewInt(0), plan.SoldAmt) + plan = k.MustGetPlan(s.Ctx, planId) + s.Assert().Equal(reservedTokens, plan.SoldAmt) // nothing sold, still reserved amount buyerBalance := s.App.BankKeeper.GetAllBalances(s.Ctx, buyer).AmountOf("adym") s.Assert().Equal(buyersFunds.AmountOf("adym"), buyerBalance) @@ -62,7 +64,7 @@ func (s *KeeperTestSuite) TestBuy() { err = k.Buy(s.Ctx, planId, buyer, buyAmt, maxAmt) s.Require().NoError(err) plan, _ = k.GetPlan(s.Ctx, planId) - s.Assert().True(plan.SoldAmt.Equal(buyAmt)) + s.Assert().True(plan.SoldAmt.Sub(reservedTokens).Equal(buyAmt)) // check cost again - should be higher expectedCost2 := curve.Cost(plan.SoldAmt, plan.SoldAmt.Add(buyAmt)) @@ -70,48 +72,11 @@ func (s *KeeperTestSuite) TestBuy() { s.Assert().True(expectedCost2.GT(expectedCost)) // assert balance - balances := s.App.BankKeeper.GetAllBalances(s.Ctx, buyer) + buyerFinalBalance := s.App.BankKeeper.GetAllBalances(s.Ctx, buyer) takerFee := s.App.BankKeeper.GetAllBalances(s.Ctx, authtypes.NewModuleAddress(txfees.ModuleName)) expectedBalance := buyersFunds.AmountOf("adym").Sub(expectedCost).Sub(takerFee.AmountOf("adym")) - s.Require().Equal(expectedBalance, balances.AmountOf("adym")) - - expectedBaseDenom := fmt.Sprintf("%s_%s", types.IROTokenPrefix, rollappId) - s.Require().Equal(buyAmt, balances.AmountOf(expectedBaseDenom)) -} - -func (s *KeeperTestSuite) TestBuyAllocationLimit() { - rollappId := s.CreateDefaultRollapp() - k := s.App.IROKeeper - // setting "cheap" curve to make calculations easier when buying alot of tokens - curve := types.BondingCurve{ - M: math.LegacyMustNewDecFromStr("0"), - N: math.LegacyMustNewDecFromStr("1"), - C: math.LegacyMustNewDecFromStr("0.000001"), - } - incentives := types.DefaultIncentivePlanParams() - - startTime := time.Now() - maxAmt := sdk.NewInt(1_000_000_000).MulRaw(1e18) - totalAllocation := sdk.NewInt(1_000_000).MulRaw(1e18) - - rollapp, _ := s.App.RollappKeeper.GetRollapp(s.Ctx, rollappId) - planId, err := k.CreatePlan(s.Ctx, totalAllocation, startTime, startTime.Add(time.Hour), rollapp, curve, incentives) - s.Require().NoError(err) - - buyer := sample.Acc() - s.FundAcc(buyer, sdk.NewCoins(sdk.NewCoin("adym", maxAmt))) - - // plan start - s.Ctx = s.Ctx.WithBlockTime(startTime.Add(time.Minute)) - - // buy more than total allocation limit - should fail - err = k.Buy(s.Ctx, planId, buyer, totalAllocation, maxAmt) - s.Require().Error(err) - - // buy less than total allocation limit - should pass - maxSellAmt := totalAllocation.ToLegacyDec().Mul(keeper.AllocationSellLimit).TruncateInt() - err = k.Buy(s.Ctx, planId, buyer, maxSellAmt, maxAmt) - s.Require().NoError(err) + s.Require().Equal(expectedBalance, buyerFinalBalance.AmountOf("adym")) + s.Require().Equal(buyAmt, buyerFinalBalance.AmountOf(plan.GetIRODenom())) } func (s *KeeperTestSuite) TestTradeAfterSettled() { @@ -223,8 +188,7 @@ func (s *KeeperTestSuite) TestSell() { // Check balances after sell balances := s.App.BankKeeper.GetAllBalances(s.Ctx, buyer) - expectedBaseDenom := fmt.Sprintf("%s_%s", types.IROTokenPrefix, rollappId) - s.Require().Equal(buyAmt.Sub(sellAmt), balances.AmountOf(expectedBaseDenom)) + s.Require().Equal(buyAmt.Sub(sellAmt), balances.AmountOf(k.MustGetPlan(s.Ctx, planId).GetIRODenom())) // Attempt to sell more than owned - should fail err = k.Sell(s.Ctx, planId, buyer, buyAmt, minReceive) diff --git a/x/iro/types/bonding_curve.go b/x/iro/types/bonding_curve.go index 69138dadf..663fa6ae3 100644 --- a/x/iro/types/bonding_curve.go +++ b/x/iro/types/bonding_curve.go @@ -1,6 +1,8 @@ package types import ( + "fmt" + errorsmod "cosmossdk.io/errors" "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" @@ -114,19 +116,35 @@ func (lbc BondingCurve) Cost(x, x1 math.Int) math.Int { // Calculate the number of tokens that can be bought with a given amount of DYM // As the integral of the bonding curve function is not invertible, we use the Newton-Raphson method to approximate the solution -// In case the solution does not converge, the function returns 0 // - currX: the current supply, in the base denomination // - spendAmt: the amount of DYM to spend, in adym // - returns: the number of tokens that can be bought with spendAmt, in the base denomination -func (lbc BondingCurve) TokensForExactDYM(currX, spendAmt math.Int) math.Int { +func (lbc BondingCurve) TokensForExactDYM(currX, spendAmt math.Int) (math.Int, error) { startingX := ScaleFromBase(currX, lbc.SupplyDecimals()) spendTokens := ScaleFromBase(spendAmt, DYMDecimals) // If the current supply is less than 1, return 0 if startingX.LT(math.LegacyOneDec()) { - return math.ZeroInt() + return math.ZeroInt(), fmt.Errorf("current supply is less than 1") + } + + // If the spend amount is not positive, return 0 + if !spendAmt.IsPositive() { + return math.ZeroInt(), fmt.Errorf("spend amount is not positive") + } + + tokens, _, err := lbc.TokensApproximation(startingX, spendTokens) + if err != nil { + return math.ZeroInt(), err } + return ScaleToBase(tokens, DYMDecimals), nil +} + +/* --------------------------- internal functions --------------------------- */ +// Calculate the number of tokens that can be bought with a given amount of DYM +// inputs validated and scaled by caller +func (lbc BondingCurve) TokensApproximation(startingX, spendTokens math.LegacyDec) (math.LegacyDec, int, error) { // Define the function we're trying to solve: f(x) = Integral(startingX + x) - Integral(startingX) - spendAmt f := func(x math.LegacyDec) math.LegacyDec { newX := startingX.Add(x) @@ -139,11 +157,9 @@ func (lbc BondingCurve) TokensForExactDYM(currX, spendAmt math.Int) math.Int { return lbc.spotPriceInternal(newX) } - // Initial guess using current spot price, assuming linear curve - x := startingX.Add(spendTokens).QuoInt64(2) - if x.LT(math.LegacyOneDec()) { - x = math.LegacyOneDec() - } + // Initial guess for the solution to the bonding curve equation + // assuming 1 DYM = 1 token for the initial guess + x := spendTokens // Newton-Raphson iteration epsilonDec := math.LegacyNewDecWithPrec(1, epsilonPrecision) @@ -151,18 +167,21 @@ func (lbc BondingCurve) TokensForExactDYM(currX, spendAmt math.Int) math.Int { fx := f(x) // If the function converges, return the result if fx.Abs().LT(epsilonDec) { - return ScaleToBase(x, DYMDecimals) + return x, i, nil } prevX := x fPrimex := fPrime(x) + + // defensive check to avoid division by zero + // not supposed to happen, as spotPriceInternal should never return 0 if fPrimex.IsZero() { - return math.ZeroInt() + return math.LegacyDec{}, i, fmt.Errorf("division by zero") } x = x.Sub(fx.Quo(fPrimex)) // If the change in x is less than epsilon * x, return the result if x.Sub(prevX).Abs().LT(epsilonDec.Mul(x.Abs())) { - return ScaleToBase(x, DYMDecimals) + return x, i, nil } // we can't allow newX to be less than 1 @@ -170,7 +189,7 @@ func (lbc BondingCurve) TokensForExactDYM(currX, spendAmt math.Int) math.Int { x = math.LegacyOneDec() } } - return math.ZeroInt() + return math.LegacyDec{}, maxIterations, fmt.Errorf("solution did not converge") } // SpotPrice returns the spot price at x @@ -257,8 +276,8 @@ func ScaleFromBase(x math.Int, precision int64) math.LegacyDec { } // Scales x from the decimal scale to it's base denomination (e.g 1.5 to 1500000000000000) -func ScaleToBase(x math.LegacyDec, precision int) math.Int { - scaleFactor := math.NewIntWithDecimal(1, precision) +func ScaleToBase(x math.LegacyDec, precision int64) math.Int { + scaleFactor := math.NewIntWithDecimal(1, int(precision)) return x.MulInt(scaleFactor).TruncateInt() } diff --git a/x/iro/types/bonding_curve_test.go b/x/iro/types/bonding_curve_test.go index c760882b2..58bbbc6fe 100644 --- a/x/iro/types/bonding_curve_test.go +++ b/x/iro/types/bonding_curve_test.go @@ -2,11 +2,13 @@ package types_test import ( fmt "fmt" + "sort" "testing" "cosmossdk.io/math" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "pgregory.net/rapid" "github.com/dymensionxyz/dymension/v3/x/iro/types" ) @@ -197,7 +199,7 @@ func TestBondingCurve_SmallX(t *testing.T) { // The goal is to ensure that both functions are inverses of each other. func TestTokensForDYM(t *testing.T) { // Define multiple starting points (used as current sold amt) - startingPoints := []string{"0", "0.5", "1", "100", "1000", "10000", "100000"} + startingPoints := []string{"1", "100", "1000", "10000", "100000"} // Define multiple X token amounts to test (used as tokens to buy) xTokens := []string{"0.01", "0.1", "0.5", "1", "10", "1000", "10000", "100000", "1000000"} @@ -227,17 +229,12 @@ func TestTokensForDYM(t *testing.T) { for _, xToken := range xTokens { x := math.LegacyMustNewDecFromStr(xToken).MulInt64(1e18).TruncateInt() - expectedTokens := x - cost := curve.curve.Cost(startingX, startingX.Add(x)) - if startingX.LT(math.NewInt(1e18)) { - expectedTokens = math.ZeroInt() - } - - tokens := curve.curve.TokensForExactDYM(startingX, cost) t.Run(fmt.Sprintf("Start=%s, X=%s", start, xToken), func(t *testing.T) { - approxEqualInt(t, expectedTokens, tokens) + tokens, err := curve.curve.TokensForExactDYM(startingX, cost) + require.NoError(t, err) + approxEqualInt(t, x, tokens) }) } } @@ -245,6 +242,71 @@ func TestTokensForDYM(t *testing.T) { } } +// benchmark the iteration count for the TokensForDYM function +func TestTokensForDYMApproximation(t *testing.T) { + // _ = flag.Set("rapid.checks", "10000") // can be enabled manually for more thorough testing + + // Define different curve types + curves := []struct { + name string + curve types.BondingCurve + }{ + {"Linear", types.DefaultBondingCurve()}, + {"Square Root", types.NewBondingCurve( + math.LegacyMustNewDecFromStr("2.24345436"), + math.LegacyMustNewDecFromStr("0.5"), + math.LegacyMustNewDecFromStr("10.5443534"), + )}, + {"Quadratic", types.NewBondingCurve( + math.LegacyMustNewDecFromStr("2"), + math.LegacyMustNewDecFromStr("1.5"), + math.LegacyZeroDec(), + )}, + } + + for _, curve := range curves { + var iterations []int + + t.Run(curve.name, func(t *testing.T) { + rapid.Check(t, func(t *rapid.T) { + startingXRapid := rapid.Int64Range(1, 1e6).Draw(t, "startingX") + xRapid := rapid.Float64Range(0.01, 1e6).Draw(t, "x") + + startingX := math.LegacyNewDec(startingXRapid).MulInt64(1e18).TruncateInt() + x := math.LegacyMustNewDecFromStr(fmt.Sprintf("%f", xRapid)).MulInt64(1e18).TruncateInt() + + cost := curve.curve.Cost(startingX, startingX.Add(x)) + + startingXScaled := types.ScaleFromBase(startingX, curve.curve.SupplyDecimals()) + spendTokensScaled := types.ScaleFromBase(cost, types.DYMDecimals) + _, iteration, err := curve.curve.TokensApproximation(startingXScaled, spendTokensScaled) + require.NoError(t, err) + + if err != nil { + t.Fatalf("Error in TokensApproximation: %v", err) + } + + t.Logf("Start=%d, X=%f, Iteration=%d", startingX, x, iteration) + iterations = append(iterations, iteration) + }) + }) + + // After all checks are done + sort.Ints(iterations) + min, max := iterations[0], iterations[len(iterations)-1] + sum := 0 + for _, v := range iterations { + sum += v + } + avg := float64(sum) / float64(len(iterations)) + + t.Logf("Statistics for %s curve:", curve.name) + t.Logf(" Min iterations: %d", min) + t.Logf(" Max iterations: %d", max) + t.Logf(" Average iterations: %.2f", avg) + } +} + /* Real world scenario: - A project wants to raise 100_000 DYM for 1_000_000 RA tokens diff --git a/x/iro/types/params.go b/x/iro/types/params.go index 0a0fb0dd9..6a244b1d3 100644 --- a/x/iro/types/params.go +++ b/x/iro/types/params.go @@ -17,6 +17,10 @@ var ( DefaultIncentivePlanMinimumStartTimeAfterSettlement = 60 * time.Minute // default: min 1 hour after settlement ) +const ( + TokenCreationFee = 1 // 1 IRO token is reserved from the allocation as a creation fee +) + // NewParams creates a new Params object func NewParams(takerFee math.LegacyDec, creationFee math.Int, minPlanDuration time.Duration, minIncentivePlanParams IncentivePlanParams) Params { return Params{ diff --git a/x/iro/types/plan.go b/x/iro/types/plan.go index f01d9c792..7dfed17d3 100644 --- a/x/iro/types/plan.go +++ b/x/iro/types/plan.go @@ -78,6 +78,11 @@ func (p Plan) GetAddress() sdk.AccAddress { return addr } +// get IRO token's denom +func (p Plan) GetIRODenom() string { + return fmt.Sprintf("%s_%s", IROTokenPrefix, p.RollappId) +} + func DefaultIncentivePlanParams() IncentivePlanParams { return IncentivePlanParams{ NumEpochsPaidOver: 43200, // 1 month in minute epoch diff --git a/x/iro/types/query.pb.go b/x/iro/types/query.pb.go index 2b6332638..197927284 100644 --- a/x/iro/types/query.pb.go +++ b/x/iro/types/query.pb.go @@ -561,6 +561,97 @@ func (m *QueryCostResponse) GetCost() *types.Coin { return nil } +// QueryTokensForDYMRequest is the request type for the Query/QueryTokensForDYM RPC method. +type QueryTokensForDYMRequest struct { + PlanId string `protobuf:"bytes,1,opt,name=plan_id,json=planId,proto3" json:"plan_id,omitempty"` + Amt github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,2,opt,name=amt,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"amt"` +} + +func (m *QueryTokensForDYMRequest) Reset() { *m = QueryTokensForDYMRequest{} } +func (m *QueryTokensForDYMRequest) String() string { return proto.CompactTextString(m) } +func (*QueryTokensForDYMRequest) ProtoMessage() {} +func (*QueryTokensForDYMRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_ae2c72bd0c23c1c0, []int{12} +} +func (m *QueryTokensForDYMRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryTokensForDYMRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryTokensForDYMRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryTokensForDYMRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryTokensForDYMRequest.Merge(m, src) +} +func (m *QueryTokensForDYMRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryTokensForDYMRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryTokensForDYMRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryTokensForDYMRequest proto.InternalMessageInfo + +func (m *QueryTokensForDYMRequest) GetPlanId() string { + if m != nil { + return m.PlanId + } + return "" +} + +// QueryTokensForDYMResponse is the response type for the Query/QueryTokensForDYM RPC method. +type QueryTokensForDYMResponse struct { + Tokens *types.Coin `protobuf:"bytes,1,opt,name=tokens,proto3" json:"tokens,omitempty"` +} + +func (m *QueryTokensForDYMResponse) Reset() { *m = QueryTokensForDYMResponse{} } +func (m *QueryTokensForDYMResponse) String() string { return proto.CompactTextString(m) } +func (*QueryTokensForDYMResponse) ProtoMessage() {} +func (*QueryTokensForDYMResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_ae2c72bd0c23c1c0, []int{13} +} +func (m *QueryTokensForDYMResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryTokensForDYMResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryTokensForDYMResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryTokensForDYMResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryTokensForDYMResponse.Merge(m, src) +} +func (m *QueryTokensForDYMResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryTokensForDYMResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryTokensForDYMResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryTokensForDYMResponse proto.InternalMessageInfo + +func (m *QueryTokensForDYMResponse) GetTokens() *types.Coin { + if m != nil { + return m.Tokens + } + return nil +} + // QueryClaimedRequest is the request type for the Query/QueryClaimed RPC // method. type QueryClaimedRequest struct { @@ -571,7 +662,7 @@ func (m *QueryClaimedRequest) Reset() { *m = QueryClaimedRequest{} } func (m *QueryClaimedRequest) String() string { return proto.CompactTextString(m) } func (*QueryClaimedRequest) ProtoMessage() {} func (*QueryClaimedRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_ae2c72bd0c23c1c0, []int{12} + return fileDescriptor_ae2c72bd0c23c1c0, []int{14} } func (m *QueryClaimedRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -617,7 +708,7 @@ func (m *QueryClaimedResponse) Reset() { *m = QueryClaimedResponse{} } func (m *QueryClaimedResponse) String() string { return proto.CompactTextString(m) } func (*QueryClaimedResponse) ProtoMessage() {} func (*QueryClaimedResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_ae2c72bd0c23c1c0, []int{13} + return fileDescriptor_ae2c72bd0c23c1c0, []int{15} } func (m *QueryClaimedResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -659,6 +750,8 @@ func init() { proto.RegisterType((*QuerySpotPriceResponse)(nil), "dymensionxyz.dymension.iro.QuerySpotPriceResponse") proto.RegisterType((*QueryCostRequest)(nil), "dymensionxyz.dymension.iro.QueryCostRequest") proto.RegisterType((*QueryCostResponse)(nil), "dymensionxyz.dymension.iro.QueryCostResponse") + proto.RegisterType((*QueryTokensForDYMRequest)(nil), "dymensionxyz.dymension.iro.QueryTokensForDYMRequest") + proto.RegisterType((*QueryTokensForDYMResponse)(nil), "dymensionxyz.dymension.iro.QueryTokensForDYMResponse") proto.RegisterType((*QueryClaimedRequest)(nil), "dymensionxyz.dymension.iro.QueryClaimedRequest") proto.RegisterType((*QueryClaimedResponse)(nil), "dymensionxyz.dymension.iro.QueryClaimedResponse") } @@ -668,57 +761,62 @@ func init() { } var fileDescriptor_ae2c72bd0c23c1c0 = []byte{ - // 789 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x96, 0xcf, 0x4f, 0x13, 0x5b, - 0x14, 0xc7, 0x3b, 0x50, 0xfa, 0x5e, 0x0f, 0x2f, 0x2f, 0xef, 0x5d, 0x50, 0xcb, 0x44, 0x4b, 0x1d, - 0x09, 0x41, 0xa0, 0xf7, 0x42, 0x11, 0x13, 0x7f, 0x2c, 0xa0, 0xb0, 0xa9, 0x6e, 0x70, 0x5c, 0x98, - 0xb8, 0xb0, 0x99, 0x4e, 0x27, 0x75, 0xe2, 0x74, 0xee, 0x30, 0x33, 0x10, 0x2a, 0x61, 0xa1, 0x7f, - 0x81, 0x89, 0xd1, 0x85, 0xd1, 0xbd, 0x0b, 0xff, 0x0e, 0xc3, 0x92, 0xc4, 0x8d, 0x71, 0x41, 0x0c, - 0xf8, 0x87, 0x98, 0xfb, 0xa3, 0xd3, 0x29, 0x4a, 0x67, 0x1a, 0x57, 0xf4, 0x9e, 0x7b, 0xbe, 0xe7, - 0x7c, 0xee, 0x9d, 0x7b, 0xbe, 0x01, 0x66, 0x9b, 0x9d, 0xb6, 0xe5, 0x06, 0x36, 0x75, 0xf7, 0x3a, - 0xcf, 0x49, 0xb4, 0x20, 0xb6, 0x4f, 0xc9, 0xf6, 0x8e, 0xe5, 0x77, 0xb0, 0xe7, 0xd3, 0x90, 0x22, - 0x35, 0x9e, 0x87, 0xa3, 0x05, 0xb6, 0x7d, 0xaa, 0x4e, 0xb6, 0x68, 0x8b, 0xf2, 0x34, 0xc2, 0x7e, - 0x09, 0x85, 0x3a, 0x65, 0xd2, 0xa0, 0x4d, 0x83, 0xba, 0xd8, 0x10, 0x0b, 0xb9, 0x75, 0xb9, 0x45, - 0x69, 0xcb, 0xb1, 0x88, 0xe1, 0xd9, 0xc4, 0x70, 0x5d, 0x1a, 0x1a, 0xa1, 0x4d, 0xdd, 0xee, 0xee, - 0xcc, 0x00, 0x24, 0xdb, 0xef, 0x96, 0x2f, 0x8a, 0x8a, 0xa4, 0x61, 0x04, 0x16, 0xd9, 0x5d, 0x6e, - 0x58, 0xa1, 0xb1, 0x4c, 0x4c, 0x6a, 0xbb, 0x62, 0x5f, 0x9b, 0x04, 0xf4, 0x80, 0xf1, 0x6f, 0x19, - 0xbe, 0xd1, 0x0e, 0x74, 0x6b, 0x7b, 0xc7, 0x0a, 0x42, 0xed, 0x11, 0x4c, 0xf4, 0x45, 0x03, 0x8f, - 0xba, 0x81, 0x85, 0xd6, 0x20, 0xe7, 0xf1, 0x48, 0x41, 0x29, 0x29, 0x73, 0xe3, 0x15, 0x0d, 0x9f, - 0x7f, 0x5c, 0x2c, 0xb4, 0xd5, 0xec, 0xe1, 0xf1, 0x74, 0x46, 0x97, 0x3a, 0x6d, 0x02, 0xfe, 0x17, - 0x85, 0x1d, 0xc3, 0x8d, 0xba, 0xe9, 0x5d, 0x06, 0x11, 0x94, 0xcd, 0xee, 0xc2, 0x98, 0xc7, 0x02, - 0x05, 0xa5, 0x34, 0x3a, 0x37, 0x5e, 0x29, 0x0d, 0xec, 0xe5, 0x18, 0xae, 0xec, 0x24, 0x44, 0xda, - 0x02, 0xfc, 0x17, 0xd5, 0x94, 0x7d, 0xd0, 0x25, 0xf8, 0x8b, 0x6d, 0xd6, 0xed, 0x26, 0xe7, 0xcf, - 0xeb, 0x39, 0xb6, 0xac, 0x35, 0xb5, 0x5a, 0x8c, 0x2a, 0xea, 0x7f, 0x03, 0xb2, 0x6c, 0x5b, 0x1e, - 0x35, 0xb1, 0xbd, 0xce, 0xb3, 0xb5, 0xdb, 0x30, 0x15, 0x95, 0xaa, 0x76, 0x74, 0xea, 0x38, 0x86, - 0xe7, 0x75, 0x01, 0xae, 0x00, 0xf8, 0x22, 0xd2, 0x63, 0xc8, 0xcb, 0x48, 0xad, 0xa9, 0xe9, 0xa0, - 0xfe, 0x4e, 0xfb, 0x47, 0x3c, 0x4b, 0x70, 0x81, 0xd7, 0x7c, 0xe8, 0xd1, 0x70, 0xcb, 0xb7, 0x4d, - 0x2b, 0xf1, 0x32, 0x9e, 0xc0, 0xc5, 0xb3, 0x0a, 0x49, 0xb0, 0x09, 0x63, 0x1e, 0x0b, 0x08, 0x41, - 0x15, 0xb3, 0xfb, 0xfe, 0x76, 0x3c, 0x3d, 0xdb, 0xb2, 0xc3, 0xa7, 0x3b, 0x0d, 0x6c, 0xd2, 0xb6, - 0x7c, 0xbf, 0xf2, 0x4f, 0x39, 0x68, 0x3e, 0x23, 0x61, 0xc7, 0xb3, 0x02, 0xbc, 0x69, 0x99, 0xba, - 0x10, 0x6b, 0x2f, 0x14, 0xf9, 0x69, 0x36, 0x68, 0x10, 0x26, 0xd1, 0xa0, 0x35, 0x18, 0x35, 0xda, - 0x61, 0x61, 0x64, 0xe8, 0x8e, 0x35, 0x37, 0xd4, 0x99, 0x14, 0x21, 0xc8, 0x06, 0x96, 0xe3, 0x14, - 0x46, 0x4b, 0xca, 0xdc, 0xdf, 0x3a, 0xff, 0xad, 0x55, 0xe5, 0x07, 0x17, 0x08, 0xf2, 0x78, 0x65, - 0xc8, 0x9a, 0x34, 0x08, 0xe5, 0x05, 0x4f, 0x61, 0x39, 0x8b, 0x6c, 0x72, 0xb0, 0x9c, 0x1c, 0xbc, - 0x41, 0x6d, 0x57, 0xe7, 0x69, 0x1a, 0x96, 0x33, 0xb2, 0xe1, 0x18, 0x76, 0xdb, 0x6a, 0x26, 0xde, - 0xab, 0x09, 0x93, 0xfd, 0xf9, 0xb2, 0xed, 0x7d, 0x18, 0x37, 0x45, 0xa8, 0xce, 0x4e, 0x2a, 0xee, - 0x76, 0x7e, 0x88, 0x53, 0x82, 0x94, 0xaf, 0xb7, 0xc3, 0xca, 0xbb, 0x3c, 0x8c, 0xf1, 0x2e, 0xe8, - 0x8d, 0x02, 0x39, 0x31, 0x82, 0x08, 0x0f, 0x7a, 0x2b, 0xbf, 0x4e, 0xbf, 0x4a, 0x52, 0xe7, 0x8b, - 0x23, 0x68, 0xf3, 0x2f, 0xbf, 0xfc, 0x78, 0x3d, 0x32, 0x83, 0x34, 0x32, 0xc0, 0x93, 0x84, 0x03, - 0xa0, 0xb7, 0x0a, 0x40, 0x6f, 0xda, 0x51, 0x39, 0xb9, 0x57, 0xcc, 0x2a, 0x54, 0x9c, 0x36, 0x5d, - 0x92, 0x5d, 0xe7, 0x64, 0xd7, 0xd0, 0xd5, 0x81, 0x64, 0x9c, 0xe4, 0x83, 0x02, 0xf9, 0xa8, 0x02, - 0x5a, 0x4c, 0xd5, 0xa8, 0x8b, 0x55, 0x4e, 0x99, 0x2d, 0xa9, 0x56, 0x38, 0x55, 0x19, 0x2d, 0x24, - 0x52, 0x91, 0x7d, 0xf9, 0x98, 0x0e, 0xd0, 0x67, 0x25, 0x66, 0x93, 0x91, 0x3d, 0xa0, 0xd5, 0x54, - 0xad, 0xcf, 0x5a, 0x91, 0x7a, 0x73, 0x58, 0x99, 0x44, 0x5f, 0xe7, 0xe8, 0x77, 0xd0, 0xad, 0x44, - 0xf4, 0x7a, 0xa3, 0x53, 0x97, 0xde, 0x46, 0xf6, 0x7b, 0xb6, 0x77, 0x80, 0x3e, 0x29, 0xf0, 0x6f, - 0xbf, 0xc3, 0xa0, 0xe5, 0x44, 0x9a, 0xb3, 0xfe, 0xa5, 0x56, 0x86, 0x91, 0x0c, 0x75, 0xef, 0x4c, - 0x12, 0xbb, 0xf7, 0xf7, 0xdd, 0x77, 0xc1, 0xcc, 0x22, 0xc5, 0xbb, 0x88, 0xd9, 0x5a, 0x8a, 0x77, - 0x11, 0x77, 0x20, 0xad, 0xc2, 0xf9, 0x16, 0xd1, 0xfc, 0x20, 0x3e, 0x66, 0x3e, 0x31, 0xbc, 0x8f, - 0x0a, 0xfc, 0x13, 0xf7, 0x15, 0x94, 0x3c, 0xbd, 0xfd, 0x8e, 0xa5, 0x2e, 0xa5, 0x17, 0x48, 0xce, - 0x55, 0xce, 0x49, 0x50, 0x79, 0x20, 0xa7, 0x10, 0xf5, 0x50, 0xab, 0xf7, 0x0e, 0x4f, 0x8a, 0xca, - 0xd1, 0x49, 0x51, 0xf9, 0x7e, 0x52, 0x54, 0x5e, 0x9d, 0x16, 0x33, 0x47, 0xa7, 0xc5, 0xcc, 0xd7, - 0xd3, 0x62, 0xe6, 0xf1, 0x52, 0xcc, 0xea, 0xce, 0x29, 0xb9, 0xbb, 0x42, 0xf6, 0x78, 0x5d, 0x6e, - 0x7c, 0x8d, 0x1c, 0xff, 0xf7, 0x65, 0xe5, 0x67, 0x00, 0x00, 0x00, 0xff, 0xff, 0x48, 0x72, 0xb6, - 0x2d, 0x99, 0x09, 0x00, 0x00, + // 868 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x96, 0xcf, 0x4f, 0xe3, 0x46, + 0x14, 0xc7, 0x63, 0x08, 0x69, 0x79, 0x54, 0x55, 0x3b, 0xd0, 0x36, 0x58, 0x6d, 0x48, 0xa7, 0x08, + 0x51, 0x20, 0x1e, 0x12, 0x7e, 0x48, 0x6d, 0x39, 0x40, 0x40, 0x95, 0xd2, 0xaa, 0x15, 0x75, 0x2b, + 0x55, 0xed, 0xa1, 0x91, 0xe3, 0xb8, 0xa9, 0x85, 0xed, 0x31, 0xb6, 0x83, 0x48, 0x11, 0x87, 0xf6, + 0x2f, 0xa8, 0x54, 0xed, 0x9e, 0x76, 0xef, 0x7b, 0xd8, 0xbf, 0x61, 0x8f, 0x2b, 0x8e, 0x48, 0x7b, + 0x59, 0xed, 0x4a, 0x68, 0x05, 0xfb, 0x87, 0xac, 0x3c, 0x33, 0x71, 0x1c, 0x16, 0x6c, 0x47, 0xab, + 0x3d, 0x11, 0xbf, 0x79, 0xdf, 0xf7, 0x3e, 0x6f, 0xfc, 0xfc, 0x15, 0xb0, 0xd0, 0xee, 0xd9, 0x86, + 0xe3, 0x9b, 0xd4, 0x39, 0xee, 0xfd, 0x4d, 0xa2, 0x07, 0x62, 0x7a, 0x94, 0x1c, 0x76, 0x0d, 0xaf, + 0xa7, 0xb8, 0x1e, 0x0d, 0x28, 0x92, 0xe3, 0x79, 0x4a, 0xf4, 0xa0, 0x98, 0x1e, 0x95, 0x67, 0x3a, + 0xb4, 0x43, 0x59, 0x1a, 0x09, 0x7f, 0x71, 0x85, 0x3c, 0xab, 0x53, 0xdf, 0xa6, 0x7e, 0x93, 0x1f, + 0xf0, 0x07, 0x71, 0xf4, 0x69, 0x87, 0xd2, 0x8e, 0x65, 0x10, 0xcd, 0x35, 0x89, 0xe6, 0x38, 0x34, + 0xd0, 0x02, 0x93, 0x3a, 0xfd, 0xd3, 0xf9, 0x04, 0x24, 0xd3, 0xeb, 0x97, 0x2f, 0xf1, 0x8a, 0xa4, + 0xa5, 0xf9, 0x06, 0x39, 0xaa, 0xb6, 0x8c, 0x40, 0xab, 0x12, 0x9d, 0x9a, 0x0e, 0x3f, 0xc7, 0x33, + 0x80, 0x7e, 0x0a, 0xf9, 0xf7, 0x35, 0x4f, 0xb3, 0x7d, 0xd5, 0x38, 0xec, 0x1a, 0x7e, 0x80, 0x7f, + 0x85, 0xe9, 0xa1, 0xa8, 0xef, 0x52, 0xc7, 0x37, 0xd0, 0x36, 0x14, 0x5c, 0x16, 0x29, 0x4a, 0x65, + 0x69, 0x71, 0xaa, 0x86, 0x95, 0xdb, 0xc7, 0x55, 0xb8, 0xb6, 0x9e, 0x3f, 0xbb, 0x98, 0xcb, 0xa9, + 0x42, 0x87, 0xa7, 0xe1, 0x43, 0x5e, 0xd8, 0xd2, 0x9c, 0xa8, 0x9b, 0xda, 0x67, 0xe0, 0x41, 0xd1, + 0x6c, 0x0b, 0x26, 0xdc, 0x30, 0x50, 0x94, 0xca, 0xe3, 0x8b, 0x53, 0xb5, 0x72, 0x62, 0x2f, 0x4b, + 0x73, 0x44, 0x27, 0x2e, 0xc2, 0xcb, 0xf0, 0x41, 0x54, 0x53, 0xf4, 0x41, 0x9f, 0xc0, 0x3b, 0xe1, + 0x61, 0xd3, 0x6c, 0x33, 0xfe, 0x49, 0xb5, 0x10, 0x3e, 0x36, 0xda, 0xb8, 0x11, 0xa3, 0x8a, 0xfa, + 0xaf, 0x43, 0x3e, 0x3c, 0x16, 0xa3, 0xa6, 0xb6, 0x57, 0x59, 0x36, 0xfe, 0x1a, 0x66, 0xa3, 0x52, + 0xf5, 0x9e, 0x4a, 0x2d, 0x4b, 0x73, 0xdd, 0x3e, 0xc0, 0x67, 0x00, 0x1e, 0x8f, 0x0c, 0x18, 0x26, + 0x45, 0xa4, 0xd1, 0xc6, 0x2a, 0xc8, 0x37, 0x69, 0xdf, 0x88, 0x67, 0x15, 0x3e, 0x62, 0x35, 0x7f, + 0x76, 0x69, 0xb0, 0xef, 0x99, 0xba, 0x91, 0x7a, 0x19, 0x7f, 0xc0, 0xc7, 0xd7, 0x15, 0x82, 0x60, + 0x0f, 0x26, 0xdc, 0x30, 0xc0, 0x05, 0x75, 0x25, 0xbc, 0xef, 0x67, 0x17, 0x73, 0x0b, 0x1d, 0x33, + 0xf8, 0xab, 0xdb, 0x52, 0x74, 0x6a, 0x8b, 0xfd, 0x15, 0x7f, 0x2a, 0x7e, 0xfb, 0x80, 0x04, 0x3d, + 0xd7, 0xf0, 0x95, 0x3d, 0x43, 0x57, 0xb9, 0x18, 0xff, 0x23, 0x89, 0x57, 0xb3, 0x4b, 0xfd, 0x20, + 0x8d, 0x06, 0x6d, 0xc3, 0xb8, 0x66, 0x07, 0xc5, 0xb1, 0x91, 0x3b, 0x36, 0x9c, 0x40, 0x0d, 0xa5, + 0x08, 0x41, 0xde, 0x37, 0x2c, 0xab, 0x38, 0x5e, 0x96, 0x16, 0xdf, 0x55, 0xd9, 0x6f, 0x5c, 0x17, + 0x2f, 0x9c, 0x23, 0x88, 0xf1, 0x2a, 0x90, 0xd7, 0xa9, 0x1f, 0x88, 0x0b, 0x9e, 0x55, 0xc4, 0xb7, + 0x18, 0x7e, 0x39, 0x8a, 0xf8, 0x72, 0x94, 0x5d, 0x6a, 0x3a, 0x2a, 0x4b, 0xc3, 0x5d, 0x28, 0xb2, + 0x1a, 0xbf, 0xd0, 0x03, 0xc3, 0xf1, 0xbf, 0xa5, 0xde, 0xde, 0x6f, 0x3f, 0xbc, 0xfd, 0x71, 0xf0, + 0x8f, 0x62, 0xc1, 0x86, 0xdb, 0x8a, 0x11, 0xaa, 0x50, 0x08, 0x58, 0x3c, 0x7d, 0x08, 0x91, 0x88, + 0x15, 0xf1, 0xa9, 0xef, 0x5a, 0x9a, 0x69, 0x1b, 0xed, 0xd4, 0xf5, 0xd0, 0x61, 0x66, 0x38, 0x5f, + 0xb4, 0xfe, 0x1e, 0xa6, 0x74, 0x1e, 0x6a, 0x86, 0x13, 0xf2, 0x15, 0x59, 0x1a, 0x61, 0x3a, 0x10, + 0xf2, 0x1d, 0x3b, 0xa8, 0x3d, 0x07, 0x98, 0x60, 0x5d, 0xd0, 0x1d, 0x09, 0x0a, 0xdc, 0x49, 0x90, + 0x92, 0xb4, 0xf2, 0xaf, 0x9b, 0x98, 0x4c, 0x32, 0xe7, 0xf3, 0x11, 0xf0, 0xd2, 0xbf, 0x4f, 0x5e, + 0xfe, 0x3f, 0x36, 0x8f, 0x30, 0x49, 0xb0, 0x56, 0x6e, 0x64, 0xe8, 0xae, 0x04, 0x30, 0x30, 0x2d, + 0x54, 0x49, 0xef, 0x15, 0x73, 0x3c, 0x59, 0xc9, 0x9a, 0x2e, 0xc8, 0xbe, 0x64, 0x64, 0x5f, 0xa0, + 0xcf, 0x13, 0xc9, 0x18, 0xc9, 0x7d, 0x09, 0x26, 0xa3, 0x0a, 0x68, 0x25, 0x53, 0xa3, 0x3e, 0x56, + 0x25, 0x63, 0xb6, 0xa0, 0x5a, 0x63, 0x54, 0x15, 0xb4, 0x9c, 0x4a, 0x45, 0x4e, 0xc4, 0x32, 0x9d, + 0xa2, 0xc7, 0x52, 0xcc, 0xed, 0x23, 0x97, 0x43, 0x1b, 0x99, 0x5a, 0x5f, 0x77, 0x54, 0x79, 0x73, + 0x54, 0x99, 0x40, 0xdf, 0x61, 0xe8, 0xdf, 0xa0, 0xaf, 0x52, 0xd1, 0x9b, 0xad, 0x5e, 0x53, 0x58, + 0x34, 0x39, 0x19, 0xb8, 0xf7, 0x29, 0x7a, 0x28, 0xc1, 0xfb, 0xc3, 0x46, 0x89, 0xaa, 0xa9, 0x34, + 0xd7, 0x6d, 0x58, 0xae, 0x8d, 0x22, 0x19, 0xe9, 0xde, 0x43, 0x49, 0xec, 0xde, 0xef, 0xf5, 0xf7, + 0x22, 0xf4, 0xbc, 0x0c, 0x7b, 0x11, 0x73, 0xe7, 0x0c, 0x7b, 0x11, 0x37, 0x52, 0x5c, 0x63, 0x7c, + 0x2b, 0x68, 0x29, 0x89, 0x2f, 0xf4, 0xd0, 0x18, 0xde, 0x23, 0x49, 0x58, 0x72, 0xdc, 0xd7, 0xd0, + 0x7a, 0x6a, 0xe3, 0x1b, 0xdc, 0x57, 0xde, 0x18, 0x51, 0x25, 0xb0, 0xb7, 0x18, 0xf6, 0x26, 0x5a, + 0x4f, 0xc2, 0xe6, 0xae, 0xd9, 0xfc, 0x93, 0x7a, 0xcd, 0x76, 0xcf, 0x8e, 0x0d, 0xf0, 0x40, 0x82, + 0xf7, 0xe2, 0xc6, 0x88, 0xd2, 0xed, 0x67, 0xd8, 0x72, 0xe5, 0xd5, 0xec, 0x02, 0x41, 0xbc, 0xc1, + 0x88, 0x09, 0xaa, 0x24, 0x5e, 0x34, 0x17, 0x0d, 0x50, 0xeb, 0xdf, 0x9d, 0x5d, 0x96, 0xa4, 0xf3, + 0xcb, 0x92, 0xf4, 0xe2, 0xb2, 0x24, 0xfd, 0x77, 0x55, 0xca, 0x9d, 0x5f, 0x95, 0x72, 0x4f, 0xaf, + 0x4a, 0xb9, 0xdf, 0x57, 0x63, 0x5e, 0x7d, 0x4b, 0xc9, 0xa3, 0x35, 0x72, 0xcc, 0x6f, 0x22, 0x74, + 0xee, 0x56, 0x81, 0xfd, 0x1b, 0xb9, 0xf6, 0x2a, 0x00, 0x00, 0xff, 0xff, 0x70, 0x2d, 0x66, 0x42, + 0x21, 0x0b, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -746,6 +844,7 @@ type QueryClient interface { QuerySpotPrice(ctx context.Context, in *QuerySpotPriceRequest, opts ...grpc.CallOption) (*QuerySpotPriceResponse, error) // QueryCost retrieves the expected cost for buying or selling the specified amount of shares. QueryCost(ctx context.Context, in *QueryCostRequest, opts ...grpc.CallOption) (*QueryCostResponse, error) + QueryTokensForDYM(ctx context.Context, in *QueryTokensForDYMRequest, opts ...grpc.CallOption) (*QueryTokensForDYMResponse, error) // QueryClaimed retrieves the claimed amount thus far for the specified plan ID. QueryClaimed(ctx context.Context, in *QueryClaimedRequest, opts ...grpc.CallOption) (*QueryClaimedResponse, error) } @@ -812,6 +911,15 @@ func (c *queryClient) QueryCost(ctx context.Context, in *QueryCostRequest, opts return out, nil } +func (c *queryClient) QueryTokensForDYM(ctx context.Context, in *QueryTokensForDYMRequest, opts ...grpc.CallOption) (*QueryTokensForDYMResponse, error) { + out := new(QueryTokensForDYMResponse) + err := c.cc.Invoke(ctx, "/dymensionxyz.dymension.iro.Query/QueryTokensForDYM", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *queryClient) QueryClaimed(ctx context.Context, in *QueryClaimedRequest, opts ...grpc.CallOption) (*QueryClaimedResponse, error) { out := new(QueryClaimedResponse) err := c.cc.Invoke(ctx, "/dymensionxyz.dymension.iro.Query/QueryClaimed", in, out, opts...) @@ -836,6 +944,7 @@ type QueryServer interface { QuerySpotPrice(context.Context, *QuerySpotPriceRequest) (*QuerySpotPriceResponse, error) // QueryCost retrieves the expected cost for buying or selling the specified amount of shares. QueryCost(context.Context, *QueryCostRequest) (*QueryCostResponse, error) + QueryTokensForDYM(context.Context, *QueryTokensForDYMRequest) (*QueryTokensForDYMResponse, error) // QueryClaimed retrieves the claimed amount thus far for the specified plan ID. QueryClaimed(context.Context, *QueryClaimedRequest) (*QueryClaimedResponse, error) } @@ -862,6 +971,9 @@ func (*UnimplementedQueryServer) QuerySpotPrice(ctx context.Context, req *QueryS func (*UnimplementedQueryServer) QueryCost(ctx context.Context, req *QueryCostRequest) (*QueryCostResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method QueryCost not implemented") } +func (*UnimplementedQueryServer) QueryTokensForDYM(ctx context.Context, req *QueryTokensForDYMRequest) (*QueryTokensForDYMResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method QueryTokensForDYM not implemented") +} func (*UnimplementedQueryServer) QueryClaimed(ctx context.Context, req *QueryClaimedRequest) (*QueryClaimedResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method QueryClaimed not implemented") } @@ -978,6 +1090,24 @@ func _Query_QueryCost_Handler(srv interface{}, ctx context.Context, dec func(int return interceptor(ctx, in, info, handler) } +func _Query_QueryTokensForDYM_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryTokensForDYMRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).QueryTokensForDYM(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/dymensionxyz.dymension.iro.Query/QueryTokensForDYM", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).QueryTokensForDYM(ctx, req.(*QueryTokensForDYMRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _Query_QueryClaimed_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(QueryClaimedRequest) if err := dec(in); err != nil { @@ -1024,6 +1154,10 @@ var _Query_serviceDesc = grpc.ServiceDesc{ MethodName: "QueryCost", Handler: _Query_QueryCost_Handler, }, + { + MethodName: "QueryTokensForDYM", + Handler: _Query_QueryTokensForDYM_Handler, + }, { MethodName: "QueryClaimed", Handler: _Query_QueryClaimed_Handler, @@ -1427,6 +1561,81 @@ func (m *QueryCostResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *QueryTokensForDYMRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryTokensForDYMRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryTokensForDYMRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size := m.Amt.Size() + i -= size + if _, err := m.Amt.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.PlanId) > 0 { + i -= len(m.PlanId) + copy(dAtA[i:], m.PlanId) + i = encodeVarintQuery(dAtA, i, uint64(len(m.PlanId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryTokensForDYMResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryTokensForDYMResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryTokensForDYMResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Tokens != nil { + { + size, err := m.Tokens.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func (m *QueryClaimedRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -1654,6 +1863,34 @@ func (m *QueryCostResponse) Size() (n int) { return n } +func (m *QueryTokensForDYMRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.PlanId) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = m.Amt.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func (m *QueryTokensForDYMResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Tokens != nil { + l = m.Tokens.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + func (m *QueryClaimedRequest) Size() (n int) { if m == nil { return 0 @@ -2677,6 +2914,208 @@ func (m *QueryCostResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *QueryTokensForDYMRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryTokensForDYMRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryTokensForDYMRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PlanId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.PlanId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Amt", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Amt.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryTokensForDYMResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryTokensForDYMResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryTokensForDYMResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Tokens", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Tokens == nil { + m.Tokens = &types.Coin{} + } + if err := m.Tokens.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *QueryClaimedRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/x/iro/types/query.pb.gw.go b/x/iro/types/query.pb.gw.go index 1dc8e3bd1..d5cf5438d 100644 --- a/x/iro/types/query.pb.gw.go +++ b/x/iro/types/query.pb.gw.go @@ -303,6 +303,78 @@ func local_request_Query_QueryCost_0(ctx context.Context, marshaler runtime.Mars } +var ( + filter_Query_QueryTokensForDYM_0 = &utilities.DoubleArray{Encoding: map[string]int{"plan_id": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} +) + +func request_Query_QueryTokensForDYM_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryTokensForDYMRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["plan_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "plan_id") + } + + protoReq.PlanId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "plan_id", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_QueryTokensForDYM_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.QueryTokensForDYM(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_QueryTokensForDYM_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryTokensForDYMRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["plan_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "plan_id") + } + + protoReq.PlanId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "plan_id", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_QueryTokensForDYM_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.QueryTokensForDYM(ctx, &protoReq) + return msg, metadata, err + +} + func request_Query_QueryClaimed_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryClaimedRequest var metadata runtime.ServerMetadata @@ -501,6 +573,29 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv }) + mux.Handle("GET", pattern_Query_QueryTokensForDYM_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_QueryTokensForDYM_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_QueryTokensForDYM_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("GET", pattern_Query_QueryClaimed_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -685,6 +780,26 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) + mux.Handle("GET", pattern_Query_QueryTokensForDYM_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_QueryTokensForDYM_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_QueryTokensForDYM_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("GET", pattern_Query_QueryClaimed_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -721,6 +836,8 @@ var ( pattern_Query_QueryCost_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"dymensionxyz", "dymension", "iro", "cost", "plan_id"}, "", runtime.AssumeColonVerbOpt(false))) + pattern_Query_QueryTokensForDYM_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"dymensionxyz", "dymension", "iro", "tokens_for_dym", "plan_id"}, "", runtime.AssumeColonVerbOpt(false))) + pattern_Query_QueryClaimed_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"dymensionxyz", "dymension", "iro", "claimed", "plan_id"}, "", runtime.AssumeColonVerbOpt(false))) ) @@ -737,5 +854,7 @@ var ( forward_Query_QueryCost_0 = runtime.ForwardResponseMessage + forward_Query_QueryTokensForDYM_0 = runtime.ForwardResponseMessage + forward_Query_QueryClaimed_0 = runtime.ForwardResponseMessage )