From b6460b73d6d93e7fa4e7314fd92660dde8a28843 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Fri, 25 Aug 2023 20:12:31 +0200 Subject: [PATCH 01/16] make market inmutable and include market version --- proto/nibiru/perp/v2/state.proto | 4 + x/perp/v2/integration/action/market.go | 4 +- x/perp/v2/integration/action/query.go | 2 +- x/perp/v2/keeper/admin.go | 9 +- x/perp/v2/keeper/admin_test.go | 5 +- x/perp/v2/keeper/grpc_query_test.go | 2 +- x/perp/v2/types/genesis.go | 4 +- x/perp/v2/types/genesis_test.go | 2 +- x/perp/v2/types/market.go | 48 +++---- x/perp/v2/types/market_test.go | 95 +++++++------- x/perp/v2/types/state.pb.go | 169 +++++++++++++++---------- x/wasm/binding/exec_perp.go | 2 +- 12 files changed, 186 insertions(+), 160 deletions(-) diff --git a/proto/nibiru/perp/v2/state.proto b/proto/nibiru/perp/v2/state.proto index 10f0c6fe5..17694077f 100644 --- a/proto/nibiru/perp/v2/state.proto +++ b/proto/nibiru/perp/v2/state.proto @@ -122,6 +122,10 @@ message AMM { (gogoproto.nullable) = false ]; + // the version of the Market, only one market can exist per pair, when one is closed it cannot be reactivated, + // so a new market must be created, this is the version of the market + uint64 version = 8; + // the amount of base reserves this AMM has string base_reserve = 2 [ (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", diff --git a/x/perp/v2/integration/action/market.go b/x/perp/v2/integration/action/market.go index e20ab8f08..3ff23a229 100644 --- a/x/perp/v2/integration/action/market.go +++ b/x/perp/v2/integration/action/market.go @@ -64,11 +64,11 @@ func CreateCustomMarket(pair asset.Pair, marketModifiers ...marketModifier) acti } for _, modifier := range marketModifiers { - modifier(market, &amm) + modifier(&market, &amm) } return createMarketAction{ - Market: *market, + Market: market, AMM: amm, } } diff --git a/x/perp/v2/integration/action/query.go b/x/perp/v2/integration/action/query.go index 716e0bb95..27e0312b9 100644 --- a/x/perp/v2/integration/action/query.go +++ b/x/perp/v2/integration/action/query.go @@ -175,7 +175,7 @@ type QueryMarketsChecker func(resp []types.AmmMarket) error func QueryMarkets_MarketsShouldContain(expectedMarket types.Market) QueryMarketsChecker { return func(resp []types.AmmMarket) error { for _, market := range resp { - if types.MarketsAreEqual(&expectedMarket, &market.Market) == nil { + if types.MarketsAreEqual(expectedMarket, market.Market) == nil { return nil } } diff --git a/x/perp/v2/keeper/admin.go b/x/perp/v2/keeper/admin.go index 3c628180f..a2c5e649b 100644 --- a/x/perp/v2/keeper/admin.go +++ b/x/perp/v2/keeper/admin.go @@ -71,8 +71,8 @@ func (k admin) CreateMarket( args ArgsCreateMarket, ) error { pair := args.Pair - _, err := k.Markets.Get(ctx, pair) - if err == nil { + market, err := k.Markets.Get(ctx, pair) + if err == nil && market.Enabled { return fmt.Errorf("market %s already exists", pair) } @@ -80,11 +80,10 @@ func (k admin) CreateMarket( sqrtDepth := args.SqrtDepth quoteReserve := sqrtDepth baseReserve := sqrtDepth - var market *types.Market if args.Market == nil { market = types.DefaultMarket(pair) } else { - market = args.Market + market = *args.Market } if err := market.Validate(); err != nil { return err @@ -104,7 +103,7 @@ func (k admin) CreateMarket( return err } - k.Markets.Insert(ctx, pair, *market) + k.Markets.Insert(ctx, pair, market) k.AMMs.Insert(ctx, pair, amm) return nil diff --git a/x/perp/v2/keeper/admin_test.go b/x/perp/v2/keeper/admin_test.go index 88e207c4c..c61755220 100644 --- a/x/perp/v2/keeper/admin_test.go +++ b/x/perp/v2/keeper/admin_test.go @@ -116,11 +116,12 @@ func TestCreateMarketFail(t *testing.T) { app, ctx := testapp.NewNibiruTestAppAndContext(true) // Error because of invalid market + market := types.DefaultMarket(pair).WithMaintenanceMarginRatio(sdk.NewDec(2)) err := app.PerpKeeperV2.Admin().CreateMarket(ctx, keeper.ArgsCreateMarket{ Pair: pair, PriceMultiplier: amm.PriceMultiplier, SqrtDepth: amm.SqrtDepth, - Market: types.DefaultMarket(pair).WithMaintenanceMarginRatio(sdk.NewDec(2)), // Invalid maintenance ratio + Market: &market, // Invalid maintenance ratio }) require.ErrorContains(t, err, "maintenance margin ratio ratio must be 0 <= ratio <= 1") @@ -140,7 +141,7 @@ func TestCreateMarketFail(t *testing.T) { }) require.NoError(t, err) - // Fail since it already exists + // Fail since it already exists and it is not disabled err = app.PerpKeeperV2.Admin().CreateMarket(ctx, keeper.ArgsCreateMarket{ Pair: pair, PriceMultiplier: amm.PriceMultiplier, diff --git a/x/perp/v2/keeper/grpc_query_test.go b/x/perp/v2/keeper/grpc_query_test.go index e425817a6..901c826c7 100644 --- a/x/perp/v2/keeper/grpc_query_test.go +++ b/x/perp/v2/keeper/grpc_query_test.go @@ -346,7 +346,7 @@ func TestQueryMarkets(t *testing.T) { ), ). Then( - QueryMarkets(QueryMarkets_MarketsShouldContain(*types.DefaultMarket(pair))), + QueryMarkets(QueryMarkets_MarketsShouldContain(types.DefaultMarket(pair))), QueryModuleAccounts(QueryModuleAccounts_ModulesBalanceShouldBe( map[string]sdk.Coins{ "perp_ef": sdk.NewCoins( diff --git a/x/perp/v2/types/genesis.go b/x/perp/v2/types/genesis.go index 75dbded29..9ac35539e 100644 --- a/x/perp/v2/types/genesis.go +++ b/x/perp/v2/types/genesis.go @@ -48,8 +48,8 @@ func (gs GenesisState) Validate() error { return nil } -func DefaultMarket(pair asset.Pair) *Market { - return &Market{ +func DefaultMarket(pair asset.Pair) Market { + return Market{ Pair: pair, Enabled: true, LatestCumulativePremiumFraction: sdk.ZeroDec(), diff --git a/x/perp/v2/types/genesis_test.go b/x/perp/v2/types/genesis_test.go index 9ddaa373a..ae765aa84 100644 --- a/x/perp/v2/types/genesis_test.go +++ b/x/perp/v2/types/genesis_test.go @@ -85,7 +85,7 @@ func TestGenesisValidate(t *testing.T) { name: "valid genesis", setupGenesis: func() *types.GenesisState { genesis := types.GenesisState{ - Markets: []types.Market{*validMarket}, + Markets: []types.Market{validMarket}, Amms: []types.AMM{validAmms}, Positions: []types.Position{validPositions}, ReserveSnapshots: []types.ReserveSnapshot{}, diff --git a/x/perp/v2/types/market.go b/x/perp/v2/types/market.go index 8145732db..5c88e5056 100644 --- a/x/perp/v2/types/market.go +++ b/x/perp/v2/types/market.go @@ -13,7 +13,7 @@ func isPercent(v sdk.Dec) bool { return v.GTE(sdk.ZeroDec()) && v.LTE(sdk.OneDec()) } -func (market *Market) Validate() error { +func (market Market) Validate() error { if !isPercent(market.MaintenanceMarginRatio) { return fmt.Errorf("maintenance margin ratio ratio must be 0 <= ratio <= 1") } @@ -49,82 +49,82 @@ func (market *Market) Validate() error { return nil } -func (market *Market) WithMaintenanceMarginRatio(value sdk.Dec) *Market { +func (market Market) WithMaintenanceMarginRatio(value sdk.Dec) Market { market.MaintenanceMarginRatio = value return market } -func (market *Market) WithMaxLeverage(value sdk.Dec) *Market { +func (market Market) WithMaxLeverage(value sdk.Dec) Market { market.MaxLeverage = value return market } -func (market *Market) WithEcosystemFee(value sdk.Dec) *Market { +func (market Market) WithEcosystemFee(value sdk.Dec) Market { market.EcosystemFundFeeRatio = value return market } -func (market *Market) WithExchangeFee(value sdk.Dec) *Market { +func (market Market) WithExchangeFee(value sdk.Dec) Market { market.ExchangeFeeRatio = value return market } -func (market *Market) WithLiquidationFee(value sdk.Dec) *Market { +func (market Market) WithLiquidationFee(value sdk.Dec) Market { market.LiquidationFeeRatio = value return market } -func (market *Market) WithPartialLiquidationRatio(value sdk.Dec) *Market { +func (market Market) WithPartialLiquidationRatio(value sdk.Dec) Market { market.PartialLiquidationRatio = value return market } -func (market *Market) WithFundingRateEpochId(value string) *Market { +func (market Market) WithFundingRateEpochId(value string) Market { market.FundingRateEpochId = value return market } -func (market *Market) WithMaxFundingRate(value sdk.Dec) *Market { +func (market Market) WithMaxFundingRate(value sdk.Dec) Market { market.MaxFundingRate = value return market } -func (market *Market) WithPair(value asset.Pair) *Market { +func (market Market) WithPair(value asset.Pair) Market { market.Pair = value return market } -func (market *Market) WithLatestCumulativePremiumFraction(value sdk.Dec) *Market { +func (market Market) WithLatestCumulativePremiumFraction(value sdk.Dec) Market { market.LatestCumulativePremiumFraction = value return market } -func (market *Market) WithEcosystemFundFeeRatio(value sdk.Dec) *Market { +func (market Market) WithEcosystemFundFeeRatio(value sdk.Dec) Market { market.EcosystemFundFeeRatio = value return market } -func (market *Market) WithExchangeFeeRatio(value sdk.Dec) *Market { +func (market Market) WithExchangeFeeRatio(value sdk.Dec) Market { market.ExchangeFeeRatio = value return market } -func (market *Market) WithLiquidationFeeRatio(value sdk.Dec) *Market { +func (market Market) WithLiquidationFeeRatio(value sdk.Dec) Market { market.LiquidationFeeRatio = value return market } -func (market *Market) WithPrepaidBadDebt(value sdk.Coin) *Market { +func (market Market) WithPrepaidBadDebt(value sdk.Coin) Market { market.PrepaidBadDebt = value return market } -func (market *Market) WithEnabled(value bool) *Market { +func (market Market) WithEnabled(value bool) Market { market.Enabled = value return market } -func (market *Market) WithTwapLookbackWindow(value time.Duration) *Market { +func (market Market) WithTwapLookbackWindow(value time.Duration) Market { market.TwapLookbackWindow = value return market } -func MarketsAreEqual(expected, actual *Market) error { +func MarketsAreEqual(expected, actual Market) error { if expected.Pair != actual.Pair { return fmt.Errorf("expected market pair %s, got %s", expected.Pair, actual.Pair) } @@ -183,15 +183,3 @@ func MarketsAreEqual(expected, actual *Market) error { return nil } - -func (m *Market) copy() *Market { - return &Market{ - MaintenanceMarginRatio: m.MaintenanceMarginRatio, - EcosystemFundFeeRatio: m.EcosystemFundFeeRatio, - ExchangeFeeRatio: m.ExchangeFeeRatio, - LiquidationFeeRatio: m.LiquidationFeeRatio, - PartialLiquidationRatio: m.PartialLiquidationRatio, - MaxLeverage: m.MaxLeverage, - MaxFundingRate: m.MaxFundingRate, - } -} diff --git a/x/perp/v2/types/market_test.go b/x/perp/v2/types/market_test.go index 8f88a5cb9..b9007b7c5 100644 --- a/x/perp/v2/types/market_test.go +++ b/x/perp/v2/types/market_test.go @@ -17,53 +17,52 @@ func TestIsPercent(t *testing.T) { } func TestValidate(t *testing.T) { - market := new(Market) - // Test when all values are within expected ranges - market.WithMaintenanceMarginRatio(sdk.NewDecWithPrec(1, 1)) - market.WithEcosystemFee(sdk.NewDecWithPrec(3, 1)) - market.WithExchangeFee(sdk.NewDecWithPrec(4, 1)) - market.WithLiquidationFee(sdk.NewDecWithPrec(2, 1)) - market.WithPartialLiquidationRatio(sdk.NewDecWithPrec(1, 1)) - market.WithMaxLeverage(sdk.NewDec(10)) - market.WithMaxFundingRate(sdk.NewDec(1)) + market := Market{}. + WithMaintenanceMarginRatio(sdk.NewDecWithPrec(1, 1)). + WithEcosystemFee(sdk.NewDecWithPrec(3, 1)). + WithExchangeFee(sdk.NewDecWithPrec(4, 1)). + WithLiquidationFee(sdk.NewDecWithPrec(2, 1)). + WithPartialLiquidationRatio(sdk.NewDecWithPrec(1, 1)). + WithMaxLeverage(sdk.NewDec(10)). + WithMaxFundingRate(sdk.NewDec(1)) require.NoError(t, market.Validate()) testCases := []struct { - modifier func(*Market) + modifier func(Market) Market requiredError string }{ { - modifier: func(m *Market) { m.WithMaintenanceMarginRatio(sdk.NewDec(-1)) }, + modifier: func(m Market) Market { return m.WithMaintenanceMarginRatio(sdk.NewDec(-1)) }, requiredError: "maintenance margin ratio ratio must be 0 <= ratio <= 1"}, { - modifier: func(m *Market) { m.WithEcosystemFee(sdk.NewDec(2)) }, + modifier: func(m Market) Market { return m.WithEcosystemFee(sdk.NewDec(2)) }, requiredError: "ecosystem fund fee ratio must be 0 <= ratio <= 1"}, { - modifier: func(m *Market) { m.WithExchangeFee(sdk.NewDec(-1)) }, + modifier: func(m Market) Market { return m.WithExchangeFee(sdk.NewDec(-1)) }, requiredError: "exchange fee ratio must be 0 <= ratio <= 1"}, { - modifier: func(m *Market) { m.WithLiquidationFee(sdk.NewDec(2)) }, + modifier: func(m Market) Market { return m.WithLiquidationFee(sdk.NewDec(2)) }, requiredError: "liquidation fee ratio must be 0 <= ratio <= 1"}, { - modifier: func(m *Market) { m.WithPartialLiquidationRatio(sdk.NewDec(-1)) }, + modifier: func(m Market) Market { return m.WithPartialLiquidationRatio(sdk.NewDec(-1)) }, requiredError: "partial liquidation ratio must be 0 <= ratio <= 1"}, { - modifier: func(m *Market) { m.WithMaxLeverage(sdk.ZeroDec()) }, + modifier: func(m Market) Market { return m.WithMaxLeverage(sdk.ZeroDec()) }, requiredError: "max leverage must be > 0"}, { - modifier: func(m *Market) { m.WithMaxFundingRate(sdk.NewDec(-1)) }, + modifier: func(m Market) Market { return m.WithMaxFundingRate(sdk.NewDec(-1)) }, requiredError: "max funding rate must be >= 0"}, { - modifier: func(m *Market) { m.WithMaxLeverage(sdk.NewDec(20)).WithMaintenanceMarginRatio(sdk.NewDec(1)) }, + modifier: func(m Market) Market { + return m.WithMaxLeverage(sdk.NewDec(20)).WithMaintenanceMarginRatio(sdk.NewDec(1)) + }, requiredError: "margin ratio opened with max leverage position will be lower than Maintenance margin ratio"}, } for _, tc := range testCases { tc := tc t.Run(tc.requiredError, func(t *testing.T) { - newMarket := market.copy() - - tc.modifier(newMarket) + newMarket := tc.modifier(market) err := newMarket.Validate() require.Error(t, err) @@ -73,82 +72,80 @@ func TestValidate(t *testing.T) { } func TestMarketEqual(t *testing.T) { - market := new(Market) + market := Market{}. + WithMaintenanceMarginRatio(sdk.NewDecWithPrec(1, 1)). + WithEcosystemFee(sdk.NewDecWithPrec(3, 1)). + WithExchangeFee(sdk.NewDecWithPrec(4, 1)). + WithLiquidationFee(sdk.NewDecWithPrec(2, 1)). + WithPartialLiquidationRatio(sdk.NewDecWithPrec(1, 1)). + WithMaxLeverage(sdk.NewDec(10)). + WithLatestCumulativePremiumFraction(sdk.OneDec()). + WithMaxFundingRate(sdk.OneDec()) // Test when all values are within expected ranges - market.WithMaintenanceMarginRatio(sdk.NewDecWithPrec(1, 1)) - market.WithEcosystemFee(sdk.NewDecWithPrec(3, 1)) - market.WithExchangeFee(sdk.NewDecWithPrec(4, 1)) - market.WithLiquidationFee(sdk.NewDecWithPrec(2, 1)) - market.WithPartialLiquidationRatio(sdk.NewDecWithPrec(1, 1)) - market.WithMaxLeverage(sdk.NewDec(10)) - market.WithLatestCumulativePremiumFraction(sdk.OneDec()) - market.WithMaxFundingRate(sdk.OneDec()) require.NoError(t, market.Validate()) testCases := []struct { - modifier func(*Market) + modifier func(Market) Market requiredError string }{ { - modifier: func(m *Market) { m.WithPair("ueth:unusd") }, + modifier: func(m Market) Market { return m.WithPair("ueth:unusd") }, requiredError: "expected market pair", }, { - modifier: func(m *Market) { m.WithMaintenanceMarginRatio(sdk.NewDec(42)) }, + modifier: func(m Market) Market { return m.WithMaintenanceMarginRatio(sdk.NewDec(42)) }, requiredError: "expected market maintenance margin ratio", }, { - modifier: func(m *Market) { m.WithMaxLeverage(sdk.NewDec(42)) }, + modifier: func(m Market) Market { return m.WithMaxLeverage(sdk.NewDec(42)) }, requiredError: "expected market max leverage", }, { - modifier: func(m *Market) { m.WithPartialLiquidationRatio(sdk.NewDec(42)) }, + modifier: func(m Market) Market { return m.WithPartialLiquidationRatio(sdk.NewDec(42)) }, requiredError: "expected market partial liquidation ratio", }, { - modifier: func(m *Market) { m.WithFundingRateEpochId("hi") }, + modifier: func(m Market) Market { return m.WithFundingRateEpochId("hi") }, requiredError: "expected market funding rate epoch id", }, { - modifier: func(m *Market) { m.WithMaxFundingRate(sdk.NewDec(42)) }, + modifier: func(m Market) Market { return m.WithMaxFundingRate(sdk.NewDec(42)) }, requiredError: "expected market max funding rate", }, { - modifier: func(m *Market) { m.WithLatestCumulativePremiumFraction(sdk.NewDec(42)) }, + modifier: func(m Market) Market { return m.WithLatestCumulativePremiumFraction(sdk.NewDec(42)) }, requiredError: "expected market latest cumulative premium fraction", }, { - modifier: func(m *Market) { m.WithEcosystemFundFeeRatio(sdk.NewDec(42)) }, + modifier: func(m Market) Market { return m.WithEcosystemFundFeeRatio(sdk.NewDec(42)) }, requiredError: "expected market ecosystem fund fee ratio", }, { - modifier: func(m *Market) { m.WithExchangeFeeRatio(sdk.NewDec(42)) }, + modifier: func(m Market) Market { return m.WithExchangeFeeRatio(sdk.NewDec(42)) }, requiredError: "expected market exchange fee ratio", }, { - modifier: func(m *Market) { m.WithLiquidationFeeRatio(sdk.NewDec(42)) }, + modifier: func(m Market) Market { return m.WithLiquidationFeeRatio(sdk.NewDec(42)) }, requiredError: "expected market liquidation fee ratio", }, { - modifier: func(m *Market) { m.WithPrepaidBadDebt(sdk.NewCoin("ubtc", sdk.OneInt())) }, + modifier: func(m Market) Market { return m.WithPrepaidBadDebt(sdk.NewCoin("ubtc", sdk.OneInt())) }, requiredError: "expected market prepaid bad debt", }, { - modifier: func(m *Market) { m.WithEnabled(true) }, + modifier: func(m Market) Market { return m.WithEnabled(true) }, requiredError: "expected market enabled", }, { - modifier: func(m *Market) { m.WithTwapLookbackWindow(time.Minute) }, + modifier: func(m Market) Market { return m.WithTwapLookbackWindow(time.Minute) }, requiredError: "expected market twap lookback window", }, } for _, tc := range testCases { tc := tc t.Run(tc.requiredError, func(t *testing.T) { - newMarket := market.copy() - - tc.modifier(newMarket) + newMarket := tc.modifier(market) err := MarketsAreEqual(market, newMarket) require.Error(t, err) @@ -165,8 +162,8 @@ func TestMarketsAreEqual(t *testing.T) { require.NoError(t, MarketsAreEqual(market1, market2)) // Test when markets are not equal - market2.WithMaintenanceMarginRatio(sdk.NewDecWithPrec(3, 1)) + market2 = market2.WithMaintenanceMarginRatio(sdk.NewDecWithPrec(3, 1)) require.Error(t, MarketsAreEqual(market1, market2)) - require.NoError(t, MarketsAreEqual(market1, market1.copy())) + require.NoError(t, MarketsAreEqual(market1, market1)) } diff --git a/x/perp/v2/types/state.pb.go b/x/perp/v2/types/state.pb.go index 2512958c2..d2a632aeb 100644 --- a/x/perp/v2/types/state.pb.go +++ b/x/perp/v2/types/state.pb.go @@ -200,6 +200,9 @@ func (m *Market) GetPrepaidBadDebt() types.Coin { type AMM struct { // identifies the market this AMM belongs to Pair github_com_NibiruChain_nibiru_x_common_asset.Pair `protobuf:"bytes,1,opt,name=pair,proto3,customtype=github.com/NibiruChain/nibiru/x/common/asset.Pair" json:"pair"` + // the version of the Market, only one market can exist per pair, when one is closed it cannot be reactivated, + // so a new market must be created, this is the version of the market + Version uint64 `protobuf:"varint,8,opt,name=version,proto3" json:"version,omitempty"` // the amount of base reserves this AMM has BaseReserve github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=base_reserve,json=baseReserve,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"base_reserve"` // the amount of quote reserves this AMM has @@ -247,6 +250,13 @@ func (m *AMM) XXX_DiscardUnknown() { var xxx_messageInfo_AMM proto.InternalMessageInfo +func (m *AMM) GetVersion() uint64 { + if m != nil { + return m.Version + } + return 0 +} + type Position struct { // address identifies the address owner of this position TraderAddress string `protobuf:"bytes,1,opt,name=trader_address,json=traderAddress,proto3" json:"trader_address,omitempty"` @@ -378,74 +388,74 @@ func init() { func init() { proto.RegisterFile("nibiru/perp/v2/state.proto", fileDescriptor_8f4829f34f7b8040) } var fileDescriptor_8f4829f34f7b8040 = []byte{ - // 1057 bytes of a gzipped FileDescriptorProto + // 1065 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x96, 0x5d, 0x6f, 0xdb, 0x36, - 0x17, 0xc7, 0xe3, 0xd8, 0x4d, 0x6d, 0xda, 0x4d, 0x0d, 0xb6, 0xe9, 0xa3, 0x04, 0x0f, 0x9c, 0x2c, - 0xc0, 0x86, 0xa0, 0x43, 0x25, 0x24, 0xbb, 0x2a, 0x76, 0xe5, 0xd7, 0xce, 0x80, 0xdf, 0x22, 0x3b, + 0x17, 0xc7, 0xe3, 0xd8, 0x4d, 0x6d, 0x3a, 0x4d, 0x0c, 0x26, 0xe9, 0xa3, 0x04, 0x0f, 0x9c, 0x2c, + 0xc0, 0x86, 0xa0, 0x43, 0x25, 0x24, 0xbb, 0x2a, 0x76, 0xe5, 0xd7, 0xce, 0x80, 0xdf, 0x2a, 0x3b, 0x08, 0x36, 0x14, 0x20, 0x28, 0x89, 0x91, 0xb9, 0x48, 0xa2, 0x42, 0x52, 0x4e, 0xba, 0x7d, 0x89, - 0x5d, 0x6e, 0x5f, 0x68, 0xe8, 0x65, 0x2f, 0x87, 0x5d, 0x74, 0x43, 0xf2, 0x19, 0x76, 0x3f, 0x90, - 0x92, 0x1d, 0x17, 0x18, 0xb0, 0x4d, 0xe8, 0xae, 0x6c, 0xf1, 0xe8, 0xfc, 0xfe, 0xd4, 0xd1, 0x39, - 0x7f, 0x0a, 0xec, 0x45, 0xd4, 0xa1, 0x3c, 0xb1, 0x62, 0xc2, 0x63, 0x6b, 0x71, 0x62, 0x09, 0x89, - 0x25, 0x31, 0x63, 0xce, 0x24, 0x83, 0xdb, 0x69, 0xcc, 0x54, 0x31, 0x73, 0x71, 0xb2, 0xf7, 0xd4, - 0x67, 0x3e, 0xd3, 0x21, 0x4b, 0xfd, 0x4b, 0xef, 0xda, 0x6b, 0xb8, 0x4c, 0x84, 0x4c, 0x58, 0x0e, - 0x16, 0xc4, 0x5a, 0x1c, 0x3b, 0x44, 0xe2, 0x63, 0xcb, 0x65, 0x34, 0xca, 0xe2, 0xbb, 0x69, 0x1c, - 0xa5, 0x89, 0xe9, 0xc5, 0x32, 0xd5, 0x67, 0xcc, 0x0f, 0x88, 0xa5, 0xaf, 0x9c, 0xe4, 0xc2, 0xf2, - 0x12, 0x8e, 0x25, 0x65, 0x59, 0xea, 0xe1, 0x1f, 0x65, 0xb0, 0x35, 0xc4, 0xfc, 0x92, 0x48, 0x38, - 0x04, 0xa5, 0x18, 0x53, 0x6e, 0x14, 0x0e, 0x0a, 0x47, 0x95, 0xd6, 0xcb, 0xb7, 0xef, 0xf7, 0x37, - 0x7e, 0x7d, 0xbf, 0x7f, 0xec, 0x53, 0x39, 0x4f, 0x1c, 0xd3, 0x65, 0xa1, 0x35, 0xd2, 0x9b, 0x6d, - 0xcf, 0x31, 0x8d, 0xac, 0xec, 0xa1, 0x6e, 0x2c, 0x97, 0x85, 0x21, 0x8b, 0x2c, 0x2c, 0x04, 0x91, - 0xe6, 0x04, 0x53, 0x6e, 0x6b, 0x0c, 0x34, 0xc0, 0x43, 0x12, 0x61, 0x27, 0x20, 0x9e, 0xb1, 0x79, - 0x50, 0x38, 0x2a, 0xdb, 0xcb, 0x4b, 0x38, 0x07, 0x46, 0x88, 0x69, 0x24, 0x49, 0x84, 0x23, 0x97, - 0xa0, 0x10, 0x73, 0x9f, 0x46, 0x48, 0x6f, 0xcb, 0x28, 0x6a, 0x71, 0x33, 0x13, 0xff, 0x6c, 0x4d, - 0x3c, 0xab, 0x41, 0xfa, 0xf3, 0x42, 0x78, 0x97, 0x96, 0x7c, 0x13, 0x13, 0x61, 0x76, 0x88, 0x6b, - 0x3f, 0x5b, 0xe3, 0x0d, 0x35, 0xce, 0x56, 0x34, 0x78, 0x0a, 0x6a, 0x21, 0xbe, 0x41, 0x01, 0x59, - 0x10, 0x8e, 0x7d, 0x62, 0x94, 0x72, 0xd1, 0xab, 0x21, 0xbe, 0x19, 0x64, 0x08, 0xf8, 0x3d, 0x38, - 0x0c, 0xb0, 0x24, 0x42, 0x22, 0x37, 0x09, 0x93, 0x00, 0x4b, 0xba, 0x20, 0x28, 0xe6, 0x24, 0xa4, - 0x49, 0x88, 0x2e, 0x38, 0x76, 0x55, 0x71, 0x8d, 0x07, 0xb9, 0x84, 0xf6, 0x53, 0x72, 0x7b, 0x05, - 0x9e, 0xa4, 0xdc, 0x5e, 0x86, 0x85, 0xaf, 0x01, 0x24, 0x37, 0xee, 0x1c, 0x47, 0x3e, 0x41, 0x17, - 0x84, 0x64, 0x35, 0xdb, 0xca, 0x25, 0x56, 0x5f, 0x92, 0x7a, 0x84, 0xa4, 0xd5, 0xf2, 0x81, 0x41, - 0x5c, 0x26, 0xde, 0x08, 0x49, 0x42, 0x74, 0x91, 0x44, 0xde, 0x9a, 0xc6, 0xc3, 0x5c, 0x1a, 0x3b, - 0x2b, 0x5e, 0x2f, 0x89, 0xbc, 0x95, 0x90, 0x03, 0x76, 0x02, 0x7a, 0x95, 0x50, 0x4f, 0x77, 0xe2, - 0x9a, 0x4a, 0x39, 0x97, 0xca, 0x93, 0x35, 0xd8, 0x4a, 0xe3, 0x5b, 0xb0, 0x1b, 0x63, 0x2e, 0x29, - 0x0e, 0xd0, 0xba, 0x56, 0xaa, 0x53, 0xc9, 0xa5, 0xf3, 0xbf, 0x0c, 0x38, 0xb8, 0xe7, 0xa5, 0x5a, - 0xc7, 0x60, 0x47, 0x95, 0x8b, 0x46, 0xbe, 0xe2, 0x13, 0x44, 0x62, 0xe6, 0xce, 0x11, 0xf5, 0x0c, - 0xa0, 0x74, 0x6c, 0x98, 0x05, 0x6d, 0x2c, 0x49, 0x57, 0x85, 0xfa, 0x1e, 0x3c, 0x03, 0x4f, 0xe5, - 0x35, 0x8e, 0x51, 0xc0, 0xd8, 0xa5, 0x83, 0xdd, 0x4b, 0x74, 0x4d, 0x23, 0x8f, 0x5d, 0x1b, 0xd5, - 0x83, 0xc2, 0x51, 0xf5, 0x64, 0xd7, 0x4c, 0xc7, 0xd6, 0x5c, 0x8e, 0xad, 0xd9, 0xc9, 0xc6, 0xb6, - 0x55, 0x56, 0x9b, 0xfe, 0xf1, 0xb7, 0xfd, 0x82, 0x0d, 0x15, 0x60, 0x90, 0xe5, 0x9f, 0xeb, 0x74, - 0xd8, 0x07, 0xf5, 0x98, 0x93, 0x18, 0x53, 0x0f, 0x39, 0xd8, 0x43, 0x1e, 0x71, 0xa4, 0x51, 0xcb, - 0x90, 0x99, 0x2f, 0x28, 0x13, 0x31, 0x33, 0x13, 0x31, 0xdb, 0x8c, 0x46, 0xad, 0x92, 0x42, 0xda, - 0xdb, 0x59, 0x62, 0x0b, 0x7b, 0x1d, 0xe2, 0x48, 0xf8, 0x1a, 0xd4, 0xd5, 0xec, 0xac, 0x3f, 0x98, - 0xf1, 0x48, 0xd7, 0xed, 0xe4, 0xdf, 0xd5, 0x4d, 0x6f, 0x76, 0x3b, 0xc4, 0x37, 0xbd, 0xfb, 0x32, - 0x1c, 0xfe, 0x5c, 0x02, 0xc5, 0xe6, 0x70, 0xf8, 0xb1, 0x4d, 0xe7, 0x14, 0xd4, 0xd4, 0xf3, 0x21, - 0x4e, 0x04, 0xe1, 0x0b, 0xa2, 0x9d, 0x27, 0xc7, 0xc0, 0x2b, 0x86, 0x9d, 0x22, 0xe0, 0x14, 0x3c, - 0xba, 0x4a, 0x98, 0xbc, 0x67, 0xe6, 0xb3, 0xa8, 0x9a, 0x86, 0x2c, 0xa1, 0x43, 0x00, 0xc4, 0x15, - 0x97, 0xc8, 0x23, 0xb1, 0x9c, 0xe7, 0xb4, 0xa5, 0x8a, 0x22, 0x74, 0x14, 0x00, 0x7e, 0xad, 0x5e, - 0x3b, 0x55, 0x5e, 0x9a, 0x04, 0x92, 0xc6, 0x01, 0x25, 0x3c, 0xa7, 0x05, 0x3d, 0xd6, 0x9c, 0xe1, - 0x0a, 0xa3, 0x76, 0x2a, 0x99, 0x54, 0x53, 0xc4, 0x22, 0x3f, 0xa7, 0xd5, 0x54, 0x34, 0x61, 0xc0, - 0x22, 0x1f, 0x8e, 0x41, 0x35, 0xc5, 0x89, 0x39, 0xe3, 0x32, 0xa7, 0xad, 0xa4, 0x3b, 0x9a, 0x2a, - 0xc2, 0xe1, 0x4f, 0x25, 0x50, 0x9e, 0x30, 0x41, 0xb5, 0x3f, 0x7e, 0x0a, 0xb6, 0x25, 0xc7, 0x1e, - 0xe1, 0x08, 0x7b, 0x1e, 0x27, 0x42, 0xa4, 0x7d, 0x65, 0x3f, 0x4a, 0x57, 0x9b, 0xe9, 0xe2, 0xaa, - 0xe9, 0x36, 0x3f, 0x4e, 0xd3, 0xb5, 0x40, 0x49, 0xd0, 0xef, 0xf2, 0x36, 0x86, 0xce, 0x85, 0x3d, - 0xb0, 0x95, 0x9e, 0x83, 0x39, 0x9b, 0x21, 0xcb, 0x56, 0xdd, 0xca, 0x62, 0x12, 0xa1, 0x88, 0xa9, - 0x82, 0xe0, 0x20, 0x67, 0x1b, 0xd4, 0x14, 0x64, 0x94, 0x31, 0xfe, 0xe1, 0x99, 0xb7, 0xf5, 0xdf, - 0x9c, 0x79, 0x2f, 0xc1, 0x6e, 0x80, 0x85, 0x44, 0x49, 0xec, 0x61, 0x49, 0x3c, 0xe4, 0x04, 0xcc, - 0xbd, 0x44, 0x51, 0x12, 0x3a, 0x84, 0xeb, 0xfe, 0x29, 0xda, 0xcf, 0xd4, 0x0d, 0x67, 0x69, 0xbc, - 0xa5, 0xc2, 0x23, 0x1d, 0x3d, 0xc4, 0xe0, 0x71, 0x36, 0x70, 0xd3, 0x08, 0xc7, 0x62, 0xce, 0x24, - 0xfc, 0x1c, 0x14, 0x71, 0x18, 0xea, 0xb6, 0xa8, 0x9e, 0x3c, 0x31, 0x3f, 0xfc, 0xfc, 0x32, 0x9b, - 0xc3, 0x61, 0xe6, 0x86, 0xea, 0x2e, 0xf8, 0x09, 0xa8, 0x49, 0x1a, 0x12, 0x21, 0x71, 0x18, 0xa3, - 0x50, 0xe8, 0x7e, 0x29, 0xda, 0xd5, 0xd5, 0xda, 0x50, 0x3c, 0xff, 0x12, 0x54, 0x3a, 0x94, 0x93, - 0x74, 0xab, 0xbb, 0x60, 0xa7, 0xd3, 0xb7, 0xbb, 0xed, 0x59, 0x7f, 0x3c, 0x42, 0x67, 0xa3, 0xe9, - 0xa4, 0xdb, 0xee, 0xf7, 0xfa, 0xdd, 0x4e, 0x7d, 0x03, 0x96, 0x41, 0x69, 0x30, 0x1e, 0xbd, 0xaa, - 0x17, 0x60, 0x05, 0x3c, 0x98, 0x7e, 0x35, 0xb6, 0x67, 0xf5, 0xcd, 0xe7, 0x3e, 0xd8, 0x9e, 0x5d, - 0xe3, 0xb8, 0x8d, 0x03, 0x77, 0x1c, 0x6b, 0xc2, 0x01, 0xf8, 0xff, 0xec, 0xbc, 0x39, 0x41, 0xed, - 0xe6, 0xa0, 0x8d, 0xc6, 0x93, 0xbf, 0x06, 0x4d, 0x27, 0xe3, 0x59, 0xbd, 0x00, 0x9f, 0x82, 0xfa, - 0xe9, 0xd9, 0x78, 0xd6, 0x45, 0xcd, 0xe9, 0xb4, 0x3b, 0x43, 0xd3, 0xf3, 0xe6, 0xa4, 0xbe, 0x09, - 0x9f, 0x80, 0xc7, 0xad, 0xe6, 0xf4, 0x83, 0xc5, 0x62, 0xeb, 0xd5, 0xdb, 0xdb, 0x46, 0xe1, 0xdd, - 0x6d, 0xa3, 0xf0, 0xfb, 0x6d, 0xa3, 0xf0, 0xc3, 0x5d, 0x63, 0xe3, 0xdd, 0x5d, 0x63, 0xe3, 0x97, - 0xbb, 0xc6, 0xc6, 0x37, 0x2f, 0xfe, 0xae, 0xe9, 0x97, 0x5f, 0xad, 0xfa, 0x8d, 0x39, 0x5b, 0xfa, - 0x40, 0xfa, 0xe2, 0xcf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf3, 0x85, 0x1a, 0x6c, 0xd4, 0x0a, 0x00, - 0x00, + 0x5d, 0x6e, 0xdf, 0xa8, 0x97, 0xbd, 0x1c, 0x76, 0xd1, 0x15, 0xc9, 0x67, 0xd8, 0xfd, 0x40, 0x4a, + 0x76, 0x5c, 0x60, 0xc0, 0x36, 0x61, 0xbd, 0x4a, 0xc8, 0xa3, 0xf3, 0xfb, 0x53, 0xc7, 0xe7, 0xfc, + 0x29, 0x70, 0x10, 0x51, 0x87, 0xf2, 0xc4, 0x8a, 0x09, 0x8f, 0xad, 0xf9, 0x99, 0x25, 0x24, 0x96, + 0xc4, 0x8c, 0x39, 0x93, 0x0c, 0x6e, 0xa5, 0x31, 0x53, 0xc5, 0xcc, 0xf9, 0xd9, 0xc1, 0xae, 0xcf, + 0x7c, 0xa6, 0x43, 0x96, 0xfa, 0x2f, 0x7d, 0xea, 0xa0, 0xee, 0x32, 0x11, 0x32, 0x61, 0x39, 0x58, + 0x10, 0x6b, 0x7e, 0xea, 0x10, 0x89, 0x4f, 0x2d, 0x97, 0xd1, 0x28, 0x8b, 0xef, 0xa7, 0x71, 0x94, + 0x26, 0xa6, 0x8b, 0x45, 0xaa, 0xcf, 0x98, 0x1f, 0x10, 0x4b, 0xaf, 0x9c, 0xe4, 0xd2, 0xf2, 0x12, + 0x8e, 0x25, 0x65, 0x59, 0xea, 0xf1, 0x1f, 0x65, 0xb0, 0x31, 0xc0, 0xfc, 0x8a, 0x48, 0x38, 0x00, + 0xa5, 0x18, 0x53, 0x6e, 0x14, 0x8e, 0x0a, 0x27, 0x95, 0xe6, 0x8b, 0xb7, 0xef, 0x0f, 0xd7, 0x7e, + 0x7b, 0x7f, 0x78, 0xea, 0x53, 0x39, 0x4b, 0x1c, 0xd3, 0x65, 0xa1, 0x35, 0xd4, 0x87, 0x6d, 0xcd, + 0x30, 0x8d, 0xac, 0xec, 0xa5, 0x6e, 0x2d, 0x97, 0x85, 0x21, 0x8b, 0x2c, 0x2c, 0x04, 0x91, 0xe6, + 0x18, 0x53, 0x6e, 0x6b, 0x0c, 0x34, 0xc0, 0x63, 0x12, 0x61, 0x27, 0x20, 0x9e, 0xb1, 0x7e, 0x54, + 0x38, 0x29, 0xdb, 0x8b, 0x25, 0x9c, 0x01, 0x23, 0xc4, 0x34, 0x92, 0x24, 0xc2, 0x91, 0x4b, 0x50, + 0x88, 0xb9, 0x4f, 0x23, 0xa4, 0x8f, 0x65, 0x14, 0xb5, 0xb8, 0x99, 0x89, 0x7f, 0xb1, 0x22, 0x9e, + 0xd5, 0x20, 0xfd, 0xf3, 0x5c, 0x78, 0x57, 0x96, 0x7c, 0x13, 0x13, 0x61, 0xb6, 0x89, 0x6b, 0x3f, + 0x5d, 0xe1, 0x0d, 0x34, 0xce, 0x56, 0x34, 0xf8, 0x0a, 0x6c, 0x86, 0xf8, 0x16, 0x05, 0x64, 0x4e, + 0x38, 0xf6, 0x89, 0x51, 0xca, 0x45, 0xaf, 0x86, 0xf8, 0xb6, 0x9f, 0x21, 0xe0, 0x8f, 0xe0, 0x38, + 0xc0, 0x92, 0x08, 0x89, 0xdc, 0x24, 0x4c, 0x02, 0x2c, 0xe9, 0x9c, 0xa0, 0x98, 0x93, 0x90, 0x26, + 0x21, 0xba, 0xe4, 0xd8, 0x55, 0xc5, 0x35, 0x1e, 0xe5, 0x12, 0x3a, 0x4c, 0xc9, 0xad, 0x25, 0x78, + 0x9c, 0x72, 0xbb, 0x19, 0x16, 0xbe, 0x06, 0x90, 0xdc, 0xba, 0x33, 0x1c, 0xf9, 0x04, 0x5d, 0x12, + 0x92, 0xd5, 0x6c, 0x23, 0x97, 0x58, 0x6d, 0x41, 0xea, 0x12, 0x92, 0x56, 0xcb, 0x07, 0x06, 0x71, + 0x99, 0x78, 0x23, 0x24, 0x09, 0xd1, 0x65, 0x12, 0x79, 0x2b, 0x1a, 0x8f, 0x73, 0x69, 0xec, 0x2d, + 0x79, 0xdd, 0x24, 0xf2, 0x96, 0x42, 0x0e, 0xd8, 0x0b, 0xe8, 0x75, 0x42, 0x3d, 0xdd, 0x89, 0x2b, + 0x2a, 0xe5, 0x5c, 0x2a, 0x3b, 0x2b, 0xb0, 0xa5, 0xc6, 0xf7, 0x60, 0x3f, 0xc6, 0x5c, 0x52, 0x1c, + 0xa0, 0x55, 0xad, 0x54, 0xa7, 0x92, 0x4b, 0xe7, 0x7f, 0x19, 0xb0, 0xff, 0xc0, 0x4b, 0xb5, 0x4e, + 0xc1, 0x9e, 0x2a, 0x17, 0x8d, 0x7c, 0xc5, 0x27, 0x88, 0xc4, 0xcc, 0x9d, 0x21, 0xea, 0x19, 0x40, + 0xe9, 0xd8, 0x30, 0x0b, 0xda, 0x58, 0x92, 0x8e, 0x0a, 0xf5, 0x3c, 0x78, 0x0e, 0x76, 0xe5, 0x0d, + 0x8e, 0x51, 0xc0, 0xd8, 0x95, 0x83, 0xdd, 0x2b, 0x74, 0x43, 0x23, 0x8f, 0xdd, 0x18, 0xd5, 0xa3, + 0xc2, 0x49, 0xf5, 0x6c, 0xdf, 0x4c, 0xc7, 0xd6, 0x5c, 0x8c, 0xad, 0xd9, 0xce, 0xc6, 0xb6, 0x59, + 0x56, 0x87, 0xfe, 0xf9, 0xf7, 0xc3, 0x82, 0x0d, 0x15, 0xa0, 0x9f, 0xe5, 0x5f, 0xe8, 0x74, 0xd8, + 0x03, 0xb5, 0x98, 0x93, 0x18, 0x53, 0x0f, 0x39, 0xd8, 0x43, 0x1e, 0x71, 0xa4, 0xb1, 0x99, 0x21, + 0x33, 0x5f, 0x50, 0x26, 0x62, 0x66, 0x26, 0x62, 0xb6, 0x18, 0x8d, 0x9a, 0x25, 0x85, 0xb4, 0xb7, + 0xb2, 0xc4, 0x26, 0xf6, 0xda, 0xc4, 0x91, 0xf0, 0x35, 0xa8, 0xa9, 0xd9, 0x59, 0x7d, 0x31, 0xe3, + 0x89, 0xae, 0xdb, 0xd9, 0xbf, 0xab, 0x9b, 0x3e, 0xec, 0x56, 0x88, 0x6f, 0xbb, 0x0f, 0x65, 0x38, + 0xfe, 0x50, 0x02, 0xc5, 0xc6, 0x60, 0xf0, 0x09, 0x4c, 0x67, 0x4e, 0xb8, 0x50, 0x23, 0xa8, 0x7a, + 0xa9, 0x64, 0x2f, 0x96, 0xca, 0x0a, 0xd4, 0x9b, 0x23, 0x4e, 0x04, 0xe1, 0x73, 0xa2, 0x3d, 0x29, + 0x87, 0x15, 0x28, 0x86, 0x9d, 0x22, 0xe0, 0x04, 0x3c, 0xb9, 0x4e, 0x98, 0x7c, 0x60, 0xe6, 0x33, + 0xaf, 0x4d, 0x0d, 0x59, 0x40, 0x07, 0x00, 0x88, 0x6b, 0x2e, 0x91, 0x47, 0x62, 0x39, 0xcb, 0x69, + 0x58, 0x15, 0x45, 0x68, 0x2b, 0x00, 0xfc, 0x56, 0x35, 0x04, 0x55, 0x2e, 0x9b, 0x04, 0x92, 0xc6, + 0x01, 0x25, 0x3c, 0xa7, 0x39, 0x6d, 0x6b, 0xce, 0x60, 0x89, 0x51, 0x27, 0x95, 0x4c, 0xaa, 0xf9, + 0x62, 0x91, 0x9f, 0xd3, 0x84, 0x2a, 0x9a, 0xd0, 0x67, 0x91, 0x0f, 0x47, 0xa0, 0x9a, 0xe2, 0xc4, + 0x8c, 0x71, 0x99, 0xd3, 0x70, 0xd2, 0x13, 0x4d, 0x14, 0xe1, 0xf8, 0x97, 0x12, 0x28, 0x8f, 0x99, + 0xa0, 0xda, 0x39, 0x3f, 0x07, 0x5b, 0x92, 0x63, 0x8f, 0x70, 0x84, 0x3d, 0x8f, 0x13, 0x21, 0xd2, + 0x8e, 0xb3, 0x9f, 0xa4, 0xbb, 0x8d, 0x74, 0x73, 0xd9, 0x8e, 0xeb, 0xff, 0x4d, 0x3b, 0x36, 0x41, + 0x49, 0xd0, 0x1f, 0xf2, 0x36, 0x86, 0xce, 0x85, 0x5d, 0xb0, 0x91, 0xde, 0x90, 0x39, 0x9b, 0x21, + 0xcb, 0x56, 0xdd, 0xca, 0x62, 0x12, 0xa1, 0x88, 0xa9, 0x82, 0xe0, 0x20, 0x67, 0x1b, 0x6c, 0x2a, + 0xc8, 0x30, 0x63, 0xfc, 0xc3, 0xdb, 0x70, 0xe3, 0xd3, 0xdc, 0x86, 0x2f, 0xc0, 0x7e, 0x80, 0x85, + 0x44, 0x49, 0xec, 0x61, 0x49, 0x3c, 0xe4, 0x04, 0xcc, 0xbd, 0x42, 0x51, 0x12, 0x3a, 0x84, 0xeb, + 0xfe, 0x29, 0xda, 0x4f, 0xd5, 0x03, 0xe7, 0x69, 0xbc, 0xa9, 0xc2, 0x43, 0x1d, 0x3d, 0xc6, 0x60, + 0x3b, 0x1b, 0xb8, 0x49, 0x84, 0x63, 0x31, 0x63, 0x12, 0x7e, 0x09, 0x8a, 0x38, 0x0c, 0x75, 0x5b, + 0x54, 0xcf, 0x76, 0xcc, 0x8f, 0x3f, 0xcc, 0xcc, 0xc6, 0x60, 0x90, 0xf9, 0xa4, 0x7a, 0x0a, 0x7e, + 0x06, 0x36, 0x25, 0x0d, 0x89, 0x90, 0x38, 0x8c, 0x51, 0x28, 0x74, 0xbf, 0x14, 0xed, 0xea, 0x72, + 0x6f, 0x20, 0x9e, 0x7d, 0x0d, 0x2a, 0x6d, 0xca, 0x49, 0x7a, 0xd4, 0x7d, 0xb0, 0xd7, 0xee, 0xd9, + 0x9d, 0xd6, 0xb4, 0x37, 0x1a, 0xa2, 0xf3, 0xe1, 0x64, 0xdc, 0x69, 0xf5, 0xba, 0xbd, 0x4e, 0xbb, + 0xb6, 0x06, 0xcb, 0xa0, 0xd4, 0x1f, 0x0d, 0x5f, 0xd6, 0x0a, 0xb0, 0x02, 0x1e, 0x4d, 0xbe, 0x19, + 0xd9, 0xd3, 0xda, 0xfa, 0x33, 0x1f, 0x6c, 0x4d, 0x6f, 0x70, 0xdc, 0xc2, 0x81, 0x3b, 0x8a, 0x35, + 0xe1, 0x08, 0xfc, 0x7f, 0x7a, 0xd1, 0x18, 0xa3, 0x56, 0xa3, 0xdf, 0x42, 0xa3, 0xf1, 0x5f, 0x83, + 0x26, 0xe3, 0xd1, 0xb4, 0x56, 0x80, 0xbb, 0xa0, 0xf6, 0xea, 0x7c, 0x34, 0xed, 0xa0, 0xc6, 0x64, + 0xd2, 0x99, 0xa2, 0xc9, 0x45, 0x63, 0x5c, 0x5b, 0x87, 0x3b, 0x60, 0xbb, 0xd9, 0x98, 0x7c, 0xb4, + 0x59, 0x6c, 0xbe, 0x7c, 0x7b, 0x57, 0x2f, 0xbc, 0xbb, 0xab, 0x17, 0x3e, 0xdc, 0xd5, 0x0b, 0x3f, + 0xdd, 0xd7, 0xd7, 0xde, 0xdd, 0xd7, 0xd7, 0x7e, 0xbd, 0xaf, 0xaf, 0x7d, 0xf7, 0xfc, 0xef, 0x9a, + 0x7e, 0xf1, 0x3d, 0xab, 0x7f, 0x31, 0x67, 0x43, 0x5f, 0x55, 0x5f, 0xfd, 0x19, 0x00, 0x00, 0xff, + 0xff, 0x99, 0xc0, 0xa4, 0x88, 0xee, 0x0a, 0x00, 0x00, } func (m *Market) Marshal() (dAtA []byte, err error) { @@ -616,6 +626,11 @@ func (m *AMM) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.Version != 0 { + i = encodeVarintState(dAtA, i, uint64(m.Version)) + i-- + dAtA[i] = 0x40 + } { size := m.TotalShort.Size() i -= size @@ -881,6 +896,9 @@ func (m *AMM) Size() (n int) { n += 1 + l + sovState(uint64(l)) l = m.TotalShort.Size() n += 1 + l + sovState(uint64(l)) + if m.Version != 0 { + n += 1 + sovState(uint64(m.Version)) + } return n } @@ -1671,6 +1689,25 @@ func (m *AMM) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 8: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType) + } + m.Version = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowState + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Version |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipState(dAtA[iNdEx:]) diff --git a/x/wasm/binding/exec_perp.go b/x/wasm/binding/exec_perp.go index d9dd7d361..11cf6931b 100644 --- a/x/wasm/binding/exec_perp.go +++ b/x/wasm/binding/exec_perp.go @@ -218,7 +218,7 @@ func (exec *ExecutorPerp) CreateMarket( var market perpv2types.Market if cwMsg.MarketParams == nil { - market = *perpv2types.DefaultMarket(pair) + market = perpv2types.DefaultMarket(pair) } else { mp := cwMsg.MarketParams market = perpv2types.Market{ From 0bdef3543b1eec20339b95a2cce1c5f2d0700350 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Mon, 28 Aug 2023 15:00:29 +0200 Subject: [PATCH 02/16] temp commit after adding market version --- proto/nibiru/perp/v2/state.proto | 14 +- x/perp/v2/integration/action/market.go | 5 +- x/perp/v2/integration/action/withdraw.go | 2 +- x/perp/v2/integration/assertion/market.go | 2 +- x/perp/v2/keeper/admin.go | 10 +- x/perp/v2/keeper/admin_test.go | 4 + x/perp/v2/keeper/amm.go | 17 + x/perp/v2/keeper/calc.go | 2 +- x/perp/v2/keeper/clearing_house.go | 6 +- x/perp/v2/keeper/clearing_house_test.go | 2 +- x/perp/v2/keeper/grpc_query.go | 6 +- x/perp/v2/keeper/hooks.go | 5 +- x/perp/v2/keeper/keeper.go | 20 +- x/perp/v2/keeper/liquidate.go | 2 +- x/perp/v2/keeper/margin.go | 4 +- x/perp/v2/keeper/twap_test.go | 4 +- x/perp/v2/keeper/withdraw.go | 7 +- x/perp/v2/module/abci.go | 3 +- x/perp/v2/module/abci_test.go | 2 +- x/perp/v2/module/genesis.go | 6 +- x/perp/v2/module/genesis_test.go | 2 +- x/perp/v2/types/state.pb.go | 370 +++++++++++++++------- x/wasm/binding/exec_perp_test.go | 2 +- x/wasm/binding/exec_test.go | 4 +- 24 files changed, 351 insertions(+), 150 deletions(-) diff --git a/proto/nibiru/perp/v2/state.proto b/proto/nibiru/perp/v2/state.proto index 17694077f..4a7831f16 100644 --- a/proto/nibiru/perp/v2/state.proto +++ b/proto/nibiru/perp/v2/state.proto @@ -44,6 +44,10 @@ message Market { // whether or not the market is enabled bool enabled = 2; + // the version of the Market, only one market can exist per pair, when one is closed it cannot be reactivated, + // so a new market must be created, this is the version of the market + uint64 version = 14; + // the minimum margin ratio which a user must maintain on this market string maintenance_margin_ratio = 3 [ (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", @@ -114,6 +118,12 @@ message Market { ]; } +// MarketLastVersion is used to store the last version of the market +message MarketLastVersion { + // version of the market + uint64 version = 1; +} + message AMM { // identifies the market this AMM belongs to string pair = 1 [ @@ -122,10 +132,6 @@ message AMM { (gogoproto.nullable) = false ]; - // the version of the Market, only one market can exist per pair, when one is closed it cannot be reactivated, - // so a new market must be created, this is the version of the market - uint64 version = 8; - // the amount of base reserves this AMM has string base_reserve = 2 [ (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", diff --git a/x/perp/v2/integration/action/market.go b/x/perp/v2/integration/action/market.go index 3ff23a229..efcb694e0 100644 --- a/x/perp/v2/integration/action/market.go +++ b/x/perp/v2/integration/action/market.go @@ -21,7 +21,7 @@ type logger struct { log string } -func (e logger) Do(app *app.NibiruApp, ctx sdk.Context) (sdk.Context, error, bool) { +func (e logger) Do(_ *app.NibiruApp, ctx sdk.Context) (sdk.Context, error, bool) { fmt.Println(e.log) return ctx, nil, true } @@ -39,7 +39,8 @@ type createMarketAction struct { } func (c createMarketAction) Do(app *app.NibiruApp, ctx sdk.Context) (sdk.Context, error, bool) { - app.PerpKeeperV2.Markets.Insert(ctx, c.Market.Pair, c.Market) + app.PerpKeeperV2.Markets.Insert(ctx, collections.Join(c.Market.Pair, uint64(1)), c.Market) + app.PerpKeeperV2.MarketLastVersion.Insert(ctx, c.Market.Pair, types.MarketLastVersion{Version: 1}) app.PerpKeeperV2.AMMs.Insert(ctx, c.AMM.Pair, c.AMM) app.PerpKeeperV2.ReserveSnapshots.Insert(ctx, collections.Join(c.AMM.Pair, ctx.BlockTime()), types.ReserveSnapshot{ diff --git a/x/perp/v2/integration/action/withdraw.go b/x/perp/v2/integration/action/withdraw.go index 8ad02d25a..6c8742e7e 100644 --- a/x/perp/v2/integration/action/withdraw.go +++ b/x/perp/v2/integration/action/withdraw.go @@ -18,7 +18,7 @@ type withdraw struct { func (w withdraw) Do(app *app.NibiruApp, ctx sdk.Context) ( outCtx sdk.Context, err error, isMandatory bool, ) { - market, err := app.PerpKeeperV2.Markets.Get(ctx, w.Pair) + market, err := app.PerpKeeperV2.GetMarket(ctx, w.Pair) if err != nil { return ctx, err, true } diff --git a/x/perp/v2/integration/assertion/market.go b/x/perp/v2/integration/assertion/market.go index 5371f445c..21234b739 100644 --- a/x/perp/v2/integration/assertion/market.go +++ b/x/perp/v2/integration/assertion/market.go @@ -20,7 +20,7 @@ type marketShouldBeEqual struct { } func (m marketShouldBeEqual) Do(app *app.NibiruApp, ctx sdk.Context) (sdk.Context, error, bool) { - market, err := app.PerpKeeperV2.Markets.Get(ctx, m.Pair) + market, err := app.PerpKeeperV2.GetMarket(ctx, m.Pair) if err != nil { return ctx, err, false } diff --git a/x/perp/v2/keeper/admin.go b/x/perp/v2/keeper/admin.go index a2c5e649b..6c05a7b18 100644 --- a/x/perp/v2/keeper/admin.go +++ b/x/perp/v2/keeper/admin.go @@ -2,6 +2,7 @@ package keeper import ( "fmt" + "github.com/NibiruChain/collections" sdkmath "cosmossdk.io/math" @@ -71,9 +72,9 @@ func (k admin) CreateMarket( args ArgsCreateMarket, ) error { pair := args.Pair - market, err := k.Markets.Get(ctx, pair) + market, err := k.GetMarket(ctx, pair) if err == nil && market.Enabled { - return fmt.Errorf("market %s already exists", pair) + return fmt.Errorf("market %s already exists and it is enabled", pair) } // init market @@ -103,7 +104,10 @@ func (k admin) CreateMarket( return err } - k.Markets.Insert(ctx, pair, market) + lastVersion := k.MarketLastVersion.GetOr(ctx, pair, types.MarketLastVersion{Version: 1}) + + k.Markets.Insert(ctx, collections.Join(pair, lastVersion.Version), market) + k.MarketLastVersion.Insert(ctx, pair, lastVersion) k.AMMs.Insert(ctx, pair, amm) return nil diff --git a/x/perp/v2/keeper/admin_test.go b/x/perp/v2/keeper/admin_test.go index c61755220..1aa3ce2dc 100644 --- a/x/perp/v2/keeper/admin_test.go +++ b/x/perp/v2/keeper/admin_test.go @@ -141,6 +141,10 @@ func TestCreateMarketFail(t *testing.T) { }) require.NoError(t, err) + lastVersion, err := app.PerpKeeperV2.MarketLastVersion.Get(ctx, pair) + require.NoError(t, err) + require.Equal(t, uint64(1), lastVersion.Version) + // Fail since it already exists and it is not disabled err = app.PerpKeeperV2.Admin().CreateMarket(ctx, keeper.ArgsCreateMarket{ Pair: pair, diff --git a/x/perp/v2/keeper/amm.go b/x/perp/v2/keeper/amm.go index 2529ddd08..29640ce89 100644 --- a/x/perp/v2/keeper/amm.go +++ b/x/perp/v2/keeper/amm.go @@ -2,6 +2,8 @@ package keeper import ( sdkmath "cosmossdk.io/math" + "fmt" + "github.com/NibiruChain/collections" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/NibiruChain/nibiru/x/common/asset" @@ -113,3 +115,18 @@ func (k Keeper) handleMarketUpdateCost(ctx sdk.Context, pair asset.Pair, costAmt } return nil } + +// GetMarket returns the market with last version. +func (k Keeper) GetMarket(ctx sdk.Context, pair asset.Pair) (types.Market, error) { + lastVersion, err := k.MarketLastVersion.Get(ctx, pair) + if err != nil { + return types.Market{}, fmt.Errorf("market %s not found", pair) + } + + market, err := k.Markets.Get(ctx, collections.Join(pair, lastVersion.Version)) + if err != nil { + return types.Market{}, fmt.Errorf("market %s not found", pair) + } + + return market, nil +} diff --git a/x/perp/v2/keeper/calc.go b/x/perp/v2/keeper/calc.go index b241cd3c3..06c14bca0 100644 --- a/x/perp/v2/keeper/calc.go +++ b/x/perp/v2/keeper/calc.go @@ -66,7 +66,7 @@ func UnrealizedPnl(position types.Position, positionNotional sdk.Dec) (unrealize } } -// Given a position and it's notional value, returns the margin ratio. +// MarginRatio Given a position and it's notional value, returns the margin ratio. func MarginRatio( position types.Position, positionNotional sdk.Dec, diff --git a/x/perp/v2/keeper/clearing_house.go b/x/perp/v2/keeper/clearing_house.go index 1a32b7562..eb8c1aafb 100644 --- a/x/perp/v2/keeper/clearing_house.go +++ b/x/perp/v2/keeper/clearing_house.go @@ -36,7 +36,7 @@ func (k Keeper) MarketOrder( leverage sdk.Dec, baseAmtLimit sdk.Dec, ) (positionResp *types.PositionResp, err error) { - market, err := k.Markets.Get(ctx, pair) + market, err := k.GetMarket(ctx, pair) if err != nil { return nil, types.ErrPairNotFound.Wrapf("pair %s not found", pair) } @@ -691,7 +691,7 @@ func (k Keeper) ClosePosition(ctx sdk.Context, pair asset.Pair, traderAddr sdk.A return nil, err } - market, err := k.Markets.Get(ctx, pair) + market, err := k.GetMarket(ctx, pair) if err != nil { return nil, fmt.Errorf("%w: %s", types.ErrPairNotFound, pair) } @@ -833,7 +833,7 @@ func (k Keeper) PartialClose( traderAddr sdk.AccAddress, sizeAmt sdk.Dec, //unsigned ) (*types.PositionResp, error) { - market, err := k.Markets.Get(ctx, pair) + market, err := k.GetMarket(ctx, pair) if err != nil { return nil, types.ErrPairNotFound.Wrapf("pair: %s", pair) } diff --git a/x/perp/v2/keeper/clearing_house_test.go b/x/perp/v2/keeper/clearing_house_test.go index 60377057a..98c68976d 100644 --- a/x/perp/v2/keeper/clearing_house_test.go +++ b/x/perp/v2/keeper/clearing_house_test.go @@ -1172,7 +1172,7 @@ func TestMarketOrderError(t *testing.T) { traderAddr := testutil.AccAddress() market := mock.TestMarket() - app.PerpKeeperV2.Markets.Insert(ctx, asset.Registry.Pair(denoms.BTC, denoms.NUSD), *market) + app.PerpKeeperV2.Markets.Insert(ctx, collections.Join(asset.Registry.Pair(denoms.BTC, denoms.NUSD), uint64(1)), *market) amm := mock.TestAMMDefault() app.PerpKeeperV2.AMMs.Insert(ctx, amm.Pair, *amm) app.PerpKeeperV2.ReserveSnapshots.Insert(ctx, collections.Join(amm.Pair, ctx.BlockTime()), types.ReserveSnapshot{ diff --git a/x/perp/v2/keeper/grpc_query.go b/x/perp/v2/keeper/grpc_query.go index fa0c9ebdd..e151db3ab 100644 --- a/x/perp/v2/keeper/grpc_query.go +++ b/x/perp/v2/keeper/grpc_query.go @@ -37,7 +37,7 @@ func (q queryServer) QueryPositions( ctx := sdk.UnwrapSDKContext(goCtx) - markets := q.k.Markets.Iterate(ctx, collections.Range[asset.Pair]{}).Values() + markets := q.k.Markets.Iterate(ctx, collections.Range[collections.Pair[asset.Pair, uint64]]{}).Values() var positions []types.QueryPositionResponse for _, market := range markets { @@ -69,7 +69,7 @@ func (q queryServer) QueryPosition( ctx := sdk.UnwrapSDKContext(goCtx) - market, err := q.k.Markets.Get(ctx, req.Pair) + market, err := q.k.GetMarket(ctx, req.Pair) if err != nil { return nil, err } @@ -131,7 +131,7 @@ func (q queryServer) QueryMarkets( ctx := sdk.UnwrapSDKContext(goCtx) var ammMarkets []types.AmmMarket - markets := q.k.Markets.Iterate(ctx, collections.Range[asset.Pair]{}).Values() + markets := q.k.Markets.Iterate(ctx, collections.Range[collections.Pair[asset.Pair, uint64]]{}).Values() for _, market := range markets { pair := market.Pair amm, err := q.k.AMMs.Get(ctx, pair) diff --git a/x/perp/v2/keeper/hooks.go b/x/perp/v2/keeper/hooks.go index 918b352c5..e5e44b669 100644 --- a/x/perp/v2/keeper/hooks.go +++ b/x/perp/v2/keeper/hooks.go @@ -17,7 +17,8 @@ func (k Keeper) BeforeEpochStart(ctx sdk.Context, epochIdentifier string, epochN } func (k Keeper) AfterEpochEnd(ctx sdk.Context, epochIdentifier string, _ uint64) { - for _, market := range k.Markets.Iterate(ctx, collections.Range[asset.Pair]{}).Values() { + for _, market := range k.Markets.Iterate(ctx, collections.Range[collections.Pair[asset.Pair, uint64]]{}).Values() { + // TODO (reviewer): this needs to be fixed for only enabled markets if !market.Enabled || epochIdentifier != market.FundingRateEpochId { return } @@ -53,7 +54,7 @@ func (k Keeper) AfterEpochEnd(ctx sdk.Context, epochIdentifier string, _ uint64) premiumFraction := clampedDivergence.Mul(indexTwap).QuoInt64(int64(intervalsPerDay)) market.LatestCumulativePremiumFraction = market.LatestCumulativePremiumFraction.Add(premiumFraction) - k.Markets.Insert(ctx, market.Pair, market) + k.Markets.Insert(ctx, collections.Join(market.Pair, market.Version), market) _ = ctx.EventManager().EmitTypedEvent(&types.FundingRateChangedEvent{ Pair: market.Pair, diff --git a/x/perp/v2/keeper/keeper.go b/x/perp/v2/keeper/keeper.go index 04fd917e6..1b349b775 100644 --- a/x/perp/v2/keeper/keeper.go +++ b/x/perp/v2/keeper/keeper.go @@ -25,10 +25,11 @@ type Keeper struct { OracleKeeper types.OracleKeeper EpochKeeper types.EpochKeeper - Markets collections.Map[asset.Pair, types.Market] - AMMs collections.Map[asset.Pair, types.AMM] - Positions collections.Map[collections.Pair[asset.Pair, sdk.AccAddress], types.Position] - ReserveSnapshots collections.Map[collections.Pair[asset.Pair, time.Time], types.ReserveSnapshot] + Markets collections.Map[collections.Pair[asset.Pair, uint64], types.Market] + MarketLastVersion collections.Map[asset.Pair, types.MarketLastVersion] + AMMs collections.Map[asset.Pair, types.AMM] + Positions collections.Map[collections.Pair[asset.Pair, sdk.AccAddress], types.Position] + ReserveSnapshots collections.Map[collections.Pair[asset.Pair, time.Time], types.ReserveSnapshot] } // NewKeeper Creates a new x/perp Keeper instance. @@ -55,9 +56,14 @@ func NewKeeper( EpochKeeper: epochKeeper, Markets: collections.NewMap( storeKey, 11, - asset.PairKeyEncoder, + collections.PairKeyEncoder(asset.PairKeyEncoder, collections.Uint64KeyEncoder), collections.ProtoValueEncoder[types.Market](cdc), ), + MarketLastVersion: collections.NewMap( + storeKey, 15, + asset.PairKeyEncoder, + collections.ProtoValueEncoder[types.MarketLastVersion](cdc), + ), AMMs: collections.NewMap( storeKey, 12, asset.PairKeyEncoder, @@ -82,11 +88,11 @@ func (k Keeper) Logger(ctx sdk.Context) log.Logger { // ChangeMarketEnabledParameter change the market enabled parameter func (k Keeper) ChangeMarketEnabledParameter(ctx sdk.Context, pair asset.Pair, enabled bool) (err error) { - market, err := k.Markets.Get(ctx, pair) + market, err := k.GetMarket(ctx, pair) if err != nil { return } market.Enabled = enabled - k.Markets.Insert(ctx, pair, market) + k.Markets.Insert(ctx, collections.Join(pair, market.Version), market) return } diff --git a/x/perp/v2/keeper/liquidate.go b/x/perp/v2/keeper/liquidate.go index 8825c3b56..4d0e73c5f 100644 --- a/x/perp/v2/keeper/liquidate.go +++ b/x/perp/v2/keeper/liquidate.go @@ -152,7 +152,7 @@ func (k Keeper) liquidate( // eventLiqFailed exists when the liquidation fails and is nil when the // liquidation succeeds. - market, err := k.Markets.Get(ctx, pair) + market, err := k.GetMarket(ctx, pair) if err != nil { eventLiqFailed := &types.LiquidationFailedEvent{ Pair: pair, diff --git a/x/perp/v2/keeper/margin.go b/x/perp/v2/keeper/margin.go index 11525c985..7fa33b3fc 100644 --- a/x/perp/v2/keeper/margin.go +++ b/x/perp/v2/keeper/margin.go @@ -26,7 +26,7 @@ import ( func (k Keeper) AddMargin( ctx sdk.Context, pair asset.Pair, traderAddr sdk.AccAddress, marginToAdd sdk.Coin, ) (res *types.MsgAddMarginResponse, err error) { - market, err := k.Markets.Get(ctx, pair) + market, err := k.GetMarket(ctx, pair) if err != nil { return nil, fmt.Errorf("%w: %s", types.ErrPairNotFound, pair) } @@ -116,7 +116,7 @@ func (k Keeper) RemoveMargin( ctx sdk.Context, pair asset.Pair, traderAddr sdk.AccAddress, marginToRemove sdk.Coin, ) (res *types.MsgRemoveMarginResponse, err error) { // fetch objects from state - market, err := k.Markets.Get(ctx, pair) + market, err := k.GetMarket(ctx, pair) if err != nil { return nil, fmt.Errorf("%w: %s", types.ErrPairNotFound, pair) } diff --git a/x/perp/v2/keeper/twap_test.go b/x/perp/v2/keeper/twap_test.go index 61d4e6ee8..edf176025 100644 --- a/x/perp/v2/keeper/twap_test.go +++ b/x/perp/v2/keeper/twap_test.go @@ -107,7 +107,7 @@ func TestInvalidTwap(t *testing.T) { pair := asset.Registry.Pair(denoms.BTC, denoms.NUSD) app, ctx := testapp.NewNibiruTestAppAndContext(true) - app.PerpKeeperV2.Markets.Insert(ctx, pair, *mock.TestMarket()) + app.PerpKeeperV2.Markets.Insert(ctx, collections.Join(pair, uint64(1)), *mock.TestMarket()) app.PerpKeeperV2.AMMs.Insert(ctx, pair, *mock.TestAMMDefault()) app.PerpKeeperV2.ReserveSnapshots.Insert(ctx, collections.Join(pair, time.UnixMilli(0)), types.ReserveSnapshot{ Amm: *mock.TestAMMDefault(), @@ -364,7 +364,7 @@ func TestCalcTwapExtended(t *testing.T) { t.Run(tc.name, func(t *testing.T) { app, ctx := testapp.NewNibiruTestAppAndContext(true) - app.PerpKeeperV2.Markets.Insert(ctx, pair, *mock.TestMarket()) + app.PerpKeeperV2.Markets.Insert(ctx, collections.Join(pair, uint64(1)), *mock.TestMarket()) app.PerpKeeperV2.AMMs.Insert(ctx, pair, *mock.TestAMMDefault()) app.PerpKeeperV2.ReserveSnapshots.Insert(ctx, collections.Join(pair, time.UnixMilli(0)), types.ReserveSnapshot{ Amm: *mock.TestAMMDefault(), diff --git a/x/perp/v2/keeper/withdraw.go b/x/perp/v2/keeper/withdraw.go index 2b06d8f18..4cc02dfab 100644 --- a/x/perp/v2/keeper/withdraw.go +++ b/x/perp/v2/keeper/withdraw.go @@ -2,6 +2,7 @@ package keeper import ( sdkmath "cosmossdk.io/math" + "github.com/NibiruChain/collections" sdk "github.com/cosmos/cosmos-sdk/types" types "github.com/NibiruChain/nibiru/x/perp/v2/types" @@ -81,19 +82,19 @@ func (k Keeper) WithdrawFromVault( // IncrementPrepaidBadDebt increases the bad debt for the provided denom. func (k Keeper) IncrementPrepaidBadDebt(ctx sdk.Context, market types.Market, amount sdkmath.Int) { market.PrepaidBadDebt.Amount = market.PrepaidBadDebt.Amount.Add(amount) - k.Markets.Insert(ctx, market.Pair, market) + k.Markets.Insert(ctx, collections.Join(market.Pair, market.Version), market) } // Zeroes out the prepaid bad debt func (k Keeper) ZeroPrepaidBadDebt(ctx sdk.Context, market types.Market) { market.PrepaidBadDebt.Amount = sdk.ZeroInt() - k.Markets.Insert(ctx, market.Pair, market) + k.Markets.Insert(ctx, collections.Join(market.Pair, market.Version), market) } // DecrementPrepaidBadDebt decrements the amount of bad debt prepaid by denom. func (k Keeper) DecrementPrepaidBadDebt(ctx sdk.Context, market types.Market, amount sdkmath.Int) { market.PrepaidBadDebt.Amount = market.PrepaidBadDebt.Amount.Sub(amount) - k.Markets.Insert(ctx, market.Pair, market) + k.Markets.Insert(ctx, collections.Join(market.Pair, market.Version), market) } /* diff --git a/x/perp/v2/module/abci.go b/x/perp/v2/module/abci.go index 7f3bf4012..6fc8bfb08 100644 --- a/x/perp/v2/module/abci.go +++ b/x/perp/v2/module/abci.go @@ -13,6 +13,7 @@ import ( // EndBlocker Called every block to store a snapshot of the perpamm. func EndBlocker(ctx sdk.Context, k keeper.Keeper) []abci.ValidatorUpdate { + // TODO: take into account only enabled markets for _, amm := range k.AMMs.Iterate(ctx, collections.Range[asset.Pair]{}).Values() { snapshot := types.ReserveSnapshot{ Amm: amm, @@ -20,7 +21,7 @@ func EndBlocker(ctx sdk.Context, k keeper.Keeper) []abci.ValidatorUpdate { } k.ReserveSnapshots.Insert(ctx, collections.Join(amm.Pair, ctx.BlockTime()), snapshot) - market, err := k.Markets.Get(ctx, amm.Pair) + market, err := k.GetMarket(ctx, amm.Pair) if err != nil { k.Logger(ctx).Error("failed to fetch market", "pair", amm.Pair, "error", err) continue diff --git a/x/perp/v2/module/abci_test.go b/x/perp/v2/module/abci_test.go index c3deeb12c..6def0b731 100644 --- a/x/perp/v2/module/abci_test.go +++ b/x/perp/v2/module/abci_test.go @@ -60,7 +60,7 @@ func TestSnapshotUpdates(t *testing.T) { assert.EqualValues(t, expectedSnapshot, snapshot) t.Log("affect mark price") - market, err := app.PerpKeeperV2.Markets.Get(ctx, asset.Registry.Pair(denoms.BTC, denoms.NUSD)) + market, err := app.PerpKeeperV2.GetMarket(ctx, asset.Registry.Pair(denoms.BTC, denoms.NUSD)) require.NoError(t, err) amm, err := app.PerpKeeperV2.AMMs.Get(ctx, asset.Registry.Pair(denoms.BTC, denoms.NUSD)) require.NoError(t, err) diff --git a/x/perp/v2/module/genesis.go b/x/perp/v2/module/genesis.go index c06ff8bfd..3bea511f3 100644 --- a/x/perp/v2/module/genesis.go +++ b/x/perp/v2/module/genesis.go @@ -15,12 +15,13 @@ import ( // InitGenesis initializes the capability module's state from a provided genesis // state. func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState) { + // TODO: take care of last versions saved in the store if err := genState.Validate(); err != nil { panic(err) } for _, m := range genState.Markets { - k.Markets.Insert(ctx, m.Pair, m) + k.Markets.Insert(ctx, collections.Join(m.Pair, m.Version), m) } for _, a := range genState.Amms { @@ -48,9 +49,10 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState) // ExportGenesis returns the capability module's exported genesis. func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState { + // TODO: take care of last versions saved in the store genesis := new(types.GenesisState) - genesis.Markets = k.Markets.Iterate(ctx, collections.Range[asset.Pair]{}).Values() + genesis.Markets = k.Markets.Iterate(ctx, collections.Range[collections.Pair[asset.Pair, uint64]]{}).Values() genesis.Amms = k.AMMs.Iterate(ctx, collections.Range[asset.Pair]{}).Values() genesis.Positions = k.Positions.Iterate(ctx, collections.PairRange[asset.Pair, sdk.AccAddress]{}).Values() genesis.ReserveSnapshots = k.ReserveSnapshots.Iterate(ctx, collections.PairRange[asset.Pair, time.Time]{}).Values() diff --git a/x/perp/v2/module/genesis_test.go b/x/perp/v2/module/genesis_test.go index c773af54b..bf412b764 100644 --- a/x/perp/v2/module/genesis_test.go +++ b/x/perp/v2/module/genesis_test.go @@ -68,7 +68,7 @@ func RunTestGenesis(t *testing.T, tc TestCase) { pair := asset.Registry.Pair(denoms.BTC, denoms.NUSD) // create some params - app.PerpKeeperV2.Markets.Insert(ctx, pair, *mock.TestMarket()) + app.PerpKeeperV2.Markets.Insert(ctx, collections.Join(pair, uint64(1)), *mock.TestMarket()) app.PerpKeeperV2.AMMs.Insert(ctx, pair, *mock.TestAMMDefault()) // create some positions diff --git a/x/perp/v2/types/state.pb.go b/x/perp/v2/types/state.pb.go index d2a632aeb..22e3a654c 100644 --- a/x/perp/v2/types/state.pb.go +++ b/x/perp/v2/types/state.pb.go @@ -103,6 +103,9 @@ type Market struct { Pair github_com_NibiruChain_nibiru_x_common_asset.Pair `protobuf:"bytes,1,opt,name=pair,proto3,customtype=github.com/NibiruChain/nibiru/x/common/asset.Pair" json:"pair"` // whether or not the market is enabled Enabled bool `protobuf:"varint,2,opt,name=enabled,proto3" json:"enabled,omitempty"` + // the version of the Market, only one market can exist per pair, when one is closed it cannot be reactivated, + // so a new market must be created, this is the version of the market + Version uint64 `protobuf:"varint,14,opt,name=version,proto3" json:"version,omitempty"` // the minimum margin ratio which a user must maintain on this market MaintenanceMarginRatio github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,3,opt,name=maintenance_margin_ratio,json=maintenanceMarginRatio,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"maintenance_margin_ratio"` // the maximum leverage a user is able to be taken on this market @@ -176,6 +179,13 @@ func (m *Market) GetEnabled() bool { return false } +func (m *Market) GetVersion() uint64 { + if m != nil { + return m.Version + } + return 0 +} + func (m *Market) GetFundingRateEpochId() string { if m != nil { return m.FundingRateEpochId @@ -197,12 +207,55 @@ func (m *Market) GetPrepaidBadDebt() types.Coin { return types.Coin{} } +// MarketLastVersion is used to store the last version of the market +type MarketLastVersion struct { + // version of the market + Version uint64 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` +} + +func (m *MarketLastVersion) Reset() { *m = MarketLastVersion{} } +func (m *MarketLastVersion) String() string { return proto.CompactTextString(m) } +func (*MarketLastVersion) ProtoMessage() {} +func (*MarketLastVersion) Descriptor() ([]byte, []int) { + return fileDescriptor_8f4829f34f7b8040, []int{1} +} +func (m *MarketLastVersion) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MarketLastVersion) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MarketLastVersion.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 *MarketLastVersion) XXX_Merge(src proto.Message) { + xxx_messageInfo_MarketLastVersion.Merge(m, src) +} +func (m *MarketLastVersion) XXX_Size() int { + return m.Size() +} +func (m *MarketLastVersion) XXX_DiscardUnknown() { + xxx_messageInfo_MarketLastVersion.DiscardUnknown(m) +} + +var xxx_messageInfo_MarketLastVersion proto.InternalMessageInfo + +func (m *MarketLastVersion) GetVersion() uint64 { + if m != nil { + return m.Version + } + return 0 +} + type AMM struct { // identifies the market this AMM belongs to Pair github_com_NibiruChain_nibiru_x_common_asset.Pair `protobuf:"bytes,1,opt,name=pair,proto3,customtype=github.com/NibiruChain/nibiru/x/common/asset.Pair" json:"pair"` - // the version of the Market, only one market can exist per pair, when one is closed it cannot be reactivated, - // so a new market must be created, this is the version of the market - Version uint64 `protobuf:"varint,8,opt,name=version,proto3" json:"version,omitempty"` // the amount of base reserves this AMM has BaseReserve github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=base_reserve,json=baseReserve,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"base_reserve"` // the amount of quote reserves this AMM has @@ -221,7 +274,7 @@ func (m *AMM) Reset() { *m = AMM{} } func (m *AMM) String() string { return proto.CompactTextString(m) } func (*AMM) ProtoMessage() {} func (*AMM) Descriptor() ([]byte, []int) { - return fileDescriptor_8f4829f34f7b8040, []int{1} + return fileDescriptor_8f4829f34f7b8040, []int{2} } func (m *AMM) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -250,13 +303,6 @@ func (m *AMM) XXX_DiscardUnknown() { var xxx_messageInfo_AMM proto.InternalMessageInfo -func (m *AMM) GetVersion() uint64 { - if m != nil { - return m.Version - } - return 0 -} - type Position struct { // address identifies the address owner of this position TraderAddress string `protobuf:"bytes,1,opt,name=trader_address,json=traderAddress,proto3" json:"trader_address,omitempty"` @@ -279,7 +325,7 @@ func (m *Position) Reset() { *m = Position{} } func (m *Position) String() string { return proto.CompactTextString(m) } func (*Position) ProtoMessage() {} func (*Position) Descriptor() ([]byte, []int) { - return fileDescriptor_8f4829f34f7b8040, []int{2} + return fileDescriptor_8f4829f34f7b8040, []int{3} } func (m *Position) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -333,7 +379,7 @@ func (m *ReserveSnapshot) Reset() { *m = ReserveSnapshot{} } func (m *ReserveSnapshot) String() string { return proto.CompactTextString(m) } func (*ReserveSnapshot) ProtoMessage() {} func (*ReserveSnapshot) Descriptor() ([]byte, []int) { - return fileDescriptor_8f4829f34f7b8040, []int{3} + return fileDescriptor_8f4829f34f7b8040, []int{4} } func (m *ReserveSnapshot) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -380,6 +426,7 @@ func init() { proto.RegisterEnum("nibiru.perp.v2.Direction", Direction_name, Direction_value) proto.RegisterEnum("nibiru.perp.v2.TwapCalcOption", TwapCalcOption_name, TwapCalcOption_value) proto.RegisterType((*Market)(nil), "nibiru.perp.v2.Market") + proto.RegisterType((*MarketLastVersion)(nil), "nibiru.perp.v2.MarketLastVersion") proto.RegisterType((*AMM)(nil), "nibiru.perp.v2.AMM") proto.RegisterType((*Position)(nil), "nibiru.perp.v2.Position") proto.RegisterType((*ReserveSnapshot)(nil), "nibiru.perp.v2.ReserveSnapshot") @@ -388,74 +435,76 @@ func init() { func init() { proto.RegisterFile("nibiru/perp/v2/state.proto", fileDescriptor_8f4829f34f7b8040) } var fileDescriptor_8f4829f34f7b8040 = []byte{ - // 1065 bytes of a gzipped FileDescriptorProto + // 1089 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x96, 0x5d, 0x6f, 0xdb, 0x36, - 0x17, 0xc7, 0xe3, 0xd8, 0x4d, 0x6d, 0x3a, 0x4d, 0x0c, 0x26, 0xe9, 0xa3, 0x04, 0x0f, 0x9c, 0x2c, - 0xc0, 0x86, 0xa0, 0x43, 0x25, 0x24, 0xbb, 0x2a, 0x76, 0xe5, 0xd7, 0xce, 0x80, 0xdf, 0x2a, 0x3b, - 0x08, 0x36, 0x14, 0x20, 0x28, 0x89, 0x91, 0xb9, 0x48, 0xa2, 0x42, 0x52, 0x4e, 0xba, 0x7d, 0x89, - 0x5d, 0x6e, 0xdf, 0xa8, 0x97, 0xbd, 0x1c, 0x76, 0xd1, 0x15, 0xc9, 0x67, 0xd8, 0xfd, 0x40, 0x4a, - 0x76, 0x5c, 0x60, 0xc0, 0x36, 0x61, 0xbd, 0x4a, 0xc8, 0xa3, 0xf3, 0xfb, 0x53, 0xc7, 0xe7, 0xfc, - 0x29, 0x70, 0x10, 0x51, 0x87, 0xf2, 0xc4, 0x8a, 0x09, 0x8f, 0xad, 0xf9, 0x99, 0x25, 0x24, 0x96, - 0xc4, 0x8c, 0x39, 0x93, 0x0c, 0x6e, 0xa5, 0x31, 0x53, 0xc5, 0xcc, 0xf9, 0xd9, 0xc1, 0xae, 0xcf, - 0x7c, 0xa6, 0x43, 0x96, 0xfa, 0x2f, 0x7d, 0xea, 0xa0, 0xee, 0x32, 0x11, 0x32, 0x61, 0x39, 0x58, - 0x10, 0x6b, 0x7e, 0xea, 0x10, 0x89, 0x4f, 0x2d, 0x97, 0xd1, 0x28, 0x8b, 0xef, 0xa7, 0x71, 0x94, - 0x26, 0xa6, 0x8b, 0x45, 0xaa, 0xcf, 0x98, 0x1f, 0x10, 0x4b, 0xaf, 0x9c, 0xe4, 0xd2, 0xf2, 0x12, - 0x8e, 0x25, 0x65, 0x59, 0xea, 0xf1, 0x1f, 0x65, 0xb0, 0x31, 0xc0, 0xfc, 0x8a, 0x48, 0x38, 0x00, - 0xa5, 0x18, 0x53, 0x6e, 0x14, 0x8e, 0x0a, 0x27, 0x95, 0xe6, 0x8b, 0xb7, 0xef, 0x0f, 0xd7, 0x7e, - 0x7b, 0x7f, 0x78, 0xea, 0x53, 0x39, 0x4b, 0x1c, 0xd3, 0x65, 0xa1, 0x35, 0xd4, 0x87, 0x6d, 0xcd, - 0x30, 0x8d, 0xac, 0xec, 0xa5, 0x6e, 0x2d, 0x97, 0x85, 0x21, 0x8b, 0x2c, 0x2c, 0x04, 0x91, 0xe6, - 0x18, 0x53, 0x6e, 0x6b, 0x0c, 0x34, 0xc0, 0x63, 0x12, 0x61, 0x27, 0x20, 0x9e, 0xb1, 0x7e, 0x54, - 0x38, 0x29, 0xdb, 0x8b, 0x25, 0x9c, 0x01, 0x23, 0xc4, 0x34, 0x92, 0x24, 0xc2, 0x91, 0x4b, 0x50, - 0x88, 0xb9, 0x4f, 0x23, 0xa4, 0x8f, 0x65, 0x14, 0xb5, 0xb8, 0x99, 0x89, 0x7f, 0xb1, 0x22, 0x9e, - 0xd5, 0x20, 0xfd, 0xf3, 0x5c, 0x78, 0x57, 0x96, 0x7c, 0x13, 0x13, 0x61, 0xb6, 0x89, 0x6b, 0x3f, - 0x5d, 0xe1, 0x0d, 0x34, 0xce, 0x56, 0x34, 0xf8, 0x0a, 0x6c, 0x86, 0xf8, 0x16, 0x05, 0x64, 0x4e, - 0x38, 0xf6, 0x89, 0x51, 0xca, 0x45, 0xaf, 0x86, 0xf8, 0xb6, 0x9f, 0x21, 0xe0, 0x8f, 0xe0, 0x38, - 0xc0, 0x92, 0x08, 0x89, 0xdc, 0x24, 0x4c, 0x02, 0x2c, 0xe9, 0x9c, 0xa0, 0x98, 0x93, 0x90, 0x26, - 0x21, 0xba, 0xe4, 0xd8, 0x55, 0xc5, 0x35, 0x1e, 0xe5, 0x12, 0x3a, 0x4c, 0xc9, 0xad, 0x25, 0x78, - 0x9c, 0x72, 0xbb, 0x19, 0x16, 0xbe, 0x06, 0x90, 0xdc, 0xba, 0x33, 0x1c, 0xf9, 0x04, 0x5d, 0x12, - 0x92, 0xd5, 0x6c, 0x23, 0x97, 0x58, 0x6d, 0x41, 0xea, 0x12, 0x92, 0x56, 0xcb, 0x07, 0x06, 0x71, - 0x99, 0x78, 0x23, 0x24, 0x09, 0xd1, 0x65, 0x12, 0x79, 0x2b, 0x1a, 0x8f, 0x73, 0x69, 0xec, 0x2d, - 0x79, 0xdd, 0x24, 0xf2, 0x96, 0x42, 0x0e, 0xd8, 0x0b, 0xe8, 0x75, 0x42, 0x3d, 0xdd, 0x89, 0x2b, - 0x2a, 0xe5, 0x5c, 0x2a, 0x3b, 0x2b, 0xb0, 0xa5, 0xc6, 0xf7, 0x60, 0x3f, 0xc6, 0x5c, 0x52, 0x1c, - 0xa0, 0x55, 0xad, 0x54, 0xa7, 0x92, 0x4b, 0xe7, 0x7f, 0x19, 0xb0, 0xff, 0xc0, 0x4b, 0xb5, 0x4e, - 0xc1, 0x9e, 0x2a, 0x17, 0x8d, 0x7c, 0xc5, 0x27, 0x88, 0xc4, 0xcc, 0x9d, 0x21, 0xea, 0x19, 0x40, - 0xe9, 0xd8, 0x30, 0x0b, 0xda, 0x58, 0x92, 0x8e, 0x0a, 0xf5, 0x3c, 0x78, 0x0e, 0x76, 0xe5, 0x0d, - 0x8e, 0x51, 0xc0, 0xd8, 0x95, 0x83, 0xdd, 0x2b, 0x74, 0x43, 0x23, 0x8f, 0xdd, 0x18, 0xd5, 0xa3, - 0xc2, 0x49, 0xf5, 0x6c, 0xdf, 0x4c, 0xc7, 0xd6, 0x5c, 0x8c, 0xad, 0xd9, 0xce, 0xc6, 0xb6, 0x59, - 0x56, 0x87, 0xfe, 0xf9, 0xf7, 0xc3, 0x82, 0x0d, 0x15, 0xa0, 0x9f, 0xe5, 0x5f, 0xe8, 0x74, 0xd8, - 0x03, 0xb5, 0x98, 0x93, 0x18, 0x53, 0x0f, 0x39, 0xd8, 0x43, 0x1e, 0x71, 0xa4, 0xb1, 0x99, 0x21, - 0x33, 0x5f, 0x50, 0x26, 0x62, 0x66, 0x26, 0x62, 0xb6, 0x18, 0x8d, 0x9a, 0x25, 0x85, 0xb4, 0xb7, - 0xb2, 0xc4, 0x26, 0xf6, 0xda, 0xc4, 0x91, 0xf0, 0x35, 0xa8, 0xa9, 0xd9, 0x59, 0x7d, 0x31, 0xe3, - 0x89, 0xae, 0xdb, 0xd9, 0xbf, 0xab, 0x9b, 0x3e, 0xec, 0x56, 0x88, 0x6f, 0xbb, 0x0f, 0x65, 0x38, - 0xfe, 0x50, 0x02, 0xc5, 0xc6, 0x60, 0xf0, 0x09, 0x4c, 0x67, 0x4e, 0xb8, 0x50, 0x23, 0xa8, 0x7a, - 0xa9, 0x64, 0x2f, 0x96, 0xca, 0x0a, 0xd4, 0x9b, 0x23, 0x4e, 0x04, 0xe1, 0x73, 0xa2, 0x3d, 0x29, - 0x87, 0x15, 0x28, 0x86, 0x9d, 0x22, 0xe0, 0x04, 0x3c, 0xb9, 0x4e, 0x98, 0x7c, 0x60, 0xe6, 0x33, - 0xaf, 0x4d, 0x0d, 0x59, 0x40, 0x07, 0x00, 0x88, 0x6b, 0x2e, 0x91, 0x47, 0x62, 0x39, 0xcb, 0x69, - 0x58, 0x15, 0x45, 0x68, 0x2b, 0x00, 0xfc, 0x56, 0x35, 0x04, 0x55, 0x2e, 0x9b, 0x04, 0x92, 0xc6, - 0x01, 0x25, 0x3c, 0xa7, 0x39, 0x6d, 0x6b, 0xce, 0x60, 0x89, 0x51, 0x27, 0x95, 0x4c, 0xaa, 0xf9, - 0x62, 0x91, 0x9f, 0xd3, 0x84, 0x2a, 0x9a, 0xd0, 0x67, 0x91, 0x0f, 0x47, 0xa0, 0x9a, 0xe2, 0xc4, - 0x8c, 0x71, 0x99, 0xd3, 0x70, 0xd2, 0x13, 0x4d, 0x14, 0xe1, 0xf8, 0x97, 0x12, 0x28, 0x8f, 0x99, - 0xa0, 0xda, 0x39, 0x3f, 0x07, 0x5b, 0x92, 0x63, 0x8f, 0x70, 0x84, 0x3d, 0x8f, 0x13, 0x21, 0xd2, - 0x8e, 0xb3, 0x9f, 0xa4, 0xbb, 0x8d, 0x74, 0x73, 0xd9, 0x8e, 0xeb, 0xff, 0x4d, 0x3b, 0x36, 0x41, - 0x49, 0xd0, 0x1f, 0xf2, 0x36, 0x86, 0xce, 0x85, 0x5d, 0xb0, 0x91, 0xde, 0x90, 0x39, 0x9b, 0x21, - 0xcb, 0x56, 0xdd, 0xca, 0x62, 0x12, 0xa1, 0x88, 0xa9, 0x82, 0xe0, 0x20, 0x67, 0x1b, 0x6c, 0x2a, - 0xc8, 0x30, 0x63, 0xfc, 0xc3, 0xdb, 0x70, 0xe3, 0xd3, 0xdc, 0x86, 0x2f, 0xc0, 0x7e, 0x80, 0x85, - 0x44, 0x49, 0xec, 0x61, 0x49, 0x3c, 0xe4, 0x04, 0xcc, 0xbd, 0x42, 0x51, 0x12, 0x3a, 0x84, 0xeb, - 0xfe, 0x29, 0xda, 0x4f, 0xd5, 0x03, 0xe7, 0x69, 0xbc, 0xa9, 0xc2, 0x43, 0x1d, 0x3d, 0xc6, 0x60, - 0x3b, 0x1b, 0xb8, 0x49, 0x84, 0x63, 0x31, 0x63, 0x12, 0x7e, 0x09, 0x8a, 0x38, 0x0c, 0x75, 0x5b, - 0x54, 0xcf, 0x76, 0xcc, 0x8f, 0x3f, 0xcc, 0xcc, 0xc6, 0x60, 0x90, 0xf9, 0xa4, 0x7a, 0x0a, 0x7e, - 0x06, 0x36, 0x25, 0x0d, 0x89, 0x90, 0x38, 0x8c, 0x51, 0x28, 0x74, 0xbf, 0x14, 0xed, 0xea, 0x72, - 0x6f, 0x20, 0x9e, 0x7d, 0x0d, 0x2a, 0x6d, 0xca, 0x49, 0x7a, 0xd4, 0x7d, 0xb0, 0xd7, 0xee, 0xd9, - 0x9d, 0xd6, 0xb4, 0x37, 0x1a, 0xa2, 0xf3, 0xe1, 0x64, 0xdc, 0x69, 0xf5, 0xba, 0xbd, 0x4e, 0xbb, - 0xb6, 0x06, 0xcb, 0xa0, 0xd4, 0x1f, 0x0d, 0x5f, 0xd6, 0x0a, 0xb0, 0x02, 0x1e, 0x4d, 0xbe, 0x19, - 0xd9, 0xd3, 0xda, 0xfa, 0x33, 0x1f, 0x6c, 0x4d, 0x6f, 0x70, 0xdc, 0xc2, 0x81, 0x3b, 0x8a, 0x35, - 0xe1, 0x08, 0xfc, 0x7f, 0x7a, 0xd1, 0x18, 0xa3, 0x56, 0xa3, 0xdf, 0x42, 0xa3, 0xf1, 0x5f, 0x83, - 0x26, 0xe3, 0xd1, 0xb4, 0x56, 0x80, 0xbb, 0xa0, 0xf6, 0xea, 0x7c, 0x34, 0xed, 0xa0, 0xc6, 0x64, - 0xd2, 0x99, 0xa2, 0xc9, 0x45, 0x63, 0x5c, 0x5b, 0x87, 0x3b, 0x60, 0xbb, 0xd9, 0x98, 0x7c, 0xb4, - 0x59, 0x6c, 0xbe, 0x7c, 0x7b, 0x57, 0x2f, 0xbc, 0xbb, 0xab, 0x17, 0x3e, 0xdc, 0xd5, 0x0b, 0x3f, - 0xdd, 0xd7, 0xd7, 0xde, 0xdd, 0xd7, 0xd7, 0x7e, 0xbd, 0xaf, 0xaf, 0x7d, 0xf7, 0xfc, 0xef, 0x9a, - 0x7e, 0xf1, 0x3d, 0xab, 0x7f, 0x31, 0x67, 0x43, 0x5f, 0x55, 0x5f, 0xfd, 0x19, 0x00, 0x00, 0xff, - 0xff, 0x99, 0xc0, 0xa4, 0x88, 0xee, 0x0a, 0x00, 0x00, + 0x17, 0xc7, 0xa3, 0xd8, 0x4d, 0x63, 0xda, 0x75, 0xfd, 0xa8, 0x4d, 0x1f, 0xa5, 0x18, 0x9c, 0xcc, + 0xc0, 0x86, 0xa0, 0x43, 0x24, 0x24, 0xbb, 0x2a, 0x76, 0xe5, 0xd7, 0xce, 0x80, 0xdf, 0x22, 0x3b, + 0x0b, 0x36, 0x14, 0x20, 0x28, 0x89, 0x91, 0xb9, 0x48, 0xa2, 0x42, 0x52, 0x4e, 0xba, 0x7d, 0x88, + 0xed, 0x72, 0xfb, 0x42, 0x43, 0x2f, 0x7b, 0x39, 0xec, 0xa2, 0x1b, 0x92, 0x2f, 0x32, 0x90, 0x92, + 0x1d, 0x07, 0x18, 0xb0, 0x4d, 0xe8, 0xae, 0x12, 0xf2, 0xe8, 0xfc, 0xce, 0xd1, 0xf1, 0x9f, 0x7f, + 0x0a, 0x3c, 0x8f, 0x88, 0x43, 0x58, 0x62, 0xc5, 0x98, 0xc5, 0xd6, 0xe2, 0xd8, 0xe2, 0x02, 0x09, + 0x6c, 0xc6, 0x8c, 0x0a, 0xaa, 0x57, 0xd3, 0x98, 0x29, 0x63, 0xe6, 0xe2, 0xf8, 0xf9, 0x53, 0x9f, + 0xfa, 0x54, 0x85, 0x2c, 0xf9, 0x5f, 0xfa, 0xd4, 0xf3, 0xba, 0x4b, 0x79, 0x48, 0xb9, 0xe5, 0x20, + 0x8e, 0xad, 0xc5, 0x91, 0x83, 0x05, 0x3a, 0xb2, 0x5c, 0x4a, 0xa2, 0x2c, 0xbe, 0x9b, 0xc6, 0x61, + 0x9a, 0x98, 0x2e, 0x96, 0xa9, 0x3e, 0xa5, 0x7e, 0x80, 0x2d, 0xb5, 0x72, 0x92, 0x73, 0xcb, 0x4b, + 0x18, 0x12, 0x84, 0x66, 0xa9, 0x8d, 0x1f, 0x4a, 0x60, 0x6b, 0x88, 0xd8, 0x05, 0x16, 0xfa, 0x10, + 0x14, 0x63, 0x44, 0x98, 0xa1, 0xed, 0x6b, 0x07, 0xa5, 0xd6, 0xcb, 0xb7, 0xef, 0xf7, 0x36, 0x7e, + 0x7b, 0xbf, 0x77, 0xe4, 0x13, 0x31, 0x4f, 0x1c, 0xd3, 0xa5, 0xa1, 0x35, 0x52, 0xcd, 0xb6, 0xe7, + 0x88, 0x44, 0x56, 0xf6, 0x52, 0xd7, 0x96, 0x4b, 0xc3, 0x90, 0x46, 0x16, 0xe2, 0x1c, 0x0b, 0x73, + 0x82, 0x08, 0xb3, 0x15, 0x46, 0x37, 0xc0, 0x43, 0x1c, 0x21, 0x27, 0xc0, 0x9e, 0xb1, 0xb9, 0xaf, + 0x1d, 0x6c, 0xdb, 0xcb, 0xa5, 0x8c, 0x2c, 0x30, 0xe3, 0x84, 0x46, 0x46, 0x75, 0x5f, 0x3b, 0x28, + 0xda, 0xcb, 0xa5, 0x3e, 0x07, 0x46, 0x88, 0x48, 0x24, 0x70, 0x84, 0x22, 0x17, 0xc3, 0x10, 0x31, + 0x9f, 0x44, 0x50, 0x35, 0x6c, 0x14, 0x54, 0x5b, 0x66, 0xd6, 0xd6, 0xa7, 0x6b, 0x6d, 0x65, 0xd3, + 0x49, 0xff, 0x1c, 0x72, 0xef, 0xc2, 0x12, 0x6f, 0x62, 0xcc, 0xcd, 0x0e, 0x76, 0xed, 0x67, 0x6b, + 0xbc, 0xa1, 0xc2, 0xd9, 0x92, 0xa6, 0x9f, 0x80, 0x4a, 0x88, 0xae, 0x61, 0x80, 0x17, 0x98, 0x21, + 0x1f, 0x1b, 0xc5, 0x5c, 0xf4, 0x72, 0x88, 0xae, 0x07, 0x19, 0x42, 0xff, 0x1e, 0x34, 0x02, 0x24, + 0x30, 0x17, 0xd0, 0x4d, 0xc2, 0x24, 0x40, 0x82, 0x2c, 0x30, 0x8c, 0x19, 0x0e, 0x49, 0x12, 0xc2, + 0x73, 0x86, 0x5c, 0x39, 0x76, 0xe3, 0x41, 0xae, 0x42, 0x7b, 0x29, 0xb9, 0xbd, 0x02, 0x4f, 0x52, + 0x6e, 0x2f, 0xc3, 0xea, 0xaf, 0x81, 0x8e, 0xaf, 0xdd, 0x39, 0x8a, 0x7c, 0x0c, 0xcf, 0x31, 0xce, + 0x66, 0xb6, 0x95, 0xab, 0x58, 0x6d, 0x49, 0xea, 0x61, 0x9c, 0x4e, 0xcb, 0x07, 0x06, 0x76, 0x29, + 0x7f, 0xc3, 0x05, 0x0e, 0xe1, 0x79, 0x12, 0x79, 0x6b, 0x35, 0x1e, 0xe6, 0xaa, 0xb1, 0xb3, 0xe2, + 0xf5, 0x92, 0xc8, 0x5b, 0x15, 0x72, 0xc0, 0x4e, 0x40, 0x2e, 0x13, 0xe2, 0x29, 0x8d, 0xae, 0x55, + 0xd9, 0xce, 0x55, 0xe5, 0xc9, 0x1a, 0x6c, 0x55, 0xe3, 0x5b, 0xb0, 0x1b, 0x23, 0x26, 0x08, 0x0a, + 0xe0, 0x7a, 0xad, 0xb4, 0x4e, 0x29, 0x57, 0x9d, 0xff, 0x67, 0xc0, 0xc1, 0x1d, 0x2f, 0xad, 0x75, + 0x04, 0x76, 0xe4, 0xb8, 0x48, 0xe4, 0x4b, 0x3e, 0x86, 0x38, 0xa6, 0xee, 0x1c, 0x12, 0xcf, 0x00, + 0xb2, 0x8e, 0xad, 0x67, 0x41, 0x1b, 0x09, 0xdc, 0x95, 0xa1, 0xbe, 0xa7, 0x9f, 0x82, 0xa7, 0xe2, + 0x0a, 0xc5, 0x30, 0xa0, 0xf4, 0xc2, 0x41, 0xee, 0x05, 0xbc, 0x22, 0x91, 0x47, 0xaf, 0x8c, 0xf2, + 0xbe, 0x76, 0x50, 0x3e, 0xde, 0x35, 0xd3, 0x03, 0x6d, 0x2e, 0x0f, 0xb4, 0xd9, 0xc9, 0x0e, 0x74, + 0x6b, 0x5b, 0x36, 0xfd, 0xd3, 0xef, 0x7b, 0x9a, 0xad, 0x4b, 0xc0, 0x20, 0xcb, 0x3f, 0x53, 0xe9, + 0x7a, 0x1f, 0xd4, 0x62, 0x86, 0x63, 0x44, 0x3c, 0xe8, 0x20, 0x0f, 0x7a, 0xd8, 0x11, 0x46, 0x25, + 0x43, 0x66, 0x8e, 0x21, 0xed, 0xc5, 0xcc, 0xec, 0xc5, 0x6c, 0x53, 0x12, 0xb5, 0x8a, 0x12, 0x69, + 0x57, 0xb3, 0xc4, 0x16, 0xf2, 0x3a, 0xd8, 0x11, 0xfa, 0x6b, 0x50, 0x93, 0x67, 0x67, 0xfd, 0xc5, + 0x8c, 0x47, 0x6a, 0x6e, 0xc7, 0xff, 0x6e, 0x6e, 0xaa, 0xd9, 0x6a, 0x88, 0xae, 0x7b, 0x77, 0x63, + 0x68, 0x1c, 0x82, 0xff, 0xa5, 0x86, 0x34, 0x40, 0x5c, 0x7c, 0x95, 0x19, 0xc3, 0x9a, 0x65, 0x68, + 0xf7, 0x2c, 0xa3, 0xf1, 0x4b, 0x11, 0x14, 0x9a, 0xc3, 0xe1, 0x87, 0x76, 0xaf, 0x13, 0x50, 0x91, + 0xe3, 0x80, 0x0c, 0x73, 0xcc, 0x16, 0x58, 0x59, 0x58, 0x0e, 0x7f, 0x90, 0x0c, 0x3b, 0x45, 0xe8, + 0x53, 0xf0, 0xe8, 0x32, 0xa1, 0xe2, 0x8e, 0x99, 0xcf, 0xd1, 0x2a, 0x0a, 0xb2, 0x84, 0x0e, 0x01, + 0xe0, 0x97, 0x4c, 0x40, 0x0f, 0xc7, 0x62, 0x9e, 0xd3, 0xc5, 0x4a, 0x92, 0xd0, 0x91, 0x00, 0xfd, + 0x6b, 0xa9, 0x12, 0x22, 0xad, 0x37, 0x09, 0x04, 0x89, 0x03, 0x82, 0x59, 0x4e, 0xc7, 0x7a, 0xac, + 0x38, 0xc3, 0x15, 0x46, 0x76, 0x2a, 0xa8, 0x90, 0x87, 0x8e, 0x46, 0x7e, 0x4e, 0x67, 0x2a, 0x29, + 0xc2, 0x80, 0x46, 0xbe, 0x3e, 0x06, 0xe5, 0x14, 0xc7, 0xe7, 0x94, 0x89, 0x9c, 0x2e, 0x94, 0x76, + 0x34, 0x95, 0x84, 0xc6, 0xcf, 0x45, 0xb0, 0x3d, 0xa1, 0x9c, 0x28, 0x3b, 0xfd, 0x04, 0x54, 0x05, + 0x43, 0x1e, 0x66, 0x10, 0x79, 0x1e, 0xc3, 0x9c, 0xa7, 0xba, 0xb2, 0x1f, 0xa5, 0xbb, 0xcd, 0x74, + 0x73, 0x25, 0xba, 0xcd, 0x0f, 0x23, 0xba, 0x16, 0x28, 0x72, 0xf2, 0x5d, 0x5e, 0x61, 0xa8, 0x5c, + 0xbd, 0x07, 0xb6, 0xd2, 0x6b, 0x33, 0xa7, 0x18, 0xb2, 0x6c, 0xa9, 0x56, 0x1a, 0xe3, 0x08, 0x46, + 0x54, 0x0e, 0x04, 0x05, 0x39, 0x65, 0x50, 0x91, 0x90, 0x51, 0xc6, 0xf8, 0x87, 0x57, 0xe4, 0xd6, + 0x7f, 0x73, 0x45, 0xbe, 0x04, 0xbb, 0x01, 0xe2, 0x02, 0x26, 0xb1, 0x87, 0x04, 0xf6, 0xa0, 0x13, + 0x50, 0xf7, 0x02, 0x46, 0x49, 0xe8, 0x60, 0xa6, 0xf4, 0x53, 0xb0, 0x9f, 0xc9, 0x07, 0x4e, 0xd3, + 0x78, 0x4b, 0x86, 0x47, 0x2a, 0xda, 0x40, 0xe0, 0x71, 0x76, 0xe0, 0xa6, 0x11, 0x8a, 0xf9, 0x9c, + 0x0a, 0xfd, 0x33, 0x50, 0x40, 0x61, 0xa8, 0x64, 0x51, 0x3e, 0x7e, 0x62, 0xde, 0xff, 0x8e, 0x33, + 0x9b, 0xc3, 0x61, 0x66, 0x9e, 0xf2, 0x29, 0xfd, 0x63, 0x50, 0x11, 0x24, 0xc4, 0x5c, 0xa0, 0x30, + 0x86, 0x21, 0x57, 0x7a, 0x29, 0xd8, 0xe5, 0xd5, 0xde, 0x90, 0xbf, 0xf8, 0x02, 0x94, 0x3a, 0x84, + 0xe1, 0xb4, 0xd5, 0x5d, 0xb0, 0xd3, 0xe9, 0xdb, 0xdd, 0xf6, 0xac, 0x3f, 0x1e, 0xc1, 0xd3, 0xd1, + 0x74, 0xd2, 0x6d, 0xf7, 0x7b, 0xfd, 0x6e, 0xa7, 0xb6, 0xa1, 0x6f, 0x83, 0xe2, 0x60, 0x3c, 0x7a, + 0x55, 0xd3, 0xf4, 0x12, 0x78, 0x30, 0xfd, 0x72, 0x6c, 0xcf, 0x6a, 0x9b, 0x2f, 0x7c, 0x50, 0x9d, + 0x5d, 0xa1, 0xb8, 0x8d, 0x02, 0x77, 0x1c, 0x2b, 0xc2, 0x3e, 0xf8, 0x68, 0x76, 0xd6, 0x9c, 0xc0, + 0x76, 0x73, 0xd0, 0x86, 0xe3, 0xc9, 0x5f, 0x83, 0xa6, 0x93, 0xf1, 0xac, 0xa6, 0xe9, 0x4f, 0x41, + 0xed, 0xe4, 0x74, 0x3c, 0xeb, 0xc2, 0xe6, 0x74, 0xda, 0x9d, 0xc1, 0xe9, 0x59, 0x73, 0x52, 0xdb, + 0xd4, 0x9f, 0x80, 0xc7, 0xad, 0xe6, 0xf4, 0xde, 0x66, 0xa1, 0xf5, 0xea, 0xed, 0x4d, 0x5d, 0x7b, + 0x77, 0x53, 0xd7, 0xfe, 0xb8, 0xa9, 0x6b, 0x3f, 0xde, 0xd6, 0x37, 0xde, 0xdd, 0xd6, 0x37, 0x7e, + 0xbd, 0xad, 0x6f, 0x7c, 0x73, 0xf8, 0x77, 0xa2, 0x5f, 0x7e, 0xfe, 0xaa, 0x5f, 0xcc, 0xd9, 0x52, + 0xf7, 0xd7, 0xe7, 0x7f, 0x06, 0x00, 0x00, 0xff, 0xff, 0x86, 0x95, 0x19, 0x49, 0x1d, 0x0b, 0x00, + 0x00, } func (m *Market) Marshal() (dAtA []byte, err error) { @@ -478,6 +527,11 @@ func (m *Market) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.Version != 0 { + i = encodeVarintState(dAtA, i, uint64(m.Version)) + i-- + dAtA[i] = 0x70 + } { size := m.MaxFundingRate.Size() i -= size @@ -606,7 +660,7 @@ func (m *Market) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *AMM) Marshal() (dAtA []byte, err error) { +func (m *MarketLastVersion) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -616,12 +670,12 @@ func (m *AMM) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *AMM) MarshalTo(dAtA []byte) (int, error) { +func (m *MarketLastVersion) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *AMM) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *MarketLastVersion) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -629,8 +683,31 @@ func (m *AMM) MarshalToSizedBuffer(dAtA []byte) (int, error) { if m.Version != 0 { i = encodeVarintState(dAtA, i, uint64(m.Version)) i-- - dAtA[i] = 0x40 + dAtA[i] = 0x8 } + return len(dAtA) - i, nil +} + +func (m *AMM) 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 *AMM) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *AMM) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l { size := m.TotalShort.Size() i -= size @@ -873,6 +950,21 @@ func (m *Market) Size() (n int) { n += 1 + l + sovState(uint64(l)) l = m.MaxFundingRate.Size() n += 1 + l + sovState(uint64(l)) + if m.Version != 0 { + n += 1 + sovState(uint64(m.Version)) + } + return n +} + +func (m *MarketLastVersion) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Version != 0 { + n += 1 + sovState(uint64(m.Version)) + } return n } @@ -896,9 +988,6 @@ func (m *AMM) Size() (n int) { n += 1 + l + sovState(uint64(l)) l = m.TotalShort.Size() n += 1 + l + sovState(uint64(l)) - if m.Version != 0 { - n += 1 + sovState(uint64(m.Version)) - } return n } @@ -1401,6 +1490,94 @@ func (m *Market) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 14: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType) + } + m.Version = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowState + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Version |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipState(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthState + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MarketLastVersion) 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 ErrIntOverflowState + } + 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: MarketLastVersion: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MarketLastVersion: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType) + } + m.Version = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowState + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Version |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipState(dAtA[iNdEx:]) @@ -1689,25 +1866,6 @@ func (m *AMM) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 8: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType) - } - m.Version = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowState - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Version |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } default: iNdEx = preIndex skippy, err := skipState(dAtA[iNdEx:]) diff --git a/x/wasm/binding/exec_perp_test.go b/x/wasm/binding/exec_perp_test.go index 7d854432a..07d2425f2 100644 --- a/x/wasm/binding/exec_perp_test.go +++ b/x/wasm/binding/exec_perp_test.go @@ -324,7 +324,7 @@ func (s *TestSuitePerpExecutor) DoSetMarketEnabledTest( return err } - market, err := s.nibiru.PerpKeeperV2.Markets.Get(s.ctx, pair) + market, err := s.nibiru.PerpKeeperV2.GetMarket(s.ctx, pair) s.NoError(err) s.Equal(enabled, market.Enabled) return err diff --git a/x/wasm/binding/exec_test.go b/x/wasm/binding/exec_test.go index 42658ba81..460e3973d 100644 --- a/x/wasm/binding/exec_test.go +++ b/x/wasm/binding/exec_test.go @@ -511,7 +511,7 @@ func (s *TestSuiteExecutor) TestSetMarketEnabled() { contractRespBz, err := s.ExecuteAgainstContract(contract, execMsg) s.NoErrorf(err, "contractRespBz: %s", contractRespBz) - marketAfter, err := s.nibiru.PerpKeeperV2.Markets.Get(s.ctx, market.Pair) + marketAfter, err := s.nibiru.PerpKeeperV2.GetMarket(s.ctx, market.Pair) s.NoError(err) s.Equal(!market.Enabled, marketAfter.Enabled) } @@ -552,7 +552,7 @@ func (s *TestSuiteExecutor) TestCreateMarket() { contractRespBz, err := s.ExecuteAgainstContract(contract, execMsg) s.NoErrorf(err, "contractRespBz: %s", contractRespBz) - market, err := s.nibiru.PerpKeeperV2.Markets.Get(s.ctx, pair) + market, err := s.nibiru.PerpKeeperV2.GetMarket(s.ctx, pair) s.NoError(err) s.NoError(market.Validate()) s.True(market.Enabled) From ccf45db5866a6bf180a0cb91a50d0cd6f1a89882 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Wed, 30 Aug 2023 17:05:14 +0200 Subject: [PATCH 03/16] make test pass --- proto/nibiru/perp/v2/genesis.proto | 13 + x/common/asset/pair.go | 2 +- x/common/testutil/genesis/perp_genesis.go | 25 +- x/common/testutil/mock/perp_market.go | 1 + x/perp/v2/keeper/admin.go | 1 + x/perp/v2/keeper/clearing_house_test.go | 3 +- x/perp/v2/module/genesis.go | 4 + x/perp/v2/types/genesis.go | 1 + x/perp/v2/types/genesis.pb.go | 323 ++++++++++++++++++++-- x/wasm/binding/cw_struct/cw_query.go | 5 +- x/wasm/binding/querier.go | 13 +- x/wasm/binding/querier_perp_test.go | 10 - x/wasm/binding/querier_test.go | 3 - x/wasm/binding/wasmbin/bindings_perp.wasm | Bin 345884 -> 347370 bytes 14 files changed, 350 insertions(+), 54 deletions(-) diff --git a/proto/nibiru/perp/v2/genesis.proto b/proto/nibiru/perp/v2/genesis.proto index 898cbb076..241e2b91c 100644 --- a/proto/nibiru/perp/v2/genesis.proto +++ b/proto/nibiru/perp/v2/genesis.proto @@ -13,6 +13,8 @@ option go_package = "github.com/NibiruChain/nibiru/x/perp/v2/types"; message GenesisState { repeated Market markets = 2 [ (gogoproto.nullable) = false ]; + repeated GenesisMarketLastVersion market_last_versions = 6 [ (gogoproto.nullable) = false ]; + repeated AMM amms = 3 [ (gogoproto.nullable) = false ]; repeated Position positions = 4 [ (gogoproto.nullable) = false ]; @@ -20,3 +22,14 @@ message GenesisState { repeated ReserveSnapshot reserve_snapshots = 5 [ (gogoproto.nullable) = false ]; } + +// GenesisMarketLastVersion is the last version including pair only used for genesis +message GenesisMarketLastVersion { + string pair = 1 [ + (gogoproto.customtype) = + "github.com/NibiruChain/nibiru/x/common/asset.Pair", + (gogoproto.nullable) = false + ]; + + uint64 version = 2; +} \ No newline at end of file diff --git a/x/common/asset/pair.go b/x/common/asset/pair.go index 087956b6d..ee7a830d4 100644 --- a/x/common/asset/pair.go +++ b/x/common/asset/pair.go @@ -23,7 +23,7 @@ func NewPair(base string, quote string) Pair { return Pair(ap) } -// New returns a new asset pair instance if the pair is valid. +// TryNewPair New returns a new asset pair instance if the pair is valid. // The form, "token0:token1", is expected for 'pair'. // Use this function to return an error instead of panicking. func TryNewPair(pair string) (Pair, error) { diff --git a/x/common/testutil/genesis/perp_genesis.go b/x/common/testutil/genesis/perp_genesis.go index 996d5d503..655985caf 100644 --- a/x/common/testutil/genesis/perp_genesis.go +++ b/x/common/testutil/genesis/perp_genesis.go @@ -22,6 +22,7 @@ func AddPerpV2Genesis(gen app.GenesisState) app.GenesisState { asset.Registry.Pair(denoms.BTC, denoms.NUSD): { Market: perpv2types.Market{ Pair: asset.NewPair(denoms.BTC, denoms.NUSD), + Version: 1, Enabled: true, MaintenanceMarginRatio: sdk.MustNewDecFromStr("0.04"), MaxLeverage: sdk.MustNewDecFromStr("20"), @@ -49,6 +50,7 @@ func AddPerpV2Genesis(gen app.GenesisState) app.GenesisState { Market: perpv2types.Market{ Pair: asset.NewPair(denoms.ATOM, denoms.NUSD), Enabled: true, + Version: 1, MaintenanceMarginRatio: sdk.MustNewDecFromStr("0.0625"), MaxLeverage: sdk.MustNewDecFromStr("15"), ExchangeFeeRatio: sdk.MustNewDecFromStr("0.0010"), @@ -75,6 +77,7 @@ func AddPerpV2Genesis(gen app.GenesisState) app.GenesisState { Market: perpv2types.Market{ Pair: asset.NewPair(denoms.OSMO, denoms.NUSD), Enabled: true, + Version: 1, MaintenanceMarginRatio: sdk.MustNewDecFromStr("0.0625"), MaxLeverage: sdk.MustNewDecFromStr("15"), ExchangeFeeRatio: sdk.MustNewDecFromStr("0.0010"), @@ -104,16 +107,22 @@ func AddPerpV2Genesis(gen app.GenesisState) app.GenesisState { var marketsv2 []perpv2types.Market var ammsv2 []perpv2types.AMM + var marketLastVersions []perpv2types.GenesisMarketLastVersion for _, marketAmm := range extraMarketAmms { marketsv2 = append(marketsv2, marketAmm.Market) ammsv2 = append(ammsv2, marketAmm.Amm) + marketLastVersions = append(marketLastVersions, perpv2types.GenesisMarketLastVersion{ + Pair: marketAmm.Market.Pair, + Version: marketAmm.Market.Version, + }) } perpV2Gen := &perpv2types.GenesisState{ - Markets: marketsv2, - Amms: ammsv2, - Positions: []perpv2types.Position{}, - ReserveSnapshots: []perpv2types.ReserveSnapshot{}, + Markets: marketsv2, + MarketLastVersions: marketLastVersions, + Amms: ammsv2, + Positions: []perpv2types.Position{}, + ReserveSnapshots: []perpv2types.ReserveSnapshot{}, } gen[perpv2types.ModuleName] = TEST_ENCODING_CONFIG.Marshaler. @@ -126,6 +135,7 @@ var START_MARKETS = map[asset.Pair]perpv2types.AmmMarket{ Market: perpv2types.Market{ Pair: asset.Registry.Pair(denoms.ETH, denoms.NUSD), Enabled: true, + Version: 1, MaintenanceMarginRatio: sdk.MustNewDecFromStr("0.0625"), MaxLeverage: sdk.MustNewDecFromStr("15"), LatestCumulativePremiumFraction: sdk.ZeroDec(), @@ -152,6 +162,7 @@ var START_MARKETS = map[asset.Pair]perpv2types.AmmMarket{ Market: perpv2types.Market{ Pair: asset.Registry.Pair(denoms.NIBI, denoms.NUSD), Enabled: true, + Version: 1, MaintenanceMarginRatio: sdk.MustNewDecFromStr("0.04"), MaxLeverage: sdk.MustNewDecFromStr("20"), LatestCumulativePremiumFraction: sdk.ZeroDec(), @@ -195,6 +206,12 @@ func PerpV2Genesis() *perpv2types.GenesisState { PrepaidBadDebt: sdk.NewCoin(denoms.NUSD, sdk.ZeroInt()), }, }, + MarketLastVersions: []perpv2types.GenesisMarketLastVersion{ + { + Pair: asset.Registry.Pair(denoms.BTC, denoms.NUSD), + Version: 1, + }, + }, Amms: []perpv2types.AMM{ { Pair: asset.Registry.Pair(denoms.BTC, denoms.NUSD), diff --git a/x/common/testutil/mock/perp_market.go b/x/common/testutil/mock/perp_market.go index f57e07a23..4c5d4de48 100644 --- a/x/common/testutil/mock/perp_market.go +++ b/x/common/testutil/mock/perp_market.go @@ -15,6 +15,7 @@ func TestMarket() *types.Market { return &types.Market{ Pair: asset.NewPair(denoms.BTC, denoms.NUSD), Enabled: true, + Version: 1, MaintenanceMarginRatio: sdk.MustNewDecFromStr("0.0625"), MaxLeverage: sdk.MustNewDecFromStr("10"), LatestCumulativePremiumFraction: sdk.ZeroDec(), diff --git a/x/perp/v2/keeper/admin.go b/x/perp/v2/keeper/admin.go index 6c05a7b18..85f50346f 100644 --- a/x/perp/v2/keeper/admin.go +++ b/x/perp/v2/keeper/admin.go @@ -105,6 +105,7 @@ func (k admin) CreateMarket( } lastVersion := k.MarketLastVersion.GetOr(ctx, pair, types.MarketLastVersion{Version: 1}) + market.Version = lastVersion.Version k.Markets.Insert(ctx, collections.Join(pair, lastVersion.Version), market) k.MarketLastVersion.Insert(ctx, pair, lastVersion) diff --git a/x/perp/v2/keeper/clearing_house_test.go b/x/perp/v2/keeper/clearing_house_test.go index 52a6ed032..63094afd3 100644 --- a/x/perp/v2/keeper/clearing_house_test.go +++ b/x/perp/v2/keeper/clearing_house_test.go @@ -1172,7 +1172,8 @@ func TestMarketOrderError(t *testing.T) { traderAddr := testutil.AccAddress() market := mock.TestMarket() - app.PerpKeeperV2.Markets.Insert(ctx, collections.Join(asset.Registry.Pair(denoms.BTC, denoms.NUSD), uint64(1)), *market) + app.PerpKeeperV2.Markets.Insert(ctx, collections.Join(asset.Registry.Pair(denoms.BTC, denoms.NUSD), market.Version), *market) + app.PerpKeeperV2.MarketLastVersion.Insert(ctx, asset.Registry.Pair(denoms.BTC, denoms.NUSD), types.MarketLastVersion{Version: market.Version}) amm := mock.TestAMMDefault() app.PerpKeeperV2.AMMs.Insert(ctx, amm.Pair, *amm) app.PerpKeeperV2.ReserveSnapshots.Insert(ctx, collections.Join(amm.Pair, ctx.BlockTime()), types.ReserveSnapshot{ diff --git a/x/perp/v2/module/genesis.go b/x/perp/v2/module/genesis.go index 3bea511f3..c855da9fb 100644 --- a/x/perp/v2/module/genesis.go +++ b/x/perp/v2/module/genesis.go @@ -24,6 +24,10 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState) k.Markets.Insert(ctx, collections.Join(m.Pair, m.Version), m) } + for _, g := range genState.MarketLastVersions { + k.MarketLastVersion.Insert(ctx, g.Pair, types.MarketLastVersion{Version: g.Version}) + } + for _, a := range genState.Amms { pair := a.Pair k.AMMs.Insert(ctx, pair, a) diff --git a/x/perp/v2/types/genesis.go b/x/perp/v2/types/genesis.go index 9ac35539e..1316be0ff 100644 --- a/x/perp/v2/types/genesis.go +++ b/x/perp/v2/types/genesis.go @@ -52,6 +52,7 @@ func DefaultMarket(pair asset.Pair) Market { return Market{ Pair: pair, Enabled: true, + Version: 1, LatestCumulativePremiumFraction: sdk.ZeroDec(), ExchangeFeeRatio: sdk.MustNewDecFromStr("0.0010"), EcosystemFundFeeRatio: sdk.MustNewDecFromStr("0.0010"), diff --git a/x/perp/v2/types/genesis.pb.go b/x/perp/v2/types/genesis.pb.go index 129d6d451..548bceddc 100644 --- a/x/perp/v2/types/genesis.pb.go +++ b/x/perp/v2/types/genesis.pb.go @@ -5,6 +5,7 @@ package types import ( fmt "fmt" + github_com_NibiruChain_nibiru_x_common_asset "github.com/NibiruChain/nibiru/x/common/asset" _ "github.com/cosmos/cosmos-sdk/types" _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" @@ -27,10 +28,11 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package // GenesisState defines the perp module's genesis state. type GenesisState struct { - Markets []Market `protobuf:"bytes,2,rep,name=markets,proto3" json:"markets"` - Amms []AMM `protobuf:"bytes,3,rep,name=amms,proto3" json:"amms"` - Positions []Position `protobuf:"bytes,4,rep,name=positions,proto3" json:"positions"` - ReserveSnapshots []ReserveSnapshot `protobuf:"bytes,5,rep,name=reserve_snapshots,json=reserveSnapshots,proto3" json:"reserve_snapshots"` + Markets []Market `protobuf:"bytes,2,rep,name=markets,proto3" json:"markets"` + MarketLastVersions []GenesisMarketLastVersion `protobuf:"bytes,6,rep,name=market_last_versions,json=marketLastVersions,proto3" json:"market_last_versions"` + Amms []AMM `protobuf:"bytes,3,rep,name=amms,proto3" json:"amms"` + Positions []Position `protobuf:"bytes,4,rep,name=positions,proto3" json:"positions"` + ReserveSnapshots []ReserveSnapshot `protobuf:"bytes,5,rep,name=reserve_snapshots,json=reserveSnapshots,proto3" json:"reserve_snapshots"` } func (m *GenesisState) Reset() { *m = GenesisState{} } @@ -73,6 +75,13 @@ func (m *GenesisState) GetMarkets() []Market { return nil } +func (m *GenesisState) GetMarketLastVersions() []GenesisMarketLastVersion { + if m != nil { + return m.MarketLastVersions + } + return nil +} + func (m *GenesisState) GetAmms() []AMM { if m != nil { return m.Amms @@ -94,35 +103,88 @@ func (m *GenesisState) GetReserveSnapshots() []ReserveSnapshot { return nil } +// GenesisMarketLastVersion is the last version including pair only used for genesis +type GenesisMarketLastVersion struct { + Pair github_com_NibiruChain_nibiru_x_common_asset.Pair `protobuf:"bytes,1,opt,name=pair,proto3,customtype=github.com/NibiruChain/nibiru/x/common/asset.Pair" json:"pair"` + Version uint64 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"` +} + +func (m *GenesisMarketLastVersion) Reset() { *m = GenesisMarketLastVersion{} } +func (m *GenesisMarketLastVersion) String() string { return proto.CompactTextString(m) } +func (*GenesisMarketLastVersion) ProtoMessage() {} +func (*GenesisMarketLastVersion) Descriptor() ([]byte, []int) { + return fileDescriptor_c2c7acfef3993fde, []int{1} +} +func (m *GenesisMarketLastVersion) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GenesisMarketLastVersion) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GenesisMarketLastVersion.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 *GenesisMarketLastVersion) XXX_Merge(src proto.Message) { + xxx_messageInfo_GenesisMarketLastVersion.Merge(m, src) +} +func (m *GenesisMarketLastVersion) XXX_Size() int { + return m.Size() +} +func (m *GenesisMarketLastVersion) XXX_DiscardUnknown() { + xxx_messageInfo_GenesisMarketLastVersion.DiscardUnknown(m) +} + +var xxx_messageInfo_GenesisMarketLastVersion proto.InternalMessageInfo + +func (m *GenesisMarketLastVersion) GetVersion() uint64 { + if m != nil { + return m.Version + } + return 0 +} + func init() { proto.RegisterType((*GenesisState)(nil), "nibiru.perp.v2.GenesisState") + proto.RegisterType((*GenesisMarketLastVersion)(nil), "nibiru.perp.v2.GenesisMarketLastVersion") } func init() { proto.RegisterFile("nibiru/perp/v2/genesis.proto", fileDescriptor_c2c7acfef3993fde) } var fileDescriptor_c2c7acfef3993fde = []byte{ - // 326 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x5c, 0x90, 0xcd, 0x4a, 0x33, 0x31, - 0x14, 0x86, 0xa7, 0x3f, 0xdf, 0x27, 0x8e, 0x22, 0x3a, 0x8a, 0x0c, 0x43, 0x49, 0xc5, 0x95, 0x9b, - 0x4e, 0x68, 0x05, 0x57, 0x6e, 0xac, 0x8b, 0xae, 0x2a, 0xd2, 0xee, 0xdc, 0x48, 0xa6, 0x84, 0x34, - 0xe8, 0xe4, 0x84, 0x9c, 0x74, 0xd0, 0x2b, 0x70, 0xeb, 0x65, 0x75, 0xd9, 0xa5, 0x2b, 0x91, 0xf6, - 0x46, 0x64, 0x32, 0x51, 0xe9, 0xec, 0xc2, 0x79, 0x9f, 0xe7, 0xe5, 0xe4, 0x84, 0x1d, 0x25, 0x33, - 0x69, 0x16, 0x54, 0x73, 0xa3, 0x69, 0x31, 0xa0, 0x82, 0x2b, 0x8e, 0x12, 0x53, 0x6d, 0xc0, 0x42, - 0x74, 0x50, 0xa5, 0x69, 0x99, 0xa6, 0xc5, 0x20, 0x39, 0x11, 0x20, 0xc0, 0x45, 0xb4, 0x7c, 0x55, - 0x54, 0xd2, 0x11, 0x00, 0xe2, 0x99, 0x53, 0xa6, 0x25, 0x65, 0x4a, 0x81, 0x65, 0x56, 0x82, 0xf2, - 0x1d, 0x09, 0x99, 0x01, 0xe6, 0x80, 0x34, 0x63, 0xc8, 0x69, 0xd1, 0xcf, 0xb8, 0x65, 0x7d, 0x3a, - 0x03, 0xa9, 0x7c, 0x9e, 0xd4, 0x36, 0x40, 0xcb, 0x2c, 0xaf, 0xb2, 0xf3, 0xb7, 0x66, 0xb8, 0x3f, - 0xaa, 0x36, 0x9a, 0x96, 0xe3, 0xe8, 0x2a, 0xdc, 0xc9, 0x99, 0x79, 0xe2, 0x16, 0xe3, 0xe6, 0x59, - 0xeb, 0x62, 0x6f, 0x70, 0x9a, 0x6e, 0xaf, 0x98, 0x8e, 0x5d, 0x3c, 0x6c, 0x2f, 0x3f, 0xbb, 0xc1, - 0xe4, 0x07, 0x8e, 0x7a, 0x61, 0x9b, 0xe5, 0x39, 0xc6, 0x2d, 0x27, 0x1d, 0xd7, 0xa5, 0x9b, 0xf1, - 0xd8, 0x1b, 0x0e, 0x8b, 0xae, 0xc3, 0x5d, 0x0d, 0x28, 0xdd, 0x37, 0xe2, 0xb6, 0x73, 0xe2, 0xba, - 0x73, 0xef, 0x01, 0x2f, 0xfe, 0x09, 0xd1, 0x24, 0x3c, 0x32, 0x1c, 0xb9, 0x29, 0xf8, 0x23, 0x2a, - 0xa6, 0x71, 0x0e, 0x16, 0xe3, 0x7f, 0xae, 0xa5, 0x5b, 0x6f, 0x99, 0x54, 0xe0, 0xd4, 0x73, 0xbe, - 0xec, 0xd0, 0x6c, 0x8f, 0x71, 0x38, 0x5a, 0xae, 0x49, 0x63, 0xb5, 0x26, 0x8d, 0xaf, 0x35, 0x69, - 0xbc, 0x6f, 0x48, 0xb0, 0xda, 0x90, 0xe0, 0x63, 0x43, 0x82, 0x87, 0x9e, 0x90, 0x76, 0xbe, 0xc8, - 0xd2, 0x19, 0xe4, 0xf4, 0xce, 0x95, 0xdf, 0xce, 0x99, 0x54, 0xd4, 0x9f, 0xf5, 0xe5, 0xf7, 0xb0, - 0xf6, 0x55, 0x73, 0xcc, 0xfe, 0xbb, 0xcb, 0x5e, 0x7e, 0x07, 0x00, 0x00, 0xff, 0xff, 0x13, 0x97, - 0x6b, 0x44, 0xf9, 0x01, 0x00, 0x00, + // 426 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x92, 0x41, 0x6b, 0x14, 0x31, + 0x1c, 0xc5, 0x77, 0xb6, 0x63, 0x4b, 0xa3, 0x88, 0xc6, 0x22, 0x61, 0x29, 0xb3, 0x4b, 0x4f, 0x7b, + 0xe9, 0x84, 0x5d, 0x41, 0x10, 0xbc, 0xb8, 0x1e, 0x7a, 0x71, 0xa5, 0x4c, 0xc1, 0x83, 0x97, 0x35, + 0x33, 0x84, 0xd9, 0x60, 0x27, 0xff, 0x90, 0x7f, 0x3a, 0xe8, 0xd9, 0x2f, 0xe0, 0xc7, 0xea, 0xb1, + 0x47, 0xf1, 0x50, 0x64, 0xf7, 0xe4, 0xb7, 0x90, 0x49, 0xb2, 0xc8, 0x0e, 0x88, 0xb7, 0x4c, 0xde, + 0x7b, 0xbf, 0xff, 0x9b, 0x24, 0xe4, 0x54, 0xab, 0x52, 0xd9, 0x1b, 0x6e, 0xa4, 0x35, 0xbc, 0x9d, + 0xf3, 0x5a, 0x6a, 0x89, 0x0a, 0x73, 0x63, 0xc1, 0x01, 0x7d, 0x1c, 0xd4, 0xbc, 0x53, 0xf3, 0x76, + 0x3e, 0x3a, 0xa9, 0xa1, 0x06, 0x2f, 0xf1, 0x6e, 0x15, 0x5c, 0xa3, 0xd3, 0x1a, 0xa0, 0xbe, 0x96, + 0x5c, 0x18, 0xc5, 0x85, 0xd6, 0xe0, 0x84, 0x53, 0xa0, 0x23, 0x63, 0x94, 0x55, 0x80, 0x0d, 0x20, + 0x2f, 0x05, 0x4a, 0xde, 0xce, 0x4a, 0xe9, 0xc4, 0x8c, 0x57, 0xa0, 0x74, 0xd4, 0x47, 0xbd, 0x06, + 0xe8, 0x84, 0x93, 0x41, 0x3b, 0xfb, 0x3d, 0x24, 0x8f, 0x2e, 0x42, 0xa3, 0xab, 0x6e, 0x9b, 0xbe, + 0x24, 0x47, 0x8d, 0xb0, 0x9f, 0xa5, 0x43, 0x36, 0x9c, 0x1c, 0x4c, 0x1f, 0xce, 0x9f, 0xe7, 0xfb, + 0x15, 0xf3, 0xa5, 0x97, 0x17, 0xe9, 0xed, 0xfd, 0x78, 0x50, 0xec, 0xcc, 0xf4, 0x13, 0x39, 0x09, + 0xcb, 0xd5, 0xb5, 0x40, 0xb7, 0x6a, 0xa5, 0xc5, 0xae, 0x22, 0x3b, 0xf4, 0x90, 0x69, 0x1f, 0x12, + 0x67, 0x06, 0xd6, 0x3b, 0x81, 0xee, 0x43, 0x08, 0x44, 0x2c, 0x6d, 0xfa, 0x02, 0xd2, 0x73, 0x92, + 0x8a, 0xa6, 0x41, 0x76, 0xe0, 0x89, 0xcf, 0xfa, 0xc4, 0x37, 0xcb, 0x65, 0x0c, 0x7b, 0x1b, 0x7d, + 0x4d, 0x8e, 0x0d, 0xa0, 0xf2, 0x07, 0xc5, 0x52, 0x9f, 0x61, 0xfd, 0xcc, 0x65, 0x34, 0xc4, 0xe0, + 0xdf, 0x00, 0x2d, 0xc8, 0x53, 0x2b, 0x51, 0xda, 0x56, 0xae, 0x50, 0x0b, 0x83, 0x6b, 0x70, 0xc8, + 0x1e, 0x78, 0xca, 0xb8, 0x4f, 0x29, 0x82, 0xf1, 0x2a, 0xfa, 0x22, 0xec, 0x89, 0xdd, 0xdf, 0xc6, + 0xb3, 0x6f, 0x09, 0x61, 0xff, 0xfa, 0x6f, 0xba, 0x24, 0xa9, 0x11, 0xca, 0xb2, 0x64, 0x92, 0x4c, + 0x8f, 0x17, 0xaf, 0x3a, 0xc4, 0xcf, 0xfb, 0xf1, 0xac, 0x56, 0x6e, 0x7d, 0x53, 0xe6, 0x15, 0x34, + 0xfc, 0xbd, 0x9f, 0xfa, 0x76, 0x2d, 0x94, 0xe6, 0xf1, 0x46, 0xbf, 0xf0, 0x0a, 0x9a, 0x06, 0x34, + 0x17, 0x88, 0xd2, 0xe5, 0x97, 0x42, 0xd9, 0xc2, 0x63, 0x28, 0x23, 0x47, 0xf1, 0x0a, 0xd8, 0x70, + 0x92, 0x4c, 0xd3, 0x62, 0xf7, 0xb9, 0xb8, 0xb8, 0xdd, 0x64, 0xc9, 0xdd, 0x26, 0x4b, 0x7e, 0x6d, + 0xb2, 0xe4, 0xfb, 0x36, 0x1b, 0xdc, 0x6d, 0xb3, 0xc1, 0x8f, 0x6d, 0x36, 0xf8, 0x78, 0xfe, 0xbf, + 0x61, 0xbb, 0x07, 0xe4, 0xbe, 0x1a, 0x89, 0xe5, 0xa1, 0x7f, 0x41, 0x2f, 0xfe, 0x04, 0x00, 0x00, + 0xff, 0xff, 0x1f, 0xfa, 0x69, 0x28, 0xe1, 0x02, 0x00, 0x00, } func (m *GenesisState) Marshal() (dAtA []byte, err error) { @@ -145,6 +207,20 @@ func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.MarketLastVersions) > 0 { + for iNdEx := len(m.MarketLastVersions) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.MarketLastVersions[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + } + } if len(m.ReserveSnapshots) > 0 { for iNdEx := len(m.ReserveSnapshots) - 1; iNdEx >= 0; iNdEx-- { { @@ -204,6 +280,44 @@ func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *GenesisMarketLastVersion) 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 *GenesisMarketLastVersion) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GenesisMarketLastVersion) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Version != 0 { + i = encodeVarintGenesis(dAtA, i, uint64(m.Version)) + i-- + dAtA[i] = 0x10 + } + { + size := m.Pair.Size() + i -= size + if _, err := m.Pair.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int { offset -= sovGenesis(v) base := offset @@ -245,6 +359,26 @@ func (m *GenesisState) Size() (n int) { n += 1 + l + sovGenesis(uint64(l)) } } + if len(m.MarketLastVersions) > 0 { + for _, e := range m.MarketLastVersions { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + return n +} + +func (m *GenesisMarketLastVersion) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Pair.Size() + n += 1 + l + sovGenesis(uint64(l)) + if m.Version != 0 { + n += 1 + sovGenesis(uint64(m.Version)) + } return n } @@ -419,6 +553,143 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MarketLastVersions", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.MarketLastVersions = append(m.MarketLastVersions, GenesisMarketLastVersion{}) + if err := m.MarketLastVersions[len(m.MarketLastVersions)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GenesisMarketLastVersion) 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 ErrIntOverflowGenesis + } + 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: GenesisMarketLastVersion: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GenesisMarketLastVersion: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pair", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + 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 ErrInvalidLengthGenesis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Pair.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType) + } + m.Version = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Version |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipGenesis(dAtA[iNdEx:]) diff --git a/x/wasm/binding/cw_struct/cw_query.go b/x/wasm/binding/cw_struct/cw_query.go index 39fb7bc32..e7bcc716e 100644 --- a/x/wasm/binding/cw_struct/cw_query.go +++ b/x/wasm/binding/cw_struct/cw_query.go @@ -59,6 +59,7 @@ type AllMarketsResponse struct { type Market struct { Pair string `json:"pair"` + Version sdkmath.Int `json:"version"` BaseReserve sdk.Dec `json:"base_reserve"` QuoteReserve sdk.Dec `json:"quote_reserve"` SqrtDepth sdk.Dec `json:"sqrt_depth"` @@ -73,7 +74,7 @@ type Market struct { BlockNumber sdkmath.Int `json:"block_number"` } -// Converts the JSON market, which comes in from Rust, to its corresponding +// ToAppMarket Converts the JSON market, which comes in from Rust, to its corresponding // protobuf (Golang) type in the app: perpv2types.Market. func (m Market) ToAppMarket() (appMarket perpv2types.Market, err error) { config := m.Config @@ -84,6 +85,7 @@ func (m Market) ToAppMarket() (appMarket perpv2types.Market, err error) { return perpv2types.Market{ Pair: pair, Enabled: true, + Version: m.Version.Uint64(), MaintenanceMarginRatio: config.MaintenanceMarginRatio, MaxLeverage: config.MaxLeverage, LatestCumulativePremiumFraction: sdk.ZeroDec(), @@ -101,6 +103,7 @@ func (m Market) ToAppMarket() (appMarket perpv2types.Market, err error) { func NewMarket(appMarket perpv2types.Market, appAmm perpv2types.AMM, indexPrice, twapMark string, blockNumber int64) Market { return Market{ Pair: appMarket.Pair.String(), + Version: sdk.NewIntFromUint64(appMarket.Version), BaseReserve: appAmm.BaseReserve, QuoteReserve: appAmm.QuoteReserve, SqrtDepth: appAmm.SqrtDepth, diff --git a/x/wasm/binding/querier.go b/x/wasm/binding/querier.go index a80caaf58..90bf223fe 100644 --- a/x/wasm/binding/querier.go +++ b/x/wasm/binding/querier.go @@ -159,24 +159,21 @@ func (perpExt *PerpQuerier) AllMarkets( marketMap := make(map[string]cw_struct.Market) for _, pbMarket := range sdkResp.AmmMarkets { - // pbPrice := sdkResp.Prices[idx] key := pbMarket.Amm.Pair.String() marketMap[key] = cw_struct.Market{ Pair: key, + Version: sdk.NewIntFromUint64(pbMarket.Market.Version), BaseReserve: pbMarket.Amm.BaseReserve, QuoteReserve: pbMarket.Amm.QuoteReserve, SqrtDepth: pbMarket.Amm.SqrtDepth, - // Depth: pbPrice.SwapInvariant, - TotalLong: pbMarket.Amm.TotalLong, - TotalShort: pbMarket.Amm.TotalShort, - PegMult: pbMarket.Amm.PriceMultiplier, + TotalLong: pbMarket.Amm.TotalLong, + TotalShort: pbMarket.Amm.TotalShort, + PegMult: pbMarket.Amm.PriceMultiplier, Config: &cw_struct.MarketConfig{ MaintenanceMarginRatio: pbMarket.Market.MaintenanceMarginRatio, MaxLeverage: pbMarket.Market.MaxLeverage, }, - MarkPrice: pbMarket.Amm.MarkPrice(), - // IndexPrice: pbPrice.IndexPrice, - // TwapMark: pbPrice.TwapMark, + MarkPrice: pbMarket.Amm.MarkPrice(), BlockNumber: sdk.NewInt(ctx.BlockHeight()), } } diff --git a/x/wasm/binding/querier_perp_test.go b/x/wasm/binding/querier_perp_test.go index 8f19d1239..31324691c 100644 --- a/x/wasm/binding/querier_perp_test.go +++ b/x/wasm/binding/querier_perp_test.go @@ -169,7 +169,6 @@ func (s *TestSuitePerpQuerier) TestAllMarkets() { marketMap := make(CwMarketMap) for pair, ammMarket := range genesis.START_MARKETS { - // rate := s.ratesMap[pair] cwMarket := cw_struct.NewMarket( ammMarket.Market, ammMarket.Amm, @@ -186,12 +185,10 @@ func (s *TestSuitePerpQuerier) TestAllMarkets() { } testCases := map[string]struct { - cwReq *cw_struct.AllMarketsRequest marketMap CwMarketMap expectErr bool }{ "happy": { - cwReq: &cw_struct.AllMarketsRequest{}, marketMap: marketMap, expectErr: false, }, @@ -250,13 +247,6 @@ func (s *TestSuitePerpQuerier) TestModuleParams() { cwResp, err := s.queryPlugin.Perp.ModuleParams(s.ctx, cwReq) s.Errorf(err, "\ncwResp: %s", cwResp) s.Nil(cwResp) - - // jsonBz, err := json.Marshal(cwResp) - // s.NoErrorf(err, "jsonBz: %s", jsonBz) - - // freshCwResp := new(cw_struct.PerpParamsResponse) - // err = json.Unmarshal(jsonBz, freshCwResp) - // s.NoErrorf(err, "freshCwResp: %s", freshCwResp) } func (s *TestSuitePerpQuerier) TestPosition() { diff --git a/x/wasm/binding/querier_test.go b/x/wasm/binding/querier_test.go index 8fd160d16..0c3d2005b 100644 --- a/x/wasm/binding/querier_test.go +++ b/x/wasm/binding/querier_test.go @@ -211,9 +211,6 @@ func (s *TestSuiteQuerier) TestQueryAllMarkets() { s.Assert().EqualValues(marketAmm.Amm.BaseReserve, cwMarket.BaseReserve) s.Assert().EqualValues(marketAmm.Amm.QuoteReserve, cwMarket.QuoteReserve) s.Assert().EqualValues(marketAmm.Amm.SqrtDepth, cwMarket.SqrtDepth) - // s.Assert().EqualValues( - // marketAmm.Amm.BaseReserve.Mul(marketAmm.Amm.QuoteReserve).String(), - // cwMarket.Depth.ToDec().String()) s.Assert().EqualValues(marketAmm.Amm.TotalLong, cwMarket.TotalLong) s.Assert().EqualValues(marketAmm.Amm.TotalShort, cwMarket.TotalShort) s.Assert().EqualValues(marketAmm.Amm.PriceMultiplier.String(), cwMarket.PegMult.String()) diff --git a/x/wasm/binding/wasmbin/bindings_perp.wasm b/x/wasm/binding/wasmbin/bindings_perp.wasm index f89abbccc7e2e57ddcf48a34fdfea6756bbce992..4d20de3af5113272b30b6691be280a3c34abe1d8 100644 GIT binary patch literal 347370 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%0Dy)+%848 zxg#F`J`MUF;vsVRK)=%E!G2$thx!A(bE4HJX1}!C*vKf}G1$TG!_BUK>rm0(3B(nk zFETWve1Lob=zrUSxG<``O<%!mSs~RO9hSc${C$~Q?xqyPR{kM{f^i}aj}ND1aUCCa z6Gg2HvW>wSuWs+^k_tc@MMUJx({QeDVlZA^aYM1`=3+`U9a9rms6MXC{T5|t7_T4_ zr~G+s#%S?W_J?S-Uct&j8|sy1h9HXx8!S!I=<=x1YB{P+&pA9@Ka`vCGHKzMIbL!f zmaAoTt%U_fpSAV!3g#3p+hIM%dEA<*d)_jKqF&OrRl@GPjd$)jN$hy)9;g0;iW#R@ zUs*9ku^UCOE4m66tr$iTU=gf#{@G_K33K)?jW>t(YgQ&ncvm`QG>T{Bq`jpUTbFo7 z!&cv7bA@3Zl?uU)bbJa(Khfeh87Lm-%I;Y$$`u^;N$=!PN1T-9ke`}V>6XF7pdB%c z97>sqF8a=N+2U9c(MM@(T6(z_D_~I}iEM&V#rk{{lBj->(uMwnR&6Qn=LsK*)s_}f zn-vgMMwgtdR|gJD+2E;ti*x~JS~==U2aLnW;HO#nR9o*#>2%o%2TM7Ar?%}uD*~W; z-(6BCvAeM$-H+tLfcY^s{I@W4IL>M;X3Um`zj*?J)9(EV1*s0sRI!sdGLd$nU+T(6&_^(MrOafpvHOuAy<^s0$H&?S_*tY0(e3tI-Ujw#a z=x&+zvdQhLS~hem3PlBSF_l|1m973lY6$H0gfc7KZs||8qXSb3%qckb?*i?y>KaDR zv|b|~X^T4363(keeLR}O1%aEAh5i)tH=O7%gmPPBDNPm?uCco?e}r8Y(i# zgQBMH>DFqh_s`&TdcP!gCm1M?wU4ci!S0}&GaMalSKH(d(XLh?xm>nWucopB{6NM! zLS|e%Z=RE>KH#d)ZQ#tWDrUG)1rgj;MTg6R`fBLP-B3;P9mdLg`wQ$v=!pu7Q?U9_ zfIy#lWkGIn3+5;J2oHbv#2)^@X|wjVN{sC0SOS|x)m!0&PKylA-V?%NuejToV;$ce zs6}=GCBM@hVwf~v3&wiz|KIUQpDe{9?Wz9=8qtW&T;@$32TA%zp(7`I6RYPJ)Pe@x ztCl==4O`=7*!>n`W;hyiD<Ie6QLmc=W1ZE@#1D)~cvQ3`HqH%4NM$Qw>0tB!)B+rw!rY1&pkwI%nNunDnAq z!KyELqBezxulWvh7hzj#2_opJh$2%|ilGvT{j$Maip!I(^=VtaSf=~ShooJbi_O}p z$~&U{b%Dc8@rLWb9gOQUEnv&_X(BJs0t54=Q)q|Eq}O}Y)F5K@k7-u{N%shAVn>Nj zAou#DFtzq4EqD*@7cID#dcOczYxfJqGlz1NI`yMyU%&Qo==oUh76F!ub{D_S2%n^z zydvMt0;k_!!b6zPqMLMnS`=?dqIL!ouk0^WtH5OTMRifnf#Tz;3p{*ClhV?$kkK?) zwvs)n$MFdo%*l{Sq}sj3QMx*P8&fkm{0(#d5gu1aQBVdH+Fbq>oeC&T>b%vY&Y?(t%5}kwDyYNnalepGf4NFV*-BuQIllN-!IN+bGR=SB07n!j1=%SsFie!1 zHOz5KM4T1L#6cZ7kFWiET%es~fC+Bng6t%P^>3P-q_F-CTotRk{>?g-e{BA(Fc@+k z*NT}O{`XAmq;ezIi0H1~B}A0*CL`i_AYw50qEMO57fB^z64ao#sClc)9cC`d)etKS zC%l?j4%L;IWw}4gJ{KGjgUQUYc11Bhb&N!QZ%KIu3>vdGVv_adG8+LSWmD)4Cd5Dy zLQmzv5td@TCP4~HM4cK5MMR_+z^weWi2bcwoKnp?aiJn&aO$%lR&Cun>Py?gmcJ0S zgTy%sC!i^VsFo434<%U3(&(3nnLEWvj8AOQEHBg@k67Nm})aj4vvzqxj0B^)vI$IS$tko_$@a>#EVAHAFLZCqg@lbC_XZv=^m+IGKCbF1 zY=@h5(=AI!q~R6$pD=HMgFM2K>V_?mHw=-7{IeH7r?lv8`pBJ78zvyUC=pd&dk~O5 zbS~;|1+$_$sf0oi0)^u(6ke?DG@VnuP2vzRZ<#rx2}St$MfjA{z8`)m@hOiP7+<8a zszn8GV~%|9T895xf@`Puwp5k*AbB(BD(6!*ipPwKSi$Y#ADUZeYYG!;!>Mbx z$Kzpt`5vj)MZxqx-}wi2Fk(O4%i~ckveJldxKw7X>5Mz?ml6BU<8A6PZ=8+grO{Q<@SE zq6-qVD~>P$>K4V~o)nMk!3#Xf9;pF|nL&?Eo>V9qbcF%wy{I{b*>#)k2CbM3qRz4x zk!&*v){JX^5}t7?YbNT67TSTMZiZIP&g9t=lMf0Rm-%!_ojaY;qtW3fR(JSwsl${$ zAYBSyJt0<{>*LB`$@O!_0P0MONW3{1+v*#&3Kk2zsAzj0j<;_KUv)u_Gn>IyJZ9cF zz&0U8neZ3fJy86$1U+T|XcN7Rxk%ja|0Ng;d^KO8ugFgcUqQgVny;7)z9L%J(9bkD zI6N+D4z80pxK3ji=mZDXY3u?WpO|m#0^|XaC&q|_>u49~G-kHb7sSN|bpt=`S@{GG5B4WTV5I>JeFAwHiy=X1s0tv_eP@j2QLnZ{<3*Q8e= zVuqwrB*Tf?G={=(2GbbY2>NaPH)mTBe!?u6-PSHqukoY|IOE^YdX2Gf2#z)Z>at!# z%C^gTjmvtCWFmbH%hZMHHOBI;7;Z;R?RL0vp|n}8-G*di!>&TV&D|>fw(TF*Z}Vh3 zbl%1stfwo3o|JRaZu7+2ZOCw$)!IucMXk*?fMR>GT`RQnW@EMXbf~qbrPgN4kU70Q za5RikD(7KMRA~_UY#pp3k|bsE6t_u9+>%8Xy)nk{IXT6|_qDP)zMqy3cWm_i!svT! z!2X^CYNeIUQZJ(;Rp`-vWo9b=7*1lW%Ya-l; z&X*(oH6y!EI{Vwm^vX%TrvAEV+P40>Y1+2_x?H2b&d#LPGRt5c+C1fHS`7C)o$Ou2 z&>(9Bw>?RXHrxqegceOp1TRo>t|ek*g|Lf*5~g@c`>o(!9A%2Svm0AkBbW|>ON9v% zaF_TPcfwBLJ@GL*EDj$to%om;M{N=xv#3YG$FMB$OgTQ+ZcP=~Ko*<)h?4>mSr(Jt z-#;VwgWE_8Xpu*@6Rc{=m!>XJad0)8qpGn2zGoF@D&*0jvlh`D0r;S2TWVz)}zEpv!=4s7{=2LqC|!5O4rmWabkx6bqS zGEMl&)G~VY&!E4DdQk7xqhez;>e7c+WN) zn|be3wh~}2wr>JZ%LZ1>!Lb@kK#Y{#B^JJrpXU&zY{yWv*VNTGiy@uAh!>yo+A2Fn z@;Z{0!b{eM7itPShP_oD5T^4Lb_|G$?HHyg*fC~hm1qmtUXn8H)GQFkjJh(g)lag~ zN5F^`*0kf44Q+q6bI4alB++&pS0y{n*M0nOGHu{L;aM~sAkKyZn}Y2*K%w-4J}m;(~$L52r{;5Z~N%?c!bR;g

*!Y45RnS8esjXScTZOeA~HM8n>r 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

G0b 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 o6HgO=x3$@HsX8`CA;l9A|MHcX{*w2jz1=wg3PC From 14051bf7ade0f0bdd7ebbaaebb7bcd6d71688557 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Wed, 30 Aug 2023 23:08:46 +0200 Subject: [PATCH 04/16] add genesis part --- x/perp/v2/module/genesis.go | 11 +++++++++-- x/perp/v2/module/genesis_test.go | 9 +++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/x/perp/v2/module/genesis.go b/x/perp/v2/module/genesis.go index c855da9fb..d2c9ee6de 100644 --- a/x/perp/v2/module/genesis.go +++ b/x/perp/v2/module/genesis.go @@ -15,7 +15,6 @@ import ( // InitGenesis initializes the capability module's state from a provided genesis // state. func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState) { - // TODO: take care of last versions saved in the store if err := genState.Validate(); err != nil { panic(err) } @@ -53,10 +52,18 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState) // ExportGenesis returns the capability module's exported genesis. func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState { - // TODO: take care of last versions saved in the store genesis := new(types.GenesisState) genesis.Markets = k.Markets.Iterate(ctx, collections.Range[collections.Pair[asset.Pair, uint64]]{}).Values() + + kv := k.MarketLastVersion.Iterate(ctx, collections.Range[asset.Pair]{}).KeyValues() + for _, kv := range kv { + genesis.MarketLastVersions = append(genesis.MarketLastVersions, types.GenesisMarketLastVersion{ + Pair: kv.Key, + Version: kv.Value.Version, + }) + } + genesis.Amms = k.AMMs.Iterate(ctx, collections.Range[asset.Pair]{}).Values() genesis.Positions = k.Positions.Iterate(ctx, collections.PairRange[asset.Pair, sdk.AccAddress]{}).Values() genesis.ReserveSnapshots = k.ReserveSnapshots.Iterate(ctx, collections.PairRange[asset.Pair, time.Time]{}).Values() diff --git a/x/perp/v2/module/genesis_test.go b/x/perp/v2/module/genesis_test.go index 202cb5b91..42d320ee2 100644 --- a/x/perp/v2/module/genesis_test.go +++ b/x/perp/v2/module/genesis_test.go @@ -69,6 +69,7 @@ func RunTestGenesis(t *testing.T, tc TestCase) { // create some params app.PerpKeeperV2.Markets.Insert(ctx, collections.Join(pair, uint64(1)), *mock.TestMarket()) + app.PerpKeeperV2.MarketLastVersion.Insert(ctx, pair, types.MarketLastVersion{Version: 1}) app.PerpKeeperV2.AMMs.Insert(ctx, pair, *mock.TestAMMDefault()) // create some positions @@ -93,9 +94,17 @@ func RunTestGenesis(t *testing.T, tc TestCase) { // export again to ensure they match genStateAfterInit := perp.ExportGenesis(ctx, app.PerpKeeperV2) + require.Len(t, genStateAfterInit.Markets, len(genState.Markets)) for i, pm := range genState.Markets { require.Equal(t, pm, genStateAfterInit.Markets[i]) } + + require.Len(t, genStateAfterInit.MarketLastVersions, len(genState.MarketLastVersions)) + for i, mlv := range genState.MarketLastVersions { + require.Equal(t, mlv, genStateAfterInit.MarketLastVersions[i]) + } + + require.Len(t, genStateAfterInit.Amms, len(genState.Amms)) for i, amm := range genState.Amms { require.Equal(t, amm, genStateAfterInit.Amms[i]) } From 93f9c18975422af704a787de2dc4f3e307d2aeac Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 7 Sep 2023 15:43:13 +0200 Subject: [PATCH 05/16] create changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 11ce1b04c..9cf22c646 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -72,6 +72,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * [#1501](https://github.com/NibiruChain/nibiru/pull/1501) - feat(proto): add Python buf generation logic for py-sdk * [#1503](https://github.com/NibiruChain/nibiru/pull/1503) - feat(wasm): add Oracle Exchange Rate query for wasm * [#1543](https://github.com/NibiruChain/nibiru/pull/1543) - epic(devgas): devgas module for incentivizing smart contract +* [#1559](https://github.com/NibiruChain/nibiru/pull/1559) - feat: add versions to markets to allow to disable them ### Bug Fixes From d2e631ea7953678beb48afab7fee194fc2e83f9f Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 7 Sep 2023 16:05:08 +0200 Subject: [PATCH 06/16] add option for market creation when another one is closed --- x/perp/v2/keeper/admin.go | 3 ++- x/perp/v2/keeper/admin_test.go | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/x/perp/v2/keeper/admin.go b/x/perp/v2/keeper/admin.go index 85f50346f..6e43d9f57 100644 --- a/x/perp/v2/keeper/admin.go +++ b/x/perp/v2/keeper/admin.go @@ -104,7 +104,8 @@ func (k admin) CreateMarket( return err } - lastVersion := k.MarketLastVersion.GetOr(ctx, pair, types.MarketLastVersion{Version: 1}) + lastVersion := k.MarketLastVersion.GetOr(ctx, pair, types.MarketLastVersion{Version: 0}) + lastVersion.Version += 1 market.Version = lastVersion.Version k.Markets.Insert(ctx, collections.Join(pair, lastVersion.Version), market) diff --git a/x/perp/v2/keeper/admin_test.go b/x/perp/v2/keeper/admin_test.go index 15d28e1ab..ec1ebd64f 100644 --- a/x/perp/v2/keeper/admin_test.go +++ b/x/perp/v2/keeper/admin_test.go @@ -152,4 +152,19 @@ func TestCreateMarketFail(t *testing.T) { SqrtDepth: amm.SqrtDepth, }) require.ErrorContains(t, err, "already exists") + + // Disable the market to test that we can create it again but with an increased version + err = app.PerpKeeperV2.ChangeMarketEnabledParameter(ctx, pair, false) + require.NoError(t, err) + + err = app.PerpKeeperV2.Admin().CreateMarket(ctx, keeper.ArgsCreateMarket{ + Pair: pair, + PriceMultiplier: amm.PriceMultiplier, + SqrtDepth: amm.SqrtDepth, + }) + require.NoError(t, err) + + lastVersion, err = app.PerpKeeperV2.MarketLastVersion.Get(ctx, pair) + require.NoError(t, err) + require.Equal(t, uint64(2), lastVersion.Version) } From 52f61d396315fa98e34095e0ed42487f930d9c09 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Fri, 8 Sep 2023 22:03:43 +0200 Subject: [PATCH 07/16] make tests pass --- proto/nibiru/perp/v2/state.proto | 4 + x/common/testutil/genesis/perp_genesis.go | 5 + x/common/testutil/mock/perp_amm.go | 1 + x/perp/v2/integration/action/market.go | 3 +- x/perp/v2/integration/action/snapshot.go | 3 +- x/perp/v2/integration/assertion/market.go | 16 +- x/perp/v2/keeper/admin.go | 12 +- x/perp/v2/keeper/admin_test.go | 15 +- x/perp/v2/keeper/amm.go | 26 +++- x/perp/v2/keeper/amm_test.go | 6 +- x/perp/v2/keeper/clearing_house.go | 7 +- x/perp/v2/keeper/clearing_house_test.go | 2 +- x/perp/v2/keeper/grpc_query.go | 11 +- x/perp/v2/keeper/keeper.go | 11 +- x/perp/v2/keeper/liquidate.go | 2 +- x/perp/v2/keeper/margin.go | 4 +- x/perp/v2/keeper/swap.go | 6 +- x/perp/v2/keeper/swap_test.go | 2 - x/perp/v2/keeper/twap_test.go | 4 +- x/perp/v2/keeper/withdraw.go | 4 +- x/perp/v2/module/abci.go | 20 ++- x/perp/v2/module/abci_test.go | 3 +- x/perp/v2/module/genesis.go | 4 +- x/perp/v2/module/genesis_test.go | 2 +- x/perp/v2/types/state.pb.go | 173 +++++++++++++--------- 25 files changed, 214 insertions(+), 132 deletions(-) diff --git a/proto/nibiru/perp/v2/state.proto b/proto/nibiru/perp/v2/state.proto index 4a7831f16..54ec777f1 100644 --- a/proto/nibiru/perp/v2/state.proto +++ b/proto/nibiru/perp/v2/state.proto @@ -132,6 +132,10 @@ message AMM { (gogoproto.nullable) = false ]; + // the version of the AMM, only one AMM can exist per pair, when one is closed it cannot be reactivated, + // so a new AMM must be created, this is the version of the AMM + uint64 version = 8; + // the amount of base reserves this AMM has string base_reserve = 2 [ (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", diff --git a/x/common/testutil/genesis/perp_genesis.go b/x/common/testutil/genesis/perp_genesis.go index 4430aaab1..2b3292533 100644 --- a/x/common/testutil/genesis/perp_genesis.go +++ b/x/common/testutil/genesis/perp_genesis.go @@ -36,6 +36,7 @@ func AddPerpV2Genesis(gen app.GenesisState) app.GenesisState { }, Amm: perpv2types.AMM{ Pair: asset.Registry.Pair(denoms.BTC, denoms.NUSD), + Version: 1, BaseReserve: sdk.NewDec(10e6), QuoteReserve: sdk.NewDec(10e6), SqrtDepth: sdk.NewDec(10e6), @@ -63,6 +64,7 @@ func AddPerpV2Genesis(gen app.GenesisState) app.GenesisState { }, Amm: perpv2types.AMM{ Pair: asset.Registry.Pair(denoms.ATOM, denoms.NUSD), + Version: 1, BaseReserve: sdk.NewDec(10e6), QuoteReserve: sdk.NewDec(10e6), SqrtDepth: sdk.NewDec(10e6), @@ -90,6 +92,7 @@ func AddPerpV2Genesis(gen app.GenesisState) app.GenesisState { }, Amm: perpv2types.AMM{ Pair: asset.Registry.Pair(denoms.OSMO, denoms.NUSD), + Version: 1, BaseReserve: sdk.NewDec(10e6), QuoteReserve: sdk.NewDec(10e6), SqrtDepth: sdk.NewDec(10e6), @@ -148,6 +151,7 @@ var START_MARKETS = map[asset.Pair]perpv2types.AmmMarket{ }, Amm: perpv2types.AMM{ Pair: asset.Registry.Pair(denoms.ETH, denoms.NUSD), + Version: 1, BaseReserve: sdk.NewDec(10e6), QuoteReserve: sdk.NewDec(10e6), SqrtDepth: sdk.NewDec(10e6), @@ -175,6 +179,7 @@ var START_MARKETS = map[asset.Pair]perpv2types.AmmMarket{ }, Amm: perpv2types.AMM{ Pair: asset.Registry.Pair(denoms.NIBI, denoms.NUSD), + Version: 1, BaseReserve: sdk.NewDec(10 * common.TO_MICRO), QuoteReserve: sdk.NewDec(10 * common.TO_MICRO), SqrtDepth: common.MustSqrtDec(sdk.NewDec(10 * common.TO_MICRO * 10 * common.TO_MICRO)), diff --git a/x/common/testutil/mock/perp_amm.go b/x/common/testutil/mock/perp_amm.go index b3d3a6363..a901691cd 100644 --- a/x/common/testutil/mock/perp_amm.go +++ b/x/common/testutil/mock/perp_amm.go @@ -12,6 +12,7 @@ import ( func TestAMMDefault() *types.AMM { return &types.AMM{ Pair: asset.NewPair(denoms.BTC, denoms.NUSD), + Version: 1, BaseReserve: sdk.NewDec(1e12), QuoteReserve: sdk.NewDec(1e12), SqrtDepth: sdk.NewDec(1e12), diff --git a/x/perp/v2/integration/action/market.go b/x/perp/v2/integration/action/market.go index efcb694e0..a1e0a94fe 100644 --- a/x/perp/v2/integration/action/market.go +++ b/x/perp/v2/integration/action/market.go @@ -41,7 +41,7 @@ type createMarketAction struct { func (c createMarketAction) Do(app *app.NibiruApp, ctx sdk.Context) (sdk.Context, error, bool) { app.PerpKeeperV2.Markets.Insert(ctx, collections.Join(c.Market.Pair, uint64(1)), c.Market) app.PerpKeeperV2.MarketLastVersion.Insert(ctx, c.Market.Pair, types.MarketLastVersion{Version: 1}) - app.PerpKeeperV2.AMMs.Insert(ctx, c.AMM.Pair, c.AMM) + app.PerpKeeperV2.AMMs.Insert(ctx, collections.Join(c.AMM.Pair, uint64(1)), c.AMM) app.PerpKeeperV2.ReserveSnapshots.Insert(ctx, collections.Join(c.AMM.Pair, ctx.BlockTime()), types.ReserveSnapshot{ Amm: c.AMM, @@ -56,6 +56,7 @@ func CreateCustomMarket(pair asset.Pair, marketModifiers ...marketModifier) acti market := types.DefaultMarket(pair) amm := types.AMM{ Pair: pair, + Version: 1, BaseReserve: sdk.NewDec(1e12), QuoteReserve: sdk.NewDec(1e12), SqrtDepth: sdk.NewDec(1e12), diff --git a/x/perp/v2/integration/action/snapshot.go b/x/perp/v2/integration/action/snapshot.go index 03380b11c..8d51a7954 100644 --- a/x/perp/v2/integration/action/snapshot.go +++ b/x/perp/v2/integration/action/snapshot.go @@ -20,8 +20,9 @@ type insertReserveSnapshot struct { } func (i insertReserveSnapshot) Do(app *app.NibiruApp, ctx sdk.Context) (sdk.Context, error, bool) { - amm := app.PerpKeeperV2.AMMs.GetOr(ctx, i.pair, types.AMM{ + amm := app.PerpKeeperV2.AMMs.GetOr(ctx, collections.Join(i.pair, uint64(1)), types.AMM{ Pair: i.pair, + Version: uint64(1), BaseReserve: sdk.ZeroDec(), QuoteReserve: sdk.ZeroDec(), SqrtDepth: sdk.ZeroDec(), diff --git a/x/perp/v2/integration/assertion/market.go b/x/perp/v2/integration/assertion/market.go index 21234b739..cfe75e797 100644 --- a/x/perp/v2/integration/assertion/market.go +++ b/x/perp/v2/integration/assertion/market.go @@ -2,6 +2,7 @@ package assertion import ( "fmt" + "github.com/NibiruChain/nibiru/x/common/testutil/action" sdkmath "cosmossdk.io/math" @@ -34,7 +35,7 @@ func (m marketShouldBeEqual) Do(app *app.NibiruApp, ctx sdk.Context) (sdk.Contex return ctx, nil, false } -func MarketShouldBeEqual(pair asset.Pair, marketCheckers ...MarketChecker) marketShouldBeEqual { +func MarketShouldBeEqual(pair asset.Pair, marketCheckers ...MarketChecker) action.Action { return marketShouldBeEqual{ Pair: pair, Checkers: marketCheckers, @@ -77,7 +78,7 @@ type ammShouldBeEqual struct { type AMMChecker func(amm types.AMM) error func (a ammShouldBeEqual) Do(app *app.NibiruApp, ctx sdk.Context) (sdk.Context, error, bool) { - amm, err := app.PerpKeeperV2.AMMs.Get(ctx, a.Pair) + amm, err := app.PerpKeeperV2.GetAMM(ctx, a.Pair) if err != nil { return ctx, err, false } @@ -91,7 +92,7 @@ func (a ammShouldBeEqual) Do(app *app.NibiruApp, ctx sdk.Context) (sdk.Context, return ctx, nil, false } -func AMMShouldBeEqual(pair asset.Pair, ammCheckers ...AMMChecker) ammShouldBeEqual { +func AMMShouldBeEqual(pair asset.Pair, ammCheckers ...AMMChecker) action.Action { return ammShouldBeEqual{ Pair: pair, Checkers: ammCheckers, @@ -152,3 +153,12 @@ func AMM_BiasShouldBeEqual(expectedBias sdk.Dec) AMMChecker { return nil } } + +func AMM_VersionShouldBeEqual(expectedVersion uint64) AMMChecker { + return func(amm types.AMM) error { + if amm.Version != expectedVersion { + return fmt.Errorf("expected version to be %d, got %d", expectedVersion, amm.Version) + } + return nil + } +} diff --git a/x/perp/v2/keeper/admin.go b/x/perp/v2/keeper/admin.go index 6e43d9f57..62db25f91 100644 --- a/x/perp/v2/keeper/admin.go +++ b/x/perp/v2/keeper/admin.go @@ -2,6 +2,7 @@ package keeper import ( "fmt" + "github.com/NibiruChain/collections" sdkmath "cosmossdk.io/math" @@ -90,9 +91,14 @@ func (k admin) CreateMarket( return err } + lastVersion := k.MarketLastVersion.GetOr(ctx, pair, types.MarketLastVersion{Version: 0}) + lastVersion.Version += 1 + market.Version = lastVersion.Version + // init amm amm := types.AMM{ Pair: pair, + Version: 1, BaseReserve: baseReserve, QuoteReserve: quoteReserve, SqrtDepth: sqrtDepth, @@ -104,13 +110,9 @@ func (k admin) CreateMarket( return err } - lastVersion := k.MarketLastVersion.GetOr(ctx, pair, types.MarketLastVersion{Version: 0}) - lastVersion.Version += 1 - market.Version = lastVersion.Version - k.Markets.Insert(ctx, collections.Join(pair, lastVersion.Version), market) + k.AMMs.Insert(ctx, collections.Join(pair, lastVersion.Version), amm) k.MarketLastVersion.Insert(ctx, pair, lastVersion) - k.AMMs.Insert(ctx, pair, amm) return nil } diff --git a/x/perp/v2/keeper/admin_test.go b/x/perp/v2/keeper/admin_test.go index ec1ebd64f..7f67772ef 100644 --- a/x/perp/v2/keeper/admin_test.go +++ b/x/perp/v2/keeper/admin_test.go @@ -4,22 +4,19 @@ import ( "testing" sdkmath "cosmossdk.io/math" - - "github.com/stretchr/testify/require" - sdk "github.com/cosmos/cosmos-sdk/types" - - . "github.com/NibiruChain/nibiru/x/common/testutil/action" - "github.com/NibiruChain/nibiru/x/common/testutil/mock" - . "github.com/NibiruChain/nibiru/x/perp/v2/integration/action" - . "github.com/NibiruChain/nibiru/x/perp/v2/integration/assertion" - "github.com/NibiruChain/nibiru/x/perp/v2/keeper" + "github.com/stretchr/testify/require" "github.com/NibiruChain/nibiru/app" "github.com/NibiruChain/nibiru/x/common/asset" "github.com/NibiruChain/nibiru/x/common/denoms" "github.com/NibiruChain/nibiru/x/common/testutil" + . "github.com/NibiruChain/nibiru/x/common/testutil/action" + "github.com/NibiruChain/nibiru/x/common/testutil/mock" "github.com/NibiruChain/nibiru/x/common/testutil/testapp" + . "github.com/NibiruChain/nibiru/x/perp/v2/integration/action" + . "github.com/NibiruChain/nibiru/x/perp/v2/integration/assertion" + "github.com/NibiruChain/nibiru/x/perp/v2/keeper" types "github.com/NibiruChain/nibiru/x/perp/v2/types" ) diff --git a/x/perp/v2/keeper/amm.go b/x/perp/v2/keeper/amm.go index 29640ce89..7de68acf9 100644 --- a/x/perp/v2/keeper/amm.go +++ b/x/perp/v2/keeper/amm.go @@ -1,8 +1,9 @@ package keeper import ( - sdkmath "cosmossdk.io/math" "fmt" + + sdkmath "cosmossdk.io/math" "github.com/NibiruChain/collections" sdk "github.com/cosmos/cosmos-sdk/types" @@ -18,7 +19,7 @@ func (k Keeper) EditPriceMultiplier( pair asset.Pair, newPriceMultiplier sdk.Dec, ) (err error) { - amm, err := k.AMMs.Get(ctx, pair) + amm, err := k.GetAMM(ctx, pair) if err != nil { return err } @@ -41,7 +42,7 @@ func (k Keeper) EditPriceMultiplier( // Do the re-peg amm.PriceMultiplier = newPriceMultiplier - k.AMMs.Insert(ctx, pair, amm) + k.AMMs.Insert(ctx, collections.Join(pair, amm.Version), amm) return nil } @@ -51,7 +52,7 @@ func (k Keeper) EditPriceMultiplier( // funds get send to the vault to pay for trader's new net margin. func (k Keeper) EditSwapInvariant(ctx sdk.Context, pair asset.Pair, newSwapInvariant sdk.Dec) (err error) { // Get the pool - amm, err := k.AMMs.Get(ctx, pair) + amm, err := k.GetAMM(ctx, pair) if err != nil { return err } @@ -72,7 +73,7 @@ func (k Keeper) EditSwapInvariant(ctx sdk.Context, pair asset.Pair, newSwapInvar return err } - k.AMMs.Insert(ctx, pair, amm) + k.AMMs.Insert(ctx, collections.Join(pair, amm.Version), amm) return nil } @@ -130,3 +131,18 @@ func (k Keeper) GetMarket(ctx sdk.Context, pair asset.Pair) (types.Market, error return market, nil } + +// GetAMM returns the amm with last version. +func (k Keeper) GetAMM(ctx sdk.Context, pair asset.Pair) (types.AMM, error) { + lastVersion, err := k.MarketLastVersion.Get(ctx, pair) + if err != nil { + return types.AMM{}, fmt.Errorf("market %s not found", pair) + } + + amm, err := k.AMMs.Get(ctx, collections.Join(pair, lastVersion.Version)) + if err != nil { + return types.AMM{}, fmt.Errorf("market %s not found", pair) + } + + return amm, nil +} diff --git a/x/perp/v2/keeper/amm_test.go b/x/perp/v2/keeper/amm_test.go index 3c31475bf..da1583244 100644 --- a/x/perp/v2/keeper/amm_test.go +++ b/x/perp/v2/keeper/amm_test.go @@ -177,9 +177,9 @@ func TestEditPriceMultiplerFail(t *testing.T) { }) require.NoError(t, err) - // Error because of invalid price multiplier + // Error because of invalid pair err = app.PerpKeeperV2.Admin().EditPriceMultiplier(ctx, asset.MustNewPair("luna:usdt"), sdk.NewDec(-1)) - require.ErrorContains(t, err, "collections: not found") + require.ErrorContains(t, err, "market luna:usdt not found") // Error because of invalid price multiplier err = app.PerpKeeperV2.Admin().EditPriceMultiplier(ctx, pair, sdk.NewDec(-1)) @@ -244,7 +244,7 @@ func TestEditSwapInvariantFail(t *testing.T) { // Error because of invalid price multiplier err = app.PerpKeeperV2.Admin().EditSwapInvariant(ctx, asset.MustNewPair("luna:usdt"), sdk.NewDec(-1)) - require.ErrorContains(t, err, "collections: not found") + require.ErrorContains(t, err, "market luna:usdt not found") // Error because of invalid price multiplier err = app.PerpKeeperV2.Admin().EditSwapInvariant(ctx, pair, sdk.NewDec(-1)) diff --git a/x/perp/v2/keeper/clearing_house.go b/x/perp/v2/keeper/clearing_house.go index 64fa0092f..21c9195db 100644 --- a/x/perp/v2/keeper/clearing_house.go +++ b/x/perp/v2/keeper/clearing_house.go @@ -45,7 +45,7 @@ func (k Keeper) MarketOrder( return nil, types.ErrMarketNotEnabled.Wrapf("market pair %s not enabled", pair) } - amm, err := k.AMMs.Get(ctx, pair) + amm, err := k.GetAMM(ctx, pair) if err != nil { return nil, types.ErrPairNotFound.Wrapf("pair %s not found", pair) } @@ -696,7 +696,7 @@ func (k Keeper) ClosePosition(ctx sdk.Context, pair asset.Pair, traderAddr sdk.A return nil, fmt.Errorf("%w: %s", types.ErrPairNotFound, pair) } - amm, err := k.AMMs.Get(ctx, pair) + amm, err := k.GetAMM(ctx, pair) if err != nil { return nil, fmt.Errorf("%w: %s", types.ErrPairNotFound, pair) } @@ -798,7 +798,6 @@ func (k Keeper) closePositionEntirely( } updatedAMM, exchangedNotionalValue, err := k.SwapBaseAsset( ctx, - market, amm, dir, currentPosition.Size_.Abs(), @@ -839,7 +838,7 @@ func (k Keeper) PartialClose( return nil, types.ErrPairNotFound.Wrapf("pair: %s", pair) } - amm, err := k.AMMs.Get(ctx, pair) + amm, err := k.GetAMM(ctx, pair) if err != nil { return nil, types.ErrPairNotFound.Wrapf("pair: %s", pair) } diff --git a/x/perp/v2/keeper/clearing_house_test.go b/x/perp/v2/keeper/clearing_house_test.go index 63094afd3..4d4639bd3 100644 --- a/x/perp/v2/keeper/clearing_house_test.go +++ b/x/perp/v2/keeper/clearing_house_test.go @@ -1175,7 +1175,7 @@ func TestMarketOrderError(t *testing.T) { app.PerpKeeperV2.Markets.Insert(ctx, collections.Join(asset.Registry.Pair(denoms.BTC, denoms.NUSD), market.Version), *market) app.PerpKeeperV2.MarketLastVersion.Insert(ctx, asset.Registry.Pair(denoms.BTC, denoms.NUSD), types.MarketLastVersion{Version: market.Version}) amm := mock.TestAMMDefault() - app.PerpKeeperV2.AMMs.Insert(ctx, amm.Pair, *amm) + app.PerpKeeperV2.AMMs.Insert(ctx, collections.Join(asset.Registry.Pair(denoms.BTC, denoms.NUSD), market.Version), *amm) app.PerpKeeperV2.ReserveSnapshots.Insert(ctx, collections.Join(amm.Pair, ctx.BlockTime()), types.ReserveSnapshot{ Amm: *amm, TimestampMs: ctx.BlockTime().UnixMilli(), diff --git a/x/perp/v2/keeper/grpc_query.go b/x/perp/v2/keeper/grpc_query.go index 214f734c4..9a01fb2ca 100644 --- a/x/perp/v2/keeper/grpc_query.go +++ b/x/perp/v2/keeper/grpc_query.go @@ -45,7 +45,7 @@ func (q queryServer) QueryPositions( var positions []types.QueryPositionResponse for _, market := range markets { - amm, err := q.k.AMMs.Get(ctx, market.Pair) + amm, err := q.k.GetAMM(ctx, market.Pair) if err != nil { return nil, err } @@ -78,7 +78,7 @@ func (q queryServer) QueryPosition( return nil, err } - amm, err := q.k.AMMs.Get(ctx, req.Pair) + amm, err := q.k.GetAMM(ctx, req.Pair) if err != nil { return nil, err } @@ -171,8 +171,13 @@ func (q queryServer) QueryMarkets( var ammMarkets []types.AmmMarket markets := q.k.Markets.Iterate(ctx, collections.Range[collections.Pair[asset.Pair, uint64]]{}).Values() for _, market := range markets { + // disabled markets are not returned + if market.Enabled == false { + continue + } + pair := market.Pair - amm, err := q.k.AMMs.Get(ctx, pair) + amm, err := q.k.AMMs.Get(ctx, collections.Join(pair, market.Version)) if err != nil { return nil, err } diff --git a/x/perp/v2/keeper/keeper.go b/x/perp/v2/keeper/keeper.go index bdeef733b..8f7e5885e 100644 --- a/x/perp/v2/keeper/keeper.go +++ b/x/perp/v2/keeper/keeper.go @@ -25,11 +25,12 @@ type Keeper struct { OracleKeeper types.OracleKeeper EpochKeeper types.EpochKeeper - Markets collections.Map[collections.Pair[asset.Pair, uint64], types.Market] MarketLastVersion collections.Map[asset.Pair, types.MarketLastVersion] - AMMs collections.Map[asset.Pair, types.AMM] - Positions collections.Map[collections.Pair[asset.Pair, sdk.AccAddress], types.Position] - ReserveSnapshots collections.Map[collections.Pair[asset.Pair, time.Time], types.ReserveSnapshot] + Markets collections.Map[collections.Pair[asset.Pair, uint64], types.Market] + AMMs collections.Map[collections.Pair[asset.Pair, uint64], types.AMM] + + Positions collections.Map[collections.Pair[asset.Pair, sdk.AccAddress], types.Position] + ReserveSnapshots collections.Map[collections.Pair[asset.Pair, time.Time], types.ReserveSnapshot] } // NewKeeper Creates a new x/perp Keeper instance. @@ -66,7 +67,7 @@ func NewKeeper( ), AMMs: collections.NewMap( storeKey, NamespaceAmms, - asset.PairKeyEncoder, + collections.PairKeyEncoder(asset.PairKeyEncoder, collections.Uint64KeyEncoder), collections.ProtoValueEncoder[types.AMM](cdc), ), Positions: collections.NewMap( diff --git a/x/perp/v2/keeper/liquidate.go b/x/perp/v2/keeper/liquidate.go index 751156db5..953085731 100644 --- a/x/perp/v2/keeper/liquidate.go +++ b/x/perp/v2/keeper/liquidate.go @@ -165,7 +165,7 @@ func (k Keeper) liquidate( return } - amm, err := k.AMMs.Get(ctx, pair) + amm, err := k.GetAMM(ctx, pair) if err != nil { eventLiqFailed := &types.LiquidationFailedEvent{ Pair: pair, diff --git a/x/perp/v2/keeper/margin.go b/x/perp/v2/keeper/margin.go index 7fa33b3fc..d5277d59e 100644 --- a/x/perp/v2/keeper/margin.go +++ b/x/perp/v2/keeper/margin.go @@ -30,7 +30,7 @@ func (k Keeper) AddMargin( if err != nil { return nil, fmt.Errorf("%w: %s", types.ErrPairNotFound, pair) } - amm, err := k.AMMs.Get(ctx, pair) + amm, err := k.GetAMM(ctx, pair) if err != nil { return nil, fmt.Errorf("%w: %s", types.ErrPairNotFound, pair) } @@ -121,7 +121,7 @@ func (k Keeper) RemoveMargin( return nil, fmt.Errorf("%w: %s", types.ErrPairNotFound, pair) } - amm, err := k.AMMs.Get(ctx, pair) + amm, err := k.GetAMM(ctx, pair) if err != nil { return nil, fmt.Errorf("%w: %s", types.ErrPairNotFound, pair) } diff --git a/x/perp/v2/keeper/swap.go b/x/perp/v2/keeper/swap.go index 2f3563ba8..7d0155452 100644 --- a/x/perp/v2/keeper/swap.go +++ b/x/perp/v2/keeper/swap.go @@ -1,6 +1,7 @@ package keeper import ( + "github.com/NibiruChain/collections" sdk "github.com/cosmos/cosmos-sdk/types" types "github.com/NibiruChain/nibiru/x/perp/v2/types" @@ -66,7 +67,7 @@ func (k Keeper) SwapQuoteAsset( return nil, sdk.Dec{}, err } - k.AMMs.Insert(ctx, amm.Pair, amm) + k.AMMs.Insert(ctx, collections.Join(amm.Pair, amm.Version), amm) return &amm, baseAssetDelta, nil } @@ -90,7 +91,6 @@ func (k Keeper) SwapQuoteAsset( // NOTE: the quoteAssetDelta is always positive func (k Keeper) SwapBaseAsset( ctx sdk.Context, - market types.Market, amm types.AMM, dir types.Direction, baseAssetAmt sdk.Dec, @@ -109,7 +109,7 @@ func (k Keeper) SwapBaseAsset( return nil, sdk.Dec{}, err } - k.AMMs.Insert(ctx, amm.Pair, amm) + k.AMMs.Insert(ctx, collections.Join(amm.Pair, amm.Version), amm) return &amm, quoteAssetDelta, err } diff --git a/x/perp/v2/keeper/swap_test.go b/x/perp/v2/keeper/swap_test.go index c5ca27ad0..279cb3274 100644 --- a/x/perp/v2/keeper/swap_test.go +++ b/x/perp/v2/keeper/swap_test.go @@ -191,12 +191,10 @@ func TestSwapBaseAsset(t *testing.T) { tc := tc t.Run(tc.name, func(t *testing.T) { app, ctx := testapp.NewNibiruTestAppAndContext() - market := mock.TestMarket() amm := mock.TestAMMDefault().WithPriceMultiplier(sdk.NewDec(2)) updatedAMM, quoteAssetAmount, err := app.PerpKeeperV2.SwapBaseAsset( ctx, - *market, *amm, tc.direction, tc.baseAssetAmt, diff --git a/x/perp/v2/keeper/twap_test.go b/x/perp/v2/keeper/twap_test.go index bdb047b16..7942f08d7 100644 --- a/x/perp/v2/keeper/twap_test.go +++ b/x/perp/v2/keeper/twap_test.go @@ -114,7 +114,7 @@ func TestInvalidTwap(t *testing.T) { startTime := time.UnixMilli(0) app.PerpKeeperV2.Markets.Insert(ctx, collections.Join(pair, uint64(1)), *mock.TestMarket()) - app.PerpKeeperV2.AMMs.Insert(ctx, pair, *mock.TestAMMDefault()) + app.PerpKeeperV2.AMMs.Insert(ctx, collections.Join(pair, uint64(1)), *mock.TestAMMDefault()) app.PerpKeeperV2.ReserveSnapshots.Insert( ctx, collections.Join(pair, startTime), types.ReserveSnapshot{ Amm: *mock.TestAMMDefault(), @@ -376,7 +376,7 @@ func TestCalcTwapExtended(t *testing.T) { startTime := time.UnixMilli(0) app.PerpKeeperV2.Markets.Insert(ctx, collections.Join(pair, uint64(1)), *mock.TestMarket()) - app.PerpKeeperV2.AMMs.Insert(ctx, pair, *mock.TestAMMDefault()) + app.PerpKeeperV2.AMMs.Insert(ctx, collections.Join(pair, uint64(1)), *mock.TestAMMDefault()) app.PerpKeeperV2.ReserveSnapshots.Insert( ctx, collections.Join(pair, startTime), types.ReserveSnapshot{ Amm: *mock.TestAMMDefault(), diff --git a/x/perp/v2/keeper/withdraw.go b/x/perp/v2/keeper/withdraw.go index 4cc02dfab..18795e1db 100644 --- a/x/perp/v2/keeper/withdraw.go +++ b/x/perp/v2/keeper/withdraw.go @@ -8,7 +8,7 @@ import ( types "github.com/NibiruChain/nibiru/x/perp/v2/types" ) -// Withdraws coins from the vault to the receiver. +// WithdrawFromVault coins from the vault to the receiver. // If the total amount of coins to withdraw is greater than the vault's amount, then // withdraw the shortage from the PerpEF and mark it as prepaid bad debt. // @@ -85,7 +85,7 @@ func (k Keeper) IncrementPrepaidBadDebt(ctx sdk.Context, market types.Market, am k.Markets.Insert(ctx, collections.Join(market.Pair, market.Version), market) } -// Zeroes out the prepaid bad debt +// ZeroPrepaidBadDebt out the prepaid bad debt func (k Keeper) ZeroPrepaidBadDebt(ctx sdk.Context, market types.Market) { market.PrepaidBadDebt.Amount = sdk.ZeroInt() k.Markets.Insert(ctx, collections.Join(market.Pair, market.Version), market) diff --git a/x/perp/v2/module/abci.go b/x/perp/v2/module/abci.go index 6fc8bfb08..4e77bcdc5 100644 --- a/x/perp/v2/module/abci.go +++ b/x/perp/v2/module/abci.go @@ -13,20 +13,24 @@ import ( // EndBlocker Called every block to store a snapshot of the perpamm. func EndBlocker(ctx sdk.Context, k keeper.Keeper) []abci.ValidatorUpdate { - // TODO: take into account only enabled markets - for _, amm := range k.AMMs.Iterate(ctx, collections.Range[asset.Pair]{}).Values() { - snapshot := types.ReserveSnapshot{ - Amm: amm, - TimestampMs: ctx.BlockTime().UnixMilli(), - } - k.ReserveSnapshots.Insert(ctx, collections.Join(amm.Pair, ctx.BlockTime()), snapshot) - + for _, amm := range k.AMMs.Iterate(ctx, collections.Range[collections.Pair[asset.Pair, uint64]]{}).Values() { market, err := k.GetMarket(ctx, amm.Pair) if err != nil { k.Logger(ctx).Error("failed to fetch market", "pair", amm.Pair, "error", err) continue } + // only snapshot enabled markets + if market.Enabled == false { + continue + } + + snapshot := types.ReserveSnapshot{ + Amm: amm, + TimestampMs: ctx.BlockTime().UnixMilli(), + } + k.ReserveSnapshots.Insert(ctx, collections.Join(amm.Pair, ctx.BlockTime()), snapshot) + markTwap, err := k.CalcTwap(ctx, amm.Pair, types.TwapCalcOption_SPOT, types.Direction_DIRECTION_UNSPECIFIED, sdk.ZeroDec(), market.TwapLookbackWindow) if err != nil { k.Logger(ctx).Error("failed to fetch twap mark price", "market.Pair", market.Pair, "error", err) diff --git a/x/perp/v2/module/abci_test.go b/x/perp/v2/module/abci_test.go index 9c23e5989..294a0f9a4 100644 --- a/x/perp/v2/module/abci_test.go +++ b/x/perp/v2/module/abci_test.go @@ -62,7 +62,7 @@ func TestSnapshotUpdates(t *testing.T) { t.Log("affect mark price") market, err := app.PerpKeeperV2.GetMarket(ctx, asset.Registry.Pair(denoms.BTC, denoms.NUSD)) require.NoError(t, err) - amm, err := app.PerpKeeperV2.AMMs.Get(ctx, asset.Registry.Pair(denoms.BTC, denoms.NUSD)) + amm, err := app.PerpKeeperV2.GetAMM(ctx, asset.Registry.Pair(denoms.BTC, denoms.NUSD)) require.NoError(t, err) _, baseAmtAbs, err := app.PerpKeeperV2.SwapQuoteAsset( @@ -80,6 +80,7 @@ func TestSnapshotUpdates(t *testing.T) { expectedSnapshot = types.ReserveSnapshot{ Amm: types.AMM{ Pair: asset.Registry.Pair(denoms.BTC, denoms.NUSD), + Version: 1, BaseReserve: sdk.NewDec(800e9), QuoteReserve: sdk.NewDec(1.25e12), SqrtDepth: sdk.NewDec(1e12), diff --git a/x/perp/v2/module/genesis.go b/x/perp/v2/module/genesis.go index d2c9ee6de..35de73549 100644 --- a/x/perp/v2/module/genesis.go +++ b/x/perp/v2/module/genesis.go @@ -29,7 +29,7 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState) for _, a := range genState.Amms { pair := a.Pair - k.AMMs.Insert(ctx, pair, a) + k.AMMs.Insert(ctx, collections.Join(a.Pair, a.Version), a) timestampMs := ctx.BlockTime().UnixMilli() k.ReserveSnapshots.Insert( ctx, @@ -64,7 +64,7 @@ func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState { }) } - genesis.Amms = k.AMMs.Iterate(ctx, collections.Range[asset.Pair]{}).Values() + genesis.Amms = k.AMMs.Iterate(ctx, collections.Range[collections.Pair[asset.Pair, uint64]]{}).Values() genesis.Positions = k.Positions.Iterate(ctx, collections.PairRange[asset.Pair, sdk.AccAddress]{}).Values() genesis.ReserveSnapshots = k.ReserveSnapshots.Iterate(ctx, collections.PairRange[asset.Pair, time.Time]{}).Values() diff --git a/x/perp/v2/module/genesis_test.go b/x/perp/v2/module/genesis_test.go index 42d320ee2..acd92ff44 100644 --- a/x/perp/v2/module/genesis_test.go +++ b/x/perp/v2/module/genesis_test.go @@ -70,7 +70,7 @@ func RunTestGenesis(t *testing.T, tc TestCase) { // create some params app.PerpKeeperV2.Markets.Insert(ctx, collections.Join(pair, uint64(1)), *mock.TestMarket()) app.PerpKeeperV2.MarketLastVersion.Insert(ctx, pair, types.MarketLastVersion{Version: 1}) - app.PerpKeeperV2.AMMs.Insert(ctx, pair, *mock.TestAMMDefault()) + app.PerpKeeperV2.AMMs.Insert(ctx, collections.Join(pair, uint64(1)), *mock.TestAMMDefault()) // create some positions for _, position := range tc.positions { diff --git a/x/perp/v2/types/state.pb.go b/x/perp/v2/types/state.pb.go index 22e3a654c..b1e10feb1 100644 --- a/x/perp/v2/types/state.pb.go +++ b/x/perp/v2/types/state.pb.go @@ -256,6 +256,9 @@ func (m *MarketLastVersion) GetVersion() uint64 { type AMM struct { // identifies the market this AMM belongs to Pair github_com_NibiruChain_nibiru_x_common_asset.Pair `protobuf:"bytes,1,opt,name=pair,proto3,customtype=github.com/NibiruChain/nibiru/x/common/asset.Pair" json:"pair"` + // the version of the AMM, only one AMM can exist per pair, when one is closed it cannot be reactivated, + // so a new AMM must be created, this is the version of the AMM + Version uint64 `protobuf:"varint,8,opt,name=version,proto3" json:"version,omitempty"` // the amount of base reserves this AMM has BaseReserve github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=base_reserve,json=baseReserve,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"base_reserve"` // the amount of quote reserves this AMM has @@ -303,6 +306,13 @@ func (m *AMM) XXX_DiscardUnknown() { var xxx_messageInfo_AMM proto.InternalMessageInfo +func (m *AMM) GetVersion() uint64 { + if m != nil { + return m.Version + } + return 0 +} + type Position struct { // address identifies the address owner of this position TraderAddress string `protobuf:"bytes,1,opt,name=trader_address,json=traderAddress,proto3" json:"trader_address,omitempty"` @@ -435,76 +445,76 @@ func init() { func init() { proto.RegisterFile("nibiru/perp/v2/state.proto", fileDescriptor_8f4829f34f7b8040) } var fileDescriptor_8f4829f34f7b8040 = []byte{ - // 1089 bytes of a gzipped FileDescriptorProto + // 1094 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x96, 0x5d, 0x6f, 0xdb, 0x36, - 0x17, 0xc7, 0xa3, 0xd8, 0x4d, 0x63, 0xda, 0x75, 0xfd, 0xa8, 0x4d, 0x1f, 0xa5, 0x18, 0x9c, 0xcc, - 0xc0, 0x86, 0xa0, 0x43, 0x24, 0x24, 0xbb, 0x2a, 0x76, 0xe5, 0xd7, 0xce, 0x80, 0xdf, 0x22, 0x3b, + 0x17, 0xc7, 0xa3, 0xd8, 0x4d, 0x6d, 0xda, 0x75, 0xfd, 0xa8, 0x4d, 0x1f, 0xa5, 0x18, 0x9c, 0xcc, + 0xc0, 0x86, 0xa0, 0x43, 0x25, 0x24, 0xbb, 0x2a, 0x76, 0xe5, 0xd7, 0xce, 0x80, 0xdf, 0x2a, 0x3b, 0x0b, 0x36, 0x14, 0x20, 0x28, 0x89, 0x91, 0xb9, 0x48, 0xa2, 0x42, 0x52, 0x4e, 0xba, 0x7d, 0x88, - 0xed, 0x72, 0xfb, 0x42, 0x43, 0x2f, 0x7b, 0x39, 0xec, 0xa2, 0x1b, 0x92, 0x2f, 0x32, 0x90, 0x92, - 0x1d, 0x07, 0x18, 0xb0, 0x4d, 0xe8, 0xae, 0x12, 0xf2, 0xe8, 0xfc, 0xce, 0xd1, 0xf1, 0x9f, 0x7f, - 0x0a, 0x3c, 0x8f, 0x88, 0x43, 0x58, 0x62, 0xc5, 0x98, 0xc5, 0xd6, 0xe2, 0xd8, 0xe2, 0x02, 0x09, - 0x6c, 0xc6, 0x8c, 0x0a, 0xaa, 0x57, 0xd3, 0x98, 0x29, 0x63, 0xe6, 0xe2, 0xf8, 0xf9, 0x53, 0x9f, - 0xfa, 0x54, 0x85, 0x2c, 0xf9, 0x5f, 0xfa, 0xd4, 0xf3, 0xba, 0x4b, 0x79, 0x48, 0xb9, 0xe5, 0x20, - 0x8e, 0xad, 0xc5, 0x91, 0x83, 0x05, 0x3a, 0xb2, 0x5c, 0x4a, 0xa2, 0x2c, 0xbe, 0x9b, 0xc6, 0x61, - 0x9a, 0x98, 0x2e, 0x96, 0xa9, 0x3e, 0xa5, 0x7e, 0x80, 0x2d, 0xb5, 0x72, 0x92, 0x73, 0xcb, 0x4b, - 0x18, 0x12, 0x84, 0x66, 0xa9, 0x8d, 0x1f, 0x4a, 0x60, 0x6b, 0x88, 0xd8, 0x05, 0x16, 0xfa, 0x10, - 0x14, 0x63, 0x44, 0x98, 0xa1, 0xed, 0x6b, 0x07, 0xa5, 0xd6, 0xcb, 0xb7, 0xef, 0xf7, 0x36, 0x7e, - 0x7b, 0xbf, 0x77, 0xe4, 0x13, 0x31, 0x4f, 0x1c, 0xd3, 0xa5, 0xa1, 0x35, 0x52, 0xcd, 0xb6, 0xe7, - 0x88, 0x44, 0x56, 0xf6, 0x52, 0xd7, 0x96, 0x4b, 0xc3, 0x90, 0x46, 0x16, 0xe2, 0x1c, 0x0b, 0x73, - 0x82, 0x08, 0xb3, 0x15, 0x46, 0x37, 0xc0, 0x43, 0x1c, 0x21, 0x27, 0xc0, 0x9e, 0xb1, 0xb9, 0xaf, - 0x1d, 0x6c, 0xdb, 0xcb, 0xa5, 0x8c, 0x2c, 0x30, 0xe3, 0x84, 0x46, 0x46, 0x75, 0x5f, 0x3b, 0x28, - 0xda, 0xcb, 0xa5, 0x3e, 0x07, 0x46, 0x88, 0x48, 0x24, 0x70, 0x84, 0x22, 0x17, 0xc3, 0x10, 0x31, - 0x9f, 0x44, 0x50, 0x35, 0x6c, 0x14, 0x54, 0x5b, 0x66, 0xd6, 0xd6, 0xa7, 0x6b, 0x6d, 0x65, 0xd3, - 0x49, 0xff, 0x1c, 0x72, 0xef, 0xc2, 0x12, 0x6f, 0x62, 0xcc, 0xcd, 0x0e, 0x76, 0xed, 0x67, 0x6b, - 0xbc, 0xa1, 0xc2, 0xd9, 0x92, 0xa6, 0x9f, 0x80, 0x4a, 0x88, 0xae, 0x61, 0x80, 0x17, 0x98, 0x21, - 0x1f, 0x1b, 0xc5, 0x5c, 0xf4, 0x72, 0x88, 0xae, 0x07, 0x19, 0x42, 0xff, 0x1e, 0x34, 0x02, 0x24, - 0x30, 0x17, 0xd0, 0x4d, 0xc2, 0x24, 0x40, 0x82, 0x2c, 0x30, 0x8c, 0x19, 0x0e, 0x49, 0x12, 0xc2, - 0x73, 0x86, 0x5c, 0x39, 0x76, 0xe3, 0x41, 0xae, 0x42, 0x7b, 0x29, 0xb9, 0xbd, 0x02, 0x4f, 0x52, - 0x6e, 0x2f, 0xc3, 0xea, 0xaf, 0x81, 0x8e, 0xaf, 0xdd, 0x39, 0x8a, 0x7c, 0x0c, 0xcf, 0x31, 0xce, - 0x66, 0xb6, 0x95, 0xab, 0x58, 0x6d, 0x49, 0xea, 0x61, 0x9c, 0x4e, 0xcb, 0x07, 0x06, 0x76, 0x29, - 0x7f, 0xc3, 0x05, 0x0e, 0xe1, 0x79, 0x12, 0x79, 0x6b, 0x35, 0x1e, 0xe6, 0xaa, 0xb1, 0xb3, 0xe2, - 0xf5, 0x92, 0xc8, 0x5b, 0x15, 0x72, 0xc0, 0x4e, 0x40, 0x2e, 0x13, 0xe2, 0x29, 0x8d, 0xae, 0x55, - 0xd9, 0xce, 0x55, 0xe5, 0xc9, 0x1a, 0x6c, 0x55, 0xe3, 0x5b, 0xb0, 0x1b, 0x23, 0x26, 0x08, 0x0a, - 0xe0, 0x7a, 0xad, 0xb4, 0x4e, 0x29, 0x57, 0x9d, 0xff, 0x67, 0xc0, 0xc1, 0x1d, 0x2f, 0xad, 0x75, - 0x04, 0x76, 0xe4, 0xb8, 0x48, 0xe4, 0x4b, 0x3e, 0x86, 0x38, 0xa6, 0xee, 0x1c, 0x12, 0xcf, 0x00, - 0xb2, 0x8e, 0xad, 0x67, 0x41, 0x1b, 0x09, 0xdc, 0x95, 0xa1, 0xbe, 0xa7, 0x9f, 0x82, 0xa7, 0xe2, - 0x0a, 0xc5, 0x30, 0xa0, 0xf4, 0xc2, 0x41, 0xee, 0x05, 0xbc, 0x22, 0x91, 0x47, 0xaf, 0x8c, 0xf2, - 0xbe, 0x76, 0x50, 0x3e, 0xde, 0x35, 0xd3, 0x03, 0x6d, 0x2e, 0x0f, 0xb4, 0xd9, 0xc9, 0x0e, 0x74, - 0x6b, 0x5b, 0x36, 0xfd, 0xd3, 0xef, 0x7b, 0x9a, 0xad, 0x4b, 0xc0, 0x20, 0xcb, 0x3f, 0x53, 0xe9, - 0x7a, 0x1f, 0xd4, 0x62, 0x86, 0x63, 0x44, 0x3c, 0xe8, 0x20, 0x0f, 0x7a, 0xd8, 0x11, 0x46, 0x25, - 0x43, 0x66, 0x8e, 0x21, 0xed, 0xc5, 0xcc, 0xec, 0xc5, 0x6c, 0x53, 0x12, 0xb5, 0x8a, 0x12, 0x69, - 0x57, 0xb3, 0xc4, 0x16, 0xf2, 0x3a, 0xd8, 0x11, 0xfa, 0x6b, 0x50, 0x93, 0x67, 0x67, 0xfd, 0xc5, - 0x8c, 0x47, 0x6a, 0x6e, 0xc7, 0xff, 0x6e, 0x6e, 0xaa, 0xd9, 0x6a, 0x88, 0xae, 0x7b, 0x77, 0x63, - 0x68, 0x1c, 0x82, 0xff, 0xa5, 0x86, 0x34, 0x40, 0x5c, 0x7c, 0x95, 0x19, 0xc3, 0x9a, 0x65, 0x68, - 0xf7, 0x2c, 0xa3, 0xf1, 0x4b, 0x11, 0x14, 0x9a, 0xc3, 0xe1, 0x87, 0x76, 0xaf, 0x13, 0x50, 0x91, - 0xe3, 0x80, 0x0c, 0x73, 0xcc, 0x16, 0x58, 0x59, 0x58, 0x0e, 0x7f, 0x90, 0x0c, 0x3b, 0x45, 0xe8, - 0x53, 0xf0, 0xe8, 0x32, 0xa1, 0xe2, 0x8e, 0x99, 0xcf, 0xd1, 0x2a, 0x0a, 0xb2, 0x84, 0x0e, 0x01, - 0xe0, 0x97, 0x4c, 0x40, 0x0f, 0xc7, 0x62, 0x9e, 0xd3, 0xc5, 0x4a, 0x92, 0xd0, 0x91, 0x00, 0xfd, - 0x6b, 0xa9, 0x12, 0x22, 0xad, 0x37, 0x09, 0x04, 0x89, 0x03, 0x82, 0x59, 0x4e, 0xc7, 0x7a, 0xac, - 0x38, 0xc3, 0x15, 0x46, 0x76, 0x2a, 0xa8, 0x90, 0x87, 0x8e, 0x46, 0x7e, 0x4e, 0x67, 0x2a, 0x29, - 0xc2, 0x80, 0x46, 0xbe, 0x3e, 0x06, 0xe5, 0x14, 0xc7, 0xe7, 0x94, 0x89, 0x9c, 0x2e, 0x94, 0x76, - 0x34, 0x95, 0x84, 0xc6, 0xcf, 0x45, 0xb0, 0x3d, 0xa1, 0x9c, 0x28, 0x3b, 0xfd, 0x04, 0x54, 0x05, - 0x43, 0x1e, 0x66, 0x10, 0x79, 0x1e, 0xc3, 0x9c, 0xa7, 0xba, 0xb2, 0x1f, 0xa5, 0xbb, 0xcd, 0x74, - 0x73, 0x25, 0xba, 0xcd, 0x0f, 0x23, 0xba, 0x16, 0x28, 0x72, 0xf2, 0x5d, 0x5e, 0x61, 0xa8, 0x5c, - 0xbd, 0x07, 0xb6, 0xd2, 0x6b, 0x33, 0xa7, 0x18, 0xb2, 0x6c, 0xa9, 0x56, 0x1a, 0xe3, 0x08, 0x46, - 0x54, 0x0e, 0x04, 0x05, 0x39, 0x65, 0x50, 0x91, 0x90, 0x51, 0xc6, 0xf8, 0x87, 0x57, 0xe4, 0xd6, - 0x7f, 0x73, 0x45, 0xbe, 0x04, 0xbb, 0x01, 0xe2, 0x02, 0x26, 0xb1, 0x87, 0x04, 0xf6, 0xa0, 0x13, - 0x50, 0xf7, 0x02, 0x46, 0x49, 0xe8, 0x60, 0xa6, 0xf4, 0x53, 0xb0, 0x9f, 0xc9, 0x07, 0x4e, 0xd3, - 0x78, 0x4b, 0x86, 0x47, 0x2a, 0xda, 0x40, 0xe0, 0x71, 0x76, 0xe0, 0xa6, 0x11, 0x8a, 0xf9, 0x9c, - 0x0a, 0xfd, 0x33, 0x50, 0x40, 0x61, 0xa8, 0x64, 0x51, 0x3e, 0x7e, 0x62, 0xde, 0xff, 0x8e, 0x33, - 0x9b, 0xc3, 0x61, 0x66, 0x9e, 0xf2, 0x29, 0xfd, 0x63, 0x50, 0x11, 0x24, 0xc4, 0x5c, 0xa0, 0x30, - 0x86, 0x21, 0x57, 0x7a, 0x29, 0xd8, 0xe5, 0xd5, 0xde, 0x90, 0xbf, 0xf8, 0x02, 0x94, 0x3a, 0x84, - 0xe1, 0xb4, 0xd5, 0x5d, 0xb0, 0xd3, 0xe9, 0xdb, 0xdd, 0xf6, 0xac, 0x3f, 0x1e, 0xc1, 0xd3, 0xd1, - 0x74, 0xd2, 0x6d, 0xf7, 0x7b, 0xfd, 0x6e, 0xa7, 0xb6, 0xa1, 0x6f, 0x83, 0xe2, 0x60, 0x3c, 0x7a, - 0x55, 0xd3, 0xf4, 0x12, 0x78, 0x30, 0xfd, 0x72, 0x6c, 0xcf, 0x6a, 0x9b, 0x2f, 0x7c, 0x50, 0x9d, - 0x5d, 0xa1, 0xb8, 0x8d, 0x02, 0x77, 0x1c, 0x2b, 0xc2, 0x3e, 0xf8, 0x68, 0x76, 0xd6, 0x9c, 0xc0, - 0x76, 0x73, 0xd0, 0x86, 0xe3, 0xc9, 0x5f, 0x83, 0xa6, 0x93, 0xf1, 0xac, 0xa6, 0xe9, 0x4f, 0x41, - 0xed, 0xe4, 0x74, 0x3c, 0xeb, 0xc2, 0xe6, 0x74, 0xda, 0x9d, 0xc1, 0xe9, 0x59, 0x73, 0x52, 0xdb, - 0xd4, 0x9f, 0x80, 0xc7, 0xad, 0xe6, 0xf4, 0xde, 0x66, 0xa1, 0xf5, 0xea, 0xed, 0x4d, 0x5d, 0x7b, - 0x77, 0x53, 0xd7, 0xfe, 0xb8, 0xa9, 0x6b, 0x3f, 0xde, 0xd6, 0x37, 0xde, 0xdd, 0xd6, 0x37, 0x7e, - 0xbd, 0xad, 0x6f, 0x7c, 0x73, 0xf8, 0x77, 0xa2, 0x5f, 0x7e, 0xfe, 0xaa, 0x5f, 0xcc, 0xd9, 0x52, - 0xf7, 0xd7, 0xe7, 0x7f, 0x06, 0x00, 0x00, 0xff, 0xff, 0x86, 0x95, 0x19, 0x49, 0x1d, 0x0b, 0x00, - 0x00, + 0xed, 0x72, 0xfb, 0x46, 0xbd, 0xec, 0xe5, 0xb0, 0x8b, 0xae, 0x48, 0xbe, 0xc8, 0x40, 0x4a, 0x76, + 0x1c, 0x60, 0xc0, 0x36, 0x61, 0xbd, 0x4a, 0xc8, 0xa3, 0xf3, 0xfb, 0x1f, 0x1d, 0x1f, 0xfe, 0x29, + 0xf0, 0x34, 0x22, 0x0e, 0x61, 0x89, 0x15, 0x63, 0x16, 0x5b, 0xcb, 0x63, 0x8b, 0x0b, 0x24, 0xb0, + 0x19, 0x33, 0x2a, 0xa8, 0x5e, 0x4b, 0x63, 0xa6, 0x8c, 0x99, 0xcb, 0xe3, 0xa7, 0x8f, 0x7d, 0xea, + 0x53, 0x15, 0xb2, 0xe4, 0x7f, 0xe9, 0x53, 0x4f, 0x1b, 0x2e, 0xe5, 0x21, 0xe5, 0x96, 0x83, 0x38, + 0xb6, 0x96, 0x47, 0x0e, 0x16, 0xe8, 0xc8, 0x72, 0x29, 0x89, 0xb2, 0xf8, 0x5e, 0x1a, 0x87, 0x69, + 0x62, 0xba, 0x58, 0xa5, 0xfa, 0x94, 0xfa, 0x01, 0xb6, 0xd4, 0xca, 0x49, 0xce, 0x2c, 0x2f, 0x61, + 0x48, 0x10, 0x9a, 0xa5, 0x36, 0x7f, 0x2a, 0x83, 0x9d, 0x11, 0x62, 0xe7, 0x58, 0xe8, 0x23, 0x50, + 0x8c, 0x11, 0x61, 0x86, 0x76, 0xa0, 0x1d, 0x96, 0xdb, 0x2f, 0xde, 0xbe, 0xdf, 0xdf, 0xfa, 0xfd, + 0xfd, 0xfe, 0x91, 0x4f, 0xc4, 0x22, 0x71, 0x4c, 0x97, 0x86, 0xd6, 0x58, 0x15, 0xdb, 0x59, 0x20, + 0x12, 0x59, 0xd9, 0x4b, 0x5d, 0x59, 0x2e, 0x0d, 0x43, 0x1a, 0x59, 0x88, 0x73, 0x2c, 0xcc, 0x29, + 0x22, 0xcc, 0x56, 0x18, 0xdd, 0x00, 0xf7, 0x71, 0x84, 0x9c, 0x00, 0x7b, 0xc6, 0xf6, 0x81, 0x76, + 0x58, 0xb2, 0x57, 0x4b, 0x19, 0x59, 0x62, 0xc6, 0x09, 0x8d, 0x8c, 0xda, 0x81, 0x76, 0x58, 0xb4, + 0x57, 0x4b, 0x7d, 0x01, 0x8c, 0x10, 0x91, 0x48, 0xe0, 0x08, 0x45, 0x2e, 0x86, 0x21, 0x62, 0x3e, + 0x89, 0xa0, 0x2a, 0xd8, 0x28, 0xa8, 0xb2, 0xcc, 0xac, 0xac, 0xcf, 0x37, 0xca, 0xca, 0xba, 0x93, + 0xfe, 0x79, 0xce, 0xbd, 0x73, 0x4b, 0xbc, 0x89, 0x31, 0x37, 0xbb, 0xd8, 0xb5, 0x9f, 0x6c, 0xf0, + 0x46, 0x0a, 0x67, 0x4b, 0x9a, 0xfe, 0x0a, 0x54, 0x43, 0x74, 0x05, 0x03, 0xbc, 0xc4, 0x0c, 0xf9, + 0xd8, 0x28, 0xe6, 0xa2, 0x57, 0x42, 0x74, 0x35, 0xcc, 0x10, 0xfa, 0x8f, 0xa0, 0x19, 0x20, 0x81, + 0xb9, 0x80, 0x6e, 0x12, 0x26, 0x01, 0x12, 0x64, 0x89, 0x61, 0xcc, 0x70, 0x48, 0x92, 0x10, 0x9e, + 0x31, 0xe4, 0xca, 0xb6, 0x1b, 0xf7, 0x72, 0x09, 0xed, 0xa7, 0xe4, 0xce, 0x1a, 0x3c, 0x4d, 0xb9, + 0xfd, 0x0c, 0xab, 0xbf, 0x06, 0x3a, 0xbe, 0x72, 0x17, 0x28, 0xf2, 0x31, 0x3c, 0xc3, 0x38, 0xeb, + 0xd9, 0x4e, 0x2e, 0xb1, 0xfa, 0x8a, 0xd4, 0xc7, 0x38, 0xed, 0x96, 0x0f, 0x0c, 0xec, 0x52, 0xfe, + 0x86, 0x0b, 0x1c, 0xc2, 0xb3, 0x24, 0xf2, 0x36, 0x34, 0xee, 0xe7, 0xd2, 0xd8, 0x5d, 0xf3, 0xfa, + 0x49, 0xe4, 0xad, 0x85, 0x1c, 0xb0, 0x1b, 0x90, 0x8b, 0x84, 0x78, 0x6a, 0x46, 0x37, 0x54, 0x4a, + 0xb9, 0x54, 0x1e, 0x6d, 0xc0, 0xd6, 0x1a, 0xdf, 0x83, 0xbd, 0x18, 0x31, 0x41, 0x50, 0x00, 0x37, + 0xb5, 0x52, 0x9d, 0x72, 0x2e, 0x9d, 0xff, 0x67, 0xc0, 0xe1, 0x2d, 0x2f, 0xd5, 0x3a, 0x02, 0xbb, + 0xb2, 0x5d, 0x24, 0xf2, 0x25, 0x1f, 0x43, 0x1c, 0x53, 0x77, 0x01, 0x89, 0x67, 0x00, 0xa9, 0x63, + 0xeb, 0x59, 0xd0, 0x46, 0x02, 0xf7, 0x64, 0x68, 0xe0, 0xe9, 0x27, 0xe0, 0xb1, 0xb8, 0x44, 0x31, + 0x0c, 0x28, 0x3d, 0x77, 0x90, 0x7b, 0x0e, 0x2f, 0x49, 0xe4, 0xd1, 0x4b, 0xa3, 0x72, 0xa0, 0x1d, + 0x56, 0x8e, 0xf7, 0xcc, 0xf4, 0x40, 0x9b, 0xab, 0x03, 0x6d, 0x76, 0xb3, 0x03, 0xdd, 0x2e, 0xc9, + 0xa2, 0x7f, 0xf9, 0x63, 0x5f, 0xb3, 0x75, 0x09, 0x18, 0x66, 0xf9, 0xa7, 0x2a, 0x5d, 0x1f, 0x80, + 0x7a, 0xcc, 0x70, 0x8c, 0x88, 0x07, 0x1d, 0xe4, 0x41, 0x0f, 0x3b, 0xc2, 0xa8, 0x66, 0xc8, 0xcc, + 0x31, 0xa4, 0xbd, 0x98, 0x99, 0xbd, 0x98, 0x1d, 0x4a, 0xa2, 0x76, 0x51, 0x22, 0xed, 0x5a, 0x96, + 0xd8, 0x46, 0x5e, 0x17, 0x3b, 0x42, 0x7f, 0x0d, 0xea, 0xf2, 0xec, 0x6c, 0xbe, 0x98, 0xf1, 0x40, + 0xf5, 0xed, 0xf8, 0xdf, 0xf5, 0x4d, 0x15, 0x5b, 0x0b, 0xd1, 0x55, 0xff, 0xb6, 0x0d, 0xcd, 0xe7, + 0xe0, 0x7f, 0xa9, 0x21, 0x0d, 0x11, 0x17, 0xdf, 0x64, 0xc6, 0xb0, 0x61, 0x19, 0xda, 0x1d, 0xcb, + 0x68, 0x7e, 0x28, 0x82, 0x42, 0x6b, 0x34, 0xfa, 0x08, 0xee, 0xb5, 0x12, 0x2c, 0xdd, 0xf5, 0xa8, + 0x57, 0xa0, 0x2a, 0x1b, 0x05, 0x19, 0xe6, 0x98, 0x2d, 0xb1, 0x32, 0xb7, 0x1c, 0xce, 0x21, 0x19, + 0x76, 0x8a, 0xd0, 0x67, 0xe0, 0xc1, 0x45, 0x42, 0xc5, 0x2d, 0x33, 0x9f, 0xd7, 0x55, 0x15, 0x64, + 0x05, 0x1d, 0x01, 0xc0, 0x2f, 0x98, 0x80, 0x1e, 0x8e, 0xc5, 0x22, 0xa7, 0xbf, 0x95, 0x25, 0xa1, + 0x2b, 0x01, 0xfa, 0xb7, 0x72, 0x7e, 0x88, 0x34, 0xe5, 0x24, 0x10, 0x24, 0x0e, 0x08, 0x66, 0x39, + 0xbd, 0xec, 0xa1, 0xe2, 0x8c, 0xd6, 0x18, 0x59, 0xa9, 0xa0, 0x42, 0x1e, 0x47, 0x1a, 0xf9, 0x39, + 0x3d, 0xab, 0xac, 0x08, 0x43, 0x1a, 0xf9, 0xfa, 0x04, 0x54, 0x52, 0x1c, 0x5f, 0x50, 0x26, 0x72, + 0xfa, 0x53, 0x5a, 0xd1, 0x4c, 0x12, 0x9a, 0xbf, 0x16, 0x41, 0x69, 0x4a, 0x39, 0x51, 0x46, 0xfb, + 0x19, 0xa8, 0x09, 0x86, 0x3c, 0xcc, 0x20, 0xf2, 0x3c, 0x86, 0x39, 0x4f, 0x27, 0xce, 0x7e, 0x90, + 0xee, 0xb6, 0xd2, 0xcd, 0xf5, 0x38, 0x6e, 0xff, 0x37, 0xe3, 0xd8, 0x06, 0x45, 0x4e, 0x7e, 0xc8, + 0x3b, 0x18, 0x2a, 0x57, 0xef, 0x83, 0x9d, 0xf4, 0x42, 0xcd, 0x39, 0x0c, 0x59, 0xb6, 0x9c, 0x56, + 0x1a, 0xe3, 0x08, 0x46, 0x54, 0x36, 0x04, 0x05, 0x39, 0xc7, 0xa0, 0x2a, 0x21, 0xe3, 0x8c, 0xf1, + 0x0f, 0x2f, 0xcf, 0x9d, 0x8f, 0x73, 0x79, 0xbe, 0x00, 0x7b, 0x01, 0xe2, 0x02, 0x26, 0xb1, 0x87, + 0x04, 0xf6, 0xa0, 0x13, 0x50, 0xf7, 0x1c, 0x46, 0x49, 0xe8, 0x60, 0xa6, 0xe6, 0xa7, 0x60, 0x3f, + 0x91, 0x0f, 0x9c, 0xa4, 0xf1, 0xb6, 0x0c, 0x8f, 0x55, 0xb4, 0x89, 0xc0, 0xc3, 0xec, 0xc0, 0xcd, + 0x22, 0x14, 0xf3, 0x05, 0x15, 0xfa, 0x17, 0xa0, 0x80, 0xc2, 0x50, 0x8d, 0x45, 0xe5, 0xf8, 0x91, + 0x79, 0xf7, 0x0b, 0xcf, 0x6c, 0x8d, 0x46, 0x99, 0xad, 0xca, 0xa7, 0xf4, 0x4f, 0x41, 0x55, 0x90, + 0x10, 0x73, 0x81, 0xc2, 0x18, 0x86, 0x5c, 0xcd, 0x4b, 0xc1, 0xae, 0xac, 0xf7, 0x46, 0xfc, 0xd9, + 0x57, 0xa0, 0xdc, 0x25, 0x0c, 0xa7, 0xa5, 0xee, 0x81, 0xdd, 0xee, 0xc0, 0xee, 0x75, 0xe6, 0x83, + 0xc9, 0x18, 0x9e, 0x8c, 0x67, 0xd3, 0x5e, 0x67, 0xd0, 0x1f, 0xf4, 0xba, 0xf5, 0x2d, 0xbd, 0x04, + 0x8a, 0xc3, 0xc9, 0xf8, 0x65, 0x5d, 0xd3, 0xcb, 0xe0, 0xde, 0xec, 0xeb, 0x89, 0x3d, 0xaf, 0x6f, + 0x3f, 0xf3, 0x41, 0x6d, 0x7e, 0x89, 0xe2, 0x0e, 0x0a, 0xdc, 0x49, 0xac, 0x08, 0x07, 0xe0, 0x93, + 0xf9, 0x69, 0x6b, 0x0a, 0x3b, 0xad, 0x61, 0x07, 0x4e, 0xa6, 0x7f, 0x0d, 0x9a, 0x4d, 0x27, 0xf3, + 0xba, 0xa6, 0x3f, 0x06, 0xf5, 0x57, 0x27, 0x93, 0x79, 0x0f, 0xb6, 0x66, 0xb3, 0xde, 0x1c, 0xce, + 0x4e, 0x5b, 0xd3, 0xfa, 0xb6, 0xfe, 0x08, 0x3c, 0x6c, 0xb7, 0x66, 0x77, 0x36, 0x0b, 0xed, 0x97, + 0x6f, 0xaf, 0x1b, 0xda, 0xbb, 0xeb, 0x86, 0xf6, 0xe1, 0xba, 0xa1, 0xfd, 0x7c, 0xd3, 0xd8, 0x7a, + 0x77, 0xd3, 0xd8, 0xfa, 0xed, 0xa6, 0xb1, 0xf5, 0xdd, 0xf3, 0xbf, 0x1b, 0xfa, 0xd5, 0x87, 0xb1, + 0xfa, 0xc5, 0x9c, 0x1d, 0x75, 0xb3, 0x7d, 0xf9, 0x67, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa3, 0xb5, + 0xb3, 0x3d, 0x37, 0x0b, 0x00, 0x00, } func (m *Market) Marshal() (dAtA []byte, err error) { @@ -708,6 +718,11 @@ func (m *AMM) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.Version != 0 { + i = encodeVarintState(dAtA, i, uint64(m.Version)) + i-- + dAtA[i] = 0x40 + } { size := m.TotalShort.Size() i -= size @@ -988,6 +1003,9 @@ func (m *AMM) Size() (n int) { n += 1 + l + sovState(uint64(l)) l = m.TotalShort.Size() n += 1 + l + sovState(uint64(l)) + if m.Version != 0 { + n += 1 + sovState(uint64(m.Version)) + } return n } @@ -1866,6 +1884,25 @@ func (m *AMM) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 8: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType) + } + m.Version = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowState + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Version |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipState(dAtA[iNdEx:]) From e47c89b237a7f2c805c5406d9d45cfe566ccacbe Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Fri, 8 Sep 2023 22:13:43 +0200 Subject: [PATCH 08/16] make linter --- x/perp/v2/integration/assertion/market.go | 1 + x/perp/v2/keeper/grpc_query.go | 2 +- x/perp/v2/module/abci.go | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/x/perp/v2/integration/assertion/market.go b/x/perp/v2/integration/assertion/market.go index cfe75e797..40d2240b5 100644 --- a/x/perp/v2/integration/assertion/market.go +++ b/x/perp/v2/integration/assertion/market.go @@ -2,6 +2,7 @@ package assertion import ( "fmt" + "github.com/NibiruChain/nibiru/x/common/testutil/action" sdkmath "cosmossdk.io/math" diff --git a/x/perp/v2/keeper/grpc_query.go b/x/perp/v2/keeper/grpc_query.go index 9a01fb2ca..7b1307193 100644 --- a/x/perp/v2/keeper/grpc_query.go +++ b/x/perp/v2/keeper/grpc_query.go @@ -172,7 +172,7 @@ func (q queryServer) QueryMarkets( markets := q.k.Markets.Iterate(ctx, collections.Range[collections.Pair[asset.Pair, uint64]]{}).Values() for _, market := range markets { // disabled markets are not returned - if market.Enabled == false { + if !market.Enabled { continue } diff --git a/x/perp/v2/module/abci.go b/x/perp/v2/module/abci.go index 4e77bcdc5..8b9edb281 100644 --- a/x/perp/v2/module/abci.go +++ b/x/perp/v2/module/abci.go @@ -21,7 +21,7 @@ func EndBlocker(ctx sdk.Context, k keeper.Keeper) []abci.ValidatorUpdate { } // only snapshot enabled markets - if market.Enabled == false { + if !market.Enabled { continue } From e5e5d20802fcb38952ede0e5a7cb282c5f1d4dce Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Wed, 13 Sep 2023 14:20:27 +0200 Subject: [PATCH 09/16] fix bug --- x/perp/v2/keeper/admin.go | 2 +- x/perp/v2/keeper/admin_test.go | 20 +++++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/x/perp/v2/keeper/admin.go b/x/perp/v2/keeper/admin.go index 62db25f91..44308d1ac 100644 --- a/x/perp/v2/keeper/admin.go +++ b/x/perp/v2/keeper/admin.go @@ -98,7 +98,7 @@ func (k admin) CreateMarket( // init amm amm := types.AMM{ Pair: pair, - Version: 1, + Version: lastVersion.Version, BaseReserve: baseReserve, QuoteReserve: quoteReserve, SqrtDepth: sqrtDepth, diff --git a/x/perp/v2/keeper/admin_test.go b/x/perp/v2/keeper/admin_test.go index 7f67772ef..69ff2d761 100644 --- a/x/perp/v2/keeper/admin_test.go +++ b/x/perp/v2/keeper/admin_test.go @@ -107,7 +107,7 @@ func TestEnableMarket(t *testing.T) { NewTestSuite(t).WithTestCases(tests...).Run() } -func TestCreateMarketFail(t *testing.T) { +func TestCreateMarket(t *testing.T) { pair := asset.Registry.Pair(denoms.BTC, denoms.NUSD) amm := *mock.TestAMMDefault() app, ctx := testapp.NewNibiruTestAppAndContext() @@ -142,6 +142,15 @@ func TestCreateMarketFail(t *testing.T) { require.NoError(t, err) require.Equal(t, uint64(1), lastVersion.Version) + // Check that amm and market have version 1 + amm, err = app.PerpKeeperV2.GetAMM(ctx, pair) + require.NoError(t, err) + require.Equal(t, uint64(1), amm.Version) + + market, err = app.PerpKeeperV2.GetMarket(ctx, pair) + require.NoError(t, err) + require.Equal(t, uint64(1), market.Version) + // Fail since it already exists and it is not disabled err = app.PerpKeeperV2.Admin().CreateMarket(ctx, keeper.ArgsCreateMarket{ Pair: pair, @@ -164,4 +173,13 @@ func TestCreateMarketFail(t *testing.T) { lastVersion, err = app.PerpKeeperV2.MarketLastVersion.Get(ctx, pair) require.NoError(t, err) require.Equal(t, uint64(2), lastVersion.Version) + + // Check that amm and market have version 2 + amm, err = app.PerpKeeperV2.GetAMM(ctx, pair) + require.NoError(t, err) + require.Equal(t, uint64(2), amm.Version) + + market, err = app.PerpKeeperV2.GetMarket(ctx, pair) + require.NoError(t, err) + require.Equal(t, uint64(2), market.Version) } From 5f5fdb3800d16690141433d4359f46e9bea625bc Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Wed, 13 Sep 2023 15:15:22 +0200 Subject: [PATCH 10/16] add convenience method for saving market --- x/epochs/types/identifier.go | 2 +- x/perp/v2/integration/action/market.go | 2 +- x/perp/v2/keeper/admin.go | 2 +- x/perp/v2/keeper/amm.go | 4 ++++ x/perp/v2/keeper/clearing_house_test.go | 2 +- x/perp/v2/keeper/hooks.go | 2 +- x/perp/v2/keeper/keeper.go | 2 +- x/perp/v2/keeper/twap_test.go | 4 ++-- x/perp/v2/keeper/withdraw.go | 7 +++---- x/perp/v2/module/genesis.go | 2 +- x/perp/v2/module/genesis_test.go | 2 +- 11 files changed, 17 insertions(+), 14 deletions(-) diff --git a/x/epochs/types/identifier.go b/x/epochs/types/identifier.go index 7760be60a..3dd3012cb 100644 --- a/x/epochs/types/identifier.go +++ b/x/epochs/types/identifier.go @@ -29,7 +29,7 @@ func ValidateEpochIdentifierInterface(i interface{}) error { return ValidateEpochIdentifierString(v) } -// ValidateEpochIdentifierInterface performs a stateless +// ValidateEpochIdentifierString performs a stateless // validation of the epoch ID. func ValidateEpochIdentifierString(s string) error { s = strings.TrimSpace(s) diff --git a/x/perp/v2/integration/action/market.go b/x/perp/v2/integration/action/market.go index a1e0a94fe..b00ffdb33 100644 --- a/x/perp/v2/integration/action/market.go +++ b/x/perp/v2/integration/action/market.go @@ -39,8 +39,8 @@ type createMarketAction struct { } func (c createMarketAction) Do(app *app.NibiruApp, ctx sdk.Context) (sdk.Context, error, bool) { - app.PerpKeeperV2.Markets.Insert(ctx, collections.Join(c.Market.Pair, uint64(1)), c.Market) app.PerpKeeperV2.MarketLastVersion.Insert(ctx, c.Market.Pair, types.MarketLastVersion{Version: 1}) + app.PerpKeeperV2.SaveMarket(ctx, c.Market) app.PerpKeeperV2.AMMs.Insert(ctx, collections.Join(c.AMM.Pair, uint64(1)), c.AMM) app.PerpKeeperV2.ReserveSnapshots.Insert(ctx, collections.Join(c.AMM.Pair, ctx.BlockTime()), types.ReserveSnapshot{ diff --git a/x/perp/v2/keeper/admin.go b/x/perp/v2/keeper/admin.go index 44308d1ac..7d3221a52 100644 --- a/x/perp/v2/keeper/admin.go +++ b/x/perp/v2/keeper/admin.go @@ -110,7 +110,7 @@ func (k admin) CreateMarket( return err } - k.Markets.Insert(ctx, collections.Join(pair, lastVersion.Version), market) + k.SaveMarket(ctx, market) k.AMMs.Insert(ctx, collections.Join(pair, lastVersion.Version), amm) k.MarketLastVersion.Insert(ctx, pair, lastVersion) diff --git a/x/perp/v2/keeper/amm.go b/x/perp/v2/keeper/amm.go index 7de68acf9..90115be7f 100644 --- a/x/perp/v2/keeper/amm.go +++ b/x/perp/v2/keeper/amm.go @@ -132,6 +132,10 @@ func (k Keeper) GetMarket(ctx sdk.Context, pair asset.Pair) (types.Market, error return market, nil } +func (k Keeper) SaveMarket(ctx sdk.Context, market types.Market) { + k.Markets.Insert(ctx, collections.Join(market.Pair, market.Version), market) +} + // GetAMM returns the amm with last version. func (k Keeper) GetAMM(ctx sdk.Context, pair asset.Pair) (types.AMM, error) { lastVersion, err := k.MarketLastVersion.Get(ctx, pair) diff --git a/x/perp/v2/keeper/clearing_house_test.go b/x/perp/v2/keeper/clearing_house_test.go index 4d4639bd3..e0424bf7d 100644 --- a/x/perp/v2/keeper/clearing_house_test.go +++ b/x/perp/v2/keeper/clearing_house_test.go @@ -1172,7 +1172,7 @@ func TestMarketOrderError(t *testing.T) { traderAddr := testutil.AccAddress() market := mock.TestMarket() - app.PerpKeeperV2.Markets.Insert(ctx, collections.Join(asset.Registry.Pair(denoms.BTC, denoms.NUSD), market.Version), *market) + app.PerpKeeperV2.SaveMarket(ctx, *market) app.PerpKeeperV2.MarketLastVersion.Insert(ctx, asset.Registry.Pair(denoms.BTC, denoms.NUSD), types.MarketLastVersion{Version: market.Version}) amm := mock.TestAMMDefault() app.PerpKeeperV2.AMMs.Insert(ctx, collections.Join(asset.Registry.Pair(denoms.BTC, denoms.NUSD), market.Version), *amm) diff --git a/x/perp/v2/keeper/hooks.go b/x/perp/v2/keeper/hooks.go index e5e44b669..23b46faca 100644 --- a/x/perp/v2/keeper/hooks.go +++ b/x/perp/v2/keeper/hooks.go @@ -54,7 +54,7 @@ func (k Keeper) AfterEpochEnd(ctx sdk.Context, epochIdentifier string, _ uint64) premiumFraction := clampedDivergence.Mul(indexTwap).QuoInt64(int64(intervalsPerDay)) market.LatestCumulativePremiumFraction = market.LatestCumulativePremiumFraction.Add(premiumFraction) - k.Markets.Insert(ctx, collections.Join(market.Pair, market.Version), market) + k.SaveMarket(ctx, market) _ = ctx.EventManager().EmitTypedEvent(&types.FundingRateChangedEvent{ Pair: market.Pair, diff --git a/x/perp/v2/keeper/keeper.go b/x/perp/v2/keeper/keeper.go index 8f7e5885e..e6f0a2d87 100644 --- a/x/perp/v2/keeper/keeper.go +++ b/x/perp/v2/keeper/keeper.go @@ -101,6 +101,6 @@ func (k Keeper) ChangeMarketEnabledParameter(ctx sdk.Context, pair asset.Pair, e return } market.Enabled = enabled - k.Markets.Insert(ctx, collections.Join(pair, market.Version), market) + k.SaveMarket(ctx, market) return } diff --git a/x/perp/v2/keeper/twap_test.go b/x/perp/v2/keeper/twap_test.go index 7942f08d7..e6ec59a37 100644 --- a/x/perp/v2/keeper/twap_test.go +++ b/x/perp/v2/keeper/twap_test.go @@ -113,7 +113,7 @@ func TestInvalidTwap(t *testing.T) { }) startTime := time.UnixMilli(0) - app.PerpKeeperV2.Markets.Insert(ctx, collections.Join(pair, uint64(1)), *mock.TestMarket()) + app.PerpKeeperV2.SaveMarket(ctx, *mock.TestMarket()) app.PerpKeeperV2.AMMs.Insert(ctx, collections.Join(pair, uint64(1)), *mock.TestAMMDefault()) app.PerpKeeperV2.ReserveSnapshots.Insert( ctx, collections.Join(pair, startTime), types.ReserveSnapshot{ @@ -375,7 +375,7 @@ func TestCalcTwapExtended(t *testing.T) { }) startTime := time.UnixMilli(0) - app.PerpKeeperV2.Markets.Insert(ctx, collections.Join(pair, uint64(1)), *mock.TestMarket()) + app.PerpKeeperV2.SaveMarket(ctx, *mock.TestMarket()) app.PerpKeeperV2.AMMs.Insert(ctx, collections.Join(pair, uint64(1)), *mock.TestAMMDefault()) app.PerpKeeperV2.ReserveSnapshots.Insert( ctx, collections.Join(pair, startTime), types.ReserveSnapshot{ diff --git a/x/perp/v2/keeper/withdraw.go b/x/perp/v2/keeper/withdraw.go index 18795e1db..7d12a4465 100644 --- a/x/perp/v2/keeper/withdraw.go +++ b/x/perp/v2/keeper/withdraw.go @@ -2,7 +2,6 @@ package keeper import ( sdkmath "cosmossdk.io/math" - "github.com/NibiruChain/collections" sdk "github.com/cosmos/cosmos-sdk/types" types "github.com/NibiruChain/nibiru/x/perp/v2/types" @@ -82,19 +81,19 @@ func (k Keeper) WithdrawFromVault( // IncrementPrepaidBadDebt increases the bad debt for the provided denom. func (k Keeper) IncrementPrepaidBadDebt(ctx sdk.Context, market types.Market, amount sdkmath.Int) { market.PrepaidBadDebt.Amount = market.PrepaidBadDebt.Amount.Add(amount) - k.Markets.Insert(ctx, collections.Join(market.Pair, market.Version), market) + k.SaveMarket(ctx, market) } // ZeroPrepaidBadDebt out the prepaid bad debt func (k Keeper) ZeroPrepaidBadDebt(ctx sdk.Context, market types.Market) { market.PrepaidBadDebt.Amount = sdk.ZeroInt() - k.Markets.Insert(ctx, collections.Join(market.Pair, market.Version), market) + k.SaveMarket(ctx, market) } // DecrementPrepaidBadDebt decrements the amount of bad debt prepaid by denom. func (k Keeper) DecrementPrepaidBadDebt(ctx sdk.Context, market types.Market, amount sdkmath.Int) { market.PrepaidBadDebt.Amount = market.PrepaidBadDebt.Amount.Sub(amount) - k.Markets.Insert(ctx, collections.Join(market.Pair, market.Version), market) + k.SaveMarket(ctx, market) } /* diff --git a/x/perp/v2/module/genesis.go b/x/perp/v2/module/genesis.go index 35de73549..2223d3599 100644 --- a/x/perp/v2/module/genesis.go +++ b/x/perp/v2/module/genesis.go @@ -20,7 +20,7 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState) } for _, m := range genState.Markets { - k.Markets.Insert(ctx, collections.Join(m.Pair, m.Version), m) + k.SaveMarket(ctx, m) } for _, g := range genState.MarketLastVersions { diff --git a/x/perp/v2/module/genesis_test.go b/x/perp/v2/module/genesis_test.go index acd92ff44..d3c45fc86 100644 --- a/x/perp/v2/module/genesis_test.go +++ b/x/perp/v2/module/genesis_test.go @@ -68,7 +68,7 @@ func RunTestGenesis(t *testing.T, tc TestCase) { pair := asset.Registry.Pair(denoms.BTC, denoms.NUSD) // create some params - app.PerpKeeperV2.Markets.Insert(ctx, collections.Join(pair, uint64(1)), *mock.TestMarket()) + app.PerpKeeperV2.SaveMarket(ctx, *mock.TestMarket()) app.PerpKeeperV2.MarketLastVersion.Insert(ctx, pair, types.MarketLastVersion{Version: 1}) app.PerpKeeperV2.AMMs.Insert(ctx, collections.Join(pair, uint64(1)), *mock.TestAMMDefault()) From c08dd5322792b9dab80cd71b2b08b5d3d57672c1 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Wed, 13 Sep 2023 15:44:16 +0200 Subject: [PATCH 11/16] add new methods --- x/perp/v2/integration/action/market.go | 2 +- x/perp/v2/keeper/admin.go | 4 +--- x/perp/v2/keeper/amm.go | 10 ++++++++-- x/perp/v2/keeper/clearing_house_test.go | 2 +- x/perp/v2/keeper/swap.go | 5 ++--- x/perp/v2/keeper/twap_test.go | 4 ++-- x/perp/v2/module/genesis.go | 8 ++++---- x/perp/v2/module/genesis_test.go | 2 +- 8 files changed, 20 insertions(+), 17 deletions(-) diff --git a/x/perp/v2/integration/action/market.go b/x/perp/v2/integration/action/market.go index b00ffdb33..fa5635504 100644 --- a/x/perp/v2/integration/action/market.go +++ b/x/perp/v2/integration/action/market.go @@ -41,7 +41,7 @@ type createMarketAction struct { func (c createMarketAction) Do(app *app.NibiruApp, ctx sdk.Context) (sdk.Context, error, bool) { app.PerpKeeperV2.MarketLastVersion.Insert(ctx, c.Market.Pair, types.MarketLastVersion{Version: 1}) app.PerpKeeperV2.SaveMarket(ctx, c.Market) - app.PerpKeeperV2.AMMs.Insert(ctx, collections.Join(c.AMM.Pair, uint64(1)), c.AMM) + app.PerpKeeperV2.SaveAMM(ctx, c.AMM) app.PerpKeeperV2.ReserveSnapshots.Insert(ctx, collections.Join(c.AMM.Pair, ctx.BlockTime()), types.ReserveSnapshot{ Amm: c.AMM, diff --git a/x/perp/v2/keeper/admin.go b/x/perp/v2/keeper/admin.go index 7d3221a52..fda963c64 100644 --- a/x/perp/v2/keeper/admin.go +++ b/x/perp/v2/keeper/admin.go @@ -3,8 +3,6 @@ package keeper import ( "fmt" - "github.com/NibiruChain/collections" - sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" @@ -111,7 +109,7 @@ func (k admin) CreateMarket( } k.SaveMarket(ctx, market) - k.AMMs.Insert(ctx, collections.Join(pair, lastVersion.Version), amm) + k.SaveAMM(ctx, amm) k.MarketLastVersion.Insert(ctx, pair, lastVersion) return nil diff --git a/x/perp/v2/keeper/amm.go b/x/perp/v2/keeper/amm.go index 90115be7f..935bbae0d 100644 --- a/x/perp/v2/keeper/amm.go +++ b/x/perp/v2/keeper/amm.go @@ -42,7 +42,7 @@ func (k Keeper) EditPriceMultiplier( // Do the re-peg amm.PriceMultiplier = newPriceMultiplier - k.AMMs.Insert(ctx, collections.Join(pair, amm.Version), amm) + k.SaveAMM(ctx, amm) return nil } @@ -73,7 +73,7 @@ func (k Keeper) EditSwapInvariant(ctx sdk.Context, pair asset.Pair, newSwapInvar return err } - k.AMMs.Insert(ctx, collections.Join(pair, amm.Version), amm) + k.SaveAMM(ctx, amm) return nil } @@ -132,6 +132,7 @@ func (k Keeper) GetMarket(ctx sdk.Context, pair asset.Pair) (types.Market, error return market, nil } +// SaveMarket saves the market by pair and version. func (k Keeper) SaveMarket(ctx sdk.Context, market types.Market) { k.Markets.Insert(ctx, collections.Join(market.Pair, market.Version), market) } @@ -150,3 +151,8 @@ func (k Keeper) GetAMM(ctx sdk.Context, pair asset.Pair) (types.AMM, error) { return amm, nil } + +// SaveAMM saves the amm by pair and version. +func (k Keeper) SaveAMM(ctx sdk.Context, amm types.AMM) { + k.AMMs.Insert(ctx, collections.Join(amm.Pair, amm.Version), amm) +} diff --git a/x/perp/v2/keeper/clearing_house_test.go b/x/perp/v2/keeper/clearing_house_test.go index e0424bf7d..a87f1fac6 100644 --- a/x/perp/v2/keeper/clearing_house_test.go +++ b/x/perp/v2/keeper/clearing_house_test.go @@ -1175,7 +1175,7 @@ func TestMarketOrderError(t *testing.T) { app.PerpKeeperV2.SaveMarket(ctx, *market) app.PerpKeeperV2.MarketLastVersion.Insert(ctx, asset.Registry.Pair(denoms.BTC, denoms.NUSD), types.MarketLastVersion{Version: market.Version}) amm := mock.TestAMMDefault() - app.PerpKeeperV2.AMMs.Insert(ctx, collections.Join(asset.Registry.Pair(denoms.BTC, denoms.NUSD), market.Version), *amm) + app.PerpKeeperV2.SaveAMM(ctx, *amm) app.PerpKeeperV2.ReserveSnapshots.Insert(ctx, collections.Join(amm.Pair, ctx.BlockTime()), types.ReserveSnapshot{ Amm: *amm, TimestampMs: ctx.BlockTime().UnixMilli(), diff --git a/x/perp/v2/keeper/swap.go b/x/perp/v2/keeper/swap.go index 7d0155452..97e40fd1a 100644 --- a/x/perp/v2/keeper/swap.go +++ b/x/perp/v2/keeper/swap.go @@ -1,7 +1,6 @@ package keeper import ( - "github.com/NibiruChain/collections" sdk "github.com/cosmos/cosmos-sdk/types" types "github.com/NibiruChain/nibiru/x/perp/v2/types" @@ -67,7 +66,7 @@ func (k Keeper) SwapQuoteAsset( return nil, sdk.Dec{}, err } - k.AMMs.Insert(ctx, collections.Join(amm.Pair, amm.Version), amm) + k.SaveAMM(ctx, amm) return &amm, baseAssetDelta, nil } @@ -109,7 +108,7 @@ func (k Keeper) SwapBaseAsset( return nil, sdk.Dec{}, err } - k.AMMs.Insert(ctx, collections.Join(amm.Pair, amm.Version), amm) + k.SaveAMM(ctx, amm) return &amm, quoteAssetDelta, err } diff --git a/x/perp/v2/keeper/twap_test.go b/x/perp/v2/keeper/twap_test.go index e6ec59a37..03129df35 100644 --- a/x/perp/v2/keeper/twap_test.go +++ b/x/perp/v2/keeper/twap_test.go @@ -114,7 +114,7 @@ func TestInvalidTwap(t *testing.T) { startTime := time.UnixMilli(0) app.PerpKeeperV2.SaveMarket(ctx, *mock.TestMarket()) - app.PerpKeeperV2.AMMs.Insert(ctx, collections.Join(pair, uint64(1)), *mock.TestAMMDefault()) + app.PerpKeeperV2.SaveAMM(ctx, *mock.TestAMMDefault()) app.PerpKeeperV2.ReserveSnapshots.Insert( ctx, collections.Join(pair, startTime), types.ReserveSnapshot{ Amm: *mock.TestAMMDefault(), @@ -376,7 +376,7 @@ func TestCalcTwapExtended(t *testing.T) { startTime := time.UnixMilli(0) app.PerpKeeperV2.SaveMarket(ctx, *mock.TestMarket()) - app.PerpKeeperV2.AMMs.Insert(ctx, collections.Join(pair, uint64(1)), *mock.TestAMMDefault()) + app.PerpKeeperV2.SaveAMM(ctx, *mock.TestAMMDefault()) app.PerpKeeperV2.ReserveSnapshots.Insert( ctx, collections.Join(pair, startTime), types.ReserveSnapshot{ Amm: *mock.TestAMMDefault(), diff --git a/x/perp/v2/module/genesis.go b/x/perp/v2/module/genesis.go index 2223d3599..3a04001b4 100644 --- a/x/perp/v2/module/genesis.go +++ b/x/perp/v2/module/genesis.go @@ -27,15 +27,15 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState) k.MarketLastVersion.Insert(ctx, g.Pair, types.MarketLastVersion{Version: g.Version}) } - for _, a := range genState.Amms { - pair := a.Pair - k.AMMs.Insert(ctx, collections.Join(a.Pair, a.Version), a) + for _, amm := range genState.Amms { + pair := amm.Pair + k.SaveAMM(ctx, amm) timestampMs := ctx.BlockTime().UnixMilli() k.ReserveSnapshots.Insert( ctx, collections.Join(pair, time.UnixMilli(timestampMs)), types.ReserveSnapshot{ - Amm: a, + Amm: amm, TimestampMs: timestampMs, }, ) diff --git a/x/perp/v2/module/genesis_test.go b/x/perp/v2/module/genesis_test.go index d3c45fc86..63d1db263 100644 --- a/x/perp/v2/module/genesis_test.go +++ b/x/perp/v2/module/genesis_test.go @@ -70,7 +70,7 @@ func RunTestGenesis(t *testing.T, tc TestCase) { // create some params app.PerpKeeperV2.SaveMarket(ctx, *mock.TestMarket()) app.PerpKeeperV2.MarketLastVersion.Insert(ctx, pair, types.MarketLastVersion{Version: 1}) - app.PerpKeeperV2.AMMs.Insert(ctx, collections.Join(pair, uint64(1)), *mock.TestAMMDefault()) + app.PerpKeeperV2.SaveAMM(ctx, *mock.TestAMMDefault()) // create some positions for _, position := range tc.positions { From 83f6f97f7aaf6054c778b249dc944ea57df848ca Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Wed, 13 Sep 2023 16:05:46 +0200 Subject: [PATCH 12/16] remove comments --- x/perp/v2/keeper/hooks.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/x/perp/v2/keeper/hooks.go b/x/perp/v2/keeper/hooks.go index 23b46faca..51beabff8 100644 --- a/x/perp/v2/keeper/hooks.go +++ b/x/perp/v2/keeper/hooks.go @@ -13,12 +13,11 @@ import ( "github.com/NibiruChain/nibiru/x/perp/v2/types" ) -func (k Keeper) BeforeEpochStart(ctx sdk.Context, epochIdentifier string, epochNumber uint64) { +func (k Keeper) BeforeEpochStart(_ sdk.Context, _ string, _ uint64) { } func (k Keeper) AfterEpochEnd(ctx sdk.Context, epochIdentifier string, _ uint64) { for _, market := range k.Markets.Iterate(ctx, collections.Range[collections.Pair[asset.Pair, uint64]]{}).Values() { - // TODO (reviewer): this needs to be fixed for only enabled markets if !market.Enabled || epochIdentifier != market.FundingRateEpochId { return } From 1e65fc08c50e77665dd3044e5c7e600d7956bbfd Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Fri, 15 Sep 2023 11:41:17 +0200 Subject: [PATCH 13/16] add query versioned markets --- proto/nibiru/perp/v2/query.proto | 4 +- x/perp/v2/client/cli/query.go | 13 ++- x/perp/v2/integration/action/market.go | 31 +++-- x/perp/v2/integration/action/query.go | 25 +++- x/perp/v2/keeper/grpc_query.go | 4 +- x/perp/v2/keeper/grpc_query_test.go | 16 ++- x/perp/v2/keeper/twap.go | 2 +- x/perp/v2/types/query.pb.go | 154 ++++++++++++++++--------- x/perp/v2/types/query.pb.gw.go | 18 +++ 9 files changed, 193 insertions(+), 74 deletions(-) diff --git a/proto/nibiru/perp/v2/query.proto b/proto/nibiru/perp/v2/query.proto index c2182bbda..e15cb30df 100644 --- a/proto/nibiru/perp/v2/query.proto +++ b/proto/nibiru/perp/v2/query.proto @@ -119,7 +119,9 @@ message AmmMarket { AMM amm = 2 [ (gogoproto.nullable) = false ]; } -message QueryMarketsRequest {} +message QueryMarketsRequest { + bool versioned = 1; +} message QueryMarketsResponse { repeated AmmMarket amm_markets = 1 [ (gogoproto.nullable) = false ]; diff --git a/x/perp/v2/client/cli/query.go b/x/perp/v2/client/cli/query.go index fa9601263..e72d3ee2f 100644 --- a/x/perp/v2/client/cli/query.go +++ b/x/perp/v2/client/cli/query.go @@ -12,6 +12,8 @@ import ( types "github.com/NibiruChain/nibiru/x/perp/v2/types" ) +const FlagVersioned = "versioned" + // GetQueryCmd returns the cli query commands for this module func GetQueryCmd() *cobra.Command { // Group stablecoin queries under a subcommand @@ -156,7 +158,14 @@ func CmdQueryMarkets() *cobra.Command { queryClient := types.NewQueryClient(clientCtx) - res, err := queryClient.QueryMarkets(cmd.Context(), &types.QueryMarketsRequest{}) + versioned, err := cmd.Flags().GetBool(FlagVersioned) + if err != nil { + return err + } + + res, err := queryClient.QueryMarkets(cmd.Context(), &types.QueryMarketsRequest{ + Versioned: versioned, + }) if err != nil { return err } @@ -165,6 +174,8 @@ func CmdQueryMarkets() *cobra.Command { }, } + cmd.Flags().Bool(FlagVersioned, false, "show all markets with version, enabled and disabled") + flags.AddQueryFlagsToCmd(cmd) return cmd diff --git a/x/perp/v2/integration/action/market.go b/x/perp/v2/integration/action/market.go index fa5635504..e61e41cf9 100644 --- a/x/perp/v2/integration/action/market.go +++ b/x/perp/v2/integration/action/market.go @@ -52,7 +52,7 @@ func (c createMarketAction) Do(app *app.NibiruApp, ctx sdk.Context) (sdk.Context } // CreateCustomMarket creates a market with custom parameters -func CreateCustomMarket(pair asset.Pair, marketModifiers ...marketModifier) action.Action { +func CreateCustomMarket(pair asset.Pair, marketModifiers ...MarketModifier) action.Action { market := types.DefaultMarket(pair) amm := types.AMM{ Pair: pair, @@ -75,33 +75,33 @@ func CreateCustomMarket(pair asset.Pair, marketModifiers ...marketModifier) acti } } -type marketModifier func(market *types.Market, amm *types.AMM) +type MarketModifier func(market *types.Market, amm *types.AMM) -func WithPrepaidBadDebt(amount sdkmath.Int) marketModifier { +func WithPrepaidBadDebt(amount sdkmath.Int) MarketModifier { return func(market *types.Market, amm *types.AMM) { market.PrepaidBadDebt = sdk.NewCoin(market.Pair.QuoteDenom(), amount) } } -func WithPricePeg(newValue sdk.Dec) marketModifier { +func WithPricePeg(newValue sdk.Dec) MarketModifier { return func(market *types.Market, amm *types.AMM) { amm.PriceMultiplier = newValue } } -func WithTotalLong(amount sdk.Dec) marketModifier { +func WithTotalLong(amount sdk.Dec) MarketModifier { return func(market *types.Market, amm *types.AMM) { amm.TotalLong = amount } } -func WithTotalShort(amount sdk.Dec) marketModifier { +func WithTotalShort(amount sdk.Dec) MarketModifier { return func(market *types.Market, amm *types.AMM) { amm.TotalShort = amount } } -func WithSqrtDepth(amount sdk.Dec) marketModifier { +func WithSqrtDepth(amount sdk.Dec) MarketModifier { return func(market *types.Market, amm *types.AMM) { amm.SqrtDepth = amount amm.BaseReserve = amount @@ -109,18 +109,31 @@ func WithSqrtDepth(amount sdk.Dec) marketModifier { } } -func WithLatestMarketCPF(amount sdk.Dec) marketModifier { +func WithLatestMarketCPF(amount sdk.Dec) MarketModifier { return func(market *types.Market, amm *types.AMM) { market.LatestCumulativePremiumFraction = amount } } -func WithMaxFundingRate(amount sdk.Dec) marketModifier { +func WithMaxFundingRate(amount sdk.Dec) MarketModifier { return func(market *types.Market, amm *types.AMM) { market.MaxFundingRate = amount } } +func WithVersion(version uint64) MarketModifier { + return func(market *types.Market, amm *types.AMM) { + market.Version = version + amm.Version = version + } +} + +func WithEnabled(enabled bool) MarketModifier { + return func(market *types.Market, amm *types.AMM) { + market.Enabled = enabled + } +} + type editPriceMultiplier struct { pair asset.Pair newValue sdk.Dec diff --git a/x/perp/v2/integration/action/query.go b/x/perp/v2/integration/action/query.go index 06aa705e6..0928cfae7 100644 --- a/x/perp/v2/integration/action/query.go +++ b/x/perp/v2/integration/action/query.go @@ -131,7 +131,11 @@ func (q queryPositionNotFound) Do(app *app.NibiruApp, ctx sdk.Context) (sdk.Cont Trader: q.traderAddress.String(), }) if !errors.Is(err, collections.ErrNotFound) { - return ctx, fmt.Errorf("expected position not found, but found a position for pair %s, trader %s", q.pair, q.traderAddress), false + return ctx, fmt.Errorf( + "expected position not found, but found a position for pair %s, trader %s", + q.pair, + q.traderAddress, + ), false } return ctx, nil, false @@ -145,13 +149,16 @@ func QueryPositionNotFound(pair asset.Pair, traderAddress sdk.AccAddress) action } type queryMarkets struct { + versioned bool allResponseCheckers []QueryMarketsChecker } func (q queryMarkets) Do(app *app.NibiruApp, ctx sdk.Context) (sdk.Context, error, bool) { queryServer := keeper.NewQuerier(app.PerpKeeperV2) - resp, err := queryServer.QueryMarkets(sdk.WrapSDKContext(ctx), &types.QueryMarketsRequest{}) + resp, err := queryServer.QueryMarkets(sdk.WrapSDKContext(ctx), &types.QueryMarketsRequest{ + Versioned: q.versioned, + }) if err != nil { return ctx, err, false } @@ -165,8 +172,10 @@ func (q queryMarkets) Do(app *app.NibiruApp, ctx sdk.Context) (sdk.Context, erro return ctx, nil, false } -func QueryMarkets(responseCheckers ...QueryMarketsChecker) action.Action { +// QueryMarkets queries all markets, versioned contains active and inactive markets +func QueryMarkets(versioned bool, responseCheckers ...QueryMarketsChecker) action.Action { return queryMarkets{ + versioned: versioned, allResponseCheckers: responseCheckers, } } @@ -188,6 +197,16 @@ func QueryMarkets_MarketsShouldContain(expectedMarket types.Market) QueryMarkets } } +func QueryMarkets_ShouldLength(length int) QueryMarketsChecker { + return func(resp []types.AmmMarket) error { + if len(resp) != length { + return fmt.Errorf("expected markets to have length %d, got %d", length, len(resp)) + } + + return nil + } +} + type queryModuleAccounts struct { allResponseCheckers []QueryModuleAccountsChecker } diff --git a/x/perp/v2/keeper/grpc_query.go b/x/perp/v2/keeper/grpc_query.go index 7b1307193..72be07dc6 100644 --- a/x/perp/v2/keeper/grpc_query.go +++ b/x/perp/v2/keeper/grpc_query.go @@ -164,7 +164,7 @@ func (q queryServer) ModuleAccounts( } func (q queryServer) QueryMarkets( - goCtx context.Context, _ *types.QueryMarketsRequest, + goCtx context.Context, req *types.QueryMarketsRequest, ) (*types.QueryMarketsResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) @@ -172,7 +172,7 @@ func (q queryServer) QueryMarkets( markets := q.k.Markets.Iterate(ctx, collections.Range[collections.Pair[asset.Pair, uint64]]{}).Values() for _, market := range markets { // disabled markets are not returned - if !market.Enabled { + if !req.Versioned && !market.Enabled { continue } diff --git a/x/perp/v2/keeper/grpc_query_test.go b/x/perp/v2/keeper/grpc_query_test.go index 4fc736d94..09302cac4 100644 --- a/x/perp/v2/keeper/grpc_query_test.go +++ b/x/perp/v2/keeper/grpc_query_test.go @@ -348,7 +348,7 @@ func TestQueryMarkets(t *testing.T) { ), ). Then( - QueryMarkets(QueryMarkets_MarketsShouldContain(types.DefaultMarket(pair))), + QueryMarkets(false, QueryMarkets_MarketsShouldContain(types.DefaultMarket(pair))), QueryModuleAccounts(QueryModuleAccounts_ModulesBalanceShouldBe( map[string]sdk.Coins{ "perp_ef": sdk.NewCoins( @@ -358,6 +358,20 @@ func TestQueryMarkets(t *testing.T) { }, )), ), + TC("versioned, all markets (active and inactive)").Given( + CreateCustomMarket("BTC:USD", WithVersion(1), WithEnabled(true)), + CreateCustomMarket("ETC:USD", WithVersion(1), WithEnabled(false)), + CreateCustomMarket("ETC:USD", WithVersion(2), WithEnabled(true)), + ).Then( + QueryMarkets(true, QueryMarkets_ShouldLength(3)), + ), + TC("not versioned, only active markets").Given( + CreateCustomMarket("BTC:USD", WithVersion(1), WithEnabled(true)), + CreateCustomMarket("ETC:USD", WithVersion(1), WithEnabled(false)), + CreateCustomMarket("ETC:USD", WithVersion(2), WithEnabled(true)), + ).Then( + QueryMarkets(true, QueryMarkets_ShouldLength(3)), + ), } NewTestSuite(t).WithTestCases(tc...).Run() diff --git a/x/perp/v2/keeper/twap.go b/x/perp/v2/keeper/twap.go index 05aef231a..b84f261ac 100644 --- a/x/perp/v2/keeper/twap.go +++ b/x/perp/v2/keeper/twap.go @@ -11,7 +11,7 @@ import ( ) /* -Gets the time-weighted average price from [ ctx.BlockTime() - interval, ctx.BlockTime() ) +CalcTwap Gets the time-weighted average price from [ ctx.BlockTime() - interval, ctx.BlockTime() ) Note the open-ended right bracket. args: diff --git a/x/perp/v2/types/query.pb.go b/x/perp/v2/types/query.pb.go index f36919ad8..b66a0e70f 100644 --- a/x/perp/v2/types/query.pb.go +++ b/x/perp/v2/types/query.pb.go @@ -512,6 +512,7 @@ func (m *AmmMarket) GetAmm() AMM { } type QueryMarketsRequest struct { + Versioned bool `protobuf:"varint,1,opt,name=versioned,proto3" json:"versioned,omitempty"` } func (m *QueryMarketsRequest) Reset() { *m = QueryMarketsRequest{} } @@ -547,6 +548,13 @@ func (m *QueryMarketsRequest) XXX_DiscardUnknown() { var xxx_messageInfo_QueryMarketsRequest proto.InternalMessageInfo +func (m *QueryMarketsRequest) GetVersioned() bool { + if m != nil { + return m.Versioned + } + return false +} + type QueryMarketsResponse struct { AmmMarkets []AmmMarket `protobuf:"bytes,1,rep,name=amm_markets,json=ammMarkets,proto3" json:"amm_markets"` } @@ -609,63 +617,64 @@ func init() { func init() { proto.RegisterFile("nibiru/perp/v2/query.proto", fileDescriptor_fc8f0be94fac333f) } var fileDescriptor_fc8f0be94fac333f = []byte{ - // 887 bytes of a gzipped FileDescriptorProto + // 904 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x56, 0x4f, 0x8f, 0xdb, 0x44, - 0x14, 0x8f, 0x93, 0x74, 0xdb, 0x7d, 0x69, 0x23, 0x98, 0xb6, 0x8b, 0xe3, 0x56, 0x4e, 0x6a, 0x4a, - 0xba, 0xb4, 0xaa, 0x87, 0x0d, 0x5c, 0x40, 0x1c, 0x68, 0x5a, 0x51, 0x71, 0x48, 0x95, 0x1a, 0x21, - 0x10, 0x1c, 0xa2, 0x89, 0x33, 0xf2, 0x5a, 0x8d, 0x67, 0x5c, 0x8f, 0xb3, 0xa2, 0x95, 0xe0, 0xd0, - 0x4f, 0x80, 0xe8, 0x47, 0xe0, 0x04, 0x57, 0xbe, 0x44, 0x8f, 0x95, 0xb8, 0xa0, 0x1e, 0x0a, 0xda, - 0xe5, 0x83, 0x20, 0x8f, 0x67, 0xb2, 0xb1, 0x93, 0xdd, 0x44, 0x7b, 0x8a, 0x3d, 0xef, 0xf7, 0xde, - 0xfb, 0xfd, 0xde, 0x9f, 0x71, 0xc0, 0x62, 0xe1, 0x38, 0x4c, 0x66, 0x38, 0xa6, 0x49, 0x8c, 0x0f, - 0x7a, 0xf8, 0xe9, 0x8c, 0x26, 0xcf, 0xdc, 0x38, 0xe1, 0x29, 0x47, 0xcd, 0xdc, 0xe6, 0x66, 0x36, - 0xf7, 0xa0, 0x67, 0x5d, 0x09, 0x78, 0xc0, 0xa5, 0x09, 0x67, 0x4f, 0x39, 0xca, 0xba, 0x1e, 0x70, - 0x1e, 0x4c, 0x29, 0x26, 0x71, 0x88, 0x09, 0x63, 0x3c, 0x25, 0x69, 0xc8, 0x99, 0x50, 0xd6, 0x72, - 0x7c, 0x91, 0x92, 0x94, 0x2a, 0x9b, 0xed, 0x73, 0x11, 0x71, 0x81, 0xc7, 0x44, 0x50, 0x7c, 0xb0, - 0x37, 0xa6, 0x29, 0xd9, 0xc3, 0x3e, 0x0f, 0x99, 0xb2, 0xdf, 0x5e, 0xb4, 0x4b, 0x62, 0x73, 0x54, - 0x4c, 0x82, 0x90, 0xc9, 0x44, 0x39, 0xd6, 0xc1, 0x70, 0xf5, 0x71, 0x86, 0x18, 0x72, 0x11, 0xca, - 0xfc, 0x1e, 0x7d, 0x3a, 0xa3, 0x22, 0x45, 0x3b, 0xb0, 0x95, 0x26, 0x64, 0x42, 0x13, 0xd3, 0xe8, - 0x18, 0xbb, 0xdb, 0x9e, 0x7a, 0x73, 0x7c, 0xd8, 0x29, 0x3b, 0x88, 0x98, 0x33, 0x41, 0xd1, 0x57, - 0xb0, 0x1d, 0xeb, 0x43, 0xd3, 0xe8, 0xd4, 0x76, 0x1b, 0xbd, 0x0f, 0xdc, 0x62, 0x29, 0xdc, 0x82, - 0xab, 0xf6, 0xec, 0xd7, 0x5f, 0xbd, 0x6d, 0x57, 0xbc, 0x63, 0x6f, 0xc7, 0x87, 0x56, 0x01, 0xf9, - 0x75, 0xca, 0x13, 0xaa, 0x99, 0x7d, 0x09, 0x70, 0x2c, 0x43, 0xb2, 0x6b, 0xf4, 0xba, 0x6e, 0xae, - 0xd9, 0xcd, 0x34, 0xbb, 0x79, 0x33, 0x94, 0x66, 0x77, 0x48, 0x02, 0xed, 0xeb, 0x2d, 0x78, 0x3a, - 0xbf, 0x19, 0x60, 0xad, 0xca, 0xa2, 0xe4, 0x7c, 0xbe, 0x2c, 0xc7, 0x2c, 0xcb, 0xd1, 0x9e, 0x4b, - 0x0a, 0xd0, 0xc3, 0x02, 0xc9, 0xaa, 0x24, 0x79, 0x6b, 0x2d, 0xc9, 0x3c, 0x75, 0x81, 0xe5, 0x4f, - 0x70, 0xa5, 0x54, 0xb4, 0xbc, 0x0a, 0x03, 0xa8, 0xc7, 0x24, 0x54, 0xdd, 0xe9, 0x7f, 0x9a, 0xe5, - 0x7f, 0xf3, 0xb6, 0xbd, 0x17, 0x84, 0xe9, 0xfe, 0x6c, 0xec, 0xfa, 0x3c, 0xc2, 0x8f, 0x24, 0xd7, - 0xfb, 0xfb, 0x24, 0x64, 0x58, 0x4d, 0xd3, 0x8f, 0xd8, 0xe7, 0x51, 0xc4, 0x19, 0x26, 0x42, 0xd0, - 0xd4, 0x1d, 0x92, 0x30, 0xf1, 0x64, 0x98, 0x85, 0x76, 0x57, 0x0b, 0xed, 0x7e, 0x53, 0x2d, 0x0d, - 0xc8, 0xbc, 0x3e, 0x9f, 0xc1, 0x05, 0x2d, 0x57, 0x35, 0x61, 0x5d, 0x79, 0xe6, 0x78, 0xf4, 0x03, - 0xbc, 0xab, 0x9f, 0x47, 0x8c, 0x67, 0x3f, 0x64, 0x9a, 0x27, 0xee, 0xbb, 0x4a, 0x49, 0x77, 0x41, - 0x89, 0x9a, 0xe7, 0xfc, 0xe7, 0xae, 0x98, 0x3c, 0xc1, 0xe9, 0xb3, 0x98, 0x0a, 0xf7, 0x01, 0xf5, - 0xbd, 0x77, 0x74, 0xa0, 0x47, 0x2a, 0x0e, 0xfa, 0x06, 0x9a, 0x33, 0x96, 0x50, 0x32, 0x0d, 0x9f, - 0xd3, 0xc9, 0x28, 0x66, 0x53, 0xb3, 0x76, 0xa6, 0xc8, 0x97, 0x8e, 0xa3, 0x0c, 0xd9, 0x14, 0x3d, - 0x86, 0x8b, 0x11, 0x49, 0x82, 0x90, 0x8d, 0x92, 0xac, 0x33, 0x66, 0xfd, 0x4c, 0x41, 0x1b, 0x79, - 0x0c, 0x2f, 0x0b, 0xe1, 0x5c, 0x57, 0x03, 0x38, 0xe0, 0x93, 0xd9, 0x94, 0xde, 0xf3, 0x7d, 0x3e, - 0x63, 0xa9, 0xde, 0x40, 0xc7, 0x87, 0x6b, 0x2b, 0xad, 0xaa, 0xfe, 0x0f, 0xe0, 0x02, 0x51, 0x67, - 0x6a, 0x3c, 0x9d, 0x72, 0xfd, 0x95, 0xcf, 0xb7, 0x61, 0xba, 0xdf, 0x27, 0x53, 0xc2, 0x7c, 0xbd, - 0x6a, 0x73, 0x4f, 0xe7, 0x77, 0x03, 0xd0, 0x32, 0x0c, 0x21, 0xa8, 0x33, 0x12, 0x51, 0xb5, 0xfb, - 0xf2, 0x19, 0x99, 0x70, 0x9e, 0x4c, 0x26, 0x09, 0x15, 0x42, 0xcd, 0x88, 0x7e, 0x45, 0x14, 0xce, - 0x8f, 0x73, 0x47, 0xb3, 0x26, 0x99, 0xb4, 0x0a, 0x93, 0xae, 0x67, 0xfc, 0x3e, 0x0f, 0x59, 0xff, - 0xa3, 0x8c, 0xc0, 0x1f, 0xff, 0xb4, 0x77, 0x37, 0x28, 0x58, 0xe6, 0x20, 0x3c, 0x1d, 0xdb, 0x61, - 0xb0, 0x7d, 0x2f, 0x8a, 0x06, 0x24, 0x79, 0x42, 0x53, 0xf4, 0x09, 0x6c, 0x45, 0xf2, 0x49, 0x0d, - 0xdf, 0x4e, 0x59, 0x7c, 0x8e, 0x53, 0x82, 0x15, 0x16, 0xdd, 0x81, 0x1a, 0x89, 0x22, 0xb5, 0x8f, - 0x97, 0x97, 0xea, 0x35, 0x18, 0x28, 0x7c, 0x86, 0x72, 0xae, 0xc2, 0xe5, 0xbc, 0x01, 0xd2, 0x77, - 0xde, 0x97, 0xef, 0xd4, 0x46, 0xce, 0x8f, 0x55, 0x43, 0xbe, 0x80, 0x06, 0x89, 0xa2, 0x51, 0x9e, - 0x49, 0xf7, 0xa4, 0xb5, 0x94, 0x43, 0x2b, 0x50, 0x99, 0x80, 0xe8, 0x03, 0xd1, 0xfb, 0xf3, 0x1c, - 0x9c, 0x93, 0xa1, 0xd1, 0xcf, 0x70, 0xa9, 0xb0, 0x75, 0xe8, 0xe6, 0x9a, 0x9b, 0x54, 0x52, 0xb3, - 0x36, 0xbb, 0x6f, 0x9d, 0xce, 0x8b, 0xbf, 0xfe, 0x7b, 0x59, 0xb5, 0x90, 0x89, 0x4b, 0x5f, 0x99, - 0xf9, 0x82, 0xbe, 0x30, 0xa0, 0x59, 0xbc, 0xe6, 0xd1, 0xe9, 0xb1, 0x75, 0x75, 0xac, 0xee, 0x3a, - 0x98, 0xe2, 0x70, 0x43, 0x72, 0xb8, 0x86, 0x5a, 0x27, 0x71, 0x10, 0xe8, 0xa5, 0x01, 0x68, 0xf9, - 0x82, 0x46, 0x1f, 0x9e, 0x9a, 0x61, 0xf1, 0x53, 0x61, 0xdd, 0xde, 0x04, 0xaa, 0x08, 0x75, 0x25, - 0xa1, 0x0e, 0xb2, 0x4f, 0x22, 0x34, 0x12, 0x32, 0xfd, 0xaf, 0x06, 0x34, 0x8b, 0x2b, 0x89, 0x56, - 0xa7, 0x59, 0xb9, 0xd5, 0xd6, 0x9d, 0x8d, 0xb0, 0x8a, 0xd3, 0x2d, 0xc9, 0xe9, 0x06, 0x6a, 0x97, - 0x39, 0x45, 0x12, 0x3f, 0xd2, 0x6b, 0x8c, 0x9e, 0xc3, 0xc5, 0xc5, 0x99, 0x44, 0xef, 0xaf, 0xce, - 0x52, 0x18, 0x64, 0xeb, 0xe6, 0xe9, 0x20, 0xc5, 0xa1, 0x2d, 0x39, 0xb4, 0xd0, 0x7b, 0x4b, 0x1c, - 0x72, 0x60, 0xff, 0xe1, 0xab, 0x43, 0xdb, 0x78, 0x7d, 0x68, 0x1b, 0xff, 0x1e, 0xda, 0xc6, 0x2f, - 0x47, 0x76, 0xe5, 0xf5, 0x91, 0x5d, 0xf9, 0xfb, 0xc8, 0xae, 0x7c, 0x7f, 0x77, 0xdd, 0xd7, 0x48, - 0x87, 0x92, 0xeb, 0x3e, 0xde, 0x92, 0x7f, 0x49, 0x3e, 0xfe, 0x3f, 0x00, 0x00, 0xff, 0xff, 0x66, - 0x89, 0x0c, 0x4b, 0x5c, 0x09, 0x00, 0x00, + 0x14, 0x5f, 0xef, 0x6e, 0xb7, 0xbb, 0x6f, 0xdb, 0x15, 0x4c, 0xcb, 0xe2, 0xb8, 0x2b, 0x27, 0x35, + 0x25, 0x5d, 0x5a, 0xd5, 0xc3, 0xa6, 0x5c, 0x40, 0x1c, 0x68, 0x5a, 0x51, 0x71, 0x48, 0x95, 0x1a, + 0x21, 0x10, 0x1c, 0xa2, 0x89, 0x33, 0xf2, 0x8e, 0x1a, 0xcf, 0xb8, 0x1e, 0x27, 0xa2, 0x95, 0xe0, + 0xd0, 0x4f, 0x80, 0xe8, 0x47, 0xe0, 0x04, 0x57, 0xbe, 0x44, 0x8f, 0x95, 0xb8, 0xa0, 0x1e, 0x0a, + 0xda, 0xe5, 0x83, 0x20, 0x8f, 0x67, 0x92, 0xd8, 0x49, 0x37, 0x51, 0x4f, 0xb1, 0xfd, 0x7e, 0xef, + 0xbd, 0xdf, 0xef, 0xfd, 0x99, 0x09, 0x38, 0x9c, 0xf5, 0x59, 0x3a, 0xc2, 0x09, 0x4d, 0x13, 0x3c, + 0x6e, 0xe1, 0xc7, 0x23, 0x9a, 0x3e, 0xf1, 0x93, 0x54, 0x64, 0x02, 0xed, 0x15, 0x36, 0x3f, 0xb7, + 0xf9, 0xe3, 0x96, 0x73, 0x39, 0x12, 0x91, 0x50, 0x26, 0x9c, 0x3f, 0x15, 0x28, 0xe7, 0x20, 0x12, + 0x22, 0x1a, 0x52, 0x4c, 0x12, 0x86, 0x09, 0xe7, 0x22, 0x23, 0x19, 0x13, 0x5c, 0x6a, 0x6b, 0x35, + 0xbe, 0xcc, 0x48, 0x46, 0xb5, 0xcd, 0x0d, 0x85, 0x8c, 0x85, 0xc4, 0x7d, 0x22, 0x29, 0x1e, 0x1f, + 0xf5, 0x69, 0x46, 0x8e, 0x70, 0x28, 0x18, 0xd7, 0xf6, 0x1b, 0xb3, 0x76, 0x45, 0x6c, 0x82, 0x4a, + 0x48, 0xc4, 0xb8, 0x4a, 0x54, 0x60, 0x3d, 0x0c, 0xef, 0x3d, 0xcc, 0x11, 0x5d, 0x21, 0x99, 0xca, + 0x1f, 0xd0, 0xc7, 0x23, 0x2a, 0x33, 0xb4, 0x0f, 0x5b, 0x59, 0x4a, 0x06, 0x34, 0xb5, 0xad, 0x86, + 0x75, 0xb8, 0x13, 0xe8, 0x37, 0x2f, 0x84, 0xfd, 0xaa, 0x83, 0x4c, 0x04, 0x97, 0x14, 0x7d, 0x05, + 0x3b, 0x89, 0xf9, 0x68, 0x5b, 0x8d, 0x8d, 0xc3, 0xdd, 0xd6, 0x87, 0x7e, 0xb9, 0x14, 0x7e, 0xc9, + 0xd5, 0x78, 0xb6, 0x37, 0x5f, 0xbc, 0xae, 0xaf, 0x05, 0x53, 0x6f, 0x2f, 0x84, 0x5a, 0x09, 0xf9, + 0x75, 0x26, 0x52, 0x6a, 0x98, 0x7d, 0x09, 0x30, 0x95, 0xa1, 0xd8, 0xed, 0xb6, 0x9a, 0x7e, 0xa1, + 0xd9, 0xcf, 0x35, 0xfb, 0x45, 0x33, 0xb4, 0x66, 0xbf, 0x4b, 0x22, 0xe3, 0x1b, 0xcc, 0x78, 0x7a, + 0xbf, 0x59, 0xe0, 0x2c, 0xca, 0xa2, 0xe5, 0x7c, 0x3e, 0x2f, 0xc7, 0xae, 0xca, 0x31, 0x9e, 0x73, + 0x0a, 0xd0, 0xfd, 0x12, 0xc9, 0x75, 0x45, 0xf2, 0xfa, 0x52, 0x92, 0x45, 0xea, 0x12, 0xcb, 0x9f, + 0xe0, 0x72, 0xa5, 0x68, 0x45, 0x15, 0x3a, 0xb0, 0x99, 0x10, 0xa6, 0xbb, 0xd3, 0xfe, 0x34, 0xcf, + 0xff, 0xea, 0x75, 0xfd, 0x28, 0x62, 0xd9, 0xf1, 0xa8, 0xef, 0x87, 0x22, 0xc6, 0x0f, 0x14, 0xd7, + 0xbb, 0xc7, 0x84, 0x71, 0xac, 0xa7, 0xe9, 0x47, 0x1c, 0x8a, 0x38, 0x16, 0x1c, 0x13, 0x29, 0x69, + 0xe6, 0x77, 0x09, 0x4b, 0x03, 0x15, 0x66, 0xa6, 0xdd, 0xeb, 0xa5, 0x76, 0xbf, 0x5a, 0xaf, 0x0c, + 0xc8, 0xa4, 0x3e, 0x9f, 0xc1, 0xb6, 0x91, 0xab, 0x9b, 0xb0, 0xac, 0x3c, 0x13, 0x3c, 0xfa, 0x01, + 0xde, 0x35, 0xcf, 0x3d, 0x2e, 0xf2, 0x1f, 0x32, 0x2c, 0x12, 0xb7, 0x7d, 0xad, 0xa4, 0x39, 0xa3, + 0x44, 0xcf, 0x73, 0xf1, 0x73, 0x4b, 0x0e, 0x1e, 0xe1, 0xec, 0x49, 0x42, 0xa5, 0x7f, 0x8f, 0x86, + 0xc1, 0x3b, 0x26, 0xd0, 0x03, 0x1d, 0x07, 0x7d, 0x03, 0x7b, 0x23, 0x9e, 0x52, 0x32, 0x64, 0x4f, + 0xe9, 0xa0, 0x97, 0xf0, 0xa1, 0xbd, 0xf1, 0x56, 0x91, 0x2f, 0x4e, 0xa3, 0x74, 0xf9, 0x10, 0x3d, + 0x84, 0x0b, 0x31, 0x49, 0x23, 0xc6, 0x7b, 0x69, 0xde, 0x19, 0x7b, 0xf3, 0xad, 0x82, 0xee, 0x16, + 0x31, 0x82, 0x3c, 0x84, 0x77, 0xa0, 0x07, 0xb0, 0x23, 0x06, 0xa3, 0x21, 0xbd, 0x13, 0x86, 0x62, + 0xc4, 0x33, 0xb3, 0x81, 0x5e, 0x08, 0x57, 0x16, 0x5a, 0x75, 0xfd, 0xef, 0xc1, 0x36, 0xd1, 0xdf, + 0xf4, 0x78, 0x7a, 0xd5, 0xfa, 0x6b, 0x9f, 0x6f, 0x59, 0x76, 0xdc, 0x26, 0x43, 0xc2, 0x43, 0xb3, + 0x6a, 0x13, 0x4f, 0xef, 0x77, 0x0b, 0xd0, 0x3c, 0x0c, 0x21, 0xd8, 0xe4, 0x24, 0xa6, 0x7a, 0xf7, + 0xd5, 0x33, 0xb2, 0xe1, 0x3c, 0x19, 0x0c, 0x52, 0x2a, 0xa5, 0x9e, 0x11, 0xf3, 0x8a, 0x28, 0x9c, + 0xef, 0x17, 0x8e, 0xf6, 0x86, 0x62, 0x52, 0x2b, 0x4d, 0xba, 0x99, 0xf1, 0xbb, 0x82, 0xf1, 0xf6, + 0xc7, 0x39, 0x81, 0x3f, 0xfe, 0xa9, 0x1f, 0xae, 0x50, 0xb0, 0xdc, 0x41, 0x06, 0x26, 0xb6, 0xc7, + 0x61, 0xe7, 0x4e, 0x1c, 0x77, 0x48, 0xfa, 0x88, 0x66, 0xe8, 0x13, 0xd8, 0x8a, 0xd5, 0x93, 0x1e, + 0xbe, 0xfd, 0xaa, 0xf8, 0x02, 0xa7, 0x05, 0x6b, 0x2c, 0xba, 0x09, 0x1b, 0x24, 0x8e, 0xf5, 0x3e, + 0x5e, 0x9a, 0xab, 0x57, 0xa7, 0xa3, 0xf1, 0x39, 0xca, 0xbb, 0x0d, 0x97, 0x8a, 0x06, 0x28, 0xdf, + 0xc9, 0xc9, 0x78, 0x00, 0x3b, 0x63, 0x9a, 0x4a, 0x26, 0x38, 0x1d, 0xa8, 0xe4, 0xdb, 0xc1, 0xf4, + 0x83, 0xf7, 0x9d, 0xde, 0xd7, 0x89, 0x93, 0x6e, 0xd7, 0x17, 0xb0, 0x4b, 0xe2, 0xb8, 0x57, 0xf0, + 0x30, 0x1d, 0xab, 0xcd, 0x31, 0x30, 0xfa, 0x34, 0x0f, 0x20, 0xe6, 0x83, 0x6c, 0xfd, 0x79, 0x0e, + 0xce, 0xa9, 0xd0, 0xe8, 0x67, 0xb8, 0x58, 0xda, 0x49, 0x74, 0x6d, 0xc9, 0x39, 0xab, 0x88, 0x3b, + 0xab, 0x9d, 0xc6, 0x5e, 0xe3, 0xd9, 0x5f, 0xff, 0x3d, 0x5f, 0x77, 0x90, 0x8d, 0x2b, 0x77, 0xd0, + 0x64, 0x7d, 0x9f, 0x59, 0xb0, 0x57, 0xbe, 0x04, 0xd0, 0xd9, 0xb1, 0x4d, 0xed, 0x9c, 0xe6, 0x32, + 0x98, 0xe6, 0x70, 0x55, 0x71, 0xb8, 0x82, 0x6a, 0x6f, 0xe2, 0x20, 0xd1, 0x73, 0x0b, 0xd0, 0xfc, + 0xf1, 0x8d, 0x3e, 0x3a, 0x33, 0xc3, 0xec, 0x45, 0xe2, 0xdc, 0x58, 0x05, 0xaa, 0x09, 0x35, 0x15, + 0xa1, 0x06, 0x72, 0xdf, 0x44, 0xa8, 0x27, 0x55, 0xfa, 0x5f, 0x2d, 0xd8, 0x2b, 0x2f, 0x2c, 0x5a, + 0x9c, 0x66, 0xe1, 0xce, 0x3b, 0x37, 0x57, 0xc2, 0x6a, 0x4e, 0xd7, 0x15, 0xa7, 0xab, 0xa8, 0x5e, + 0xe5, 0x14, 0x2b, 0x7c, 0xcf, 0x2c, 0x39, 0x7a, 0x0a, 0x17, 0x66, 0x67, 0x12, 0x7d, 0xb0, 0x38, + 0x4b, 0x69, 0xcc, 0x9d, 0x6b, 0x67, 0x83, 0x34, 0x87, 0xba, 0xe2, 0x50, 0x43, 0xef, 0xcf, 0x71, + 0x28, 0x80, 0xed, 0xfb, 0x2f, 0x4e, 0x5c, 0xeb, 0xe5, 0x89, 0x6b, 0xfd, 0x7b, 0xe2, 0x5a, 0xbf, + 0x9c, 0xba, 0x6b, 0x2f, 0x4f, 0xdd, 0xb5, 0xbf, 0x4f, 0xdd, 0xb5, 0xef, 0x6f, 0x2d, 0xbb, 0xab, + 0x4c, 0x28, 0x75, 0x18, 0xf4, 0xb7, 0xd4, 0x1f, 0x96, 0xdb, 0xff, 0x07, 0x00, 0x00, 0xff, 0xff, + 0xbb, 0xf9, 0xd2, 0xa6, 0x7a, 0x09, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -1324,6 +1333,16 @@ func (m *QueryMarketsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.Versioned { + i-- + if m.Versioned { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x8 + } return len(dAtA) - i, nil } @@ -1533,6 +1552,9 @@ func (m *QueryMarketsRequest) Size() (n int) { } var l int _ = l + if m.Versioned { + n += 2 + } return n } @@ -2657,6 +2679,26 @@ func (m *QueryMarketsRequest) Unmarshal(dAtA []byte) error { return fmt.Errorf("proto: QueryMarketsRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Versioned", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Versioned = bool(v != 0) default: iNdEx = preIndex skippy, err := skipQuery(dAtA[iNdEx:]) diff --git a/x/perp/v2/types/query.pb.gw.go b/x/perp/v2/types/query.pb.gw.go index 155f87eb2..d7f2bee0d 100644 --- a/x/perp/v2/types/query.pb.gw.go +++ b/x/perp/v2/types/query.pb.gw.go @@ -159,10 +159,21 @@ func local_request_Query_ModuleAccounts_0(ctx context.Context, marshaler runtime } +var ( + filter_Query_QueryMarkets_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + func request_Query_QueryMarkets_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryMarketsRequest var metadata runtime.ServerMetadata + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_QueryMarkets_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := client.QueryMarkets(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err @@ -172,6 +183,13 @@ func local_request_Query_QueryMarkets_0(ctx context.Context, marshaler runtime.M var protoReq QueryMarketsRequest var metadata runtime.ServerMetadata + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_QueryMarkets_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := server.QueryMarkets(ctx, &protoReq) return msg, metadata, err From bee302629940bd54369781f26ec123e82f860988 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Fri, 15 Sep 2023 11:43:25 +0200 Subject: [PATCH 14/16] update query markets --- x/perp/v2/client/cli/query.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/x/perp/v2/client/cli/query.go b/x/perp/v2/client/cli/query.go index e72d3ee2f..de4a8e464 100644 --- a/x/perp/v2/client/cli/query.go +++ b/x/perp/v2/client/cli/query.go @@ -149,7 +149,9 @@ func CmdQueryMarkets() *cobra.Command { cmd := &cobra.Command{ Use: "markets", Short: "query all market info", - Args: cobra.NoArgs, + Long: "query all market info, including version, if --versioned is set to true all markets will be shown, " + + "active and inactive, otherwise only active markets will be shown", + Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { clientCtx, err := client.GetClientQueryContext(cmd) if err != nil { From 5f54d0bd0022599278897beac2a070f364ded502 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Fri, 15 Sep 2023 12:00:00 +0200 Subject: [PATCH 15/16] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 72feed4fd..e1d38f190 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -73,6 +73,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * [#1503](https://github.com/NibiruChain/nibiru/pull/1503) - feat(wasm): add Oracle Exchange Rate query for wasm * [#1543](https://github.com/NibiruChain/nibiru/pull/1543) - epic(devgas): devgas module for incentivizing smart contract * [#1559](https://github.com/NibiruChain/nibiru/pull/1559) - feat: add versions to markets to allow to disable them +* [#1585](https://github.com/NibiruChain/nibiru/pull/1585) - feat: include flag versioned in query markets to allow to query disabled markets ### Bug Fixes From d405bf9b98f34de55c591a0fbbbb0030b821b2c7 Mon Sep 17 00:00:00 2001 From: Unique-Divine Date: Tue, 19 Sep 2023 00:15:46 -0500 Subject: [PATCH 16/16] docs(perp): small docs improvements for CLI and proto comment --- proto/nibiru/perp/v2/genesis.proto | 2 + proto/nibiru/tokenfactory/v1/state.proto | 91 ++++++++++++++++++++++++ x/perp/v2/client/cli/query.go | 10 +-- x/perp/v2/types/genesis.pb.go | 2 + 4 files changed, 101 insertions(+), 4 deletions(-) create mode 100644 proto/nibiru/tokenfactory/v1/state.proto diff --git a/proto/nibiru/perp/v2/genesis.proto b/proto/nibiru/perp/v2/genesis.proto index 592af5202..86a7ee0c4 100644 --- a/proto/nibiru/perp/v2/genesis.proto +++ b/proto/nibiru/perp/v2/genesis.proto @@ -10,6 +10,8 @@ import "nibiru/perp/v2/state.proto"; option go_package = "github.com/NibiruChain/nibiru/x/perp/v2/types"; // GenesisState defines the perp module's genesis state. +// Thge genesis state is used not only to start the network but also useful for +// exporting and importing state during network upgrades. message GenesisState { repeated Market markets = 2 [ (gogoproto.nullable) = false ]; diff --git a/proto/nibiru/tokenfactory/v1/state.proto b/proto/nibiru/tokenfactory/v1/state.proto new file mode 100644 index 000000000..255398aa2 --- /dev/null +++ b/proto/nibiru/tokenfactory/v1/state.proto @@ -0,0 +1,91 @@ +syntax = "proto3"; + +package nibiru.tokenfactory.v1; + +import "gogoproto/gogo.proto"; +import "cosmos_proto/cosmos.proto"; +import "cosmos/base/v1beta1/coin.proto"; + +option go_package = "github.com/NibiruChain/nibiru/x/tokenfactory/types"; + +// DenomAuthorityMetadata specifies metadata foraddresses that have specific +// capabilities over a token factory denom. Right now there is only one Admin +// permission, but is planned to be extended to the future. +message DenomAuthorityMetadata { + option (gogoproto.equal) = true; + + // Admin: Bech32 address of the admin for the tokefactory denom. Can be empty + // for no admin. + string admin = 1 [ (gogoproto.moretags) = "yaml:\"admin\"" ]; +} + +// ModuleParams defines the parameters for the tokenfactory module. +// +// ### On Denom Creation Costs +// +// We'd like for fees to be paid by the user/signer of a ransaction, but in many +// casess, token creation is abstracted away behind a smart contract. Setting a +// nonzero `denom_creation_fee` would force each contract to handle collecting +// and paying a fees for denom (factory/{contract-addr}/{subdenom}) creation on +// behalf of the end user. +// +// For IBC token transfers, it's unclear who should pay the feeā€”the contract, +// the relayer, or the original sender? +// > "Charging fees will mess up composability, the same way Terra transfer tax +// caused all kinds of headaches for contract devs." - @ethanfrey +// +// ### Recommended Solution +// +// Have the end user (signer) pay fees directly in the form of higher gas costs. +// This way, contracts won't need to handle collecting or paying fees. And for +// IBC, the gas costs are already paid by the original sender and can be +// estimated by the relayer. It's easier to tune gas costs to make spam +// prohibitively expensive since there are per-transaction and per-block gas +// limits. +// +// See https://github.com/CosmWasm/token-factory/issues/11 for the initial +// discussion of the issue with @ethanfrey and @valardragon. +message ModuleParams { + // Adds gas consumption to the execution of `MsgCreateDenom` as a method of + // spam prevention. Defaults to 10 NIBI. + uint64 denom_creation_gas_consume = 1 + [ (gogoproto.moretags) = "yaml:\"denom_creation_gas_consume\"" ]; +} + +// TFDenom is a token factory (TF) denom. The canonical representation is +// "tf/{creator}/{subdenom}", its unique denomination in the x/bank module. +message TFDenom { + option (gogoproto.goproto_stringer) = false; + option (gogoproto.stringer) = false; + + // Creator: Bech32 address of the creator of the denom. + string creator = 1; + // Subdenom: Unique suffix of a token factory denom. A subdenom is specific + // to a given creator. It is the name given during a token factory "Mint". + string subdenom = 2; +} + +// ---------------------------------------------- +// Genesis +// ---------------------------------------------- + +// GenesisState for the Token Factory module. +message GenesisState { + ModuleParams params = 1 [ (gogoproto.nullable) = false ]; + + repeated GenesisDenom factory_denoms = 2 [ + (gogoproto.moretags) = "yaml:\"factory_denoms\"", + (gogoproto.nullable) = false + ]; +} + +// GenesisDenom defines a tokenfactory denoms in the genesis state. +message GenesisDenom { + option (gogoproto.equal) = true; + + string denom = 1 [ (gogoproto.moretags) = "yaml:\"denom\"" ]; + DenomAuthorityMetadata authority_metadata = 2 [ + (gogoproto.moretags) = "yaml:\"authority_metadata\"", + (gogoproto.nullable) = false + ]; +} diff --git a/x/perp/v2/client/cli/query.go b/x/perp/v2/client/cli/query.go index de4a8e464..12967a4a0 100644 --- a/x/perp/v2/client/cli/query.go +++ b/x/perp/v2/client/cli/query.go @@ -148,9 +148,11 @@ func CmdQueryModuleAccounts() *cobra.Command { func CmdQueryMarkets() *cobra.Command { cmd := &cobra.Command{ Use: "markets", - Short: "query all market info", - Long: "query all market info, including version, if --versioned is set to true all markets will be shown, " + - "active and inactive, otherwise only active markets will be shown", + Short: "Query all market info", + Long: ` +Query all market info. By default, only active tradable markets are shown. +If --versioned is to to true, the query will return all markets including the +inactive ones.`, Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { clientCtx, err := client.GetClientQueryContext(cmd) @@ -176,7 +178,7 @@ func CmdQueryMarkets() *cobra.Command { }, } - cmd.Flags().Bool(FlagVersioned, false, "show all markets with version, enabled and disabled") + cmd.Flags().Bool(FlagVersioned, false, "toggles whether to include inactive markets") flags.AddQueryFlagsToCmd(cmd) diff --git a/x/perp/v2/types/genesis.pb.go b/x/perp/v2/types/genesis.pb.go index 1ed62a548..2e5f22760 100644 --- a/x/perp/v2/types/genesis.pb.go +++ b/x/perp/v2/types/genesis.pb.go @@ -28,6 +28,8 @@ var _ = math.Inf const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package // GenesisState defines the perp module's genesis state. +// Thge genesis state is used not only to start the network but also useful for +// exporting and importing state during network upgrades. type GenesisState struct { Markets []Market `protobuf:"bytes,2,rep,name=markets,proto3" json:"markets"` Amms []AMM `protobuf:"bytes,3,rep,name=amms,proto3" json:"amms"`