diff --git a/.gitmodules b/.gitmodules index ac88c34b0..e826f596b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -18,7 +18,7 @@ path = deps/juno url = https://github.com/CosmosContracts/juno.git [submodule "deps/osmosis"] - # Commit: v16.1.1-no-fees + # Commit: v20.5.0-no-fees path = deps/osmosis url = https://github.com/Stride-Labs/osmosis.git [submodule "deps/stargaze"] diff --git a/Makefile b/Makefile index b095fe814..99632af02 100644 --- a/Makefile +++ b/Makefile @@ -151,6 +151,12 @@ upgrade-integration-tests-part-1: start-docker-all start-upgrade-integration-tes setup-ics: UPGRADE_HEIGHT=150 bash $(DOCKERNET_HOME)/upgrades/setup_ics.sh +############################################################################### +### LocalNet ### +############################################################################### +start-local-node: + @bash scripts/start_local_node.sh + ############################################################################### ### Local to Mainnet ### ############################################################################### diff --git a/app/app.go b/app/app.go index d42ca579e..804b23dd2 100644 --- a/app/app.go +++ b/app/app.go @@ -590,6 +590,7 @@ func NewStrideApp( keys[stakeibcmoduletypes.StoreKey], keys[stakeibcmoduletypes.MemStoreKey], app.GetSubspace(stakeibcmoduletypes.ModuleName), + authtypes.NewModuleAddress(govtypes.ModuleName).String(), app.AccountKeeper, app.BankKeeper, app.ICAControllerKeeper, diff --git a/app/apptesting/test_helpers.go b/app/apptesting/test_helpers.go index 6ad11e6f3..ee6432706 100644 --- a/app/apptesting/test_helpers.go +++ b/app/apptesting/test_helpers.go @@ -12,6 +12,8 @@ import ( "github.com/cosmos/cosmos-sdk/baseapp" codectypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/bech32" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" "github.com/cosmos/gogoproto/proto" @@ -231,7 +233,10 @@ func (s *AppTestHelper) CreateICAChannel(owner string) (channelID, portID string _, transferChannelExists := s.App.IBCKeeper.ChannelKeeper.GetChannel(s.Ctx, ibctesting.TransferPort, ibctesting.FirstChannelID) if !transferChannelExists { ownerSplit := strings.Split(owner, ".") - s.Require().Equal(2, len(ownerSplit), "owner should be of the form: {HostZone}.{AccountName}") + isHostZoneICA := len(ownerSplit) == 2 + isTradeRouteICA := len(ownerSplit) == 3 + s.Require().True(isHostZoneICA || isTradeRouteICA, + "owner should be either of the form: {chainId}.{AccountName} or {chainId}.{rewarDenom}-{hostDenom}.{accountName}") hostChainID := ownerSplit[0] s.CreateTransferChannel(hostChainID) @@ -352,6 +357,34 @@ func (s *AppTestHelper) UpdateChannelState(portId, channelId string, channelStat s.App.IBCKeeper.ChannelKeeper.SetChannel(s.Ctx, portId, channelId, channel) } +// Helper function to check if an ICA was submitted by seeing if the sequence number incremented +func (s *AppTestHelper) CheckICATxSubmitted(portId, channelId string, icaFunction func() error) { + // Get the sequence before the tested funciton is run + startSequence := s.MustGetNextSequenceNumber(portId, channelId) + + // Run the test function and confirm there's no error + err := icaFunction() + s.Require().NoError(err, "no error expected executing tested function") + + // Check that the sequence number incremented + endSequence := s.MustGetNextSequenceNumber(portId, channelId) + s.Require().Equal(startSequence+1, endSequence, "sequence number should have incremented from tested function") +} + +// Helper function to check if an ICA was NOT submitted by seeing if the sequence number did not increment +func (s *AppTestHelper) CheckICATxNotSubmitted(portId, channelId string, icaFunction func() error) { + // Get the sequence before the tested funciton is run + startSequence := s.MustGetNextSequenceNumber(portId, channelId) + + // Run the test function and confirm there's no error + err := icaFunction() + s.Require().NoError(err, "no error expected executing tested function") + + // Check that the sequence number did not change + endSequence := s.MustGetNextSequenceNumber(portId, channelId) + s.Require().Equal(startSequence, endSequence, "sequence number should NOT have incremented from tested function") +} + // Constructs an ICA Packet Acknowledgement compatible with ibc-go v5+ func ICAPacketAcknowledgement(t *testing.T, msgType string, msgResponses []proto.Message) channeltypes.Acknowledgement { txMsgData := &sdk.TxMsgData{ @@ -409,6 +442,13 @@ func (s *AppTestHelper) GetIBCDenomTrace(denom string) transfertypes.DenomTrace return transfertypes.ParseDenomTrace(prefixedDenom) } +// Helper function to get the next sequence number for testing when an ICA was submitted +func (s *AppTestHelper) MustGetNextSequenceNumber(portId, channelId string) uint64 { + sequence, found := s.App.StakeibcKeeper.IBCKeeper.ChannelKeeper.GetNextSequenceSend(s.Ctx, portId, channelId) + s.Require().True(found, "sequence number for port %s and channel %s was not found", portId, channelId) + return sequence +} + // Creates and stores an IBC denom from a base denom on transfer channel-0 // This is only required for tests that use the transfer keeper and require that the IBC // denom is present in the store @@ -437,6 +477,46 @@ func (s *AppTestHelper) MockClientLatestHeight(height uint64) { s.App.IBCKeeper.ClientKeeper.SetClientState(s.Ctx, FirstClientId, &clientState) } +// Helper function to mock out a client and connection to test +// mapping from connection ID back to chain ID +// This also mocks out the consensus state to enable testing registering interchain accounts +func (s *AppTestHelper) MockClientAndConnection(chainId, clientId, connectionId string) { + clientHeight := clienttypes.Height{ + RevisionHeight: uint64(s.Ctx.BlockHeight()), + } + clientState := tendermint.ClientState{ + ChainId: chainId, + LatestHeight: clientHeight, + TrustingPeriod: time.Minute * 10, + } + s.App.IBCKeeper.ClientKeeper.SetClientState(s.Ctx, clientId, &clientState) + + consensusState := tendermint.ConsensusState{ + Timestamp: s.Ctx.BlockTime(), + } + s.App.IBCKeeper.ClientKeeper.SetClientConsensusState(s.Ctx, clientId, clientHeight, &consensusState) + + connection := connectiontypes.ConnectionEnd{ + ClientId: clientId, + Versions: []*connectiontypes.Version{connectiontypes.DefaultIBCVersion}, + } + s.App.IBCKeeper.ConnectionKeeper.SetConnection(s.Ctx, connectionId, connection) +} + +// Helper function to mock out an ICA address +func (s *AppTestHelper) MockICAChannel(connectionId, channelId, owner, address string) { + // Create an open channel with the ICA port + portId, _ := icatypes.NewControllerPortID(owner) + channel := channeltypes.Channel{ + State: channeltypes.OPEN, + } + s.App.IBCKeeper.ChannelKeeper.SetChannel(s.Ctx, portId, channelId, channel) + + // Then set the address and make the channel active + s.App.ICAControllerKeeper.SetInterchainAccountAddress(s.Ctx, connectionId, portId, address) + s.App.ICAControllerKeeper.SetActiveChannelID(s.Ctx, connectionId, portId, channelId) +} + func (s *AppTestHelper) ConfirmUpgradeSucceededs(upgradeName string, upgradeHeight int64) { s.Ctx = s.Ctx.WithBlockHeight(upgradeHeight - 1) plan := upgradetypes.Plan{Name: upgradeName, Height: upgradeHeight} @@ -452,6 +532,23 @@ func (s *AppTestHelper) ConfirmUpgradeSucceededs(upgradeName string, upgradeHeig }) } +// Returns the bank store key prefix for an address and denom +// Useful for testing balance ICQs +func (s *AppTestHelper) GetBankStoreKeyPrefix(address, denom string) []byte { + _, addressBz, err := bech32.DecodeAndConvert(address) + s.Require().NoError(err, "no error expected when bech decoding address") + return append(banktypes.CreateAccountBalancesPrefix(addressBz), []byte(denom)...) +} + +// Extracts the address and denom from a bank store prefix +// Useful for testing balance ICQs as it can confirm that the serialized query request +// data has the proper address and denom +func (s *AppTestHelper) ExtractAddressAndDenomFromBankPrefix(data []byte) (address, denom string) { + addressBz, denom, err := banktypes.AddressAndDenomFromBalancesStore(data[1:]) // Remove BalancePrefix byte + s.Require().NoError(err, "no error expected when getting address and denom from balance store") + return addressBz.String(), denom +} + // Generates a valid and invalid test address (used for non-keeper tests) func GenerateTestAddrs() (string, string) { pk1 := ed25519.GenPrivKey().PubKey() diff --git a/app/proposals_whitelisting.go b/app/proposals_whitelisting.go index 94bcac310..3b5247755 100644 --- a/app/proposals_whitelisting.go +++ b/app/proposals_whitelisting.go @@ -32,6 +32,9 @@ var WhiteListModule = map[string]struct{}{ "/cosmos.upgrade.v1beta1.MsgCancelUpgrade": {}, "/stride.icaoracle.MsgToggleOracle": {}, "/stride.icaoracle.MsgRemoveOracle": {}, + "/stride.stakeibc.MsgCreateTradeRoute": {}, + "/stride.stakeibc.MsgUpdateTradeRoute": {}, + "/stride.stakeibc.MsgDeleteTradeRoute": {}, } func IsModuleWhiteList(typeUrl string) bool { diff --git a/deps/osmosis b/deps/osmosis index 3e2c32630..30532bd83 160000 --- a/deps/osmosis +++ b/deps/osmosis @@ -1 +1 @@ -Subproject commit 3e2c326301aff138214c1d25630edb360459c0fd +Subproject commit 30532bd83ebac4e8985fb9d4ead91bc2722810fb diff --git a/dockernet/README.md b/dockernet/README.md index 37c9c5534..662e30c29 100644 --- a/dockernet/README.md +++ b/dockernet/README.md @@ -42,12 +42,10 @@ make build-docker build={z} volumes: - ./dockernet/state/{new-host-zone}2:/home/{new-host-zone}/.{new-host-zone}d - ... - - {new-host-zone}5: + {new-host-zone}3: image: stridezone:{new-host-zone} volumes: - - ./dockernet/state/{new-host-zone}5:/home/{new-host-zone}/.{new-host-zone}d + - ./dockernet/state/{new-host-zone}3:/home/{new-host-zone}/.{new-host-zone}d ... relayer-{chain}: image: stridezone:relayer diff --git a/dockernet/config.sh b/dockernet/config.sh index 286eb15e2..a6afe699f 100755 --- a/dockernet/config.sh +++ b/dockernet/config.sh @@ -37,6 +37,7 @@ if [[ "${ALL_HOST_CHAINS:-false}" == "true" ]]; then elif [[ "${#HOST_CHAINS[@]}" == "0" ]]; then HOST_CHAINS=(GAIA) fi +REWARD_CONVERTER_HOST_ZONE=${HOST_CHAINS[0]} # DENOMS STRD_DENOM="ustrd" @@ -108,7 +109,7 @@ IBC_STARS_DENOM=$IBC_STARS_CHANNEL_3_DENOM # CHAIN PARAMS BLOCK_TIME='1s' -STRIDE_HOUR_EPOCH_DURATION="90s" +STRIDE_HOUR_EPOCH_DURATION="60s" STRIDE_DAY_EPOCH_DURATION="140s" STRIDE_EPOCH_EPOCH_DURATION="35s" STRIDE_MINT_EPOCH_DURATION="20s" @@ -336,15 +337,24 @@ STRIDE_RELAYER_MNEMONICS=( "$RELAYER_GAIA_ICS_MNEMONIC" "$RELAYER_DYDX_MNEMONIC" ) -# Mnemonics for connections between two non-stride chains -RELAYER_NOBLE_DYDX_MNEMONIC="sentence fruit crumble sail bar knife exact flame apart prosper hint myth clean among tiny burden depart purity select envelope identify cross physical emerge" -RELAYER_DYDX_NOBLE_MNEMONIC="aerobic breeze claw climb bounce morning tank victory eight funny employ bracket hire reduce fine flee lava domain warfare loop theme fly tattoo must" +# Mnemonics for connections between accessory chains +RELAYER_STRIDE_OSMO_MNEMONIC="father october lonely ticket leave regret pudding buffalo return asthma plastic piano beef orient ill clip right phone ready pottery helmet hip solid galaxy" +RELAYER_OSMO_STRIDE_MNEMONIC="narrow assist come feel canyon anxiety three reason satoshi inspire region little attend impulse what student dog armor economy faculty dutch distance upon calm" +RELAYER_STRIDE_NOBLE_MNEMONIC="absent confirm lumber hobby glide alter remain yard mixed fiscal series kitchen effort protect pistol hire bless police year struggle near hour wisdom jewel" +RELAYER_NOBLE_STRIDE_MNEMONIC="jar point equal question fatigue frog disorder wasp labor obtain head print orbit entire frown high sadness dash retire idea coffee rubber rough until" RELAYER_NOBLE_OSMO_MNEMONIC="actual field visual wage orbit add human unit happy rich evil chair entire person february cactus deputy impact gasp elbow sunset brand possible fly" RELAYER_OSMO_NOBLE_MNEMONIC="obey clinic miss grunt inflict laugh sell moral kitchen tumble gold song flavor rather horn exhaust state amazing poverty differ approve spike village device" +# Mnemonics between host zone and accessory chains when running with GAIA as the host +RELAYER_GAIA_NOBLE_MNEMONIC="aerobic breeze claw climb bounce morning tank victory eight funny employ bracket hire reduce fine flee lava domain warfare loop theme fly tattoo must" +RELAYER_NOBLE_GAIA_MNEMONIC="sentence fruit crumble sail bar knife exact flame apart prosper hint myth clean among tiny burden depart purity select envelope identify cross physical emerge" +RELAYER_GAIA_OSMO_MNEMONIC="small fire step promote fox reward book seek arctic session illegal loyal because brass spoil minute wonder jazz shoe price muffin churn evil monitor" +RELAYER_OSMO_GAIA_MNEMONIC="risk wool reason sweet current strategy female miracle squeeze that wire develop ocean rapid domain lift blame monkey sick round museum item maze trumpet" +# Mnemonics between host zone and accessory chains when running with DYDX as the host +RELAYER_NOBLE_DYDX_MNEMONIC="sentence fruit crumble sail bar knife exact flame apart prosper hint myth clean among tiny burden depart purity select envelope identify cross physical emerge" +RELAYER_DYDX_NOBLE_MNEMONIC="aerobic breeze claw climb bounce morning tank victory eight funny employ bracket hire reduce fine flee lava domain warfare loop theme fly tattoo must" RELAYER_DYDX_OSMO_MNEMONIC="small fire step promote fox reward book seek arctic session illegal loyal because brass spoil minute wonder jazz shoe price muffin churn evil monitor" RELAYER_OSMO_DYDX_MNEMONIC="risk wool reason sweet current strategy female miracle squeeze that wire develop ocean rapid domain lift blame monkey sick round museum item maze trumpet" - STRIDE_ADDRESS() { # After an upgrade, the keys query can sometimes print migration info, # so we need to filter by valid addresses using the prefix @@ -512,6 +522,41 @@ GET_COUNTERPARTY_TRANSFER_CHANNEL_ID() { $main_cmd q ibc channel end transfer $channel_id | grep -A 2 counterparty | grep channel_id | awk '{print $2}' } +GET_LATEST_PROPOSAL_ID() { + chain="$1" + + main_cmd=$(GET_VAR_VALUE ${chain}_MAIN_CMD) + $main_cmd q gov proposals | grep ' id:' | tail -1 | awk '{printf $2}' | tr -d '"' +} + +WATCH_PROPOSAL_STATUS() { + chain="$1" + proposal_id="$2" + + main_cmd=$(GET_VAR_VALUE ${chain}_MAIN_CMD) + + # Continually polls the proposal status until it passes or fails + while true; do + status=$($main_cmd query gov proposal $proposal_id | grep "status" | awk '{printf $2}') + if [[ "$status" == "PROPOSAL_STATUS_VOTING_PERIOD" ]]; then + echo " Proposal still in progress..." + sleep 5 + elif [[ "$status" == "PROPOSAL_STATUS_PASSED" ]]; then + echo " Proposal passed!" + exit 0 + elif [[ "$status" == "PROPOSAL_STATUS_REJECTED" ]]; then + echo " Proposal rejected!" + exit 1 + elif [[ "$status" == "PROPOSAL_STATUS_FAILED" ]]; then + echo " Proposal failed!" + exit 1 + else + echo "ERROR: Unknown proposal status: $status" + exit 1 + fi + done +} + TRIM_TX() { grep -E "code:|txhash:" | sed 's/^/ /' } diff --git a/dockernet/config/ica_host.json b/dockernet/config/ica_host.json index 3a8a8abf0..d7bbd9d4d 100644 --- a/dockernet/config/ica_host.json +++ b/dockernet/config/ica_host.json @@ -20,7 +20,8 @@ "/cosmos.distribution.v1beta1.MsgFundCommunityPool", "/ibc.applications.transfer.v1.MsgTransfer", "/cosmwasm.wasm.v1.MsgExecuteContract", - "/cosmwasm.wasm.v1.MsgInstantiateContract" + "/cosmwasm.wasm.v1.MsgInstantiateContract", + "/osmosis.gamm.v1beta1.MsgSwapExactAmountIn" ] } } diff --git a/dockernet/config/relayer_config_dydx_noble.yaml b/dockernet/config/relayer_config_reward_converter.yaml similarity index 52% rename from dockernet/config/relayer_config_dydx_noble.yaml rename to dockernet/config/relayer_config_reward_converter.yaml index a8d9fc5ac..50de6afd8 100644 --- a/dockernet/config/relayer_config_dydx_noble.yaml +++ b/dockernet/config/relayer_config_reward_converter.yaml @@ -4,6 +4,36 @@ global: memo: "" light-cache-size: 20 chains: + stride: + type: cosmos + value: + key: stride + chain-id: STRIDE + rpc-addr: http://stride1:26657 + account-prefix: stride + keyring-backend: test + gas-adjustment: 1.3 + gas-prices: 0.02ustrd + coin-type: 118 + debug: false + timeout: 20s + output-format: json + sign-mode: direct + gaia: + type: cosmos + value: + key: gaia + chain-id: GAIA + rpc-addr: http://gaia1:26657 + account-prefix: cosmos + keyring-backend: test + gas-adjustment: 1.3 + gas-prices: 0.02uatom + coin-type: 118 + debug: false + timeout: 20s + output-format: json + sign-mode: direct dydx: type: cosmos value: @@ -50,9 +80,18 @@ chains: output-format: json sign-mode: direct paths: - dydx-noble: + # Paths for accessory chains + stride-osmo: src: - chain-id: DYDX + chain-id: STRIDE + dst: + chain-id: OSMO + src-channel-filter: + rule: "" + channel-list: [] + stride-noble: + src: + chain-id: STRIDE dst: chain-id: NOBLE src-channel-filter: @@ -66,11 +105,37 @@ paths: src-channel-filter: rule: "" channel-list: [] - osmo-dydx: + # Paths for host chain (if running GAIA) + gaia-noble: + src: + chain-id: GAIA + dst: + chain-id: NOBLE + src-channel-filter: + rule: "" + channel-list: [] + osmo-gaia: src: chain-id: OSMO dst: + chain-id: GAIA + src-channel-filter: + rule: "" + channel-list: [] + # Paths for host chain (if running DYDX) + dydx-noble: + src: chain-id: DYDX + dst: + chain-id: NOBLE src-channel-filter: rule: "" channel-list: [] + osmo-dydx: + src: + chain-id: OSMO + dst: + chain-id: DYDX + src-channel-filter: + rule: "" + channel-list: [] \ No newline at end of file diff --git a/dockernet/docker-compose.yml b/dockernet/docker-compose.yml index d9afb44b2..85248776f 100644 --- a/dockernet/docker-compose.yml +++ b/dockernet/docker-compose.yml @@ -1,5 +1,6 @@ version: "3" services: + # Stride nodes stride1: image: stridezone:stride volumes: @@ -19,6 +20,7 @@ services: volumes: - ./state/stride3:/home/stride/.stride + # Host zones gaia1: image: stridezone:gaia volumes: @@ -38,16 +40,6 @@ services: volumes: - ./state/gaia3:/home/gaia/.gaia - gaia4: - image: stridezone:gaia - volumes: - - ./state/gaia4:/home/gaia/.gaia - - gaia5: - image: stridezone:gaia - volumes: - - ./state/gaia5:/home/gaia/.gaia - juno1: image: stridezone:juno volumes: @@ -67,16 +59,6 @@ services: volumes: - ./state/juno3:/home/juno/.juno - juno4: - image: stridezone:juno - volumes: - - ./state/juno4:/home/juno/.juno - - juno5: - image: stridezone:juno - volumes: - - ./state/juno5:/home/juno/.juno - osmo1: image: stridezone:osmo volumes: @@ -96,16 +78,6 @@ services: volumes: - ./state/osmo3:/home/osmosis/.osmosisd - osmo4: - image: stridezone:osmo - volumes: - - ./state/osmo4:/home/osmosis/.osmosisd - - osmo5: - image: stridezone:osmo - volumes: - - ./state/osmo5:/home/osmosis/.osmosisd - stars1: image: stridezone:stars volumes: @@ -125,16 +97,6 @@ services: volumes: - ./state/stars3:/home/stars/.starsd - stars4: - image: stridezone:stars - volumes: - - ./state/stars4:/home/stars/.starsd - - stars5: - image: stridezone:stars - volumes: - - ./state/stars5:/home/stars/.starsd - # For the host chain, we must override the command to prevent an old binary from # being run when testing upgrades host1: @@ -159,18 +121,6 @@ services: volumes: - ./state/host3:/home/stride/.stride - host4: - image: stridezone:stride - command: strided start - volumes: - - ./state/host4:/home/stride/.stride - - host5: - image: stridezone:stride - command: strided start - volumes: - - ./state/host5:/home/stride/.stride - evmos1: image: stridezone:evmos volumes: @@ -190,16 +140,6 @@ services: volumes: - ./state/evmos3:/home/evmos/.evmosd - evmos4: - image: stridezone:evmos - volumes: - - ./state/evmos4:/home/evmos/.evmosd - - evmos5: - image: stridezone:evmos - volumes: - - ./state/evmos5:/home/evmos/.evmosd - dydx1: image: stridezone:dydx volumes: @@ -219,16 +159,6 @@ services: volumes: - ./state/dydx3:/home/dydx/.dydxprotocol - dydx4: - image: stridezone:dydx - volumes: - - ./state/dydx4:/home/dydx/.dydxprotocol - - dydx5: - image: stridezone:dydx - volumes: - - ./state/dydx5:/home/dydx/.dydxprotocol - noble1: image: stridezone:noble volumes: @@ -248,16 +178,6 @@ services: volumes: - ./state/noble3:/home/noble/.noble - noble4: - image: stridezone:noble - volumes: - - ./state/noble4:/home/noble/.noble - - noble5: - image: stridezone:noble - volumes: - - ./state/noble5:/home/noble/.noble - # Fill in new host zone being tested here hermes: @@ -267,6 +187,7 @@ services: - ./state/hermes/config.toml:/home/hermes/.hermes/config.toml restart: always + # Host zone relayers relayer-gaia: image: stridezone:relayer volumes: @@ -323,6 +244,7 @@ services: restart: always command: [ "bash", "start.sh", "stride-dydx" ] + # Relayers for rate limiter tests relayer-juno-osmo: image: stridezone:relayer volumes: @@ -330,12 +252,13 @@ services: restart: always command: [ "bash", "start.sh", "juno-osmo" ] - relayer-dydx-noble: + # Relayers for reward converter accessory chains + relayer-stride-noble: image: stridezone:relayer volumes: - - ./state/relayer-dydx-noble:/home/relayer/.relayer + - ./state/relayer-stride-noble:/home/relayer/.relayer restart: always - command: [ "bash", "start.sh", "dydx-noble" ] + command: [ "bash", "start.sh", "stride-noble" ] relayer-noble-osmo: image: stridezone:relayer @@ -344,9 +267,39 @@ services: restart: always command: [ "bash", "start.sh", "noble-osmo" ] + relayer-stride-osmo: + image: stridezone:relayer + volumes: + - ./state/relayer-stride-osmo:/home/relayer/.relayer + restart: always + command: [ "bash", "start.sh", "stride-osmo" ] + + # Relayers for reward converter with dydx + relayer-dydx-noble: + image: stridezone:relayer + volumes: + - ./state/relayer-dydx-noble:/home/relayer/.relayer + restart: always + command: [ "bash", "start.sh", "dydx-noble" ] + relayer-osmo-dydx: image: stridezone:relayer volumes: - ./state/relayer-osmo-dydx:/home/relayer/.relayer restart: always command: [ "bash", "start.sh", "osmo-dydx" ] + + # Relayers for reward converter with gaia + relayer-gaia-noble: + image: stridezone:relayer + volumes: + - ./state/relayer-gaia-noble:/home/relayer/.relayer + restart: always + command: [ "bash", "start.sh", "gaia-noble" ] + + relayer-osmo-gaia: + image: stridezone:relayer + volumes: + - ./state/relayer-osmo-gaia:/home/relayer/.relayer + restart: always + command: [ "bash", "start.sh", "osmo-gaia" ] \ No newline at end of file diff --git a/dockernet/dockerfiles/Dockerfile.osmo b/dockernet/dockerfiles/Dockerfile.osmo index 957f25763..e8e0278b3 100644 --- a/dockernet/dockerfiles/Dockerfile.osmo +++ b/dockernet/dockerfiles/Dockerfile.osmo @@ -4,7 +4,7 @@ WORKDIR /opt/ RUN set -eux; apk add --no-cache ca-certificates build-base; apk add git linux-headers -ENV COMMIT_HASH=v16.1.1-no-fees +ENV COMMIT_HASH=v20.5.0-no-fees RUN git clone https://github.com/Stride-Labs/osmosis.git \ && cd osmosis \ diff --git a/dockernet/scripts/community-pool-staking/README.md b/dockernet/scripts/community-pool-staking/README.md index bc840bb33..5585e6b6d 100644 --- a/dockernet/scripts/community-pool-staking/README.md +++ b/dockernet/scripts/community-pool-staking/README.md @@ -1,7 +1,7 @@ ## Community Pool Staking Integration Tests ### Liquid Staking and Redemptions * To test only liquid staking and redemptions from the community pool (without reinvestment), the setup is much simpler -* Set `HOST_CHAINS` to `(DYDX)` in `config.sh` +* Set `HOST_CHAINS` to either `(DYDX)` or `(GAIA)` in `config.sh` * Start dockernet ```bash make start-docker @@ -27,7 +27,7 @@ bash dockernet/scripts/community-pool-staking/stake_proposal.sh ### Reinvestment * To test reinvestment, you must start up noble and osmosis as well - * Set `HOST_CHAINS` to `(DYDX)` in `config.sh` + * Set `HOST_CHAINS` to either `(DYDX)` or `(GAIA)` in `config.sh` * Set `ACCESSORY_CHAINS` to `(NOBLE OSMO)` in `config.sh * Start the network ```bash @@ -41,7 +41,11 @@ bash dockernet/scripts/community-pool-staking/start_relayers.sh ```bash bash dockernet/scripts/community-pool-staking/create_pool.sh ``` -* Finally, test the reinvestment flow by sending USDC to the withdrawal address +* Register the trade route to configure the conversion of reward tokens to host tokens +```bash +bash dockernet/scripts/community-pool-staking/add_trade_route.sh +``` +* Finally, test the reinvestment flow by sending USDC to the withdrawal address. View `logs/balances.log` to watch the funds traverse the different accounts ```bash bash dockernet/scripts/community-pool-staking/reinvest.sh -``` \ No newline at end of file +``` diff --git a/dockernet/scripts/community-pool-staking/add_trade_route.sh b/dockernet/scripts/community-pool-staking/add_trade_route.sh new file mode 100644 index 000000000..173b7a964 --- /dev/null +++ b/dockernet/scripts/community-pool-staking/add_trade_route.sh @@ -0,0 +1,120 @@ +#!/bin/bash +set -eu +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +source ${SCRIPT_DIR}/../../config.sh + +HOST_CHAIN=$REWARD_CONVERTER_HOST_ZONE +HOST_VAL_ADDRESS=$(${HOST_CHAIN}_ADDRESS) +HOST_CHAIN_ID=$(GET_VAR_VALUE ${HOST_CHAIN}_CHAIN_ID) +HOST_DENOM=$(GET_VAR_VALUE ${HOST_CHAIN}_DENOM) + +GAS="--gas-prices 0.1ustrd --gas auto --gas-adjustment 1.3" + +echo "Determining relevant connections and channels..." +stride_to_noble_client=$(GET_CLIENT_ID_FROM_CHAIN_ID STRIDE NOBLE) +stride_to_noble_connection=$(GET_CONNECTION_ID_FROM_CLIENT_ID STRIDE $stride_to_noble_client) + +stride_to_osmo_client=$(GET_CLIENT_ID_FROM_CHAIN_ID STRIDE OSMO) +stride_to_osmo_connection=$(GET_CONNECTION_ID_FROM_CLIENT_ID STRIDE $stride_to_osmo_client) + +host_to_noble_client=$(GET_CLIENT_ID_FROM_CHAIN_ID $HOST_CHAIN NOBLE) +host_to_noble_connection=$(GET_CONNECTION_ID_FROM_CLIENT_ID $HOST_CHAIN $host_to_noble_client) +host_to_noble_channel=$(GET_TRANSFER_CHANNEL_ID_FROM_CONNECTION_ID $HOST_CHAIN $host_to_noble_connection) + +noble_to_host_client=$(GET_CLIENT_ID_FROM_CHAIN_ID NOBLE $HOST_CHAIN) +noble_to_host_connection=$(GET_CONNECTION_ID_FROM_CLIENT_ID NOBLE $noble_to_host_client) +noble_to_host_channel=$(GET_TRANSFER_CHANNEL_ID_FROM_CONNECTION_ID NOBLE $noble_to_host_connection) + +noble_to_osmo_client=$(GET_CLIENT_ID_FROM_CHAIN_ID NOBLE OSMO) +noble_to_osmo_connection=$(GET_CONNECTION_ID_FROM_CLIENT_ID NOBLE $noble_to_osmo_client) +noble_to_osmo_channel=$(GET_TRANSFER_CHANNEL_ID_FROM_CONNECTION_ID NOBLE $noble_to_osmo_connection) + +osmo_to_host_client=$(GET_CLIENT_ID_FROM_CHAIN_ID OSMO $HOST_CHAIN) +osmo_to_host_connection=$(GET_CONNECTION_ID_FROM_CLIENT_ID OSMO $osmo_to_host_client) +osmo_to_host_channel=$(GET_TRANSFER_CHANNEL_ID_FROM_CONNECTION_ID OSMO $osmo_to_host_connection) + +osmo_to_noble_client=$(GET_CLIENT_ID_FROM_CHAIN_ID OSMO NOBLE) +osmo_to_noble_connection=$(GET_CONNECTION_ID_FROM_CLIENT_ID OSMO $osmo_to_noble_client) +osmo_to_noble_channel=$(GET_TRANSFER_CHANNEL_ID_FROM_CONNECTION_ID OSMO $osmo_to_noble_connection) + +echo -e "\nSTRIDE -> NOBLE:" +echo " Client: $stride_to_noble_client" +echo " Connection: $stride_to_noble_connection" + +echo -e "\nSTRIDE -> OSMO:" +echo " Client: $stride_to_osmo_client" +echo " Connection: $stride_to_osmo_connection" + +echo -e "\n$HOST_CHAIN -> NOBLE:" +echo " Client: $host_to_noble_client" +echo " Connection: $host_to_noble_connection" +echo " Transfer Channel: $host_to_noble_channel -> $noble_to_host_channel" + +echo -e "\nNOBLE -> OSMO:" +echo " Client: $noble_to_osmo_client" +echo " Connection: $noble_to_osmo_connection" +echo " Transfer Channel: $noble_to_osmo_channel" + +echo -e "\nOSMO -> $HOST_CHAIN:" +echo " Client: $osmo_to_host_client" +echo " Connection: $osmo_to_host_connection" +echo " Transfer Channel: $osmo_to_host_channel" + +echo -e "\nTransferring $USDC_DENOM to $HOST_DENOM to create ibc denom..." +$NOBLE_MAIN_CMD tx ibc-transfer transfer transfer $noble_to_host_channel $HOST_VAL_ADDRESS 10000${USDC_DENOM} \ + --from ${NOBLE_VAL_PREFIX}1 -y | TRIM_TX +sleep 15 + +echo -e "\nDetermining IBC Denoms..." +usdc_denom_on_host=$(GET_IBC_DENOM $HOST_CHAIN_ID $host_to_noble_channel $USDC_DENOM) +usdc_denom_on_osmo=$(GET_IBC_DENOM OSMO $osmo_to_noble_channel $USDC_DENOM) +host_denom_on_osmo=$(GET_IBC_DENOM OSMO $osmo_to_host_channel $HOST_DENOM) + +echo " ibc/$USDC_DENOM on Host: $usdc_denom_on_host" +echo " ibc/$USDC_DENOM on Osmosis: $usdc_denom_on_osmo" +echo " ibc/$HOST_DENOM on Osmosis: $host_denom_on_osmo" + +proposal_file=${STATE}/${STRIDE_NODE_PREFIX}1/trade_route.json +cat << EOF > $proposal_file +{ + "title": "Create a new trade route for host chain X", + "metadata": "Create a new trade route for host chain X", + "summary": "Create a new trade route for host chain X", + "messages": [ + { + "@type": "/stride.stakeibc.MsgCreateTradeRoute", + "authority": "stride10d07y265gmmuvt4z0w9aw880jnsr700jefnezl", + "host_chain_id": "$HOST_CHAIN_ID", + "stride_to_reward_connection_id": "$stride_to_noble_connection", + "stride_to_trade_connection_id": "$stride_to_osmo_connection", + "host_to_reward_transfer_channel_id": "$host_to_noble_channel", + "reward_to_trade_transfer_channel_id": "$noble_to_osmo_channel", + "trade_to_host_transfer_channel_id": "$osmo_to_host_channel", + "reward_denom_on_host": "$usdc_denom_on_host", + "reward_denom_on_reward": "$USDC_DENOM", + "reward_denom_on_trade": "$usdc_denom_on_osmo", + "host_denom_on_trade": "$host_denom_on_osmo", + "host_denom_on_host": "$HOST_DENOM", + "pool_id": 1, + "max_allowed_swap_loss_rate": "0.15" + } + ], + "deposit": "2000000000ustrd" +} +EOF + +echo -e "\nCreate trade route proposal file:" +cat $proposal_file + +echo -e "\n>>> Submitting proposal to register trade route..." +$STRIDE_MAIN_CMD tx gov submit-proposal $proposal_file --from val1 -y $GAS | TRIM_TX +sleep 5 + +echo -e "\n>>> Voting on proposal..." +proposal_id=$(GET_LATEST_PROPOSAL_ID STRIDE) +$STRIDE_MAIN_CMD tx gov vote $proposal_id yes --from val1 -y | TRIM_TX +$STRIDE_MAIN_CMD tx gov vote $proposal_id yes --from val2 -y | TRIM_TX +$STRIDE_MAIN_CMD tx gov vote $proposal_id yes --from val3 -y | TRIM_TX + +echo -e "\nProposal Status:" +WATCH_PROPOSAL_STATUS STRIDE $proposal_id \ No newline at end of file diff --git a/dockernet/scripts/community-pool-staking/claim.sh b/dockernet/scripts/community-pool-staking/claim.sh index 70b504350..5b8f22aba 100644 --- a/dockernet/scripts/community-pool-staking/claim.sh +++ b/dockernet/scripts/community-pool-staking/claim.sh @@ -2,20 +2,24 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) source ${SCRIPT_DIR}/../../config.sh -community_pool_return_address=$(GET_ICA_ADDR DYDX community_pool_return) -community_pool_holding_address=$(GET_HOST_ZONE_FIELD DYDX community_pool_redeem_holding_address) +HOST_CHAIN=$REWARD_CONVERTER_HOST_ZONE +HOST_MAIN_CMD=$(GET_VAR_VALUE ${HOST_CHAIN}_MAIN_CMD) +HOST_DENOM=$(GET_VAR_VALUE ${HOST_CHAIN}_DENOM) + +community_pool_return_address=$(GET_ICA_ADDR $HOST_CHAIN community_pool_return) +community_pool_holding_address=$(GET_HOST_ZONE_FIELD $HOST_CHAIN community_pool_redeem_holding_address) # check balances before claiming redeemed stake echo ">>> Balances before claim..." -$DYDX_MAIN_CMD q bank balances $community_pool_return_address +$HOST_MAIN_CMD q bank balances $community_pool_return_address #claim stake echo -e "\n>>> Claiming redeemed tokens..." epoch=$($STRIDE_MAIN_CMD q records list-user-redemption-record | grep -B 3 -m 1 "receiver: $community_pool_return_address" | grep "epoch_number"| NUMBERS_ONLY) -$STRIDE_MAIN_CMD tx stakeibc claim-undelegated-tokens DYDX $epoch $community_pool_holding_address --from ${STRIDE_VAL_PREFIX}1 -y | TRIM_TX +$STRIDE_MAIN_CMD tx stakeibc claim-undelegated-tokens $HOST_CHAIN_ID $epoch $community_pool_holding_address --from ${STRIDE_VAL_PREFIX}1 -y | TRIM_TX sleep 5 # check balances after claiming redeemed stake echo -e "\n>>> Balances after claim..." -$DYDX_MAIN_CMD q bank balances $community_pool_return_address +$HOST_MAIN_CMD q bank balances $community_pool_return_address diff --git a/dockernet/scripts/community-pool-staking/create_pool.sh b/dockernet/scripts/community-pool-staking/create_pool.sh index 67e139854..016874f1a 100644 --- a/dockernet/scripts/community-pool-staking/create_pool.sh +++ b/dockernet/scripts/community-pool-staking/create_pool.sh @@ -3,41 +3,42 @@ set -eu SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) source ${SCRIPT_DIR}/../../config.sh +HOST_CHAIN=$REWARD_CONVERTER_HOST_ZONE +HOST_MAIN_CMD=$(GET_VAR_VALUE ${HOST_CHAIN}_MAIN_CMD) +HOST_VAL_PREFIX=$(GET_VAR_VALUE ${HOST_CHAIN}_VAL_PREFIX) +HOST_DENOM=$(GET_VAR_VALUE ${HOST_CHAIN}_DENOM) + LIQUIDITY=1000000000000 GAS="--gas-prices 0.1uosmo --gas auto --gas-adjustment 1.3" echo "Determining relevant channels..." -dydx_to_osmo_client=$(GET_CLIENT_ID_FROM_CHAIN_ID DYDX OSMO) -dydx_to_osmo_connection=$(GET_CONNECTION_ID_FROM_CLIENT_ID DYDX $dydx_to_osmo_client) -dydx_to_osmo_channel=$(GET_TRANSFER_CHANNEL_ID_FROM_CONNECTION_ID DYDX $dydx_to_osmo_connection) -osmo_to_dydx_channel=$(GET_COUNTERPARTY_TRANSFER_CHANNEL_ID DYDX $dydx_to_osmo_channel) -dydx_denom_on_osmo=$(GET_IBC_DENOM OSMO $osmo_to_dydx_channel $DYDX_DENOM) +host_to_osmo_client=$(GET_CLIENT_ID_FROM_CHAIN_ID $HOST_CHAIN OSMO) +host_to_osmo_connection=$(GET_CONNECTION_ID_FROM_CLIENT_ID $HOST_CHAIN $host_to_osmo_client) +host_to_osmo_channel=$(GET_TRANSFER_CHANNEL_ID_FROM_CONNECTION_ID $HOST_CHAIN $host_to_osmo_connection) +osmo_to_host_channel=$(GET_COUNTERPARTY_TRANSFER_CHANNEL_ID $HOST_CHAIN $host_to_osmo_channel) -echo -e "\nDYDX -> OSMO:" -echo " Client: $dydx_to_osmo_client" -echo " Connection: $dydx_to_osmo_connection" -echo " Transfer Channel: $dydx_to_osmo_channel -> $osmo_to_dydx_channel" -echo " IBC Denom: $dydx_denom_on_osmo" +echo -e "\n$HOST_CHAIN -> OSMO:" +echo " Client: $host_to_osmo_client" +echo " Connection: $host_to_osmo_connection" +echo " Transfer Channel: $host_to_osmo_channel -> $osmo_to_host_channel" noble_to_osmo_client=$(GET_CLIENT_ID_FROM_CHAIN_ID NOBLE OSMO) noble_to_osmo_connection=$(GET_CONNECTION_ID_FROM_CLIENT_ID NOBLE $noble_to_osmo_client) noble_to_osmo_channel=$(GET_TRANSFER_CHANNEL_ID_FROM_CONNECTION_ID NOBLE $noble_to_osmo_connection) osmo_to_noble_channel=$(GET_COUNTERPARTY_TRANSFER_CHANNEL_ID NOBLE $noble_to_osmo_channel) -usdc_denom_on_osmo=$(GET_IBC_DENOM OSMO $osmo_to_noble_channel $USDC_DENOM) echo -e "\nNOBLE -> OSMO:" echo " Client: $noble_to_osmo_client" echo " Connection: $noble_to_osmo_connection" echo " Transfer Channel: $noble_to_osmo_channel -> $osmo_to_noble_channel" -echo " IBC Denom: $usdc_denom_on_osmo" -echo -e "\nSending dydx/usdc to osmosis for initial liquidity..." +echo -e "\nSending $HOST_DENOM and $USDC_DENOM to osmosis for initial liquidity..." -echo ">>> DYDX to Osmosis:" -$DYDX_MAIN_CMD tx ibc-transfer transfer transfer $dydx_to_osmo_channel $(OSMO_ADDRESS) ${LIQUIDITY}${DYDX_DENOM} \ - --from ${DYDX_VAL_PREFIX}1 -y | TRIM_TX +echo ">>> $HOST_DENOM to Osmosis:" +$HOST_MAIN_CMD tx ibc-transfer transfer transfer $host_to_osmo_channel $(OSMO_ADDRESS) ${LIQUIDITY}${HOST_DENOM} \ + --from ${HOST_VAL_PREFIX}1 -y | TRIM_TX -echo ">>> USDC to Osmosis:" +echo ">>> $USDC_DENOM to Osmosis:" $NOBLE_MAIN_CMD tx ibc-transfer transfer transfer $noble_to_osmo_channel $(OSMO_ADDRESS) ${LIQUIDITY}${USDC_DENOM} \ --from ${NOBLE_VAL_PREFIX}1 -y | TRIM_TX sleep 15 @@ -45,12 +46,19 @@ sleep 15 echo ">>> Balances:" $OSMO_MAIN_CMD q bank balances $(OSMO_ADDRESS) -echo -e "\nCreating dydx/usdc pool on osmosis..." +echo -e "\nDetermining IBC Denoms..." +host_denom_on_osmo=$(GET_IBC_DENOM OSMO $osmo_to_host_channel $HOST_DENOM) +usdc_denom_on_osmo=$(GET_IBC_DENOM OSMO $osmo_to_noble_channel $USDC_DENOM) + +echo " ibc/$HOST_DENOM on Osmosis: $host_denom_on_osmo" +echo " ibc/$USDC_DENOM on Osmosis: $usdc_denom_on_osmo" + +echo -e "\nCreating $HOST_DENOM/$USDC_DENOM pool on osmosis..." pool_file=${STATE}/${OSMO_NODE_PREFIX}1/pool.json cat << EOF > $pool_file { - "weights": "5${dydx_denom_on_osmo},5${usdc_denom_on_osmo}", - "initial-deposit": "1000000000000${dydx_denom_on_osmo},1000000000000${usdc_denom_on_osmo}", + "weights": "5${host_denom_on_osmo},5${usdc_denom_on_osmo}", + "initial-deposit": "1000000000000${host_denom_on_osmo},1000000000000${usdc_denom_on_osmo}", "swap-fee": "0.01", "exit-fee": "0.0", "future-governor": "" diff --git a/dockernet/scripts/community-pool-staking/redeem.sh b/dockernet/scripts/community-pool-staking/redeem.sh index 90cef0def..4c7f4c538 100644 --- a/dockernet/scripts/community-pool-staking/redeem.sh +++ b/dockernet/scripts/community-pool-staking/redeem.sh @@ -3,18 +3,23 @@ set -eu SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) source ${SCRIPT_DIR}/../../config.sh +HOST_CHAIN=$REWARD_CONVERTER_HOST_ZONE +HOST_MAIN_CMD=$(GET_VAR_VALUE ${HOST_CHAIN}_MAIN_CMD) +HOST_VAL_PREFIX=$(GET_VAR_VALUE ${HOST_CHAIN}_VAL_PREFIX) +HOST_DENOM=$(GET_VAR_VALUE ${HOST_CHAIN}_DENOM) + # Transfer to stride echo ">>> Transfering native token to Stride..." -$DYDX_MAIN_CMD tx ibc-transfer transfer transfer channel-0 $(STRIDE_ADDRESS) 1000000${DYDX_DENOM} --from ${DYDX_VAL_PREFIX}1 -y | TRIM_TX +$HOST_MAIN_CMD tx ibc-transfer transfer transfer channel-0 $(STRIDE_ADDRESS) 1000000${HOST_DENOM} --from ${HOST_VAL_PREFIX}1 -y | TRIM_TX sleep 10 #Liquid stake echo -e "\n>>> Liquid staking..." -$STRIDE_MAIN_CMD tx stakeibc liquid-stake 1000000 ${DYDX_DENOM} --from ${STRIDE_VAL_PREFIX}1 -y | TRIM_TX +$STRIDE_MAIN_CMD tx stakeibc liquid-stake 1000000 ${HOST_DENOM} --from ${STRIDE_VAL_PREFIX}1 -y | TRIM_TX sleep 5 # Send stATOM to community pool return address echo -e "\n>>> Transfer stToken to deposit ICA..." -$STRIDE_MAIN_CMD tx ibc-transfer transfer transfer channel-0 $(GET_ICA_ADDR DYDX community_pool_deposit) \ - 900000${STDYDX_DENOM} --from ${STRIDE_VAL_PREFIX}1 -y | TRIM_TX +$STRIDE_MAIN_CMD tx ibc-transfer transfer transfer channel-0 $(GET_ICA_ADDR $HOST_CHAIN community_pool_deposit) \ + 900000st${HOST_DENOM} --from ${STRIDE_VAL_PREFIX}1 -y | TRIM_TX sleep 10 diff --git a/dockernet/scripts/community-pool-staking/reinvest.sh b/dockernet/scripts/community-pool-staking/reinvest.sh index 2ab30c70c..cbf89cb64 100644 --- a/dockernet/scripts/community-pool-staking/reinvest.sh +++ b/dockernet/scripts/community-pool-staking/reinvest.sh @@ -4,5 +4,5 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) source ${SCRIPT_DIR}/../../config.sh echo ">>> Sending usdc tokens to withdrawal ICA to simulate rewards..." -$NOBLE_MAIN_CMD tx ibc-transfer transfer transfer channel-0 $(GET_ICA_ADDR DYDX withdrawal) 1000000${USDC_DENOM} \ +$NOBLE_MAIN_CMD tx ibc-transfer transfer transfer channel-0 $(GET_ICA_ADDR $REWARD_CONVERTER_HOST_ZONE withdrawal) 1000000${USDC_DENOM} \ --from ${NOBLE_VAL_PREFIX}1 -y | TRIM_TX \ No newline at end of file diff --git a/dockernet/scripts/community-pool-staking/setup_relayers.sh b/dockernet/scripts/community-pool-staking/setup_relayers.sh index a59e8dc19..209bac6d3 100644 --- a/dockernet/scripts/community-pool-staking/setup_relayers.sh +++ b/dockernet/scripts/community-pool-staking/setup_relayers.sh @@ -3,14 +3,18 @@ set -eu SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) source ${SCRIPT_DIR}/../../config.sh -for path in "dydx-noble" "noble-osmo" "osmo-dydx"; do +# Host chain can be dydx or gaia +HOST_CHAIN=$REWARD_CONVERTER_HOST_ZONE +host_chain=$(printf "$HOST_CHAIN" | awk '{ print tolower($0) }') + +for path in "$host_chain-noble" "noble-osmo" "osmo-$host_chain" "stride-osmo" "stride-noble"; do relayer_logs=${LOGS}/relayer-${path}.log relayer_config=$STATE/relayer-${path}/config relayer_exec="$DOCKER_COMPOSE run --rm relayer-$path" mkdir -p $relayer_config chmod -R 777 $STATE/relayer-${path} - cp ${DOCKERNET_HOME}/config/relayer_config_dydx_noble.yaml $relayer_config/config.yaml + cp ${DOCKERNET_HOME}/config/relayer_config_reward_converter.yaml $relayer_config/config.yaml IFS='-' read -r zone_1 zone_2 <<< "$path" @@ -51,4 +55,4 @@ for path in "dydx-noble" "noble-osmo" "osmo-dydx"; do $DOCKER_COMPOSE up -d relayer-${path} SAVE_DOCKER_LOGS relayer-${path} $relayer_logs -done +done \ No newline at end of file diff --git a/dockernet/scripts/community-pool-staking/stake.sh b/dockernet/scripts/community-pool-staking/stake.sh index b8676ebb9..d2107709e 100644 --- a/dockernet/scripts/community-pool-staking/stake.sh +++ b/dockernet/scripts/community-pool-staking/stake.sh @@ -3,5 +3,11 @@ set -eu SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) source ${SCRIPT_DIR}/../../config.sh +HOST_CHAIN=$REWARD_CONVERTER_HOST_ZONE +HOST_MAIN_CMD=$(GET_VAR_VALUE ${HOST_CHAIN}_MAIN_CMD) +HOST_VAL_PREFIX=$(GET_VAR_VALUE ${HOST_CHAIN}_VAL_PREFIX) +HOST_VAL_ADDRESS=$(${HOST_CHAIN}_ADDRESS) +HOST_DENOM=$(GET_VAR_VALUE ${HOST_CHAIN}_DENOM) + echo ">>> Sending native tokens to deposit ICA to simulate community pool liquid stake..." -$DYDX_MAIN_CMD tx bank send $(DYDX_ADDRESS) $(GET_ICA_ADDR DYDX community_pool_deposit) 1000000${DYDX_DENOM} --from ${DYDX_VAL_PREFIX}1 -y | TRIM_TX \ No newline at end of file +$HOST_MAIN_CMD tx bank send $HOST_VAL_ADDRESS $(GET_ICA_ADDR $HOST_CHAIN community_pool_deposit) 1000000${HOST_DENOM} --from ${HOST_VAL_PREFIX}1 -y | TRIM_TX \ No newline at end of file diff --git a/dockernet/scripts/community-pool-staking/stake_proposal.sh b/dockernet/scripts/community-pool-staking/stake_proposal.sh index 8426a4b6a..3554163a2 100644 --- a/dockernet/scripts/community-pool-staking/stake_proposal.sh +++ b/dockernet/scripts/community-pool-staking/stake_proposal.sh @@ -4,7 +4,7 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) source ${SCRIPT_DIR}/../../config.sh deposit_ica_account=$(GET_ICA_ADDR DYDX community_pool_deposit) -proposal_file=${STATE}/${DYDX_NODE_PREFIX}1/pool.json +proposal_file=${STATE}/${DYDX_NODE_PREFIX}1/proposal.json cat << EOF > $proposal_file { "title": "Community Spend: Liquid stake", diff --git a/dockernet/src/create_logs.sh b/dockernet/src/create_logs.sh index 6464d55a7..16aac5f56 100755 --- a/dockernet/src/create_logs.sh +++ b/dockernet/src/create_logs.sh @@ -11,6 +11,7 @@ TEMP_LOGS_DIR=$LOGS_DIR/temp STATE_LOG=state.log BALANCES_LOG=balances.log +CHANNELS_LOG=channels.log mkdir -p $TEMP_LOGS_DIR @@ -18,6 +19,7 @@ while true; do N_VALIDATORS_STRIDE=$($STRIDE_MAIN_CMD q tendermint-validator-set | grep -o address | wc -l | tr -dc '0-9') echo "STRIDE @ $($STRIDE_MAIN_CMD q tendermint-validator-set | head -n 1 | tr -dc '0-9') | $N_VALIDATORS_STRIDE VALS" >$TEMP_LOGS_DIR/$STATE_LOG echo "STRIDE @ $($STRIDE_MAIN_CMD q tendermint-validator-set | head -n 1 | tr -dc '0-9') | $N_VALIDATORS_STRIDE VALS" >$TEMP_LOGS_DIR/$BALANCES_LOG + echo "STRIDE @ $($STRIDE_MAIN_CMD q tendermint-validator-set | head -n 1 | tr -dc '0-9') | $N_VALIDATORS_STRIDE VALS" >$TEMP_LOGS_DIR/$CHANNELS_LOG for chain in ${HOST_CHAINS[@]}; do HOST_MAIN_CMD=$(GET_VAR_VALUE ${chain}_MAIN_CMD) @@ -37,10 +39,15 @@ while true; do $STRIDE_MAIN_CMD q records list-user-redemption-record >> $TEMP_LOGS_DIR/$STATE_LOG printf '\n%s\n' "LIST-LSM-TOKEN-DEPOSIT-RECORDS" >>$TEMP_LOGS_DIR/$STATE_LOG $STRIDE_MAIN_CMD q records lsm-deposits >> $TEMP_LOGS_DIR/$STATE_LOG + printf '\n%s\n' "LIST-TRADE-ROUTES" >>$TEMP_LOGS_DIR/$STATE_LOG + $STRIDE_MAIN_CMD q stakeibc list-trade-routes >> $TEMP_LOGS_DIR/$STATE_LOG printf '\n%s\n' "BALANCES STRIDE" >>$TEMP_LOGS_DIR/$BALANCES_LOG $STRIDE_MAIN_CMD q bank balances $(STRIDE_ADDRESS) >>$TEMP_LOGS_DIR/$BALANCES_LOG + printf '\n%s\n' "========================== STRIDE =============================" >> $TEMP_LOGS_DIR/$CHANNELS_LOG + $STRIDE_MAIN_CMD q ibc channel channels | grep -E "channel_id|port|state" >> $TEMP_LOGS_DIR/$CHANNELS_LOG || true + for chain in ${HOST_CHAINS[@]}; do HOST_CHAIN_ID=$(GET_VAR_VALUE ${chain}_CHAIN_ID) HOST_MAIN_CMD=$(GET_VAR_VALUE ${chain}_MAIN_CMD) @@ -84,6 +91,22 @@ while true; do $STRIDE_MAIN_CMD q bank balances $COMMUNITY_POOL_STAKE_ADDR >> $TEMP_LOGS_DIR/$BALANCES_LOG printf '\n%s\n' "COMMUNITY POOL REDEEM HOLDING ACCT BALANCE" >> $TEMP_LOGS_DIR/$BALANCES_LOG $STRIDE_MAIN_CMD q bank balances $COMMUNITY_POOL_REDEEM_ADDR >> $TEMP_LOGS_DIR/$BALANCES_LOG + + printf '\n%s\n' "========================== $chain =============================" >> $TEMP_LOGS_DIR/$CHANNELS_LOG + $HOST_MAIN_CMD q ibc channel channels | grep -E "channel_id|port|state" >> $TEMP_LOGS_DIR/$CHANNELS_LOG || true + done + + + TRADE_ICA_ADDR=$($STRIDE_MAIN_CMD q stakeibc list-trade-routes | grep trade_account -A 2 | grep address | awk '{print $2}') + if [[ "$TRADE_ICA_ADDR" == "$OSMO_ADDRESS_PREFIX"* ]]; then + printf '\n%s\n' "TRADE ACCT BALANCE" >> $TEMP_LOGS_DIR/$BALANCES_LOG + $OSMO_MAIN_CMD q bank balances $TRADE_ICA_ADDR >> $TEMP_LOGS_DIR/$BALANCES_LOG + fi + + for chain in ${ACCESSORY_CHAINS[@]:-}; do + ACCESSORY_MAIN_CMD=$(GET_VAR_VALUE ${chain}_MAIN_CMD) + printf '\n%s\n' "========================== $chain =============================" >> $TEMP_LOGS_DIR/$CHANNELS_LOG + $ACCESSORY_MAIN_CMD q ibc channel channels | grep -E "channel_id|port|state" >> $TEMP_LOGS_DIR/$CHANNELS_LOG || true done mv $TEMP_LOGS_DIR/*.log $LOGS_DIR diff --git a/dockernet/src/init_chain.sh b/dockernet/src/init_chain.sh index 66ed6f8c5..18300b3c0 100644 --- a/dockernet/src/init_chain.sh +++ b/dockernet/src/init_chain.sh @@ -255,6 +255,7 @@ else add_relayer_account "$RELAYER_GAIA_ICS_ACCT" "$RELAYER_GAIA_ICS_MNEMONIC" fi if [ "$CHAIN" == "NOBLE" ]; then + add_relayer_account stride-noble "$RELAYER_NOBLE_STRIDE_MNEMONIC" add_relayer_account noble-dydx "$RELAYER_NOBLE_DYDX_MNEMONIC" add_relayer_account noble-osmo "$RELAYER_NOBLE_OSMO_MNEMONIC" fi diff --git a/dockernet/tests/run_all_tests.sh b/dockernet/tests/run_all_tests.sh index 9868c3a96..1d030948b 100755 --- a/dockernet/tests/run_all_tests.sh +++ b/dockernet/tests/run_all_tests.sh @@ -1,10 +1,11 @@ #!/bin/bash SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +source ${SCRIPT_DIR}/../config.sh # run test files BATS=${SCRIPT_DIR}/bats/bats-core/bin/bats INTEGRATION_TEST_FILE=${SCRIPT_DIR}/integration_tests.bats -CHAIN_NAME=GAIA TRANSFER_CHANNEL_NUMBER=0 $BATS $INTEGRATION_TEST_FILE -CHAIN_NAME=EVMOS TRANSFER_CHANNEL_NUMBER=1 $BATS $INTEGRATION_TEST_FILE -CHAIN_NAME=HOST TRANSFER_CHANNEL_NUMBER=2 $BATS $INTEGRATION_TEST_FILE +for i in ${!HOST_CHAINS[@]}; do + CHAIN_NAME=${HOST_CHAINS[i]} TRANSFER_CHANNEL_NUMBER=$i $BATS $INTEGRATION_TEST_FILE +done \ No newline at end of file diff --git a/proto/osmosis/gamm/v1beta1/osmosis.proto b/proto/osmosis/gamm/v1beta1/osmosis.proto new file mode 100644 index 000000000..05c0a6049 --- /dev/null +++ b/proto/osmosis/gamm/v1beta1/osmosis.proto @@ -0,0 +1,88 @@ +syntax = "proto3"; +package osmosis.gamm.v1beta1; + +import "gogoproto/gogo.proto"; +import "amino/amino.proto"; +import "cosmos/base/v1beta1/coin.proto"; +import "google/protobuf/timestamp.proto"; + +option go_package = "github.com/Stride-Labs/stride/v16/x/stakeibc/types"; + +// MsgSwapExactAmountIn stores the tx Msg type to swap tokens in the trade ICA +message MsgSwapExactAmountIn { + option (amino.name) = "osmosis/gamm/swap-exact-amount-in"; + + string sender = 1 [ (gogoproto.moretags) = "yaml:\"sender\"" ]; + repeated SwapAmountInRoute routes = 2 [ (gogoproto.nullable) = false ]; + cosmos.base.v1beta1.Coin token_in = 3 [ + (gogoproto.moretags) = "yaml:\"token_in\"", + (gogoproto.nullable) = false + ]; + string token_out_min_amount = 4 [ + + (gogoproto.customtype) = "cosmossdk.io/math.Int", + (gogoproto.moretags) = "yaml:\"token_out_min_amount\"", + (gogoproto.nullable) = false + ]; +} + +message SwapAmountInRoute { + uint64 pool_id = 1 [ (gogoproto.moretags) = "yaml:\"pool_id\"" ]; + string token_out_denom = 2 + [ (gogoproto.moretags) = "yaml:\"token_out_denom\"" ]; +} + +// A TwapRecord stores the most recent price of a pair of denom's +message OsmosisTwapRecord { + uint64 pool_id = 1; + // Lexicographically smaller denom of the pair + string asset0_denom = 2; + // Lexicographically larger denom of the pair + string asset1_denom = 3; + // height this record corresponds to, for debugging purposes + int64 height = 4 [ + (gogoproto.moretags) = "yaml:\"record_height\"", + (gogoproto.jsontag) = "record_height" + ]; + // This field should only exist until we have a global registry in the state + // machine, mapping prior block heights within {TIME RANGE} to times. + google.protobuf.Timestamp time = 5 [ + (gogoproto.nullable) = false, + (gogoproto.stdtime) = true, + (gogoproto.moretags) = "yaml:\"record_time\"" + ]; + + // We store the last spot prices in the struct, so that we can interpolate + // accumulator values for times between when accumulator records are stored. + string p0_last_spot_price = 6 [ + (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", + (gogoproto.nullable) = false + ]; + string p1_last_spot_price = 7 [ + (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", + (gogoproto.nullable) = false + ]; + + string p0_arithmetic_twap_accumulator = 8 [ + (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", + (gogoproto.nullable) = false + ]; + string p1_arithmetic_twap_accumulator = 9 [ + (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", + (gogoproto.nullable) = false + ]; + + string geometric_twap_accumulator = 10 [ + (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", + (gogoproto.nullable) = false + ]; + + // This field contains the time in which the last spot price error occured. + // It is used to alert the caller if they are getting a potentially erroneous + // TWAP, due to an unforeseen underlying error. + google.protobuf.Timestamp last_error_time = 11 [ + (gogoproto.nullable) = false, + (gogoproto.stdtime) = true, + (gogoproto.moretags) = "yaml:\"last_error_time\"" + ]; +} diff --git a/proto/stride/stakeibc/callbacks.proto b/proto/stride/stakeibc/callbacks.proto index 62239b3ed..ee94fcd2c 100644 --- a/proto/stride/stakeibc/callbacks.proto +++ b/proto/stride/stakeibc/callbacks.proto @@ -94,3 +94,8 @@ message CommunityPoolBalanceQueryCallback { ICAAccountType ica_type = 1; string denom = 2; } + +message TradeRouteCallback { + string reward_denom = 1; + string host_denom = 2; +} diff --git a/proto/stride/stakeibc/ica_account.proto b/proto/stride/stakeibc/ica_account.proto index 857cdaee3..f4e77dcbf 100644 --- a/proto/stride/stakeibc/ica_account.proto +++ b/proto/stride/stakeibc/ica_account.proto @@ -10,4 +10,13 @@ enum ICAAccountType { REDEMPTION = 3; COMMUNITY_POOL_DEPOSIT = 4; COMMUNITY_POOL_RETURN = 5; + CONVERTER_UNWIND = 6; + CONVERTER_TRADE = 7; +} + +message ICAAccount { + string chain_id = 1; + ICAAccountType type = 2; + string connection_id = 3; + string address = 4; } diff --git a/proto/stride/stakeibc/query.proto b/proto/stride/stakeibc/query.proto index feb50668e..ed942eebe 100644 --- a/proto/stride/stakeibc/query.proto +++ b/proto/stride/stakeibc/query.proto @@ -9,6 +9,7 @@ import "stride/stakeibc/validator.proto"; import "stride/stakeibc/host_zone.proto"; import "stride/stakeibc/epoch_tracker.proto"; import "stride/stakeibc/address_unbonding.proto"; +import "stride/stakeibc/trade_route.proto"; option go_package = "github.com/Stride-Labs/stride/v16/x/stakeibc/types"; @@ -73,6 +74,12 @@ service Query { option (google.api.http).get = "/Stride-Labs/stride/stakeibc/unbondings/{address}"; } + + // Queries all trade routes + rpc AllTradeRoutes(QueryAllTradeRoutes) + returns (QueryAllTradeRoutesResponse) { + option (google.api.http).get = "/Stride-Labs/stride/stakeibc/trade_routes"; + } } // QueryInterchainAccountFromAddressRequest is the request type for the @@ -146,3 +153,9 @@ message QueryAddressUnbondingsResponse { repeated AddressUnbonding address_unbondings = 1 [ (gogoproto.nullable) = false ]; } + +message QueryAllTradeRoutes {}; + +message QueryAllTradeRoutesResponse { + repeated TradeRoute trade_routes = 1 [ (gogoproto.nullable) = false ]; +} diff --git a/proto/stride/stakeibc/trade_route.proto b/proto/stride/stakeibc/trade_route.proto new file mode 100644 index 000000000..9bf90218b --- /dev/null +++ b/proto/stride/stakeibc/trade_route.proto @@ -0,0 +1,90 @@ +syntax = "proto3"; +package stride.stakeibc; + +import "gogoproto/gogo.proto"; +import "stride/stakeibc/ica_account.proto"; +import "cosmos_proto/cosmos.proto"; + +option go_package = "github.com/Stride-Labs/stride/v16/x/stakeibc/types"; + +// Stores pool information needed to execute the swap along a trade route +message TradeConfig { + // Currently Osmosis is the only trade chain so this is an osmosis pool id + uint64 pool_id = 1; + + // Spot price in the pool to convert the reward denom to the host denom + // output_tokens = swap_price * input tokens + // This value may be slightly stale as it is updated by an ICQ + string swap_price = 2 [ + (cosmos_proto.scalar) = "cosmos.Dec", + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; + // unix time in seconds that the price was last updated + uint64 price_update_timestamp = 3; + + // Threshold defining the percentage of tokens that could be lost in the trade + // This captures both the loss from slippage and from a stale price on stride + // 0.05 means the output from the trade can be no less than a 5% deviation + // from the current value + string max_allowed_swap_loss_rate = 4 [ + (cosmos_proto.scalar) = "cosmos.Dec", + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; + + // min and max set boundaries of reward denom on trade chain we will swap + // min also decides when reward token transfers are worth it (transfer fees) + string min_swap_amount = 5 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", + (gogoproto.nullable) = false + ]; + string max_swap_amount = 6 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", + (gogoproto.nullable) = false + ]; +} + +// TradeRoute represents a round trip including info on transfer and how to do +// the swap. It makes the assumption that the reward token is always foreign to +// the host so therefore the first two hops are to unwind the ibc denom enroute +// to the trade chain and the last hop is the return so funds start/end in the +// withdrawl ICA on hostZone +// The structure is key'd on reward denom and host denom in their native forms +// (i.e. reward_denom_on_reward_zone and host_denom_on_host_zone) +message TradeRoute { + // ibc denom for the reward on the host zone + string reward_denom_on_host_zone = 1; + // should be the native denom for the reward chain + string reward_denom_on_reward_zone = 2; + // ibc denom of the reward on the trade chain, input to the swap + string reward_denom_on_trade_zone = 3; + // ibc of the host denom on the trade chain, output from the swap + string host_denom_on_trade_zone = 4; + // should be the same as the native host denom on the host chain + string host_denom_on_host_zone = 5; + + // ICAAccount on the host zone with the reward tokens + // This is the same as the host zone withdrawal ICA account + ICAAccount host_account = 6 [ (gogoproto.nullable) = false ]; + // ICAAccount on the reward zone that is acts as the intermediate + // receiver of the transfer from host zone to trade zone + ICAAccount reward_account = 7 [ (gogoproto.nullable) = false ]; + // ICAAccount responsible for executing the swap of reward + // tokens for host tokens + ICAAccount trade_account = 8 [ (gogoproto.nullable) = false ]; + + // Channel responsible for the transfer of reward tokens from the host + // zone to the reward zone. This is the channel ID on the host zone side + string host_to_reward_channel_id = 9; + // Channel responsible for the transfer of reward tokens from the reward + // zone to the trade zone. This is the channel ID on the reward zone side + string reward_to_trade_channel_id = 10; + // Channel responsible for the transfer of host tokens from the trade + // zone, back to the host zone. This is the channel ID on the trade zone side + string trade_to_host_channel_id = 11; + + // specifies the configuration needed to execute the swap + // such as pool_id, slippage, min trade amount, etc. + TradeConfig trade_config = 12 [ (gogoproto.nullable) = false ]; +} diff --git a/proto/stride/stakeibc/tx.proto b/proto/stride/stakeibc/tx.proto index 91c4b3d90..e3a0d795e 100644 --- a/proto/stride/stakeibc/tx.proto +++ b/proto/stride/stakeibc/tx.proto @@ -1,13 +1,14 @@ syntax = "proto3"; package stride.stakeibc; -import "stride/stakeibc/ica_account.proto"; import "stride/stakeibc/validator.proto"; option go_package = "github.com/Stride-Labs/stride/v16/x/stakeibc/types"; import "gogoproto/gogo.proto"; import "cosmos_proto/cosmos.proto"; import "cosmos/base/v1beta1/coin.proto"; +import "cosmos/msg/v1/msg.proto"; +import "amino/amino.proto"; // Msg defines the Msg service. service Msg { @@ -35,6 +36,12 @@ service Msg { rpc UpdateInnerRedemptionRateBounds(MsgUpdateInnerRedemptionRateBounds) returns (MsgUpdateInnerRedemptionRateBoundsResponse); rpc ResumeHostZone(MsgResumeHostZone) returns (MsgResumeHostZoneResponse); + rpc CreateTradeRoute(MsgCreateTradeRoute) + returns (MsgCreateTradeRouteResponse); + rpc DeleteTradeRoute(MsgDeleteTradeRoute) + returns (MsgDeleteTradeRouteResponse); + rpc UpdateTradeRoute(MsgUpdateTradeRoute) + returns (MsgUpdateTradeRouteResponse); } message MsgUpdateInnerRedemptionRateBounds { @@ -170,7 +177,8 @@ message MsgDeleteValidatorResponse {} message MsgRestoreInterchainAccount { string creator = 1; string chain_id = 2; - ICAAccountType account_type = 3; + string connection_id = 3; + string account_owner = 4; } message MsgRestoreInterchainAccountResponse {} @@ -180,6 +188,7 @@ message MsgUpdateValidatorSharesExchRate { string valoper = 3; } message MsgUpdateValidatorSharesExchRateResponse {} + message MsgUndelegateHost { string creator = 1; string amount = 2 [ @@ -200,4 +209,114 @@ message MsgResumeHostZone { string creator = 1; string chain_id = 2; } -message MsgResumeHostZoneResponse {} \ No newline at end of file +message MsgResumeHostZoneResponse {} + +// Creates a new trade route +message MsgCreateTradeRoute { + option (cosmos.msg.v1.signer) = "authority"; + option (amino.name) = "stride/x/stakeibc/MsgCreateTradeRoute"; + + // authority is the address that controls the module (defaults to x/gov unless + // overwritten). + string authority = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; + + // The chain ID of the host zone + string host_chain_id = 2; + + // Connection IDs between stride and the other zones + string stride_to_reward_connection_id = 3; + string stride_to_trade_connection_id = 4; + + // Transfer channels between the host, reward, and trade zones + string host_to_reward_transfer_channel_id = 5; + string reward_to_trade_transfer_channel_id = 6; + string trade_to_host_transfer_channel_id = 7; + + // ibc denom for the reward token on the host zone (e.g. ibc/usdc on dYdX) + string reward_denom_on_host = 8; + // native denom of reward token on the reward zone (e.g. usdc on Noble) + string reward_denom_on_reward = 9; + // ibc denom of the reward token on the trade zone (e.g. ibc/usdc on Osmosis) + string reward_denom_on_trade = 10; + // ibc denom of the host's token on the trade zone (e.g. ibc/dydx on Osmosis) + string host_denom_on_trade = 11; + // the host zone's native denom (e.g. dydx on dYdX) + string host_denom_on_host = 12; + + // The osmosis pool ID + uint64 pool_id = 13; + + // Threshold defining the percentage of tokens that could be lost in the trade + // This captures both the loss from slippage and from a stale price on stride + // "0.05" means the output from the trade can be no less than a 5% deviation + // from the current value + string max_allowed_swap_loss_rate = 14; + + // minimum amount of reward tokens to initate a swap + // if not provided, defaults to 0 + string min_swap_amount = 15 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", + (gogoproto.nullable) = false + ]; + // maximum amount of reward tokens in a single swap + // if not provided, defaults to 10e24 + string max_swap_amount = 16 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", + (gogoproto.nullable) = false + ]; +} +message MsgCreateTradeRouteResponse {} + +// Deletes a trade route +message MsgDeleteTradeRoute { + option (cosmos.msg.v1.signer) = "authority"; + option (amino.name) = "stride/x/stakeibc/MsgDeleteTradeRoute"; + + // authority is the address that controls the module (defaults to x/gov unless + // overwritten). + string authority = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; + + // The reward denom of the route in it's native form (e.g. usdc) + string reward_denom = 2; + // The host zone's denom in it's native form (e.g. dydx) + string host_denom = 3; +} +message MsgDeleteTradeRouteResponse {} + +// Updates the config of a trade route +message MsgUpdateTradeRoute { + option (cosmos.msg.v1.signer) = "authority"; + option (amino.name) = "stride/x/stakeibc/MsgUpdateTradeRoute"; + + // authority is the address that controls the module (defaults to x/gov unless + // overwritten). + string authority = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; + + // The reward denom of the route in it's native form (e.g. usdc) + string reward_denom = 2; + // The host zone's denom in it's native form (e.g. dydx) + string host_denom = 3; + + // The osmosis pool ID + uint64 pool_id = 4; + + // Threshold defining the percentage of tokens that could be lost in the trade + // This captures both the loss from slippage and from a stale price on stride + // "0.05" means the output from the trade can be no less than a 5% deviation + // from the current value + string max_allowed_swap_loss_rate = 5; + + // minimum amount of reward tokens to initate a swap + // if not provided, defaults to 0 + string min_swap_amount = 6 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", + (gogoproto.nullable) = false + ]; + // maximum amount of reward tokens in a single swap + // if not provided, defaults to 10e24 + string max_swap_amount = 7 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", + (gogoproto.nullable) = false + ]; +} +message MsgUpdateTradeRouteResponse {} diff --git a/scripts/protocgen.sh b/scripts/protocgen.sh index b6f56f13a..fdb200c31 100644 --- a/scripts/protocgen.sh +++ b/scripts/protocgen.sh @@ -20,6 +20,7 @@ cd proto generate_protos "./stride" generate_protos "./cosmos" generate_protos "./cosmwasm" +generate_protos "./osmosis" cd .. diff --git a/scripts/start_local_node.sh b/scripts/start_local_node.sh index 8ed852028..fa9ae2a12 100644 --- a/scripts/start_local_node.sh +++ b/scripts/start_local_node.sh @@ -38,6 +38,8 @@ sed -i -E "s|chain-id = \"\"|chain-id = \"${CHAIN_ID}\"|g" $client_toml sed -i -E "s|keyring-backend = \"os\"|keyring-backend = \"test\"|g" $client_toml sed -i -E "s|node = \".*\"|node = \"tcp://localhost:26657\"|g" $client_toml +sed -i -E "s|\"stake\"|\"${DENOM}\"|g" $genesis_json + jq '(.app_state.epochs.epochs[] | select(.identifier=="day") ).duration = $epochLen' --arg epochLen $STRIDE_DAY_EPOCH_DURATION $genesis_json > json.tmp && mv json.tmp $genesis_json jq '(.app_state.epochs.epochs[] | select(.identifier=="stride_epoch") ).duration = $epochLen' --arg epochLen $STRIDE_EPOCH_EPOCH_DURATION $genesis_json > json.tmp && mv json.tmp $genesis_json jq '.app_state.gov.params.max_deposit_period = $newVal' --arg newVal "$MAX_DEPOSIT_PERIOD" $genesis_json > json.tmp && mv json.tmp $genesis_json @@ -62,6 +64,17 @@ $STRIDED add-genesis-account $($STRIDED keys show val -a) 100000000000${DENOM} echo "$STRIDE_ADMIN_MNEMONIC" | $STRIDED keys add admin --recover --keyring-backend=test $STRIDED add-genesis-account $($STRIDED keys show admin -a) 100000000000${DENOM} -$STRIDED start +# Start the daemon in the background +$STRIDED start & +pid=$! +sleep 10 +# Add a governator +echo "Adding governator..." +pub_key=$($STRIDED tendermint show-validator) +$STRIDED tx staking create-validator --amount 1000000000${DENOM} --from val \ + --pubkey=$pub_key --commission-rate="0.10" --commission-max-rate="0.20" \ + --commission-max-change-rate="0.01" --min-self-delegation="1" -y +# Bring the daemon back to the foreground +wait $pid \ No newline at end of file diff --git a/x/icaoracle/keeper/keeper.go b/x/icaoracle/keeper/keeper.go index 7cb8eaece..1a59943e9 100644 --- a/x/icaoracle/keeper/keeper.go +++ b/x/icaoracle/keeper/keeper.go @@ -59,7 +59,7 @@ func (k Keeper) Logger(ctx sdk.Context) log.Logger { return ctx.Logger().With("module", fmt.Sprintf("x/%s", types.ModuleName)) } -// GetAuthority returns the x/staking module's authority. +// GetAuthority returns the x/icaoracle module's authority. func (k Keeper) GetAuthority() string { return k.authority } diff --git a/x/interchainquery/types/keys.go b/x/interchainquery/types/keys.go index 21117a062..7da8303e9 100644 --- a/x/interchainquery/types/keys.go +++ b/x/interchainquery/types/keys.go @@ -1,5 +1,7 @@ package types +import fmt "fmt" + const ( // ModuleName defines the module name ModuleName = "interchainquery" @@ -31,6 +33,14 @@ const ( STAKING_STORE_QUERY_WITH_PROOF = "store/staking/key" // The bank store is key'd by the account address BANK_STORE_QUERY_WITH_PROOF = "store/bank/key" + // The Osmosis twap store - key'd by the pool ID and denom's + TWAP_STORE_QUERY_WITH_PROOF = "store/twap/key" +) + +var ( + // Osmosis TWAP query info + OsmosisKeySeparator = "|" + OsmosisMostRecentTWAPsPrefix = "recent_twap" + OsmosisKeySeparator ) var ( @@ -42,3 +52,13 @@ var ( func KeyPrefix(p string) []byte { return []byte(p) } + +func FormatOsmosisMostRecentTWAPKey(poolId uint64, denom1, denom2 string) []byte { + // Sort denoms + if denom1 > denom2 { + denom1, denom2 = denom2, denom1 + } + + poolIdBz := fmt.Sprintf("%0.20d", poolId) + return []byte(fmt.Sprintf("%s%s%s%s%s%s", OsmosisMostRecentTWAPsPrefix, poolIdBz, OsmosisKeySeparator, denom1, OsmosisKeySeparator, denom2)) +} diff --git a/x/stakeibc/client/cli/query.go b/x/stakeibc/client/cli/query.go index 0d687a602..cd8977927 100644 --- a/x/stakeibc/client/cli/query.go +++ b/x/stakeibc/client/cli/query.go @@ -29,6 +29,7 @@ func GetQueryCmd(queryRoute string) *cobra.Command { cmd.AddCommand(CmdListEpochTracker()) cmd.AddCommand(CmdShowEpochTracker()) cmd.AddCommand(CmdNextPacketSequence()) + cmd.AddCommand(CmdListTradeRoutes()) return cmd } diff --git a/x/stakeibc/client/cli/query_trade_routes.go b/x/stakeibc/client/cli/query_trade_routes.go new file mode 100644 index 000000000..6c370d917 --- /dev/null +++ b/x/stakeibc/client/cli/query_trade_routes.go @@ -0,0 +1,36 @@ +package cli + +import ( + "context" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/spf13/cobra" + + "github.com/Stride-Labs/stride/v16/x/stakeibc/types" +) + +func CmdListTradeRoutes() *cobra.Command { + cmd := &cobra.Command{ + Use: "list-trade-routes", + Short: "list all trade routes", + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx := client.GetClientContextFromCmd(cmd) + + queryClient := types.NewQueryClient(clientCtx) + + params := &types.QueryAllTradeRoutes{} + res, err := queryClient.AllTradeRoutes(context.Background(), params) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddPaginationFlagsToCmd(cmd, cmd.Use) + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} diff --git a/x/stakeibc/client/cli/tx_restore_interchain_account.go b/x/stakeibc/client/cli/tx_restore_interchain_account.go index 92b9adb29..eefdcfc1f 100644 --- a/x/stakeibc/client/cli/tx_restore_interchain_account.go +++ b/x/stakeibc/client/cli/tx_restore_interchain_account.go @@ -1,8 +1,6 @@ package cli import ( - "errors" - "fmt" "strings" "github.com/cosmos/cosmos-sdk/client" @@ -15,24 +13,26 @@ import ( func CmdRestoreInterchainAccount() *cobra.Command { cmd := &cobra.Command{ - Use: "restore-interchain-account [chain-id] [account-type]", + Use: "restore-interchain-account [chain-id] [connection-id] [account-owner]", Short: "Broadcast message restore-interchain-account", Long: strings.TrimSpace( - fmt.Sprintf(`Restores a closed channel associated with an interchain account. -Specify the interchain account type as either: %s, %s, %s, or %s`, - types.ICAAccountType_DELEGATION, - types.ICAAccountType_WITHDRAWAL, - types.ICAAccountType_REDEMPTION, - types.ICAAccountType_FEE)), - Args: cobra.ExactArgs(2), + `Restores a closed channel associated with an interchain account. +Specify the chain ID and account owner - where the owner is the alias for the ICA account + +For host zone ICA accounts, the owner is of the form {chainId}.{accountType} +ex: +>>> strided tx restore-interchain-account cosmoshub-4 connection-0 cosmoshub-4.DELEGATION + +For trade route ICA accounts, the owner is of the form: + {chainId}.{rewardDenom}-{hostDenom}.{accountType} +ex: +>>> strided tx restore-interchain-account dydx-mainnet-1 connection-1 dydx-mainnet-1.uusdc-udydx.CONVERTER_TRADE + `), + Args: cobra.ExactArgs(3), RunE: func(cmd *cobra.Command, args []string) (err error) { - argChainId := args[0] - argAccountType := args[1] - - accountType, found := types.ICAAccountType_value[argAccountType] - if !found { - return errors.New("Invalid account type.") - } + chainId := args[0] + connectionId := args[1] + accountOwner := args[2] clientCtx, err := client.GetClientTxContext(cmd) if err != nil { @@ -41,8 +41,9 @@ Specify the interchain account type as either: %s, %s, %s, or %s`, msg := types.NewMsgRestoreInterchainAccount( clientCtx.GetFromAddress().String(), - argChainId, - types.ICAAccountType(accountType), + chainId, + connectionId, + accountOwner, ) if err := msg.ValidateBasic(); err != nil { return err diff --git a/x/stakeibc/handler.go b/x/stakeibc/handler.go index 7663e7aa2..46ab96a0a 100644 --- a/x/stakeibc/handler.go +++ b/x/stakeibc/handler.go @@ -70,6 +70,15 @@ func NewMessageHandler(k keeper.Keeper) sdk.Handler { case *types.MsgResumeHostZone: res, err := msgServer.ResumeHostZone(sdk.WrapSDKContext(ctx), msg) return sdk.WrapServiceResult(ctx, res, err) + case *types.MsgCreateTradeRoute: + res, err := msgServer.CreateTradeRoute(sdk.WrapSDKContext(ctx), msg) + return sdk.WrapServiceResult(ctx, res, err) + case *types.MsgDeleteTradeRoute: + res, err := msgServer.DeleteTradeRoute(sdk.WrapSDKContext(ctx), msg) + return sdk.WrapServiceResult(ctx, res, err) + case *types.MsgUpdateTradeRoute: + res, err := msgServer.UpdateTradeRoute(sdk.WrapSDKContext(ctx), msg) + return sdk.WrapServiceResult(ctx, res, err) default: errMsg := fmt.Sprintf("unrecognized %s message type: %T", types.ModuleName, msg) return nil, errorsmod.Wrap(sdkerrors.ErrUnknownRequest, errMsg) diff --git a/x/stakeibc/ibc_middleware.go b/x/stakeibc/ibc_middleware.go index 8bda28c7f..151dd990a 100644 --- a/x/stakeibc/ibc_middleware.go +++ b/x/stakeibc/ibc_middleware.go @@ -5,15 +5,12 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" - icatypes "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/types" clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" porttypes "github.com/cosmos/ibc-go/v7/modules/core/05-port/types" ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" - ratelimittypes "github.com/Stride-Labs/stride/v16/x/ratelimit/types" "github.com/Stride-Labs/stride/v16/x/stakeibc/keeper" - "github.com/Stride-Labs/stride/v16/x/stakeibc/types" ) var _ porttypes.Middleware = &IBCMiddleware{} @@ -67,118 +64,10 @@ func (im IBCMiddleware) OnChanOpenAck( counterpartyVersion string, ) error { im.keeper.Logger(ctx).Info(fmt.Sprintf("OnChanOpenAck: portID %s, channelID %s, counterpartyChannelID %s, counterpartyVersion %s", portID, channelID, counterpartyChannelID, counterpartyVersion)) - controllerConnectionId, err := im.keeper.GetConnectionId(ctx, portID) - if err != nil { - ctx.Logger().Error(fmt.Sprintf("Unable to get connection for port: %s", portID)) - } - address, found := im.keeper.ICAControllerKeeper.GetInterchainAccountAddress(ctx, controllerConnectionId, portID) - if !found { - ctx.Logger().Error(fmt.Sprintf("Expected to find an address for %s/%s", controllerConnectionId, portID)) - return nil - } - // get host chain id from connection - // fetch counterparty connection - hostChainId, err := im.keeper.GetChainID(ctx, controllerConnectionId) - if err != nil { - ctx.Logger().Error(fmt.Sprintf("Unable to obtain counterparty chain for connection: %s, port: %s, err: %s", controllerConnectionId, portID, err.Error())) - return nil - } - // get zone info - zoneInfo, found := im.keeper.GetHostZone(ctx, hostChainId) - if !found { - ctx.Logger().Error(fmt.Sprintf("Expected to find zone info for %v", hostChainId)) - return nil - } - ctx.Logger().Info(fmt.Sprintf("Found matching address for chain: %s, address %s, port %s", zoneInfo.ChainId, address, portID)) - - // expected port IDs for each ICA account type - withdrawalPortID, err := icatypes.NewControllerPortID(types.FormatICAAccountOwner(hostChainId, types.ICAAccountType_WITHDRAWAL)) - if err != nil { - return err - } - feePortID, err := icatypes.NewControllerPortID(types.FormatICAAccountOwner(hostChainId, types.ICAAccountType_FEE)) - if err != nil { - return err - } - delegationPortID, err := icatypes.NewControllerPortID(types.FormatICAAccountOwner(hostChainId, types.ICAAccountType_DELEGATION)) - if err != nil { - return err - } - redemptionPortID, err := icatypes.NewControllerPortID(types.FormatICAAccountOwner(hostChainId, types.ICAAccountType_REDEMPTION)) - if err != nil { - return err - } - communityPoolDepositOwner := types.FormatICAAccountOwner(hostChainId, types.ICAAccountType_COMMUNITY_POOL_DEPOSIT) - communityPoolDepositPortID, err := icatypes.NewControllerPortID(communityPoolDepositOwner) - if err != nil { + if err := im.keeper.OnChanOpenAck(ctx, portID, channelID); err != nil { + ctx.Logger().Error(fmt.Sprintf("Error during stakeibc OnChanOpenAck: %s", err.Error())) return err } - communityPoolReturnOwner := types.FormatICAAccountOwner(hostChainId, types.ICAAccountType_COMMUNITY_POOL_RETURN) - communityPoolReturnPortID, err := icatypes.NewControllerPortID(communityPoolReturnOwner) - if err != nil { - return err - } - - // Set ICA account addresses - switch { - case portID == withdrawalPortID: - zoneInfo.WithdrawalIcaAddress = address - case portID == feePortID: - zoneInfo.FeeIcaAddress = address - case portID == delegationPortID: - zoneInfo.DelegationIcaAddress = address - case portID == redemptionPortID: - zoneInfo.RedemptionIcaAddress = address - case portID == communityPoolDepositPortID: - zoneInfo.CommunityPoolDepositIcaAddress = address - case portID == communityPoolReturnPortID: - zoneInfo.CommunityPoolReturnIcaAddress = address - default: - ctx.Logger().Error(fmt.Sprintf("Missing portId: %s", portID)) - } - - // Once the delegation channel is registered, whitelist epochly transfers so they're not rate limited - // Epochly transfers go from the deposit address to the delegation address - if portID == delegationPortID { - im.keeper.RatelimitKeeper.SetWhitelistedAddressPair(ctx, ratelimittypes.WhitelistedAddressPair{ - Sender: zoneInfo.DepositAddress, - Receiver: zoneInfo.DelegationIcaAddress, - }) - } - - // Once the fee channel is registered, whitelist reward transfers so they're not rate limited - // Reward transfers go from the fee address to the reward collector - if portID == feePortID { - rewardCollectorAddress := im.keeper.AccountKeeper.GetModuleAccount(ctx, types.RewardCollectorName).GetAddress() - im.keeper.RatelimitKeeper.SetWhitelistedAddressPair(ctx, ratelimittypes.WhitelistedAddressPair{ - Sender: zoneInfo.FeeIcaAddress, - Receiver: rewardCollectorAddress.String(), - }) - } - - // Once the community pool deposit ICA is registered, whitelist epochly community pool transfers - // from the deposit ICA to the community pool holding accounts - if portID == communityPoolDepositPortID { - im.keeper.RatelimitKeeper.SetWhitelistedAddressPair(ctx, ratelimittypes.WhitelistedAddressPair{ - Sender: zoneInfo.CommunityPoolDepositIcaAddress, - Receiver: zoneInfo.CommunityPoolStakeHoldingAddress, - }) - im.keeper.RatelimitKeeper.SetWhitelistedAddressPair(ctx, ratelimittypes.WhitelistedAddressPair{ - Sender: zoneInfo.CommunityPoolDepositIcaAddress, - Receiver: zoneInfo.CommunityPoolRedeemHoldingAddress, - }) - } - - // Once the community pool return ICA is registered, whitelist epochly community pool transfers - // from the community pool stake holding account to the community pool return ICA - if portID == communityPoolReturnPortID { - im.keeper.RatelimitKeeper.SetWhitelistedAddressPair(ctx, ratelimittypes.WhitelistedAddressPair{ - Sender: zoneInfo.CommunityPoolStakeHoldingAddress, - Receiver: zoneInfo.CommunityPoolReturnIcaAddress, - }) - } - - im.keeper.SetHostZone(ctx, zoneInfo) // call underlying app's OnChanOpenAck return im.app.OnChanOpenAck(ctx, portID, channelID, counterpartyChannelID, counterpartyVersion) diff --git a/x/stakeibc/keeper/grpc_query_trade_routes.go b/x/stakeibc/keeper/grpc_query_trade_routes.go new file mode 100644 index 000000000..5bccce8b4 --- /dev/null +++ b/x/stakeibc/keeper/grpc_query_trade_routes.go @@ -0,0 +1,23 @@ +package keeper + +import ( + "context" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + "github.com/Stride-Labs/stride/v16/x/stakeibc/types" +) + +func (k Keeper) AllTradeRoutes(c context.Context, req *types.QueryAllTradeRoutes) (*types.QueryAllTradeRoutesResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "invalid request") + } + ctx := sdk.UnwrapSDKContext(c) + + routes := k.GetAllTradeRoutes(ctx) + + return &types.QueryAllTradeRoutesResponse{TradeRoutes: routes}, nil +} diff --git a/x/stakeibc/keeper/hooks.go b/x/stakeibc/keeper/hooks.go index a11c12612..7bef44a50 100644 --- a/x/stakeibc/keeper/hooks.go +++ b/x/stakeibc/keeper/hooks.go @@ -86,10 +86,18 @@ func (k Keeper) BeforeEpochStart(ctx sdk.Context, epochInfo epochstypes.EpochInf // Transfers in and out of tokens for hostZones which have community pools k.ProcessAllCommunityPoolTokens(ctx) + + // Do transfers for all reward and swapped tokens defined by the trade routes every stride epoch + k.TransferAllRewardTokens(ctx) } if epochInfo.Identifier == epochstypes.MINT_EPOCH { k.AllocateHostZoneReward(ctx) } + // At the hour epoch, query the swap price on each trade route and initiate the token swap + if epochInfo.Identifier == epochstypes.HOUR_EPOCH { + k.UpdateAllSwapPrices(ctx) + k.SwapAllRewardTokens(ctx) + } } func (k Keeper) AfterEpochEnd(ctx sdk.Context, epochInfo epochstypes.EpochInfo) {} diff --git a/x/stakeibc/keeper/host_zone.go b/x/stakeibc/keeper/host_zone.go index 2630c54f5..4aefc39ab 100644 --- a/x/stakeibc/keeper/host_zone.go +++ b/x/stakeibc/keeper/host_zone.go @@ -35,6 +35,18 @@ func (k Keeper) GetHostZone(ctx sdk.Context, chainId string) (val types.HostZone return val, true } +// GetActiveHostZone returns an error if the host zone is not found or if it's found, but is halted +func (k Keeper) GetActiveHostZone(ctx sdk.Context, chainId string) (hostZone types.HostZone, err error) { + hostZone, found := k.GetHostZone(ctx, chainId) + if !found { + return hostZone, types.ErrHostZoneNotFound.Wrapf("host zone %s not found", chainId) + } + if hostZone.Halted { + return hostZone, types.ErrHaltedHostZone.Wrapf("host zone %s is halted", chainId) + } + return hostZone, nil +} + // GetHostZoneFromHostDenom returns a HostZone from a HostDenom func (k Keeper) GetHostZoneFromHostDenom(ctx sdk.Context, denom string) (*types.HostZone, error) { var matchZone types.HostZone @@ -62,9 +74,9 @@ func (k Keeper) GetHostZoneFromTransferChannelID(ctx sdk.Context, channelID stri } // RemoveHostZone removes a hostZone from the store -func (k Keeper) RemoveHostZone(ctx sdk.Context, chain_id string) { +func (k Keeper) RemoveHostZone(ctx sdk.Context, chainId string) { store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.HostZoneKey)) - store.Delete([]byte(chain_id)) + store.Delete([]byte(chainId)) } // GetAllHostZone returns all hostZone diff --git a/x/stakeibc/keeper/ibc.go b/x/stakeibc/keeper/ibc.go new file mode 100644 index 000000000..50391c7f0 --- /dev/null +++ b/x/stakeibc/keeper/ibc.go @@ -0,0 +1,194 @@ +package keeper + +import ( + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + icatypes "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/types" + + ratelimittypes "github.com/Stride-Labs/stride/v16/x/ratelimit/types" + "github.com/Stride-Labs/stride/v16/x/stakeibc/types" +) + +func (k Keeper) OnChanOpenAck(ctx sdk.Context, portID, channelID string) error { + // Lookup the ICA address and chainId from the port and connection + controllerConnectionId, found := k.GetConnectionIdFromICAPortId(ctx, portID) + if !found { + k.Logger(ctx).Info(fmt.Sprintf("portId %s has no associated ICA account", portID)) + return nil + } + address, found := k.ICAControllerKeeper.GetInterchainAccountAddress(ctx, controllerConnectionId, portID) + if !found { + k.Logger(ctx).Info(fmt.Sprintf("No ICA address associated with connection %s and port %s", controllerConnectionId, portID)) + return nil + } + chainId, err := k.GetChainIdFromConnectionId(ctx, controllerConnectionId) + if err != nil { + return err + } + k.Logger(ctx).Info(fmt.Sprintf("Found matching address for chain: %s, address %s, port %s", chainId, address, portID)) + + // Check if the chainId matches one of the host zones, and if so, + // store the relevant ICA address on the host zone struct + if err := k.StoreHostZoneIcaAddress(ctx, chainId, portID, address); err != nil { + return err + } + + // Check if the chainId matches any ICAs from trade routes, and if so, + // store the relevant ICA addresses in the trade route structs + if err := k.StoreTradeRouteIcaAddress(ctx, chainId, portID, address); err != nil { + return err + } + + return nil +} + +// Checks if the chainId matches a given host zone, and the address matches a relevant ICA account +// If so, stores the ICA address on the host zone struct +// Also whitelists ICA addresses from rate limiting +func (k Keeper) StoreHostZoneIcaAddress(ctx sdk.Context, chainId, portId, address string) error { + // Check if the chainId matches a host zone + // If the chainId does not match (for instance, a reward zone in a trade route is not a host zone) + // then we can ignore the ICA address checks + hostZone, found := k.GetHostZone(ctx, chainId) + if !found { + k.Logger(ctx).Info(fmt.Sprintf("chainId %s has no associated host zone", chainId)) + return nil + } + + // expected port IDs for each ICA account type + delegationOwner := types.FormatHostZoneICAOwner(chainId, types.ICAAccountType_DELEGATION) + delegationPortID, err := icatypes.NewControllerPortID(delegationOwner) + if err != nil { + return err + } + withdrawalOwner := types.FormatHostZoneICAOwner(chainId, types.ICAAccountType_WITHDRAWAL) + withdrawalPortID, err := icatypes.NewControllerPortID(withdrawalOwner) + if err != nil { + return err + } + feeOwner := types.FormatHostZoneICAOwner(chainId, types.ICAAccountType_FEE) + feePortID, err := icatypes.NewControllerPortID(feeOwner) + if err != nil { + return err + } + redemptionOwner := types.FormatHostZoneICAOwner(chainId, types.ICAAccountType_REDEMPTION) + redemptionPortID, err := icatypes.NewControllerPortID(redemptionOwner) + if err != nil { + return err + } + communityPoolDepositOwner := types.FormatHostZoneICAOwner(chainId, types.ICAAccountType_COMMUNITY_POOL_DEPOSIT) + communityPoolDepositPortID, err := icatypes.NewControllerPortID(communityPoolDepositOwner) + if err != nil { + return err + } + communityPoolReturnOwner := types.FormatHostZoneICAOwner(chainId, types.ICAAccountType_COMMUNITY_POOL_RETURN) + communityPoolReturnPortID, err := icatypes.NewControllerPortID(communityPoolReturnOwner) + if err != nil { + return err + } + + // Set ICA account addresses + switch { + case portId == withdrawalPortID: + hostZone.WithdrawalIcaAddress = address + case portId == feePortID: + hostZone.FeeIcaAddress = address + case portId == delegationPortID: + hostZone.DelegationIcaAddress = address + case portId == redemptionPortID: + hostZone.RedemptionIcaAddress = address + case portId == communityPoolDepositPortID: + hostZone.CommunityPoolDepositIcaAddress = address + case portId == communityPoolReturnPortID: + hostZone.CommunityPoolReturnIcaAddress = address + default: + k.Logger(ctx).Info(fmt.Sprintf("portId %s has an associated host zone, but does not match any ICA accounts", portId)) + return nil + } + + k.SetHostZone(ctx, hostZone) + + // Once the delegation channel is registered, whitelist epochly transfers so they're not rate limited + // Epochly transfers go from the deposit address to the delegation address + if portId == delegationPortID { + k.RatelimitKeeper.SetWhitelistedAddressPair(ctx, ratelimittypes.WhitelistedAddressPair{ + Sender: hostZone.DepositAddress, + Receiver: hostZone.DelegationIcaAddress, + }) + } + + // Once the fee channel is registered, whitelist reward transfers so they're not rate limited + // Reward transfers go from the fee address to the reward collector + if portId == feePortID { + rewardCollectorAddress := k.AccountKeeper.GetModuleAccount(ctx, types.RewardCollectorName).GetAddress() + k.RatelimitKeeper.SetWhitelistedAddressPair(ctx, ratelimittypes.WhitelistedAddressPair{ + Sender: hostZone.FeeIcaAddress, + Receiver: rewardCollectorAddress.String(), + }) + } + + // Once the community pool deposit ICA is registered, whitelist epochly community pool transfers + // from the deposit ICA to the community pool holding accounts + if portId == communityPoolDepositPortID { + k.RatelimitKeeper.SetWhitelistedAddressPair(ctx, ratelimittypes.WhitelistedAddressPair{ + Sender: hostZone.CommunityPoolDepositIcaAddress, + Receiver: hostZone.CommunityPoolStakeHoldingAddress, + }) + k.RatelimitKeeper.SetWhitelistedAddressPair(ctx, ratelimittypes.WhitelistedAddressPair{ + Sender: hostZone.CommunityPoolDepositIcaAddress, + Receiver: hostZone.CommunityPoolRedeemHoldingAddress, + }) + } + + // Once the community pool return ICA is registered, whitelist epochly community pool transfers + // from the community pool stake holding account to the community pool return ICA + if portId == communityPoolReturnPortID { + k.RatelimitKeeper.SetWhitelistedAddressPair(ctx, ratelimittypes.WhitelistedAddressPair{ + Sender: hostZone.CommunityPoolStakeHoldingAddress, + Receiver: hostZone.CommunityPoolReturnIcaAddress, + }) + } + + return nil +} + +// Checks if the port matches an ICA account on the trade route, and if so, stores the +// relevant ICA address on the trade route +func (k Keeper) StoreTradeRouteIcaAddress(ctx sdk.Context, callbackChainId, callbackPortId, address string) error { + // Check if the port Id matches either the trade or unwind ICA on the tradeRoute + // If the chainId and port Id from the callback match the account + // on a trade route, set the ICA address in the relevant places, + // including the from/to addresses on each hop + for _, route := range k.GetAllTradeRoutes(ctx) { + // Build the expected port ID for the reward and trade accounts, + // using the chainId and route ID + rewardAccount := route.RewardAccount + rewardOwner := types.FormatTradeRouteICAOwnerFromRouteId(rewardAccount.ChainId, route.GetRouteId(), rewardAccount.Type) + rewardPortId, err := icatypes.NewControllerPortID(rewardOwner) + if err != nil { + return err + } + + tradeAccount := route.TradeAccount + tradeOwner := types.FormatTradeRouteICAOwnerFromRouteId(tradeAccount.ChainId, route.GetRouteId(), tradeAccount.Type) + tradePortId, err := icatypes.NewControllerPortID(tradeOwner) + if err != nil { + return err + } + + // Check if route IDs match the callback chainId/portId + if route.RewardAccount.ChainId == callbackChainId && callbackPortId == rewardPortId { + k.Logger(ctx).Info(fmt.Sprintf("ICA Address %s found for Unwind ICA on %s", address, route.Description())) + route.RewardAccount.Address = address + + } else if route.TradeAccount.ChainId == callbackChainId && callbackPortId == tradePortId { + k.Logger(ctx).Info(fmt.Sprintf("ICA Address %s found for Trade ICA on %s", address, route.Description())) + route.TradeAccount.Address = address + } + + k.SetTradeRoute(ctx, route) + } + + return nil +} diff --git a/x/stakeibc/keeper/ibc_test.go b/x/stakeibc/keeper/ibc_test.go new file mode 100644 index 000000000..6edc972ef --- /dev/null +++ b/x/stakeibc/keeper/ibc_test.go @@ -0,0 +1,294 @@ +package keeper_test + +import ( + icatypes "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/types" + + "github.com/Stride-Labs/stride/v16/x/stakeibc/types" +) + +// ------------------------------------------ +// OnChanOpenAck +// ------------------------------------------ + +func (s *KeeperTestSuite) TestOnChanOpenAck() { + // Define the mocked out ids for both the delegation and trade accounts + delegationChainId := "delegation-1" + delegationAddress := "delegation-address" + delegationConnectionId := "connection-0" + delegationChannelId := "channel-0" + delegationClientId := "07-tendermint-0" + + tradeChainId := "trade-1" + tradeAddress := "trade-address" + tradeConnectionId := "connection-1" + tradeChannelId := "channel-1" + tradeClientId := "07-tendermint-1" + + // Create a host zone with out any ICA addresses + s.App.StakeibcKeeper.SetHostZone(s.Ctx, types.HostZone{ + ChainId: delegationChainId, + }) + + // Create a trade route without any ICA addresses + s.App.StakeibcKeeper.SetTradeRoute(s.Ctx, types.TradeRoute{ + RewardDenomOnRewardZone: RewardDenom, + HostDenomOnHostZone: HostDenom, + TradeAccount: types.ICAAccount{ + ChainId: tradeChainId, + Type: types.ICAAccountType_CONVERTER_TRADE, + }, + }) + + // Create the ICA channels for both the delegation and trade accounts + delegationOwner := types.FormatHostZoneICAOwner(delegationChainId, types.ICAAccountType_DELEGATION) + delegationPortId, _ := icatypes.NewControllerPortID(delegationOwner) + + tradeOwner := types.FormatTradeRouteICAOwner(tradeChainId, RewardDenom, HostDenom, types.ICAAccountType_CONVERTER_TRADE) + tradePortId, _ := icatypes.NewControllerPortID(tradeOwner) + + // Mock out an ICA address for each + s.App.ICAControllerKeeper.SetInterchainAccountAddress(s.Ctx, delegationConnectionId, delegationPortId, delegationAddress) + s.App.ICAControllerKeeper.SetInterchainAccountAddress(s.Ctx, tradeConnectionId, tradePortId, tradeAddress) + + // Mock out a client and connection for each channel so the callback can map back from portId to chainId + s.MockClientAndConnection(delegationChainId, delegationClientId, delegationConnectionId) + s.MockClientAndConnection(tradeChainId, tradeClientId, tradeConnectionId) + + // Call the callback with the delegation ICA port and confirm the delegation address is set + err := s.App.StakeibcKeeper.OnChanOpenAck(s.Ctx, delegationPortId, delegationChannelId) + s.Require().NoError(err, "no error expected when running callback with delegation port") + + hostZone := s.MustGetHostZone(delegationChainId) + s.Require().Equal(delegationAddress, hostZone.DelegationIcaAddress, "delegation address") + + // Call the callback with the trade ICA port and confirm the trade address is set + err = s.App.StakeibcKeeper.OnChanOpenAck(s.Ctx, tradePortId, tradeChannelId) + s.Require().NoError(err, "no error expected when running callback with trade port") + + tradeRoute, found := s.App.StakeibcKeeper.GetTradeRoute(s.Ctx, RewardDenom, HostDenom) + s.Require().True(found, "trade route should have been round") + s.Require().Equal(tradeAddress, tradeRoute.TradeAccount.Address, "trade address") + + // Call the callback with a non-ICA port and confirm the host zone and trade route remained unchanged + err = s.App.StakeibcKeeper.OnChanOpenAck(s.Ctx, tradePortId, tradeChannelId) + s.Require().NoError(err, "no error expected when running callback with non-ICA port") + + finalHostZone := s.MustGetHostZone(delegationChainId) + s.Require().Equal(hostZone, finalHostZone, "host zone should not have been modified") + + finalTradeRoute, found := s.App.StakeibcKeeper.GetTradeRoute(s.Ctx, RewardDenom, HostDenom) + s.Require().True(found, "trade route should have been round") + s.Require().Equal(tradeRoute, finalTradeRoute, "trade route should not have been modified") +} + +// ------------------------------------------ +// StoreHostZoneIcaAddress +// ------------------------------------------ + +// Helper function to check that a single ICA address was stored on the host zone +// The address stored will match the string of the ICA account type +func (s *KeeperTestSuite) checkHostZoneAddressStored(accountType types.ICAAccountType) { + // Determine the expected ICA addresses based on whether the account in question + // is registered in this test case + delegationAddress := "" + if accountType == types.ICAAccountType_DELEGATION { + delegationAddress = accountType.String() + } + withdrawalAddress := "" + if accountType == types.ICAAccountType_WITHDRAWAL { + withdrawalAddress = accountType.String() + } + redemptionAddress := "" + if accountType == types.ICAAccountType_REDEMPTION { + redemptionAddress = accountType.String() + } + feeAddress := "" + if accountType == types.ICAAccountType_FEE { + feeAddress = accountType.String() + } + communityPoolDepositAddress := "" + if accountType == types.ICAAccountType_COMMUNITY_POOL_DEPOSIT { + communityPoolDepositAddress = accountType.String() + } + communityPoolReturnAddress := "" + if accountType == types.ICAAccountType_COMMUNITY_POOL_RETURN { + communityPoolReturnAddress = accountType.String() + } + + // Confirm the expected addresses with the host zone + hostZone := s.MustGetHostZone(HostChainId) + + s.Require().Equal(delegationAddress, hostZone.DelegationIcaAddress, "delegation address") + s.Require().Equal(withdrawalAddress, hostZone.WithdrawalIcaAddress, "withdrawal address") + s.Require().Equal(redemptionAddress, hostZone.RedemptionIcaAddress, "redemption address") + s.Require().Equal(feeAddress, hostZone.FeeIcaAddress, "fee address") + s.Require().Equal(communityPoolDepositAddress, hostZone.CommunityPoolDepositIcaAddress, "community pool deposit address") + s.Require().Equal(communityPoolReturnAddress, hostZone.CommunityPoolReturnIcaAddress, "commuity pool return address") +} + +// Helper function to check that relevant ICA addresses are whitelisted after the callback +func (s *KeeperTestSuite) checkAddressesWhitelisted(accountType types.ICAAccountType) { + if accountType == types.ICAAccountType_DELEGATION { + isWhitelisted := s.App.RatelimitKeeper.IsAddressPairWhitelisted(s.Ctx, DepositAddress, accountType.String()) + s.Require().True(isWhitelisted, "deposit -> delegation whitelist") + } + + if accountType == types.ICAAccountType_FEE { + sender := accountType.String() + receiver := s.App.AccountKeeper.GetModuleAccount(s.Ctx, types.RewardCollectorName).GetAddress().String() + + isWhitelisted := s.App.RatelimitKeeper.IsAddressPairWhitelisted(s.Ctx, sender, receiver) + s.Require().True(isWhitelisted, "fee -> reward collector whitelist") + } + + if accountType == types.ICAAccountType_COMMUNITY_POOL_DEPOSIT { + sender := accountType.String() + + receiver := CommunityPoolStakeHoldingAddress + isWhitelisted := s.App.RatelimitKeeper.IsAddressPairWhitelisted(s.Ctx, sender, receiver) + s.Require().True(isWhitelisted, "community pool deposit -> community pool stake holding") + + receiver = CommunityPoolRedeemHoldingAddress + isWhitelisted = s.App.RatelimitKeeper.IsAddressPairWhitelisted(s.Ctx, sender, receiver) + s.Require().True(isWhitelisted, "community pool deposit -> community pool redeem holding") + } + + if accountType == types.ICAAccountType_COMMUNITY_POOL_RETURN { + sender := CommunityPoolStakeHoldingAddress + receiver := accountType.String() + + isWhitelisted := s.App.RatelimitKeeper.IsAddressPairWhitelisted(s.Ctx, sender, receiver) + s.Require().True(isWhitelisted, "community pool stake holding -> community pool return") + } +} + +func (s *KeeperTestSuite) TestStoreHostZoneIcaAddress() { + // We'll run a test case for each ICA account, with two of them not being relevant for the host zone + icaAccountTypes := []types.ICAAccountType{ + types.ICAAccountType_DELEGATION, + types.ICAAccountType_WITHDRAWAL, + types.ICAAccountType_REDEMPTION, + types.ICAAccountType_FEE, + types.ICAAccountType_COMMUNITY_POOL_DEPOSIT, + types.ICAAccountType_COMMUNITY_POOL_RETURN, + + types.ICAAccountType_CONVERTER_TRADE, // not on the host zone + -1, // indicates test case for non-ICA port + } + + for _, accountType := range icaAccountTypes { + // Reset the host zone for each test and wipe all addresses + s.App.StakeibcKeeper.SetHostZone(s.Ctx, types.HostZone{ + ChainId: HostChainId, + DepositAddress: DepositAddress, + CommunityPoolStakeHoldingAddress: CommunityPoolStakeHoldingAddress, + CommunityPoolRedeemHoldingAddress: CommunityPoolRedeemHoldingAddress, + }) + + // Determine the port Id from the account type + // If the portId is -1, pass a non-ica port + portId := "not-ica-port" + if accountType != -1 { + owner := types.FormatHostZoneICAOwner(HostChainId, accountType) + portId, _ = icatypes.NewControllerPortID(owner) + } + + // Call StoreHostZoneIcaAddress with the portId + // use the account name as the address to make the matching easier + address := accountType.String() + err := s.App.StakeibcKeeper.StoreHostZoneIcaAddress(s.Ctx, HostChainId, portId, address) + s.Require().NoError(err, "no error expected when calling store host zone ICA for %s", accountType.String()) + + // Check if the updated addresses matches expectations + s.checkHostZoneAddressStored(accountType) + + // Check that the relevant accounts are white listed from the rate limiter + s.checkAddressesWhitelisted(accountType) + } +} + +// ------------------------------------------ +// StoreTradeRouteIcaAddress +// ------------------------------------------ + +// Helper function to check that a single ICA address was stored on the trade route +// The address stored will match the string of the ICA account type +func (s *KeeperTestSuite) checkTradeRouteAddressStored(accountType types.ICAAccountType) { + // Determine the expected ICA addresses based on whether the account in question + // is registered in this test case + unwindAddress := "" + if accountType == types.ICAAccountType_CONVERTER_UNWIND { + unwindAddress = types.ICAAccountType_CONVERTER_UNWIND.String() + } + tradeAddress := "" + if accountType == types.ICAAccountType_CONVERTER_TRADE { + tradeAddress = types.ICAAccountType_CONVERTER_TRADE.String() + } + + // Confirm the expected addresses with the host zone + tradeRoute, found := s.App.StakeibcKeeper.GetTradeRoute(s.Ctx, RewardDenom, HostDenom) + s.Require().True(found, "trade route should have been found") + + s.Require().Equal(unwindAddress, tradeRoute.RewardAccount.Address, "unwind address") + s.Require().Equal(tradeAddress, tradeRoute.TradeAccount.Address, "trade address") +} + +func (s *KeeperTestSuite) TestStoreTradeRouteIcaAddress() { + // We'll run a test case for each the two ICA accounts, and 2 test cases for ports not on the trade route + icaAccountTypes := []types.ICAAccountType{ + types.ICAAccountType_CONVERTER_UNWIND, + types.ICAAccountType_CONVERTER_TRADE, + + types.ICAAccountType_DELEGATION, // not on the trade route + -1, // indicates test case for non-ICA port + } + + emptyTradeRoute := types.TradeRoute{ + RewardDenomOnRewardZone: RewardDenom, + HostDenomOnHostZone: HostDenom, + RewardAccount: types.ICAAccount{ + ChainId: HostChainId, + Type: types.ICAAccountType_CONVERTER_UNWIND, + }, + TradeAccount: types.ICAAccount{ + ChainId: HostChainId, + Type: types.ICAAccountType_CONVERTER_TRADE, + }, + } + + for _, accountType := range icaAccountTypes { + // Reset the trade route for each test and wipe all addresses + s.App.StakeibcKeeper.SetTradeRoute(s.Ctx, emptyTradeRoute) + + // Determine the port Id from the account type + // If the portId is -1, pass a non-ica port + portId := "not-ica-port" + if accountType != -1 { + owner := types.FormatTradeRouteICAOwner(HostChainId, RewardDenom, HostDenom, accountType) + portId, _ = icatypes.NewControllerPortID(owner) + } + + // Call StoreTradeRouteIcaAddress with the portId + // use the account name as the address to make the matching easier + address := accountType.String() + err := s.App.StakeibcKeeper.StoreTradeRouteIcaAddress(s.Ctx, HostChainId, portId, address) + s.Require().NoError(err, "no error expected when calling store trade route ICA for %s", accountType.String()) + + // Check if the updated addresses matches expectations + s.checkTradeRouteAddressStored(accountType) + } + + // Check with a matching port, but no matching chainId + accountType := types.ICAAccountType_CONVERTER_TRADE + owner := types.FormatTradeRouteICAOwner(HostChainId, RewardDenom, HostDenom, accountType) + portId, _ := icatypes.NewControllerPortID(owner) + address := accountType.String() + + emptyTradeRoute.TradeAccount.ChainId = "different-chain-id" + s.App.StakeibcKeeper.SetTradeRoute(s.Ctx, emptyTradeRoute) + + err := s.App.StakeibcKeeper.StoreTradeRouteIcaAddress(s.Ctx, HostChainId, portId, address) + s.Require().NoError(err, "no error expected when calling store trade route ICA for trade ICA with no chainId") + + s.checkTradeRouteAddressStored(-1) // checks no matches +} diff --git a/x/stakeibc/keeper/icqcallbacks.go b/x/stakeibc/keeper/icqcallbacks.go index 23d004ede..e6e6f94ac 100644 --- a/x/stakeibc/keeper/icqcallbacks.go +++ b/x/stakeibc/keeper/icqcallbacks.go @@ -13,6 +13,10 @@ const ( ICQCallbackID_Validator = "validator" ICQCallbackID_Calibrate = "calibrate" ICQCallbackID_CommunityPoolIcaBalance = "communitypoolicabalance" + ICQCallbackID_WithdrawalRewardBalance = "withdrawalrewardbalance" + ICQCallbackID_TradeRewardBalance = "traderewardbalance" + ICQCallbackID_TradeConvertedBalance = "tradeconvertedbalance" + ICQCallbackID_PoolPrice = "poolprice" ) // ICQCallbacks wrapper struct for stakeibc keeper @@ -50,5 +54,9 @@ func (c ICQCallbacks) RegisterICQCallbacks() icqtypes.QueryCallbacks { AddICQCallback(ICQCallbackID_Delegation, ICQCallback(DelegatorSharesCallback)). AddICQCallback(ICQCallbackID_Validator, ICQCallback(ValidatorSharesToTokensRateCallback)). AddICQCallback(ICQCallbackID_Calibrate, ICQCallback(CalibrateDelegationCallback)). - AddICQCallback(ICQCallbackID_CommunityPoolIcaBalance, ICQCallback(CommunityPoolIcaBalanceCallback)) + AddICQCallback(ICQCallbackID_CommunityPoolIcaBalance, ICQCallback(CommunityPoolIcaBalanceCallback)). + AddICQCallback(ICQCallbackID_WithdrawalRewardBalance, ICQCallback(WithdrawalRewardBalanceCallback)). + AddICQCallback(ICQCallbackID_TradeRewardBalance, ICQCallback(TradeRewardBalanceCallback)). + AddICQCallback(ICQCallbackID_TradeConvertedBalance, ICQCallback(TradeConvertedBalanceCallback)). + AddICQCallback(ICQCallbackID_PoolPrice, ICQCallback(PoolPriceCallback)) } diff --git a/x/stakeibc/keeper/icqcallbacks_fee_balance_test.go b/x/stakeibc/keeper/icqcallbacks_fee_balance_test.go index a0ef76437..a6a4e7819 100644 --- a/x/stakeibc/keeper/icqcallbacks_fee_balance_test.go +++ b/x/stakeibc/keeper/icqcallbacks_fee_balance_test.go @@ -216,5 +216,5 @@ func (s *KeeperTestSuite) TestFeeBalanceCallback_FailedSubmitTx() { err := keeper.FeeBalanceCallback(s.App.StakeibcKeeper, s.Ctx, tc.validArgs.callbackArgs, tc.validArgs.query) s.Require().ErrorContains(err, "Failed to SubmitTxs") - s.Require().ErrorContains(err, "invalid connection id, connection-X not found") + s.Require().ErrorContains(err, "connection connection-X not found") } diff --git a/x/stakeibc/keeper/icqcallbacks_pool_price.go b/x/stakeibc/keeper/icqcallbacks_pool_price.go new file mode 100644 index 000000000..5110f042e --- /dev/null +++ b/x/stakeibc/keeper/icqcallbacks_pool_price.go @@ -0,0 +1,97 @@ +package keeper + +import ( + "fmt" + + errorsmod "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/gogoproto/proto" + + "github.com/Stride-Labs/stride/v16/utils" + icqtypes "github.com/Stride-Labs/stride/v16/x/interchainquery/types" + "github.com/Stride-Labs/stride/v16/x/stakeibc/types" +) + +// PoolPriceCallback is a callback handler for PoolPrice query. +// The query response returns an Osmosis TwapRecord for the associated pool denom's +// +// The assets in the response are identified by indicies and are sorted alphabetically +// (e.g. if the two denom's are ibc/AXXX, and ibc/BXXX, +// then Asset0Denom is ibc/AXXX and Asset1Denom is ibc/BXXX) +// +// The price fields (P0LastSpotPrice and P1LastSpotPrice) represent the relative +// ratios of tokens in the pool +// +// P0LastSpotPrice gives the ratio of Asset0Denom / Asset1Denom +// P1LastSpotPrice gives the ratio of Asset1Denom / Asset0Denom +// +// When storing down the price, we want to store down the ratio of HostDenom. +// Meaning, if Asset0Denom is the host denom, we want to store P0LastSpotPrice +func PoolPriceCallback(k Keeper, ctx sdk.Context, args []byte, query icqtypes.Query) error { + k.Logger(ctx).Info(utils.LogICQCallbackWithHostZone(query.ChainId, ICQCallbackID_PoolPrice, + "Starting pool spot price callback, QueryId: %vs, QueryType: %s, Connection: %s", query.Id, query.QueryType, query.ConnectionId)) + + chainId := query.ChainId // should be the tradeZoneId, used in logging + + // Unmarshal the query response args, should be a TwapRecord type + var twapRecord types.OsmosisTwapRecord + err := twapRecord.Unmarshal(args) + if err != nil { + return errorsmod.Wrap(err, "unable to unmarshal the query response") + } + + // Unmarshal the callback data containing the tradeRoute we are on + var tradeRouteCallback types.TradeRouteCallback + if err := proto.Unmarshal(query.CallbackData, &tradeRouteCallback); err != nil { + return errorsmod.Wrapf(err, "unable to unmarshal trade reward balance callback data") + } + + // Lookup the trade route from the keys in the callback + tradeRoute, found := k.GetTradeRoute(ctx, tradeRouteCallback.RewardDenom, tradeRouteCallback.HostDenom) + if !found { + return types.ErrTradeRouteNotFound.Wrapf("trade route from %s to %s not found", + tradeRouteCallback.RewardDenom, tradeRouteCallback.HostDenom) + } + + // Confirm the denom's from the query response match the denom's in the route + if err := AssertTwapAssetsMatchTradeRoute(twapRecord, tradeRoute); err != nil { + return err + } + + // Get the associate "SpotPrice" from the twap record, based on the asset ordering + // The "SpotPrice" is actually a ratio of the assets in the pool + var price sdk.Dec + if twapRecord.Asset0Denom == tradeRoute.HostDenomOnTradeZone { + price = twapRecord.P0LastSpotPrice + } else { + price = twapRecord.P1LastSpotPrice + } + + k.Logger(ctx).Info(utils.LogICQCallbackWithHostZone(chainId, ICQCallbackID_PoolPrice, + "Query response - price ratio of %s to %s is %s", + tradeRoute.RewardDenomOnTradeZone, tradeRoute.HostDenomOnTradeZone, price)) + + // Update the price and time on the trade route data + tradeRoute.TradeConfig.SwapPrice = price + tradeRoute.TradeConfig.PriceUpdateTimestamp = uint64(ctx.BlockTime().UnixNano()) + k.SetTradeRoute(ctx, tradeRoute) + + return nil +} + +// Helper function to confirm that the two assets in the twap record match the assets in the trade route +// The assets in the twap record are sorted alphabetically, so we have to check both orderings +func AssertTwapAssetsMatchTradeRoute(twapRecord types.OsmosisTwapRecord, tradeRoute types.TradeRoute) error { + hostDenomMatchFirst := twapRecord.Asset0Denom == tradeRoute.HostDenomOnTradeZone + rewardDenomMatchSecond := twapRecord.Asset1Denom == tradeRoute.RewardDenomOnTradeZone + + rewardDenomMatchFirst := twapRecord.Asset0Denom == tradeRoute.RewardDenomOnTradeZone + hostDenomMatchSecond := twapRecord.Asset1Denom == tradeRoute.HostDenomOnTradeZone + + if (hostDenomMatchFirst && rewardDenomMatchSecond) || (rewardDenomMatchFirst && hostDenomMatchSecond) { + return nil + } + + return fmt.Errorf("Assets in query response (%s, %s) do not match denom's from trade route (%s, %s)", + twapRecord.Asset0Denom, twapRecord.Asset1Denom, tradeRoute.HostDenomOnTradeZone, tradeRoute.RewardDenomOnTradeZone) +} diff --git a/x/stakeibc/keeper/icqcallbacks_pool_price_test.go b/x/stakeibc/keeper/icqcallbacks_pool_price_test.go new file mode 100644 index 000000000..6e0302834 --- /dev/null +++ b/x/stakeibc/keeper/icqcallbacks_pool_price_test.go @@ -0,0 +1,227 @@ +package keeper_test + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/gogoproto/proto" + + icqtypes "github.com/Stride-Labs/stride/v16/x/interchainquery/types" + "github.com/Stride-Labs/stride/v16/x/stakeibc/keeper" + "github.com/Stride-Labs/stride/v16/x/stakeibc/types" +) + +type PoolPriceQueryCallbackTestCase struct { + TradeRoute types.TradeRoute + Price sdk.Dec + Response ICQCallbackArgs +} + +func (s *KeeperTestSuite) SetupPoolPriceCallbackTestCase(priceOnAsset0 bool) PoolPriceQueryCallbackTestCase { + hostPrice := sdk.MustNewDecFromStr("1.2") + rewardPrice := sdk.MustNewDecFromStr("0.8") + + // Alphabetize the and sort the denom's according to the ordering + rewardDenom := "ibc/reward-denom-on-trade" + hostDenom := "ibc/host-denom-on-trade" + + var twapRecord types.OsmosisTwapRecord + if priceOnAsset0 { + hostDenom = "a-" + hostDenom + rewardDenom = "z-" + rewardDenom + + twapRecord = types.OsmosisTwapRecord{ + Asset0Denom: hostDenom, + Asset1Denom: rewardDenom, + P0LastSpotPrice: hostPrice, + P1LastSpotPrice: rewardPrice, + } + } else { + hostDenom = "z-" + hostDenom + rewardDenom = "a-" + rewardDenom + + twapRecord = types.OsmosisTwapRecord{ + Asset0Denom: rewardDenom, + Asset1Denom: hostDenom, + P0LastSpotPrice: rewardPrice, + P1LastSpotPrice: hostPrice, + } + } + + route := types.TradeRoute{ + RewardDenomOnRewardZone: RewardDenom, + HostDenomOnHostZone: HostDenom, + + RewardDenomOnTradeZone: rewardDenom, + HostDenomOnTradeZone: hostDenom, + } + s.App.StakeibcKeeper.SetTradeRoute(s.Ctx, route) + + // Build query object and serialized query response + callbackDataBz, _ := proto.Marshal(&types.TradeRouteCallback{ + RewardDenom: RewardDenom, + HostDenom: HostDenom, + }) + query := icqtypes.Query{CallbackData: callbackDataBz} + queryResponse, _ := proto.Marshal(&twapRecord) + + return PoolPriceQueryCallbackTestCase{ + TradeRoute: route, + Price: hostPrice, + Response: ICQCallbackArgs{ + Query: query, + CallbackArgs: queryResponse, + }, + } +} + +func (s *KeeperTestSuite) TestPoolPriceCallback_Successful_HostTokenFirst() { + hostTokenFirst := true + tc := s.SetupPoolPriceCallbackTestCase(hostTokenFirst) + + err := keeper.PoolPriceCallback(s.App.StakeibcKeeper, s.Ctx, tc.Response.CallbackArgs, tc.Response.Query) + s.Require().NoError(err) + + // Confirm the new price was set on the trade route + route, found := s.App.StakeibcKeeper.GetTradeRoute(s.Ctx, RewardDenom, HostDenom) + s.Require().True(found, "trade route should have been found") + s.Require().Equal(tc.Price.String(), route.TradeConfig.SwapPrice.String(), "pool price") +} + +func (s *KeeperTestSuite) TestPoolPriceCallback_Successful_RewardTokenFirst() { + hostTokenFirst := false + tc := s.SetupPoolPriceCallbackTestCase(hostTokenFirst) + + err := keeper.PoolPriceCallback(s.App.StakeibcKeeper, s.Ctx, tc.Response.CallbackArgs, tc.Response.Query) + s.Require().NoError(err) + + // Confirm the new price was set on the trade route + route, found := s.App.StakeibcKeeper.GetTradeRoute(s.Ctx, RewardDenom, HostDenom) + s.Require().True(found, "trade route should have been found") + s.Require().Equal(tc.Price.String(), route.TradeConfig.SwapPrice.String(), "pool price") +} + +func (s *KeeperTestSuite) TestPoolPriceCallback_InvalidArgs() { + tc := s.SetupPoolPriceCallbackTestCase(true) // ordering doesn't matter + + // Submit callback with invalid callback args (so that it can't unmarshal into a coin) + invalidArgs := []byte("random bytes") + + err := keeper.PoolPriceCallback(s.App.StakeibcKeeper, s.Ctx, invalidArgs, tc.Response.Query) + s.Require().ErrorContains(err, "unable to unmarshal the query response") +} + +func (s *KeeperTestSuite) TestPoolPriceCallback_FailedToUnmarshalCallback() { + tc := s.SetupPoolPriceCallbackTestCase(true) // ordering doesn't matter + + // Update the callback data so that it can't be successfully unmarshalled + invalidQuery := tc.Response.Query + invalidQuery.CallbackData = []byte("random bytes") + + err := keeper.PoolPriceCallback(s.App.StakeibcKeeper, s.Ctx, tc.Response.CallbackArgs, invalidQuery) + s.Require().ErrorContains(err, "unable to unmarshal trade reward balance callback data") +} + +func (s *KeeperTestSuite) TestPoolPriceCallback_TradeRouteNotFound() { + tc := s.SetupPoolPriceCallbackTestCase(true) // ordering doesn't matter + + // Update the callback data so that it keys to a trade route that doesn't exist + invalidCallbackDataBz, _ := proto.Marshal(&types.TradeRouteCallback{ + RewardDenom: RewardDenom, + HostDenom: "different-host-denom", + }) + invalidQuery := tc.Response.Query + invalidQuery.CallbackData = invalidCallbackDataBz + + err := keeper.PoolPriceCallback(s.App.StakeibcKeeper, s.Ctx, tc.Response.CallbackArgs, invalidQuery) + s.Require().ErrorContains(err, "trade route not found") +} + +func (s *KeeperTestSuite) TestPoolPriceCallback_TradeDenomMismatch() { + tc := s.SetupPoolPriceCallbackTestCase(true) // ordering doesn't matter + + // Update the trade route so that the denom's in the route don't match the query response + invalidTradeRoute := tc.TradeRoute + invalidTradeRoute.RewardDenomOnTradeZone = "different-denom" + s.App.StakeibcKeeper.SetTradeRoute(s.Ctx, invalidTradeRoute) + + err := keeper.PoolPriceCallback(s.App.StakeibcKeeper, s.Ctx, tc.Response.CallbackArgs, tc.Response.Query) + s.Require().ErrorContains(err, "Assets in query response") + s.Require().ErrorContains(err, "do not match denom's from trade route") + + // Do it again, but with the other denom + invalidTradeRoute = tc.TradeRoute + invalidTradeRoute.HostDenomOnTradeZone = "different-denom" + s.App.StakeibcKeeper.SetTradeRoute(s.Ctx, invalidTradeRoute) + + err = keeper.PoolPriceCallback(s.App.StakeibcKeeper, s.Ctx, tc.Response.CallbackArgs, tc.Response.Query) + s.Require().ErrorContains(err, "Assets in query response") + s.Require().ErrorContains(err, "do not match denom's from trade route") +} + +func (s *KeeperTestSuite) TestAssertTwapAssetsMatchTradeRoute() { + testCases := []struct { + name string + twapRecord types.OsmosisTwapRecord + tradeRoute types.TradeRoute + expectedMatch bool + }{ + { + name: "successful match - 1", + twapRecord: types.OsmosisTwapRecord{Asset0Denom: "denom-a", Asset1Denom: "denom-b"}, + tradeRoute: types.TradeRoute{RewardDenomOnTradeZone: "denom-a", HostDenomOnTradeZone: "denom-b"}, + expectedMatch: true, + }, + { + name: "successful match - 2", + twapRecord: types.OsmosisTwapRecord{Asset0Denom: "denom-b", Asset1Denom: "denom-a"}, + tradeRoute: types.TradeRoute{RewardDenomOnTradeZone: "denom-b", HostDenomOnTradeZone: "denom-a"}, + expectedMatch: true, + }, + { + name: "successful match - 3", + twapRecord: types.OsmosisTwapRecord{Asset0Denom: "denom-a", Asset1Denom: "denom-b"}, + tradeRoute: types.TradeRoute{RewardDenomOnTradeZone: "denom-b", HostDenomOnTradeZone: "denom-a"}, + expectedMatch: true, + }, + { + name: "successful match - 4", + twapRecord: types.OsmosisTwapRecord{Asset0Denom: "denom-b", Asset1Denom: "denom-a"}, + tradeRoute: types.TradeRoute{RewardDenomOnTradeZone: "denom-a", HostDenomOnTradeZone: "denom-b"}, + expectedMatch: true, + }, + { + name: "mismatch osmo asset 0", + twapRecord: types.OsmosisTwapRecord{Asset0Denom: "denom-z", Asset1Denom: "denom-b"}, + tradeRoute: types.TradeRoute{RewardDenomOnTradeZone: "denom-a", HostDenomOnTradeZone: "denom-b"}, + expectedMatch: false, + }, + { + name: "mismatch osmo asset 1", + twapRecord: types.OsmosisTwapRecord{Asset0Denom: "denom-a", Asset1Denom: "denom-z"}, + tradeRoute: types.TradeRoute{RewardDenomOnTradeZone: "denom-a", HostDenomOnTradeZone: "denom-b"}, + expectedMatch: false, + }, + { + name: "mismatch route reward denom", + twapRecord: types.OsmosisTwapRecord{Asset0Denom: "denom-a", Asset1Denom: "denom-b"}, + tradeRoute: types.TradeRoute{RewardDenomOnTradeZone: "denom-z", HostDenomOnTradeZone: "denom-b"}, + expectedMatch: false, + }, + { + name: "mismatch route host denom", + twapRecord: types.OsmosisTwapRecord{Asset0Denom: "denom-a", Asset1Denom: "denom-b"}, + tradeRoute: types.TradeRoute{RewardDenomOnTradeZone: "denom-a", HostDenomOnTradeZone: "denom-z"}, + expectedMatch: false, + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + err := keeper.AssertTwapAssetsMatchTradeRoute(tc.twapRecord, tc.tradeRoute) + if tc.expectedMatch { + s.Require().NoError(err) + } else { + s.Require().Error(err) + } + }) + } +} diff --git a/x/stakeibc/keeper/icqcallbacks_trade_converted_balance.go b/x/stakeibc/keeper/icqcallbacks_trade_converted_balance.go new file mode 100644 index 000000000..79696d70d --- /dev/null +++ b/x/stakeibc/keeper/icqcallbacks_trade_converted_balance.go @@ -0,0 +1,64 @@ +package keeper + +import ( + sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + + errorsmod "cosmossdk.io/errors" + "github.com/cosmos/gogoproto/proto" + + icqkeeper "github.com/Stride-Labs/stride/v16/x/interchainquery/keeper" + + "github.com/Stride-Labs/stride/v16/utils" + icqtypes "github.com/Stride-Labs/stride/v16/x/interchainquery/types" + "github.com/Stride-Labs/stride/v16/x/stakeibc/types" +) + +// TradeConvertedBalanceCallback is a callback handler for TradeConvertedBalance queries. +// The query response will return the trade account balance for a converted (foreign ibc) denom +// If the balance is non-zero, ICA MsgSends are submitted to transfer the discovered balance back to hostZone +// +// Note: for now, to get proofs in your ICQs, you need to query the entire store on the host zone! e.g. "store/bank/key" +func TradeConvertedBalanceCallback(k Keeper, ctx sdk.Context, args []byte, query icqtypes.Query) error { + k.Logger(ctx).Info(utils.LogICQCallbackWithHostZone(query.ChainId, ICQCallbackID_TradeConvertedBalance, + "Starting trade converted balance callback, QueryId: %vs, QueryType: %s, Connection: %s", query.Id, query.QueryType, query.ConnectionId)) + + chainId := query.ChainId // should be the tradeZoneId + + // Unmarshal the query response args to determine the balance + tradeConvertedBalanceAmount, err := icqkeeper.UnmarshalAmountFromBalanceQuery(k.cdc, args) + if err != nil { + return errorsmod.Wrap(err, "unable to determine balance from query response") + } + + // Unmarshal the callback data containing the tradeRoute we are on + var tradeRouteCallback types.TradeRouteCallback + if err := proto.Unmarshal(query.CallbackData, &tradeRouteCallback); err != nil { + return errorsmod.Wrapf(err, "unable to unmarshal trade reward balance callback data") + } + + // Lookup the trade route from the keys in the callback + tradeRoute, found := k.GetTradeRoute(ctx, tradeRouteCallback.RewardDenom, tradeRouteCallback.HostDenom) + if !found { + return types.ErrTradeRouteNotFound.Wrapf("trade route from %s to %s not found", + tradeRouteCallback.RewardDenom, tradeRouteCallback.HostDenom) + } + + // Confirm the balance is greater than zero, or else exit with no further action + if tradeConvertedBalanceAmount.LTE(sdkmath.ZeroInt()) { + k.Logger(ctx).Info(utils.LogICQCallbackWithHostZone(chainId, ICQCallbackID_TradeConvertedBalance, + "Not enough balance of traded tokens yet, balance: %v", tradeConvertedBalanceAmount)) + return nil + } + + // Using ICA commands on the trade address, transfer the found converted tokens from the trade zone to the host zone + if err := k.TransferConvertedTokensTradeToHost(ctx, tradeConvertedBalanceAmount, tradeRoute); err != nil { + return errorsmod.Wrapf(err, "initiating transfer of converted tokens to back to host zone failed") + } + + k.Logger(ctx).Info(utils.LogICQCallbackWithHostZone(chainId, ICQCallbackID_TradeConvertedBalance, + "Sending discovered converted tokens %v %s from tradeZone back to hostZone", + tradeConvertedBalanceAmount, tradeRoute.HostDenomOnTradeZone)) + + return nil +} diff --git a/x/stakeibc/keeper/icqcallbacks_trade_converted_balance_test.go b/x/stakeibc/keeper/icqcallbacks_trade_converted_balance_test.go new file mode 100644 index 000000000..6d6162209 --- /dev/null +++ b/x/stakeibc/keeper/icqcallbacks_trade_converted_balance_test.go @@ -0,0 +1,137 @@ +package keeper_test + +import ( + "time" + + sdkmath "cosmossdk.io/math" + "github.com/cosmos/gogoproto/proto" + ibctesting "github.com/cosmos/ibc-go/v7/testing" + + epochtypes "github.com/Stride-Labs/stride/v16/x/epochs/types" + icqtypes "github.com/Stride-Labs/stride/v16/x/interchainquery/types" + "github.com/Stride-Labs/stride/v16/x/stakeibc/keeper" + "github.com/Stride-Labs/stride/v16/x/stakeibc/types" +) + +func (s *KeeperTestSuite) SetupTradeConvertedBalanceCallbackTestCase() BalanceQueryCallbackTestCase { + // Create the connection between Stride and HostChain with the withdrawal account initialized + tradeAccountOwner := types.FormatTradeRouteICAOwner(HostChainId, RewardDenom, HostDenom, types.ICAAccountType_CONVERTER_TRADE) + tradeChannelId, tradePortId := s.CreateICAChannel(tradeAccountOwner) + + route := types.TradeRoute{ + RewardDenomOnRewardZone: RewardDenom, + HostDenomOnHostZone: HostDenom, + HostDenomOnTradeZone: "ibc/host_on_trade", + + TradeToHostChannelId: "channel-2", + + HostAccount: types.ICAAccount{ + Address: "withdrawal-address", + }, + TradeAccount: types.ICAAccount{ + ChainId: HostChainId, + Address: "trade-address", + ConnectionId: ibctesting.FirstConnectionID, + Type: types.ICAAccountType_CONVERTER_TRADE, + }, + } + s.App.StakeibcKeeper.SetTradeRoute(s.Ctx, route) + + // Create and set the epoch tracker for timeouts + timeoutDuration := time.Second * 30 + s.CreateEpochForICATimeout(epochtypes.STRIDE_EPOCH, timeoutDuration) + + // Build query object and serialized query response + balance := sdkmath.NewInt(1_000_000) + callbackDataBz, _ := proto.Marshal(&types.TradeRouteCallback{ + RewardDenom: RewardDenom, + HostDenom: HostDenom, + }) + query := icqtypes.Query{CallbackData: callbackDataBz} + queryResponse := s.CreateBalanceQueryResponse(balance.Int64(), route.HostDenomOnTradeZone) + + return BalanceQueryCallbackTestCase{ + TradeRoute: route, + Balance: balance, + Response: ICQCallbackArgs{ + Query: query, + CallbackArgs: queryResponse, + }, + ChannelID: tradeChannelId, + PortID: tradePortId, + } +} + +// Verify that a normal TradeConvertedBalanceCallback does fire off the ICA for transfer +func (s *KeeperTestSuite) TestTradeConvertedBalanceCallback_Successful() { + tc := s.SetupTradeConvertedBalanceCallbackTestCase() + + // Check that the ICA was submitted from within the ICQ callback + s.CheckICATxSubmitted(tc.PortID, tc.ChannelID, func() error { + return keeper.TradeConvertedBalanceCallback(s.App.StakeibcKeeper, s.Ctx, tc.Response.CallbackArgs, tc.Response.Query) + }) +} + +func (s *KeeperTestSuite) TestTradeConvertedBalanceCallback_ZeroBalance() { + tc := s.SetupTradeConvertedBalanceCallbackTestCase() + + // Replace the query response with a coin that has a zero amount + tc.Response.CallbackArgs = s.CreateBalanceQueryResponse(0, tc.TradeRoute.HostDenomOnHostZone) + + // We also remove the connection ID from the trade route so that, IF an ICA was submitted it would fail + // However, it should never go down this route since the balance is 0 + invalidRoute := tc.TradeRoute + invalidRoute.TradeAccount.ConnectionId = "bad-connection" + s.App.StakeibcKeeper.SetTradeRoute(s.Ctx, invalidRoute) + + err := keeper.TradeConvertedBalanceCallback(s.App.StakeibcKeeper, s.Ctx, tc.Response.CallbackArgs, tc.Response.Query) + s.Require().NoError(err) +} + +func (s *KeeperTestSuite) TestTradeConvertedBalanceCallback_InvalidArgs() { + tc := s.SetupTradeConvertedBalanceCallbackTestCase() + + // Submit callback with invalid callback args (so that it can't unmarshal into a coin) + invalidArgs := []byte("random bytes") + + err := keeper.TradeConvertedBalanceCallback(s.App.StakeibcKeeper, s.Ctx, invalidArgs, tc.Response.Query) + s.Require().ErrorContains(err, "unable to determine balance from query response") +} + +func (s *KeeperTestSuite) TestTradeConvertedBalanceCallback_InvalidCallbackData() { + tc := s.SetupTradeConvertedBalanceCallbackTestCase() + + // Update the callback data so that it can't be successfully unmarshalled + invalidQuery := tc.Response.Query + invalidQuery.CallbackData = []byte("random bytes") + + err := keeper.TradeConvertedBalanceCallback(s.App.StakeibcKeeper, s.Ctx, tc.Response.CallbackArgs, invalidQuery) + s.Require().ErrorContains(err, "unable to unmarshal trade reward balance callback data") +} + +func (s *KeeperTestSuite) TestTradeConvertedBalanceCallback_TradeRouteNotFound() { + tc := s.SetupTradeConvertedBalanceCallbackTestCase() + + // Update the callback data so that it keys to a trade route that doesn't exist + invalidCallbackDataBz, _ := proto.Marshal(&types.TradeRouteCallback{ + RewardDenom: RewardDenom, + HostDenom: "different-host-denom", + }) + invalidQuery := tc.Response.Query + invalidQuery.CallbackData = invalidCallbackDataBz + + err := keeper.TradeConvertedBalanceCallback(s.App.StakeibcKeeper, s.Ctx, tc.Response.CallbackArgs, invalidQuery) + s.Require().ErrorContains(err, "trade route not found") +} + +func (s *KeeperTestSuite) TestTradeConvertedBalanceCallback_FailedSubmitTx() { + tc := s.SetupTradeConvertedBalanceCallbackTestCase() + + // Remove connectionId from host ICAAccount on TradeRoute so the ICA tx fails + invalidRoute := tc.TradeRoute + invalidRoute.TradeAccount.ConnectionId = "bad-connection" + s.App.StakeibcKeeper.SetTradeRoute(s.Ctx, invalidRoute) + + err := keeper.TradeConvertedBalanceCallback(s.App.StakeibcKeeper, s.Ctx, tc.Response.CallbackArgs, tc.Response.Query) + s.Require().ErrorContains(err, "Failed to submit ICA tx") +} diff --git a/x/stakeibc/keeper/icqcallbacks_trade_reward_balance.go b/x/stakeibc/keeper/icqcallbacks_trade_reward_balance.go new file mode 100644 index 000000000..4917b61e4 --- /dev/null +++ b/x/stakeibc/keeper/icqcallbacks_trade_reward_balance.go @@ -0,0 +1,66 @@ +package keeper + +import ( + sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + + errorsmod "cosmossdk.io/errors" + "github.com/cosmos/gogoproto/proto" + + icqkeeper "github.com/Stride-Labs/stride/v16/x/interchainquery/keeper" + + "github.com/Stride-Labs/stride/v16/utils" + icqtypes "github.com/Stride-Labs/stride/v16/x/interchainquery/types" + "github.com/Stride-Labs/stride/v16/x/stakeibc/types" +) + +// TradeRewardBalanceCallback is a callback handler for TradeRewardBalance queries. +// The query response will return the trade ICA account balance for a specific (foreign ibc) denom +// If the balance is non-zero, ICA MsgSends are submitted to initiate a swap on the tradeZone +// +// Note: for now, to get proofs in your ICQs, you need to query the entire store on the host zone! e.g. "store/bank/key" +func TradeRewardBalanceCallback(k Keeper, ctx sdk.Context, args []byte, query icqtypes.Query) error { + k.Logger(ctx).Info(utils.LogICQCallbackWithHostZone(query.ChainId, ICQCallbackID_TradeRewardBalance, + "Starting withdrawal reward balance callback, QueryId: %vs, QueryType: %s, Connection: %s", query.Id, query.QueryType, query.ConnectionId)) + + chainId := query.ChainId // should be the tradeZoneId, used in logging + + // Unmarshal the query response args to determine the balance + tradeRewardBalanceAmount, err := icqkeeper.UnmarshalAmountFromBalanceQuery(k.cdc, args) + if err != nil { + return errorsmod.Wrap(err, "unable to determine balance from query response") + } + + // Confirm the balance is greater than zero, or else exit without further action for now + if tradeRewardBalanceAmount.LTE(sdkmath.ZeroInt()) { + k.Logger(ctx).Info(utils.LogICQCallbackWithHostZone(chainId, ICQCallbackID_TradeRewardBalance, + "Not enough reward tokens found in trade ICA, balance: %+v", tradeRewardBalanceAmount)) + return nil + } + + // Unmarshal the callback data containing the tradeRoute we are on + var tradeRouteCallback types.TradeRouteCallback + if err := proto.Unmarshal(query.CallbackData, &tradeRouteCallback); err != nil { + return errorsmod.Wrapf(err, "unable to unmarshal trade reward balance callback data") + } + + // Lookup the trade route from the keys in the callback + tradeRoute, found := k.GetTradeRoute(ctx, tradeRouteCallback.RewardDenom, tradeRouteCallback.HostDenom) + if !found { + return types.ErrTradeRouteNotFound.Wrapf("trade route from %s to %s not found", + tradeRouteCallback.RewardDenom, tradeRouteCallback.HostDenom) + } + k.Logger(ctx).Info(utils.LogICQCallbackWithHostZone(chainId, ICQCallbackID_TradeRewardBalance, + "Query response - Withdrawal Reward Balance: %v %s", tradeRewardBalanceAmount, tradeRoute.RewardDenomOnTradeZone)) + + // Trade all found reward tokens in the trade ICA to the output denom of their trade pool + if err := k.SwapRewardTokens(ctx, tradeRewardBalanceAmount, tradeRoute); err != nil { + return errorsmod.Wrapf(err, "unable to swap reward tokens") + } + + k.Logger(ctx).Info(utils.LogICQCallbackWithHostZone(chainId, ICQCallbackID_TradeRewardBalance, + "Swapping discovered reward tokens %v %s for %s", + tradeRewardBalanceAmount, tradeRoute.RewardDenomOnTradeZone, tradeRoute.HostDenomOnTradeZone)) + + return nil +} diff --git a/x/stakeibc/keeper/icqcallbacks_trade_reward_balance_test.go b/x/stakeibc/keeper/icqcallbacks_trade_reward_balance_test.go new file mode 100644 index 000000000..9a261bd7c --- /dev/null +++ b/x/stakeibc/keeper/icqcallbacks_trade_reward_balance_test.go @@ -0,0 +1,154 @@ +package keeper_test + +import ( + "time" + + sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/gogoproto/proto" + ibctesting "github.com/cosmos/ibc-go/v7/testing" + + epochtypes "github.com/Stride-Labs/stride/v16/x/epochs/types" + icqtypes "github.com/Stride-Labs/stride/v16/x/interchainquery/types" + "github.com/Stride-Labs/stride/v16/x/stakeibc/keeper" + "github.com/Stride-Labs/stride/v16/x/stakeibc/types" +) + +func (s *KeeperTestSuite) SetupTradeRewardBalanceCallbackTestCase() BalanceQueryCallbackTestCase { + // Create the connection between Stride and HostChain with the withdrawal account initialized + tradeAccountOwner := types.FormatTradeRouteICAOwner(HostChainId, RewardDenom, HostDenom, types.ICAAccountType_CONVERTER_TRADE) + tradeChannelId, tradePortId := s.CreateICAChannel(tradeAccountOwner) + + route := types.TradeRoute{ + RewardDenomOnRewardZone: RewardDenom, + HostDenomOnHostZone: HostDenom, + + RewardDenomOnTradeZone: "ibc/reward_on_trade", + HostDenomOnTradeZone: "ibc/host_on_trade", + + TradeAccount: types.ICAAccount{ + ChainId: HostChainId, + Address: "trade-address", + ConnectionId: ibctesting.FirstConnectionID, + Type: types.ICAAccountType_CONVERTER_TRADE, + }, + + TradeConfig: types.TradeConfig{ + PoolId: 100, + SwapPrice: sdk.OneDec(), + MinSwapAmount: sdk.ZeroInt(), + MaxSwapAmount: sdkmath.NewInt(1000), + MaxAllowedSwapLossRate: sdk.MustNewDecFromStr("0.1"), + }, + } + s.App.StakeibcKeeper.SetTradeRoute(s.Ctx, route) + + // Create and set the epoch tracker for timeouts + timeoutDuration := time.Second * 30 + s.CreateEpochForICATimeout(epochtypes.HOUR_EPOCH, timeoutDuration) + + // Build query object and serialized query response + balance := sdkmath.NewInt(1_000_000) + callbackDataBz, _ := proto.Marshal(&types.TradeRouteCallback{ + RewardDenom: RewardDenom, + HostDenom: HostDenom, + }) + query := icqtypes.Query{CallbackData: callbackDataBz} + queryResponse := s.CreateBalanceQueryResponse(balance.Int64(), route.RewardDenomOnTradeZone) + + return BalanceQueryCallbackTestCase{ + TradeRoute: route, + Balance: balance, + Response: ICQCallbackArgs{ + Query: query, + CallbackArgs: queryResponse, + }, + ChannelID: tradeChannelId, + PortID: tradePortId, + } +} + +// Verify that a normal TradeRewardBalanceCallback does fire off the ICA for transfer +func (s *KeeperTestSuite) TestTradeRewardBalanceCallback_Successful() { + tc := s.SetupTradeRewardBalanceCallbackTestCase() + + // Check that the callback triggered the ICA + s.CheckICATxSubmitted(tc.PortID, tc.ChannelID, func() error { + return keeper.TradeRewardBalanceCallback(s.App.StakeibcKeeper, s.Ctx, tc.Response.CallbackArgs, tc.Response.Query) + }) +} + +// Verify that if the amount returned by the ICQ response is less than the min_swap_amount, no trade happens +func (s *KeeperTestSuite) TestTradeRewardBalanceCallback_SuccessfulNoSwap() { + tc := s.SetupTradeRewardBalanceCallbackTestCase() + + // Set min swap amount to be greater than the transfer amount + route := tc.TradeRoute + route.TradeConfig.MinSwapAmount = tc.Balance.Add(sdkmath.OneInt()) + s.App.StakeibcKeeper.SetTradeRoute(s.Ctx, route) + + // ICA inside of TransferRewardTokensHostToTrade should not actually execute because of min_swap_amount + s.CheckICATxNotSubmitted(tc.PortID, tc.ChannelID, func() error { + return keeper.TradeRewardBalanceCallback(s.App.StakeibcKeeper, s.Ctx, tc.Response.CallbackArgs, tc.Response.Query) + }) +} + +func (s *KeeperTestSuite) TestTradeRewardBalanceCallback_ZeroBalance() { + tc := s.SetupTradeRewardBalanceCallbackTestCase() + + // Replace the query response with a coin that has a zero amount + tc.Response.CallbackArgs = s.CreateBalanceQueryResponse(0, tc.TradeRoute.HostDenomOnTradeZone) + + // Confirm the ICA was not executed + s.CheckICATxNotSubmitted(tc.PortID, tc.ChannelID, func() error { + return keeper.TradeRewardBalanceCallback(s.App.StakeibcKeeper, s.Ctx, tc.Response.CallbackArgs, tc.Response.Query) + }) +} + +func (s *KeeperTestSuite) TestTradeRewardBalanceCallback_InvalidArgs() { + tc := s.SetupTradeRewardBalanceCallbackTestCase() + + // Submit callback with invalid callback args (so that it can't unmarshal into a coin) + invalidArgs := []byte("random bytes") + + err := keeper.TradeRewardBalanceCallback(s.App.StakeibcKeeper, s.Ctx, invalidArgs, tc.Response.Query) + s.Require().ErrorContains(err, "unable to determine balance from query response") +} + +func (s *KeeperTestSuite) TestTradeRewardBalanceCallback_InvalidCallbackData() { + tc := s.SetupTradeRewardBalanceCallbackTestCase() + + // Update the callback data so that it can't be successfully unmarshalled + invalidQuery := tc.Response.Query + invalidQuery.CallbackData = []byte("random bytes") + + err := keeper.TradeRewardBalanceCallback(s.App.StakeibcKeeper, s.Ctx, tc.Response.CallbackArgs, invalidQuery) + s.Require().ErrorContains(err, "unable to unmarshal trade reward balance callback data") +} + +func (s *KeeperTestSuite) TestTradeRewardBalanceCallback_TradeRouteNotFound() { + tc := s.SetupTradeRewardBalanceCallbackTestCase() + + // Update the callback data so that it keys to a trade route that doesn't exist + invalidCallbackDataBz, _ := proto.Marshal(&types.TradeRouteCallback{ + RewardDenom: RewardDenom, + HostDenom: "different-host-denom", + }) + invalidQuery := tc.Response.Query + invalidQuery.CallbackData = invalidCallbackDataBz + + err := keeper.TradeRewardBalanceCallback(s.App.StakeibcKeeper, s.Ctx, tc.Response.CallbackArgs, invalidQuery) + s.Require().ErrorContains(err, "trade route not found") +} + +func (s *KeeperTestSuite) TestTradeRewardBalanceCallback_FailedSubmitTx() { + tc := s.SetupTradeRewardBalanceCallbackTestCase() + + // Remove connectionId from host ICAAccount on TradeRoute so the ICA tx fails + invalidRoute := tc.TradeRoute + invalidRoute.TradeAccount.ConnectionId = "bad-connection" + s.App.StakeibcKeeper.SetTradeRoute(s.Ctx, invalidRoute) + + err := keeper.TradeRewardBalanceCallback(s.App.StakeibcKeeper, s.Ctx, tc.Response.CallbackArgs, tc.Response.Query) + s.Require().ErrorContains(err, "Failed to submit ICA tx") +} diff --git a/x/stakeibc/keeper/icqcallbacks_withdrawal_balance_test.go b/x/stakeibc/keeper/icqcallbacks_withdrawal_balance_test.go index c9f9ed96b..9edf88528 100644 --- a/x/stakeibc/keeper/icqcallbacks_withdrawal_balance_test.go +++ b/x/stakeibc/keeper/icqcallbacks_withdrawal_balance_test.go @@ -238,5 +238,5 @@ func (s *KeeperTestSuite) TestWithdrawalBalanceCallback_FailedSubmitTx() { err := keeper.WithdrawalBalanceCallback(s.App.StakeibcKeeper, s.Ctx, tc.validArgs.callbackArgs, tc.validArgs.query) s.Require().ErrorContains(err, "Failed to SubmitTxs") - s.Require().ErrorContains(err, "invalid connection id, connection-X not found") + s.Require().ErrorContains(err, "connection connection-X not found") } diff --git a/x/stakeibc/keeper/icqcallbacks_withdrawal_reward_balance.go b/x/stakeibc/keeper/icqcallbacks_withdrawal_reward_balance.go new file mode 100644 index 000000000..f72dcb36e --- /dev/null +++ b/x/stakeibc/keeper/icqcallbacks_withdrawal_reward_balance.go @@ -0,0 +1,67 @@ +package keeper + +import ( + sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + + errorsmod "cosmossdk.io/errors" + "github.com/cosmos/gogoproto/proto" + + icqkeeper "github.com/Stride-Labs/stride/v16/x/interchainquery/keeper" + + "github.com/Stride-Labs/stride/v16/utils" + icqtypes "github.com/Stride-Labs/stride/v16/x/interchainquery/types" + "github.com/Stride-Labs/stride/v16/x/stakeibc/types" +) + +// WithdrawalRewardBalanceCallback is a callback handler for WithdrawalRewardBalance queries. +// The query response will return the withdrawal account balance for a specific (foreign ibc) denom +// If the balance is non-zero, ICA MsgSends are submitted to transfer the discovered balance to the tradeZone +// +// Note: for now, to get proofs in your ICQs, you need to query the entire store on the host zone! e.g. "store/bank/key" +func WithdrawalRewardBalanceCallback(k Keeper, ctx sdk.Context, args []byte, query icqtypes.Query) error { + k.Logger(ctx).Info(utils.LogICQCallbackWithHostZone(query.ChainId, ICQCallbackID_WithdrawalRewardBalance, + "Starting withdrawal reward balance callback, QueryId: %vs, QueryType: %s, Connection: %s", query.Id, query.QueryType, query.ConnectionId)) + + chainId := query.ChainId + + // Unmarshal the query response args to determine the balance + withdrawalRewardBalanceAmount, err := icqkeeper.UnmarshalAmountFromBalanceQuery(k.cdc, args) + if err != nil { + return errorsmod.Wrap(err, "unable to determine balance from query response") + } + + // Confirm the balance is greater than zero, or else exit early without further action + if withdrawalRewardBalanceAmount.LTE(sdkmath.ZeroInt()) { + k.Logger(ctx).Info(utils.LogICQCallbackWithHostZone(chainId, ICQCallbackID_WithdrawalRewardBalance, + "Not enough reward tokens yet found in withdrawalICA, balance: %v", withdrawalRewardBalanceAmount)) + return nil + } + + // Unmarshal the callback data containing the tradeRoute we are on + var tradeRouteCallback types.TradeRouteCallback + if err := proto.Unmarshal(query.CallbackData, &tradeRouteCallback); err != nil { + return errorsmod.Wrapf(err, "unable to unmarshal trade reward balance callback data") + } + + // Lookup the trade route from the keys in the callback + tradeRoute, found := k.GetTradeRoute(ctx, tradeRouteCallback.RewardDenom, tradeRouteCallback.HostDenom) + if !found { + return types.ErrTradeRouteNotFound.Wrapf("trade route from %s to %s not found", + tradeRouteCallback.RewardDenom, tradeRouteCallback.HostDenom) + } + + k.Logger(ctx).Info(utils.LogICQCallbackWithHostZone(chainId, ICQCallbackID_WithdrawalRewardBalance, + "Query response - Withdrawal Reward Balance: %v %s", withdrawalRewardBalanceAmount, tradeRoute.RewardDenomOnHostZone)) + + // Using ICA commands on the withdrawal address, transfer the found reward tokens from the host zone to the trade zone + if err := k.TransferRewardTokensHostToTrade(ctx, withdrawalRewardBalanceAmount, tradeRoute); err != nil { + return errorsmod.Wrapf(err, "initiating transfer of reward tokens to trade ICA failed") + } + + k.Logger(ctx).Info(utils.LogICQCallbackWithHostZone(chainId, ICQCallbackID_WithdrawalRewardBalance, + "Sending discovered reward tokens %v %s from hostZone to tradeZone", + withdrawalRewardBalanceAmount, tradeRoute.RewardDenomOnHostZone)) + + return nil +} diff --git a/x/stakeibc/keeper/icqcallbacks_withdrawal_reward_balance_test.go b/x/stakeibc/keeper/icqcallbacks_withdrawal_reward_balance_test.go new file mode 100644 index 000000000..963e940dd --- /dev/null +++ b/x/stakeibc/keeper/icqcallbacks_withdrawal_reward_balance_test.go @@ -0,0 +1,163 @@ +package keeper_test + +import ( + "time" + + sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/gogoproto/proto" + ibctesting "github.com/cosmos/ibc-go/v7/testing" + + epochtypes "github.com/Stride-Labs/stride/v16/x/epochs/types" + icqtypes "github.com/Stride-Labs/stride/v16/x/interchainquery/types" + "github.com/Stride-Labs/stride/v16/x/stakeibc/keeper" + "github.com/Stride-Labs/stride/v16/x/stakeibc/types" +) + +// WithdrawalRewardBalanceCallback will trigger TransferRewardTokensHostToTrade +// Therefore we need to setup traderoute fields used in the entire transfer (with pfm) +func (s *KeeperTestSuite) SetupWithdrawalRewardBalanceCallbackTestCase() BalanceQueryCallbackTestCase { + // Create the connection between Stride and HostChain with the withdrawal account initialized + withdrawalAccountOwner := types.FormatHostZoneICAOwner(HostChainId, types.ICAAccountType_WITHDRAWAL) + withdrawalChannelId, withdrawalPortId := s.CreateICAChannel(withdrawalAccountOwner) + + route := types.TradeRoute{ + RewardDenomOnRewardZone: RewardDenom, + HostDenomOnHostZone: HostDenom, + RewardDenomOnHostZone: "ibc/reward_on_host", + + HostToRewardChannelId: "channel-2", + RewardToTradeChannelId: "channel-3", + + HostAccount: types.ICAAccount{ + ChainId: HostChainId, + Address: "withdrawal-address", + ConnectionId: ibctesting.FirstConnectionID, + Type: types.ICAAccountType_WITHDRAWAL, + }, + RewardAccount: types.ICAAccount{ + Address: "reward-address", + }, + TradeAccount: types.ICAAccount{ + Address: "trade-address", + }, + + TradeConfig: types.TradeConfig{ + MinSwapAmount: sdk.ZeroInt(), + SwapPrice: sdk.OneDec(), + }, + } + s.App.StakeibcKeeper.SetTradeRoute(s.Ctx, route) + + // Create and set the epoch tracker for timeouts + timeoutDuration := time.Second * 30 + s.CreateEpochForICATimeout(epochtypes.STRIDE_EPOCH, timeoutDuration) + + // Build query object and serialized query response + balance := sdkmath.NewInt(1_000_000) + callbackDataBz, _ := proto.Marshal(&types.TradeRouteCallback{ + RewardDenom: RewardDenom, + HostDenom: HostDenom, + }) + query := icqtypes.Query{CallbackData: callbackDataBz} + queryResponse := s.CreateBalanceQueryResponse(balance.Int64(), route.RewardDenomOnHostZone) + + return BalanceQueryCallbackTestCase{ + TradeRoute: route, + Balance: balance, + Response: ICQCallbackArgs{ + Query: query, + CallbackArgs: queryResponse, + }, + ChannelID: withdrawalChannelId, + PortID: withdrawalPortId, + } +} + +// Verify that a normal WithdrawalRewardBalanceCallback does fire off the ICA for transfer +func (s *KeeperTestSuite) TestWithdrawalRewardBalanceCallback_Successful() { + tc := s.SetupWithdrawalRewardBalanceCallbackTestCase() + + // ICA inside of TransferRewardTokensHostToTrade should execute but it uses submitTXWithoutCallback + // So no need to confirm ICA callback data was stored and no need to confirm callback args values + + // Confirm ICA was submitted by checking that the sequence number incremented + s.CheckICATxSubmitted(tc.PortID, tc.ChannelID, func() error { + return keeper.WithdrawalRewardBalanceCallback(s.App.StakeibcKeeper, s.Ctx, tc.Response.CallbackArgs, tc.Response.Query) + }) +} + +// Verify that if the amount returned by the ICQ response is less than the min_swap_amount, no transfer happens +func (s *KeeperTestSuite) TestWithdrawalRewardBalanceCallback_SuccessfulNoTransfer() { + tc := s.SetupWithdrawalRewardBalanceCallbackTestCase() + + // Set min swap amount to be greater than the transfer amount + route := tc.TradeRoute + route.TradeConfig.MinSwapAmount = tc.Balance.Add(sdkmath.OneInt()) + s.App.StakeibcKeeper.SetTradeRoute(s.Ctx, route) + + // ICA inside of TransferRewardTokensHostToTrade should not actually execute because of min_swap_amount + s.CheckICATxNotSubmitted(tc.PortID, tc.ChannelID, func() error { + return keeper.WithdrawalRewardBalanceCallback(s.App.StakeibcKeeper, s.Ctx, tc.Response.CallbackArgs, tc.Response.Query) + }) +} + +func (s *KeeperTestSuite) TestWithdrawalRewardBalanceCallback_ZeroBalance() { + tc := s.SetupWithdrawalRewardBalanceCallbackTestCase() + + // Replace the query response with a coin that has a zero amount + tc.Response.CallbackArgs = s.CreateBalanceQueryResponse(0, tc.TradeRoute.RewardDenomOnHostZone) + + // Confirm the transfer ICA was never sent + s.CheckICATxNotSubmitted(tc.PortID, tc.ChannelID, func() error { + return keeper.WithdrawalRewardBalanceCallback(s.App.StakeibcKeeper, s.Ctx, tc.Response.CallbackArgs, tc.Response.Query) + }) +} + +func (s *KeeperTestSuite) TestWithdrawalRewardBalanceCallback_InvalidArgs() { + tc := s.SetupWithdrawalRewardBalanceCallbackTestCase() + + // Submit callback with invalid callback args (so that it can't unmarshal into a coin) + invalidArgs := []byte("random bytes") + + err := keeper.WithdrawalRewardBalanceCallback(s.App.StakeibcKeeper, s.Ctx, invalidArgs, tc.Response.Query) + s.Require().ErrorContains(err, "unable to determine balance from query response") +} + +func (s *KeeperTestSuite) TestWithdrawalRewardBalanceCallback_InvalidCallbackData() { + tc := s.SetupWithdrawalRewardBalanceCallbackTestCase() + + // Update the callback data so that it can't be successfully unmarshalled + invalidQuery := tc.Response.Query + invalidQuery.CallbackData = []byte("random bytes") + + err := keeper.WithdrawalRewardBalanceCallback(s.App.StakeibcKeeper, s.Ctx, tc.Response.CallbackArgs, invalidQuery) + s.Require().ErrorContains(err, "unable to unmarshal trade reward balance callback data") +} + +func (s *KeeperTestSuite) TestWithdrawalRewardBalanceCallback_TradeRouteNotFound() { + tc := s.SetupWithdrawalRewardBalanceCallbackTestCase() + + // Update the callback data so that it keys to a trade route that doesn't exist + invalidCallbackDataBz, _ := proto.Marshal(&types.TradeRouteCallback{ + RewardDenom: RewardDenom, + HostDenom: "different-host-denom", + }) + invalidQuery := tc.Response.Query + invalidQuery.CallbackData = invalidCallbackDataBz + + err := keeper.WithdrawalRewardBalanceCallback(s.App.StakeibcKeeper, s.Ctx, tc.Response.CallbackArgs, invalidQuery) + s.Require().ErrorContains(err, "trade route not found") +} + +func (s *KeeperTestSuite) TestWithdrawalRewardBalanceCallback_FailedSubmitTx() { + tc := s.SetupWithdrawalRewardBalanceCallbackTestCase() + + // Remove connectionId from host ICAAccount on TradeRoute so the ICA tx fails + invalidRoute := tc.TradeRoute + invalidRoute.HostAccount.ConnectionId = "bad-connection" + s.App.StakeibcKeeper.SetTradeRoute(s.Ctx, invalidRoute) + + err := keeper.WithdrawalRewardBalanceCallback(s.App.StakeibcKeeper, s.Ctx, tc.Response.CallbackArgs, tc.Response.Query) + s.Require().ErrorContains(err, "Failed to submit ICA tx") +} diff --git a/x/stakeibc/keeper/keeper.go b/x/stakeibc/keeper/keeper.go index c0c6e4bfc..036bf934c 100644 --- a/x/stakeibc/keeper/keeper.go +++ b/x/stakeibc/keeper/keeper.go @@ -5,27 +5,25 @@ import ( errorsmod "cosmossdk.io/errors" "github.com/cometbft/cometbft/libs/log" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - "github.com/spf13/cast" - "github.com/cosmos/cosmos-sdk/codec" + storetypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" - - icqkeeper "github.com/Stride-Labs/stride/v16/x/interchainquery/keeper" - "github.com/Stride-Labs/stride/v16/x/stakeibc/types" - paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" icacontrollerkeeper "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/controller/keeper" + clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types" + connectiontypes "github.com/cosmos/ibc-go/v7/modules/core/03-connection/types" ibckeeper "github.com/cosmos/ibc-go/v7/modules/core/keeper" ibctmtypes "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint" - - storetypes "github.com/cosmos/cosmos-sdk/store/types" + "github.com/spf13/cast" epochstypes "github.com/Stride-Labs/stride/v16/x/epochs/types" icacallbackskeeper "github.com/Stride-Labs/stride/v16/x/icacallbacks/keeper" + icqkeeper "github.com/Stride-Labs/stride/v16/x/interchainquery/keeper" recordsmodulekeeper "github.com/Stride-Labs/stride/v16/x/records/keeper" + "github.com/Stride-Labs/stride/v16/x/stakeibc/types" ) type ( @@ -35,6 +33,7 @@ type ( storeKey storetypes.StoreKey memKey storetypes.StoreKey paramstore paramtypes.Subspace + authority string ICAControllerKeeper icacontrollerkeeper.Keeper IBCKeeper ibckeeper.Keeper bankKeeper bankkeeper.Keeper @@ -55,6 +54,7 @@ func NewKeeper( storeKey, memKey storetypes.StoreKey, ps paramtypes.Subspace, + authority string, accountKeeper types.AccountKeeper, bankKeeper bankkeeper.Keeper, icacontrollerkeeper icacontrollerkeeper.Keeper, @@ -77,6 +77,7 @@ func NewKeeper( storeKey: storeKey, memKey: memKey, paramstore: ps, + authority: authority, AccountKeeper: accountKeeper, bankKeeper: bankKeeper, ICAControllerKeeper: icacontrollerkeeper, @@ -106,24 +107,24 @@ func (k *Keeper) SetHooks(gh types.StakeIBCHooks) *Keeper { return k } -func (k Keeper) GetChainID(ctx sdk.Context, connectionID string) (string, error) { - conn, found := k.IBCKeeper.ConnectionKeeper.GetConnection(ctx, connectionID) +// GetAuthority returns the x/stakeibc module's authority. +func (k Keeper) GetAuthority() string { + return k.authority +} + +// Lookup a chain ID from a connection ID by looking up the client state +func (k Keeper) GetChainIdFromConnectionId(ctx sdk.Context, connectionID string) (string, error) { + connection, found := k.IBCKeeper.ConnectionKeeper.GetConnection(ctx, connectionID) if !found { - errMsg := fmt.Sprintf("invalid connection id, %s not found", connectionID) - k.Logger(ctx).Error(errMsg) - return "", fmt.Errorf(errMsg) + return "", errorsmod.Wrapf(connectiontypes.ErrConnectionNotFound, "connection %s not found", connectionID) } - clientState, found := k.IBCKeeper.ClientKeeper.GetClientState(ctx, conn.ClientId) + clientState, found := k.IBCKeeper.ClientKeeper.GetClientState(ctx, connection.ClientId) if !found { - errMsg := fmt.Sprintf("client id %s not found for connection %s", conn.ClientId, connectionID) - k.Logger(ctx).Error(errMsg) - return "", fmt.Errorf(errMsg) + return "", errorsmod.Wrapf(clienttypes.ErrClientNotFound, "client %s not found", connection.ClientId) } client, ok := clientState.(*ibctmtypes.ClientState) if !ok { - errMsg := fmt.Sprintf("invalid client state for client %s on connection %s", conn.ClientId, connectionID) - k.Logger(ctx).Error(errMsg) - return "", fmt.Errorf(errMsg) + return "", types.ErrClientStateNotTendermint } return client.ChainId, nil @@ -152,16 +153,15 @@ func (k Keeper) GetCounterpartyChainId(ctx sdk.Context, connectionID string) (st return counterpartyClient.ChainId, nil } -func (k Keeper) GetConnectionId(ctx sdk.Context, portId string) (string, error) { +// Searches all interchain accounts and finds the connection ID that corresponds with a given port ID +func (k Keeper) GetConnectionIdFromICAPortId(ctx sdk.Context, portId string) (connectionId string, found bool) { icas := k.ICAControllerKeeper.GetAllInterchainAccounts(ctx) for _, ica := range icas { if ica.PortId == portId { - return ica.ConnectionId, nil + return ica.ConnectionId, true } } - errMsg := fmt.Sprintf("portId %s has no associated connectionId", portId) - k.Logger(ctx).Error(errMsg) - return "", fmt.Errorf(errMsg) + return "", false } // helper to get what share of the curr epoch we're through diff --git a/x/stakeibc/keeper/keeper_test.go b/x/stakeibc/keeper/keeper_test.go index c5088e06a..b615b9fe6 100644 --- a/x/stakeibc/keeper/keeper_test.go +++ b/x/stakeibc/keeper/keeper_test.go @@ -2,16 +2,22 @@ package keeper_test import ( "testing" + "time" sdk "github.com/cosmos/cosmos-sdk/types" + ibctesting "github.com/cosmos/ibc-go/v7/testing" "github.com/stretchr/testify/suite" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + "github.com/Stride-Labs/stride/v16/app/apptesting" + icqtypes "github.com/Stride-Labs/stride/v16/x/interchainquery/types" "github.com/Stride-Labs/stride/v16/x/stakeibc/keeper" "github.com/Stride-Labs/stride/v16/x/stakeibc/types" ) -const ( +var ( Atom = "uatom" StAtom = "stuatom" IbcAtom = "ibc/uatom" @@ -25,11 +31,26 @@ const ( OsmoPrefix = "osmo" OsmoChainId = "OSMO" - ValAddress = "cosmosvaloper1uk4ze0x4nvh4fk0xm4jdud58eqn4yxhrdt795p" - HostICAAddress = "cosmos1gcx4yeplccq9nk6awzmm0gq8jf7yet80qj70tkwy0mz7pg87nepswn2dj8" - LSMTokenBaseDenom = ValAddress + "/32" + HostDenom = "udenom" + RewardDenom = "ureward" + + ValAddress = "cosmosvaloper1uk4ze0x4nvh4fk0xm4jdud58eqn4yxhrdt795p" + StrideICAAddress = "stride1gcx4yeplccq9nk6awzmm0gq8jf7yet80qj70tkwy0mz7pg87nepsen0l38" + HostICAAddress = "cosmos1gcx4yeplccq9nk6awzmm0gq8jf7yet80qj70tkwy0mz7pg87nepswn2dj8" + LSMTokenBaseDenom = ValAddress + "/32" + + DepositAddress = "deposit" + CommunityPoolStakeHoldingAddress = "staking-holding" + CommunityPoolRedeemHoldingAddress = "redeem-holding" + + Authority = authtypes.NewModuleAddress(govtypes.ModuleName).String() ) +type ICQCallbackArgs struct { + Query icqtypes.Query + CallbackArgs []byte +} + type KeeperTestSuite struct { apptesting.AppTestHelper } @@ -51,6 +72,58 @@ func TestKeeperTestSuite(t *testing.T) { suite.Run(t, new(KeeperTestSuite)) } +// Helper function to get a host zone and confirm it was found +func (s *KeeperTestSuite) MustGetHostZone(chainId string) types.HostZone { + hostZone, found := s.App.StakeibcKeeper.GetHostZone(s.Ctx, chainId) + s.Require().True(found, "host zone should have been found") + return hostZone +} + +// Helper function to create an epoch tracker that dictates the timeout +func (s *KeeperTestSuite) CreateEpochForICATimeout(epochType string, timeoutDuration time.Duration) { + epochEndTime := uint64(s.Ctx.BlockTime().Add(timeoutDuration).UnixNano()) + epochTracker := types.EpochTracker{ + EpochIdentifier: epochType, + NextEpochStartTime: epochEndTime, + Duration: uint64(timeoutDuration), + } + s.App.StakeibcKeeper.SetEpochTracker(s.Ctx, epochTracker) +} + +// Validates the query object stored after an ICQ submission, using some default testing +// values (e.g. HostChainId, stakeibc module name, etc.), and returning the query +// NOTE: This assumes there was only one submission and grabs the first query from the store +func (s *KeeperTestSuite) ValidateQuerySubmission( + queryType string, + queryData []byte, + callbackId string, + timeoutDuration time.Duration, + timeoutPolicy icqtypes.TimeoutPolicy, +) icqtypes.Query { + // Check that there's only one query + queries := s.App.InterchainqueryKeeper.AllQueries(s.Ctx) + s.Require().Len(queries, 1, "there should have been 1 query submitted") + query := queries[0] + + // Validate the chainId and connectionId + s.Require().Equal(HostChainId, query.ChainId, "query chain ID") + s.Require().Equal(ibctesting.FirstConnectionID, query.ConnectionId, "query connection ID") + s.Require().Equal(types.ModuleName, query.CallbackModule, "query module") + + // Validate the query type and request data + s.Require().Equal(queryType, query.QueryType, "query type") + s.Require().Equal(string(queryData), string(query.RequestData), "query request data") + s.Require().Equal(callbackId, query.CallbackId, "query callback ID") + + // Validate the query timeout + expectedTimeoutTimestamp := s.Ctx.BlockTime().Add(timeoutDuration).UnixNano() + s.Require().Equal(timeoutDuration, query.TimeoutDuration, "query timeout duration") + s.Require().Equal(expectedTimeoutTimestamp, int64(query.TimeoutTimestamp), "query timeout timestamp") + s.Require().Equal(icqtypes.TimeoutPolicy_REJECT_QUERY_RESPONSE, query.TimeoutPolicy, "query timeout policy") + + return query +} + func (s *KeeperTestSuite) TestIsRedemptionRateWithinSafetyBounds() { params := s.App.StakeibcKeeper.GetParams(s.Ctx) params.DefaultMinRedemptionRateThreshold = 75 diff --git a/x/stakeibc/keeper/lsm.go b/x/stakeibc/keeper/lsm.go index 0fc834c9d..a4f10206a 100644 --- a/x/stakeibc/keeper/lsm.go +++ b/x/stakeibc/keeper/lsm.go @@ -339,7 +339,7 @@ func (k Keeper) DetokenizeAllLSMDeposits(ctx sdk.Context) { // Submit detokenization ICAs for each active host zone for _, hostZone := range k.GetAllActiveHostZone(ctx) { // Get the host zone's delegation ICA portID - delegationICAOwner := types.FormatICAAccountOwner(hostZone.ChainId, types.ICAAccountType_DELEGATION) + delegationICAOwner := types.FormatHostZoneICAOwner(hostZone.ChainId, types.ICAAccountType_DELEGATION) delegationICAPortID, err := icatypes.NewControllerPortID(delegationICAOwner) if err != nil { k.Logger(ctx).Error(fmt.Sprintf("Unable to get delegation port ID for %s: %s", hostZone.ChainId, err)) diff --git a/x/stakeibc/keeper/lsm_test.go b/x/stakeibc/keeper/lsm_test.go index dafc943fa..9d1f7a5ac 100644 --- a/x/stakeibc/keeper/lsm_test.go +++ b/x/stakeibc/keeper/lsm_test.go @@ -582,7 +582,7 @@ func (s *KeeperTestSuite) TestTransferAllLSMDeposits() { func (s *KeeperTestSuite) TestDetokenizeLSMDeposit() { // Create the delegation ICA - owner := types.FormatICAAccountOwner(HostChainId, types.ICAAccountType_DELEGATION) + owner := types.FormatHostZoneICAOwner(HostChainId, types.ICAAccountType_DELEGATION) s.CreateICAChannel(owner) portId, err := icatypes.NewControllerPortID(owner) s.Require().NoError(err, "no error expected when formatting portId") @@ -649,7 +649,7 @@ func (s *KeeperTestSuite) TestDetokenizeLSMDeposit() { func (s *KeeperTestSuite) TestDetokenizeAllLSMDeposits() { // Create an open delegation ICA channel - owner := types.FormatICAAccountOwner(HostChainId, types.ICAAccountType_DELEGATION) + owner := types.FormatHostZoneICAOwner(HostChainId, types.ICAAccountType_DELEGATION) s.CreateICAChannel(owner) portId, err := icatypes.NewControllerPortID(owner) s.Require().NoError(err, "no error expected when formatting portId") diff --git a/x/stakeibc/keeper/msg_server_claim_accrued_staking_rewards_on_host_test.go b/x/stakeibc/keeper/msg_server_claim_accrued_staking_rewards_on_host_test.go index 94afe7b1e..f4aa7ac7d 100644 --- a/x/stakeibc/keeper/msg_server_claim_accrued_staking_rewards_on_host_test.go +++ b/x/stakeibc/keeper/msg_server_claim_accrued_staking_rewards_on_host_test.go @@ -16,7 +16,7 @@ const numZeroDelegations = 37 func (s *KeeperTestSuite) ClaimAccruedStakingRewardsOnHost() { // Create a delegation ICA channel for the ICA submission - owner := types.FormatICAAccountOwner(HostChainId, types.ICAAccountType_DELEGATION) + owner := types.FormatHostZoneICAOwner(HostChainId, types.ICAAccountType_DELEGATION) channelId, portId := s.CreateICAChannel(owner) // Create validators diff --git a/x/stakeibc/keeper/msg_server_create_trade_route.go b/x/stakeibc/keeper/msg_server_create_trade_route.go new file mode 100644 index 000000000..18ff51477 --- /dev/null +++ b/x/stakeibc/keeper/msg_server_create_trade_route.go @@ -0,0 +1,210 @@ +package keeper + +import ( + "context" + + sdkmath "cosmossdk.io/math" + + "github.com/Stride-Labs/stride/v16/x/stakeibc/types" + + errorsmod "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + icatypes "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/types" + connectiontypes "github.com/cosmos/ibc-go/v7/modules/core/03-connection/types" +) + +var ( + DefaultMaxAllowedSwapLossRate = "0.05" + DefaultMaxSwapAmount = sdkmath.NewIntWithDecimal(10, 24) // 10e24 +) + +// Gov tx to register a trade route that swaps reward tokens for a different denom +// +// Example proposal: +// +// { +// "title": "Create a new trade route for host chain X", +// "metadata": "Create a new trade route for host chain X", +// "summary": "Create a new trade route for host chain X", +// "messages":[ +// { +// "@type": "/stride.stakeibc.MsgCreateTradeRoute", +// "authority": "stride10d07y265gmmuvt4z0w9aw880jnsr700jefnezl", +// +// "stride_to_host_connection_id": "connection-0", +// "stride_to_reward_connection_id": "connection-1", +// "stride_to_trade_connection_id": "connection-2", +// +// "host_to_reward_transfer_channel_id": "channel-0", +// "reward_to_trade_transfer_channel_id": "channel-1", +// "trade_to_host_transfer_channel_id": "channel-2", +// +// "reward_denom_on_host": "ibc/rewardTokenXXX", +// "reward_denom_on_reward": "rewardToken", +// "reward_denom_on_trade": "ibc/rewardTokenYYY", +// "host_denom_on_trade": "ibc/hostTokenZZZ", +// "host_denom_on_host": "hostToken", +// +// "pool_id": 1, +// "max_allowed_swap_loss_rate": "0.05" +// "min_swap_amount": "10000000", +// "max_swap_amount": "1000000000" +// } +// ], +// "deposit": "2000000000ustrd" +// } +// +// >>> strided tx gov submit-proposal {proposal_file.json} --from wallet +func (ms msgServer) CreateTradeRoute(goCtx context.Context, msg *types.MsgCreateTradeRoute) (*types.MsgCreateTradeRouteResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + if ms.authority != msg.Authority { + return nil, errorsmod.Wrapf(govtypes.ErrInvalidSigner, "invalid authority; expected %s, got %s", ms.authority, msg.Authority) + } + + // Validate trade route does not already exist for this denom + _, found := ms.Keeper.GetTradeRoute(ctx, msg.RewardDenomOnReward, msg.HostDenomOnHost) + if found { + return nil, errorsmod.Wrapf(types.ErrTradeRouteAlreadyExists, + "trade route already exists for rewardDenom %s, hostDenom %s", msg.RewardDenomOnReward, msg.HostDenomOnHost) + } + + // Confirm the host chain exists and the withdrawal address has been initialized + hostZone, err := ms.Keeper.GetActiveHostZone(ctx, msg.HostChainId) + if err != nil { + return nil, err + } + if hostZone.WithdrawalIcaAddress == "" { + return nil, errorsmod.Wrapf(types.ErrICAAccountNotFound, "withdrawal account not initialized on host zone") + } + + // Register the new ICA accounts + tradeRouteId := types.GetTradeRouteId(msg.RewardDenomOnReward, msg.HostDenomOnHost) + hostICA := types.ICAAccount{ + ChainId: msg.HostChainId, + Type: types.ICAAccountType_WITHDRAWAL, + ConnectionId: hostZone.ConnectionId, + Address: hostZone.WithdrawalIcaAddress, + } + + unwindConnectionId := msg.StrideToRewardConnectionId + unwindICAType := types.ICAAccountType_CONVERTER_UNWIND + unwindICA, err := ms.Keeper.RegisterTradeRouteICAAccount(ctx, tradeRouteId, unwindConnectionId, unwindICAType) + if err != nil { + return nil, errorsmod.Wrapf(err, "unable to register the unwind ICA account") + } + + tradeConnectionId := msg.StrideToTradeConnectionId + tradeICAType := types.ICAAccountType_CONVERTER_TRADE + tradeICA, err := ms.Keeper.RegisterTradeRouteICAAccount(ctx, tradeRouteId, tradeConnectionId, tradeICAType) + if err != nil { + return nil, errorsmod.Wrapf(err, "unable to register the trade ICA account") + } + + // If a max allowed swap loss is not provided, use the default + maxAllowedSwapLossRate := msg.MaxAllowedSwapLossRate + if maxAllowedSwapLossRate == "" { + maxAllowedSwapLossRate = DefaultMaxAllowedSwapLossRate + } + maxSwapAmount := msg.MaxSwapAmount + if maxSwapAmount.IsZero() { + maxSwapAmount = DefaultMaxSwapAmount + } + + // Create the trade config to specify parameters needed for the swap + tradeConfig := types.TradeConfig{ + PoolId: msg.PoolId, + SwapPrice: sdk.ZeroDec(), // this should only ever be set by ICQ so initialize to blank + PriceUpdateTimestamp: 0, + + MaxAllowedSwapLossRate: sdk.MustNewDecFromStr(maxAllowedSwapLossRate), + MinSwapAmount: msg.MinSwapAmount, + MaxSwapAmount: maxSwapAmount, + } + + // Finally build and store the main trade route + tradeRoute := types.TradeRoute{ + RewardDenomOnHostZone: msg.RewardDenomOnHost, + RewardDenomOnRewardZone: msg.RewardDenomOnReward, + RewardDenomOnTradeZone: msg.RewardDenomOnTrade, + HostDenomOnTradeZone: msg.HostDenomOnTrade, + HostDenomOnHostZone: msg.HostDenomOnHost, + + HostAccount: hostICA, + RewardAccount: unwindICA, + TradeAccount: tradeICA, + + HostToRewardChannelId: msg.HostToRewardTransferChannelId, + RewardToTradeChannelId: msg.RewardToTradeTransferChannelId, + TradeToHostChannelId: msg.TradeToHostTransferChannelId, + + TradeConfig: tradeConfig, + } + + ms.Keeper.SetTradeRoute(ctx, tradeRoute) + + return &types.MsgCreateTradeRouteResponse{}, nil +} + +// Registers a new TradeRoute ICAAccount, given the type +// Stores down the connection and chainId now, and the address upon callback +func (k Keeper) RegisterTradeRouteICAAccount( + ctx sdk.Context, + tradeRouteId string, + connectionId string, + icaAccountType types.ICAAccountType, +) (account types.ICAAccount, err error) { + // Get the chain ID and counterparty connection-id from the connection ID on Stride + chainId, err := k.GetChainIdFromConnectionId(ctx, connectionId) + if err != nil { + return account, err + } + connection, found := k.IBCKeeper.ConnectionKeeper.GetConnection(ctx, connectionId) + if !found { + return account, errorsmod.Wrap(connectiontypes.ErrConnectionNotFound, connectionId) + } + counterpartyConnectionId := connection.Counterparty.ConnectionId + + // Build the appVersion, owner, and portId needed for registration + appVersion := string(icatypes.ModuleCdc.MustMarshalJSON(&icatypes.Metadata{ + Version: icatypes.Version, + ControllerConnectionId: connectionId, + HostConnectionId: counterpartyConnectionId, + Encoding: icatypes.EncodingProtobuf, + TxType: icatypes.TxTypeSDKMultiMsg, + })) + owner := types.FormatTradeRouteICAOwnerFromRouteId(chainId, tradeRouteId, icaAccountType) + portID, err := icatypes.NewControllerPortID(owner) + if err != nil { + return account, err + } + + // Create the associate ICAAccount object + account = types.ICAAccount{ + ChainId: chainId, + Type: icaAccountType, + ConnectionId: connectionId, + } + + // Check if an ICA account has already been created + // (in the event that this trade route was removed and then added back) + // If so, there's no need to register a new ICA + _, channelFound := k.ICAControllerKeeper.GetOpenActiveChannel(ctx, connectionId, portID) + icaAddress, icaFound := k.ICAControllerKeeper.GetInterchainAccountAddress(ctx, connectionId, portID) + if channelFound && icaFound { + account = types.ICAAccount{ + ChainId: chainId, + Type: icaAccountType, + ConnectionId: connectionId, + Address: icaAddress, + } + return account, nil + } + + // Otherwise, if there's no account already, register a new one + if err := k.ICAControllerKeeper.RegisterInterchainAccount(ctx, connectionId, owner, appVersion); err != nil { + return account, err + } + + return account, nil +} diff --git a/x/stakeibc/keeper/msg_server_create_trade_route_test.go b/x/stakeibc/keeper/msg_server_create_trade_route_test.go new file mode 100644 index 000000000..3f28e0292 --- /dev/null +++ b/x/stakeibc/keeper/msg_server_create_trade_route_test.go @@ -0,0 +1,229 @@ +package keeper_test + +import ( + sdkmath "cosmossdk.io/math" + + sdk "github.com/cosmos/cosmos-sdk/types" + icatypes "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/types" + + "github.com/Stride-Labs/stride/v16/x/stakeibc/keeper" + "github.com/Stride-Labs/stride/v16/x/stakeibc/types" +) + +func (s *KeeperTestSuite) SetupTestCreateTradeRoute() (msg types.MsgCreateTradeRoute, expectedTradeRoute types.TradeRoute) { + rewardChainId := "reward-0" + tradeChainId := "trade-0" + + hostConnectionId := "connection-0" + rewardConnectionId := "connection-1" + tradeConnectionId := "connection-2" + + hostToRewardChannelId := "channel-100" + rewardToTradeChannelId := "channel-200" + tradeToHostChannelId := "channel-300" + + rewardDenomOnHost := "ibc/reward-on-host" + rewardDenomOnReward := RewardDenom + rewardDenomOnTrade := "ibc/reward-on-trade" + hostDenomOnTrade := "ibc/host-on-trade" + hostDenomOnHost := HostDenom + + withdrawalAddress := "withdrawal-address" + unwindAddress := "unwind-address" + + poolId := uint64(100) + maxAllowedSwapLossRate := "0.05" + minSwapAmount := sdkmath.NewInt(100) + maxSwapAmount := sdkmath.NewInt(1_000) + + // Mock out connections for the reward an trade chain so that an ICA registration can be submitted + s.MockClientAndConnection(rewardChainId, "07-tendermint-0", rewardConnectionId) + s.MockClientAndConnection(tradeChainId, "07-tendermint-1", tradeConnectionId) + + // Register an exisiting ICA account for the unwind ICA to test that + // existing accounts are re-used + owner := types.FormatTradeRouteICAOwner(rewardChainId, RewardDenom, HostDenom, types.ICAAccountType_CONVERTER_UNWIND) + s.MockICAChannel(rewardConnectionId, "channel-0", owner, unwindAddress) + + // Create a host zone with an exisiting withdrawal address + hostZone := types.HostZone{ + ChainId: HostChainId, + ConnectionId: hostConnectionId, + WithdrawalIcaAddress: withdrawalAddress, + } + s.App.StakeibcKeeper.SetHostZone(s.Ctx, hostZone) + + // Define a valid message given the parameters above + msg = types.MsgCreateTradeRoute{ + Authority: Authority, + HostChainId: HostChainId, + + StrideToRewardConnectionId: rewardConnectionId, + StrideToTradeConnectionId: tradeConnectionId, + + HostToRewardTransferChannelId: hostToRewardChannelId, + RewardToTradeTransferChannelId: rewardToTradeChannelId, + TradeToHostTransferChannelId: tradeToHostChannelId, + + RewardDenomOnHost: rewardDenomOnHost, + RewardDenomOnReward: rewardDenomOnReward, + RewardDenomOnTrade: rewardDenomOnTrade, + HostDenomOnTrade: hostDenomOnTrade, + HostDenomOnHost: hostDenomOnHost, + + PoolId: poolId, + MaxAllowedSwapLossRate: maxAllowedSwapLossRate, + MinSwapAmount: minSwapAmount, + MaxSwapAmount: maxSwapAmount, + } + + // Build out the expected trade route given the above + expectedTradeRoute = types.TradeRoute{ + RewardDenomOnHostZone: rewardDenomOnHost, + RewardDenomOnRewardZone: rewardDenomOnReward, + RewardDenomOnTradeZone: rewardDenomOnTrade, + HostDenomOnTradeZone: hostDenomOnTrade, + HostDenomOnHostZone: hostDenomOnHost, + + HostAccount: types.ICAAccount{ + ChainId: HostChainId, + Type: types.ICAAccountType_WITHDRAWAL, + ConnectionId: hostConnectionId, + Address: withdrawalAddress, + }, + RewardAccount: types.ICAAccount{ + ChainId: rewardChainId, + Type: types.ICAAccountType_CONVERTER_UNWIND, + ConnectionId: rewardConnectionId, + Address: unwindAddress, + }, + TradeAccount: types.ICAAccount{ + ChainId: tradeChainId, + Type: types.ICAAccountType_CONVERTER_TRADE, + ConnectionId: tradeConnectionId, + }, + + HostToRewardChannelId: hostToRewardChannelId, + RewardToTradeChannelId: rewardToTradeChannelId, + TradeToHostChannelId: tradeToHostChannelId, + + TradeConfig: types.TradeConfig{ + PoolId: poolId, + SwapPrice: sdk.ZeroDec(), + PriceUpdateTimestamp: 0, + + MaxAllowedSwapLossRate: sdk.MustNewDecFromStr(maxAllowedSwapLossRate), + MinSwapAmount: minSwapAmount, + MaxSwapAmount: maxSwapAmount, + }, + } + + return msg, expectedTradeRoute +} + +// Helper function to create a trade route and check the created route matched expectations +func (s *KeeperTestSuite) submitCreateTradeRouteAndValidate(msg types.MsgCreateTradeRoute, expectedRoute types.TradeRoute) { + _, err := s.GetMsgServer().CreateTradeRoute(sdk.WrapSDKContext(s.Ctx), &msg) + s.Require().NoError(err, "no error expected when creating trade route") + + actualRoute, found := s.App.StakeibcKeeper.GetTradeRoute(s.Ctx, msg.RewardDenomOnReward, msg.HostDenomOnHost) + s.Require().True(found, "trade route should have been created") + s.Require().Equal(expectedRoute, actualRoute, "trade route") +} + +// Tests a successful trade route creation +func (s *KeeperTestSuite) TestCreateTradeRoute_Success() { + msg, expectedRoute := s.SetupTestCreateTradeRoute() + s.submitCreateTradeRouteAndValidate(msg, expectedRoute) +} + +// Tests creating a trade route that uses the default pool config values +func (s *KeeperTestSuite) TestCreateTradeRoute_Success_DefaultPoolConfig() { + msg, expectedRoute := s.SetupTestCreateTradeRoute() + + // Update the message and remove some trade config parameters + // so that the defaults are used + msg.MaxSwapAmount = sdk.ZeroInt() + msg.MaxAllowedSwapLossRate = "" + + expectedRoute.TradeConfig.MaxAllowedSwapLossRate = sdk.MustNewDecFromStr(keeper.DefaultMaxAllowedSwapLossRate) + expectedRoute.TradeConfig.MaxSwapAmount = keeper.DefaultMaxSwapAmount + + s.submitCreateTradeRouteAndValidate(msg, expectedRoute) +} + +// Tests trying to create a route from an invalid authority +func (s *KeeperTestSuite) TestCreateTradeRoute_Failure_Authority() { + msg, _ := s.SetupTestCreateTradeRoute() + + msg.Authority = "not-gov-address" + + _, err := s.GetMsgServer().CreateTradeRoute(sdk.WrapSDKContext(s.Ctx), &msg) + s.Require().ErrorContains(err, "invalid authority") +} + +// Tests creating a duplicate trade route +func (s *KeeperTestSuite) TestCreateTradeRoute_Failure_DuplicateTradeRoute() { + msg, _ := s.SetupTestCreateTradeRoute() + + // Store down a trade route so the tx hits a duplicate trade route error + s.App.StakeibcKeeper.SetTradeRoute(s.Ctx, types.TradeRoute{ + RewardDenomOnRewardZone: RewardDenom, + HostDenomOnHostZone: HostDenom, + }) + + _, err := s.GetMsgServer().CreateTradeRoute(sdk.WrapSDKContext(s.Ctx), &msg) + s.Require().ErrorContains(err, "Trade route already exists") +} + +// Tests creating a trade route when the host zone or withdrawal address does not exist +func (s *KeeperTestSuite) TestCreateTradeRoute_Failure_HostZoneNotRegistered() { + msg, _ := s.SetupTestCreateTradeRoute() + + // Remove the host zone withdrawal address and confirm it fails + invalidHostZone := s.MustGetHostZone(HostChainId) + invalidHostZone.WithdrawalIcaAddress = "" + s.App.StakeibcKeeper.SetHostZone(s.Ctx, invalidHostZone) + + _, err := s.GetMsgServer().CreateTradeRoute(sdk.WrapSDKContext(s.Ctx), &msg) + s.Require().ErrorContains(err, "withdrawal account not initialized on host zone") + + // Remove the host zone completely and check that that also fails + s.App.StakeibcKeeper.RemoveHostZone(s.Ctx, HostChainId) + + _, err = s.GetMsgServer().CreateTradeRoute(sdk.WrapSDKContext(s.Ctx), &msg) + s.Require().ErrorContains(err, "host zone not found") +} + +// Tests creating a trade route where the ICA channels cannot be created +// because the ICA connections do not exist +func (s *KeeperTestSuite) TestCreateTradeRoute_Failure_ConnectionNotFound() { + // Test with non-existent reward connection + msg, _ := s.SetupTestCreateTradeRoute() + msg.StrideToRewardConnectionId = "connection-X" + + // Remove the host zone completely and check that that also fails + _, err := s.GetMsgServer().CreateTradeRoute(sdk.WrapSDKContext(s.Ctx), &msg) + s.Require().ErrorContains(err, "unable to register the unwind ICA account: connection connection-X not found") + + // Setup again, but this time use a non-existent trade connection + msg, _ = s.SetupTestCreateTradeRoute() + msg.StrideToTradeConnectionId = "connection-Y" + + _, err = s.GetMsgServer().CreateTradeRoute(sdk.WrapSDKContext(s.Ctx), &msg) + s.Require().ErrorContains(err, "unable to register the trade ICA account: connection connection-Y not found") +} + +// Tests creating a trade route where the ICA registration step fails +func (s *KeeperTestSuite) TestCreateTradeRoute_Failure_UnableToRegisterICA() { + msg, expectedRoute := s.SetupTestCreateTradeRoute() + + // Disable ICA middleware for the trade channel so the ICA fails + tradeAccount := expectedRoute.TradeAccount + tradeOwner := types.FormatTradeRouteICAOwner(tradeAccount.ChainId, RewardDenom, HostDenom, types.ICAAccountType_CONVERTER_TRADE) + tradePortId, _ := icatypes.NewControllerPortID(tradeOwner) + s.App.ICAControllerKeeper.SetMiddlewareDisabled(s.Ctx, tradePortId, tradeAccount.ConnectionId) + + _, err := s.GetMsgServer().CreateTradeRoute(sdk.WrapSDKContext(s.Ctx), &msg) + s.Require().ErrorContains(err, "unable to register the trade ICA account") +} diff --git a/x/stakeibc/keeper/msg_server_delete_trade_route.go b/x/stakeibc/keeper/msg_server_delete_trade_route.go new file mode 100644 index 000000000..9a899c689 --- /dev/null +++ b/x/stakeibc/keeper/msg_server_delete_trade_route.go @@ -0,0 +1,49 @@ +package keeper + +import ( + "context" + + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + + "github.com/Stride-Labs/stride/v16/x/stakeibc/types" + + errorsmod "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// Gov tx to remove a trade route +// +// Example proposal: +// +// { +// "title": "Remove a new trade route for host chain X", +// "metadata": "Remove a new trade route for host chain X", +// "summary": "Remove a new trade route for host chain X", +// "messages":[ +// { +// "@type": "/stride.stakeibc.MsgDeleteTradeRoute", +// "authority": "stride10d07y265gmmuvt4z0w9aw880jnsr700jefnezl", +// "reward_denom": "rewardToken", +// "host_denom": "hostToken +// } +// ], +// "deposit": "2000000000ustrd" +// } +// +// >>> strided tx gov submit-proposal {proposal_file.json} --from wallet +func (ms msgServer) DeleteTradeRoute(goCtx context.Context, msg *types.MsgDeleteTradeRoute) (*types.MsgDeleteTradeRouteResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + if ms.authority != msg.Authority { + return nil, errorsmod.Wrapf(govtypes.ErrInvalidSigner, "invalid authority; expected %s, got %s", ms.authority, msg.Authority) + } + + _, found := ms.Keeper.GetTradeRoute(ctx, msg.RewardDenom, msg.HostDenom) + if !found { + return nil, errorsmod.Wrapf(types.ErrTradeRouteNotFound, + "no trade route for rewardDenom %s and hostDenom %s", msg.RewardDenom, msg.HostDenom) + } + + ms.Keeper.RemoveTradeRoute(ctx, msg.RewardDenom, msg.HostDenom) + + return &types.MsgDeleteTradeRouteResponse{}, nil +} diff --git a/x/stakeibc/keeper/msg_server_delete_trade_route_test.go b/x/stakeibc/keeper/msg_server_delete_trade_route_test.go new file mode 100644 index 000000000..7b7c5cecc --- /dev/null +++ b/x/stakeibc/keeper/msg_server_delete_trade_route_test.go @@ -0,0 +1,44 @@ +package keeper_test + +import ( + "github.com/Stride-Labs/stride/v16/x/stakeibc/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func (s *KeeperTestSuite) TestDeleteTradeRoute() { + initialRoute := types.TradeRoute{ + RewardDenomOnRewardZone: RewardDenom, + HostDenomOnHostZone: HostDenom, + } + s.App.StakeibcKeeper.SetTradeRoute(s.Ctx, initialRoute) + + msg := types.MsgDeleteTradeRoute{ + Authority: Authority, + RewardDenom: RewardDenom, + HostDenom: HostDenom, + } + + // Confirm the route is present before attepmting to delete was deleted + _, found := s.App.StakeibcKeeper.GetTradeRoute(s.Ctx, RewardDenom, HostDenom) + s.Require().True(found, "trade route should have been found before delete message") + + // Delete the trade route + _, err := s.GetMsgServer().DeleteTradeRoute(sdk.WrapSDKContext(s.Ctx), &msg) + s.Require().NoError(err, "no error expected when deleting trade route") + + // Confirm it was deleted + _, found = s.App.StakeibcKeeper.GetTradeRoute(s.Ctx, RewardDenom, HostDenom) + s.Require().False(found, "trade route should have been deleted") + + // Attempt to delete it again, it should fail since it doesn't exist + _, err = s.GetMsgServer().DeleteTradeRoute(sdk.WrapSDKContext(s.Ctx), &msg) + s.Require().ErrorContains(err, "trade route not found") + + // Attempt to delete with the wrong authority - it should fail + invalidMsg := msg + invalidMsg.Authority = "not-gov-address" + + _, err = s.GetMsgServer().DeleteTradeRoute(sdk.WrapSDKContext(s.Ctx), &invalidMsg) + s.Require().ErrorContains(err, "invalid authority") +} diff --git a/x/stakeibc/keeper/msg_server_register_host_zone.go b/x/stakeibc/keeper/msg_server_register_host_zone.go index 9d25bbf2b..36d812156 100644 --- a/x/stakeibc/keeper/msg_server_register_host_zone.go +++ b/x/stakeibc/keeper/msg_server_register_host_zone.go @@ -29,7 +29,7 @@ func (k msgServer) RegisterHostZone(goCtx context.Context, msg *types.MsgRegiste counterpartyConnection := connectionEnd.Counterparty // Get chain id from connection - chainId, err := k.GetChainID(ctx, msg.ConnectionId) + chainId, err := k.GetChainIdFromConnectionId(ctx, msg.ConnectionId) if err != nil { errMsg := fmt.Sprintf("unable to obtain chain id from connection %s, err: %s", msg.ConnectionId, err.Error()) k.Logger(ctx).Error(errMsg) @@ -128,7 +128,7 @@ func (k msgServer) RegisterHostZone(goCtx context.Context, msg *types.MsgRegiste // generate delegate account // NOTE: in the future, if we implement proxy governance, we'll need many more delegate accounts - delegateAccount := types.FormatICAAccountOwner(chainId, types.ICAAccountType_DELEGATION) + delegateAccount := types.FormatHostZoneICAOwner(chainId, types.ICAAccountType_DELEGATION) if err := k.ICAControllerKeeper.RegisterInterchainAccount(ctx, zone.ConnectionId, delegateAccount, appVersion); err != nil { errMsg := fmt.Sprintf("unable to register delegation account, err: %s", err.Error()) k.Logger(ctx).Error(errMsg) @@ -136,7 +136,7 @@ func (k msgServer) RegisterHostZone(goCtx context.Context, msg *types.MsgRegiste } // generate fee account - feeAccount := types.FormatICAAccountOwner(chainId, types.ICAAccountType_FEE) + feeAccount := types.FormatHostZoneICAOwner(chainId, types.ICAAccountType_FEE) if err := k.ICAControllerKeeper.RegisterInterchainAccount(ctx, zone.ConnectionId, feeAccount, appVersion); err != nil { errMsg := fmt.Sprintf("unable to register fee account, err: %s", err.Error()) k.Logger(ctx).Error(errMsg) @@ -144,7 +144,7 @@ func (k msgServer) RegisterHostZone(goCtx context.Context, msg *types.MsgRegiste } // generate withdrawal account - withdrawalAccount := types.FormatICAAccountOwner(chainId, types.ICAAccountType_WITHDRAWAL) + withdrawalAccount := types.FormatHostZoneICAOwner(chainId, types.ICAAccountType_WITHDRAWAL) if err := k.ICAControllerKeeper.RegisterInterchainAccount(ctx, zone.ConnectionId, withdrawalAccount, appVersion); err != nil { errMsg := fmt.Sprintf("unable to register withdrawal account, err: %s", err.Error()) k.Logger(ctx).Error(errMsg) @@ -152,7 +152,7 @@ func (k msgServer) RegisterHostZone(goCtx context.Context, msg *types.MsgRegiste } // generate redemption account - redemptionAccount := types.FormatICAAccountOwner(chainId, types.ICAAccountType_REDEMPTION) + redemptionAccount := types.FormatHostZoneICAOwner(chainId, types.ICAAccountType_REDEMPTION) if err := k.ICAControllerKeeper.RegisterInterchainAccount(ctx, zone.ConnectionId, redemptionAccount, appVersion); err != nil { errMsg := fmt.Sprintf("unable to register redemption account, err: %s", err.Error()) k.Logger(ctx).Error(errMsg) @@ -160,13 +160,13 @@ func (k msgServer) RegisterHostZone(goCtx context.Context, msg *types.MsgRegiste } // create community pool deposit account - communityPoolDepositAccount := types.FormatICAAccountOwner(chainId, types.ICAAccountType_COMMUNITY_POOL_DEPOSIT) + communityPoolDepositAccount := types.FormatHostZoneICAOwner(chainId, types.ICAAccountType_COMMUNITY_POOL_DEPOSIT) if err := k.ICAControllerKeeper.RegisterInterchainAccount(ctx, zone.ConnectionId, communityPoolDepositAccount, appVersion); err != nil { return nil, errorsmod.Wrapf(types.ErrFailedToRegisterHostZone, "failed to register community pool deposit ICA") } // create community pool return account - communityPoolReturnAccount := types.FormatICAAccountOwner(chainId, types.ICAAccountType_COMMUNITY_POOL_RETURN) + communityPoolReturnAccount := types.FormatHostZoneICAOwner(chainId, types.ICAAccountType_COMMUNITY_POOL_RETURN) if err := k.ICAControllerKeeper.RegisterInterchainAccount(ctx, zone.ConnectionId, communityPoolReturnAccount, appVersion); err != nil { return nil, errorsmod.Wrapf(types.ErrFailedToRegisterHostZone, "failed to register community pool return ICA") } diff --git a/x/stakeibc/keeper/msg_server_restore_interchain_account.go b/x/stakeibc/keeper/msg_server_restore_interchain_account.go index 4b981a2ee..77736a9e3 100644 --- a/x/stakeibc/keeper/msg_server_restore_interchain_account.go +++ b/x/stakeibc/keeper/msg_server_restore_interchain_account.go @@ -6,8 +6,8 @@ import ( errorsmod "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" icatypes "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/types" + connectiontypes "github.com/cosmos/ibc-go/v7/modules/core/03-connection/types" recordtypes "github.com/Stride-Labs/stride/v16/x/records/types" "github.com/Stride-Labs/stride/v16/x/stakeibc/types" @@ -16,52 +16,43 @@ import ( func (k msgServer) RestoreInterchainAccount(goCtx context.Context, msg *types.MsgRestoreInterchainAccount) (*types.MsgRestoreInterchainAccountResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) - // Confirm host zone exists - hostZone, found := k.GetHostZone(ctx, msg.ChainId) - if !found { - k.Logger(ctx).Error(fmt.Sprintf("Host Zone not found: %s", msg.ChainId)) - return nil, types.ErrInvalidHostZone - } - // Get ConnectionEnd (for counterparty connection) - connectionEnd, found := k.IBCKeeper.ConnectionKeeper.GetConnection(ctx, hostZone.ConnectionId) + connectionEnd, found := k.IBCKeeper.ConnectionKeeper.GetConnection(ctx, msg.ConnectionId) if !found { - errMsg := fmt.Sprintf("invalid connection id from host %s, %s not found", msg.ChainId, hostZone.ConnectionId) - k.Logger(ctx).Error(errMsg) - return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, errMsg) + return nil, errorsmod.Wrapf(connectiontypes.ErrConnectionNotFound, "connection %s not found", msg.ConnectionId) } counterpartyConnection := connectionEnd.Counterparty // only allow restoring an account if it already exists - owner := types.FormatICAAccountOwner(msg.ChainId, msg.AccountType) - portID, err := icatypes.NewControllerPortID(owner) + portID, err := icatypes.NewControllerPortID(msg.AccountOwner) if err != nil { - errMsg := fmt.Sprintf("could not create portID for ICA controller account address: %s", owner) - k.Logger(ctx).Error(errMsg) return nil, err } - _, exists := k.ICAControllerKeeper.GetInterchainAccountAddress(ctx, hostZone.ConnectionId, portID) + _, exists := k.ICAControllerKeeper.GetInterchainAccountAddress(ctx, msg.ConnectionId, portID) if !exists { - errMsg := fmt.Sprintf("ICA controller account address not found: %s", owner) - k.Logger(ctx).Error(errMsg) - return nil, errorsmod.Wrapf(types.ErrInvalidInterchainAccountAddress, errMsg) + return nil, errorsmod.Wrapf(types.ErrInvalidInterchainAccountAddress, + "ICA controller account address not found: %s", msg.AccountOwner) } appVersion := string(icatypes.ModuleCdc.MustMarshalJSON(&icatypes.Metadata{ Version: icatypes.Version, - ControllerConnectionId: hostZone.ConnectionId, + ControllerConnectionId: msg.ConnectionId, HostConnectionId: counterpartyConnection.ConnectionId, Encoding: icatypes.EncodingProtobuf, TxType: icatypes.TxTypeSDKMultiMsg, })) - if err := k.ICAControllerKeeper.RegisterInterchainAccount(ctx, hostZone.ConnectionId, owner, appVersion); err != nil { - k.Logger(ctx).Error(fmt.Sprintf("unable to register %s account : %s", msg.AccountType.String(), err)) - return nil, err + if err := k.ICAControllerKeeper.RegisterInterchainAccount(ctx, msg.ConnectionId, msg.AccountOwner, appVersion); err != nil { + return nil, errorsmod.Wrapf(err, "unable to register account for owner %s", msg.AccountOwner) } // If we're restoring a delegation account, we also have to reset record state - if msg.AccountType == types.ICAAccountType_DELEGATION { + if msg.AccountOwner == types.FormatHostZoneICAOwner(msg.ChainId, types.ICAAccountType_DELEGATION) { + hostZone, found := k.GetHostZone(ctx, msg.ChainId) + if !found { + return nil, types.ErrHostZoneNotFound.Wrapf("delegation ICA supplied, but no associated host zone") + } + // revert DELEGATION_IN_PROGRESS records for the closed ICA channel (so that they can be staked) depositRecords := k.RecordsKeeper.GetAllDepositRecord(ctx) for _, depositRecord := range depositRecords { diff --git a/x/stakeibc/keeper/msg_server_restore_interchain_account_test.go b/x/stakeibc/keeper/msg_server_restore_interchain_account_test.go index 05b4f0a48..44da10bb5 100644 --- a/x/stakeibc/keeper/msg_server_restore_interchain_account_test.go +++ b/x/stakeibc/keeper/msg_server_restore_interchain_account_test.go @@ -165,9 +165,10 @@ func (s *KeeperTestSuite) SetupRestoreInterchainAccount(createDelegationICAChann } defaultMsg := types.MsgRestoreInterchainAccount{ - Creator: "creatoraddress", - ChainId: HostChainId, - AccountType: types.ICAAccountType_DELEGATION, + Creator: "creatoraddress", + ChainId: HostChainId, + ConnectionId: ibctesting.FirstConnectionID, + AccountOwner: types.FormatHostZoneICAOwner(HostChainId, types.ICAAccountType_DELEGATION), } return RestoreInterchainAccountTestCase{ @@ -279,31 +280,34 @@ func (s *KeeperTestSuite) TestRestoreInterchainAccount_InvalidConnectionId() { tc := s.SetupRestoreInterchainAccount(false) // Update the connectionId on the host zone so that it doesn't exist - hostZone, found := s.App.StakeibcKeeper.GetHostZone(s.Ctx, tc.validMsg.ChainId) - s.Require().True(found) - hostZone.ConnectionId = "fake_connection" - s.App.StakeibcKeeper.SetHostZone(s.Ctx, hostZone) + invalidMsg := tc.validMsg + invalidMsg.ConnectionId = "fake_connection" - _, err := s.GetMsgServer().RestoreInterchainAccount(sdk.WrapSDKContext(s.Ctx), &tc.validMsg) - s.Require().EqualError(err, "invalid connection id from host GAIA, fake_connection not found: invalid request") + _, err := s.GetMsgServer().RestoreInterchainAccount(sdk.WrapSDKContext(s.Ctx), &invalidMsg) + s.Require().ErrorContains(err, "connection fake_connection not found") } func (s *KeeperTestSuite) TestRestoreInterchainAccount_CannotRestoreNonExistentAcct() { tc := s.SetupRestoreInterchainAccount(false) + + // Attempt to restore an account that does not exist msg := tc.validMsg - msg.AccountType = types.ICAAccountType_WITHDRAWAL + msg.AccountOwner = types.FormatHostZoneICAOwner(HostChainId, types.ICAAccountType_WITHDRAWAL) _, err := s.GetMsgServer().RestoreInterchainAccount(sdk.WrapSDKContext(s.Ctx), &msg) s.Require().ErrorContains(err, "ICA controller account address not found: GAIA.WITHDRAWAL") } -func (s *KeeperTestSuite) TestRestoreInterchainAccount_FailsForIncorrectHostZone() { - tc := s.SetupRestoreInterchainAccount(false) - invalidMsg := tc.validMsg - invalidMsg.ChainId = "incorrectchainid" +func (s *KeeperTestSuite) TestRestoreInterchainAccount_HostZoneNotFound() { + tc := s.SetupRestoreInterchainAccount(true) + s.closeICAChannel(tc.delegationPortID, tc.delegationChannelID) - _, err := s.GetMsgServer().RestoreInterchainAccount(sdk.WrapSDKContext(s.Ctx), &invalidMsg) - s.Require().ErrorContains(err, "host zone not registered") + // Delete the host zone so the lookup fails + // (this check only runs for the delegation channel) + s.App.StakeibcKeeper.RemoveHostZone(s.Ctx, HostChainId) + + _, err := s.GetMsgServer().RestoreInterchainAccount(sdk.WrapSDKContext(s.Ctx), &tc.validMsg) + s.Require().ErrorContains(err, "delegation ICA supplied, but no associated host zone") } func (s *KeeperTestSuite) TestRestoreInterchainAccount_RevertDepositRecords_Failure() { @@ -333,7 +337,7 @@ func (s *KeeperTestSuite) TestRestoreInterchainAccount_NoRecordChange_Success() // Restore the channel msg := tc.validMsg - msg.AccountType = types.ICAAccountType_WITHDRAWAL + msg.AccountOwner = types.FormatHostZoneICAOwner(HostChainId, types.ICAAccountType_WITHDRAWAL) s.restoreChannelAndVerifySuccess(msg, portID, channelID) // Verify the record status' were NOT reverted diff --git a/x/stakeibc/keeper/msg_server_submit_tx.go b/x/stakeibc/keeper/msg_server_submit_tx.go index 25f9e3028..51e02eaf7 100644 --- a/x/stakeibc/keeper/msg_server_submit_tx.go +++ b/x/stakeibc/keeper/msg_server_submit_tx.go @@ -36,15 +36,16 @@ const ( ) func (k Keeper) DelegateOnHost(ctx sdk.Context, hostZone types.HostZone, amt sdk.Coin, depositRecord recordstypes.DepositRecord) error { + // TODO: Remove this block and use connection-id from host zone // the relevant ICA is the delegate account - owner := types.FormatICAAccountOwner(hostZone.ChainId, types.ICAAccountType_DELEGATION) + owner := types.FormatHostZoneICAOwner(hostZone.ChainId, types.ICAAccountType_DELEGATION) portID, err := icatypes.NewControllerPortID(owner) if err != nil { return errorsmod.Wrapf(sdkerrors.ErrInvalidAddress, "%s has no associated portId", owner) } - connectionId, err := k.GetConnectionId(ctx, portID) - if err != nil { - return errorsmod.Wrapf(sdkerrors.ErrInvalidChainID, "%s has no associated connection", portID) + connectionId, found := k.GetConnectionIdFromICAPortId(ctx, portID) + if !found { + return errorsmod.Wrapf(types.ErrICAAccountNotFound, "unable to find ICA connection Id for port %s", portID) } // Fetch the relevant ICA @@ -118,15 +119,16 @@ func (k Keeper) DelegateOnHost(ctx sdk.Context, hostZone types.HostZone, amt sdk } func (k Keeper) SetWithdrawalAddressOnHost(ctx sdk.Context, hostZone types.HostZone) error { + // TODO: Remove this block and use connection-id from host zone // The relevant ICA is the delegate account - owner := types.FormatICAAccountOwner(hostZone.ChainId, types.ICAAccountType_DELEGATION) + owner := types.FormatHostZoneICAOwner(hostZone.ChainId, types.ICAAccountType_DELEGATION) portID, err := icatypes.NewControllerPortID(owner) if err != nil { return errorsmod.Wrapf(sdkerrors.ErrInvalidAddress, "%s has no associated portId", owner) } - connectionId, err := k.GetConnectionId(ctx, portID) - if err != nil { - return errorsmod.Wrapf(sdkerrors.ErrInvalidChainID, "%s has no associated connection", portID) + connectionId, found := k.GetConnectionIdFromICAPortId(ctx, portID) + if !found { + return errorsmod.Wrapf(types.ErrICAAccountNotFound, "unable to find ICA connection Id for port %s", portID) } // Fetch the relevant ICA @@ -309,6 +311,7 @@ func (k Keeper) SubmitTxsEpoch( } // SubmitTxs submits an ICA transaction containing multiple messages +// This function only supports messages to ICAs on the host zone func (k Keeper) SubmitTxs( ctx sdk.Context, connectionId string, @@ -318,11 +321,11 @@ func (k Keeper) SubmitTxs( callbackId string, callbackArgs []byte, ) (uint64, error) { - chainId, err := k.GetChainID(ctx, connectionId) + chainId, err := k.GetChainIdFromConnectionId(ctx, connectionId) if err != nil { return 0, err } - owner := types.FormatICAAccountOwner(chainId, icaAccountType) + owner := types.FormatHostZoneICAOwner(chainId, icaAccountType) portID, err := icatypes.NewControllerPortID(owner) if err != nil { return 0, err @@ -377,6 +380,35 @@ func (k Keeper) SubmitTxs( return sequence, nil } +func (k Keeper) SubmitICATxWithoutCallback( + ctx sdk.Context, + connectionId string, + icaAccountOwner string, + msgs []proto.Message, + timeoutTimestamp uint64, +) error { + // Serialize tx messages + txBz, err := icatypes.SerializeCosmosTx(k.cdc, msgs) + if err != nil { + return errorsmod.Wrapf(err, "unable to serialize cosmos transaction") + } + packetData := icatypes.InterchainAccountPacketData{ + Type: icatypes.EXECUTE_TX, + Data: txBz, + } + relativeTimeoutOffset := timeoutTimestamp - uint64(ctx.BlockTime().UnixNano()) + + // Submit ICA, no need to store callback data or register callback function + icaMsgServer := icacontrollerkeeper.NewMsgServerImpl(&k.ICAControllerKeeper) + msgSendTx := icacontrollertypes.NewMsgSendTx(icaAccountOwner, connectionId, relativeTimeoutOffset, packetData) + _, err = icaMsgServer.SendTx(ctx, msgSendTx) + if err != nil { + return errorsmod.Wrapf(err, "unable to send ICA tx") + } + + return nil +} + func (k Keeper) GetLightClientHeightSafely(ctx sdk.Context, connectionID string) (uint64, error) { // get light client's latest height conn, found := k.IBCKeeper.ConnectionKeeper.GetConnection(ctx, connectionID) diff --git a/x/stakeibc/keeper/msg_server_update_trade_route.go b/x/stakeibc/keeper/msg_server_update_trade_route.go new file mode 100644 index 000000000..9c23fd65c --- /dev/null +++ b/x/stakeibc/keeper/msg_server_update_trade_route.go @@ -0,0 +1,73 @@ +package keeper + +import ( + "context" + + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + + "github.com/Stride-Labs/stride/v16/x/stakeibc/types" + + errorsmod "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// Gov tx to update the trade config of a trade route +// +// Example proposal: +// +// { +// "title": "Update a the trade config for host chain X", +// "metadata": "Update a the trade config for host chain X", +// "summary": "Update a the trade config for host chain X", +// "messages":[ +// { +// "@type": "/stride.stakeibc.MsgUpdateTradeRoute", +// "authority": "stride10d07y265gmmuvt4z0w9aw880jnsr700jefnezl", +// +// "pool_id": 1, +// "max_allowed_swap_loss_rate": "0.05", +// "min_swap_amount": "10000000", +// "max_swap_amount": "1000000000" +// } +// ], +// "deposit": "2000000000ustrd" +// } +// +// >>> strided tx gov submit-proposal {proposal_file.json} --from wallet +func (ms msgServer) UpdateTradeRoute(goCtx context.Context, msg *types.MsgUpdateTradeRoute) (*types.MsgUpdateTradeRouteResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + if ms.authority != msg.Authority { + return nil, errorsmod.Wrapf(govtypes.ErrInvalidSigner, "invalid authority; expected %s, got %s", ms.authority, msg.Authority) + } + + route, found := ms.Keeper.GetTradeRoute(ctx, msg.RewardDenom, msg.HostDenom) + if !found { + return nil, errorsmod.Wrapf(types.ErrTradeRouteNotFound, + "no trade route for rewardDenom %s and hostDenom %s", msg.RewardDenom, msg.HostDenom) + } + + maxAllowedSwapLossRate := msg.MaxAllowedSwapLossRate + if maxAllowedSwapLossRate == "" { + maxAllowedSwapLossRate = DefaultMaxAllowedSwapLossRate + } + maxSwapAmount := msg.MaxSwapAmount + if maxSwapAmount.IsZero() { + maxSwapAmount = DefaultMaxSwapAmount + } + + updatedConfig := types.TradeConfig{ + PoolId: msg.PoolId, + + SwapPrice: sdk.ZeroDec(), + PriceUpdateTimestamp: 0, + + MaxAllowedSwapLossRate: sdk.MustNewDecFromStr(maxAllowedSwapLossRate), + MinSwapAmount: msg.MinSwapAmount, + MaxSwapAmount: maxSwapAmount, + } + + route.TradeConfig = updatedConfig + ms.Keeper.SetTradeRoute(ctx, route) + + return &types.MsgUpdateTradeRouteResponse{}, nil +} diff --git a/x/stakeibc/keeper/msg_server_update_trade_route_test.go b/x/stakeibc/keeper/msg_server_update_trade_route_test.go new file mode 100644 index 000000000..75c666023 --- /dev/null +++ b/x/stakeibc/keeper/msg_server_update_trade_route_test.go @@ -0,0 +1,86 @@ +package keeper_test + +import ( + sdkmath "cosmossdk.io/math" + + "github.com/Stride-Labs/stride/v16/x/stakeibc/keeper" + "github.com/Stride-Labs/stride/v16/x/stakeibc/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// Helper function to update a trade route and check the updated route matched expectations +func (s *KeeperTestSuite) submitUpdateTradeRouteAndValidate(msg types.MsgUpdateTradeRoute, expectedRoute types.TradeRoute) { + _, err := s.GetMsgServer().UpdateTradeRoute(sdk.WrapSDKContext(s.Ctx), &msg) + s.Require().NoError(err, "no error expected when updating trade route") + + actualRoute, found := s.App.StakeibcKeeper.GetTradeRoute(s.Ctx, RewardDenom, HostDenom) + s.Require().True(found, "trade route should have been updated") + s.Require().Equal(expectedRoute, actualRoute, "trade route") +} + +func (s *KeeperTestSuite) TestUpdateTradeRoute() { + poolId := uint64(100) + maxAllowedSwapLossRate := "0.05" + minSwapAmount := sdkmath.NewInt(100) + maxSwapAmount := sdkmath.NewInt(1_000) + + // Create a trade route with no parameters + initialRoute := types.TradeRoute{ + RewardDenomOnRewardZone: RewardDenom, + HostDenomOnHostZone: HostDenom, + } + s.App.StakeibcKeeper.SetTradeRoute(s.Ctx, initialRoute) + + // Define a valid message given the parameters above + msg := types.MsgUpdateTradeRoute{ + Authority: Authority, + + RewardDenom: RewardDenom, + HostDenom: HostDenom, + + PoolId: poolId, + MaxAllowedSwapLossRate: maxAllowedSwapLossRate, + MinSwapAmount: minSwapAmount, + MaxSwapAmount: maxSwapAmount, + } + + // Build out the expected trade route given the above + expectedRoute := initialRoute + expectedRoute.TradeConfig = types.TradeConfig{ + PoolId: poolId, + SwapPrice: sdk.ZeroDec(), + PriceUpdateTimestamp: 0, + + MaxAllowedSwapLossRate: sdk.MustNewDecFromStr(maxAllowedSwapLossRate), + MinSwapAmount: minSwapAmount, + MaxSwapAmount: maxSwapAmount, + } + + // Update the route and confirm the changes persisted + s.submitUpdateTradeRouteAndValidate(msg, expectedRoute) + + // Update it again, this time using default args + defaultMsg := msg + defaultMsg.MaxAllowedSwapLossRate = "" + defaultMsg.MaxSwapAmount = sdkmath.ZeroInt() + + expectedRoute.TradeConfig.MaxAllowedSwapLossRate = sdk.MustNewDecFromStr(keeper.DefaultMaxAllowedSwapLossRate) + expectedRoute.TradeConfig.MaxSwapAmount = keeper.DefaultMaxSwapAmount + + s.submitUpdateTradeRouteAndValidate(defaultMsg, expectedRoute) + + // Test that an error is thrown if the correct authority is not specified + invalidMsg := msg + invalidMsg.Authority = "not-gov-address" + + _, err := s.GetMsgServer().UpdateTradeRoute(sdk.WrapSDKContext(s.Ctx), &invalidMsg) + s.Require().ErrorContains(err, "invalid authority") + + // Test that an error is thrown if the route doesn't exist + invalidMsg = msg + invalidMsg.RewardDenom = "invalid-reward-denom" + + _, err = s.GetMsgServer().UpdateTradeRoute(sdk.WrapSDKContext(s.Ctx), &invalidMsg) + s.Require().ErrorContains(err, "trade route not found") +} diff --git a/x/stakeibc/keeper/reward_converter.go b/x/stakeibc/keeper/reward_converter.go new file mode 100644 index 000000000..3d4e76898 --- /dev/null +++ b/x/stakeibc/keeper/reward_converter.go @@ -0,0 +1,558 @@ +package keeper + +import ( + "encoding/json" + "fmt" + "time" + + errorsmod "cosmossdk.io/errors" + sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/bech32" + bankTypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/cosmos/gogoproto/proto" + + transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" + + "github.com/Stride-Labs/stride/v16/utils" + epochstypes "github.com/Stride-Labs/stride/v16/x/epochs/types" + icqtypes "github.com/Stride-Labs/stride/v16/x/interchainquery/types" + "github.com/Stride-Labs/stride/v16/x/stakeibc/types" +) + +// JSON Memo for PFM transfers +type PacketForwardMetadata struct { + Forward *ForwardMetadata `json:"forward"` +} +type ForwardMetadata struct { + Receiver string `json:"receiver"` + Port string `json:"port"` + Channel string `json:"channel"` + Timeout string `json:"timeout"` + Retries int64 `json:"retries"` +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// The goal of this code is to allow certain reward token types to be automatically traded into other types +// This happens before the rest of the staking, allocation, distribution etc. would continue as normal +// +// Reward tokens are any special denoms which are paid out in the withdrawal address +// Most host zones inflate their tokens and their native token is what appears in the withdrawal ICA +// The following allows for chains to use foreign denoms as revenue, which can be traded to any other denom first +// +// 1. Epochly check the reward denom balance in the withdrawal address +// on callback, send all this reward denom from withdrawl ICA to trade ICA on the trade zone (OSMOSIS) +// 2. Epochly check the reward denom balance in trade ICA +// on callback, trade all reward denom for host denom defined by pool and routes in params +// 3. Epochly check the host denom balance in trade ICA +// on callback, transfer these host denom tokens from trade ICA to withdrawal ICA on original host zone +// +// Normal staking flow continues from there. So the host denom tokens will land on the original host zone +// and the normal staking and distribution flow will continue from there. +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// Builds a PFM transfer message to send reward tokens from the host zone, +// through the reward zone (to unwind) and finally to the trade zone +func (k Keeper) BuildHostToTradeTransferMsg( + ctx sdk.Context, + amount sdkmath.Int, + route types.TradeRoute, +) (msg transfertypes.MsgTransfer, err error) { + // Get the epoch tracker to determine the timeouts + strideEpochTracker, found := k.GetEpochTracker(ctx, epochstypes.STRIDE_EPOCH) + if !found { + return msg, errorsmod.Wrapf(types.ErrEpochNotFound, epochstypes.STRIDE_EPOCH) + } + + // Timeout the first transfer halfway through the epoch, and the second transfer at the end of the epoch + // The pfm transfer requires a duration instead of a timestamp for the timeout, so we just use half the epoch length + halfEpochDuration := strideEpochTracker.Duration / 2 + transfer1TimeoutTimestamp := uint64(strideEpochTracker.NextEpochStartTime - halfEpochDuration) // unix nano + transfer2TimeoutDuration := fmt.Sprintf("%ds", halfEpochDuration/1e9) // string in seconds + + startingDenom := route.RewardDenomOnHostZone + sendTokens := sdk.NewCoin(startingDenom, amount) + + withdrawlIcaAddress := route.HostAccount.Address + unwindIcaAddress := route.RewardAccount.Address + tradeIcaAddress := route.TradeAccount.Address + + // Validate ICAs were registered + if withdrawlIcaAddress == "" { + return msg, errorsmod.Wrapf(types.ErrICAAccountNotFound, "no host account found for %s", route.Description()) + } + if unwindIcaAddress == "" { + return msg, errorsmod.Wrapf(types.ErrICAAccountNotFound, "no reward account found for %s", route.Description()) + } + if tradeIcaAddress == "" { + return msg, errorsmod.Wrapf(types.ErrICAAccountNotFound, "no trade account found for %s", route.Description()) + } + + // Build the pfm memo to specify the forwarding logic + // This transfer channel id is a channel on the reward Zone for transfers to the trade zone + // (not to be confused with a transfer channel on Stride or the Host Zone) + memo := PacketForwardMetadata{ + Forward: &ForwardMetadata{ + Receiver: tradeIcaAddress, + Port: transfertypes.PortID, + Channel: route.RewardToTradeChannelId, + Timeout: transfer2TimeoutDuration, + Retries: 0, + }, + } + memoJSON, err := json.Marshal(memo) + if err != nil { + return msg, err + } + + msg = transfertypes.MsgTransfer{ + SourcePort: transfertypes.PortID, + SourceChannel: route.HostToRewardChannelId, // channel on hostZone for transfers to rewardZone + Token: sendTokens, + Sender: withdrawlIcaAddress, + Receiver: unwindIcaAddress, // could be "pfm" or a real address depending on version + TimeoutTimestamp: transfer1TimeoutTimestamp, + Memo: string(memoJSON), + } + + return msg, nil +} + +// ICA tx will kick off transfering the reward tokens from the hostZone withdrawl ICA to the tradeZone trade ICA +// This will be two hops to unwind the ibc denom through the rewardZone using pfm in the transfer memo +func (k Keeper) TransferRewardTokensHostToTrade(ctx sdk.Context, amount sdkmath.Int, route types.TradeRoute) error { + // If the min swap amount was not set it would be ZeroInt, if positive we need to compare to the amount given + // then if the min swap amount is greater than the current amount, do nothing this epoch to avoid small transfers + // Particularly important for the PFM hop if the reward chain has frictional transfer fees (like noble chain) + if route.TradeConfig.MinSwapAmount.GT(amount) { + return nil + } + + // Similarly, if there's no price on the trade route yet, don't initiate the transfer because + // we know the swap will not be submitted + if route.TradeConfig.SwapPrice.IsZero() { + return nil + } + + // Build the PFM transfer message from host to trade zone + msg, err := k.BuildHostToTradeTransferMsg(ctx, amount, route) + if err != nil { + return err + } + msgs := []proto.Message{&msg} + + hostZoneId := route.HostAccount.ChainId + rewardZoneId := route.RewardAccount.ChainId + tradeZoneId := route.TradeAccount.ChainId + k.Logger(ctx).Info(utils.LogWithHostZone(hostZoneId, + "Preparing MsgTransfer of %+v from %s to %s to %s", msg.Token, hostZoneId, rewardZoneId, tradeZoneId)) + + // Send the ICA tx to kick off transfer from hostZone through rewardZone to the tradeZone (no callbacks) + hostAccount := route.HostAccount + withdrawalOwner := types.FormatHostZoneICAOwner(hostAccount.ChainId, hostAccount.Type) + err = k.SubmitICATxWithoutCallback(ctx, hostAccount.ConnectionId, withdrawalOwner, msgs, msg.TimeoutTimestamp) + if err != nil { + return errorsmod.Wrapf(err, "Failed to submit ICA tx, Messages: %+v", msgs) + } + + return nil +} + +// ICA tx to kick off transfering the converted tokens back from tradeZone to the hostZone withdrawal ICA +func (k Keeper) TransferConvertedTokensTradeToHost(ctx sdk.Context, amount sdkmath.Int, route types.TradeRoute) error { + // Timeout for ica tx and the transfer msgs is at end of epoch + strideEpochTracker, found := k.GetEpochTracker(ctx, epochstypes.STRIDE_EPOCH) + if !found { + return errorsmod.Wrapf(types.ErrEpochNotFound, epochstypes.STRIDE_EPOCH) + } + timeout := uint64(strideEpochTracker.NextEpochStartTime) + + convertedDenom := route.HostDenomOnTradeZone + sendTokens := sdk.NewCoin(convertedDenom, amount) + + // Validate ICAs were registered + tradeIcaAddress := route.TradeAccount.Address + withdrawlIcaAddress := route.HostAccount.Address + if withdrawlIcaAddress == "" { + return errorsmod.Wrapf(types.ErrICAAccountNotFound, "no host account found for %s", route.Description()) + } + if tradeIcaAddress == "" { + return errorsmod.Wrapf(types.ErrICAAccountNotFound, "no trade account found for %s", route.Description()) + } + + var msgs []proto.Message + msgs = append(msgs, &transfertypes.MsgTransfer{ + SourcePort: transfertypes.PortID, + SourceChannel: route.TradeToHostChannelId, // channel on tradeZone for transfers to hostZone + Token: sendTokens, + Sender: tradeIcaAddress, + Receiver: withdrawlIcaAddress, + TimeoutTimestamp: timeout, + Memo: "", + }) + + hostZoneId := route.HostAccount.ChainId + tradeZoneId := route.TradeAccount.ChainId + k.Logger(ctx).Info(utils.LogWithHostZone(hostZoneId, + "Preparing MsgTransfer of %+v from %s to %s", sendTokens, tradeZoneId, hostZoneId)) + + // Send the ICA tx to kick off transfer from hostZone through rewardZone to the tradeZone (no callbacks) + tradeAccount := route.TradeAccount + tradeOwner := types.FormatTradeRouteICAOwnerFromRouteId(tradeAccount.ChainId, route.GetRouteId(), tradeAccount.Type) + err := k.SubmitICATxWithoutCallback(ctx, tradeAccount.ConnectionId, tradeOwner, msgs, timeout) + if err != nil { + return errorsmod.Wrapf(err, "Failed to submit ICA tx, Messages: %+v", msgs) + } + + return nil +} + +// Builds the Osmosis swap message to trade reward tokens for host tokens +// Depending on min and max swap amounts set in the route, it is possible not the full amount given will swap +// The minimum amount of tokens that can come out of the trade is calculated using a price from the pool +func (k Keeper) BuildSwapMsg(rewardAmount sdkmath.Int, route types.TradeRoute) (msg types.MsgSwapExactAmountIn, err error) { + // Validate the trade ICA was registered + tradeIcaAddress := route.TradeAccount.Address + if tradeIcaAddress == "" { + return msg, errorsmod.Wrapf(types.ErrICAAccountNotFound, "no trade account found for %s", route.Description()) + } + + // If the max swap amount was not set it would be ZeroInt, if positive we need to compare to the amount given + // then if max swap amount is LTE to amount full swap is possible so amount is fine, otherwise set amount to max + tradeConfig := route.TradeConfig + if tradeConfig.MaxSwapAmount.IsPositive() && rewardAmount.GT(tradeConfig.MaxSwapAmount) { + rewardAmount = tradeConfig.MaxSwapAmount + } + + // See if pool swap price has been set to a valid ratio + // The only time this should not be set is right after the pool is added, + // before an ICQ has been submitted for the price + if tradeConfig.SwapPrice.IsZero() { + return msg, fmt.Errorf("Price not found for pool %d", tradeConfig.PoolId) + } + + // If there is a valid price, use it to set a floor for the acceptable minimum output tokens + // minOut is the minimum number of HostDenom tokens we must receive or the swap will fail + // + // To calculate minOut, we first convert the rewardAmount into units of HostDenom, + // and then we multiply by (1 - MaxAllowedSwapLossRate) + // + // The price on the trade route represents the ratio of host denom to reward denom + // So, to convert from units of RewardTokens to units of HostTokens, + // we multiply the reward amount by the price: + // AmountInHost = AmountInReward * SwapPrice + rewardAmountConverted := sdk.NewDecFromInt(rewardAmount).Mul(tradeConfig.SwapPrice) + minOutPercentage := sdk.OneDec().Sub(tradeConfig.MaxAllowedSwapLossRate) + minOut := rewardAmountConverted.Mul(minOutPercentage).TruncateInt() + + tradeTokens := sdk.NewCoin(route.RewardDenomOnTradeZone, rewardAmount) + + // Prepare Osmosis GAMM module MsgSwapExactAmountIn from the trade account to perform the trade + // If we want to generalize in the future, write swap message generation funcs for each DEX type, + // decide which msg generation function to call based on check of which tradeZone was passed in + routes := []types.SwapAmountInRoute{{ + PoolId: tradeConfig.PoolId, + TokenOutDenom: route.HostDenomOnTradeZone, + }} + msg = types.MsgSwapExactAmountIn{ + Sender: tradeIcaAddress, + Routes: routes, + TokenIn: tradeTokens, + TokenOutMinAmount: minOut, + } + + return msg, nil +} + +// Trade reward tokens in the Trade ICA for the host denom tokens using ICA remote tx on trade zone +// The amount represents the total amount of the reward token in the trade ICA found by the calling ICQ +func (k Keeper) SwapRewardTokens(ctx sdk.Context, rewardAmount sdkmath.Int, route types.TradeRoute) error { + // If the min swap amount was not set it would be ZeroInt, if positive we need to compare to the amount given + // then if the min swap amount is greater than the current amount, do nothing this epoch to avoid small swaps + tradeConfig := route.TradeConfig + if tradeConfig.MinSwapAmount.IsPositive() && tradeConfig.MinSwapAmount.GT(rewardAmount) { + return nil + } + + // Build the Osmosis swap message to convert reward tokens to host tokens + msg, err := k.BuildSwapMsg(rewardAmount, route) + if err != nil { + return err + } + msgs := []proto.Message{&msg} + + tradeAccount := route.TradeAccount + k.Logger(ctx).Info(utils.LogWithHostZone(tradeAccount.ChainId, + "Preparing MsgSwapExactAmountIn of %+v from the trade account", msg.TokenIn)) + + // Timeout the swap at the end of the epoch + strideEpochTracker, found := k.GetEpochTracker(ctx, epochstypes.HOUR_EPOCH) + if !found { + return errorsmod.Wrapf(types.ErrEpochNotFound, epochstypes.HOUR_EPOCH) + } + timeout := uint64(strideEpochTracker.NextEpochStartTime) + + // Send the ICA tx to perform the swap on the tradeZone + tradeOwner := types.FormatTradeRouteICAOwnerFromRouteId(tradeAccount.ChainId, route.GetRouteId(), tradeAccount.Type) + err = k.SubmitICATxWithoutCallback(ctx, tradeAccount.ConnectionId, tradeOwner, msgs, timeout) + if err != nil { + return errorsmod.Wrapf(err, "Failed to submit ICA tx for the swap, Messages: %v", msgs) + } + + return nil +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// ICQ calls for remote ICA balances +// There is a single trade zone (hardcoded as Osmosis for now but maybe additional DEXes allowed in the future) +// We have to initialize a single hostZone object for the trade zone once in initialization and +// then it can be used in all these calls +/////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// Kick off ICQ for the reward denom balance in the withdrawal address +func (k Keeper) WithdrawalRewardBalanceQuery(ctx sdk.Context, route types.TradeRoute) error { + withdrawalAccount := route.HostAccount + k.Logger(ctx).Info(utils.LogWithHostZone(withdrawalAccount.ChainId, "Submitting ICQ for reward denom in withdrawal account")) + + // Encode the withdrawal account address for the query request + // The query request consists of the withdrawal account address and reward denom + _, withdrawalAddressBz, err := bech32.DecodeAndConvert(withdrawalAccount.Address) + if err != nil { + return errorsmod.Wrapf(err, "invalid withdrawal account address (%s), could not decode", withdrawalAccount.Address) + } + queryData := append(bankTypes.CreateAccountBalancesPrefix(withdrawalAddressBz), []byte(route.RewardDenomOnHostZone)...) + + // Timeout the query halfway through the epoch (since that's when the first transfer + // in the pfm sequence will timeout) + strideEpochTracker, found := k.GetEpochTracker(ctx, epochstypes.STRIDE_EPOCH) + if !found { + return errorsmod.Wrapf(types.ErrEpochNotFound, epochstypes.STRIDE_EPOCH) + } + timeoutDuration := time.Duration(strideEpochTracker.Duration) / 2 + + // We need the trade route keys in the callback to look up the tradeRoute struct + callbackData := types.TradeRouteCallback{ + RewardDenom: route.RewardDenomOnRewardZone, + HostDenom: route.HostDenomOnHostZone, + } + callbackDataBz, err := proto.Marshal(&callbackData) + if err != nil { + return errorsmod.Wrapf(err, "unable to marshal TradeRoute callback data") + } + + // Submit the ICQ for the withdrawal account balance + query := icqtypes.Query{ + ChainId: withdrawalAccount.ChainId, + ConnectionId: withdrawalAccount.ConnectionId, + QueryType: icqtypes.BANK_STORE_QUERY_WITH_PROOF, + RequestData: queryData, + CallbackModule: types.ModuleName, + CallbackId: ICQCallbackID_WithdrawalRewardBalance, + CallbackData: callbackDataBz, + TimeoutDuration: timeoutDuration, + TimeoutPolicy: icqtypes.TimeoutPolicy_REJECT_QUERY_RESPONSE, + } + if err := k.InterchainQueryKeeper.SubmitICQRequest(ctx, query, false); err != nil { + return err + } + + return nil +} + +// Kick off ICQ for how many reward tokens are in the trade ICA associated with this host zone +func (k Keeper) TradeRewardBalanceQuery(ctx sdk.Context, route types.TradeRoute) error { + tradeAccount := route.TradeAccount + k.Logger(ctx).Info(utils.LogWithHostZone(tradeAccount.ChainId, "Submitting ICQ for reward denom in trade ICA account")) + + // Encode the trade account address for the query request + // The query request consists of the trade account address and reward denom + // keep in mind this ICA address actually exists on trade zone but is associated with trades performed for host zone + _, tradeAddressBz, err := bech32.DecodeAndConvert(tradeAccount.Address) + if err != nil { + return errorsmod.Wrapf(err, "invalid trade account address (%s), could not decode", tradeAccount.Address) + } + queryData := append(bankTypes.CreateAccountBalancesPrefix(tradeAddressBz), []byte(route.RewardDenomOnTradeZone)...) + + // Timeout query at end of epoch + hourEpochTracker, found := k.GetEpochTracker(ctx, epochstypes.HOUR_EPOCH) + if !found { + return errorsmod.Wrapf(types.ErrEpochNotFound, epochstypes.HOUR_EPOCH) + } + timeout := time.Unix(0, int64(hourEpochTracker.NextEpochStartTime)) + timeoutDuration := timeout.Sub(ctx.BlockTime()) + + // We need the trade route keys in the callback to look up the tradeRoute struct + callbackData := types.TradeRouteCallback{ + RewardDenom: route.RewardDenomOnRewardZone, + HostDenom: route.HostDenomOnHostZone, + } + callbackDataBz, err := proto.Marshal(&callbackData) + if err != nil { + return errorsmod.Wrapf(err, "unable to marshal TradeRewardBalanceQuery callback data") + } + + // Submit the ICQ for the withdrawal account balance + query := icqtypes.Query{ + ChainId: tradeAccount.ChainId, + ConnectionId: tradeAccount.ConnectionId, // query needs to go to the trade zone, not the host zone + QueryType: icqtypes.BANK_STORE_QUERY_WITH_PROOF, + RequestData: queryData, + CallbackModule: types.ModuleName, + CallbackId: ICQCallbackID_TradeRewardBalance, + CallbackData: callbackDataBz, + TimeoutDuration: timeoutDuration, + TimeoutPolicy: icqtypes.TimeoutPolicy_REJECT_QUERY_RESPONSE, + } + if err := k.InterchainQueryKeeper.SubmitICQRequest(ctx, query, false); err != nil { + return err + } + + return nil +} + +// Kick off ICQ for how many converted tokens are in the trade ICA associated with this host zone +func (k Keeper) TradeConvertedBalanceQuery(ctx sdk.Context, route types.TradeRoute) error { + tradeAccount := route.TradeAccount + k.Logger(ctx).Info(utils.LogWithHostZone(tradeAccount.ChainId, "Submitting ICQ for converted denom in trade ICA account")) + + // Encode the trade account address for the query request + // The query request consists of the trade account address and converted denom + // keep in mind this ICA address actually exists on trade zone but is associated with trades performed for host zone + _, tradeAddressBz, err := bech32.DecodeAndConvert(tradeAccount.Address) + if err != nil { + return errorsmod.Wrapf(err, "invalid trade account address (%s), could not decode", tradeAccount.Address) + } + queryData := append(bankTypes.CreateAccountBalancesPrefix(tradeAddressBz), []byte(route.HostDenomOnTradeZone)...) + + // Timeout query at end of epoch + strideEpochTracker, found := k.GetEpochTracker(ctx, epochstypes.STRIDE_EPOCH) + if !found { + return errorsmod.Wrapf(types.ErrEpochNotFound, epochstypes.STRIDE_EPOCH) + } + timeout := time.Unix(0, int64(strideEpochTracker.NextEpochStartTime)) + timeoutDuration := timeout.Sub(ctx.BlockTime()) + + // We need the trade route keys in the callback to look up the tradeRoute struct + callbackData := types.TradeRouteCallback{ + RewardDenom: route.RewardDenomOnRewardZone, + HostDenom: route.HostDenomOnHostZone, + } + callbackDataBz, err := proto.Marshal(&callbackData) + if err != nil { + return errorsmod.Wrapf(err, "unable to marshal trade route as callback data") + } + + // Submit the ICQ for the withdrawal account balance + query := icqtypes.Query{ + ChainId: tradeAccount.ChainId, + ConnectionId: tradeAccount.ConnectionId, // query needs to go to the trade zone, not the host zone + QueryType: icqtypes.BANK_STORE_QUERY_WITH_PROOF, + RequestData: queryData, + CallbackModule: types.ModuleName, + CallbackId: ICQCallbackID_TradeConvertedBalance, + CallbackData: callbackDataBz, + TimeoutDuration: timeoutDuration, + TimeoutPolicy: icqtypes.TimeoutPolicy_REJECT_QUERY_RESPONSE, + } + if err := k.InterchainQueryKeeper.SubmitICQRequest(ctx, query, false); err != nil { + return err + } + + return nil +} + +// Kick off ICQ for the spot price on the pool given the input and output denoms implied by the given TradeRoute +// the callback for this query is responsible for updating the returned spot price on the keeper data +func (k Keeper) PoolPriceQuery(ctx sdk.Context, route types.TradeRoute) error { + tradeAccount := route.TradeAccount + k.Logger(ctx).Info(utils.LogWithHostZone(tradeAccount.ChainId, "Submitting ICQ for spot price in this pool")) + + // Build query request data which consists of the TWAP store key built from each denom + queryData := icqtypes.FormatOsmosisMostRecentTWAPKey( + route.TradeConfig.PoolId, + route.RewardDenomOnTradeZone, + route.HostDenomOnTradeZone, + ) + + // Timeout query at end of epoch + hourEpochTracker, found := k.GetEpochTracker(ctx, epochstypes.HOUR_EPOCH) + if !found { + return errorsmod.Wrapf(types.ErrEpochNotFound, epochstypes.HOUR_EPOCH) + } + timeout := time.Unix(0, int64(hourEpochTracker.NextEpochStartTime)) + timeoutDuration := timeout.Sub(ctx.BlockTime()) + + // We need the trade route keys in the callback to look up the tradeRoute struct + callbackData := types.TradeRouteCallback{ + RewardDenom: route.RewardDenomOnRewardZone, + HostDenom: route.HostDenomOnHostZone, + } + callbackDataBz, err := proto.Marshal(&callbackData) + if err != nil { + return errorsmod.Wrapf(err, "unable to marshal TradeRewardBalanceQuery callback data") + } + + // Submit the ICQ for the trade pool spot price query + query := icqtypes.Query{ + ChainId: tradeAccount.ChainId, + ConnectionId: tradeAccount.ConnectionId, // query needs to go to the trade zone, not the host zone + QueryType: icqtypes.TWAP_STORE_QUERY_WITH_PROOF, + RequestData: queryData, + CallbackModule: types.ModuleName, + CallbackId: ICQCallbackID_PoolPrice, + CallbackData: callbackDataBz, + TimeoutDuration: timeoutDuration, + TimeoutPolicy: icqtypes.TimeoutPolicy_REJECT_QUERY_RESPONSE, + } + if err := k.InterchainQueryKeeper.SubmitICQRequest(ctx, query, false); err != nil { + k.Logger(ctx).Error(fmt.Sprintf("Error querying pool spot price, error: %s", err.Error())) + return err + } + + return nil +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// The current design assumes foreign reward tokens start and end in the hostZone withdrawal address +// Step 1: transfer reward tokens to trade chain +// Step 2: perform the swap with as many reward tokens as possible +// Step 3: return the swapped tokens to the withdrawal ICA on hostZone +// Independently there is an ICQ to get the swap price and update it in the keeper state +// +// Because the swaps have limits on how many tokens can be used to avoid slippage, +// the swaps and price checks happen on a faster (hourly) cadence than the transfers (stride epochly) +//////////////////////////////////////////////////////////////////////////////////////////////////// + +// Helper function to be run stride epochly, kicks off queries on specific denoms on route +func (k Keeper) TransferAllRewardTokens(ctx sdk.Context) { + for _, route := range k.GetAllTradeRoutes(ctx) { + // Step 1: ICQ reward balance on hostZone, transfer funds with unwinding to trade chain + if err := k.WithdrawalRewardBalanceQuery(ctx, route); err != nil { + k.Logger(ctx).Error(fmt.Sprintf("Unable to submit query for reward balance in withdrawal ICA: %s", err)) + } + // Step 3: ICQ converted tokens in trade ICA, transfer funds back to hostZone withdrawal ICA + if err := k.TradeConvertedBalanceQuery(ctx, route); err != nil { + k.Logger(ctx).Error(fmt.Sprintf("Unable to submit query for converted balance in trade ICA: %s", err)) + } + } +} + +// Helper function to be run hourly, kicks off query which will kick off actual swaps to happen +func (k Keeper) SwapAllRewardTokens(ctx sdk.Context) { + for _, route := range k.GetAllTradeRoutes(ctx) { + // Step 2: ICQ reward balance in trade ICA, swap tokens according to limiting rules + if err := k.TradeRewardBalanceQuery(ctx, route); err != nil { + k.Logger(ctx).Error(fmt.Sprintf("Unable to submit query for reward balance in trade ICA: %s", err)) + } + } +} + +// Helper function to be run hourly, kicks off query to get and update the swap price in keeper data +func (k Keeper) UpdateAllSwapPrices(ctx sdk.Context) { + for _, route := range k.GetAllTradeRoutes(ctx) { + // ICQ swap price for the specific pair on this route and update keeper on callback + if err := k.PoolPriceQuery(ctx, route); err != nil { + k.Logger(ctx).Error(fmt.Sprintf("Unable to submit query for pool spot price: %s", err)) + } + } +} diff --git a/x/stakeibc/keeper/reward_converter_test.go b/x/stakeibc/keeper/reward_converter_test.go new file mode 100644 index 000000000..c05534154 --- /dev/null +++ b/x/stakeibc/keeper/reward_converter_test.go @@ -0,0 +1,854 @@ +package keeper_test + +import ( + "fmt" + "time" + + sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/gogoproto/proto" + transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" + ibctesting "github.com/cosmos/ibc-go/v7/testing" + + epochtypes "github.com/Stride-Labs/stride/v16/x/epochs/types" + icqtypes "github.com/Stride-Labs/stride/v16/x/interchainquery/types" + "github.com/Stride-Labs/stride/v16/x/stakeibc/keeper" + "github.com/Stride-Labs/stride/v16/x/stakeibc/types" +) + +// Useful across all balance query icqcallback tests +type BalanceQueryCallbackTestCase struct { + TradeRoute types.TradeRoute + Response ICQCallbackArgs + Balance sdkmath.Int + ChannelID string + PortID string +} + +type TransferRewardHostToTradeTestCase struct { + TradeRoute types.TradeRoute + TransferAmount sdkmath.Int + ExpectedTransferMsg transfertypes.MsgTransfer + ChannelID string + PortID string +} + +// -------------------------------------------------------------- +// Transfer Host to Trade +// -------------------------------------------------------------- + +func (s *KeeperTestSuite) SetupTransferRewardTokensHostToTradeTestCase() TransferRewardHostToTradeTestCase { + // Create an ICA channel for the transfer submission + owner := types.FormatHostZoneICAOwner(HostChainId, types.ICAAccountType_WITHDRAWAL) + channelId, portId := s.CreateICAChannel(owner) + + // Define components of transfer message + hostToRewardChannelId := "channel-0" + rewardToTradeChannelId := "channel-1" + + rewardDenomOnHostZone := "ibc/reward_on_host" + rewardDenomOnRewardZone := RewardDenom + + withdrawalAddress := "withdrawal_address" + unwindAddress := "unwind_address" + tradeAddress := "trade_address" + + transferAmount := sdk.NewInt(1000) + transferToken := sdk.NewCoin(rewardDenomOnHostZone, transferAmount) + minSwapAmount := sdk.NewInt(500) + + currentTime := s.Ctx.BlockTime() + epochLength := time.Second * 10 // 10 seconds + transfer1TimeoutTimestamp := currentTime.Add(time.Second * 5) // 5 seconds from now (halfway through) + transfer2TimeoutDuration := "5s" + + // Create a trade route with the relevant addresses and transfer channels + route := types.TradeRoute{ + HostToRewardChannelId: hostToRewardChannelId, + RewardToTradeChannelId: rewardToTradeChannelId, + + RewardDenomOnHostZone: rewardDenomOnHostZone, + RewardDenomOnRewardZone: rewardDenomOnRewardZone, + HostDenomOnHostZone: HostDenom, + + HostAccount: types.ICAAccount{ + ChainId: HostChainId, + Address: withdrawalAddress, + ConnectionId: ibctesting.FirstConnectionID, + Type: types.ICAAccountType_WITHDRAWAL, + }, + RewardAccount: types.ICAAccount{ + Address: unwindAddress, + }, + TradeAccount: types.ICAAccount{ + Address: tradeAddress, + }, + + TradeConfig: types.TradeConfig{ + SwapPrice: sdk.OneDec(), + MinSwapAmount: minSwapAmount, + }, + } + + // Create an epoch tracker to dictate the timeout + s.CreateEpochForICATimeout(epochtypes.STRIDE_EPOCH, epochLength) + + // Define the expected transfer message using all the above + memoJSON := fmt.Sprintf(`{"forward":{"receiver":"%s","port":"transfer","channel":"%s","timeout":"%s","retries":0}}`, + tradeAddress, rewardToTradeChannelId, transfer2TimeoutDuration) + + expectedMsg := transfertypes.MsgTransfer{ + SourcePort: transfertypes.PortID, + SourceChannel: hostToRewardChannelId, + Token: transferToken, + Sender: withdrawalAddress, + Receiver: unwindAddress, + TimeoutTimestamp: uint64(transfer1TimeoutTimestamp.UnixNano()), + Memo: memoJSON, + } + + return TransferRewardHostToTradeTestCase{ + TradeRoute: route, + TransferAmount: transferAmount, + ExpectedTransferMsg: expectedMsg, + ChannelID: channelId, + PortID: portId, + } +} + +func (s *KeeperTestSuite) TestBuildHostToTradeTransferMsg_Success() { + tc := s.SetupTransferRewardTokensHostToTradeTestCase() + + // Confirm the generated message matches expectations + actualMsg, err := s.App.StakeibcKeeper.BuildHostToTradeTransferMsg(s.Ctx, tc.TransferAmount, tc.TradeRoute) + s.Require().NoError(err, "no error expected when building transfer message") + s.Require().Equal(tc.ExpectedTransferMsg, actualMsg, "transfer message should have matched") +} + +func (s *KeeperTestSuite) TestBuildHostToTradeTransferMsg_InvalidICAAddress() { + tc := s.SetupTransferRewardTokensHostToTradeTestCase() + + // Check unregisted ICA addresses cause failures + invalidRoute := tc.TradeRoute + invalidRoute.HostAccount.Address = "" + _, err := s.App.StakeibcKeeper.BuildHostToTradeTransferMsg(s.Ctx, tc.TransferAmount, invalidRoute) + s.Require().ErrorContains(err, "no host account found") + + invalidRoute = tc.TradeRoute + invalidRoute.RewardAccount.Address = "" + _, err = s.App.StakeibcKeeper.BuildHostToTradeTransferMsg(s.Ctx, tc.TransferAmount, invalidRoute) + s.Require().ErrorContains(err, "no reward account found") + + invalidRoute = tc.TradeRoute + invalidRoute.TradeAccount.Address = "" + _, err = s.App.StakeibcKeeper.BuildHostToTradeTransferMsg(s.Ctx, tc.TransferAmount, invalidRoute) + s.Require().ErrorContains(err, "no trade account found") +} + +func (s *KeeperTestSuite) TestBuildHostToTradeTransferMsg_EpochNotFound() { + tc := s.SetupTransferRewardTokensHostToTradeTestCase() + + // Delete the epoch tracker and confirm the message cannot be built + s.App.StakeibcKeeper.RemoveEpochTracker(s.Ctx, epochtypes.STRIDE_EPOCH) + + _, err := s.App.StakeibcKeeper.BuildHostToTradeTransferMsg(s.Ctx, tc.TransferAmount, tc.TradeRoute) + s.Require().ErrorContains(err, "epoch not found") +} + +func (s *KeeperTestSuite) TestTransferRewardTokensHostToTrade_Success() { + tc := s.SetupTransferRewardTokensHostToTradeTestCase() + + // Check that the transfer ICA is submitted when the function is called + s.CheckICATxSubmitted(tc.PortID, tc.ChannelID, func() error { + return s.App.StakeibcKeeper.TransferRewardTokensHostToTrade(s.Ctx, tc.TransferAmount, tc.TradeRoute) + }) +} + +func (s *KeeperTestSuite) TestTransferRewardTokensHostToTrade_TransferAmountBelowMin() { + tc := s.SetupTransferRewardTokensHostToTradeTestCase() + + // Attempt to call the function with an transfer amount below the min, + // it should not submit an ICA + invalidTransferAmount := tc.TradeRoute.TradeConfig.MinSwapAmount.Sub(sdkmath.OneInt()) + s.CheckICATxNotSubmitted(tc.PortID, tc.ChannelID, func() error { + return s.App.StakeibcKeeper.TransferRewardTokensHostToTrade(s.Ctx, invalidTransferAmount, tc.TradeRoute) + }) +} + +func (s *KeeperTestSuite) TestTransferRewardTokensHostToTrade_NoPoolPrice() { + tc := s.SetupTransferRewardTokensHostToTradeTestCase() + + // Attempt to call the function with a route that does not have a pool price + // If should not initiate the transfer (since the swap would be unable to execute) + invalidRoute := tc.TradeRoute + invalidRoute.TradeConfig.SwapPrice = sdk.ZeroDec() + + s.CheckICATxNotSubmitted(tc.PortID, tc.ChannelID, func() error { + return s.App.StakeibcKeeper.TransferRewardTokensHostToTrade(s.Ctx, tc.TransferAmount, invalidRoute) + }) +} + +func (s *KeeperTestSuite) TestTransferRewardTokensHostToTrade_FailedToSubmitICA() { + tc := s.SetupTransferRewardTokensHostToTradeTestCase() + + // Remove the connection ID and confirm the ICA submission fails + invalidRoute := tc.TradeRoute + invalidRoute.HostAccount.ConnectionId = "" + + err := s.App.StakeibcKeeper.TransferRewardTokensHostToTrade(s.Ctx, tc.TransferAmount, invalidRoute) + s.Require().ErrorContains(err, "Failed to submit ICA tx") +} + +func (s *KeeperTestSuite) TestTransferRewardTokensHostToTrade_EpochNotFound() { + tc := s.SetupTransferRewardTokensHostToTradeTestCase() + + // Delete the epoch tracker and confirm the transfer cannot be initiated + s.App.StakeibcKeeper.RemoveEpochTracker(s.Ctx, epochtypes.STRIDE_EPOCH) + + err := s.App.StakeibcKeeper.TransferRewardTokensHostToTrade(s.Ctx, tc.TransferAmount, tc.TradeRoute) + s.Require().ErrorContains(err, "epoch not found") +} + +// -------------------------------------------------------------- +// Transfer Trade to Trade +// -------------------------------------------------------------- + +func (s *KeeperTestSuite) TestTransferConvertedTokensTradeToHost() { + transferAmount := sdkmath.NewInt(1000) + + // Register a trade ICA account for the transfer + owner := types.FormatTradeRouteICAOwner(HostChainId, RewardDenom, HostDenom, types.ICAAccountType_CONVERTER_TRADE) + channelId, portId := s.CreateICAChannel(owner) + + // Create trade route with fields needed for transfer + route := types.TradeRoute{ + RewardDenomOnRewardZone: RewardDenom, + HostDenomOnHostZone: HostDenom, + + HostDenomOnTradeZone: "ibc/host-on-trade", + TradeToHostChannelId: "channel-1", + HostAccount: types.ICAAccount{ + Address: "host_address", + }, + TradeAccount: types.ICAAccount{ + ChainId: HostChainId, + Address: "trade_address", + ConnectionId: ibctesting.FirstConnectionID, + Type: types.ICAAccountType_CONVERTER_TRADE, + }, + } + s.App.StakeibcKeeper.SetTradeRoute(s.Ctx, route) + + // Create epoch tracker to dictate timeout + s.CreateEpochForICATimeout(epochtypes.STRIDE_EPOCH, time.Second*10) + + // Confirm the sequence number was incremented after a successful send + startSequence := s.MustGetNextSequenceNumber(portId, channelId) + + err := s.App.StakeibcKeeper.TransferConvertedTokensTradeToHost(s.Ctx, transferAmount, route) + s.Require().NoError(err, "no error expected when transfering tokens") + + endSequence := s.MustGetNextSequenceNumber(portId, channelId) + s.Require().Equal(startSequence+1, endSequence, "sequence number should have incremented from transfer") + + // Attempt to send without a valid ICA address - it should fail + invalidRoute := route + invalidRoute.HostAccount.Address = "" + err = s.App.StakeibcKeeper.TransferConvertedTokensTradeToHost(s.Ctx, transferAmount, invalidRoute) + s.Require().ErrorContains(err, "no host account found") + + invalidRoute = route + invalidRoute.TradeAccount.Address = "" + err = s.App.StakeibcKeeper.TransferConvertedTokensTradeToHost(s.Ctx, transferAmount, invalidRoute) + s.Require().ErrorContains(err, "no trade account found") +} + +// -------------------------------------------------------------- +// Reward Token Swap +// -------------------------------------------------------------- + +func (s *KeeperTestSuite) TestBuildSwapMsg() { + poolId := uint64(100) + tradeAddress := "trade_address" + + rewardDenom := "ibc/reward_on_trade" + hostDenom := "ibc/host_on_trade" + + baseTradeRoute := types.TradeRoute{ + RewardDenomOnTradeZone: rewardDenom, + HostDenomOnTradeZone: hostDenom, + + TradeAccount: types.ICAAccount{ + Address: tradeAddress, + }, + + TradeConfig: types.TradeConfig{ + PoolId: poolId, + }, + } + + testCases := []struct { + name string + price sdk.Dec + maxAllowedSwapLoss sdk.Dec + minSwapAmount sdkmath.Int + maxSwapAmount sdkmath.Int + rewardAmount sdkmath.Int + expectedTradeAmount sdkmath.Int + expectedMinOut sdkmath.Int + expectedError string + }{ + { + // Reward Amount: 100, Min: 0, Max: 200 => Trade Amount: 100 + // Price: 1, Slippage: 5% => Min Out: 95 + name: "swap 1", + price: sdk.MustNewDecFromStr("1.0"), + maxAllowedSwapLoss: sdk.MustNewDecFromStr("0.05"), + + maxSwapAmount: sdkmath.NewInt(200), + rewardAmount: sdkmath.NewInt(100), + expectedTradeAmount: sdkmath.NewInt(100), + + expectedMinOut: sdkmath.NewInt(95), + }, + { + // Reward Amount: 100, Min: 0, Max: 200 => Trade Amount: 100 + // Price: 0.70, Slippage: 10% => Min Out: 100 * 0.70 * 0.9 = 63 + name: "swap 2", + price: sdk.MustNewDecFromStr("0.70"), + maxAllowedSwapLoss: sdk.MustNewDecFromStr("0.10"), + + maxSwapAmount: sdkmath.NewInt(200), + rewardAmount: sdkmath.NewInt(100), + expectedTradeAmount: sdkmath.NewInt(100), + + expectedMinOut: sdkmath.NewInt(63), + }, + { + // Reward Amount: 100, Min: 0, Max: 200 => Trade Amount: 100 + // Price: 1.80, Slippage: 15% => Min Out: 100 * 1.8 * 0.85 = 153 + name: "swap 3", + price: sdk.MustNewDecFromStr("1.8"), + maxAllowedSwapLoss: sdk.MustNewDecFromStr("0.15"), + + maxSwapAmount: sdkmath.NewInt(200), + rewardAmount: sdkmath.NewInt(100), + expectedTradeAmount: sdkmath.NewInt(100), + + expectedMinOut: sdkmath.NewInt(153), + }, + { + // Reward Amount: 200, Min: 0, Max: 100 => Trade Amount: 100 + // Price: 1, Slippage: 5% => Min Out: 95 + name: "capped by max swap amount", + price: sdk.MustNewDecFromStr("1.0"), + maxAllowedSwapLoss: sdk.MustNewDecFromStr("0.05"), + + maxSwapAmount: sdkmath.NewInt(100), + rewardAmount: sdkmath.NewInt(200), + expectedTradeAmount: sdkmath.NewInt(100), + + expectedMinOut: sdkmath.NewInt(95), + }, + { + // Reward Amount: 100, Min: 0, Max: 200 => Trade Amount: 100 + // Price: 1, Slippage: 5.001% => Min Out: 94.999 => truncated to 94 + name: "int truncation in min out caused by decimal max swap allowed", + price: sdk.MustNewDecFromStr("1.0"), + maxAllowedSwapLoss: sdk.MustNewDecFromStr("0.05001"), + + maxSwapAmount: sdkmath.NewInt(200), + rewardAmount: sdkmath.NewInt(100), + expectedTradeAmount: sdkmath.NewInt(100), + + expectedMinOut: sdkmath.NewInt(94), + }, + { + // Reward Amount: 100, Min: 0, Max: 200 => Trade Amount: 100 + // Price: 0.9998, Slippage: 10% => Min Out: 89.991 => truncated to 89 + name: "int truncation in min out caused by decimal price", + price: sdk.MustNewDecFromStr("0.9998"), + maxAllowedSwapLoss: sdk.MustNewDecFromStr("0.10"), + + maxSwapAmount: sdkmath.NewInt(200), + rewardAmount: sdkmath.NewInt(100), + expectedTradeAmount: sdkmath.NewInt(100), + + expectedMinOut: sdkmath.NewInt(89), + }, + { + // Reward Amount: 89234, Min: 0, Max: 23424 => Trade Amount: 23424 + // Price: 15.234323, Slippage: 9.234329% + // => Min Out: 23424 * 15.234323 * 0.90765671 = 323896.19 => truncates to 323896 + name: "int truncation from random numbers", + price: sdk.MustNewDecFromStr("15.234323"), + maxAllowedSwapLoss: sdk.MustNewDecFromStr("0.09234329"), + + maxSwapAmount: sdkmath.NewInt(23424), + rewardAmount: sdkmath.NewInt(89234), + expectedTradeAmount: sdkmath.NewInt(23424), + + expectedMinOut: sdkmath.NewInt(323896), + }, + { + // Missing price + name: "missing price error", + price: sdk.ZeroDec(), + maxAllowedSwapLoss: sdk.MustNewDecFromStr("0"), + + maxSwapAmount: sdkmath.NewInt(0), + rewardAmount: sdkmath.NewInt(0), + expectedTradeAmount: sdkmath.NewInt(0), + expectedMinOut: sdkmath.NewInt(0), + + expectedError: "Price not found for pool", + }, + } + + for _, tc := range testCases { + route := baseTradeRoute + + route.TradeConfig.SwapPrice = tc.price + route.TradeConfig.MinSwapAmount = tc.minSwapAmount + route.TradeConfig.MaxSwapAmount = tc.maxSwapAmount + route.TradeConfig.MaxAllowedSwapLossRate = tc.maxAllowedSwapLoss + + msg, err := s.App.StakeibcKeeper.BuildSwapMsg(tc.rewardAmount, route) + + if tc.expectedError != "" { + s.Require().ErrorContains(err, tc.expectedError, "%s - error expected", tc.name) + continue + } + s.Require().Equal(tradeAddress, msg.Sender, "%s - sender", tc.name) + s.Require().Equal(poolId, msg.Routes[0].PoolId, "%s - pool id", tc.name) + + s.Require().Equal(hostDenom, msg.Routes[0].TokenOutDenom, "%s - token out denom", tc.name) + s.Require().Equal(rewardDenom, msg.TokenIn.Denom, "%s - token in denom", tc.name) + + s.Require().Equal(tc.expectedTradeAmount.Int64(), msg.TokenIn.Amount.Int64(), "%s - token in amount", tc.name) + s.Require().Equal(tc.expectedMinOut.Int64(), msg.TokenOutMinAmount.Int64(), "%s - min token out", tc.name) + } + + // Test with a missing ICA address + invalidRoute := baseTradeRoute + invalidRoute.TradeAccount.Address = "" + _, err := s.App.StakeibcKeeper.BuildSwapMsg(sdk.NewInt(1), invalidRoute) + s.Require().ErrorContains(err, "no trade account found") +} + +func (s *KeeperTestSuite) TestSwapRewardTokens() { + // Create an ICA channel for the transfer submission + owner := types.FormatTradeRouteICAOwner(HostChainId, RewardDenom, HostDenom, types.ICAAccountType_CONVERTER_TRADE) + channelId, portId := s.CreateICAChannel(owner) + + minSwapAmount := sdkmath.NewInt(10) + rewardAmount := sdkmath.NewInt(100) + + route := types.TradeRoute{ + RewardDenomOnRewardZone: RewardDenom, + HostDenomOnHostZone: HostDenom, + + RewardDenomOnTradeZone: "ibc/reward_on_trade", + HostDenomOnTradeZone: "ibc/host_on_trade", + + TradeAccount: types.ICAAccount{ + ChainId: HostChainId, + Address: "trade_address", + ConnectionId: ibctesting.FirstConnectionID, + Type: types.ICAAccountType_CONVERTER_TRADE, + }, + + TradeConfig: types.TradeConfig{ + PoolId: 100, + SwapPrice: sdk.OneDec(), + MinSwapAmount: minSwapAmount, + MaxSwapAmount: sdkmath.NewInt(1000), + MaxAllowedSwapLossRate: sdk.MustNewDecFromStr("0.1"), + }, + } + + // Create an epoch tracker to dictate the timeout + s.CreateEpochForICATimeout(epochtypes.HOUR_EPOCH, time.Minute) // arbitrary timeout time + + // Execute the swap and confirm the sequence number increments + startSequence := s.MustGetNextSequenceNumber(portId, channelId) + + err := s.App.StakeibcKeeper.SwapRewardTokens(s.Ctx, rewardAmount, route) + s.Require().NoError(err, "no error expected when submitting swap") + + sequenceAfterSwap := s.MustGetNextSequenceNumber(portId, channelId) + s.Require().Equal(startSequence+1, sequenceAfterSwap, "sequence number should have incremented") + + // Attempt to call the function again with an swap amount below the min, + // it should not submit an ICA + invalidSwapAmount := minSwapAmount.Sub(sdkmath.OneInt()) + err = s.App.StakeibcKeeper.SwapRewardTokens(s.Ctx, invalidSwapAmount, route) + s.Require().NoError(err, "no error expected when submitting transfer with amount below minimum") + + endSequence := s.MustGetNextSequenceNumber(portId, channelId) + s.Require().Equal(sequenceAfterSwap, endSequence, "sequence number should NOT have incremented") + + // Remove the connection ID so the ICA fails + invalidRoute := route + invalidRoute.TradeAccount.ConnectionId = "" + err = s.App.StakeibcKeeper.SwapRewardTokens(s.Ctx, rewardAmount, invalidRoute) + s.Require().ErrorContains(err, "Failed to submit ICA tx") + + // Delete the epoch tracker and confirm the swap fails + s.App.StakeibcKeeper.RemoveEpochTracker(s.Ctx, epochtypes.HOUR_EPOCH) + err = s.App.StakeibcKeeper.SwapRewardTokens(s.Ctx, rewardAmount, route) + s.Require().ErrorContains(err, "epoch not found") +} + +// -------------------------------------------------------------- +// Trade Route ICQ Test Helpers +// -------------------------------------------------------------- + +// Helper function to validate the address and denom from the query request data +func (s *KeeperTestSuite) validateAddressAndDenomInRequest(data []byte, expectedAddress, expectedDenom string) { + actualAddress, actualDenom := s.ExtractAddressAndDenomFromBankPrefix(data) + s.Require().Equal(expectedAddress, actualAddress, "query account address") + s.Require().Equal(expectedDenom, actualDenom, "query denom") +} + +// Helper function to validate the trade route query callback data +func (s *KeeperTestSuite) validateTradeRouteQueryCallback(actualCallbackDataBz []byte) { + expectedCallbackData := types.TradeRouteCallback{ + RewardDenom: RewardDenom, + HostDenom: HostDenom, + } + + var actualCallbackData types.TradeRouteCallback + err := proto.Unmarshal(actualCallbackDataBz, &actualCallbackData) + s.Require().NoError(err) + s.Require().Equal(expectedCallbackData, actualCallbackData, "query callback data") +} + +// -------------------------------------------------------------- +// Withdrawal Account - Reward Balance Query +// -------------------------------------------------------------- + +// Create the traderoute for these tests, only need the withdrawal address and the +// reward_denom_on_host since this will be what is used in the query, no other setup +func (s *KeeperTestSuite) SetupWithdrawalRewardBalanceQueryTestCase() (route types.TradeRoute, expectedTimeout time.Duration) { + // Create a transfer channel so the connection exists for the query submission + s.CreateTransferChannel(HostChainId) + + // Create and set the trade route + tradeRoute := types.TradeRoute{ + RewardDenomOnRewardZone: RewardDenom, + HostDenomOnHostZone: HostDenom, + RewardDenomOnHostZone: "ibc/reward_on_host", + HostAccount: types.ICAAccount{ + ChainId: HostChainId, + ConnectionId: ibctesting.FirstConnectionID, + Address: StrideICAAddress, // must be a valid bech32, easiest to use stride prefix for validation + }, + } + s.App.StakeibcKeeper.SetTradeRoute(s.Ctx, tradeRoute) + + // Create and set the epoch tracker for timeouts (the timeout is halfway through the epoch) + epochDuration := time.Second * 30 + expectedTimeout = epochDuration / 2 + s.CreateEpochForICATimeout(epochtypes.STRIDE_EPOCH, epochDuration) + + return tradeRoute, expectedTimeout +} + +// Tests a successful WithdrawalRewardBalanceQuery +func (s *KeeperTestSuite) TestWithdrawalRewardBalanceQuery_Successful() { + route, timeoutDuration := s.SetupWithdrawalRewardBalanceQueryTestCase() + + err := s.App.StakeibcKeeper.WithdrawalRewardBalanceQuery(s.Ctx, route) + s.Require().NoError(err, "no error expected when querying balance") + + // Validate fields from ICQ submission + expectedRequestData := s.GetBankStoreKeyPrefix(StrideICAAddress, route.RewardDenomOnHostZone) + + query := s.ValidateQuerySubmission( + icqtypes.BANK_STORE_QUERY_WITH_PROOF, + expectedRequestData, + keeper.ICQCallbackID_WithdrawalRewardBalance, + timeoutDuration, + icqtypes.TimeoutPolicy_REJECT_QUERY_RESPONSE, + ) + + s.validateAddressAndDenomInRequest(query.RequestData, route.HostAccount.Address, route.RewardDenomOnHostZone) + s.validateTradeRouteQueryCallback(query.CallbackData) +} + +// Tests a WithdrawalRewardBalanceQuery that fails due to an invalid account address +func (s *KeeperTestSuite) TestWithdrawalRewardBalanceQuery_Failure_InvalidAccountAddress() { + tradeRoute, _ := s.SetupWithdrawalRewardBalanceQueryTestCase() + + // Change the withdrawal ICA account address to be invalid + tradeRoute.HostAccount.Address = "invalid_address" + + err := s.App.StakeibcKeeper.WithdrawalRewardBalanceQuery(s.Ctx, tradeRoute) + s.Require().ErrorContains(err, "invalid withdrawal account address") +} + +// Tests a WithdrawalRewardBalanceQuery that fails due to a missing epoch tracker +func (s *KeeperTestSuite) TestWithdrawalRewardBalanceQuery_Failure_MissingEpoch() { + tradeRoute, _ := s.SetupWithdrawalRewardBalanceQueryTestCase() + + // Remove the stride epoch so the test fails + s.App.StakeibcKeeper.RemoveEpochTracker(s.Ctx, epochtypes.STRIDE_EPOCH) + + err := s.App.StakeibcKeeper.WithdrawalRewardBalanceQuery(s.Ctx, tradeRoute) + s.Require().ErrorContains(err, "stride_epoch: epoch not found") +} + +// Tests a WithdrawalRewardBalanceQuery that fails to submit the query due to bad connection +func (s *KeeperTestSuite) TestWithdrawalRewardBalanceQuery_FailedQuerySubmission() { + tradeRoute, _ := s.SetupWithdrawalRewardBalanceQueryTestCase() + + // Change the withdrawal ICA connection id to be invalid + tradeRoute.HostAccount.ConnectionId = "invalid_connection" + + err := s.App.StakeibcKeeper.WithdrawalRewardBalanceQuery(s.Ctx, tradeRoute) + s.Require().ErrorContains(err, "invalid connection-id (invalid_connection)") +} + +// -------------------------------------------------------------- +// Trade Account - Reward Balance Query +// -------------------------------------------------------------- + +// Create the traderoute for these tests, only need the trade address and the +// reward_denom_on_trade since this will be what is used in the query, no other setup +func (s *KeeperTestSuite) SetupTradeRewardBalanceQueryTestCase() (route types.TradeRoute, expectedTimeout time.Duration) { + // Create a transfer channel so the connection exists for the query submission + s.CreateTransferChannel(HostChainId) + + // Create and set the trade route + tradeRoute := types.TradeRoute{ + RewardDenomOnRewardZone: RewardDenom, + HostDenomOnHostZone: HostDenom, + RewardDenomOnTradeZone: "ibc/reward_on_trade", + TradeAccount: types.ICAAccount{ + ChainId: HostChainId, + ConnectionId: ibctesting.FirstConnectionID, + Address: StrideICAAddress, // must be a valid bech32, easiest to use stride prefix for validation + }, + } + s.App.StakeibcKeeper.SetTradeRoute(s.Ctx, tradeRoute) + + // Create and set the epoch tracker for timeouts + timeoutDuration := time.Second * 30 + s.CreateEpochForICATimeout(epochtypes.HOUR_EPOCH, timeoutDuration) + + return tradeRoute, timeoutDuration +} + +// Tests a successful TradeRewardBalanceQuery +func (s *KeeperTestSuite) TestTradeRewardBalanceQuery_Successful() { + route, timeoutDuration := s.SetupTradeRewardBalanceQueryTestCase() + + err := s.App.StakeibcKeeper.TradeRewardBalanceQuery(s.Ctx, route) + s.Require().NoError(err, "no error expected when querying balance") + + // Validate fields from ICQ submission + expectedRequestData := s.GetBankStoreKeyPrefix(StrideICAAddress, route.RewardDenomOnTradeZone) + + query := s.ValidateQuerySubmission( + icqtypes.BANK_STORE_QUERY_WITH_PROOF, + expectedRequestData, + keeper.ICQCallbackID_TradeRewardBalance, + timeoutDuration, + icqtypes.TimeoutPolicy_REJECT_QUERY_RESPONSE, + ) + + s.validateAddressAndDenomInRequest(query.RequestData, route.TradeAccount.Address, route.RewardDenomOnTradeZone) + s.validateTradeRouteQueryCallback(query.CallbackData) +} + +// Tests a TradeRewardBalanceQuery that fails due to an invalid account address +func (s *KeeperTestSuite) TestTradeRewardBalanceQuery_Failure_InvalidAccountAddress() { + tradeRoute, _ := s.SetupTradeRewardBalanceQueryTestCase() + + // Change the trade ICA account address to be invalid + tradeRoute.TradeAccount.Address = "invalid_address" + + err := s.App.StakeibcKeeper.TradeRewardBalanceQuery(s.Ctx, tradeRoute) + s.Require().ErrorContains(err, "invalid trade account address") +} + +// Tests a TradeRewardBalanceQuery that fails due to a missing epoch tracker +func (s *KeeperTestSuite) TestTradeRewardBalanceQuery_Failure_MissingEpoch() { + tradeRoute, _ := s.SetupTradeRewardBalanceQueryTestCase() + + // Remove the stride epoch so the test fails + s.App.StakeibcKeeper.RemoveEpochTracker(s.Ctx, epochtypes.HOUR_EPOCH) + + err := s.App.StakeibcKeeper.TradeRewardBalanceQuery(s.Ctx, tradeRoute) + s.Require().ErrorContains(err, "hour: epoch not found") +} + +// Tests a TradeRewardBalanceQuery that fails to submit the query due to bad connection +func (s *KeeperTestSuite) TestTradeRewardBalanceQuery_FailedQuerySubmission() { + tradeRoute, _ := s.SetupTradeRewardBalanceQueryTestCase() + + // Change the trade ICA connection id to be invalid + tradeRoute.TradeAccount.ConnectionId = "invalid_connection" + + err := s.App.StakeibcKeeper.TradeRewardBalanceQuery(s.Ctx, tradeRoute) + s.Require().ErrorContains(err, "invalid connection-id (invalid_connection)") +} + +// -------------------------------------------------------------- +// Trade Account - Converted Balance Query +// -------------------------------------------------------------- + +// Create the traderoute for these tests, only need the trade address and the +// host_denom_on_trade since this will be what is used in the query, no other setup +func (s *KeeperTestSuite) SetupTradeConvertedBalanceQueryTestCase() (route types.TradeRoute, expectedTimeout time.Duration) { + // Create a transfer channel so the connection exists for the query submission + s.CreateTransferChannel(HostChainId) + + // Create and set the trade route + tradeRoute := types.TradeRoute{ + RewardDenomOnRewardZone: RewardDenom, + HostDenomOnHostZone: HostDenom, + HostDenomOnTradeZone: "ibc/host_on_trade", + TradeAccount: types.ICAAccount{ + ChainId: HostChainId, + ConnectionId: ibctesting.FirstConnectionID, + Address: StrideICAAddress, // must be a valid bech32, easiest to use stride prefix for validation + }, + } + s.App.StakeibcKeeper.SetTradeRoute(s.Ctx, tradeRoute) + + // Create and set the epoch tracker for timeouts + timeoutDuration := time.Second * 30 + s.CreateEpochForICATimeout(epochtypes.STRIDE_EPOCH, timeoutDuration) + + return tradeRoute, timeoutDuration +} + +// Tests a successful TradeConvertedBalanceQuery +func (s *KeeperTestSuite) TestTradeConvertedBalanceQuery_Successful() { + route, timeoutDuration := s.SetupTradeConvertedBalanceQueryTestCase() + + err := s.App.StakeibcKeeper.TradeConvertedBalanceQuery(s.Ctx, route) + s.Require().NoError(err, "no error expected when querying balance") + + // Validate fields from ICQ submission + expectedRequestData := s.GetBankStoreKeyPrefix(StrideICAAddress, route.HostDenomOnTradeZone) + + query := s.ValidateQuerySubmission( + icqtypes.BANK_STORE_QUERY_WITH_PROOF, + expectedRequestData, + keeper.ICQCallbackID_TradeConvertedBalance, + timeoutDuration, + icqtypes.TimeoutPolicy_REJECT_QUERY_RESPONSE, + ) + + s.validateAddressAndDenomInRequest(query.RequestData, route.TradeAccount.Address, route.HostDenomOnTradeZone) + s.validateTradeRouteQueryCallback(query.CallbackData) +} + +// Tests a TradeConvertedBalanceQuery that fails due to an invalid account address +func (s *KeeperTestSuite) TestTradeConvertedBalanceQuery_Failure_InvalidAccountAddress() { + tradeRoute, _ := s.SetupTradeConvertedBalanceQueryTestCase() + + // Change the trade ICA account address to be invalid + tradeRoute.TradeAccount.Address = "invalid_address" + + err := s.App.StakeibcKeeper.TradeConvertedBalanceQuery(s.Ctx, tradeRoute) + s.Require().ErrorContains(err, "invalid trade account address") +} + +// Tests a TradeConvertedBalanceQuery that fails due to a missing epoch tracker +func (s *KeeperTestSuite) TestTradeConvertedBalanceQuery_Failure_MissingEpoch() { + tradeRoute, _ := s.SetupTradeConvertedBalanceQueryTestCase() + + // Remove the stride epoch so the test fails + s.App.StakeibcKeeper.RemoveEpochTracker(s.Ctx, epochtypes.STRIDE_EPOCH) + + err := s.App.StakeibcKeeper.TradeConvertedBalanceQuery(s.Ctx, tradeRoute) + s.Require().ErrorContains(err, "stride_epoch: epoch not found") +} + +// Tests a TradeConvertedBalanceQuery that fails to submit the query due to bad connection +func (s *KeeperTestSuite) TestTradeConvertedBalanceQuery_FailedQuerySubmission() { + tradeRoute, _ := s.SetupTradeConvertedBalanceQueryTestCase() + + // Change the trade ICA connection id to be invalid + tradeRoute.TradeAccount.ConnectionId = "invalid_connection" + + err := s.App.StakeibcKeeper.TradeConvertedBalanceQuery(s.Ctx, tradeRoute) + s.Require().ErrorContains(err, "invalid connection-id (invalid_connection)") +} + +// -------------------------------------------------------------- +// Pool Price Query +// -------------------------------------------------------------- + +func (s *KeeperTestSuite) TestPoolPriceQuery() { + // Create a transfer channel so the connection exists for the query submission + s.CreateTransferChannel(HostChainId) + + // Create an epoch tracker to dictate the query timeout + timeoutDuration := time.Minute * 10 + s.CreateEpochForICATimeout(epochtypes.HOUR_EPOCH, timeoutDuration) + + // Define the trade route + poolId := uint64(100) + tradeRewardDenom := "ibc/reward-denom-on-trade" + tradeHostDenom := "ibc/reward-denom-on-host" + + route := types.TradeRoute{ + RewardDenomOnRewardZone: RewardDenom, + HostDenomOnHostZone: HostDenom, + RewardDenomOnTradeZone: tradeRewardDenom, + HostDenomOnTradeZone: tradeHostDenom, + + TradeAccount: types.ICAAccount{ + ChainId: HostChainId, + ConnectionId: ibctesting.FirstConnectionID, + }, + TradeConfig: types.TradeConfig{ + PoolId: poolId, + }, + } + + expectedCallbackData := types.TradeRouteCallback{ + RewardDenom: RewardDenom, + HostDenom: HostDenom, + } + + // Submit the pool price ICQ + err := s.App.StakeibcKeeper.PoolPriceQuery(s.Ctx, route) + s.Require().NoError(err, "no error expected when submitting pool price query") + + // Confirm the query request key is the same regardless of which order the denom's are specified + expectedRequestData := icqtypes.FormatOsmosisMostRecentTWAPKey(poolId, tradeRewardDenom, tradeHostDenom) + expectedRequestDataSwapped := icqtypes.FormatOsmosisMostRecentTWAPKey(poolId, tradeHostDenom, tradeRewardDenom) + s.Require().Equal(expectedRequestData, expectedRequestDataSwapped, "osmosis twap denoms should be sorted") + + // Validate the fields of the query + query := s.ValidateQuerySubmission( + icqtypes.TWAP_STORE_QUERY_WITH_PROOF, + expectedRequestData, + keeper.ICQCallbackID_PoolPrice, + timeoutDuration, + icqtypes.TimeoutPolicy_REJECT_QUERY_RESPONSE, + ) + + // Validate the query callback data + var actualCallbackData types.TradeRouteCallback + err = proto.Unmarshal(query.CallbackData, &actualCallbackData) + s.Require().NoError(err) + s.Require().Equal(expectedCallbackData, actualCallbackData, "query callback data") + + // Remove the connection ID from the trade account and confirm the query submission fails + invalidRoute := route + invalidRoute.TradeAccount.ConnectionId = "" + err = s.App.StakeibcKeeper.PoolPriceQuery(s.Ctx, invalidRoute) + s.Require().ErrorContains(err, "invalid interchain query request") + + // Remove the epoch tracker so the function fails to get a timeout + s.App.StakeibcKeeper.RemoveEpochTracker(s.Ctx, epochtypes.HOUR_EPOCH) + err = s.App.StakeibcKeeper.PoolPriceQuery(s.Ctx, route) + s.Require().ErrorContains(err, "hour: epoch not found") +} diff --git a/x/stakeibc/keeper/trade_route.go b/x/stakeibc/keeper/trade_route.go new file mode 100644 index 000000000..181e6eeea --- /dev/null +++ b/x/stakeibc/keeper/trade_route.go @@ -0,0 +1,53 @@ +package keeper + +import ( + "github.com/cosmos/cosmos-sdk/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/Stride-Labs/stride/v16/x/stakeibc/types" +) + +// SetTradeRoute set a specific tradeRoute in the store +func (k Keeper) SetTradeRoute(ctx sdk.Context, tradeRoute types.TradeRoute) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.TradeRouteKeyPrefix)) + key := tradeRoute.GetKey() + b := k.cdc.MustMarshal(&tradeRoute) + store.Set(key, b) +} + +// GetTradeRoute returns a tradeRoute from its start and end denoms +// The start and end denom's are in their native format (e.g. uusdc and udydx) +func (k Keeper) GetTradeRoute(ctx sdk.Context, rewardDenom string, hostDenom string) (val types.TradeRoute, found bool) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.TradeRouteKeyPrefix)) + key := types.TradeRouteKeyFromDenoms(rewardDenom, hostDenom) + b := store.Get(key) + if len(b) == 0 { + return val, false + } + k.cdc.MustUnmarshal(b, &val) + return val, true +} + +// RemoveTradeRoute removes a tradeRoute from the store +// The start and end denom's are in their native format (e.g. uusdc and udydx) +func (k Keeper) RemoveTradeRoute(ctx sdk.Context, rewardDenom string, hostDenom string) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.TradeRouteKeyPrefix)) + key := types.TradeRouteKeyFromDenoms(rewardDenom, hostDenom) + store.Delete(key) +} + +// GetAllTradeRoute returns all tradeRoutes +func (k Keeper) GetAllTradeRoutes(ctx sdk.Context) (list []types.TradeRoute) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.TradeRouteKeyPrefix)) + iterator := sdk.KVStorePrefixIterator(store, []byte{}) + + defer iterator.Close() + + for ; iterator.Valid(); iterator.Next() { + var val types.TradeRoute + k.cdc.MustUnmarshal(iterator.Value(), &val) + list = append(list, val) + } + + return +} diff --git a/x/stakeibc/keeper/trade_route_test.go b/x/stakeibc/keeper/trade_route_test.go new file mode 100644 index 000000000..b7e85a3fe --- /dev/null +++ b/x/stakeibc/keeper/trade_route_test.go @@ -0,0 +1,98 @@ +package keeper_test + +import ( + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/Stride-Labs/stride/v16/x/stakeibc/types" +) + +func (s *KeeperTestSuite) CreateTradeRoutes() (routes []types.TradeRoute) { + for i := 1; i <= 5; i++ { + hostChain := fmt.Sprintf("chain-H%d", i) + rewardChain := fmt.Sprintf("chain-R%d", i) + tradeChain := fmt.Sprintf("chain-T%d", i) + + hostICA := types.ICAAccount{ + ChainId: hostChain, + Type: types.ICAAccountType_WITHDRAWAL, + ConnectionId: fmt.Sprintf("connection-0%d", i), + Address: "host_ica_address", + } + rewardICA := types.ICAAccount{ + ChainId: rewardChain, + Type: types.ICAAccountType_CONVERTER_UNWIND, + ConnectionId: fmt.Sprintf("connection-1%d", i), + Address: "reward_ica_address", + } + tradeICA := types.ICAAccount{ + ChainId: tradeChain, + Type: types.ICAAccountType_CONVERTER_TRADE, + ConnectionId: fmt.Sprintf("connection-2%d", i), + Address: "trade_ica_address", + } + + tradeConfig := types.TradeConfig{ + PoolId: uint64(i * 100), + SwapPrice: sdk.OneDec(), + MaxAllowedSwapLossRate: sdk.MustNewDecFromStr("0.05"), + + MinSwapAmount: sdk.ZeroInt(), + MaxSwapAmount: sdk.NewInt(1_000_000_000), + } + + hostDenom := fmt.Sprintf("host-denom-%d", i) + rewardDenom := fmt.Sprintf("reward-denom-%d", i) + + route := types.TradeRoute{ + RewardDenomOnHostZone: "ibc-" + rewardDenom + "-on-" + hostChain, + RewardDenomOnRewardZone: rewardDenom, + RewardDenomOnTradeZone: "ibc-" + rewardDenom + "-on-" + tradeChain, + HostDenomOnTradeZone: "ibc-" + hostDenom + "-on-" + tradeChain, + HostDenomOnHostZone: hostDenom, + + HostAccount: hostICA, + RewardAccount: rewardICA, + TradeAccount: tradeICA, + + HostToRewardChannelId: fmt.Sprintf("channel-0%d", i), + RewardToTradeChannelId: fmt.Sprintf("channel-1%d", i), + TradeToHostChannelId: fmt.Sprintf("channel-2%d", i), + + TradeConfig: tradeConfig, + } + routes = append(routes, route) + + s.App.StakeibcKeeper.SetTradeRoute(s.Ctx, route) + } + + return routes +} + +func (s *KeeperTestSuite) TestGetTradeRoute() { + routes := s.CreateTradeRoutes() + for i, route := range routes { + rewardDenom := route.RewardDenomOnRewardZone + hostDenom := route.HostDenomOnHostZone + + actualRoute, found := s.App.StakeibcKeeper.GetTradeRoute(s.Ctx, rewardDenom, hostDenom) + s.Require().True(found, "route should have been found") + s.Require().Equal(routes[i], actualRoute, "route doesn't match") + } +} + +func (s *KeeperTestSuite) TestRemoveTradeRoute() { + routes := s.CreateTradeRoutes() + for _, route := range routes { + s.App.StakeibcKeeper.RemoveTradeRoute(s.Ctx, route.RewardDenomOnRewardZone, route.HostDenomOnHostZone) + _, found := s.App.StakeibcKeeper.GetTradeRoute(s.Ctx, route.RewardDenomOnRewardZone, route.HostDenomOnHostZone) + s.Require().False(found, "route should not have been found") + } +} + +func (s *KeeperTestSuite) TestGetAllTradeRoutes() { + expectedRoutes := s.CreateTradeRoutes() + actualRoutes := s.App.StakeibcKeeper.GetAllTradeRoutes(s.Ctx) + s.Require().ElementsMatch(expectedRoutes, actualRoutes) +} diff --git a/x/stakeibc/keeper/transfer_test.go b/x/stakeibc/keeper/transfer_test.go index c6f530922..01b8080bd 100644 --- a/x/stakeibc/keeper/transfer_test.go +++ b/x/stakeibc/keeper/transfer_test.go @@ -24,7 +24,7 @@ type TransferCommunityPoolDepositToHoldingTestCase struct { } func (s *KeeperTestSuite) SetupTransferCommunityPoolDepositToHolding() TransferCommunityPoolDepositToHoldingTestCase { - owner := types.FormatICAAccountOwner(chainId, types.ICAAccountType_COMMUNITY_POOL_DEPOSIT) + owner := types.FormatHostZoneICAOwner(chainId, types.ICAAccountType_COMMUNITY_POOL_DEPOSIT) channelId, portId := s.CreateICAChannel(owner) holdingAddress := s.TestAccs[0].String() @@ -93,11 +93,11 @@ func (s *KeeperTestSuite) TestTransferCommunityPoolDepositToHolding_MissingDepos func (s *KeeperTestSuite) TestTransferCommunityPoolDepositToHolding_ConnectionSendFail() { tc := s.SetupTransferCommunityPoolDepositToHolding() - tc.hostZone.ConnectionId = "MissingChannel" + tc.hostZone.ConnectionId = "MissingConnection" // Verify that the ICA msg was successfully sent off err := s.App.StakeibcKeeper.TransferCommunityPoolDepositToHolding(s.Ctx, tc.hostZone, tc.coin) - s.Require().ErrorContains(err, "invalid connection id") + s.Require().ErrorContains(err, "connection MissingConnection not found") } type TransferHoldingToCommunityPoolReturnTestCase struct { diff --git a/x/stakeibc/keeper/unbonding_records_get_host_zone_unbondings_msgs_test.go b/x/stakeibc/keeper/unbonding_records_get_host_zone_unbondings_msgs_test.go index 4148b1ada..15e2b3688 100644 --- a/x/stakeibc/keeper/unbonding_records_get_host_zone_unbondings_msgs_test.go +++ b/x/stakeibc/keeper/unbonding_records_get_host_zone_unbondings_msgs_test.go @@ -35,7 +35,7 @@ func (s *KeeperTestSuite) SetupTestUnbondFromHostZone( unbondAmount sdkmath.Int, validators []*types.Validator, ) UnbondingTestCase { - delegationAccountOwner := types.FormatICAAccountOwner(HostChainId, types.ICAAccountType_DELEGATION) + delegationAccountOwner := types.FormatHostZoneICAOwner(HostChainId, types.ICAAccountType_DELEGATION) delegationChannelID, delegationPortID := s.CreateICAChannel(delegationAccountOwner) // Sanity checks: diff --git a/x/stakeibc/keeper/undelegate_host_test.go b/x/stakeibc/keeper/undelegate_host_test.go index e90dda9a7..4c82a84a3 100644 --- a/x/stakeibc/keeper/undelegate_host_test.go +++ b/x/stakeibc/keeper/undelegate_host_test.go @@ -22,7 +22,7 @@ func (s *KeeperTestSuite) SetupTestUndelegateHost( unbondAmount sdkmath.Int, validators []*types.Validator, ) UnbondingTestCase { - delegationAccountOwner := types.FormatICAAccountOwner(UndelegateHostZoneChainId, types.ICAAccountType_DELEGATION) + delegationAccountOwner := types.FormatHostZoneICAOwner(UndelegateHostZoneChainId, types.ICAAccountType_DELEGATION) delegationChannelID, delegationPortID := s.CreateICAChannel(delegationAccountOwner) // Sanity checks: diff --git a/x/stakeibc/types/callbacks.pb.go b/x/stakeibc/types/callbacks.pb.go index df6f758ae..18652683b 100644 --- a/x/stakeibc/types/callbacks.pb.go +++ b/x/stakeibc/types/callbacks.pb.go @@ -743,6 +743,58 @@ func (m *CommunityPoolBalanceQueryCallback) GetDenom() string { return "" } +type TradeRouteCallback struct { + RewardDenom string `protobuf:"bytes,1,opt,name=reward_denom,json=rewardDenom,proto3" json:"reward_denom,omitempty"` + HostDenom string `protobuf:"bytes,2,opt,name=host_denom,json=hostDenom,proto3" json:"host_denom,omitempty"` +} + +func (m *TradeRouteCallback) Reset() { *m = TradeRouteCallback{} } +func (m *TradeRouteCallback) String() string { return proto.CompactTextString(m) } +func (*TradeRouteCallback) ProtoMessage() {} +func (*TradeRouteCallback) Descriptor() ([]byte, []int) { + return fileDescriptor_f41c99b09b96a5ac, []int{14} +} +func (m *TradeRouteCallback) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *TradeRouteCallback) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_TradeRouteCallback.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 *TradeRouteCallback) XXX_Merge(src proto.Message) { + xxx_messageInfo_TradeRouteCallback.Merge(m, src) +} +func (m *TradeRouteCallback) XXX_Size() int { + return m.Size() +} +func (m *TradeRouteCallback) XXX_DiscardUnknown() { + xxx_messageInfo_TradeRouteCallback.DiscardUnknown(m) +} + +var xxx_messageInfo_TradeRouteCallback proto.InternalMessageInfo + +func (m *TradeRouteCallback) GetRewardDenom() string { + if m != nil { + return m.RewardDenom + } + return "" +} + +func (m *TradeRouteCallback) GetHostDenom() string { + if m != nil { + return m.HostDenom + } + return "" +} + func init() { proto.RegisterType((*SplitDelegation)(nil), "stride.stakeibc.SplitDelegation") proto.RegisterType((*DelegateCallback)(nil), "stride.stakeibc.DelegateCallback") @@ -758,70 +810,73 @@ func init() { proto.RegisterType((*ValidatorSharesToTokensQueryCallback)(nil), "stride.stakeibc.ValidatorSharesToTokensQueryCallback") proto.RegisterType((*DelegatorSharesQueryCallback)(nil), "stride.stakeibc.DelegatorSharesQueryCallback") proto.RegisterType((*CommunityPoolBalanceQueryCallback)(nil), "stride.stakeibc.CommunityPoolBalanceQueryCallback") + proto.RegisterType((*TradeRouteCallback)(nil), "stride.stakeibc.TradeRouteCallback") } func init() { proto.RegisterFile("stride/stakeibc/callbacks.proto", fileDescriptor_f41c99b09b96a5ac) } var fileDescriptor_f41c99b09b96a5ac = []byte{ - // 913 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0xcd, 0x6e, 0xdc, 0x36, - 0x17, 0xb5, 0x3c, 0xf9, 0x62, 0xfb, 0x7a, 0xfc, 0x27, 0x04, 0xf9, 0xc6, 0x83, 0xc1, 0x8c, 0xad, - 0x14, 0x6d, 0x50, 0x20, 0x12, 0xec, 0x02, 0x41, 0x7f, 0x36, 0xb1, 0xc7, 0x28, 0x32, 0xc0, 0xb8, - 0x68, 0x35, 0x76, 0x17, 0xd9, 0x08, 0x94, 0x48, 0xcc, 0x10, 0x96, 0xc8, 0x89, 0x48, 0x39, 0x75, - 0x9e, 0xa0, 0xcb, 0x6c, 0xfb, 0x08, 0xed, 0xa6, 0x4f, 0xd0, 0x4d, 0x57, 0x59, 0x66, 0x59, 0x74, - 0x91, 0x16, 0xf6, 0x8b, 0x14, 0xa4, 0xa8, 0x9f, 0x19, 0xa7, 0x41, 0xed, 0x76, 0x25, 0xe9, 0xf2, - 0x90, 0xf7, 0x9e, 0x73, 0x78, 0x49, 0x41, 0x4f, 0xc8, 0x94, 0x62, 0xe2, 0x09, 0x89, 0xce, 0x08, - 0x0d, 0x23, 0x2f, 0x42, 0x71, 0x1c, 0xa2, 0xe8, 0x4c, 0xb8, 0xd3, 0x94, 0x4b, 0x6e, 0x6f, 0xe4, - 0x00, 0xb7, 0x00, 0xb4, 0xef, 0x8d, 0xf9, 0x98, 0xeb, 0x31, 0x4f, 0xbd, 0xe5, 0xb0, 0x76, 0x37, - 0xe2, 0x22, 0xe1, 0xc2, 0x0b, 0x91, 0x20, 0xde, 0xf9, 0x5e, 0x48, 0x24, 0xda, 0xf3, 0x22, 0x4e, - 0x99, 0x19, 0xef, 0x98, 0x3c, 0x29, 0x89, 0x78, 0x8a, 0x45, 0xf1, 0x34, 0xa3, 0xd7, 0xaa, 0x98, - 0x70, 0x21, 0x83, 0x97, 0x9c, 0x91, 0xbf, 0x03, 0x9c, 0xa3, 0x98, 0x62, 0x24, 0x79, 0x6a, 0x00, - 0xbb, 0xf3, 0x00, 0x1a, 0xa1, 0x00, 0x45, 0x11, 0xcf, 0x98, 0xcc, 0x21, 0xce, 0x0b, 0xd8, 0x18, - 0x4d, 0x63, 0x2a, 0x8f, 0x48, 0x4c, 0xc6, 0x48, 0x52, 0xce, 0xec, 0x0e, 0xac, 0x94, 0x0b, 0xb5, - 0xac, 0x1d, 0xeb, 0xe1, 0x8a, 0x5f, 0x05, 0xec, 0x2f, 0xe1, 0x2e, 0x4a, 0xd4, 0x02, 0xad, 0x45, - 0x35, 0x74, 0xe8, 0xbe, 0x7e, 0xdb, 0x5b, 0xf8, 0xfd, 0x6d, 0xef, 0xc3, 0x31, 0x95, 0x93, 0x2c, - 0x74, 0x23, 0x9e, 0x78, 0x86, 0x76, 0xfe, 0x78, 0x24, 0xf0, 0x99, 0x27, 0x2f, 0xa6, 0x44, 0xb8, - 0x03, 0x26, 0x7d, 0x33, 0xdb, 0xf9, 0xd9, 0x82, 0x4d, 0x93, 0x94, 0xf4, 0x8d, 0xbc, 0xf6, 0x0e, - 0x34, 0x4b, 0x92, 0x01, 0xc5, 0x26, 0x3b, 0xa8, 0xd8, 0x33, 0xce, 0xc8, 0x00, 0xdb, 0x1f, 0xc3, - 0x16, 0x26, 0x53, 0x2e, 0xa8, 0x0c, 0x72, 0xb5, 0x14, 0x4c, 0x55, 0x72, 0xc7, 0xdf, 0x30, 0x03, - 0xbe, 0x8e, 0x0f, 0xb0, 0x7d, 0x0c, 0x5b, 0x42, 0x71, 0x0b, 0x70, 0x49, 0x4e, 0xb4, 0x1a, 0x3b, - 0x8d, 0x87, 0xab, 0xfb, 0x3b, 0xee, 0x9c, 0x83, 0xee, 0x9c, 0x0a, 0xfe, 0xa6, 0x98, 0x0d, 0x08, - 0xe7, 0x7b, 0x0b, 0xd6, 0xfa, 0x31, 0xa2, 0x49, 0x59, 0xee, 0x67, 0xb0, 0x9d, 0x09, 0x92, 0x06, - 0x29, 0xc1, 0x24, 0x99, 0x2a, 0x54, 0xad, 0xa8, 0xbc, 0xf6, 0xfb, 0x0a, 0xe0, 0x97, 0xe3, 0x65, - 0x6d, 0xdb, 0xb0, 0x1c, 0x4d, 0x10, 0x65, 0x45, 0xf9, 0x2b, 0xfe, 0x92, 0xfe, 0x1e, 0x60, 0x7b, - 0x17, 0x9a, 0x64, 0xca, 0xa3, 0x49, 0xc0, 0xb2, 0x24, 0x24, 0x69, 0xab, 0xa1, 0xd9, 0xad, 0xea, - 0xd8, 0x57, 0x3a, 0xe4, 0xfc, 0x68, 0xc1, 0xa6, 0x4f, 0x28, 0x3b, 0x27, 0x42, 0x96, 0xd5, 0x08, - 0xd8, 0x48, 0x4d, 0x2c, 0x30, 0x16, 0xa9, 0x1a, 0x56, 0xf7, 0xb7, 0xdd, 0xdc, 0x09, 0x57, 0xed, - 0x43, 0xd7, 0xec, 0x43, 0xb7, 0xcf, 0x29, 0x3b, 0xf4, 0x94, 0x7b, 0x3f, 0xfd, 0xd1, 0xfb, 0xe8, - 0x1f, 0xb8, 0xa7, 0x26, 0xf8, 0xeb, 0x45, 0x8a, 0x03, 0x9d, 0xe1, 0x9a, 0x63, 0x8d, 0x79, 0xc7, - 0x9c, 0x5f, 0x2d, 0xb0, 0x4f, 0x19, 0xbe, 0xb9, 0xd5, 0xef, 0xb4, 0x6f, 0xf1, 0xb6, 0xf6, 0xd9, - 0x5f, 0x40, 0x3b, 0x97, 0x35, 0x63, 0x21, 0x67, 0x98, 0xb2, 0x71, 0x65, 0x56, 0xbe, 0x2d, 0xee, - 0xf8, 0xff, 0xd7, 0x88, 0xd3, 0x02, 0x50, 0xb8, 0x25, 0x94, 0xe0, 0xf7, 0x2b, 0x12, 0x4f, 0x79, - 0x4d, 0xf6, 0x27, 0xd0, 0x40, 0x49, 0x2e, 0xf5, 0xcd, 0xbb, 0x41, 0x4d, 0xfd, 0x8f, 0x89, 0x3a, - 0x02, 0xec, 0x6a, 0xc3, 0xdd, 0x40, 0xef, 0xf7, 0x0b, 0xb4, 0xf8, 0x7e, 0x81, 0x7e, 0xb0, 0x60, - 0xd5, 0x27, 0x21, 0x8a, 0x11, 0x8b, 0x28, 0x1b, 0xdb, 0x0f, 0x60, 0x4d, 0xa4, 0x51, 0x30, 0x7f, - 0x90, 0x34, 0x45, 0x1a, 0x7d, 0x5b, 0x9e, 0x25, 0x0f, 0x60, 0x0d, 0x0b, 0x59, 0x03, 0xe5, 0x9d, - 0xd0, 0xc4, 0x42, 0x56, 0x20, 0xa3, 0x6f, 0xe3, 0xd6, 0xfa, 0x3a, 0x2f, 0x60, 0xab, 0x28, 0xed, - 0x26, 0xfb, 0xef, 0x09, 0x34, 0xd3, 0x8a, 0x51, 0xe1, 0x48, 0xe7, 0x9a, 0x23, 0x35, 0xda, 0xfe, - 0xcc, 0x0c, 0xe7, 0x14, 0x5a, 0x47, 0x44, 0xf2, 0x33, 0xc2, 0xe8, 0x4b, 0x32, 0x9a, 0xa0, 0x94, - 0x88, 0xda, 0xd9, 0xb1, 0x64, 0xce, 0x2b, 0xd3, 0xa5, 0xbd, 0x62, 0xe1, 0xe2, 0x16, 0x18, 0x8e, - 0x8e, 0x4f, 0xd4, 0xdc, 0x23, 0x73, 0xac, 0x15, 0x78, 0xe7, 0x17, 0x0b, 0xd6, 0x87, 0xa3, 0xe3, - 0x21, 0x7d, 0x9e, 0x51, 0x3c, 0x52, 0x65, 0xfc, 0x8b, 0xd5, 0xec, 0xc7, 0xb0, 0x52, 0x0a, 0xa1, - 0x0d, 0x50, 0x07, 0xc6, 0x3c, 0xc7, 0xa7, 0x46, 0x16, 0x7f, 0xb9, 0x10, 0xc8, 0xfe, 0xb4, 0x7e, - 0x4d, 0x34, 0xf4, 0xbc, 0xf6, 0xb5, 0x79, 0xa5, 0x8d, 0xb5, 0x2b, 0xc4, 0x79, 0x0e, 0x1f, 0x94, - 0xf1, 0x5c, 0x95, 0x13, 0xae, 0x6b, 0x13, 0xdf, 0x64, 0x24, 0xbd, 0x28, 0x25, 0x1a, 0xc0, 0x66, - 0x2c, 0x92, 0x20, 0xd6, 0x3c, 0x03, 0xbd, 0xe6, 0x3c, 0xbb, 0x32, 0xd1, 0xac, 0x1e, 0xfe, 0x7a, - 0x2c, 0x92, 0xda, 0xb7, 0xf3, 0xca, 0x82, 0x8e, 0xe9, 0x91, 0x22, 0xe7, 0x6c, 0xae, 0x29, 0x74, - 0x28, 0xa3, 0x92, 0xa2, 0xb8, 0xda, 0x8e, 0xb5, 0x7e, 0xbc, 0x65, 0x7b, 0xb7, 0xcd, 0x9a, 0x25, - 0xdd, 0xaa, 0x4f, 0x9d, 0x0c, 0x76, 0xfb, 0x3c, 0x49, 0x32, 0x46, 0xe5, 0xc5, 0xd7, 0x9c, 0xc7, - 0x87, 0xf9, 0x06, 0x9d, 0x2d, 0xeb, 0x73, 0x58, 0x56, 0x77, 0xb6, 0x5a, 0x51, 0x97, 0xb0, 0xfe, - 0x0e, 0xea, 0x83, 0xfe, 0xc1, 0x41, 0x7e, 0xa7, 0x9f, 0x5c, 0x4c, 0x89, 0xbf, 0x44, 0x23, 0xa4, - 0x5e, 0xec, 0x7b, 0xf0, 0x3f, 0x4c, 0x18, 0x4f, 0x4c, 0x57, 0xe5, 0x1f, 0x87, 0xc3, 0xd7, 0x97, - 0x5d, 0xeb, 0xcd, 0x65, 0xd7, 0xfa, 0xf3, 0xb2, 0x6b, 0xbd, 0xba, 0xea, 0x2e, 0xbc, 0xb9, 0xea, - 0x2e, 0xfc, 0x76, 0xd5, 0x5d, 0x78, 0xb6, 0x5f, 0x23, 0x35, 0xd2, 0x39, 0x1e, 0x0d, 0x51, 0x28, - 0x3c, 0xf3, 0x13, 0x71, 0xbe, 0xf7, 0xd8, 0xfb, 0xae, 0xfa, 0x95, 0xd0, 0x24, 0xc3, 0xbb, 0xfa, - 0x2f, 0xe2, 0x93, 0xbf, 0x02, 0x00, 0x00, 0xff, 0xff, 0x60, 0x7b, 0xe9, 0xf9, 0x32, 0x09, 0x00, - 0x00, + // 953 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0xcf, 0x6e, 0xdb, 0xc6, + 0x13, 0x36, 0xad, 0xfc, 0x62, 0x7b, 0x24, 0xff, 0x23, 0x82, 0xfc, 0x64, 0x41, 0x95, 0x6c, 0xa6, + 0x68, 0x83, 0x02, 0x21, 0x61, 0x17, 0x08, 0xfa, 0xe7, 0x12, 0x5b, 0x46, 0x11, 0x01, 0x72, 0xd1, + 0x52, 0x76, 0x0e, 0xb9, 0x10, 0x4b, 0xee, 0x42, 0x5a, 0x98, 0xdc, 0x55, 0xb8, 0x4b, 0xbb, 0xce, + 0x13, 0xf4, 0x98, 0x6b, 0x1f, 0xa1, 0xbd, 0xf4, 0x09, 0x7a, 0xe9, 0x29, 0xc7, 0x1c, 0x8b, 0x1e, + 0xd2, 0xc2, 0x7e, 0x91, 0x62, 0x97, 0x4b, 0x8a, 0x92, 0xd3, 0xa0, 0x76, 0x7b, 0x22, 0x39, 0x3b, + 0x3b, 0xf3, 0xcd, 0xf7, 0xcd, 0xec, 0x12, 0xba, 0x42, 0xa6, 0x14, 0x13, 0x4f, 0x48, 0x74, 0x4a, + 0x68, 0x18, 0x79, 0x11, 0x8a, 0xe3, 0x10, 0x45, 0xa7, 0xc2, 0x9d, 0xa4, 0x5c, 0x72, 0x7b, 0x3d, + 0x77, 0x70, 0x0b, 0x87, 0xd6, 0xbd, 0x11, 0x1f, 0x71, 0xbd, 0xe6, 0xa9, 0xb7, 0xdc, 0xad, 0xd5, + 0x89, 0xb8, 0x48, 0xb8, 0xf0, 0x42, 0x24, 0x88, 0x77, 0xb6, 0x1b, 0x12, 0x89, 0x76, 0xbd, 0x88, + 0x53, 0x66, 0xd6, 0xdb, 0x26, 0x4f, 0x4a, 0x22, 0x9e, 0x62, 0x51, 0x3c, 0xcd, 0xea, 0x35, 0x14, + 0x63, 0x2e, 0x64, 0xf0, 0x92, 0x33, 0xf2, 0x77, 0x0e, 0x67, 0x28, 0xa6, 0x18, 0x49, 0x9e, 0x1a, + 0x87, 0x9d, 0x79, 0x07, 0x1a, 0xa1, 0x00, 0x45, 0x11, 0xcf, 0x98, 0xcc, 0x5d, 0x9c, 0x73, 0x58, + 0x1f, 0x4e, 0x62, 0x2a, 0x0f, 0x49, 0x4c, 0x46, 0x48, 0x52, 0xce, 0xec, 0x36, 0xac, 0x94, 0x81, + 0x9a, 0xd6, 0xb6, 0xf5, 0x70, 0xc5, 0x9f, 0x1a, 0xec, 0xaf, 0xe0, 0x2e, 0x4a, 0x54, 0x80, 0xe6, + 0xa2, 0x5a, 0x3a, 0x70, 0x5f, 0xbf, 0xed, 0x2e, 0xfc, 0xfe, 0xb6, 0xfb, 0xd1, 0x88, 0xca, 0x71, + 0x16, 0xba, 0x11, 0x4f, 0x3c, 0x53, 0x76, 0xfe, 0x78, 0x24, 0xf0, 0xa9, 0x27, 0x2f, 0x26, 0x44, + 0xb8, 0x7d, 0x26, 0x7d, 0xb3, 0xdb, 0xf9, 0xd9, 0x82, 0x0d, 0x93, 0x94, 0xf4, 0x0c, 0xbd, 0xf6, + 0x36, 0x34, 0xca, 0x22, 0x03, 0x8a, 0x4d, 0x76, 0x50, 0xb6, 0xe7, 0x9c, 0x91, 0x3e, 0xb6, 0x3f, + 0x81, 0x4d, 0x4c, 0x26, 0x5c, 0x50, 0x19, 0xe4, 0x6c, 0x29, 0x37, 0x85, 0xe4, 0x8e, 0xbf, 0x6e, + 0x16, 0x7c, 0x6d, 0xef, 0x63, 0xfb, 0x08, 0x36, 0x85, 0xaa, 0x2d, 0xc0, 0x65, 0x71, 0xa2, 0x59, + 0xdb, 0xae, 0x3d, 0xac, 0xef, 0x6d, 0xbb, 0x73, 0x0a, 0xba, 0x73, 0x2c, 0xf8, 0x1b, 0x62, 0xd6, + 0x20, 0x9c, 0xef, 0x2d, 0x58, 0xed, 0xc5, 0x88, 0x26, 0x25, 0xdc, 0xcf, 0x61, 0x2b, 0x13, 0x24, + 0x0d, 0x52, 0x82, 0x49, 0x32, 0x51, 0x5e, 0x15, 0x50, 0x39, 0xf6, 0xfb, 0xca, 0xc1, 0x2f, 0xd7, + 0x4b, 0x6c, 0x5b, 0xb0, 0x1c, 0x8d, 0x11, 0x65, 0x05, 0xfc, 0x15, 0x7f, 0x49, 0x7f, 0xf7, 0xb1, + 0xbd, 0x03, 0x0d, 0x32, 0xe1, 0xd1, 0x38, 0x60, 0x59, 0x12, 0x92, 0xb4, 0x59, 0xd3, 0xd5, 0xd5, + 0xb5, 0xed, 0x6b, 0x6d, 0x72, 0x7e, 0xb4, 0x60, 0xc3, 0x27, 0x94, 0x9d, 0x11, 0x21, 0x4b, 0x34, + 0x02, 0xd6, 0x53, 0x63, 0x0b, 0x8c, 0x44, 0x0a, 0x43, 0x7d, 0x6f, 0xcb, 0xcd, 0x95, 0x70, 0x55, + 0x1f, 0xba, 0xa6, 0x0f, 0xdd, 0x1e, 0xa7, 0xec, 0xc0, 0x53, 0xea, 0xfd, 0xf4, 0x47, 0xf7, 0xe3, + 0x7f, 0xa0, 0x9e, 0xda, 0xe0, 0xaf, 0x15, 0x29, 0xf6, 0x75, 0x86, 0x6b, 0x8a, 0xd5, 0xe6, 0x15, + 0x73, 0x7e, 0xb5, 0xc0, 0x3e, 0x61, 0xf8, 0xe6, 0x52, 0xbf, 0x53, 0xbe, 0xc5, 0xdb, 0xca, 0x67, + 0x7f, 0x09, 0xad, 0x9c, 0xd6, 0x8c, 0x85, 0x9c, 0x61, 0xca, 0x46, 0x53, 0xb1, 0xf2, 0xb6, 0xb8, + 0xe3, 0xff, 0x5f, 0x7b, 0x9c, 0x14, 0x0e, 0x85, 0x5a, 0x42, 0x11, 0x7e, 0x7f, 0x5a, 0xc4, 0x53, + 0x5e, 0xa1, 0xfd, 0x09, 0xd4, 0x50, 0x92, 0x53, 0x7d, 0xf3, 0x69, 0x50, 0x5b, 0xff, 0xe3, 0x42, + 0x1d, 0x01, 0xf6, 0xb4, 0xe1, 0x6e, 0xc0, 0xf7, 0xfb, 0x09, 0x5a, 0x7c, 0x3f, 0x41, 0x3f, 0x58, + 0x50, 0xf7, 0x49, 0x88, 0x62, 0xc4, 0x22, 0xca, 0x46, 0xf6, 0x03, 0x58, 0x15, 0x69, 0x14, 0xcc, + 0x1f, 0x24, 0x0d, 0x91, 0x46, 0xcf, 0xca, 0xb3, 0xe4, 0x01, 0xac, 0x62, 0x21, 0x2b, 0x4e, 0xf9, + 0x24, 0x34, 0xb0, 0x90, 0x53, 0x27, 0xc3, 0x6f, 0xed, 0xd6, 0xfc, 0x3a, 0xe7, 0xb0, 0x59, 0x40, + 0xbb, 0x49, 0xff, 0x3d, 0x81, 0x46, 0x3a, 0xad, 0xa8, 0x50, 0xa4, 0x7d, 0x4d, 0x91, 0x4a, 0xd9, + 0xfe, 0xcc, 0x0e, 0xe7, 0x04, 0x9a, 0x87, 0x44, 0xf2, 0x53, 0xc2, 0xe8, 0x4b, 0x32, 0x1c, 0xa3, + 0x94, 0x88, 0xca, 0xd9, 0xb1, 0x64, 0xce, 0x2b, 0x33, 0xa5, 0xdd, 0x22, 0x70, 0x71, 0x0b, 0x0c, + 0x86, 0x47, 0xc7, 0x6a, 0xef, 0xa1, 0x39, 0xd6, 0x0a, 0x7f, 0xe7, 0x17, 0x0b, 0xd6, 0x06, 0xc3, + 0xa3, 0x01, 0x7d, 0x91, 0x51, 0x3c, 0x54, 0x30, 0xfe, 0x45, 0x34, 0xfb, 0x31, 0xac, 0x94, 0x44, + 0x68, 0x01, 0xd4, 0x81, 0x31, 0x5f, 0xe3, 0x53, 0x43, 0x8b, 0xbf, 0x5c, 0x10, 0x64, 0x7f, 0x56, + 0xbd, 0x26, 0x6a, 0x7a, 0x5f, 0xeb, 0xda, 0xbe, 0x52, 0xc6, 0xca, 0x15, 0xe2, 0xbc, 0x80, 0x0f, + 0x4b, 0x7b, 0xce, 0xca, 0x31, 0xd7, 0xd8, 0xc4, 0xb7, 0x19, 0x49, 0x2f, 0x4a, 0x8a, 0xfa, 0xb0, + 0x11, 0x8b, 0x24, 0x88, 0x75, 0x9d, 0x81, 0x8e, 0x39, 0x5f, 0x5d, 0x99, 0x68, 0x96, 0x0f, 0x7f, + 0x2d, 0x16, 0x49, 0xe5, 0xdb, 0x79, 0x65, 0x41, 0xdb, 0xcc, 0x48, 0x91, 0x73, 0x36, 0xd7, 0x04, + 0xda, 0x94, 0x51, 0x49, 0x51, 0x3c, 0x6d, 0xc7, 0xca, 0x3c, 0xde, 0x72, 0xbc, 0x5b, 0x26, 0x66, + 0x59, 0xee, 0x74, 0x4e, 0x9d, 0x0c, 0x76, 0x7a, 0x3c, 0x49, 0x32, 0x46, 0xe5, 0xc5, 0x37, 0x9c, + 0xc7, 0x07, 0x79, 0x83, 0xce, 0xc2, 0xfa, 0x02, 0x96, 0xd5, 0x9d, 0xad, 0x22, 0x6a, 0x08, 0x6b, + 0xef, 0x28, 0xbd, 0xdf, 0xdb, 0xdf, 0xcf, 0xef, 0xf4, 0xe3, 0x8b, 0x09, 0xf1, 0x97, 0x68, 0x84, + 0xd4, 0x8b, 0x7d, 0x0f, 0xfe, 0x87, 0x09, 0xe3, 0x89, 0x99, 0xaa, 0xfc, 0xc3, 0x79, 0x06, 0xf6, + 0x71, 0x8a, 0x30, 0xf1, 0x79, 0x56, 0x39, 0x8d, 0x77, 0x54, 0xaf, 0x9f, 0xa3, 0x14, 0x07, 0xf9, + 0x96, 0x7c, 0x1a, 0xea, 0xb9, 0xed, 0x50, 0x99, 0xec, 0x0f, 0x40, 0x0f, 0x47, 0x50, 0x8d, 0xa9, + 0x3b, 0x47, 0x2f, 0x1f, 0x0c, 0x5e, 0x5f, 0x76, 0xac, 0x37, 0x97, 0x1d, 0xeb, 0xcf, 0xcb, 0x8e, + 0xf5, 0xea, 0xaa, 0xb3, 0xf0, 0xe6, 0xaa, 0xb3, 0xf0, 0xdb, 0x55, 0x67, 0xe1, 0xf9, 0x5e, 0x85, + 0xac, 0xa1, 0xc6, 0xfe, 0x68, 0x80, 0x42, 0xe1, 0x99, 0x9f, 0x93, 0xb3, 0xdd, 0xc7, 0xde, 0x77, + 0xd3, 0x5f, 0x14, 0x4d, 0x5e, 0x78, 0x57, 0xff, 0x9d, 0x7c, 0xfa, 0x57, 0x00, 0x00, 0x00, 0xff, + 0xff, 0x88, 0x27, 0x41, 0x11, 0x8a, 0x09, 0x00, 0x00, } func (m *SplitDelegation) Marshal() (dAtA []byte, err error) { @@ -1440,6 +1495,43 @@ func (m *CommunityPoolBalanceQueryCallback) MarshalToSizedBuffer(dAtA []byte) (i return len(dAtA) - i, nil } +func (m *TradeRouteCallback) 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 *TradeRouteCallback) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *TradeRouteCallback) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.HostDenom) > 0 { + i -= len(m.HostDenom) + copy(dAtA[i:], m.HostDenom) + i = encodeVarintCallbacks(dAtA, i, uint64(len(m.HostDenom))) + i-- + dAtA[i] = 0x12 + } + if len(m.RewardDenom) > 0 { + i -= len(m.RewardDenom) + copy(dAtA[i:], m.RewardDenom) + i = encodeVarintCallbacks(dAtA, i, uint64(len(m.RewardDenom))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func encodeVarintCallbacks(dAtA []byte, offset int, v uint64) int { offset -= sovCallbacks(v) base := offset @@ -1698,6 +1790,23 @@ func (m *CommunityPoolBalanceQueryCallback) Size() (n int) { return n } +func (m *TradeRouteCallback) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.RewardDenom) + if l > 0 { + n += 1 + l + sovCallbacks(uint64(l)) + } + l = len(m.HostDenom) + if l > 0 { + n += 1 + l + sovCallbacks(uint64(l)) + } + return n +} + func sovCallbacks(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -3450,6 +3559,120 @@ func (m *CommunityPoolBalanceQueryCallback) Unmarshal(dAtA []byte) error { } return nil } +func (m *TradeRouteCallback) 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 ErrIntOverflowCallbacks + } + 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: TradeRouteCallback: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TradeRouteCallback: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RewardDenom", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCallbacks + } + 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 ErrInvalidLengthCallbacks + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthCallbacks + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RewardDenom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field HostDenom", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCallbacks + } + 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 ErrInvalidLengthCallbacks + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthCallbacks + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.HostDenom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipCallbacks(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthCallbacks + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipCallbacks(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/stakeibc/types/errors.go b/x/stakeibc/types/errors.go index 81f26ed76..76c75791a 100644 --- a/x/stakeibc/types/errors.go +++ b/x/stakeibc/types/errors.go @@ -60,4 +60,8 @@ var ( ErrHostZoneNotHalted = errorsmod.Register(ModuleName, 1553, "host zone is not halted") ErrFailedToLiquidStake = errorsmod.Register(ModuleName, 1554, "Failed to liquid stake") ErrUnableToRedeemStake = errorsmod.Register(ModuleName, 1555, "Failed to redeem stake") + ErrInvalidDenom = errorsmod.Register(ModuleName, 1556, "Invalid denom") + ErrTradeRouteAlreadyExists = errorsmod.Register(ModuleName, 1557, "Trade route already exists") + ErrClientStateNotTendermint = errorsmod.Register(ModuleName, 1558, "Client state not tendermint") + ErrTradeRouteNotFound = errorsmod.Register(ModuleName, 1559, "trade route not found") ) diff --git a/x/stakeibc/types/ica_account.go b/x/stakeibc/types/ica_account.go index 4a14ccb2d..f3d7e5753 100644 --- a/x/stakeibc/types/ica_account.go +++ b/x/stakeibc/types/ica_account.go @@ -1,5 +1,21 @@ package types -func FormatICAAccountOwner(chainId string, accountType ICAAccountType) (result string) { +import fmt "fmt" + +// Helper function to build the host zone ICA owner in the form "{chainId}.{ICA_TYPE}" +func FormatHostZoneICAOwner(chainId string, accountType ICAAccountType) (result string) { return chainId + "." + accountType.String() } + +// Helper function to build the ICA owner for a trade route ICA +// in the form "{chainId}.{rewardDenom}-{hostDenom}.{ICA_TYPE}" +func FormatTradeRouteICAOwner(chainId, rewardDenom, hostDenom string, icaAccountType ICAAccountType) string { + tradeRouteId := GetTradeRouteId(rewardDenom, hostDenom) + return FormatTradeRouteICAOwnerFromRouteId(chainId, tradeRouteId, icaAccountType) +} + +// Helper function to build the ICA owner for a trade route ICA +// in the form "{chainId}.{tradeRouteId}.{ICA_TYPE}" +func FormatTradeRouteICAOwnerFromRouteId(chainId, tradeRouteId string, icaAccountType ICAAccountType) string { + return fmt.Sprintf("%s.%s.%s", chainId, tradeRouteId, icaAccountType.String()) +} diff --git a/x/stakeibc/types/ica_account.pb.go b/x/stakeibc/types/ica_account.pb.go index de393fe94..656e7167d 100644 --- a/x/stakeibc/types/ica_account.pb.go +++ b/x/stakeibc/types/ica_account.pb.go @@ -6,7 +6,9 @@ package types import ( fmt "fmt" proto "github.com/cosmos/gogoproto/proto" + io "io" math "math" + math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. @@ -29,6 +31,8 @@ const ( ICAAccountType_REDEMPTION ICAAccountType = 3 ICAAccountType_COMMUNITY_POOL_DEPOSIT ICAAccountType = 4 ICAAccountType_COMMUNITY_POOL_RETURN ICAAccountType = 5 + ICAAccountType_CONVERTER_UNWIND ICAAccountType = 6 + ICAAccountType_CONVERTER_TRADE ICAAccountType = 7 ) var ICAAccountType_name = map[int32]string{ @@ -38,6 +42,8 @@ var ICAAccountType_name = map[int32]string{ 3: "REDEMPTION", 4: "COMMUNITY_POOL_DEPOSIT", 5: "COMMUNITY_POOL_RETURN", + 6: "CONVERTER_UNWIND", + 7: "CONVERTER_TRADE", } var ICAAccountType_value = map[string]int32{ @@ -47,6 +53,8 @@ var ICAAccountType_value = map[string]int32{ "REDEMPTION": 3, "COMMUNITY_POOL_DEPOSIT": 4, "COMMUNITY_POOL_RETURN": 5, + "CONVERTER_UNWIND": 6, + "CONVERTER_TRADE": 7, } func (x ICAAccountType) String() string { @@ -57,28 +65,444 @@ func (ICAAccountType) EnumDescriptor() ([]byte, []int) { return fileDescriptor_2976ae6e7f6ce824, []int{0} } +type ICAAccount struct { + ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + Type ICAAccountType `protobuf:"varint,2,opt,name=type,proto3,enum=stride.stakeibc.ICAAccountType" json:"type,omitempty"` + ConnectionId string `protobuf:"bytes,3,opt,name=connection_id,json=connectionId,proto3" json:"connection_id,omitempty"` + Address string `protobuf:"bytes,4,opt,name=address,proto3" json:"address,omitempty"` +} + +func (m *ICAAccount) Reset() { *m = ICAAccount{} } +func (m *ICAAccount) String() string { return proto.CompactTextString(m) } +func (*ICAAccount) ProtoMessage() {} +func (*ICAAccount) Descriptor() ([]byte, []int) { + return fileDescriptor_2976ae6e7f6ce824, []int{0} +} +func (m *ICAAccount) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ICAAccount) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ICAAccount.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 *ICAAccount) XXX_Merge(src proto.Message) { + xxx_messageInfo_ICAAccount.Merge(m, src) +} +func (m *ICAAccount) XXX_Size() int { + return m.Size() +} +func (m *ICAAccount) XXX_DiscardUnknown() { + xxx_messageInfo_ICAAccount.DiscardUnknown(m) +} + +var xxx_messageInfo_ICAAccount proto.InternalMessageInfo + +func (m *ICAAccount) GetChainId() string { + if m != nil { + return m.ChainId + } + return "" +} + +func (m *ICAAccount) GetType() ICAAccountType { + if m != nil { + return m.Type + } + return ICAAccountType_DELEGATION +} + +func (m *ICAAccount) GetConnectionId() string { + if m != nil { + return m.ConnectionId + } + return "" +} + +func (m *ICAAccount) GetAddress() string { + if m != nil { + return m.Address + } + return "" +} + func init() { proto.RegisterEnum("stride.stakeibc.ICAAccountType", ICAAccountType_name, ICAAccountType_value) + proto.RegisterType((*ICAAccount)(nil), "stride.stakeibc.ICAAccount") } func init() { proto.RegisterFile("stride/stakeibc/ica_account.proto", fileDescriptor_2976ae6e7f6ce824) } var fileDescriptor_2976ae6e7f6ce824 = []byte{ - // 242 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x2c, 0x2e, 0x29, 0xca, - 0x4c, 0x49, 0xd5, 0x2f, 0x2e, 0x49, 0xcc, 0x4e, 0xcd, 0x4c, 0x4a, 0xd6, 0xcf, 0x4c, 0x4e, 0x8c, - 0x4f, 0x4c, 0x4e, 0xce, 0x2f, 0xcd, 0x2b, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x87, - 0x28, 0xd1, 0x83, 0x29, 0xd1, 0x6a, 0x60, 0xe4, 0xe2, 0xf3, 0x74, 0x76, 0x74, 0x84, 0xa8, 0x0a, - 0xa9, 0x2c, 0x48, 0x15, 0xe2, 0xe3, 0xe2, 0x72, 0x71, 0xf5, 0x71, 0x75, 0x77, 0x0c, 0xf1, 0xf4, - 0xf7, 0x13, 0x60, 0x10, 0x62, 0xe7, 0x62, 0x76, 0x73, 0x75, 0x15, 0x60, 0x04, 0x49, 0x84, 0x7b, - 0x86, 0x78, 0xb8, 0x04, 0x39, 0x86, 0x3b, 0xfa, 0x08, 0x30, 0x81, 0xf8, 0x41, 0xae, 0x2e, 0xae, - 0xbe, 0x01, 0x60, 0x85, 0xcc, 0x42, 0x52, 0x5c, 0x62, 0xce, 0xfe, 0xbe, 0xbe, 0xa1, 0x7e, 0x9e, - 0x21, 0x91, 0xf1, 0x01, 0xfe, 0xfe, 0x3e, 0xf1, 0x2e, 0xae, 0x01, 0xfe, 0xc1, 0x9e, 0x21, 0x02, - 0x2c, 0x42, 0x92, 0x5c, 0xa2, 0x68, 0x72, 0x41, 0xae, 0x21, 0xa1, 0x41, 0x7e, 0x02, 0xac, 0x4e, - 0x3e, 0x27, 0x1e, 0xc9, 0x31, 0x5e, 0x78, 0x24, 0xc7, 0xf8, 0xe0, 0x91, 0x1c, 0xe3, 0x84, 0xc7, - 0x72, 0x0c, 0x17, 0x1e, 0xcb, 0x31, 0xdc, 0x78, 0x2c, 0xc7, 0x10, 0x65, 0x94, 0x9e, 0x59, 0x92, - 0x51, 0x9a, 0xa4, 0x97, 0x9c, 0x9f, 0xab, 0x1f, 0x0c, 0x76, 0xb8, 0xae, 0x4f, 0x62, 0x52, 0xb1, - 0x3e, 0xd4, 0x9f, 0x65, 0x86, 0x66, 0xfa, 0x15, 0x08, 0xdf, 0x96, 0x54, 0x16, 0xa4, 0x16, 0x27, - 0xb1, 0x81, 0x3d, 0x6a, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0x9e, 0xb5, 0xd8, 0xf0, 0x0d, 0x01, - 0x00, 0x00, + // 366 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x5c, 0x91, 0xcf, 0x4e, 0xea, 0x40, + 0x14, 0xc6, 0x3b, 0xc0, 0xa5, 0xf7, 0x4e, 0xee, 0x85, 0xc9, 0xdc, 0x3f, 0x29, 0x77, 0x51, 0x51, + 0x37, 0xc4, 0xc4, 0x36, 0x42, 0xe2, 0xbe, 0xd2, 0x51, 0x27, 0x29, 0x2d, 0x19, 0x06, 0x89, 0x6e, + 0x9a, 0x76, 0xda, 0x48, 0x63, 0x6c, 0x09, 0x2d, 0x46, 0xde, 0xc2, 0xbd, 0x8f, 0xe0, 0x8b, 0xb8, + 0x64, 0xe9, 0xd2, 0xc0, 0x8b, 0x18, 0x0a, 0xa6, 0x91, 0xe5, 0x77, 0xce, 0x2f, 0xbf, 0x93, 0x9c, + 0x0f, 0xee, 0xa7, 0xd9, 0x34, 0x0a, 0x42, 0x3d, 0xcd, 0xbc, 0xbb, 0x30, 0xf2, 0x85, 0x1e, 0x09, + 0xcf, 0xf5, 0x84, 0x48, 0x66, 0x71, 0xa6, 0x4d, 0xa6, 0x49, 0x96, 0xe0, 0xfa, 0x06, 0xd1, 0x3e, + 0x91, 0x83, 0x67, 0x00, 0x21, 0xed, 0x1a, 0xc6, 0x86, 0xc2, 0x0d, 0xf8, 0x5d, 0x8c, 0xbd, 0x28, + 0x76, 0xa3, 0x40, 0x01, 0x4d, 0xd0, 0xfa, 0xc1, 0xe4, 0x3c, 0xd3, 0x00, 0x77, 0x60, 0x25, 0x9b, + 0x4f, 0x42, 0xa5, 0xd4, 0x04, 0xad, 0x5a, 0x7b, 0x4f, 0xdb, 0x31, 0x69, 0x85, 0x85, 0xcf, 0x27, + 0x21, 0xcb, 0x61, 0x7c, 0x08, 0x7f, 0x89, 0x24, 0x8e, 0x43, 0x91, 0x45, 0x49, 0x2e, 0x2d, 0xe7, + 0xd2, 0x9f, 0xc5, 0x90, 0x06, 0x58, 0x81, 0xb2, 0x17, 0x04, 0xd3, 0x30, 0x4d, 0x95, 0xca, 0xe6, + 0xe6, 0x36, 0x1e, 0xbd, 0x00, 0x58, 0xfb, 0xea, 0xc5, 0x35, 0x08, 0x4d, 0x62, 0x91, 0x0b, 0x83, + 0x53, 0xc7, 0x46, 0x12, 0x96, 0x61, 0xf9, 0x9c, 0x10, 0x04, 0xd6, 0x8b, 0x11, 0xe5, 0x97, 0x26, + 0x33, 0x46, 0x86, 0x85, 0x4a, 0xeb, 0xcc, 0x88, 0x49, 0x7a, 0xfd, 0x1c, 0x2c, 0xe3, 0xff, 0xf0, + 0x5f, 0xd7, 0xe9, 0xf5, 0x86, 0x36, 0xe5, 0xd7, 0x6e, 0xdf, 0x71, 0x2c, 0xd7, 0x24, 0x7d, 0x67, + 0x40, 0x39, 0xaa, 0xe0, 0x06, 0xfc, 0xbb, 0xb3, 0x63, 0x84, 0x0f, 0x99, 0x8d, 0xbe, 0xe1, 0x3f, + 0x10, 0x75, 0x1d, 0xfb, 0x8a, 0x30, 0x4e, 0x98, 0x3b, 0xb4, 0x47, 0xd4, 0x36, 0x51, 0x15, 0xff, + 0x86, 0xf5, 0x62, 0xca, 0x99, 0x61, 0x12, 0x24, 0x9f, 0x59, 0xaf, 0x4b, 0x15, 0x2c, 0x96, 0x2a, + 0x78, 0x5f, 0xaa, 0xe0, 0x69, 0xa5, 0x4a, 0x8b, 0x95, 0x2a, 0xbd, 0xad, 0x54, 0xe9, 0xa6, 0x7d, + 0x1b, 0x65, 0xe3, 0x99, 0xaf, 0x89, 0xe4, 0x5e, 0x1f, 0xe4, 0x7f, 0x3b, 0xb6, 0x3c, 0x3f, 0xd5, + 0xb7, 0x85, 0x3d, 0x9c, 0x9c, 0xea, 0x8f, 0x45, 0x6d, 0xeb, 0xcf, 0xa5, 0x7e, 0x35, 0x6f, 0xac, + 0xf3, 0x11, 0x00, 0x00, 0xff, 0xff, 0x44, 0x80, 0x94, 0xbd, 0xd6, 0x01, 0x00, 0x00, +} + +func (m *ICAAccount) 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 *ICAAccount) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ICAAccount) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintIcaAccount(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0x22 + } + if len(m.ConnectionId) > 0 { + i -= len(m.ConnectionId) + copy(dAtA[i:], m.ConnectionId) + i = encodeVarintIcaAccount(dAtA, i, uint64(len(m.ConnectionId))) + i-- + dAtA[i] = 0x1a + } + if m.Type != 0 { + i = encodeVarintIcaAccount(dAtA, i, uint64(m.Type)) + i-- + dAtA[i] = 0x10 + } + if len(m.ChainId) > 0 { + i -= len(m.ChainId) + copy(dAtA[i:], m.ChainId) + i = encodeVarintIcaAccount(dAtA, i, uint64(len(m.ChainId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintIcaAccount(dAtA []byte, offset int, v uint64) int { + offset -= sovIcaAccount(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base } +func (m *ICAAccount) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ChainId) + if l > 0 { + n += 1 + l + sovIcaAccount(uint64(l)) + } + if m.Type != 0 { + n += 1 + sovIcaAccount(uint64(m.Type)) + } + l = len(m.ConnectionId) + if l > 0 { + n += 1 + l + sovIcaAccount(uint64(l)) + } + l = len(m.Address) + if l > 0 { + n += 1 + l + sovIcaAccount(uint64(l)) + } + return n +} + +func sovIcaAccount(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozIcaAccount(x uint64) (n int) { + return sovIcaAccount(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *ICAAccount) 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 ErrIntOverflowIcaAccount + } + 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: ICAAccount: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ICAAccount: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowIcaAccount + } + 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 ErrInvalidLengthIcaAccount + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthIcaAccount + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ChainId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) + } + m.Type = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowIcaAccount + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Type |= ICAAccountType(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ConnectionId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowIcaAccount + } + 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 ErrInvalidLengthIcaAccount + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthIcaAccount + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ConnectionId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowIcaAccount + } + 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 ErrInvalidLengthIcaAccount + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthIcaAccount + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipIcaAccount(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthIcaAccount + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipIcaAccount(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowIcaAccount + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowIcaAccount + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowIcaAccount + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthIcaAccount + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupIcaAccount + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthIcaAccount + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthIcaAccount = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowIcaAccount = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupIcaAccount = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/stakeibc/types/ica_account_test.go b/x/stakeibc/types/ica_account_test.go new file mode 100644 index 000000000..5a2965297 --- /dev/null +++ b/x/stakeibc/types/ica_account_test.go @@ -0,0 +1,81 @@ +package types_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/Stride-Labs/stride/v16/x/stakeibc/types" +) + +func TestFormatHostZoneICAOwner(t *testing.T) { + chainId := "chain-0" + + testCases := []struct { + accountType types.ICAAccountType + owner string + }{ + { + accountType: types.ICAAccountType_DELEGATION, + owner: "chain-0.DELEGATION", + }, + { + accountType: types.ICAAccountType_WITHDRAWAL, + owner: "chain-0.WITHDRAWAL", + }, + { + accountType: types.ICAAccountType_REDEMPTION, + owner: "chain-0.REDEMPTION", + }, + { + accountType: types.ICAAccountType_FEE, + owner: "chain-0.FEE", + }, + { + accountType: types.ICAAccountType_COMMUNITY_POOL_DEPOSIT, + owner: "chain-0.COMMUNITY_POOL_DEPOSIT", + }, + { + accountType: types.ICAAccountType_COMMUNITY_POOL_RETURN, + owner: "chain-0.COMMUNITY_POOL_RETURN", + }, + } + + for _, tc := range testCases { + t.Run(tc.accountType.String(), func(t *testing.T) { + actual := types.FormatHostZoneICAOwner(chainId, tc.accountType) + require.Equal(t, tc.owner, actual) + }) + } +} + +func TestFormatTradeRouteICAOwner(t *testing.T) { + chainId := "chain-0" + rewardDenom := "ureward" + hostDenom := "uhost" + + testCases := []struct { + accountType types.ICAAccountType + owner string + }{ + { + accountType: types.ICAAccountType_CONVERTER_UNWIND, + owner: "chain-0.ureward-uhost.CONVERTER_UNWIND", + }, + { + accountType: types.ICAAccountType_CONVERTER_TRADE, + owner: "chain-0.ureward-uhost.CONVERTER_TRADE", + }, + } + + for _, tc := range testCases { + t.Run(tc.accountType.String(), func(t *testing.T) { + actual := types.FormatTradeRouteICAOwner(chainId, rewardDenom, hostDenom, tc.accountType) + require.Equal(t, actual, tc.owner, "format trade route ICA owner") + + tradeRouteId := "ureward-uhost" + actual = types.FormatTradeRouteICAOwnerFromRouteId(chainId, tradeRouteId, tc.accountType) + require.Equal(t, actual, tc.owner, "format trade route ICA owner by account") + }) + } +} diff --git a/x/stakeibc/types/keys.go b/x/stakeibc/types/keys.go index df65fc1cd..36f8defe9 100644 --- a/x/stakeibc/types/keys.go +++ b/x/stakeibc/types/keys.go @@ -47,10 +47,18 @@ func EpochTrackerKey(epochIdentifier string) []byte { return key } +// Definition for the store key format based on tradeRoute start and end denoms +func TradeRouteKeyFromDenoms(rewardDenom, hostDenom string) (key []byte) { + return []byte(rewardDenom + "-" + hostDenom) +} + const ( // Host zone keys prefix the HostZone structs HostZoneKey = "HostZone-value-" // EpochTrackerKeyPrefix is the prefix to retrieve all EpochTracker EpochTrackerKeyPrefix = "EpochTracker/value/" + + // TradeRoute keys prefix to retrieve all TradeZones + TradeRouteKeyPrefix = "TradeRoute-value-" ) diff --git a/x/stakeibc/types/message_create_trade_route.go b/x/stakeibc/types/message_create_trade_route.go new file mode 100644 index 000000000..b7a77ecf6 --- /dev/null +++ b/x/stakeibc/types/message_create_trade_route.go @@ -0,0 +1,139 @@ +package types + +import ( + "regexp" + "strings" + + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + + errorsmod "cosmossdk.io/errors" + sdkmath "cosmossdk.io/math" + "github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx" +) + +const TypeMsgCreateTradeRoute = "create_trade_route" + +const ( + ConnectionIdRegex = `^connection-\d+$` + ChannelIdRegex = `^channel-\d+$` + IBCPrefix = "ibc/" +) + +var ( + _ sdk.Msg = &MsgCreateTradeRoute{} + _ legacytx.LegacyMsg = &MsgCreateTradeRoute{} +) + +func (msg *MsgCreateTradeRoute) Type() string { + return TypeMsgCreateTradeRoute +} + +func (msg *MsgCreateTradeRoute) Route() string { + return RouterKey +} + +func (msg *MsgCreateTradeRoute) GetSignBytes() []byte { + bz := ModuleCdc.MustMarshalJSON(msg) + return sdk.MustSortJSON(bz) +} + +func (msg *MsgCreateTradeRoute) GetSigners() []sdk.AccAddress { + addr, _ := sdk.AccAddressFromBech32(msg.Authority) + return []sdk.AccAddress{addr} +} + +func (msg *MsgCreateTradeRoute) ValidateBasic() error { + if _, err := sdk.AccAddressFromBech32(msg.Authority); err != nil { + return errorsmod.Wrap(err, "invalid authority address") + } + + if msg.HostChainId == "" { + return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "host chain ID cannot be empty") + } + + if err := ValidateConnectionId(msg.StrideToRewardConnectionId); err != nil { + return errorsmod.Wrap(err, "invalid stride to reward connection ID") + } + if err := ValidateConnectionId(msg.StrideToTradeConnectionId); err != nil { + return errorsmod.Wrap(err, "invalid stride to trade connection ID") + } + + if err := ValidateChannelId(msg.HostToRewardTransferChannelId); err != nil { + return errorsmod.Wrap(err, "invalid host to reward channel ID") + } + if err := ValidateChannelId(msg.RewardToTradeTransferChannelId); err != nil { + return errorsmod.Wrap(err, "invalid reward to trade channel ID") + } + if err := ValidateChannelId(msg.TradeToHostTransferChannelId); err != nil { + return errorsmod.Wrap(err, "invalid trade to host channel ID") + } + + if err := ValidateDenom(msg.RewardDenomOnHost, true); err != nil { + return errorsmod.Wrap(err, "invalid reward denom on host") + } + if err := ValidateDenom(msg.RewardDenomOnReward, false); err != nil { + return errorsmod.Wrap(err, "invalid reward denom on reward") + } + if err := ValidateDenom(msg.RewardDenomOnTrade, true); err != nil { + return errorsmod.Wrap(err, "invalid reward denom on trade") + } + if err := ValidateDenom(msg.HostDenomOnTrade, true); err != nil { + return errorsmod.Wrap(err, "invalid host denom on trade") + } + if err := ValidateDenom(msg.HostDenomOnHost, false); err != nil { + return errorsmod.Wrap(err, "invalid host denom on host") + } + + if msg.PoolId < 1 { + return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "invalid pool id") + } + if msg.MaxSwapAmount.GT(sdkmath.ZeroInt()) && msg.MinSwapAmount.GT(msg.MaxSwapAmount) { + return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "min swap amount cannot be greater than max swap amount") + } + + maxAllowedSwapLossRate, err := sdk.NewDecFromStr(msg.MaxAllowedSwapLossRate) + if err != nil { + return errorsmod.Wrapf(err, "unable to cast max allowed swap loss rate to a decimal") + } + if maxAllowedSwapLossRate.LT(sdk.ZeroDec()) || maxAllowedSwapLossRate.GT(sdk.OneDec()) { + return errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "max allowed swap loss rate must be between 0 and 1") + } + + return nil +} + +// Helper function to validate a connection Id +func ValidateConnectionId(connectionId string) error { + matched, err := regexp.MatchString(ConnectionIdRegex, connectionId) + if err != nil { + return errorsmod.Wrapf(err, "unable to verify connnection-id (%s)", connectionId) + } + if !matched { + return errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "invalid connection-id (%s), must be of the format 'connection-{N}'", connectionId) + } + return nil +} + +// Helper function to validate a channel Id +func ValidateChannelId(channelId string) error { + matched, err := regexp.MatchString(ChannelIdRegex, channelId) + if err != nil { + return errorsmod.Wrapf(err, "unable to verify channel-id (%s)", channelId) + } + if !matched { + return errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "invalid channel-id (%s), must be of the format 'channel-{N}'", channelId) + } + return nil +} + +// Helper function to validate a denom +func ValidateDenom(denom string, ibc bool) error { + if denom == "" { + return errorsmod.Wrap(ErrInvalidDenom, "denom is empty") + } + if ibc && !strings.HasPrefix(denom, IBCPrefix) { + return errorsmod.Wrapf(ErrInvalidDenom, "denom (%s) should have ibc prefix", denom) + } + return nil +} diff --git a/x/stakeibc/types/message_create_trade_route_test.go b/x/stakeibc/types/message_create_trade_route_test.go new file mode 100644 index 000000000..6e7d14299 --- /dev/null +++ b/x/stakeibc/types/message_create_trade_route_test.go @@ -0,0 +1,169 @@ +package types_test + +import ( + "testing" + + sdkmath "cosmossdk.io/math" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + "github.com/stretchr/testify/require" + + "github.com/Stride-Labs/stride/v16/app/apptesting" + "github.com/Stride-Labs/stride/v16/x/stakeibc/types" +) + +func TestMsgCreateTradeRoute(t *testing.T) { + apptesting.SetupConfig() + + authority := authtypes.NewModuleAddress(govtypes.ModuleName).String() + + validChainId := "chain-1" + validConnectionId1 := "connection-1" + validConnectionId2 := "connection-17" + validTransferChannelId1 := "channel-2" + validTransferChannelId2 := "channel-202" + validTransferChannelId3 := "channel-40" + + validNativeDenom := "denom" + validIBCDenom := "ibc/denom" + + validPoolId := uint64(1) + validMaxAllowedSwapLossRate := "0.05" + validMinSwapAmount := sdkmath.NewInt(100) + validMaxSwapAmount := sdkmath.NewInt(10000) + + validMessage := types.MsgCreateTradeRoute{ + Authority: authority, + + HostChainId: validChainId, + StrideToRewardConnectionId: validConnectionId1, + StrideToTradeConnectionId: validConnectionId2, + + HostToRewardTransferChannelId: validTransferChannelId1, + RewardToTradeTransferChannelId: validTransferChannelId2, + TradeToHostTransferChannelId: validTransferChannelId3, + + RewardDenomOnHost: validIBCDenom, + RewardDenomOnReward: validNativeDenom, + RewardDenomOnTrade: validIBCDenom, + HostDenomOnTrade: validIBCDenom, + HostDenomOnHost: validNativeDenom, + + PoolId: validPoolId, + MaxAllowedSwapLossRate: validMaxAllowedSwapLossRate, + MinSwapAmount: validMinSwapAmount, + MaxSwapAmount: validMaxSwapAmount, + } + + // Validate successful message + require.NoError(t, validMessage.ValidateBasic(), "valid message") + require.Equal(t, validMessage.Route(), types.RouterKey) + require.Equal(t, validMessage.Type(), "create_trade_route") + + signers := validMessage.GetSigners() + require.Equal(t, len(signers), 1) + require.Equal(t, signers[0].String(), authority) + + // Remove authority - confirm invalid + invalidMessage := validMessage + invalidMessage.Authority = "" + require.ErrorContains(t, invalidMessage.ValidateBasic(), "invalid authority address") + + // Set invalid chain ID - confirm invalid + invalidMessage = validMessage + invalidMessage.HostChainId = "" + require.ErrorContains(t, invalidMessage.ValidateBasic(), "host chain ID cannot be empty") + + // Set invalid connection IDs - confirm invalid + invalidMessage = validMessage + invalidMessage.StrideToRewardConnectionId = "" + require.ErrorContains(t, invalidMessage.ValidateBasic(), "invalid stride to reward connection ID") + + invalidMessage = validMessage + invalidMessage.StrideToTradeConnectionId = "connection-X" + require.ErrorContains(t, invalidMessage.ValidateBasic(), "invalid stride to trade connection ID") + + // Set invalid channel IDs - confirm invalid + invalidMessage = validMessage + invalidMessage.HostToRewardTransferChannelId = "" + require.ErrorContains(t, invalidMessage.ValidateBasic(), "invalid host to reward channel ID") + + invalidMessage = validMessage + invalidMessage.RewardToTradeTransferChannelId = "channel-" + require.ErrorContains(t, invalidMessage.ValidateBasic(), "invalid reward to trade channel ID") + + invalidMessage = validMessage + invalidMessage.TradeToHostTransferChannelId = "channel-X" + require.ErrorContains(t, invalidMessage.ValidateBasic(), "invalid trade to host channel ID") + + // Set invalid denom's - confirm invalid + invalidMessage = validMessage + invalidMessage.RewardDenomOnHost = "not-ibc-denom" + require.ErrorContains(t, invalidMessage.ValidateBasic(), "invalid reward denom on host") + + invalidMessage = validMessage + invalidMessage.RewardDenomOnReward = "" + require.ErrorContains(t, invalidMessage.ValidateBasic(), "invalid reward denom on reward") + + invalidMessage = validMessage + invalidMessage.RewardDenomOnTrade = "not-ibc-denom" + require.ErrorContains(t, invalidMessage.ValidateBasic(), "invalid reward denom on trade") + + invalidMessage = validMessage + invalidMessage.HostDenomOnTrade = "not-ibc-denom" + require.ErrorContains(t, invalidMessage.ValidateBasic(), "invalid host denom on trade") + + invalidMessage = validMessage + invalidMessage.HostDenomOnHost = "" + require.ErrorContains(t, invalidMessage.ValidateBasic(), "invalid host denom on host") + + // Set invalid pool configurations - confirm invalid + invalidMessage = validMessage + invalidMessage.PoolId = 0 + require.ErrorContains(t, invalidMessage.ValidateBasic(), "invalid pool id") + + invalidMessage = validMessage + invalidMessage.MinSwapAmount = sdkmath.NewInt(10) + invalidMessage.MaxSwapAmount = sdkmath.NewInt(9) + require.ErrorContains(t, invalidMessage.ValidateBasic(), "min swap amount cannot be greater than max swap amount") + + invalidMessage = validMessage + invalidMessage.MaxAllowedSwapLossRate = "" + require.ErrorContains(t, invalidMessage.ValidateBasic(), "unable to cast max allowed swap loss rate to a decimal") + + invalidMessage = validMessage + invalidMessage.MaxAllowedSwapLossRate = "-0.01" + require.ErrorContains(t, invalidMessage.ValidateBasic(), "max allowed swap loss rate must be between 0 and 1") + + invalidMessage = validMessage + invalidMessage.MaxAllowedSwapLossRate = "1.01" + require.ErrorContains(t, invalidMessage.ValidateBasic(), "max allowed swap loss rate must be between 0 and 1") +} + +func TestValidateConnectionId(t *testing.T) { + require.NoError(t, types.ValidateConnectionId("connection-0")) + require.NoError(t, types.ValidateConnectionId("connection-10")) + require.NoError(t, types.ValidateConnectionId("connection-1203")) + + require.ErrorContains(t, types.ValidateConnectionId("connection-X"), "invalid connection-id (connection-X)") + require.ErrorContains(t, types.ValidateConnectionId(""), "invalid connection-id ()") +} + +func TestValidateChannelId(t *testing.T) { + require.NoError(t, types.ValidateChannelId("channel-0")) + require.NoError(t, types.ValidateChannelId("channel-10")) + require.NoError(t, types.ValidateChannelId("channel-1203")) + + require.ErrorContains(t, types.ValidateChannelId("channel-X"), "invalid channel-id (channel-X)") + require.ErrorContains(t, types.ValidateChannelId(""), "invalid channel-id ()") +} + +func TestValidateDenom(t *testing.T) { + require.NoError(t, types.ValidateDenom("denom", false)) + require.NoError(t, types.ValidateDenom("ibc/denom", false)) + require.NoError(t, types.ValidateDenom("ibc/denom", true)) + + require.ErrorContains(t, types.ValidateDenom("", false), "denom is empty") + require.ErrorContains(t, types.ValidateDenom("", true), "denom is empty") + require.ErrorContains(t, types.ValidateDenom("denom", true), "denom (denom) should have ibc prefix") +} diff --git a/x/stakeibc/types/message_delete_trade_route.go b/x/stakeibc/types/message_delete_trade_route.go new file mode 100644 index 000000000..1dda70b89 --- /dev/null +++ b/x/stakeibc/types/message_delete_trade_route.go @@ -0,0 +1,49 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx" + + errorsmod "cosmossdk.io/errors" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +const TypeMsgDeleteTradeRoute = "delete_trade_route" + +var ( + _ sdk.Msg = &MsgDeleteTradeRoute{} + _ legacytx.LegacyMsg = &MsgDeleteTradeRoute{} +) + +func (msg *MsgDeleteTradeRoute) Type() string { + return TypeMsgDeleteTradeRoute +} + +func (msg *MsgDeleteTradeRoute) Route() string { + return RouterKey +} + +func (msg *MsgDeleteTradeRoute) GetSignBytes() []byte { + bz := ModuleCdc.MustMarshalJSON(msg) + return sdk.MustSortJSON(bz) +} + +func (msg *MsgDeleteTradeRoute) GetSigners() []sdk.AccAddress { + addr, _ := sdk.AccAddressFromBech32(msg.Authority) + return []sdk.AccAddress{addr} +} + +func (msg *MsgDeleteTradeRoute) ValidateBasic() error { + if _, err := sdk.AccAddressFromBech32(msg.Authority); err != nil { + return errorsmod.Wrap(err, "invalid authority address") + } + + if msg.HostDenom == "" { + return errorsmod.Wrapf(sdkerrors.ErrNotFound, "missing host denom") + } + if msg.RewardDenom == "" { + return errorsmod.Wrapf(sdkerrors.ErrNotFound, "missing reward denom") + } + + return nil +} diff --git a/x/stakeibc/types/message_delete_trade_route_test.go b/x/stakeibc/types/message_delete_trade_route_test.go new file mode 100644 index 000000000..725336eb8 --- /dev/null +++ b/x/stakeibc/types/message_delete_trade_route_test.go @@ -0,0 +1,78 @@ +package types_test + +import ( + "testing" + + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + "github.com/stretchr/testify/require" + + "github.com/Stride-Labs/stride/v16/app/apptesting" + "github.com/Stride-Labs/stride/v16/x/stakeibc/types" +) + +func TestMsgDeleteTradeRoute(t *testing.T) { + apptesting.SetupConfig() + + authority := authtypes.NewModuleAddress(govtypes.ModuleName).String() + + validDenom := "denom" + + tests := []struct { + name string + msg types.MsgDeleteTradeRoute + err string + }{ + { + name: "successful message", + msg: types.MsgDeleteTradeRoute{ + Authority: authority, + HostDenom: validDenom, + RewardDenom: validDenom, + }, + }, + { + name: "invalid authority message", + msg: types.MsgDeleteTradeRoute{ + Authority: "", + HostDenom: validDenom, + RewardDenom: validDenom, + }, + err: "invalid authority address", + }, + { + name: "invalid host denom", + msg: types.MsgDeleteTradeRoute{ + Authority: authority, + HostDenom: "", + RewardDenom: validDenom, + }, + err: "missing host denom", + }, + { + name: "invalid reward denom", + msg: types.MsgDeleteTradeRoute{ + Authority: authority, + HostDenom: validDenom, + RewardDenom: "", + }, + err: "missing reward denom", + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + if test.err == "" { + require.NoError(t, test.msg.ValidateBasic(), "test: %v", test.name) + require.Equal(t, test.msg.Route(), types.RouterKey) + require.Equal(t, test.msg.Type(), "delete_trade_route") + + signers := test.msg.GetSigners() + require.Equal(t, len(signers), 1) + require.Equal(t, signers[0].String(), authority) + } else { + require.ErrorContains(t, test.msg.ValidateBasic(), test.err, "test: %v", test.name) + } + }) + } +} diff --git a/x/stakeibc/types/message_restore_interchain_account.go b/x/stakeibc/types/message_restore_interchain_account.go index 344dd04aa..b2ae7d123 100644 --- a/x/stakeibc/types/message_restore_interchain_account.go +++ b/x/stakeibc/types/message_restore_interchain_account.go @@ -1,20 +1,23 @@ package types import ( + "strings" + errorsmod "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) -const TypeMsgRestoreInterchainAccount = "register_interchain_account" +const TypeMsgRestoreInterchainAccount = "restore_interchain_account" var _ sdk.Msg = &MsgRestoreInterchainAccount{} -func NewMsgRestoreInterchainAccount(creator string, chainId string, accountType ICAAccountType) *MsgRestoreInterchainAccount { +func NewMsgRestoreInterchainAccount(creator, chainId, connectionId, owner string) *MsgRestoreInterchainAccount { return &MsgRestoreInterchainAccount{ - Creator: creator, - ChainId: chainId, - AccountType: accountType, + Creator: creator, + ChainId: chainId, + ConnectionId: connectionId, + AccountOwner: owner, } } @@ -44,5 +47,17 @@ func (msg *MsgRestoreInterchainAccount) ValidateBasic() error { if err != nil { return errorsmod.Wrapf(sdkerrors.ErrInvalidAddress, "invalid creator address (%s)", err) } + if msg.ChainId == "" { + return errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "chain ID must be specified") + } + if !strings.HasPrefix(msg.ConnectionId, "connection-") { + return errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "connection ID must be specified") + } + if msg.AccountOwner == "" { + return errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "ICA account owner must be specified") + } + if !strings.HasPrefix(msg.AccountOwner, msg.ChainId) { + return errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "ICA account owner does not match chain ID") + } return nil } diff --git a/x/stakeibc/types/message_restore_interchain_account_test.go b/x/stakeibc/types/message_restore_interchain_account_test.go index c0e7577a7..4b00fd54b 100644 --- a/x/stakeibc/types/message_restore_interchain_account_test.go +++ b/x/stakeibc/types/message_restore_interchain_account_test.go @@ -3,36 +3,93 @@ package types import ( "testing" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/stretchr/testify/require" "github.com/Stride-Labs/stride/v16/testutil/sample" ) func TestMsgRestoreInterchainAccount_ValidateBasic(t *testing.T) { + validChainId := "chain-0" + validConnectionId := "connection-0" + validHostZoneOwner := "chain-0.DELEGATION" + validTradeRouteOwner := "chain-0.reward.host.CONVERTER_TRADE" + tests := []struct { name string msg MsgRestoreInterchainAccount - err error + err string }{ { - name: "invalid address", + name: "valid host zone message", msg: MsgRestoreInterchainAccount{ - Creator: "invalid_address", + Creator: sample.AccAddress(), + ChainId: validChainId, + ConnectionId: validConnectionId, + AccountOwner: validHostZoneOwner, + }, + }, + { + name: "valid trade route message", + msg: MsgRestoreInterchainAccount{ + Creator: sample.AccAddress(), + ChainId: validChainId, + ConnectionId: validConnectionId, + AccountOwner: validTradeRouteOwner, }, - err: sdkerrors.ErrInvalidAddress, - }, { - name: "not admin address", + }, + { + name: "missing chain id", msg: MsgRestoreInterchainAccount{ - Creator: sample.AccAddress(), + Creator: sample.AccAddress(), + ChainId: "", + ConnectionId: validConnectionId, + AccountOwner: validHostZoneOwner, + }, + err: "chain ID must be specified", + }, + { + name: "missing connection id", + msg: MsgRestoreInterchainAccount{ + Creator: sample.AccAddress(), + ChainId: validChainId, + ConnectionId: "con-0", + AccountOwner: validHostZoneOwner, + }, + err: "connection ID must be specified", + }, + { + name: "missing account owner", + msg: MsgRestoreInterchainAccount{ + Creator: sample.AccAddress(), + ChainId: validChainId, + ConnectionId: validConnectionId, + AccountOwner: "", + }, + err: "ICA account owner must be specified", + }, + { + name: "chain id does not match owner", + msg: MsgRestoreInterchainAccount{ + Creator: sample.AccAddress(), + ChainId: validChainId, + ConnectionId: validConnectionId, + AccountOwner: "chain-1.reward.host.CONVERTER_TRADE", + }, + err: "ICA account owner does not match chain ID", + }, + { + name: "invalid address", + msg: MsgRestoreInterchainAccount{ + Creator: "invalid_address", }, + err: "invalid address", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { err := tt.msg.ValidateBasic() - if tt.err != nil { - require.ErrorIs(t, err, tt.err) + if tt.err != "" { + require.ErrorContains(t, err, tt.err) return } require.NoError(t, err) diff --git a/x/stakeibc/types/message_update_trade_route.go b/x/stakeibc/types/message_update_trade_route.go new file mode 100644 index 000000000..e95a8a4fd --- /dev/null +++ b/x/stakeibc/types/message_update_trade_route.go @@ -0,0 +1,63 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx" + + errorsmod "cosmossdk.io/errors" + sdkmath "cosmossdk.io/math" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +const TypeMsgUpdateTradeRoute = "update_trade_route" + +var ( + _ sdk.Msg = &MsgUpdateTradeRoute{} + _ legacytx.LegacyMsg = &MsgUpdateTradeRoute{} +) + +func (msg *MsgUpdateTradeRoute) Type() string { + return TypeMsgUpdateTradeRoute +} + +func (msg *MsgUpdateTradeRoute) Route() string { + return RouterKey +} + +func (msg *MsgUpdateTradeRoute) GetSignBytes() []byte { + bz := ModuleCdc.MustMarshalJSON(msg) + return sdk.MustSortJSON(bz) +} + +func (msg *MsgUpdateTradeRoute) GetSigners() []sdk.AccAddress { + addr, _ := sdk.AccAddressFromBech32(msg.Authority) + return []sdk.AccAddress{addr} +} +func (msg *MsgUpdateTradeRoute) ValidateBasic() error { + if _, err := sdk.AccAddressFromBech32(msg.Authority); err != nil { + return errorsmod.Wrap(err, "invalid authority address") + } + + if msg.HostDenom == "" { + return errorsmod.Wrapf(sdkerrors.ErrNotFound, "missing host denom") + } + if msg.RewardDenom == "" { + return errorsmod.Wrapf(sdkerrors.ErrNotFound, "missing reward denom") + } + + if msg.PoolId < 1 { + return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "invalid pool id") + } + if msg.MaxSwapAmount.GT(sdkmath.ZeroInt()) && msg.MinSwapAmount.GT(msg.MaxSwapAmount) { + return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "min swap amount cannot be greater than max swap amount") + } + maxAllowedSwapLossRate, err := sdk.NewDecFromStr(msg.MaxAllowedSwapLossRate) + if err != nil { + return errorsmod.Wrapf(err, "unable to cast max allowed swap loss rate to a decimal") + } + if maxAllowedSwapLossRate.LT(sdk.ZeroDec()) || maxAllowedSwapLossRate.GT(sdk.OneDec()) { + return errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "max allowed swap loss rate must be between 0 and 1") + } + + return nil +} diff --git a/x/stakeibc/types/message_update_trade_route_test.go b/x/stakeibc/types/message_update_trade_route_test.go new file mode 100644 index 000000000..1f1643069 --- /dev/null +++ b/x/stakeibc/types/message_update_trade_route_test.go @@ -0,0 +1,164 @@ +package types_test + +import ( + "testing" + + sdkmath "cosmossdk.io/math" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + "github.com/stretchr/testify/require" + + "github.com/Stride-Labs/stride/v16/app/apptesting" + "github.com/Stride-Labs/stride/v16/x/stakeibc/types" +) + +func TestMsgUpdateTradeRoute(t *testing.T) { + apptesting.SetupConfig() + + authority := authtypes.NewModuleAddress(govtypes.ModuleName).String() + + validDenom := "denom" + validPoolId := uint64(1) + validMaxAllowedSwapLossRate := "0.05" + validMinSwapAmount := sdkmath.NewInt(100) + validMaxSwapAmount := sdkmath.NewInt(10000) + + tests := []struct { + name string + msg types.MsgUpdateTradeRoute + err string + }{ + { + name: "successful message", + msg: types.MsgUpdateTradeRoute{ + Authority: authority, + HostDenom: validDenom, + RewardDenom: validDenom, + PoolId: validPoolId, + MaxAllowedSwapLossRate: validMaxAllowedSwapLossRate, + MinSwapAmount: validMinSwapAmount, + MaxSwapAmount: validMaxSwapAmount, + }, + }, + { + name: "invalid authority", + msg: types.MsgUpdateTradeRoute{ + Authority: "", + HostDenom: validDenom, + RewardDenom: validDenom, + PoolId: validPoolId, + MaxAllowedSwapLossRate: validMaxAllowedSwapLossRate, + MinSwapAmount: validMinSwapAmount, + MaxSwapAmount: validMaxSwapAmount, + }, + err: "invalid authority address", + }, + { + name: "invalid host denom", + msg: types.MsgUpdateTradeRoute{ + Authority: authority, + HostDenom: "", + RewardDenom: validDenom, + PoolId: validPoolId, + MaxAllowedSwapLossRate: validMaxAllowedSwapLossRate, + MinSwapAmount: validMinSwapAmount, + MaxSwapAmount: validMaxSwapAmount, + }, + err: "missing host denom", + }, + { + name: "invalid reward denom", + msg: types.MsgUpdateTradeRoute{ + Authority: authority, + HostDenom: validDenom, + RewardDenom: "", + PoolId: validPoolId, + MaxAllowedSwapLossRate: validMaxAllowedSwapLossRate, + MinSwapAmount: validMinSwapAmount, + MaxSwapAmount: validMaxSwapAmount, + }, + err: "missing reward denom", + }, + { + name: "invalid pool id", + msg: types.MsgUpdateTradeRoute{ + Authority: authority, + HostDenom: validDenom, + RewardDenom: validDenom, + PoolId: 0, + MaxAllowedSwapLossRate: validMaxAllowedSwapLossRate, + MinSwapAmount: validMinSwapAmount, + MaxSwapAmount: validMaxSwapAmount, + }, + err: "invalid pool id", + }, + { + name: "invalid swap loss rate - negative", + msg: types.MsgUpdateTradeRoute{ + Authority: authority, + HostDenom: validDenom, + RewardDenom: validDenom, + PoolId: validPoolId, + MaxAllowedSwapLossRate: "-0.01", + MinSwapAmount: validMinSwapAmount, + MaxSwapAmount: validMaxSwapAmount, + }, + err: "max allowed swap loss rate must be between 0 and 1", + }, + { + name: "invalid swap loss rate - greater than 1", + msg: types.MsgUpdateTradeRoute{ + Authority: authority, + HostDenom: validDenom, + RewardDenom: validDenom, + PoolId: validPoolId, + MaxAllowedSwapLossRate: "1.01", + MinSwapAmount: validMinSwapAmount, + MaxSwapAmount: validMaxSwapAmount, + }, + err: "max allowed swap loss rate must be between 0 and 1", + }, + { + name: "invalid swap loss rate - can't cast", + msg: types.MsgUpdateTradeRoute{ + Authority: authority, + HostDenom: validDenom, + RewardDenom: validDenom, + PoolId: validPoolId, + MaxAllowedSwapLossRate: "", + MinSwapAmount: validMinSwapAmount, + MaxSwapAmount: validMaxSwapAmount, + }, + err: "unable to cast max allowed swap loss rate to a decimal", + }, + { + name: "invalid min/max swap amount", + msg: types.MsgUpdateTradeRoute{ + Authority: authority, + HostDenom: validDenom, + RewardDenom: validDenom, + PoolId: validPoolId, + MaxAllowedSwapLossRate: validMaxAllowedSwapLossRate, + MinSwapAmount: sdkmath.NewInt(10), + MaxSwapAmount: sdkmath.NewInt(5), + }, + err: "min swap amount cannot be greater than max swap amount", + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + if test.err == "" { + require.NoError(t, test.msg.ValidateBasic(), "test: %v", test.name) + require.Equal(t, test.msg.Route(), types.RouterKey) + require.Equal(t, test.msg.Type(), "update_trade_route") + + signers := test.msg.GetSigners() + require.Equal(t, len(signers), 1) + require.Equal(t, signers[0].String(), authority) + } else { + require.ErrorContains(t, test.msg.ValidateBasic(), test.err, "test: %v", test.name) + } + }) + } +} diff --git a/x/stakeibc/types/osmosis.pb.go b/x/stakeibc/types/osmosis.pb.go new file mode 100644 index 000000000..87e2564c2 --- /dev/null +++ b/x/stakeibc/types/osmosis.pb.go @@ -0,0 +1,1370 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: osmosis/gamm/v1beta1/osmosis.proto + +package types + +import ( + cosmossdk_io_math "cosmossdk.io/math" + fmt "fmt" + types "github.com/cosmos/cosmos-sdk/types" + _ "github.com/cosmos/cosmos-sdk/types/tx/amino" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + _ "github.com/cosmos/gogoproto/types" + github_com_cosmos_gogoproto_types "github.com/cosmos/gogoproto/types" + io "io" + math "math" + math_bits "math/bits" + time "time" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf +var _ = time.Kitchen + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// MsgSwapExactAmountIn stores the tx Msg type to swap tokens in the trade ICA +type MsgSwapExactAmountIn struct { + Sender string `protobuf:"bytes,1,opt,name=sender,proto3" json:"sender,omitempty" yaml:"sender"` + Routes []SwapAmountInRoute `protobuf:"bytes,2,rep,name=routes,proto3" json:"routes"` + TokenIn types.Coin `protobuf:"bytes,3,opt,name=token_in,json=tokenIn,proto3" json:"token_in" yaml:"token_in"` + TokenOutMinAmount cosmossdk_io_math.Int `protobuf:"bytes,4,opt,name=token_out_min_amount,json=tokenOutMinAmount,proto3,customtype=cosmossdk.io/math.Int" json:"token_out_min_amount" yaml:"token_out_min_amount"` +} + +func (m *MsgSwapExactAmountIn) Reset() { *m = MsgSwapExactAmountIn{} } +func (m *MsgSwapExactAmountIn) String() string { return proto.CompactTextString(m) } +func (*MsgSwapExactAmountIn) ProtoMessage() {} +func (*MsgSwapExactAmountIn) Descriptor() ([]byte, []int) { + return fileDescriptor_39668b2e9488de8c, []int{0} +} +func (m *MsgSwapExactAmountIn) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgSwapExactAmountIn) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgSwapExactAmountIn.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 *MsgSwapExactAmountIn) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgSwapExactAmountIn.Merge(m, src) +} +func (m *MsgSwapExactAmountIn) XXX_Size() int { + return m.Size() +} +func (m *MsgSwapExactAmountIn) XXX_DiscardUnknown() { + xxx_messageInfo_MsgSwapExactAmountIn.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgSwapExactAmountIn proto.InternalMessageInfo + +func (m *MsgSwapExactAmountIn) GetSender() string { + if m != nil { + return m.Sender + } + return "" +} + +func (m *MsgSwapExactAmountIn) GetRoutes() []SwapAmountInRoute { + if m != nil { + return m.Routes + } + return nil +} + +func (m *MsgSwapExactAmountIn) GetTokenIn() types.Coin { + if m != nil { + return m.TokenIn + } + return types.Coin{} +} + +type SwapAmountInRoute struct { + PoolId uint64 `protobuf:"varint,1,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty" yaml:"pool_id"` + TokenOutDenom string `protobuf:"bytes,2,opt,name=token_out_denom,json=tokenOutDenom,proto3" json:"token_out_denom,omitempty" yaml:"token_out_denom"` +} + +func (m *SwapAmountInRoute) Reset() { *m = SwapAmountInRoute{} } +func (m *SwapAmountInRoute) String() string { return proto.CompactTextString(m) } +func (*SwapAmountInRoute) ProtoMessage() {} +func (*SwapAmountInRoute) Descriptor() ([]byte, []int) { + return fileDescriptor_39668b2e9488de8c, []int{1} +} +func (m *SwapAmountInRoute) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SwapAmountInRoute) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SwapAmountInRoute.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 *SwapAmountInRoute) XXX_Merge(src proto.Message) { + xxx_messageInfo_SwapAmountInRoute.Merge(m, src) +} +func (m *SwapAmountInRoute) XXX_Size() int { + return m.Size() +} +func (m *SwapAmountInRoute) XXX_DiscardUnknown() { + xxx_messageInfo_SwapAmountInRoute.DiscardUnknown(m) +} + +var xxx_messageInfo_SwapAmountInRoute proto.InternalMessageInfo + +func (m *SwapAmountInRoute) GetPoolId() uint64 { + if m != nil { + return m.PoolId + } + return 0 +} + +func (m *SwapAmountInRoute) GetTokenOutDenom() string { + if m != nil { + return m.TokenOutDenom + } + return "" +} + +// A TwapRecord stores the most recent price of a pair of denom's +type OsmosisTwapRecord struct { + PoolId uint64 `protobuf:"varint,1,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` + // Lexicographically smaller denom of the pair + Asset0Denom string `protobuf:"bytes,2,opt,name=asset0_denom,json=asset0Denom,proto3" json:"asset0_denom,omitempty"` + // Lexicographically larger denom of the pair + Asset1Denom string `protobuf:"bytes,3,opt,name=asset1_denom,json=asset1Denom,proto3" json:"asset1_denom,omitempty"` + // height this record corresponds to, for debugging purposes + Height int64 `protobuf:"varint,4,opt,name=height,proto3" json:"record_height" yaml:"record_height"` + // This field should only exist until we have a global registry in the state + // machine, mapping prior block heights within {TIME RANGE} to times. + Time time.Time `protobuf:"bytes,5,opt,name=time,proto3,stdtime" json:"time" yaml:"record_time"` + // We store the last spot prices in the struct, so that we can interpolate + // accumulator values for times between when accumulator records are stored. + P0LastSpotPrice cosmossdk_io_math.LegacyDec `protobuf:"bytes,6,opt,name=p0_last_spot_price,json=p0LastSpotPrice,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"p0_last_spot_price"` + P1LastSpotPrice cosmossdk_io_math.LegacyDec `protobuf:"bytes,7,opt,name=p1_last_spot_price,json=p1LastSpotPrice,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"p1_last_spot_price"` + P0ArithmeticTwapAccumulator cosmossdk_io_math.LegacyDec `protobuf:"bytes,8,opt,name=p0_arithmetic_twap_accumulator,json=p0ArithmeticTwapAccumulator,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"p0_arithmetic_twap_accumulator"` + P1ArithmeticTwapAccumulator cosmossdk_io_math.LegacyDec `protobuf:"bytes,9,opt,name=p1_arithmetic_twap_accumulator,json=p1ArithmeticTwapAccumulator,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"p1_arithmetic_twap_accumulator"` + GeometricTwapAccumulator cosmossdk_io_math.LegacyDec `protobuf:"bytes,10,opt,name=geometric_twap_accumulator,json=geometricTwapAccumulator,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"geometric_twap_accumulator"` + // This field contains the time in which the last spot price error occured. + // It is used to alert the caller if they are getting a potentially erroneous + // TWAP, due to an unforeseen underlying error. + LastErrorTime time.Time `protobuf:"bytes,11,opt,name=last_error_time,json=lastErrorTime,proto3,stdtime" json:"last_error_time" yaml:"last_error_time"` +} + +func (m *OsmosisTwapRecord) Reset() { *m = OsmosisTwapRecord{} } +func (m *OsmosisTwapRecord) String() string { return proto.CompactTextString(m) } +func (*OsmosisTwapRecord) ProtoMessage() {} +func (*OsmosisTwapRecord) Descriptor() ([]byte, []int) { + return fileDescriptor_39668b2e9488de8c, []int{2} +} +func (m *OsmosisTwapRecord) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *OsmosisTwapRecord) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_OsmosisTwapRecord.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 *OsmosisTwapRecord) XXX_Merge(src proto.Message) { + xxx_messageInfo_OsmosisTwapRecord.Merge(m, src) +} +func (m *OsmosisTwapRecord) XXX_Size() int { + return m.Size() +} +func (m *OsmosisTwapRecord) XXX_DiscardUnknown() { + xxx_messageInfo_OsmosisTwapRecord.DiscardUnknown(m) +} + +var xxx_messageInfo_OsmosisTwapRecord proto.InternalMessageInfo + +func (m *OsmosisTwapRecord) GetPoolId() uint64 { + if m != nil { + return m.PoolId + } + return 0 +} + +func (m *OsmosisTwapRecord) GetAsset0Denom() string { + if m != nil { + return m.Asset0Denom + } + return "" +} + +func (m *OsmosisTwapRecord) GetAsset1Denom() string { + if m != nil { + return m.Asset1Denom + } + return "" +} + +func (m *OsmosisTwapRecord) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *OsmosisTwapRecord) GetTime() time.Time { + if m != nil { + return m.Time + } + return time.Time{} +} + +func (m *OsmosisTwapRecord) GetLastErrorTime() time.Time { + if m != nil { + return m.LastErrorTime + } + return time.Time{} +} + +func init() { + proto.RegisterType((*MsgSwapExactAmountIn)(nil), "osmosis.gamm.v1beta1.MsgSwapExactAmountIn") + proto.RegisterType((*SwapAmountInRoute)(nil), "osmosis.gamm.v1beta1.SwapAmountInRoute") + proto.RegisterType((*OsmosisTwapRecord)(nil), "osmosis.gamm.v1beta1.OsmosisTwapRecord") +} + +func init() { + proto.RegisterFile("osmosis/gamm/v1beta1/osmosis.proto", fileDescriptor_39668b2e9488de8c) +} + +var fileDescriptor_39668b2e9488de8c = []byte{ + // 774 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x53, 0x4f, 0x6f, 0xe3, 0x44, + 0x14, 0x8f, 0x9b, 0x90, 0xee, 0x4e, 0x08, 0x51, 0xac, 0xc0, 0x9a, 0x54, 0xb2, 0xbb, 0x46, 0x82, + 0x2e, 0x28, 0x76, 0x5c, 0x24, 0x0e, 0x2b, 0x2e, 0x31, 0xdb, 0x43, 0xa4, 0x94, 0x5d, 0xb9, 0x7b, + 0xe2, 0x62, 0x4d, 0x9c, 0xa9, 0x33, 0x6a, 0xc6, 0x63, 0x79, 0xc6, 0x4d, 0x7b, 0xe7, 0xc4, 0xa9, + 0x1f, 0x85, 0x8f, 0xd1, 0x63, 0x8f, 0x88, 0x83, 0x41, 0xed, 0x01, 0x89, 0x03, 0x87, 0x7c, 0x02, + 0x34, 0x33, 0x4e, 0xda, 0xa4, 0x85, 0x6d, 0x2f, 0xd1, 0xf8, 0xcd, 0xef, 0xcf, 0x7b, 0xf3, 0x7e, + 0x01, 0x36, 0x65, 0x84, 0x32, 0xcc, 0xdc, 0x18, 0x12, 0xe2, 0x9e, 0x7a, 0x63, 0xc4, 0xa1, 0xe7, + 0x96, 0x45, 0x27, 0xcd, 0x28, 0xa7, 0x7a, 0x67, 0xf9, 0x29, 0x30, 0x4e, 0x89, 0xe9, 0x76, 0x62, + 0x1a, 0x53, 0x09, 0x70, 0xc5, 0x49, 0x61, 0xbb, 0x6d, 0x48, 0x70, 0x42, 0x5d, 0xf9, 0x5b, 0x96, + 0xcc, 0x48, 0xf2, 0xdd, 0x31, 0x64, 0x68, 0xe5, 0x10, 0x51, 0x9c, 0x94, 0xf7, 0x56, 0x4c, 0x69, + 0x3c, 0x43, 0xae, 0xfc, 0x1a, 0xe7, 0xc7, 0x2e, 0xc7, 0x04, 0x31, 0x0e, 0x49, 0xaa, 0x00, 0xf6, + 0x3f, 0x5b, 0xa0, 0x73, 0xc8, 0xe2, 0xa3, 0x39, 0x4c, 0x0f, 0xce, 0x60, 0xc4, 0x07, 0x84, 0xe6, + 0x09, 0x1f, 0x26, 0xfa, 0x2b, 0x50, 0x67, 0x28, 0x99, 0xa0, 0xcc, 0xd0, 0x76, 0xb5, 0xbd, 0xe7, + 0x7e, 0x7b, 0x51, 0x58, 0xcd, 0x73, 0x48, 0x66, 0xaf, 0x6d, 0x55, 0xb7, 0x83, 0x12, 0xa0, 0x1f, + 0x80, 0x7a, 0x46, 0x73, 0x8e, 0x98, 0xb1, 0xb5, 0x5b, 0xdd, 0x6b, 0xec, 0x7f, 0xe5, 0x3c, 0x34, + 0x94, 0x23, 0x3c, 0x96, 0xf2, 0x81, 0xc0, 0xfb, 0xb5, 0xcb, 0xc2, 0xaa, 0x04, 0x25, 0x59, 0x3f, + 0x04, 0xcf, 0x38, 0x3d, 0x41, 0x49, 0x88, 0x13, 0xa3, 0xba, 0xab, 0xed, 0x35, 0xf6, 0x3f, 0x77, + 0xd4, 0x78, 0x8e, 0x18, 0x6f, 0xa5, 0xf3, 0x03, 0xc5, 0x89, 0xff, 0x42, 0x50, 0x17, 0x85, 0xd5, + 0x52, 0x2d, 0x2d, 0x89, 0x76, 0xb0, 0x2d, 0x8f, 0xc3, 0x44, 0x27, 0xa0, 0xa3, 0xaa, 0x34, 0xe7, + 0x21, 0xc1, 0x49, 0x08, 0xa5, 0xb7, 0x51, 0x93, 0xe3, 0x7c, 0x2f, 0xf8, 0xbf, 0x17, 0xd6, 0xa7, + 0xca, 0x81, 0x4d, 0x4e, 0x1c, 0x4c, 0x5d, 0x02, 0xf9, 0xd4, 0x19, 0x26, 0x7c, 0x51, 0x58, 0x3b, + 0x77, 0x85, 0xd7, 0x25, 0xec, 0xa0, 0x2d, 0xcb, 0x6f, 0x73, 0x7e, 0x88, 0x13, 0x35, 0xd2, 0xeb, + 0x2f, 0x7f, 0xf9, 0xeb, 0xd7, 0xaf, 0x5f, 0xae, 0x6d, 0x9c, 0xcd, 0x61, 0xda, 0x43, 0xe2, 0x55, + 0x7b, 0x8a, 0xd8, 0xc3, 0x89, 0xfd, 0xb3, 0x06, 0xda, 0xf7, 0x5e, 0x42, 0xff, 0x06, 0x6c, 0xa7, + 0x94, 0xce, 0x42, 0x3c, 0x91, 0xcf, 0x5d, 0xf3, 0xf5, 0x45, 0x61, 0x7d, 0xa2, 0x5a, 0x28, 0x2f, + 0xec, 0xa0, 0x2e, 0x4e, 0xc3, 0x89, 0xee, 0x83, 0xd6, 0x6d, 0x5b, 0x13, 0x94, 0x50, 0x62, 0x6c, + 0xc9, 0xa1, 0xba, 0x8b, 0xc2, 0xfa, 0x6c, 0xb3, 0x6f, 0x09, 0xb0, 0x83, 0xe6, 0xb2, 0xe5, 0x37, + 0xf2, 0xfb, 0xb2, 0x0e, 0xda, 0x6f, 0x55, 0xb3, 0xef, 0xe7, 0x30, 0x0d, 0x50, 0x44, 0xb3, 0x89, + 0xfe, 0x62, 0xa3, 0x8d, 0x95, 0xe5, 0x4b, 0xf0, 0x31, 0x64, 0x0c, 0xf1, 0xfe, 0x5d, 0xbf, 0xa0, + 0xa1, 0x6a, 0x52, 0x71, 0x05, 0xf1, 0x4a, 0x48, 0xf5, 0x0e, 0xc4, 0x53, 0x90, 0x01, 0xa8, 0x4f, + 0x11, 0x8e, 0xa7, 0x6a, 0x09, 0x55, 0xff, 0xd5, 0xdf, 0x85, 0xd5, 0xcc, 0xa4, 0x75, 0xa8, 0x2e, + 0x16, 0x85, 0xd5, 0x51, 0x03, 0xac, 0x95, 0xed, 0xa0, 0x24, 0xea, 0x3f, 0x82, 0x9a, 0x88, 0xb0, + 0xf1, 0x91, 0x0c, 0x48, 0xd7, 0x51, 0xf9, 0x76, 0x96, 0xf9, 0x76, 0xde, 0x2f, 0xf3, 0xed, 0x9b, + 0x65, 0x42, 0xf4, 0x35, 0x3d, 0x41, 0xb6, 0x2f, 0xfe, 0xb0, 0xb4, 0x40, 0xea, 0xe8, 0xef, 0x80, + 0x9e, 0xf6, 0xc3, 0x19, 0x64, 0x3c, 0x64, 0x29, 0xe5, 0x61, 0x9a, 0xe1, 0x08, 0x19, 0x75, 0xf9, + 0x9c, 0x5f, 0x94, 0x19, 0xd9, 0xb9, 0x9f, 0x91, 0x11, 0x8a, 0x61, 0x74, 0xfe, 0x06, 0x45, 0x41, + 0x2b, 0xed, 0x8f, 0x20, 0xe3, 0x47, 0x29, 0xe5, 0xef, 0x04, 0x57, 0x2a, 0x7a, 0xf7, 0x14, 0xb7, + 0x9f, 0xa2, 0xe8, 0xad, 0x2b, 0x4e, 0x81, 0x99, 0xf6, 0x43, 0x98, 0x61, 0x3e, 0x25, 0x88, 0xe3, + 0x28, 0xe4, 0x73, 0x98, 0x86, 0x30, 0x8a, 0x72, 0x92, 0xcf, 0x20, 0xa7, 0x99, 0xf1, 0xec, 0xf1, + 0xea, 0x3b, 0x69, 0x7f, 0xb0, 0x52, 0x12, 0xab, 0x1f, 0xdc, 0xea, 0x48, 0x27, 0xef, 0x7f, 0x9d, + 0x9e, 0x3f, 0xc5, 0xc9, 0xfb, 0x6f, 0x27, 0x08, 0xba, 0x31, 0xa2, 0x04, 0xf1, 0xec, 0x21, 0x17, + 0xf0, 0x78, 0x17, 0x63, 0x25, 0xb3, 0x69, 0x71, 0x0c, 0x5a, 0x72, 0x0b, 0x28, 0xcb, 0x68, 0x26, + 0x17, 0x6f, 0x34, 0x3e, 0x98, 0x1a, 0xbb, 0x4c, 0x4d, 0xf9, 0x37, 0xda, 0x10, 0x50, 0xc9, 0x69, + 0x8a, 0xea, 0x81, 0x28, 0x0a, 0x9e, 0x3f, 0xba, 0xbc, 0x36, 0xb5, 0xab, 0x6b, 0x53, 0xfb, 0xf3, + 0xda, 0xd4, 0x2e, 0x6e, 0xcc, 0xca, 0xd5, 0x8d, 0x59, 0xf9, 0xed, 0xc6, 0xac, 0xfc, 0xb4, 0x1f, + 0x63, 0x3e, 0xcd, 0xc7, 0x4e, 0x44, 0x89, 0x7b, 0xc4, 0x33, 0x3c, 0x41, 0xbd, 0x11, 0x1c, 0x33, + 0x97, 0xc9, 0xb3, 0x7b, 0xea, 0x7d, 0xe7, 0x9e, 0xb9, 0x8c, 0xc3, 0x13, 0x84, 0xc7, 0x91, 0xcb, + 0xcf, 0x53, 0xc4, 0xc6, 0x75, 0xd9, 0xd4, 0xb7, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0x7e, 0xfc, + 0x9f, 0x22, 0x3d, 0x06, 0x00, 0x00, +} + +func (m *MsgSwapExactAmountIn) 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 *MsgSwapExactAmountIn) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgSwapExactAmountIn) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size := m.TokenOutMinAmount.Size() + i -= size + if _, err := m.TokenOutMinAmount.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintOsmosis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + { + size, err := m.TokenIn.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintOsmosis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + if len(m.Routes) > 0 { + for iNdEx := len(m.Routes) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Routes[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintOsmosis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if len(m.Sender) > 0 { + i -= len(m.Sender) + copy(dAtA[i:], m.Sender) + i = encodeVarintOsmosis(dAtA, i, uint64(len(m.Sender))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *SwapAmountInRoute) 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 *SwapAmountInRoute) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SwapAmountInRoute) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.TokenOutDenom) > 0 { + i -= len(m.TokenOutDenom) + copy(dAtA[i:], m.TokenOutDenom) + i = encodeVarintOsmosis(dAtA, i, uint64(len(m.TokenOutDenom))) + i-- + dAtA[i] = 0x12 + } + if m.PoolId != 0 { + i = encodeVarintOsmosis(dAtA, i, uint64(m.PoolId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *OsmosisTwapRecord) 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 *OsmosisTwapRecord) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *OsmosisTwapRecord) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + n2, err2 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.LastErrorTime, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.LastErrorTime):]) + if err2 != nil { + return 0, err2 + } + i -= n2 + i = encodeVarintOsmosis(dAtA, i, uint64(n2)) + i-- + dAtA[i] = 0x5a + { + size := m.GeometricTwapAccumulator.Size() + i -= size + if _, err := m.GeometricTwapAccumulator.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintOsmosis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x52 + { + size := m.P1ArithmeticTwapAccumulator.Size() + i -= size + if _, err := m.P1ArithmeticTwapAccumulator.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintOsmosis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x4a + { + size := m.P0ArithmeticTwapAccumulator.Size() + i -= size + if _, err := m.P0ArithmeticTwapAccumulator.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintOsmosis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x42 + { + size := m.P1LastSpotPrice.Size() + i -= size + if _, err := m.P1LastSpotPrice.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintOsmosis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + { + size := m.P0LastSpotPrice.Size() + i -= size + if _, err := m.P0LastSpotPrice.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintOsmosis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + n3, err3 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Time):]) + if err3 != nil { + return 0, err3 + } + i -= n3 + i = encodeVarintOsmosis(dAtA, i, uint64(n3)) + i-- + dAtA[i] = 0x2a + if m.Height != 0 { + i = encodeVarintOsmosis(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x20 + } + if len(m.Asset1Denom) > 0 { + i -= len(m.Asset1Denom) + copy(dAtA[i:], m.Asset1Denom) + i = encodeVarintOsmosis(dAtA, i, uint64(len(m.Asset1Denom))) + i-- + dAtA[i] = 0x1a + } + if len(m.Asset0Denom) > 0 { + i -= len(m.Asset0Denom) + copy(dAtA[i:], m.Asset0Denom) + i = encodeVarintOsmosis(dAtA, i, uint64(len(m.Asset0Denom))) + i-- + dAtA[i] = 0x12 + } + if m.PoolId != 0 { + i = encodeVarintOsmosis(dAtA, i, uint64(m.PoolId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func encodeVarintOsmosis(dAtA []byte, offset int, v uint64) int { + offset -= sovOsmosis(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *MsgSwapExactAmountIn) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Sender) + if l > 0 { + n += 1 + l + sovOsmosis(uint64(l)) + } + if len(m.Routes) > 0 { + for _, e := range m.Routes { + l = e.Size() + n += 1 + l + sovOsmosis(uint64(l)) + } + } + l = m.TokenIn.Size() + n += 1 + l + sovOsmosis(uint64(l)) + l = m.TokenOutMinAmount.Size() + n += 1 + l + sovOsmosis(uint64(l)) + return n +} + +func (m *SwapAmountInRoute) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PoolId != 0 { + n += 1 + sovOsmosis(uint64(m.PoolId)) + } + l = len(m.TokenOutDenom) + if l > 0 { + n += 1 + l + sovOsmosis(uint64(l)) + } + return n +} + +func (m *OsmosisTwapRecord) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PoolId != 0 { + n += 1 + sovOsmosis(uint64(m.PoolId)) + } + l = len(m.Asset0Denom) + if l > 0 { + n += 1 + l + sovOsmosis(uint64(l)) + } + l = len(m.Asset1Denom) + if l > 0 { + n += 1 + l + sovOsmosis(uint64(l)) + } + if m.Height != 0 { + n += 1 + sovOsmosis(uint64(m.Height)) + } + l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Time) + n += 1 + l + sovOsmosis(uint64(l)) + l = m.P0LastSpotPrice.Size() + n += 1 + l + sovOsmosis(uint64(l)) + l = m.P1LastSpotPrice.Size() + n += 1 + l + sovOsmosis(uint64(l)) + l = m.P0ArithmeticTwapAccumulator.Size() + n += 1 + l + sovOsmosis(uint64(l)) + l = m.P1ArithmeticTwapAccumulator.Size() + n += 1 + l + sovOsmosis(uint64(l)) + l = m.GeometricTwapAccumulator.Size() + n += 1 + l + sovOsmosis(uint64(l)) + l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.LastErrorTime) + n += 1 + l + sovOsmosis(uint64(l)) + return n +} + +func sovOsmosis(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozOsmosis(x uint64) (n int) { + return sovOsmosis(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *MsgSwapExactAmountIn) 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 ErrIntOverflowOsmosis + } + 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: MsgSwapExactAmountIn: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgSwapExactAmountIn: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sender", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOsmosis + } + 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 ErrInvalidLengthOsmosis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthOsmosis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Sender = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Routes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOsmosis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthOsmosis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthOsmosis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Routes = append(m.Routes, SwapAmountInRoute{}) + if err := m.Routes[len(m.Routes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TokenIn", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOsmosis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthOsmosis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthOsmosis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.TokenIn.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TokenOutMinAmount", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOsmosis + } + 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 ErrInvalidLengthOsmosis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthOsmosis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.TokenOutMinAmount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipOsmosis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthOsmosis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *SwapAmountInRoute) 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 ErrIntOverflowOsmosis + } + 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: SwapAmountInRoute: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SwapAmountInRoute: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PoolId", wireType) + } + m.PoolId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOsmosis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PoolId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TokenOutDenom", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOsmosis + } + 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 ErrInvalidLengthOsmosis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthOsmosis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.TokenOutDenom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipOsmosis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthOsmosis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *OsmosisTwapRecord) 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 ErrIntOverflowOsmosis + } + 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: OsmosisTwapRecord: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: OsmosisTwapRecord: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PoolId", wireType) + } + m.PoolId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOsmosis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PoolId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Asset0Denom", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOsmosis + } + 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 ErrInvalidLengthOsmosis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthOsmosis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Asset0Denom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Asset1Denom", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOsmosis + } + 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 ErrInvalidLengthOsmosis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthOsmosis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Asset1Denom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOsmosis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOsmosis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthOsmosis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthOsmosis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.Time, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field P0LastSpotPrice", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOsmosis + } + 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 ErrInvalidLengthOsmosis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthOsmosis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.P0LastSpotPrice.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field P1LastSpotPrice", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOsmosis + } + 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 ErrInvalidLengthOsmosis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthOsmosis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.P1LastSpotPrice.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field P0ArithmeticTwapAccumulator", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOsmosis + } + 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 ErrInvalidLengthOsmosis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthOsmosis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.P0ArithmeticTwapAccumulator.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field P1ArithmeticTwapAccumulator", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOsmosis + } + 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 ErrInvalidLengthOsmosis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthOsmosis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.P1ArithmeticTwapAccumulator.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field GeometricTwapAccumulator", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOsmosis + } + 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 ErrInvalidLengthOsmosis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthOsmosis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.GeometricTwapAccumulator.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LastErrorTime", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOsmosis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthOsmosis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthOsmosis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.LastErrorTime, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipOsmosis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthOsmosis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipOsmosis(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowOsmosis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowOsmosis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowOsmosis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthOsmosis + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupOsmosis + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthOsmosis + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthOsmosis = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowOsmosis = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupOsmosis = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/stakeibc/types/query.pb.go b/x/stakeibc/types/query.pb.go index e7ba7beff..4ebacfb2d 100644 --- a/x/stakeibc/types/query.pb.go +++ b/x/stakeibc/types/query.pb.go @@ -931,6 +931,86 @@ func (m *QueryAddressUnbondingsResponse) GetAddressUnbondings() []AddressUnbondi return nil } +type QueryAllTradeRoutes struct { +} + +func (m *QueryAllTradeRoutes) Reset() { *m = QueryAllTradeRoutes{} } +func (m *QueryAllTradeRoutes) String() string { return proto.CompactTextString(m) } +func (*QueryAllTradeRoutes) ProtoMessage() {} +func (*QueryAllTradeRoutes) Descriptor() ([]byte, []int) { + return fileDescriptor_494b786fe66f2b80, []int{20} +} +func (m *QueryAllTradeRoutes) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryAllTradeRoutes) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryAllTradeRoutes.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 *QueryAllTradeRoutes) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryAllTradeRoutes.Merge(m, src) +} +func (m *QueryAllTradeRoutes) XXX_Size() int { + return m.Size() +} +func (m *QueryAllTradeRoutes) XXX_DiscardUnknown() { + xxx_messageInfo_QueryAllTradeRoutes.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryAllTradeRoutes proto.InternalMessageInfo + +type QueryAllTradeRoutesResponse struct { + TradeRoutes []TradeRoute `protobuf:"bytes,1,rep,name=trade_routes,json=tradeRoutes,proto3" json:"trade_routes"` +} + +func (m *QueryAllTradeRoutesResponse) Reset() { *m = QueryAllTradeRoutesResponse{} } +func (m *QueryAllTradeRoutesResponse) String() string { return proto.CompactTextString(m) } +func (*QueryAllTradeRoutesResponse) ProtoMessage() {} +func (*QueryAllTradeRoutesResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_494b786fe66f2b80, []int{21} +} +func (m *QueryAllTradeRoutesResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryAllTradeRoutesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryAllTradeRoutesResponse.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 *QueryAllTradeRoutesResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryAllTradeRoutesResponse.Merge(m, src) +} +func (m *QueryAllTradeRoutesResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryAllTradeRoutesResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryAllTradeRoutesResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryAllTradeRoutesResponse proto.InternalMessageInfo + +func (m *QueryAllTradeRoutesResponse) GetTradeRoutes() []TradeRoute { + if m != nil { + return m.TradeRoutes + } + return nil +} + func init() { proto.RegisterType((*QueryInterchainAccountFromAddressRequest)(nil), "stride.stakeibc.QueryInterchainAccountFromAddressRequest") proto.RegisterType((*QueryInterchainAccountFromAddressResponse)(nil), "stride.stakeibc.QueryInterchainAccountFromAddressResponse") @@ -952,85 +1032,92 @@ func init() { proto.RegisterType((*QueryGetNextPacketSequenceResponse)(nil), "stride.stakeibc.QueryGetNextPacketSequenceResponse") proto.RegisterType((*QueryAddressUnbondings)(nil), "stride.stakeibc.QueryAddressUnbondings") proto.RegisterType((*QueryAddressUnbondingsResponse)(nil), "stride.stakeibc.QueryAddressUnbondingsResponse") + proto.RegisterType((*QueryAllTradeRoutes)(nil), "stride.stakeibc.QueryAllTradeRoutes") + proto.RegisterType((*QueryAllTradeRoutesResponse)(nil), "stride.stakeibc.QueryAllTradeRoutesResponse") } func init() { proto.RegisterFile("stride/stakeibc/query.proto", fileDescriptor_494b786fe66f2b80) } var fileDescriptor_494b786fe66f2b80 = []byte{ - // 1158 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x97, 0xdd, 0x6e, 0x1b, 0x45, - 0x1b, 0xc7, 0xb3, 0x4d, 0x9a, 0x8f, 0x27, 0x89, 0xf2, 0x76, 0xde, 0x88, 0x38, 0xdb, 0xc4, 0x21, - 0xd3, 0xd2, 0x7c, 0x90, 0x7a, 0x89, 0x53, 0x2a, 0x35, 0xa2, 0x82, 0x44, 0x6a, 0x1b, 0xa3, 0x80, - 0x82, 0x0b, 0x15, 0x2a, 0x07, 0xd6, 0x78, 0x77, 0xb0, 0x57, 0x5d, 0xcf, 0xb8, 0xbb, 0xeb, 0x90, - 0x10, 0x59, 0x95, 0xb8, 0x82, 0x0a, 0xc4, 0x09, 0x67, 0x45, 0x1c, 0x70, 0xcc, 0x55, 0xf4, 0x8c, - 0x4a, 0x9c, 0x70, 0x14, 0xa1, 0x84, 0x2b, 0xa8, 0xb8, 0x00, 0xb4, 0x33, 0xb3, 0x6b, 0x7b, 0x3f, - 0x8c, 0xd3, 0x33, 0xcf, 0xcc, 0xf3, 0xf1, 0x9b, 0x67, 0x9e, 0xf9, 0xcf, 0x1a, 0xae, 0x7a, 0xbe, - 0x6b, 0x5b, 0xd4, 0xf0, 0x7c, 0xf2, 0x84, 0xda, 0x55, 0xd3, 0x78, 0xda, 0xa2, 0xee, 0x71, 0xa1, - 0xe9, 0x72, 0x9f, 0xa3, 0x19, 0xb9, 0x58, 0x08, 0x17, 0xf5, 0xd9, 0x1a, 0xaf, 0x71, 0xb1, 0x66, - 0x04, 0xbf, 0xa4, 0x99, 0xbe, 0x50, 0xe3, 0xbc, 0xe6, 0x50, 0x83, 0x34, 0x6d, 0x83, 0x30, 0xc6, - 0x7d, 0xe2, 0xdb, 0x9c, 0x79, 0x6a, 0x75, 0xdd, 0xe4, 0x5e, 0x83, 0x7b, 0x46, 0x95, 0x78, 0x54, - 0x46, 0x37, 0x0e, 0x37, 0xab, 0xd4, 0x27, 0x9b, 0x46, 0x93, 0xd4, 0x6c, 0x26, 0x8c, 0xc3, 0x48, - 0x71, 0x9a, 0x26, 0x71, 0x49, 0x23, 0x8c, 0xb4, 0x14, 0x5f, 0x3d, 0x24, 0x8e, 0x6d, 0x11, 0x9f, - 0xbb, 0x59, 0x06, 0x75, 0xee, 0xf9, 0x95, 0x6f, 0x39, 0xa3, 0xca, 0xe0, 0x5a, 0xdc, 0x80, 0x36, - 0xb9, 0x59, 0xaf, 0xf8, 0x2e, 0x31, 0x9f, 0xd0, 0x30, 0xca, 0x4a, 0xdc, 0x88, 0x58, 0x96, 0x4b, - 0x3d, 0xaf, 0xd2, 0x62, 0x55, 0xce, 0x2c, 0x9b, 0xd5, 0xa4, 0x21, 0x7e, 0x06, 0xab, 0x9f, 0x05, - 0xfb, 0x29, 0x31, 0x9f, 0xba, 0x66, 0x9d, 0xd8, 0x6c, 0xc7, 0x34, 0x79, 0x8b, 0xf9, 0xf7, 0x5d, - 0xde, 0xd8, 0x91, 0x4e, 0x65, 0xfa, 0xb4, 0x45, 0x3d, 0x1f, 0xcd, 0xc2, 0x65, 0xfe, 0x0d, 0xa3, - 0x6e, 0x4e, 0x7b, 0x5b, 0x5b, 0x9d, 0x28, 0xcb, 0x01, 0xba, 0x0b, 0xd3, 0x26, 0x67, 0x8c, 0x9a, - 0x41, 0x0d, 0x2a, 0xb6, 0x95, 0xbb, 0x14, 0xac, 0xee, 0xe6, 0x5e, 0x9f, 0x2e, 0xcd, 0x1e, 0x93, - 0x86, 0xb3, 0x8d, 0x7b, 0x96, 0x71, 0x79, 0xaa, 0x33, 0x2e, 0x59, 0xf8, 0xb9, 0x06, 0x6b, 0x03, - 0x10, 0x78, 0x4d, 0xce, 0x3c, 0x8a, 0x4c, 0xd0, 0xed, 0xc8, 0xae, 0x42, 0xa4, 0x61, 0x45, 0x6d, - 0x4e, 0x72, 0xed, 0xbe, 0xf3, 0xfa, 0x74, 0x69, 0x59, 0x66, 0xce, 0xb6, 0xc5, 0xe5, 0x9c, 0x1d, - 0x4f, 0xa8, 0x92, 0xe1, 0x59, 0x40, 0x82, 0xe8, 0x40, 0x1c, 0x9c, 0xda, 0x3d, 0xde, 0x87, 0xff, - 0xf7, 0xcc, 0x2a, 0xa2, 0xf7, 0x61, 0x54, 0x1e, 0xb0, 0xc8, 0x3e, 0x59, 0x9c, 0x2b, 0xc4, 0x1a, - 0xae, 0x20, 0x1d, 0x76, 0x47, 0x5e, 0x9e, 0x2e, 0x0d, 0x95, 0x95, 0x31, 0xbe, 0x0d, 0xf3, 0x22, - 0xda, 0x03, 0xea, 0x3f, 0x0a, 0x3b, 0x20, 0x2a, 0xf4, 0x3c, 0x8c, 0x4b, 0x68, 0xdb, 0x52, 0xb5, - 0x1e, 0x13, 0xe3, 0x92, 0x85, 0xbf, 0x04, 0x3d, 0xcd, 0x4f, 0xc1, 0x6c, 0x03, 0x44, 0xfd, 0x14, - 0x00, 0x0d, 0xaf, 0x4e, 0x16, 0xf5, 0x04, 0x50, 0xe4, 0x58, 0xee, 0xb2, 0xc6, 0xb7, 0x60, 0x2e, - 0x8c, 0xbc, 0xc7, 0x3d, 0xff, 0x31, 0x67, 0x74, 0x20, 0x9e, 0x5c, 0xd2, 0x4b, 0xd1, 0x7c, 0x00, - 0x13, 0x51, 0xf3, 0xaa, 0xea, 0xcc, 0x27, 0x60, 0x42, 0x2f, 0x55, 0x9f, 0xf1, 0xba, 0x1a, 0x63, - 0xa2, 0x78, 0x76, 0x1c, 0x27, 0xce, 0x73, 0x1f, 0xa0, 0x73, 0xed, 0x54, 0xe4, 0x1b, 0x05, 0x79, - 0x47, 0x0b, 0xc1, 0x1d, 0x2d, 0x48, 0x05, 0x50, 0x77, 0xb4, 0x70, 0x40, 0x6a, 0xa1, 0x6f, 0xb9, - 0xcb, 0x13, 0xbf, 0xd0, 0x14, 0x7d, 0x4f, 0x8e, 0x74, 0xfa, 0xe1, 0x0b, 0xd1, 0xa3, 0x07, 0x3d, - 0x88, 0x97, 0x04, 0xe2, 0xca, 0x7f, 0x22, 0xca, 0xd4, 0x3d, 0x8c, 0x86, 0x6a, 0x94, 0x4f, 0xb8, - 0xd5, 0x72, 0x68, 0xec, 0x46, 0x22, 0x18, 0x61, 0xa4, 0x41, 0xd5, 0xa1, 0x88, 0xdf, 0xf8, 0x3d, - 0xd5, 0x21, 0x31, 0x07, 0xb5, 0x2b, 0x04, 0x23, 0xc1, 0x0d, 0x08, 0x3d, 0x82, 0xdf, 0x78, 0x0f, - 0xae, 0x86, 0x67, 0x78, 0x2f, 0xd0, 0x92, 0xcf, 0xa5, 0x94, 0x84, 0x49, 0xd6, 0xe0, 0x7f, 0x52, - 0x62, 0x6c, 0x8b, 0x32, 0xdf, 0xfe, 0xda, 0x8e, 0x14, 0x60, 0x46, 0xcc, 0x97, 0xa2, 0x69, 0x5c, - 0x87, 0x85, 0xf4, 0x48, 0x2a, 0xfb, 0x1e, 0x4c, 0xf7, 0xa8, 0x95, 0x3a, 0xbb, 0xc5, 0x44, 0x5d, - 0xbb, 0xbd, 0x55, 0x6d, 0xa7, 0x68, 0xd7, 0x1c, 0x5e, 0x54, 0xcc, 0x3b, 0x8e, 0x93, 0xc2, 0x1c, - 0x81, 0x24, 0x96, 0xb3, 0x41, 0x86, 0xdf, 0x0c, 0xe4, 0x2b, 0x58, 0x0e, 0xb7, 0xfc, 0x29, 0x3d, - 0xf2, 0x0f, 0x82, 0x59, 0xff, 0x61, 0x80, 0xc1, 0xcc, 0xa8, 0x61, 0x17, 0x01, 0xcc, 0x3a, 0x61, - 0x8c, 0x3a, 0x9d, 0x2b, 0x34, 0xa1, 0x66, 0x4a, 0x16, 0x9a, 0x83, 0xb1, 0x26, 0x77, 0xfd, 0x48, - 0x3c, 0xcb, 0xa3, 0xc1, 0xb0, 0x64, 0xe1, 0x8f, 0x00, 0xf7, 0x0b, 0xae, 0x36, 0xa3, 0xc3, 0xb8, - 0xa7, 0xe6, 0x44, 0xec, 0x91, 0x72, 0x34, 0xc6, 0x45, 0x78, 0x4b, 0x16, 0x42, 0xf6, 0xc1, 0x17, - 0xa1, 0xfc, 0x7b, 0x28, 0x07, 0x63, 0x3d, 0xba, 0x59, 0x0e, 0x87, 0xf8, 0x08, 0xf2, 0xe9, 0x3e, - 0x51, 0xc6, 0x47, 0x80, 0x12, 0x0f, 0x4a, 0xa8, 0x37, 0xcb, 0x89, 0x1a, 0xc6, 0xe3, 0xa8, 0x3a, - 0x5e, 0x21, 0xf1, 0xf8, 0xc5, 0x7f, 0xa6, 0xe0, 0xb2, 0x48, 0x8d, 0x9e, 0xc1, 0xa8, 0xd4, 0x4d, - 0x74, 0x2d, 0x11, 0x2f, 0x29, 0xce, 0xfa, 0xf5, 0xfe, 0x46, 0x12, 0x1b, 0xaf, 0x7f, 0xf7, 0xc7, - 0xdf, 0x3f, 0x5c, 0xba, 0x8e, 0xb0, 0xf1, 0x50, 0x58, 0x3b, 0xa4, 0xea, 0x19, 0xe9, 0xcf, 0x35, - 0x7a, 0xa1, 0x01, 0x74, 0x14, 0x16, 0xad, 0xa7, 0x27, 0x48, 0x93, 0x6f, 0xfd, 0xdd, 0x81, 0x6c, - 0x15, 0xd3, 0xb6, 0x60, 0xba, 0x85, 0x8a, 0x8a, 0xe9, 0xe6, 0x7e, 0x1a, 0x54, 0x47, 0xa7, 0x8d, - 0x93, 0x50, 0x8a, 0xdb, 0xe8, 0x27, 0x0d, 0xc6, 0x43, 0x05, 0x42, 0xab, 0x99, 0x59, 0x63, 0xf2, - 0xa9, 0xaf, 0x0d, 0x60, 0xa9, 0xe8, 0xee, 0x08, 0xba, 0x2d, 0xb4, 0xd9, 0x97, 0x2e, 0xd2, 0xc9, - 0x6e, 0xb8, 0xef, 0x35, 0x98, 0x0c, 0xe3, 0xed, 0x38, 0x4e, 0x16, 0x5f, 0x52, 0xde, 0xb3, 0xf8, - 0x52, 0x44, 0x1a, 0x17, 0x04, 0xdf, 0x2a, 0xba, 0x31, 0x18, 0x1f, 0xfa, 0x45, 0x83, 0xe9, 0x1e, - 0x61, 0xcc, 0x3a, 0xd8, 0x34, 0xb9, 0xcd, 0x3a, 0xd8, 0x54, 0xa5, 0x1d, 0xf0, 0x60, 0x1b, 0xc2, - 0x37, 0xfc, 0x2a, 0x31, 0x4e, 0x02, 0x09, 0x6f, 0xa3, 0x1f, 0x35, 0x58, 0xe8, 0xf7, 0x3d, 0x84, - 0xee, 0xa4, 0x93, 0x0c, 0xf0, 0x15, 0xa7, 0x6f, 0xbf, 0x89, 0xab, 0xba, 0xf7, 0xbf, 0x69, 0x30, - 0xd5, 0xad, 0x88, 0x68, 0x23, 0xb3, 0x95, 0x52, 0x54, 0x59, 0xbf, 0x39, 0xa0, 0xb5, 0xaa, 0xe0, - 0x3d, 0x51, 0xc1, 0x0f, 0xd1, 0xdd, 0xbe, 0x15, 0xec, 0xd1, 0x71, 0xe3, 0x24, 0xfe, 0x54, 0xb5, - 0xd1, 0xcf, 0x1a, 0xcc, 0x74, 0xc7, 0x0f, 0x9a, 0x71, 0x23, 0xb3, 0xc5, 0x2e, 0xc0, 0x9d, 0xf1, - 0xb8, 0xe0, 0xa2, 0xe0, 0xde, 0x40, 0xeb, 0x83, 0x73, 0xa3, 0xdf, 0x35, 0x40, 0x49, 0x89, 0x47, - 0xc5, 0xcc, 0x8a, 0x65, 0x3e, 0x36, 0xfa, 0xd6, 0x85, 0x7c, 0x14, 0xf3, 0x81, 0x60, 0xfe, 0x18, - 0xed, 0xf5, 0x65, 0x66, 0xf4, 0xc8, 0xaf, 0x34, 0x45, 0x84, 0x4a, 0xf8, 0xc4, 0x88, 0x3b, 0xaf, - 0x9e, 0xb6, 0xb6, 0x71, 0xa2, 0x1e, 0xb2, 0x36, 0xfa, 0x55, 0x83, 0x2b, 0xc9, 0x57, 0x67, 0x25, - 0xa3, 0x94, 0x71, 0x43, 0xdd, 0x18, 0xd0, 0xf0, 0x82, 0x52, 0xd5, 0x79, 0xae, 0x8c, 0x13, 0x75, - 0xe9, 0xda, 0xbb, 0xfb, 0x2f, 0xcf, 0xf2, 0xda, 0xab, 0xb3, 0xbc, 0xf6, 0xd7, 0x59, 0x5e, 0x7b, - 0x7e, 0x9e, 0x1f, 0x7a, 0x75, 0x9e, 0x1f, 0xfa, 0xf3, 0x3c, 0x3f, 0xf4, 0xb8, 0x58, 0xb3, 0xfd, - 0x7a, 0xab, 0x5a, 0x30, 0x79, 0x23, 0x2d, 0xec, 0xe1, 0xe6, 0x6d, 0xe3, 0xa8, 0x13, 0xdc, 0x3f, - 0x6e, 0x52, 0xaf, 0x3a, 0x2a, 0xfe, 0x59, 0x6d, 0xfd, 0x1b, 0x00, 0x00, 0xff, 0xff, 0xe8, 0xb0, - 0x27, 0x34, 0x97, 0x0e, 0x00, 0x00, + // 1239 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x97, 0x4d, 0x6f, 0x1b, 0x45, + 0x18, 0xc7, 0xb3, 0x6d, 0x9a, 0xa6, 0x4f, 0xd2, 0x86, 0x0e, 0x81, 0x38, 0x9b, 0xc4, 0x21, 0xd3, + 0xd0, 0xbc, 0x34, 0xf5, 0x12, 0xa7, 0x54, 0x6a, 0x44, 0x05, 0x8e, 0x68, 0x1b, 0xa3, 0x80, 0x82, + 0x5b, 0x2a, 0x54, 0x0e, 0xd6, 0x78, 0x77, 0xb0, 0x57, 0x5d, 0xef, 0xb8, 0xbb, 0xe3, 0x90, 0x10, + 0x59, 0x95, 0xf8, 0x00, 0xa8, 0x02, 0x21, 0x24, 0x6e, 0x45, 0x1c, 0x38, 0xf3, 0x29, 0x7a, 0xa3, + 0x12, 0x17, 0x4e, 0x11, 0x4a, 0xf8, 0x04, 0xfd, 0x04, 0x68, 0x67, 0x67, 0xd7, 0xeb, 0x7d, 0x31, + 0x4e, 0x6f, 0x9e, 0x99, 0xe7, 0xe5, 0x37, 0xcf, 0xcc, 0x3c, 0xff, 0x35, 0xcc, 0xb8, 0xdc, 0x31, + 0x0d, 0xaa, 0xb9, 0x9c, 0x3c, 0xa6, 0x66, 0x4d, 0xd7, 0x9e, 0xb4, 0xa9, 0x73, 0x50, 0x68, 0x39, + 0x8c, 0x33, 0x34, 0xe1, 0x2f, 0x16, 0x82, 0x45, 0x75, 0xb2, 0xce, 0xea, 0x4c, 0xac, 0x69, 0xde, + 0x2f, 0xdf, 0x4c, 0x9d, 0xad, 0x33, 0x56, 0xb7, 0xa8, 0x46, 0x5a, 0xa6, 0x46, 0x6c, 0x9b, 0x71, + 0xc2, 0x4d, 0x66, 0xbb, 0x72, 0x75, 0x55, 0x67, 0x6e, 0x93, 0xb9, 0x5a, 0x8d, 0xb8, 0xd4, 0x8f, + 0xae, 0xed, 0xad, 0xd7, 0x28, 0x27, 0xeb, 0x5a, 0x8b, 0xd4, 0x4d, 0x5b, 0x18, 0x07, 0x91, 0xe2, + 0x34, 0x2d, 0xe2, 0x90, 0x66, 0x10, 0x69, 0x3e, 0xbe, 0xba, 0x47, 0x2c, 0xd3, 0x20, 0x9c, 0x39, + 0x59, 0x06, 0x0d, 0xe6, 0xf2, 0xea, 0xb7, 0xcc, 0xa6, 0xd2, 0xe0, 0x4a, 0xdc, 0x80, 0xb6, 0x98, + 0xde, 0xa8, 0x72, 0x87, 0xe8, 0x8f, 0x69, 0x10, 0x65, 0x29, 0x6e, 0x44, 0x0c, 0xc3, 0xa1, 0xae, + 0x5b, 0x6d, 0xdb, 0x35, 0x66, 0x1b, 0xa6, 0x5d, 0x97, 0x86, 0x0b, 0x71, 0x43, 0xee, 0x10, 0x83, + 0x56, 0x1d, 0xd6, 0xe6, 0x32, 0x21, 0x7e, 0x0a, 0xcb, 0x9f, 0x7b, 0x5b, 0x2e, 0xdb, 0x9c, 0x3a, + 0x7a, 0x83, 0x98, 0x76, 0x49, 0xd7, 0x59, 0xdb, 0xe6, 0x77, 0x1d, 0xd6, 0x2c, 0xf9, 0x71, 0x2b, + 0xf4, 0x49, 0x9b, 0xba, 0x1c, 0x4d, 0xc2, 0x39, 0xf6, 0x8d, 0x4d, 0x9d, 0x9c, 0xf2, 0x8e, 0xb2, + 0x7c, 0xa1, 0xe2, 0x0f, 0xd0, 0x6d, 0xb8, 0xa8, 0x33, 0xdb, 0xa6, 0xba, 0x57, 0xa6, 0xaa, 0x69, + 0xe4, 0xce, 0x78, 0xab, 0x5b, 0xb9, 0x57, 0x47, 0xf3, 0x93, 0x07, 0xa4, 0x69, 0x6d, 0xe2, 0x9e, + 0x65, 0x5c, 0x19, 0xef, 0x8e, 0xcb, 0x06, 0x7e, 0xa6, 0xc0, 0xca, 0x00, 0x04, 0x6e, 0x8b, 0xd9, + 0x2e, 0x45, 0x3a, 0xa8, 0x66, 0x68, 0x57, 0x25, 0xbe, 0x61, 0x55, 0xee, 0xdf, 0xe7, 0xda, 0x7a, + 0xf7, 0xd5, 0xd1, 0xfc, 0x82, 0x9f, 0x39, 0xdb, 0x16, 0x57, 0x72, 0x66, 0x3c, 0xa1, 0x4c, 0x86, + 0x27, 0x01, 0x09, 0xa2, 0x5d, 0x71, 0xb6, 0x72, 0xf7, 0x78, 0x07, 0xde, 0xec, 0x99, 0x95, 0x44, + 0xef, 0xc3, 0x88, 0x7f, 0x07, 0x44, 0xf6, 0xb1, 0xe2, 0x54, 0x21, 0x76, 0x27, 0x0b, 0xbe, 0xc3, + 0xd6, 0xf0, 0x8b, 0xa3, 0xf9, 0xa1, 0x8a, 0x34, 0xc6, 0x37, 0x61, 0x5a, 0x44, 0xbb, 0x47, 0xf9, + 0xc3, 0xe0, 0x92, 0x84, 0x85, 0x9e, 0x86, 0x51, 0x1f, 0xda, 0x34, 0x64, 0xad, 0xcf, 0x8b, 0x71, + 0xd9, 0xc0, 0x5f, 0x82, 0x9a, 0xe6, 0x27, 0x61, 0x36, 0x01, 0xc2, 0x2b, 0xe7, 0x01, 0x9d, 0x5d, + 0x1e, 0x2b, 0xaa, 0x09, 0xa0, 0xd0, 0xb1, 0x12, 0xb1, 0xc6, 0x37, 0x60, 0x2a, 0x88, 0xbc, 0xcd, + 0x5c, 0xfe, 0x88, 0xd9, 0x74, 0x20, 0x9e, 0x5c, 0xd2, 0x4b, 0xd2, 0x7c, 0x00, 0x17, 0xc2, 0xfb, + 0x2d, 0xab, 0x33, 0x9d, 0x80, 0x09, 0xbc, 0x64, 0x7d, 0x46, 0x1b, 0x72, 0x8c, 0x89, 0xe4, 0x29, + 0x59, 0x56, 0x9c, 0xe7, 0x2e, 0x40, 0xf7, 0x65, 0xca, 0xc8, 0x57, 0x0b, 0xfe, 0x33, 0x2e, 0x78, + 0xcf, 0xb8, 0xe0, 0x37, 0x09, 0xf9, 0x8c, 0x0b, 0xbb, 0xa4, 0x1e, 0xf8, 0x56, 0x22, 0x9e, 0xf8, + 0xb9, 0x22, 0xe9, 0x7b, 0x72, 0xa4, 0xd3, 0x9f, 0x3d, 0x15, 0x3d, 0xba, 0xd7, 0x83, 0x78, 0x46, + 0x20, 0x2e, 0xfd, 0x2f, 0xa2, 0x9f, 0xba, 0x87, 0x51, 0x93, 0x17, 0xe5, 0x53, 0x66, 0xb4, 0x2d, + 0x1a, 0x7b, 0x91, 0x08, 0x86, 0x6d, 0xd2, 0xa4, 0xf2, 0x50, 0xc4, 0x6f, 0xfc, 0x9e, 0xbc, 0x21, + 0x31, 0x07, 0xb9, 0x2b, 0x04, 0xc3, 0xde, 0x0b, 0x08, 0x3c, 0xbc, 0xdf, 0x78, 0x1b, 0x66, 0x82, + 0x33, 0xbc, 0xe3, 0xb5, 0x9b, 0x07, 0x7e, 0xb7, 0x09, 0x92, 0xac, 0xc0, 0x1b, 0x7e, 0x17, 0x32, + 0x0d, 0x6a, 0x73, 0xf3, 0x6b, 0x33, 0xec, 0x00, 0x13, 0x62, 0xbe, 0x1c, 0x4e, 0xe3, 0x06, 0xcc, + 0xa6, 0x47, 0x92, 0xd9, 0xb7, 0xe1, 0x62, 0x4f, 0x43, 0x93, 0x67, 0x37, 0x97, 0xa8, 0x6b, 0xd4, + 0x5b, 0xd6, 0x76, 0x9c, 0x46, 0xe6, 0xf0, 0x9c, 0x64, 0x2e, 0x59, 0x56, 0x0a, 0x73, 0x08, 0x92, + 0x58, 0xce, 0x06, 0x39, 0xfb, 0x7a, 0x20, 0x5f, 0xc1, 0x42, 0xb0, 0xe5, 0xcf, 0xe8, 0x3e, 0xdf, + 0xf5, 0x66, 0xf9, 0x7d, 0x0f, 0xc3, 0xd6, 0xc3, 0x0b, 0x3b, 0x07, 0xa0, 0x37, 0x88, 0x6d, 0x53, + 0xab, 0xfb, 0x84, 0x2e, 0xc8, 0x99, 0xb2, 0x81, 0xa6, 0xe0, 0x7c, 0x8b, 0x39, 0x3c, 0x6c, 0x9e, + 0x95, 0x11, 0x6f, 0x58, 0x36, 0xf0, 0x47, 0x80, 0xfb, 0x05, 0x97, 0x9b, 0x51, 0x61, 0xd4, 0x95, + 0x73, 0x22, 0xf6, 0x70, 0x25, 0x1c, 0xe3, 0x22, 0xbc, 0xed, 0x17, 0xc2, 0xbf, 0x07, 0x5f, 0x04, + 0x0a, 0xe1, 0xa2, 0x1c, 0x9c, 0xef, 0xe9, 0x9b, 0x95, 0x60, 0x88, 0xf7, 0x21, 0x9f, 0xee, 0x13, + 0x66, 0x7c, 0x08, 0x28, 0xa1, 0x39, 0x41, 0xbf, 0x59, 0x48, 0xd4, 0x30, 0x1e, 0x47, 0xd6, 0xf1, + 0x32, 0x89, 0xc7, 0xc7, 0x6f, 0xc9, 0x1e, 0x5b, 0xb2, 0xac, 0x07, 0x9e, 0x54, 0x55, 0x3c, 0xa5, + 0x72, 0xb1, 0xde, 0x3d, 0xec, 0xc8, 0x74, 0x48, 0xf3, 0x31, 0x8c, 0x47, 0x84, 0x2d, 0xe0, 0x98, + 0x49, 0x70, 0x74, 0x7d, 0x25, 0xc1, 0x18, 0xef, 0x46, 0x2b, 0x7e, 0x7f, 0x09, 0xce, 0x89, 0x2c, + 0xe8, 0x29, 0x8c, 0xf8, 0x3d, 0x1b, 0x5d, 0x49, 0xc4, 0x48, 0x0a, 0x83, 0xba, 0xd8, 0xdf, 0xc8, + 0x87, 0xc4, 0xab, 0xdf, 0xfd, 0xf5, 0xef, 0x8f, 0x67, 0x16, 0x11, 0xd6, 0xee, 0x0b, 0x6b, 0x8b, + 0xd4, 0x5c, 0x2d, 0xfd, 0x6b, 0x02, 0x3d, 0x57, 0x00, 0xba, 0xdd, 0x1d, 0xad, 0xa6, 0x27, 0x48, + 0x93, 0x0e, 0xf5, 0xda, 0x40, 0xb6, 0x92, 0x69, 0x53, 0x30, 0xdd, 0x40, 0x45, 0xc9, 0x74, 0x7d, + 0x27, 0x0d, 0xaa, 0xab, 0x11, 0xda, 0x61, 0x20, 0x03, 0x1d, 0xf4, 0x8b, 0x02, 0xa3, 0x41, 0xf7, + 0x43, 0xcb, 0x99, 0x59, 0x63, 0xad, 0x5b, 0x5d, 0x19, 0xc0, 0x52, 0xd2, 0xdd, 0x12, 0x74, 0x1b, + 0x68, 0xbd, 0x2f, 0x5d, 0xd8, 0xa3, 0xa3, 0x70, 0x3f, 0x28, 0x30, 0x16, 0xc4, 0x2b, 0x59, 0x56, + 0x16, 0x5f, 0x52, 0x5a, 0xb2, 0xf8, 0x52, 0x04, 0x02, 0x17, 0x04, 0xdf, 0x32, 0xba, 0x3a, 0x18, + 0x1f, 0xfa, 0x4d, 0x81, 0x8b, 0x3d, 0x4d, 0x39, 0xeb, 0x60, 0xd3, 0x5a, 0x7d, 0xd6, 0xc1, 0xa6, + 0x76, 0xf9, 0x01, 0x0f, 0xb6, 0x29, 0x7c, 0x83, 0x2f, 0x22, 0xed, 0xd0, 0x93, 0x8f, 0x0e, 0xfa, + 0x49, 0x81, 0xd9, 0x7e, 0xdf, 0x62, 0xe8, 0x56, 0x3a, 0xc9, 0x00, 0x5f, 0x90, 0xea, 0xe6, 0xeb, + 0xb8, 0xca, 0x57, 0xfe, 0x87, 0x02, 0xe3, 0xd1, 0x6e, 0x8c, 0xd6, 0x32, 0xaf, 0x52, 0x8a, 0x22, + 0xa8, 0xd7, 0x07, 0xb4, 0x96, 0x15, 0xbc, 0x23, 0x2a, 0xf8, 0x21, 0xba, 0xdd, 0xb7, 0x82, 0x3d, + 0x1a, 0xa2, 0x1d, 0xc6, 0x65, 0xb2, 0x83, 0x7e, 0x55, 0x60, 0x22, 0x1a, 0xdf, 0xbb, 0x8c, 0x6b, + 0x99, 0x57, 0xec, 0x14, 0xdc, 0x19, 0xc2, 0x86, 0x8b, 0x82, 0x7b, 0x0d, 0xad, 0x0e, 0xce, 0x8d, + 0xfe, 0x54, 0x00, 0x25, 0xe5, 0x05, 0x15, 0x33, 0x2b, 0x96, 0x29, 0x74, 0xea, 0xc6, 0xa9, 0x7c, + 0x24, 0xf3, 0xae, 0x60, 0xfe, 0x04, 0x6d, 0xf7, 0x65, 0xb6, 0xe9, 0x3e, 0xaf, 0xb6, 0x44, 0x84, + 0x6a, 0x20, 0x6f, 0xe2, 0xcd, 0x4b, 0x59, 0xed, 0x68, 0x87, 0x52, 0x44, 0x3b, 0xe8, 0x77, 0x05, + 0x2e, 0x27, 0x15, 0x6f, 0x29, 0xa3, 0x94, 0x71, 0x43, 0x55, 0x1b, 0xd0, 0xf0, 0x94, 0xad, 0xaa, + 0x2b, 0x95, 0xda, 0xa1, 0x7c, 0x74, 0x1d, 0xf4, 0xb3, 0x02, 0x97, 0x7a, 0x75, 0x0d, 0x2d, 0x66, + 0x1e, 0x79, 0xc4, 0x4a, 0x5d, 0x1b, 0xc4, 0x2a, 0x24, 0x5c, 0x17, 0x84, 0xd7, 0xd0, 0x4a, 0x5f, + 0xc2, 0xa8, 0x8c, 0x6e, 0xed, 0xbc, 0x38, 0xce, 0x2b, 0x2f, 0x8f, 0xf3, 0xca, 0x3f, 0xc7, 0x79, + 0xe5, 0xd9, 0x49, 0x7e, 0xe8, 0xe5, 0x49, 0x7e, 0xe8, 0xef, 0x93, 0xfc, 0xd0, 0xa3, 0x62, 0xdd, + 0xe4, 0x8d, 0x76, 0xad, 0xa0, 0xb3, 0x66, 0x5a, 0xb8, 0xbd, 0xf5, 0x9b, 0xda, 0x7e, 0x24, 0xe8, + 0x41, 0x8b, 0xba, 0xb5, 0x11, 0xf1, 0x7f, 0x73, 0xe3, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa1, + 0xba, 0x20, 0x28, 0xd0, 0x0f, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -1066,6 +1153,8 @@ type QueryClient interface { NextPacketSequence(ctx context.Context, in *QueryGetNextPacketSequenceRequest, opts ...grpc.CallOption) (*QueryGetNextPacketSequenceResponse, error) // Queries an address's unbondings AddressUnbondings(ctx context.Context, in *QueryAddressUnbondings, opts ...grpc.CallOption) (*QueryAddressUnbondingsResponse, error) + // Queries all trade routes + AllTradeRoutes(ctx context.Context, in *QueryAllTradeRoutes, opts ...grpc.CallOption) (*QueryAllTradeRoutesResponse, error) } type queryClient struct { @@ -1166,6 +1255,15 @@ func (c *queryClient) AddressUnbondings(ctx context.Context, in *QueryAddressUnb return out, nil } +func (c *queryClient) AllTradeRoutes(ctx context.Context, in *QueryAllTradeRoutes, opts ...grpc.CallOption) (*QueryAllTradeRoutesResponse, error) { + out := new(QueryAllTradeRoutesResponse) + err := c.cc.Invoke(ctx, "/stride.stakeibc.Query/AllTradeRoutes", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // QueryServer is the server API for Query service. type QueryServer interface { // Parameters queries the parameters of the module. @@ -1189,6 +1287,8 @@ type QueryServer interface { NextPacketSequence(context.Context, *QueryGetNextPacketSequenceRequest) (*QueryGetNextPacketSequenceResponse, error) // Queries an address's unbondings AddressUnbondings(context.Context, *QueryAddressUnbondings) (*QueryAddressUnbondingsResponse, error) + // Queries all trade routes + AllTradeRoutes(context.Context, *QueryAllTradeRoutes) (*QueryAllTradeRoutesResponse, error) } // UnimplementedQueryServer can be embedded to have forward compatible implementations. @@ -1225,6 +1325,9 @@ func (*UnimplementedQueryServer) NextPacketSequence(ctx context.Context, req *Qu func (*UnimplementedQueryServer) AddressUnbondings(ctx context.Context, req *QueryAddressUnbondings) (*QueryAddressUnbondingsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method AddressUnbondings not implemented") } +func (*UnimplementedQueryServer) AllTradeRoutes(ctx context.Context, req *QueryAllTradeRoutes) (*QueryAllTradeRoutesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method AllTradeRoutes not implemented") +} func RegisterQueryServer(s grpc1.Server, srv QueryServer) { s.RegisterService(&_Query_serviceDesc, srv) @@ -1410,6 +1513,24 @@ func _Query_AddressUnbondings_Handler(srv interface{}, ctx context.Context, dec return interceptor(ctx, in, info, handler) } +func _Query_AllTradeRoutes_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryAllTradeRoutes) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).AllTradeRoutes(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/stride.stakeibc.Query/AllTradeRoutes", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).AllTradeRoutes(ctx, req.(*QueryAllTradeRoutes)) + } + return interceptor(ctx, in, info, handler) +} + var _Query_serviceDesc = grpc.ServiceDesc{ ServiceName: "stride.stakeibc.Query", HandlerType: (*QueryServer)(nil), @@ -1454,6 +1575,10 @@ var _Query_serviceDesc = grpc.ServiceDesc{ MethodName: "AddressUnbondings", Handler: _Query_AddressUnbondings_Handler, }, + { + MethodName: "AllTradeRoutes", + Handler: _Query_AllTradeRoutes_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "stride/stakeibc/query.proto", @@ -2111,6 +2236,66 @@ func (m *QueryAddressUnbondingsResponse) MarshalToSizedBuffer(dAtA []byte) (int, return len(dAtA) - i, nil } +func (m *QueryAllTradeRoutes) 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 *QueryAllTradeRoutes) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryAllTradeRoutes) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryAllTradeRoutesResponse) 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 *QueryAllTradeRoutesResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryAllTradeRoutesResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.TradeRoutes) > 0 { + for iNdEx := len(m.TradeRoutes) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.TradeRoutes[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { offset -= sovQuery(v) base := offset @@ -2387,6 +2572,30 @@ func (m *QueryAddressUnbondingsResponse) Size() (n int) { return n } +func (m *QueryAllTradeRoutes) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryAllTradeRoutesResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.TradeRoutes) > 0 { + for _, e := range m.TradeRoutes { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + return n +} + func sovQuery(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -4071,6 +4280,140 @@ func (m *QueryAddressUnbondingsResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *QueryAllTradeRoutes) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryAllTradeRoutes: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryAllTradeRoutes: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryAllTradeRoutesResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryAllTradeRoutesResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryAllTradeRoutesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TradeRoutes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.TradeRoutes = append(m.TradeRoutes, TradeRoute{}) + if err := m.TradeRoutes[len(m.TradeRoutes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipQuery(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/stakeibc/types/query.pb.gw.go b/x/stakeibc/types/query.pb.gw.go index 9f8b48147..09aeee14b 100644 --- a/x/stakeibc/types/query.pb.gw.go +++ b/x/stakeibc/types/query.pb.gw.go @@ -451,6 +451,24 @@ func local_request_Query_AddressUnbondings_0(ctx context.Context, marshaler runt } +func request_Query_AllTradeRoutes_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAllTradeRoutes + var metadata runtime.ServerMetadata + + msg, err := client.AllTradeRoutes(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_AllTradeRoutes_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAllTradeRoutes + var metadata runtime.ServerMetadata + + msg, err := server.AllTradeRoutes(ctx, &protoReq) + return msg, metadata, err + +} + // RegisterQueryHandlerServer registers the http handlers for service Query to "mux". // UnaryRPC :call QueryServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. @@ -664,6 +682,29 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv }) + mux.Handle("GET", pattern_Query_AllTradeRoutes_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_AllTradeRoutes_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_AllTradeRoutes_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -885,6 +926,26 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) + mux.Handle("GET", pattern_Query_AllTradeRoutes_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_AllTradeRoutes_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_AllTradeRoutes_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -906,6 +967,8 @@ var ( pattern_Query_NextPacketSequence_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 1, 0, 4, 1, 5, 5}, []string{"Stride-Labs", "stride", "stakeibc", "next_packet_sequence", "channel_id", "port_id"}, "", runtime.AssumeColonVerbOpt(false))) pattern_Query_AddressUnbondings_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"Stride-Labs", "stride", "stakeibc", "unbondings", "address"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_AllTradeRoutes_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"Stride-Labs", "stride", "stakeibc", "trade_routes"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( @@ -926,4 +989,6 @@ var ( forward_Query_NextPacketSequence_0 = runtime.ForwardResponseMessage forward_Query_AddressUnbondings_0 = runtime.ForwardResponseMessage + + forward_Query_AllTradeRoutes_0 = runtime.ForwardResponseMessage ) diff --git a/x/stakeibc/types/trade_route.go b/x/stakeibc/types/trade_route.go new file mode 100644 index 000000000..c20908871 --- /dev/null +++ b/x/stakeibc/types/trade_route.go @@ -0,0 +1,23 @@ +package types + +import fmt "fmt" + +// Builds the store key (as a string) from the reward and host denom's +func GetTradeRouteId(rewardDenom, hostDenom string) string { + return rewardDenom + "-" + hostDenom +} + +// Builds the store key (as a string) from the reward and host denom's +func (t TradeRoute) GetRouteId() string { + return GetTradeRouteId(t.RewardDenomOnRewardZone, t.HostDenomOnHostZone) +} + +// Builds the store key from the reward and host denom's +func (t TradeRoute) GetKey() []byte { + return TradeRouteKeyFromDenoms(t.RewardDenomOnRewardZone, t.HostDenomOnHostZone) +} + +// Human readable description for logging +func (t TradeRoute) Description() string { + return fmt.Sprintf("TradeRoute from %s to %s", t.RewardDenomOnRewardZone, t.HostDenomOnHostZone) +} diff --git a/x/stakeibc/types/trade_route.pb.go b/x/stakeibc/types/trade_route.pb.go new file mode 100644 index 000000000..bb5b11aa9 --- /dev/null +++ b/x/stakeibc/types/trade_route.pb.go @@ -0,0 +1,1333 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: stride/stakeibc/trade_route.proto + +package types + +import ( + fmt "fmt" + _ "github.com/cosmos/cosmos-proto" + github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// Stores pool information needed to execute the swap along a trade route +type TradeConfig struct { + // Currently Osmosis is the only trade chain so this is an osmosis pool id + PoolId uint64 `protobuf:"varint,1,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` + // Spot price in the pool to convert the reward denom to the host denom + // output_tokens = swap_price * input tokens + // This value may be slightly stale as it is updated by an ICQ + SwapPrice github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=swap_price,json=swapPrice,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"swap_price"` + // unix time in seconds that the price was last updated + PriceUpdateTimestamp uint64 `protobuf:"varint,3,opt,name=price_update_timestamp,json=priceUpdateTimestamp,proto3" json:"price_update_timestamp,omitempty"` + // Threshold defining the percentage of tokens that could be lost in the trade + // This captures both the loss from slippage and from a stale price on stride + // 0.05 means the output from the trade can be no less than a 5% deviation + // from the current value + MaxAllowedSwapLossRate github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,4,opt,name=max_allowed_swap_loss_rate,json=maxAllowedSwapLossRate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"max_allowed_swap_loss_rate"` + // min and max set boundaries of reward denom on trade chain we will swap + // min also decides when reward token transfers are worth it (transfer fees) + MinSwapAmount github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,5,opt,name=min_swap_amount,json=minSwapAmount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"min_swap_amount"` + MaxSwapAmount github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,6,opt,name=max_swap_amount,json=maxSwapAmount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"max_swap_amount"` +} + +func (m *TradeConfig) Reset() { *m = TradeConfig{} } +func (m *TradeConfig) String() string { return proto.CompactTextString(m) } +func (*TradeConfig) ProtoMessage() {} +func (*TradeConfig) Descriptor() ([]byte, []int) { + return fileDescriptor_c252b142ecf88017, []int{0} +} +func (m *TradeConfig) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *TradeConfig) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_TradeConfig.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 *TradeConfig) XXX_Merge(src proto.Message) { + xxx_messageInfo_TradeConfig.Merge(m, src) +} +func (m *TradeConfig) XXX_Size() int { + return m.Size() +} +func (m *TradeConfig) XXX_DiscardUnknown() { + xxx_messageInfo_TradeConfig.DiscardUnknown(m) +} + +var xxx_messageInfo_TradeConfig proto.InternalMessageInfo + +func (m *TradeConfig) GetPoolId() uint64 { + if m != nil { + return m.PoolId + } + return 0 +} + +func (m *TradeConfig) GetPriceUpdateTimestamp() uint64 { + if m != nil { + return m.PriceUpdateTimestamp + } + return 0 +} + +// TradeRoute represents a round trip including info on transfer and how to do +// the swap. It makes the assumption that the reward token is always foreign to +// the host so therefore the first two hops are to unwind the ibc denom enroute +// to the trade chain and the last hop is the return so funds start/end in the +// withdrawl ICA on hostZone +// The structure is key'd on reward denom and host denom in their native forms +// (i.e. reward_denom_on_reward_zone and host_denom_on_host_zone) +type TradeRoute struct { + // ibc denom for the reward on the host zone + RewardDenomOnHostZone string `protobuf:"bytes,1,opt,name=reward_denom_on_host_zone,json=rewardDenomOnHostZone,proto3" json:"reward_denom_on_host_zone,omitempty"` + // should be the native denom for the reward chain + RewardDenomOnRewardZone string `protobuf:"bytes,2,opt,name=reward_denom_on_reward_zone,json=rewardDenomOnRewardZone,proto3" json:"reward_denom_on_reward_zone,omitempty"` + // ibc denom of the reward on the trade chain, input to the swap + RewardDenomOnTradeZone string `protobuf:"bytes,3,opt,name=reward_denom_on_trade_zone,json=rewardDenomOnTradeZone,proto3" json:"reward_denom_on_trade_zone,omitempty"` + // ibc of the host denom on the trade chain, output from the swap + HostDenomOnTradeZone string `protobuf:"bytes,4,opt,name=host_denom_on_trade_zone,json=hostDenomOnTradeZone,proto3" json:"host_denom_on_trade_zone,omitempty"` + // should be the same as the native host denom on the host chain + HostDenomOnHostZone string `protobuf:"bytes,5,opt,name=host_denom_on_host_zone,json=hostDenomOnHostZone,proto3" json:"host_denom_on_host_zone,omitempty"` + // ICAAccount on the host zone with the reward tokens + // This is the same as the host zone withdrawal ICA account + HostAccount ICAAccount `protobuf:"bytes,6,opt,name=host_account,json=hostAccount,proto3" json:"host_account"` + // ICAAccount on the reward zone that is acts as the intermediate + // receiver of the transfer from host zone to trade zone + RewardAccount ICAAccount `protobuf:"bytes,7,opt,name=reward_account,json=rewardAccount,proto3" json:"reward_account"` + // ICAAccount responsible for executing the swap of reward + // tokens for host tokens + TradeAccount ICAAccount `protobuf:"bytes,8,opt,name=trade_account,json=tradeAccount,proto3" json:"trade_account"` + // Channel responsible for the transfer of reward tokens from the host + // zone to the reward zone. This is the channel ID on the host zone side + HostToRewardChannelId string `protobuf:"bytes,9,opt,name=host_to_reward_channel_id,json=hostToRewardChannelId,proto3" json:"host_to_reward_channel_id,omitempty"` + // Channel responsible for the transfer of reward tokens from the reward + // zone to the trade zone. This is the channel ID on the reward zone side + RewardToTradeChannelId string `protobuf:"bytes,10,opt,name=reward_to_trade_channel_id,json=rewardToTradeChannelId,proto3" json:"reward_to_trade_channel_id,omitempty"` + // Channel responsible for the transfer of host tokens from the trade + // zone, back to the host zone. This is the channel ID on the trade zone side + TradeToHostChannelId string `protobuf:"bytes,11,opt,name=trade_to_host_channel_id,json=tradeToHostChannelId,proto3" json:"trade_to_host_channel_id,omitempty"` + // specifies the configuration needed to execute the swap + // such as pool_id, slippage, min trade amount, etc. + TradeConfig TradeConfig `protobuf:"bytes,12,opt,name=trade_config,json=tradeConfig,proto3" json:"trade_config"` +} + +func (m *TradeRoute) Reset() { *m = TradeRoute{} } +func (m *TradeRoute) String() string { return proto.CompactTextString(m) } +func (*TradeRoute) ProtoMessage() {} +func (*TradeRoute) Descriptor() ([]byte, []int) { + return fileDescriptor_c252b142ecf88017, []int{1} +} +func (m *TradeRoute) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *TradeRoute) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_TradeRoute.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 *TradeRoute) XXX_Merge(src proto.Message) { + xxx_messageInfo_TradeRoute.Merge(m, src) +} +func (m *TradeRoute) XXX_Size() int { + return m.Size() +} +func (m *TradeRoute) XXX_DiscardUnknown() { + xxx_messageInfo_TradeRoute.DiscardUnknown(m) +} + +var xxx_messageInfo_TradeRoute proto.InternalMessageInfo + +func (m *TradeRoute) GetRewardDenomOnHostZone() string { + if m != nil { + return m.RewardDenomOnHostZone + } + return "" +} + +func (m *TradeRoute) GetRewardDenomOnRewardZone() string { + if m != nil { + return m.RewardDenomOnRewardZone + } + return "" +} + +func (m *TradeRoute) GetRewardDenomOnTradeZone() string { + if m != nil { + return m.RewardDenomOnTradeZone + } + return "" +} + +func (m *TradeRoute) GetHostDenomOnTradeZone() string { + if m != nil { + return m.HostDenomOnTradeZone + } + return "" +} + +func (m *TradeRoute) GetHostDenomOnHostZone() string { + if m != nil { + return m.HostDenomOnHostZone + } + return "" +} + +func (m *TradeRoute) GetHostAccount() ICAAccount { + if m != nil { + return m.HostAccount + } + return ICAAccount{} +} + +func (m *TradeRoute) GetRewardAccount() ICAAccount { + if m != nil { + return m.RewardAccount + } + return ICAAccount{} +} + +func (m *TradeRoute) GetTradeAccount() ICAAccount { + if m != nil { + return m.TradeAccount + } + return ICAAccount{} +} + +func (m *TradeRoute) GetHostToRewardChannelId() string { + if m != nil { + return m.HostToRewardChannelId + } + return "" +} + +func (m *TradeRoute) GetRewardToTradeChannelId() string { + if m != nil { + return m.RewardToTradeChannelId + } + return "" +} + +func (m *TradeRoute) GetTradeToHostChannelId() string { + if m != nil { + return m.TradeToHostChannelId + } + return "" +} + +func (m *TradeRoute) GetTradeConfig() TradeConfig { + if m != nil { + return m.TradeConfig + } + return TradeConfig{} +} + +func init() { + proto.RegisterType((*TradeConfig)(nil), "stride.stakeibc.TradeConfig") + proto.RegisterType((*TradeRoute)(nil), "stride.stakeibc.TradeRoute") +} + +func init() { proto.RegisterFile("stride/stakeibc/trade_route.proto", fileDescriptor_c252b142ecf88017) } + +var fileDescriptor_c252b142ecf88017 = []byte{ + // 661 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x94, 0xcf, 0x4f, 0x13, 0x41, + 0x14, 0xc7, 0x5b, 0xf9, 0x65, 0xa7, 0x45, 0x92, 0x15, 0x61, 0x29, 0xa6, 0x20, 0x07, 0xc3, 0x85, + 0xdd, 0x88, 0x84, 0x10, 0xc3, 0xa5, 0x50, 0x0d, 0x4d, 0x48, 0x34, 0x4b, 0xf5, 0x80, 0x87, 0xc9, + 0x74, 0x77, 0x2c, 0x1b, 0xba, 0xf3, 0x36, 0x3b, 0x53, 0xbb, 0xfa, 0x57, 0xf8, 0xc7, 0xf8, 0x47, + 0x70, 0x24, 0x9e, 0x8c, 0x07, 0x62, 0xe8, 0x9f, 0xe1, 0xc5, 0xcc, 0x9b, 0x5d, 0xd8, 0x82, 0x07, + 0x34, 0x9e, 0xda, 0xd9, 0xf7, 0x3e, 0xdf, 0x37, 0x6f, 0xbe, 0x33, 0x8f, 0x3c, 0x91, 0x2a, 0x09, + 0x03, 0xee, 0x4a, 0xc5, 0x4e, 0x79, 0xd8, 0xf5, 0x5d, 0x95, 0xb0, 0x80, 0xd3, 0x04, 0x06, 0x8a, + 0x3b, 0x71, 0x02, 0x0a, 0xac, 0x39, 0x93, 0xe2, 0xe4, 0x29, 0xf5, 0xf9, 0x1e, 0xf4, 0x00, 0x63, + 0xae, 0xfe, 0x67, 0xd2, 0xea, 0xb7, 0x94, 0x42, 0x9f, 0x51, 0xe6, 0xfb, 0x30, 0x10, 0x2a, 0x4b, + 0x59, 0xf2, 0x41, 0x46, 0x20, 0xa9, 0x61, 0xcd, 0xc2, 0x84, 0xd6, 0x46, 0x13, 0xa4, 0xda, 0xd1, + 0xa5, 0xf7, 0x41, 0x7c, 0x08, 0x7b, 0xd6, 0x22, 0x99, 0x89, 0x01, 0xfa, 0x34, 0x0c, 0xec, 0xf2, + 0x6a, 0x79, 0x7d, 0xd2, 0x9b, 0xd6, 0xcb, 0x76, 0x60, 0xbd, 0x27, 0x44, 0x0e, 0x59, 0x4c, 0xe3, + 0x24, 0xf4, 0xb9, 0x7d, 0x6f, 0xb5, 0xbc, 0x5e, 0xd9, 0xdb, 0x3d, 0xbb, 0x58, 0x29, 0xfd, 0xb8, + 0x58, 0x79, 0xda, 0x0b, 0xd5, 0xc9, 0xa0, 0xeb, 0xf8, 0x10, 0x65, 0xea, 0xd9, 0xcf, 0x86, 0x0c, + 0x4e, 0x5d, 0xf5, 0x29, 0xe6, 0xd2, 0x69, 0x71, 0xff, 0xdb, 0xd7, 0x0d, 0x92, 0x15, 0x6f, 0x71, + 0xdf, 0xab, 0x68, 0xbd, 0x37, 0x5a, 0xce, 0xda, 0x22, 0x0b, 0xa8, 0x4b, 0x07, 0x71, 0xc0, 0x14, + 0xa7, 0x2a, 0x8c, 0xb8, 0x54, 0x2c, 0x8a, 0xed, 0x09, 0xdc, 0xc4, 0x3c, 0x46, 0xdf, 0x62, 0xb0, + 0x93, 0xc7, 0xac, 0x94, 0xd4, 0x23, 0x96, 0x52, 0xd6, 0xef, 0xc3, 0x90, 0x07, 0x14, 0xb7, 0xd7, + 0x07, 0x29, 0x69, 0xc2, 0x14, 0xb7, 0x27, 0xff, 0xc3, 0x16, 0x17, 0x22, 0x96, 0x36, 0x8d, 0xfc, + 0xd1, 0x90, 0xc5, 0x87, 0x20, 0xa5, 0xc7, 0x14, 0xb7, 0xde, 0x91, 0xb9, 0x28, 0x14, 0xa6, 0x22, + 0x8b, 0xf4, 0x49, 0xdb, 0x53, 0x58, 0xce, 0xf9, 0x8b, 0x72, 0x6d, 0xa1, 0xbc, 0xd9, 0x28, 0x14, + 0x5a, 0xb9, 0x89, 0x22, 0xa8, 0xcb, 0xd2, 0x31, 0xdd, 0xe9, 0x7f, 0xd4, 0x65, 0xe9, 0xb5, 0xee, + 0xda, 0xaf, 0x29, 0x42, 0xd0, 0x65, 0x4f, 0xdf, 0x2f, 0x6b, 0x87, 0x2c, 0x25, 0x7c, 0xc8, 0x92, + 0x80, 0x06, 0x5c, 0x40, 0x44, 0x41, 0xd0, 0x13, 0x90, 0x8a, 0x7e, 0x06, 0xc1, 0xd1, 0xf6, 0x8a, + 0xf7, 0xc8, 0x24, 0xb4, 0x74, 0xfc, 0xb5, 0x38, 0x00, 0xa9, 0x8e, 0x41, 0x70, 0x6b, 0x97, 0x2c, + 0xdf, 0x24, 0xb3, 0x35, 0xb2, 0x78, 0x2d, 0xbc, 0xc5, 0x31, 0xd6, 0xc3, 0x05, 0xd2, 0x2f, 0x48, + 0xfd, 0x26, 0x6d, 0xae, 0x3d, 0xc2, 0x13, 0x08, 0x2f, 0x8c, 0xc1, 0xb8, 0x69, 0x64, 0xb7, 0x89, + 0x8d, 0x7b, 0xfc, 0x13, 0x89, 0x56, 0x7b, 0xf3, 0x3a, 0x7e, 0x8b, 0xdb, 0x22, 0x8b, 0xe3, 0xdc, + 0x75, 0xa7, 0x68, 0x99, 0xf7, 0xb0, 0x80, 0x5d, 0xf5, 0xd9, 0x22, 0x35, 0xcc, 0xcb, 0xde, 0x11, + 0xba, 0x50, 0xdd, 0x5c, 0x76, 0x6e, 0x3c, 0x49, 0xa7, 0xbd, 0xdf, 0x6c, 0x9a, 0x94, 0xbd, 0x49, + 0x6d, 0x91, 0x57, 0xd5, 0x58, 0xf6, 0xc9, 0x3a, 0x20, 0x0f, 0xb2, 0x7e, 0x73, 0x9d, 0x99, 0xbb, + 0xea, 0xcc, 0x1a, 0x30, 0x57, 0x7a, 0x45, 0x66, 0x4d, 0xbf, 0xb9, 0xd0, 0xfd, 0xbb, 0x0a, 0xd5, + 0x90, 0xcb, 0x75, 0x76, 0xc8, 0x12, 0xf6, 0xa5, 0x20, 0xf7, 0xcd, 0x3f, 0x61, 0x42, 0x70, 0x7c, + 0xf0, 0x15, 0xe3, 0xbc, 0x4e, 0xe8, 0x80, 0xb1, 0x6d, 0xdf, 0x44, 0xdb, 0x41, 0xc1, 0x3b, 0x05, + 0xd9, 0xd9, 0x17, 0x50, 0x52, 0xf4, 0xae, 0x03, 0x66, 0xa2, 0x5c, 0xb1, 0xdb, 0xc4, 0x36, 0x84, + 0x02, 0x73, 0xfc, 0x05, 0xb2, 0x6a, 0xbc, 0xc3, 0x78, 0x07, 0xb4, 0x01, 0xd7, 0xdc, 0x4b, 0x52, + 0xcb, 0x2a, 0xe1, 0x70, 0xb2, 0x6b, 0xd8, 0xf4, 0xe3, 0x5b, 0x4d, 0x17, 0x06, 0x58, 0x6e, 0x83, + 0x2a, 0x7c, 0x3a, 0x3c, 0xbb, 0x6c, 0x94, 0xcf, 0x2f, 0x1b, 0xe5, 0x9f, 0x97, 0x8d, 0xf2, 0x97, + 0x51, 0xa3, 0x74, 0x3e, 0x6a, 0x94, 0xbe, 0x8f, 0x1a, 0xa5, 0xe3, 0xcd, 0xc2, 0x73, 0x3a, 0x42, + 0xd1, 0x8d, 0x43, 0xd6, 0x95, 0x6e, 0x36, 0x52, 0x3f, 0x3e, 0xdb, 0x76, 0xd3, 0xc2, 0x88, 0xd6, + 0xcf, 0xab, 0x3b, 0x8d, 0x83, 0xf3, 0xf9, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0xe8, 0x7e, 0xc7, + 0x96, 0xc2, 0x05, 0x00, 0x00, +} + +func (m *TradeConfig) 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 *TradeConfig) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *TradeConfig) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size := m.MaxSwapAmount.Size() + i -= size + if _, err := m.MaxSwapAmount.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintTradeRoute(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + { + size := m.MinSwapAmount.Size() + i -= size + if _, err := m.MinSwapAmount.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintTradeRoute(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + { + size := m.MaxAllowedSwapLossRate.Size() + i -= size + if _, err := m.MaxAllowedSwapLossRate.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintTradeRoute(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + if m.PriceUpdateTimestamp != 0 { + i = encodeVarintTradeRoute(dAtA, i, uint64(m.PriceUpdateTimestamp)) + i-- + dAtA[i] = 0x18 + } + { + size := m.SwapPrice.Size() + i -= size + if _, err := m.SwapPrice.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintTradeRoute(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if m.PoolId != 0 { + i = encodeVarintTradeRoute(dAtA, i, uint64(m.PoolId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *TradeRoute) 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 *TradeRoute) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *TradeRoute) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.TradeConfig.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTradeRoute(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x62 + if len(m.TradeToHostChannelId) > 0 { + i -= len(m.TradeToHostChannelId) + copy(dAtA[i:], m.TradeToHostChannelId) + i = encodeVarintTradeRoute(dAtA, i, uint64(len(m.TradeToHostChannelId))) + i-- + dAtA[i] = 0x5a + } + if len(m.RewardToTradeChannelId) > 0 { + i -= len(m.RewardToTradeChannelId) + copy(dAtA[i:], m.RewardToTradeChannelId) + i = encodeVarintTradeRoute(dAtA, i, uint64(len(m.RewardToTradeChannelId))) + i-- + dAtA[i] = 0x52 + } + if len(m.HostToRewardChannelId) > 0 { + i -= len(m.HostToRewardChannelId) + copy(dAtA[i:], m.HostToRewardChannelId) + i = encodeVarintTradeRoute(dAtA, i, uint64(len(m.HostToRewardChannelId))) + i-- + dAtA[i] = 0x4a + } + { + size, err := m.TradeAccount.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTradeRoute(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x42 + { + size, err := m.RewardAccount.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTradeRoute(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + { + size, err := m.HostAccount.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTradeRoute(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + if len(m.HostDenomOnHostZone) > 0 { + i -= len(m.HostDenomOnHostZone) + copy(dAtA[i:], m.HostDenomOnHostZone) + i = encodeVarintTradeRoute(dAtA, i, uint64(len(m.HostDenomOnHostZone))) + i-- + dAtA[i] = 0x2a + } + if len(m.HostDenomOnTradeZone) > 0 { + i -= len(m.HostDenomOnTradeZone) + copy(dAtA[i:], m.HostDenomOnTradeZone) + i = encodeVarintTradeRoute(dAtA, i, uint64(len(m.HostDenomOnTradeZone))) + i-- + dAtA[i] = 0x22 + } + if len(m.RewardDenomOnTradeZone) > 0 { + i -= len(m.RewardDenomOnTradeZone) + copy(dAtA[i:], m.RewardDenomOnTradeZone) + i = encodeVarintTradeRoute(dAtA, i, uint64(len(m.RewardDenomOnTradeZone))) + i-- + dAtA[i] = 0x1a + } + if len(m.RewardDenomOnRewardZone) > 0 { + i -= len(m.RewardDenomOnRewardZone) + copy(dAtA[i:], m.RewardDenomOnRewardZone) + i = encodeVarintTradeRoute(dAtA, i, uint64(len(m.RewardDenomOnRewardZone))) + i-- + dAtA[i] = 0x12 + } + if len(m.RewardDenomOnHostZone) > 0 { + i -= len(m.RewardDenomOnHostZone) + copy(dAtA[i:], m.RewardDenomOnHostZone) + i = encodeVarintTradeRoute(dAtA, i, uint64(len(m.RewardDenomOnHostZone))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintTradeRoute(dAtA []byte, offset int, v uint64) int { + offset -= sovTradeRoute(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *TradeConfig) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PoolId != 0 { + n += 1 + sovTradeRoute(uint64(m.PoolId)) + } + l = m.SwapPrice.Size() + n += 1 + l + sovTradeRoute(uint64(l)) + if m.PriceUpdateTimestamp != 0 { + n += 1 + sovTradeRoute(uint64(m.PriceUpdateTimestamp)) + } + l = m.MaxAllowedSwapLossRate.Size() + n += 1 + l + sovTradeRoute(uint64(l)) + l = m.MinSwapAmount.Size() + n += 1 + l + sovTradeRoute(uint64(l)) + l = m.MaxSwapAmount.Size() + n += 1 + l + sovTradeRoute(uint64(l)) + return n +} + +func (m *TradeRoute) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.RewardDenomOnHostZone) + if l > 0 { + n += 1 + l + sovTradeRoute(uint64(l)) + } + l = len(m.RewardDenomOnRewardZone) + if l > 0 { + n += 1 + l + sovTradeRoute(uint64(l)) + } + l = len(m.RewardDenomOnTradeZone) + if l > 0 { + n += 1 + l + sovTradeRoute(uint64(l)) + } + l = len(m.HostDenomOnTradeZone) + if l > 0 { + n += 1 + l + sovTradeRoute(uint64(l)) + } + l = len(m.HostDenomOnHostZone) + if l > 0 { + n += 1 + l + sovTradeRoute(uint64(l)) + } + l = m.HostAccount.Size() + n += 1 + l + sovTradeRoute(uint64(l)) + l = m.RewardAccount.Size() + n += 1 + l + sovTradeRoute(uint64(l)) + l = m.TradeAccount.Size() + n += 1 + l + sovTradeRoute(uint64(l)) + l = len(m.HostToRewardChannelId) + if l > 0 { + n += 1 + l + sovTradeRoute(uint64(l)) + } + l = len(m.RewardToTradeChannelId) + if l > 0 { + n += 1 + l + sovTradeRoute(uint64(l)) + } + l = len(m.TradeToHostChannelId) + if l > 0 { + n += 1 + l + sovTradeRoute(uint64(l)) + } + l = m.TradeConfig.Size() + n += 1 + l + sovTradeRoute(uint64(l)) + return n +} + +func sovTradeRoute(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTradeRoute(x uint64) (n int) { + return sovTradeRoute(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *TradeConfig) 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 ErrIntOverflowTradeRoute + } + 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: TradeConfig: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TradeConfig: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PoolId", wireType) + } + m.PoolId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTradeRoute + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PoolId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SwapPrice", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTradeRoute + } + 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 ErrInvalidLengthTradeRoute + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTradeRoute + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.SwapPrice.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PriceUpdateTimestamp", wireType) + } + m.PriceUpdateTimestamp = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTradeRoute + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PriceUpdateTimestamp |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxAllowedSwapLossRate", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTradeRoute + } + 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 ErrInvalidLengthTradeRoute + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTradeRoute + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.MaxAllowedSwapLossRate.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MinSwapAmount", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTradeRoute + } + 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 ErrInvalidLengthTradeRoute + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTradeRoute + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.MinSwapAmount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxSwapAmount", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTradeRoute + } + 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 ErrInvalidLengthTradeRoute + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTradeRoute + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.MaxSwapAmount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTradeRoute(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTradeRoute + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *TradeRoute) 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 ErrIntOverflowTradeRoute + } + 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: TradeRoute: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TradeRoute: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RewardDenomOnHostZone", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTradeRoute + } + 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 ErrInvalidLengthTradeRoute + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTradeRoute + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RewardDenomOnHostZone = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RewardDenomOnRewardZone", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTradeRoute + } + 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 ErrInvalidLengthTradeRoute + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTradeRoute + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RewardDenomOnRewardZone = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RewardDenomOnTradeZone", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTradeRoute + } + 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 ErrInvalidLengthTradeRoute + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTradeRoute + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RewardDenomOnTradeZone = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field HostDenomOnTradeZone", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTradeRoute + } + 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 ErrInvalidLengthTradeRoute + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTradeRoute + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.HostDenomOnTradeZone = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field HostDenomOnHostZone", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTradeRoute + } + 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 ErrInvalidLengthTradeRoute + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTradeRoute + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.HostDenomOnHostZone = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field HostAccount", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTradeRoute + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTradeRoute + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTradeRoute + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.HostAccount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RewardAccount", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTradeRoute + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTradeRoute + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTradeRoute + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.RewardAccount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TradeAccount", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTradeRoute + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTradeRoute + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTradeRoute + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.TradeAccount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field HostToRewardChannelId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTradeRoute + } + 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 ErrInvalidLengthTradeRoute + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTradeRoute + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.HostToRewardChannelId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RewardToTradeChannelId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTradeRoute + } + 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 ErrInvalidLengthTradeRoute + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTradeRoute + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RewardToTradeChannelId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TradeToHostChannelId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTradeRoute + } + 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 ErrInvalidLengthTradeRoute + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTradeRoute + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.TradeToHostChannelId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 12: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TradeConfig", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTradeRoute + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTradeRoute + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTradeRoute + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.TradeConfig.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTradeRoute(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTradeRoute + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTradeRoute(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTradeRoute + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTradeRoute + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTradeRoute + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthTradeRoute + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTradeRoute + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTradeRoute + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTradeRoute = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTradeRoute = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTradeRoute = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/stakeibc/types/tx.pb.go b/x/stakeibc/types/tx.pb.go index a96e7df94..c1172c271 100644 --- a/x/stakeibc/types/tx.pb.go +++ b/x/stakeibc/types/tx.pb.go @@ -9,6 +9,8 @@ import ( _ "github.com/cosmos/cosmos-proto" github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" types "github.com/cosmos/cosmos-sdk/types" + _ "github.com/cosmos/cosmos-sdk/types/msgservice" + _ "github.com/cosmos/cosmos-sdk/types/tx/amino" _ "github.com/cosmos/gogoproto/gogoproto" grpc1 "github.com/cosmos/gogoproto/grpc" proto "github.com/cosmos/gogoproto/proto" @@ -1094,9 +1096,10 @@ func (m *MsgDeleteValidatorResponse) XXX_DiscardUnknown() { var xxx_messageInfo_MsgDeleteValidatorResponse proto.InternalMessageInfo type MsgRestoreInterchainAccount struct { - Creator string `protobuf:"bytes,1,opt,name=creator,proto3" json:"creator,omitempty"` - ChainId string `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` - AccountType ICAAccountType `protobuf:"varint,3,opt,name=account_type,json=accountType,proto3,enum=stride.stakeibc.ICAAccountType" json:"account_type,omitempty"` + Creator string `protobuf:"bytes,1,opt,name=creator,proto3" json:"creator,omitempty"` + ChainId string `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + ConnectionId string `protobuf:"bytes,3,opt,name=connection_id,json=connectionId,proto3" json:"connection_id,omitempty"` + AccountOwner string `protobuf:"bytes,4,opt,name=account_owner,json=accountOwner,proto3" json:"account_owner,omitempty"` } func (m *MsgRestoreInterchainAccount) Reset() { *m = MsgRestoreInterchainAccount{} } @@ -1146,11 +1149,18 @@ func (m *MsgRestoreInterchainAccount) GetChainId() string { return "" } -func (m *MsgRestoreInterchainAccount) GetAccountType() ICAAccountType { +func (m *MsgRestoreInterchainAccount) GetConnectionId() string { + if m != nil { + return m.ConnectionId + } + return "" +} + +func (m *MsgRestoreInterchainAccount) GetAccountOwner() string { if m != nil { - return m.AccountType + return m.AccountOwner } - return ICAAccountType_DELEGATION + return "" } type MsgRestoreInterchainAccountResponse struct { @@ -1552,6 +1562,441 @@ func (m *MsgResumeHostZoneResponse) XXX_DiscardUnknown() { var xxx_messageInfo_MsgResumeHostZoneResponse proto.InternalMessageInfo +// Creates a new trade route +type MsgCreateTradeRoute struct { + // authority is the address that controls the module (defaults to x/gov unless + // overwritten). + Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` + // The chain ID of the host zone + HostChainId string `protobuf:"bytes,2,opt,name=host_chain_id,json=hostChainId,proto3" json:"host_chain_id,omitempty"` + // Connection IDs between stride and the other zones + StrideToRewardConnectionId string `protobuf:"bytes,3,opt,name=stride_to_reward_connection_id,json=strideToRewardConnectionId,proto3" json:"stride_to_reward_connection_id,omitempty"` + StrideToTradeConnectionId string `protobuf:"bytes,4,opt,name=stride_to_trade_connection_id,json=strideToTradeConnectionId,proto3" json:"stride_to_trade_connection_id,omitempty"` + // Transfer channels between the host, reward, and trade zones + HostToRewardTransferChannelId string `protobuf:"bytes,5,opt,name=host_to_reward_transfer_channel_id,json=hostToRewardTransferChannelId,proto3" json:"host_to_reward_transfer_channel_id,omitempty"` + RewardToTradeTransferChannelId string `protobuf:"bytes,6,opt,name=reward_to_trade_transfer_channel_id,json=rewardToTradeTransferChannelId,proto3" json:"reward_to_trade_transfer_channel_id,omitempty"` + TradeToHostTransferChannelId string `protobuf:"bytes,7,opt,name=trade_to_host_transfer_channel_id,json=tradeToHostTransferChannelId,proto3" json:"trade_to_host_transfer_channel_id,omitempty"` + // ibc denom for the reward token on the host zone (e.g. ibc/usdc on dYdX) + RewardDenomOnHost string `protobuf:"bytes,8,opt,name=reward_denom_on_host,json=rewardDenomOnHost,proto3" json:"reward_denom_on_host,omitempty"` + // native denom of reward token on the reward zone (e.g. usdc on Noble) + RewardDenomOnReward string `protobuf:"bytes,9,opt,name=reward_denom_on_reward,json=rewardDenomOnReward,proto3" json:"reward_denom_on_reward,omitempty"` + // ibc denom of the reward token on the trade zone (e.g. ibc/usdc on Osmosis) + RewardDenomOnTrade string `protobuf:"bytes,10,opt,name=reward_denom_on_trade,json=rewardDenomOnTrade,proto3" json:"reward_denom_on_trade,omitempty"` + // ibc denom of the host's token on the trade zone (e.g. ibc/dydx on Osmosis) + HostDenomOnTrade string `protobuf:"bytes,11,opt,name=host_denom_on_trade,json=hostDenomOnTrade,proto3" json:"host_denom_on_trade,omitempty"` + // the host zone's native denom (e.g. dydx on dYdX) + HostDenomOnHost string `protobuf:"bytes,12,opt,name=host_denom_on_host,json=hostDenomOnHost,proto3" json:"host_denom_on_host,omitempty"` + // The osmosis pool ID + PoolId uint64 `protobuf:"varint,13,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` + // Threshold defining the percentage of tokens that could be lost in the trade + // This captures both the loss from slippage and from a stale price on stride + // "0.05" means the output from the trade can be no less than a 5% deviation + // from the current value + MaxAllowedSwapLossRate string `protobuf:"bytes,14,opt,name=max_allowed_swap_loss_rate,json=maxAllowedSwapLossRate,proto3" json:"max_allowed_swap_loss_rate,omitempty"` + // minimum amount of reward tokens to initate a swap + // if not provided, defaults to 0 + MinSwapAmount github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,15,opt,name=min_swap_amount,json=minSwapAmount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"min_swap_amount"` + // maximum amount of reward tokens in a single swap + // if not provided, defaults to 10e24 + MaxSwapAmount github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,16,opt,name=max_swap_amount,json=maxSwapAmount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"max_swap_amount"` +} + +func (m *MsgCreateTradeRoute) Reset() { *m = MsgCreateTradeRoute{} } +func (m *MsgCreateTradeRoute) String() string { return proto.CompactTextString(m) } +func (*MsgCreateTradeRoute) ProtoMessage() {} +func (*MsgCreateTradeRoute) Descriptor() ([]byte, []int) { + return fileDescriptor_9b7e09c9ad51cd54, []int{32} +} +func (m *MsgCreateTradeRoute) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgCreateTradeRoute) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgCreateTradeRoute.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 *MsgCreateTradeRoute) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgCreateTradeRoute.Merge(m, src) +} +func (m *MsgCreateTradeRoute) XXX_Size() int { + return m.Size() +} +func (m *MsgCreateTradeRoute) XXX_DiscardUnknown() { + xxx_messageInfo_MsgCreateTradeRoute.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgCreateTradeRoute proto.InternalMessageInfo + +func (m *MsgCreateTradeRoute) GetAuthority() string { + if m != nil { + return m.Authority + } + return "" +} + +func (m *MsgCreateTradeRoute) GetHostChainId() string { + if m != nil { + return m.HostChainId + } + return "" +} + +func (m *MsgCreateTradeRoute) GetStrideToRewardConnectionId() string { + if m != nil { + return m.StrideToRewardConnectionId + } + return "" +} + +func (m *MsgCreateTradeRoute) GetStrideToTradeConnectionId() string { + if m != nil { + return m.StrideToTradeConnectionId + } + return "" +} + +func (m *MsgCreateTradeRoute) GetHostToRewardTransferChannelId() string { + if m != nil { + return m.HostToRewardTransferChannelId + } + return "" +} + +func (m *MsgCreateTradeRoute) GetRewardToTradeTransferChannelId() string { + if m != nil { + return m.RewardToTradeTransferChannelId + } + return "" +} + +func (m *MsgCreateTradeRoute) GetTradeToHostTransferChannelId() string { + if m != nil { + return m.TradeToHostTransferChannelId + } + return "" +} + +func (m *MsgCreateTradeRoute) GetRewardDenomOnHost() string { + if m != nil { + return m.RewardDenomOnHost + } + return "" +} + +func (m *MsgCreateTradeRoute) GetRewardDenomOnReward() string { + if m != nil { + return m.RewardDenomOnReward + } + return "" +} + +func (m *MsgCreateTradeRoute) GetRewardDenomOnTrade() string { + if m != nil { + return m.RewardDenomOnTrade + } + return "" +} + +func (m *MsgCreateTradeRoute) GetHostDenomOnTrade() string { + if m != nil { + return m.HostDenomOnTrade + } + return "" +} + +func (m *MsgCreateTradeRoute) GetHostDenomOnHost() string { + if m != nil { + return m.HostDenomOnHost + } + return "" +} + +func (m *MsgCreateTradeRoute) GetPoolId() uint64 { + if m != nil { + return m.PoolId + } + return 0 +} + +func (m *MsgCreateTradeRoute) GetMaxAllowedSwapLossRate() string { + if m != nil { + return m.MaxAllowedSwapLossRate + } + return "" +} + +type MsgCreateTradeRouteResponse struct { +} + +func (m *MsgCreateTradeRouteResponse) Reset() { *m = MsgCreateTradeRouteResponse{} } +func (m *MsgCreateTradeRouteResponse) String() string { return proto.CompactTextString(m) } +func (*MsgCreateTradeRouteResponse) ProtoMessage() {} +func (*MsgCreateTradeRouteResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_9b7e09c9ad51cd54, []int{33} +} +func (m *MsgCreateTradeRouteResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgCreateTradeRouteResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgCreateTradeRouteResponse.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 *MsgCreateTradeRouteResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgCreateTradeRouteResponse.Merge(m, src) +} +func (m *MsgCreateTradeRouteResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgCreateTradeRouteResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgCreateTradeRouteResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgCreateTradeRouteResponse proto.InternalMessageInfo + +// Deletes a trade route +type MsgDeleteTradeRoute struct { + // authority is the address that controls the module (defaults to x/gov unless + // overwritten). + Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` + // The reward denom of the route in it's native form (e.g. usdc) + RewardDenom string `protobuf:"bytes,2,opt,name=reward_denom,json=rewardDenom,proto3" json:"reward_denom,omitempty"` + // The host zone's denom in it's native form (e.g. dydx) + HostDenom string `protobuf:"bytes,3,opt,name=host_denom,json=hostDenom,proto3" json:"host_denom,omitempty"` +} + +func (m *MsgDeleteTradeRoute) Reset() { *m = MsgDeleteTradeRoute{} } +func (m *MsgDeleteTradeRoute) String() string { return proto.CompactTextString(m) } +func (*MsgDeleteTradeRoute) ProtoMessage() {} +func (*MsgDeleteTradeRoute) Descriptor() ([]byte, []int) { + return fileDescriptor_9b7e09c9ad51cd54, []int{34} +} +func (m *MsgDeleteTradeRoute) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgDeleteTradeRoute) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgDeleteTradeRoute.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 *MsgDeleteTradeRoute) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgDeleteTradeRoute.Merge(m, src) +} +func (m *MsgDeleteTradeRoute) XXX_Size() int { + return m.Size() +} +func (m *MsgDeleteTradeRoute) XXX_DiscardUnknown() { + xxx_messageInfo_MsgDeleteTradeRoute.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgDeleteTradeRoute proto.InternalMessageInfo + +func (m *MsgDeleteTradeRoute) GetAuthority() string { + if m != nil { + return m.Authority + } + return "" +} + +func (m *MsgDeleteTradeRoute) GetRewardDenom() string { + if m != nil { + return m.RewardDenom + } + return "" +} + +func (m *MsgDeleteTradeRoute) GetHostDenom() string { + if m != nil { + return m.HostDenom + } + return "" +} + +type MsgDeleteTradeRouteResponse struct { +} + +func (m *MsgDeleteTradeRouteResponse) Reset() { *m = MsgDeleteTradeRouteResponse{} } +func (m *MsgDeleteTradeRouteResponse) String() string { return proto.CompactTextString(m) } +func (*MsgDeleteTradeRouteResponse) ProtoMessage() {} +func (*MsgDeleteTradeRouteResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_9b7e09c9ad51cd54, []int{35} +} +func (m *MsgDeleteTradeRouteResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgDeleteTradeRouteResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgDeleteTradeRouteResponse.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 *MsgDeleteTradeRouteResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgDeleteTradeRouteResponse.Merge(m, src) +} +func (m *MsgDeleteTradeRouteResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgDeleteTradeRouteResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgDeleteTradeRouteResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgDeleteTradeRouteResponse proto.InternalMessageInfo + +// Updates the config of a trade route +type MsgUpdateTradeRoute struct { + // authority is the address that controls the module (defaults to x/gov unless + // overwritten). + Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` + // The reward denom of the route in it's native form (e.g. usdc) + RewardDenom string `protobuf:"bytes,2,opt,name=reward_denom,json=rewardDenom,proto3" json:"reward_denom,omitempty"` + // The host zone's denom in it's native form (e.g. dydx) + HostDenom string `protobuf:"bytes,3,opt,name=host_denom,json=hostDenom,proto3" json:"host_denom,omitempty"` + // The osmosis pool ID + PoolId uint64 `protobuf:"varint,4,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` + // Threshold defining the percentage of tokens that could be lost in the trade + // This captures both the loss from slippage and from a stale price on stride + // "0.05" means the output from the trade can be no less than a 5% deviation + // from the current value + MaxAllowedSwapLossRate string `protobuf:"bytes,5,opt,name=max_allowed_swap_loss_rate,json=maxAllowedSwapLossRate,proto3" json:"max_allowed_swap_loss_rate,omitempty"` + // minimum amount of reward tokens to initate a swap + // if not provided, defaults to 0 + MinSwapAmount github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,6,opt,name=min_swap_amount,json=minSwapAmount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"min_swap_amount"` + // maximum amount of reward tokens in a single swap + // if not provided, defaults to 10e24 + MaxSwapAmount github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,7,opt,name=max_swap_amount,json=maxSwapAmount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"max_swap_amount"` +} + +func (m *MsgUpdateTradeRoute) Reset() { *m = MsgUpdateTradeRoute{} } +func (m *MsgUpdateTradeRoute) String() string { return proto.CompactTextString(m) } +func (*MsgUpdateTradeRoute) ProtoMessage() {} +func (*MsgUpdateTradeRoute) Descriptor() ([]byte, []int) { + return fileDescriptor_9b7e09c9ad51cd54, []int{36} +} +func (m *MsgUpdateTradeRoute) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateTradeRoute) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateTradeRoute.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 *MsgUpdateTradeRoute) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateTradeRoute.Merge(m, src) +} +func (m *MsgUpdateTradeRoute) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateTradeRoute) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateTradeRoute.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUpdateTradeRoute proto.InternalMessageInfo + +func (m *MsgUpdateTradeRoute) GetAuthority() string { + if m != nil { + return m.Authority + } + return "" +} + +func (m *MsgUpdateTradeRoute) GetRewardDenom() string { + if m != nil { + return m.RewardDenom + } + return "" +} + +func (m *MsgUpdateTradeRoute) GetHostDenom() string { + if m != nil { + return m.HostDenom + } + return "" +} + +func (m *MsgUpdateTradeRoute) GetPoolId() uint64 { + if m != nil { + return m.PoolId + } + return 0 +} + +func (m *MsgUpdateTradeRoute) GetMaxAllowedSwapLossRate() string { + if m != nil { + return m.MaxAllowedSwapLossRate + } + return "" +} + +type MsgUpdateTradeRouteResponse struct { +} + +func (m *MsgUpdateTradeRouteResponse) Reset() { *m = MsgUpdateTradeRouteResponse{} } +func (m *MsgUpdateTradeRouteResponse) String() string { return proto.CompactTextString(m) } +func (*MsgUpdateTradeRouteResponse) ProtoMessage() {} +func (*MsgUpdateTradeRouteResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_9b7e09c9ad51cd54, []int{37} +} +func (m *MsgUpdateTradeRouteResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateTradeRouteResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateTradeRouteResponse.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 *MsgUpdateTradeRouteResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateTradeRouteResponse.Merge(m, src) +} +func (m *MsgUpdateTradeRouteResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateTradeRouteResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateTradeRouteResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUpdateTradeRouteResponse proto.InternalMessageInfo + func init() { proto.RegisterType((*MsgUpdateInnerRedemptionRateBounds)(nil), "stride.stakeibc.MsgUpdateInnerRedemptionRateBounds") proto.RegisterType((*MsgUpdateInnerRedemptionRateBoundsResponse)(nil), "stride.stakeibc.MsgUpdateInnerRedemptionRateBoundsResponse") @@ -1585,111 +2030,147 @@ func init() { proto.RegisterType((*MsgCalibrateDelegationResponse)(nil), "stride.stakeibc.MsgCalibrateDelegationResponse") proto.RegisterType((*MsgResumeHostZone)(nil), "stride.stakeibc.MsgResumeHostZone") proto.RegisterType((*MsgResumeHostZoneResponse)(nil), "stride.stakeibc.MsgResumeHostZoneResponse") + proto.RegisterType((*MsgCreateTradeRoute)(nil), "stride.stakeibc.MsgCreateTradeRoute") + proto.RegisterType((*MsgCreateTradeRouteResponse)(nil), "stride.stakeibc.MsgCreateTradeRouteResponse") + proto.RegisterType((*MsgDeleteTradeRoute)(nil), "stride.stakeibc.MsgDeleteTradeRoute") + proto.RegisterType((*MsgDeleteTradeRouteResponse)(nil), "stride.stakeibc.MsgDeleteTradeRouteResponse") + proto.RegisterType((*MsgUpdateTradeRoute)(nil), "stride.stakeibc.MsgUpdateTradeRoute") + proto.RegisterType((*MsgUpdateTradeRouteResponse)(nil), "stride.stakeibc.MsgUpdateTradeRouteResponse") } func init() { proto.RegisterFile("stride/stakeibc/tx.proto", fileDescriptor_9b7e09c9ad51cd54) } var fileDescriptor_9b7e09c9ad51cd54 = []byte{ - // 1581 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0x4f, 0x6f, 0xdc, 0xc6, - 0x15, 0x17, 0x2d, 0x59, 0x5e, 0x3f, 0xfd, 0xa7, 0x64, 0x99, 0xa2, 0xea, 0x5d, 0x99, 0xea, 0x1f, - 0xd5, 0xb5, 0x76, 0x2b, 0xc9, 0x68, 0x51, 0xb7, 0x3d, 0x68, 0x25, 0x17, 0x5e, 0xc0, 0x32, 0x0a, - 0xca, 0xae, 0x01, 0x03, 0x05, 0x3b, 0x4b, 0x8e, 0xb8, 0x84, 0xc9, 0xe1, 0x9a, 0xc3, 0x95, 0xd7, - 0x3d, 0x14, 0xbe, 0x14, 0xe8, 0xa5, 0x40, 0x82, 0x00, 0x39, 0x06, 0x3e, 0xe4, 0x10, 0x24, 0xb7, - 0xc0, 0x1f, 0xc2, 0x40, 0x2e, 0x86, 0x4f, 0x41, 0x0e, 0x9b, 0xc0, 0xbe, 0xe4, 0xac, 0x4f, 0x10, - 0xcc, 0x90, 0x3b, 0x4b, 0xae, 0x66, 0x25, 0x59, 0x56, 0x7c, 0x92, 0x66, 0xde, 0x6f, 0xde, 0xfb, - 0xbd, 0x37, 0x6f, 0xde, 0x7b, 0x4b, 0xd0, 0x68, 0x1c, 0x79, 0x0e, 0xae, 0xd0, 0x18, 0x3d, 0xc2, - 0x5e, 0xdd, 0xae, 0xc4, 0xed, 0x72, 0x33, 0x0a, 0xe3, 0x50, 0x9d, 0x4a, 0x24, 0xe5, 0xae, 0x44, - 0xbf, 0xda, 0x0f, 0xf5, 0x6c, 0x64, 0x21, 0xdb, 0x0e, 0x5b, 0x24, 0x4e, 0xce, 0xe8, 0xa5, 0x7e, - 0xc8, 0x3e, 0xf2, 0x3d, 0x07, 0xc5, 0x61, 0x94, 0x02, 0xe6, 0xdc, 0xd0, 0x0d, 0xf9, 0xbf, 0x15, - 0xf6, 0x5f, 0xba, 0xbb, 0x60, 0x87, 0x34, 0x08, 0xa9, 0x95, 0x08, 0x92, 0x45, 0x2a, 0x2a, 0x26, - 0xab, 0x4a, 0x1d, 0x51, 0x5c, 0xd9, 0x5f, 0xab, 0xe3, 0x18, 0xad, 0x55, 0xec, 0xd0, 0x23, 0x89, - 0xdc, 0xf8, 0xe6, 0x1c, 0x18, 0x3b, 0xd4, 0xbd, 0xdf, 0x74, 0x50, 0x8c, 0x6b, 0x84, 0xe0, 0xc8, - 0xc4, 0x0e, 0x0e, 0x9a, 0xb1, 0x17, 0x12, 0x13, 0xc5, 0xb8, 0x1a, 0xb6, 0x88, 0x43, 0x55, 0x0d, - 0x2e, 0xd8, 0x11, 0x66, 0x44, 0x34, 0x65, 0x49, 0x59, 0xb9, 0x68, 0x76, 0x97, 0xea, 0x02, 0x14, - 0xec, 0x06, 0xf2, 0x88, 0xe5, 0x39, 0xda, 0xb9, 0x54, 0xc4, 0xd6, 0x35, 0x47, 0x7d, 0x02, 0x0b, - 0x01, 0x13, 0x30, 0xad, 0x56, 0x24, 0xd4, 0x5a, 0x11, 0x8a, 0xb1, 0x36, 0xcc, 0xb0, 0xd5, 0xbf, - 0xbc, 0xec, 0x94, 0x86, 0xbe, 0xeb, 0x94, 0x7e, 0xed, 0x7a, 0x71, 0xa3, 0x55, 0x2f, 0xdb, 0x61, - 0x90, 0xf2, 0x4f, 0xff, 0xac, 0x52, 0xe7, 0x51, 0x25, 0x7e, 0xda, 0xc4, 0xb4, 0xbc, 0x8d, 0xed, - 0xd7, 0x2f, 0x56, 0x21, 0x75, 0x6f, 0x1b, 0xdb, 0xe6, 0x7c, 0xe0, 0x11, 0x09, 0x67, 0x6e, 0x18, - 0xb5, 0x07, 0x18, 0x1e, 0x39, 0x13, 0xc3, 0xa8, 0x2d, 0x31, 0x6c, 0x5c, 0x87, 0x6b, 0xc7, 0x07, - 0xd3, 0xc4, 0xb4, 0x19, 0x12, 0x8a, 0x8d, 0x8f, 0x15, 0x98, 0xdc, 0xa1, 0xee, 0x1d, 0xef, 0x71, - 0xcb, 0x73, 0x76, 0xd9, 0x95, 0x1f, 0x11, 0xe7, 0xbf, 0xc1, 0x28, 0x0a, 0x58, 0xaa, 0x24, 0x51, - 0xae, 0x96, 0xdf, 0xc1, 0x81, 0x1a, 0x89, 0xcd, 0xf4, 0xb4, 0x7a, 0x05, 0xa0, 0x11, 0xd2, 0xd8, - 0x72, 0x30, 0x09, 0x83, 0xe4, 0x16, 0xcc, 0x8b, 0x6c, 0x67, 0x9b, 0x6d, 0x18, 0xcf, 0x14, 0x98, - 0xcf, 0x73, 0xea, 0xd2, 0x55, 0xf7, 0xa0, 0x40, 0x63, 0x2b, 0x0e, 0x1f, 0x61, 0xc2, 0xc9, 0x8d, - 0xad, 0x2f, 0x94, 0xd3, 0x98, 0xb0, 0xec, 0x2a, 0xa7, 0xd9, 0x55, 0xde, 0x0a, 0x3d, 0x52, 0xfd, - 0x3d, 0xa3, 0xf7, 0xe5, 0xf7, 0xa5, 0x95, 0x13, 0xd0, 0x63, 0x07, 0xa8, 0x79, 0x81, 0xc6, 0xf7, - 0x98, 0x6e, 0xe3, 0x73, 0x05, 0x66, 0x18, 0x85, 0xdd, 0x9d, 0x0f, 0x1b, 0x99, 0x55, 0x98, 0xf5, - 0x69, 0x90, 0x38, 0x68, 0x79, 0x75, 0x3b, 0x17, 0xa2, 0x69, 0x9f, 0x06, 0x9c, 0x5e, 0xad, 0x6e, - 0x27, 0x91, 0xba, 0x0b, 0x0b, 0x87, 0x58, 0x8a, 0x58, 0xad, 0xc1, 0x5c, 0x1c, 0x21, 0x42, 0x91, - 0xcd, 0x13, 0xcf, 0x0e, 0x83, 0xa6, 0x8f, 0x63, 0xcc, 0xa9, 0x17, 0xcc, 0xd9, 0x8c, 0x6c, 0x2b, - 0x15, 0x19, 0x5f, 0x28, 0x30, 0xb5, 0x43, 0xdd, 0x2d, 0x1f, 0xa3, 0xa8, 0x8a, 0x7c, 0x44, 0x6c, - 0x7c, 0xba, 0x67, 0xd7, 0x8b, 0xc7, 0xf0, 0x7b, 0xc5, 0x83, 0x19, 0x6f, 0x20, 0x42, 0xb0, 0x9f, - 0xbc, 0x19, 0xb3, 0xbb, 0x34, 0x16, 0xe0, 0x72, 0x1f, 0x53, 0x91, 0xd3, 0x5f, 0x25, 0x39, 0xcd, - 0xf2, 0x1e, 0x07, 0x1f, 0xea, 0xe6, 0x16, 0x81, 0x67, 0xb0, 0xf5, 0xef, 0x90, 0xa4, 0x85, 0xc5, - 0x2c, 0xb0, 0x8d, 0x87, 0x21, 0xc1, 0xaa, 0x0e, 0x85, 0x08, 0xdb, 0xd8, 0xdb, 0xc7, 0x51, 0xea, - 0x87, 0x58, 0x1b, 0x1a, 0x4f, 0xf6, 0x0c, 0x59, 0xe1, 0xc7, 0xd7, 0xe7, 0x61, 0x96, 0x8b, 0x5c, - 0x8f, 0xc6, 0x38, 0xba, 0xdd, 0xd5, 0xf6, 0x57, 0x98, 0xb0, 0x43, 0x42, 0x70, 0x72, 0xaf, 0xdd, - 0xe0, 0x57, 0xb5, 0x83, 0x4e, 0x69, 0xee, 0x29, 0x0a, 0xfc, 0x9b, 0x46, 0x4e, 0x6c, 0x98, 0xe3, - 0xbd, 0x75, 0xcd, 0x51, 0x0d, 0x18, 0xaf, 0x63, 0xbb, 0xb1, 0xb1, 0xde, 0x8c, 0xf0, 0x9e, 0xd7, - 0xd6, 0xc6, 0x39, 0xa1, 0xdc, 0x9e, 0x7a, 0x23, 0xf7, 0x42, 0x93, 0x72, 0x75, 0xe9, 0xa0, 0x53, - 0x9a, 0x49, 0xf4, 0xf7, 0x64, 0x46, 0xe6, 0xe1, 0xaa, 0x6b, 0x70, 0xb1, 0x97, 0xb3, 0xe7, 0xf9, - 0xa1, 0xb9, 0x83, 0x4e, 0x69, 0x3a, 0x39, 0x24, 0x44, 0x86, 0x59, 0xf0, 0xd2, 0x0c, 0xce, 0x5e, - 0xcc, 0x68, 0xfe, 0x62, 0xee, 0x42, 0x92, 0xa2, 0x7b, 0x38, 0xb2, 0xd2, 0x4b, 0x67, 0xbe, 0x02, - 0x57, 0x5b, 0x3c, 0xe8, 0x94, 0xf4, 0x44, 0xad, 0x04, 0x64, 0x98, 0x33, 0xdd, 0xdd, 0xad, 0x64, - 0x93, 0xa7, 0xe4, 0x74, 0x8b, 0xd4, 0x43, 0xe2, 0x78, 0xc4, 0xb5, 0x9a, 0x38, 0xf2, 0x42, 0x47, - 0x1b, 0x5b, 0x52, 0x56, 0x46, 0xaa, 0x8b, 0x07, 0x9d, 0xd2, 0xe5, 0x44, 0x59, 0x3f, 0xc2, 0x30, - 0xa7, 0xc4, 0xd6, 0xdf, 0xf9, 0x8e, 0xea, 0xc3, 0x2c, 0xeb, 0x28, 0xfd, 0x25, 0x7d, 0xe2, 0x0c, - 0x4a, 0xfa, 0x4c, 0xe0, 0x91, 0xbe, 0x36, 0xc2, 0xac, 0xa1, 0xf6, 0x21, 0x6b, 0x93, 0x67, 0x62, - 0x0d, 0xb5, 0xfb, 0xac, 0xfd, 0x11, 0x34, 0x56, 0x7e, 0x7c, 0x5e, 0x4d, 0x2c, 0x3e, 0x01, 0x58, - 0x98, 0xa0, 0xba, 0x8f, 0x1d, 0x6d, 0x8a, 0x97, 0x8d, 0x4b, 0x3e, 0x0d, 0x32, 0xc5, 0xe6, 0x56, - 0x22, 0xbc, 0x59, 0xf8, 0xdf, 0xf3, 0xd2, 0xd0, 0x8f, 0xcf, 0x4b, 0x43, 0xc6, 0x15, 0x58, 0x94, - 0xe4, 0xac, 0xc8, 0xe9, 0xff, 0x2a, 0xbc, 0x64, 0x6d, 0xf9, 0xc8, 0x0b, 0xee, 0x13, 0x07, 0xfb, - 0xd8, 0x45, 0x31, 0x76, 0x78, 0x59, 0x3b, 0xaa, 0xc5, 0x2f, 0xc1, 0xb8, 0x78, 0x5e, 0xbd, 0x7a, - 0x03, 0xdd, 0x17, 0x56, 0x73, 0xd4, 0x39, 0x38, 0x8f, 0x9b, 0xa1, 0xdd, 0xe0, 0x8f, 0x6f, 0xc4, - 0x4c, 0x16, 0xea, 0x3c, 0x8c, 0x52, 0x4c, 0x1c, 0xf1, 0xee, 0xd2, 0x95, 0xb1, 0x0c, 0x57, 0x07, - 0xd2, 0x10, 0x64, 0xe3, 0xf4, 0x69, 0xd6, 0x93, 0x02, 0xf3, 0x8f, 0xee, 0x20, 0x74, 0x14, 0xd1, - 0x5c, 0x1d, 0x38, 0xd7, 0x57, 0x07, 0x96, 0x61, 0x82, 0xb4, 0x02, 0x2b, 0xea, 0x6a, 0x4c, 0xb9, - 0x8e, 0x93, 0x56, 0x20, 0xac, 0x18, 0x4b, 0x50, 0x94, 0x5b, 0xcd, 0x06, 0x71, 0x7a, 0x87, 0xba, - 0x9b, 0x8e, 0xf3, 0xfe, 0x94, 0x6e, 0x02, 0x88, 0x01, 0x8f, 0x6a, 0xc3, 0x4b, 0xc3, 0x2b, 0x63, - 0xeb, 0x7a, 0xb9, 0x6f, 0x6e, 0x2c, 0x0b, 0x3b, 0x66, 0x06, 0x6d, 0xe8, 0xa0, 0xf5, 0xd3, 0x10, - 0x1c, 0x3f, 0x53, 0xb8, 0x90, 0xbd, 0x3f, 0xb7, 0xe7, 0xc3, 0x03, 0xec, 0xb9, 0x8d, 0xf8, 0xb4, - 0x5c, 0x37, 0xa0, 0xb0, 0x8f, 0x7c, 0x0b, 0x39, 0x4e, 0x94, 0xf6, 0x15, 0xed, 0xf5, 0x8b, 0xd5, - 0xb9, 0x34, 0xa7, 0x37, 0x1d, 0x27, 0xc2, 0x94, 0xee, 0xc6, 0x91, 0x47, 0x5c, 0xf3, 0xc2, 0x3e, - 0xf2, 0xd9, 0x0e, 0xcb, 0x80, 0x27, 0xdc, 0x2a, 0xcf, 0x80, 0x11, 0x33, 0x5d, 0x19, 0x06, 0x2c, - 0x0d, 0xe2, 0x27, 0x9c, 0x78, 0xa6, 0x80, 0xba, 0x43, 0xdd, 0x6d, 0xcc, 0xba, 0xa3, 0x00, 0x7d, - 0x48, 0xfa, 0xc6, 0x2f, 0x40, 0x3f, 0xcc, 0x40, 0x10, 0xfc, 0x54, 0x49, 0x9f, 0x1b, 0x8d, 0xc3, - 0x08, 0xd7, 0x48, 0x8c, 0x23, 0xde, 0x82, 0x37, 0x93, 0x91, 0xfe, 0x74, 0xcd, 0xbb, 0x0a, 0xe3, - 0xe9, 0x4f, 0x02, 0x8b, 0xd5, 0x0e, 0xce, 0x75, 0x72, 0xbd, 0x74, 0x28, 0x29, 0x6a, 0x5b, 0x9b, - 0xa9, 0x9d, 0x7b, 0x4f, 0x9b, 0xd8, 0x1c, 0x43, 0xbd, 0x85, 0xf1, 0x2b, 0x58, 0x3e, 0x82, 0x97, - 0xe0, 0xff, 0x98, 0x5f, 0x42, 0x32, 0xac, 0x0a, 0xef, 0x76, 0x1b, 0x28, 0xc2, 0xf4, 0x56, 0xdb, - 0x6e, 0xf0, 0xa2, 0x74, 0x2a, 0x1f, 0x34, 0x60, 0x11, 0x0c, 0x9b, 0x38, 0x0d, 0xb5, 0xd9, 0x5d, - 0x1a, 0xd7, 0x60, 0xe5, 0x38, 0x93, 0x82, 0x5e, 0x8b, 0x4f, 0x81, 0xbd, 0x02, 0xc1, 0xca, 0xd9, - 0xcf, 0x3f, 0x4b, 0x18, 0x8b, 0xbc, 0x46, 0xe6, 0xcd, 0x0a, 0x4e, 0x2e, 0x2f, 0x4a, 0x5b, 0xc8, - 0xf7, 0xea, 0xac, 0x15, 0x6c, 0x27, 0x18, 0x2f, 0x24, 0x67, 0x1d, 0xa8, 0xa4, 0x0e, 0x49, 0x0c, - 0x09, 0x2a, 0xb7, 0x79, 0x78, 0x4c, 0x4c, 0x5b, 0x01, 0x16, 0xd3, 0xc9, 0x69, 0x58, 0xa4, 0x1e, - 0xe7, 0x35, 0x75, 0xcd, 0xac, 0x77, 0x26, 0x60, 0x78, 0x87, 0xba, 0xea, 0x03, 0x18, 0xcb, 0x4e, - 0xe3, 0x87, 0x13, 0x32, 0xff, 0xa3, 0x41, 0xff, 0xcd, 0x31, 0x00, 0x31, 0x29, 0xff, 0x0b, 0x26, - 0xfb, 0x26, 0x7d, 0x43, 0x7a, 0x34, 0x87, 0xd1, 0xaf, 0x1d, 0x8f, 0x11, 0x16, 0x1e, 0xc0, 0x58, - 0x76, 0x1c, 0x95, 0x52, 0xcf, 0x00, 0xe4, 0xd4, 0x25, 0x33, 0xa2, 0xba, 0x07, 0xd3, 0x87, 0xe6, - 0xc3, 0x5f, 0xca, 0x0f, 0xe7, 0x51, 0xfa, 0xf5, 0x93, 0xa0, 0x84, 0x9d, 0x36, 0xcc, 0x0f, 0xe8, - 0xd9, 0xd2, 0x30, 0xc8, 0xb1, 0xfa, 0xfa, 0xc9, 0xb1, 0xc2, 0x72, 0x08, 0xb3, 0xb2, 0x0e, 0x3c, - 0x20, 0x42, 0x87, 0x80, 0x7a, 0xe5, 0x84, 0x40, 0x61, 0xf0, 0x9f, 0x30, 0x91, 0xef, 0xac, 0x57, - 0x65, 0x1a, 0x72, 0x10, 0xfd, 0xb7, 0xc7, 0x42, 0x84, 0xfa, 0x16, 0x5c, 0x92, 0x37, 0x45, 0xa9, - 0x0e, 0x29, 0x54, 0x5f, 0x3b, 0x31, 0x54, 0x98, 0xb5, 0x61, 0xaa, 0xbf, 0x8d, 0x2d, 0xcb, 0xb4, - 0xf4, 0x81, 0xf4, 0xdf, 0x9d, 0x00, 0x24, 0x8c, 0xfc, 0x07, 0xb4, 0x81, 0xad, 0x68, 0x40, 0xbe, - 0xc9, 0xd1, 0xfa, 0x8d, 0x77, 0x41, 0x0b, 0xfb, 0xff, 0x57, 0xe0, 0xca, 0xd1, 0xcd, 0x44, 0x1a, - 0xb9, 0x23, 0x8f, 0xe8, 0x7f, 0x7a, 0xe7, 0x23, 0xd9, 0xdc, 0x95, 0x15, 0x6a, 0x69, 0xee, 0x4a, - 0x80, 0xf2, 0xdc, 0x3d, 0xa2, 0x22, 0xab, 0x0f, 0x61, 0x3c, 0xf7, 0xe3, 0x7d, 0x49, 0xfe, 0xe0, - 0x7a, 0x08, 0x7d, 0xe5, 0x38, 0x44, 0xb6, 0x4a, 0xf6, 0x75, 0x42, 0x69, 0x95, 0xcc, 0x63, 0xe4, - 0x55, 0x52, 0xde, 0xda, 0xd4, 0x4f, 0x14, 0x28, 0x1d, 0xf7, 0x15, 0x70, 0x63, 0xf0, 0x6d, 0x0c, - 0x3c, 0xa4, 0xff, 0xf9, 0x14, 0x87, 0xb2, 0x7e, 0xf7, 0xb5, 0x38, 0x63, 0x40, 0x72, 0x66, 0x30, - 0x72, 0xbf, 0xe5, 0x0d, 0xae, 0x7a, 0xe7, 0xe5, 0x9b, 0xa2, 0xf2, 0xea, 0x4d, 0x51, 0xf9, 0xe1, - 0x4d, 0x51, 0xf9, 0xe8, 0x6d, 0x71, 0xe8, 0xd5, 0xdb, 0xe2, 0xd0, 0xb7, 0x6f, 0x8b, 0x43, 0x0f, - 0xd7, 0x33, 0x93, 0xc3, 0x2e, 0xd7, 0xb7, 0x7a, 0x07, 0xd5, 0x69, 0x25, 0xfd, 0x46, 0xbb, 0xbf, - 0xf6, 0x87, 0x4a, 0x3b, 0xf3, 0xdd, 0x97, 0x4d, 0x12, 0xf5, 0x51, 0xfe, 0x55, 0x75, 0xe3, 0xa7, - 0x00, 0x00, 0x00, 0xff, 0xff, 0xe3, 0xea, 0x73, 0x2e, 0x17, 0x16, 0x00, 0x00, + // 2057 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x59, 0x4f, 0x6f, 0x24, 0x47, + 0x15, 0xf7, 0xac, 0xbd, 0xf6, 0xf8, 0xd9, 0x5e, 0xdb, 0x6d, 0xaf, 0x77, 0xdc, 0x1b, 0xcf, 0x78, + 0xdb, 0x1b, 0x30, 0x4e, 0x3c, 0x83, 0xed, 0x28, 0x80, 0x01, 0x09, 0xff, 0x09, 0x64, 0xc4, 0x3a, + 0x41, 0x6d, 0x27, 0x2b, 0xad, 0x84, 0x9a, 0x9a, 0xee, 0xda, 0x99, 0xd6, 0x76, 0x77, 0x4d, 0xba, + 0x7a, 0xec, 0x59, 0x0e, 0x28, 0x42, 0x42, 0x42, 0x08, 0x24, 0x10, 0x12, 0x27, 0x84, 0x72, 0xe0, + 0x80, 0xe0, 0x12, 0xa1, 0x7c, 0x88, 0x20, 0x24, 0x14, 0xe5, 0x84, 0x38, 0x18, 0xb4, 0x7b, 0x08, + 0x67, 0x7f, 0x02, 0x54, 0x55, 0x3d, 0x35, 0xdd, 0x3d, 0x35, 0x1e, 0xdb, 0x71, 0x56, 0x5c, 0x6c, + 0x57, 0xd5, 0xaf, 0xde, 0xfb, 0xbd, 0x57, 0xef, 0xbd, 0x7a, 0xd5, 0x86, 0x02, 0x8d, 0x42, 0xd7, + 0xc1, 0x15, 0x1a, 0xa1, 0x27, 0xd8, 0xad, 0xd9, 0x95, 0xa8, 0x5d, 0x6e, 0x86, 0x24, 0x22, 0xda, + 0xb4, 0x58, 0x29, 0x77, 0x56, 0xf4, 0x52, 0x16, 0x7a, 0x8c, 0x3c, 0xd7, 0x41, 0x11, 0x09, 0xc5, + 0x0e, 0x7d, 0xbe, 0x4e, 0xea, 0x84, 0xff, 0x59, 0x61, 0x7f, 0xc5, 0xb3, 0x8b, 0x36, 0xa1, 0x3e, + 0xa1, 0x96, 0x58, 0x10, 0x83, 0x78, 0xa9, 0x28, 0x46, 0x95, 0x1a, 0xa2, 0xb8, 0x72, 0xbc, 0x51, + 0xc3, 0x11, 0xda, 0xa8, 0xd8, 0xc4, 0x0d, 0xe2, 0xf5, 0x3b, 0xf1, 0xba, 0x4f, 0xeb, 0x95, 0xe3, + 0x0d, 0xf6, 0x2b, 0x5e, 0x98, 0x45, 0xbe, 0x1b, 0x90, 0x0a, 0xff, 0x29, 0xa6, 0x8c, 0xbf, 0xdf, + 0x00, 0xe3, 0x80, 0xd6, 0xdf, 0x69, 0x3a, 0x28, 0xc2, 0xd5, 0x20, 0xc0, 0xa1, 0x89, 0x1d, 0xec, + 0x37, 0x23, 0x97, 0x04, 0x26, 0x8a, 0xf0, 0x2e, 0x69, 0x05, 0x0e, 0xd5, 0x0a, 0x30, 0x66, 0x87, + 0x98, 0x91, 0x2e, 0xe4, 0x96, 0x73, 0xab, 0xe3, 0x66, 0x67, 0xa8, 0x2d, 0x42, 0xde, 0x6e, 0x20, + 0x37, 0xb0, 0x5c, 0xa7, 0x70, 0x23, 0x5e, 0x62, 0xe3, 0xaa, 0xa3, 0x9d, 0xc0, 0xa2, 0xcf, 0x16, + 0x98, 0x54, 0x2b, 0x94, 0x62, 0xad, 0x10, 0x45, 0xb8, 0x30, 0xcc, 0xb0, 0xbb, 0xdf, 0xfa, 0xf8, + 0xb4, 0x34, 0xf4, 0xaf, 0xd3, 0xd2, 0x97, 0xea, 0x6e, 0xd4, 0x68, 0xd5, 0xca, 0x36, 0xf1, 0x63, + 0x5b, 0xe3, 0x5f, 0xeb, 0xd4, 0x79, 0x52, 0x89, 0x9e, 0x36, 0x31, 0x2d, 0xef, 0x63, 0xfb, 0xd3, + 0x8f, 0xd6, 0x21, 0x76, 0xc5, 0x3e, 0xb6, 0xcd, 0x05, 0xdf, 0x0d, 0x14, 0x9c, 0xb9, 0x62, 0xd4, + 0xee, 0xa3, 0x78, 0xe4, 0x5a, 0x14, 0xa3, 0xb6, 0x42, 0xb1, 0xf1, 0x2a, 0xac, 0x0d, 0x76, 0xa6, + 0x89, 0x69, 0x93, 0x04, 0x14, 0x1b, 0xbf, 0xc9, 0xc1, 0xad, 0x03, 0x5a, 0x7f, 0xe0, 0xbe, 0xd7, + 0x72, 0x9d, 0x43, 0x16, 0x1e, 0xe7, 0xf8, 0xf9, 0xbb, 0x30, 0x8a, 0x7c, 0xd2, 0x0a, 0x22, 0xe1, + 0xe5, 0xdd, 0xf2, 0x25, 0x0c, 0xa8, 0x06, 0x91, 0x19, 0xef, 0xd6, 0x96, 0x00, 0x1a, 0x84, 0x46, + 0x96, 0x83, 0x03, 0xe2, 0x8b, 0x53, 0x30, 0xc7, 0xd9, 0xcc, 0x3e, 0x9b, 0x30, 0xde, 0xcf, 0xc1, + 0x42, 0x9a, 0x53, 0x87, 0xae, 0xf6, 0x18, 0xf2, 0x34, 0xb2, 0x22, 0xf2, 0x04, 0x07, 0x9c, 0xdc, + 0xc4, 0xe6, 0x62, 0x39, 0xf6, 0x09, 0x8b, 0xc4, 0x72, 0x1c, 0x89, 0xe5, 0x3d, 0xe2, 0x06, 0xbb, + 0x5f, 0x65, 0xf4, 0xfe, 0xfc, 0xef, 0xd2, 0xea, 0x05, 0xe8, 0xb1, 0x0d, 0xd4, 0x1c, 0xa3, 0xd1, + 0x11, 0x93, 0x6d, 0xfc, 0x31, 0x07, 0xb3, 0x8c, 0xc2, 0xe1, 0xc1, 0x8b, 0xf5, 0xcc, 0x3a, 0xcc, + 0x79, 0xd4, 0x17, 0x06, 0x5a, 0x6e, 0xcd, 0x4e, 0xb9, 0x68, 0xc6, 0xa3, 0x3e, 0xa7, 0x57, 0xad, + 0xd9, 0xc2, 0x53, 0x6f, 0xc1, 0x62, 0x0f, 0x4b, 0xe9, 0xab, 0x0d, 0x98, 0x8f, 0x42, 0x14, 0x50, + 0x64, 0xf3, 0xc0, 0xb3, 0x89, 0xdf, 0xf4, 0x70, 0x84, 0x39, 0xf5, 0xbc, 0x39, 0x97, 0x58, 0xdb, + 0x8b, 0x97, 0x8c, 0x3f, 0xe5, 0x60, 0xfa, 0x80, 0xd6, 0xf7, 0x3c, 0x8c, 0xc2, 0x5d, 0xe4, 0xa1, + 0xc0, 0xc6, 0x57, 0x4b, 0xbb, 0xae, 0x3f, 0x86, 0x3f, 0x97, 0x3f, 0x98, 0xf2, 0x06, 0x0a, 0x02, + 0xec, 0x89, 0x9c, 0x31, 0x3b, 0x43, 0x63, 0x11, 0xee, 0x64, 0x98, 0xca, 0x98, 0xfe, 0x8b, 0x88, + 0x69, 0x16, 0xf7, 0xd8, 0x7f, 0x51, 0x27, 0x77, 0x17, 0x78, 0x04, 0x5b, 0x3f, 0x26, 0x41, 0x5c, + 0x58, 0xcc, 0x3c, 0x9b, 0x78, 0x44, 0x02, 0xac, 0xe9, 0x90, 0x0f, 0xb1, 0x8d, 0xdd, 0x63, 0x1c, + 0xc6, 0x76, 0xc8, 0xb1, 0x51, 0xe0, 0xc1, 0x9e, 0x20, 0x2b, 0xed, 0xf8, 0xeb, 0x4d, 0x98, 0xe3, + 0x4b, 0x75, 0x97, 0x46, 0x38, 0x7c, 0xb3, 0x23, 0xed, 0xdb, 0x30, 0x65, 0x93, 0x20, 0xc0, 0xe2, + 0x5c, 0x3b, 0xce, 0xdf, 0x2d, 0x9c, 0x9d, 0x96, 0xe6, 0x9f, 0x22, 0xdf, 0xdb, 0x36, 0x52, 0xcb, + 0x86, 0x39, 0xd9, 0x1d, 0x57, 0x1d, 0xcd, 0x80, 0xc9, 0x1a, 0xb6, 0x1b, 0x5b, 0x9b, 0xcd, 0x10, + 0x3f, 0x76, 0xdb, 0x85, 0x49, 0x4e, 0x28, 0x35, 0xa7, 0xbd, 0x96, 0xca, 0x50, 0x51, 0xae, 0x6e, + 0x9f, 0x9d, 0x96, 0x66, 0x85, 0xfc, 0xee, 0x9a, 0x91, 0x48, 0x5c, 0x6d, 0x03, 0xc6, 0xbb, 0x31, + 0x7b, 0x93, 0x6f, 0x9a, 0x3f, 0x3b, 0x2d, 0xcd, 0x88, 0x4d, 0x72, 0xc9, 0x30, 0xf3, 0x6e, 0x1c, + 0xc1, 0xc9, 0x83, 0x19, 0x4d, 0x1f, 0xcc, 0x5b, 0x20, 0x42, 0xf4, 0x31, 0x0e, 0xad, 0xf8, 0xd0, + 0x99, 0xad, 0xc0, 0xc5, 0x16, 0xcf, 0x4e, 0x4b, 0xba, 0x10, 0xab, 0x00, 0x19, 0xe6, 0x6c, 0x67, + 0x76, 0x4f, 0x4c, 0xf2, 0x90, 0x9c, 0x69, 0x05, 0x35, 0x12, 0x38, 0x6e, 0x50, 0xb7, 0x9a, 0x38, + 0x74, 0x89, 0x53, 0x98, 0x58, 0xce, 0xad, 0x8e, 0xec, 0xde, 0x3d, 0x3b, 0x2d, 0xdd, 0x11, 0xc2, + 0xb2, 0x08, 0xc3, 0x9c, 0x96, 0x53, 0x3f, 0xe0, 0x33, 0x9a, 0x07, 0x73, 0xec, 0x46, 0xc9, 0x96, + 0xf4, 0xa9, 0x6b, 0x28, 0xe9, 0xb3, 0xbe, 0x1b, 0x64, 0xae, 0x11, 0xa6, 0x0d, 0xb5, 0x7b, 0xb4, + 0xdd, 0xba, 0x16, 0x6d, 0xa8, 0x9d, 0xd1, 0xf6, 0x35, 0x28, 0xb0, 0xf2, 0xe3, 0xf1, 0x6a, 0x62, + 0xf1, 0x6e, 0xc1, 0xc2, 0x01, 0xaa, 0x79, 0xd8, 0x29, 0x4c, 0xf3, 0xb2, 0x71, 0xdb, 0xa3, 0x7e, + 0xa2, 0xd8, 0xbc, 0x21, 0x16, 0xb7, 0xf3, 0x3f, 0xff, 0xa0, 0x34, 0xf4, 0xdf, 0x0f, 0x4a, 0x43, + 0xc6, 0x12, 0xdc, 0x55, 0xc4, 0xac, 0x8c, 0xe9, 0x9f, 0xe5, 0x78, 0xc9, 0xda, 0xf3, 0x90, 0xeb, + 0xbf, 0x13, 0x38, 0xd8, 0xc3, 0x75, 0x14, 0x61, 0x87, 0x97, 0xb5, 0xf3, 0xae, 0xf8, 0x65, 0x98, + 0x94, 0xe9, 0xd5, 0xad, 0x37, 0xd0, 0xc9, 0xb0, 0xaa, 0xa3, 0xcd, 0xc3, 0x4d, 0xdc, 0x24, 0x76, + 0x83, 0x27, 0xdf, 0x88, 0x29, 0x06, 0xda, 0x02, 0x8c, 0x52, 0x1c, 0x38, 0x32, 0xef, 0xe2, 0x91, + 0xb1, 0x02, 0xf7, 0xfa, 0xd2, 0x90, 0x64, 0xa3, 0x38, 0x35, 0x6b, 0xa2, 0xc0, 0xbc, 0xdb, 0x69, + 0x9a, 0xce, 0x23, 0x9a, 0xaa, 0x03, 0x37, 0x32, 0x75, 0x60, 0x05, 0xa6, 0x82, 0x96, 0x6f, 0x85, + 0x1d, 0x89, 0x31, 0xd7, 0xc9, 0xa0, 0xe5, 0x4b, 0x2d, 0xc6, 0x32, 0x14, 0xd5, 0x5a, 0x93, 0x4e, + 0x9c, 0x39, 0xa0, 0xf5, 0x1d, 0xc7, 0xf9, 0xfc, 0x94, 0xb6, 0x01, 0x64, 0x33, 0x48, 0x0b, 0xc3, + 0xcb, 0xc3, 0xab, 0x13, 0x9b, 0x7a, 0x39, 0xd3, 0x40, 0x96, 0xa5, 0x1e, 0x33, 0x81, 0x36, 0x74, + 0x28, 0x64, 0x69, 0x48, 0x8e, 0x7f, 0xc8, 0xf1, 0x45, 0x96, 0x7f, 0xf5, 0xae, 0x0d, 0x0f, 0xb1, + 0x5b, 0x6f, 0x44, 0x57, 0xe5, 0xba, 0x05, 0xf9, 0x63, 0xe4, 0x59, 0xc8, 0x71, 0xc2, 0xf8, 0x5e, + 0x29, 0x7c, 0xfa, 0xd1, 0xfa, 0x7c, 0x1c, 0xd3, 0x3b, 0x8e, 0x13, 0x62, 0x4a, 0x0f, 0xa3, 0xd0, + 0x0d, 0xea, 0xe6, 0xd8, 0x31, 0xf2, 0xd8, 0x0c, 0x8b, 0x80, 0x13, 0xae, 0x95, 0x47, 0xc0, 0x88, + 0x19, 0x8f, 0x0c, 0x03, 0x96, 0xfb, 0xf1, 0x93, 0x46, 0xbc, 0x9f, 0x03, 0xed, 0x80, 0xd6, 0xf7, + 0x31, 0xbb, 0x1d, 0x25, 0xe8, 0x45, 0xd2, 0x37, 0x5e, 0x02, 0xbd, 0x97, 0x81, 0x24, 0xf8, 0xfb, + 0x5c, 0x9c, 0x6e, 0x34, 0x22, 0x21, 0xae, 0x06, 0x11, 0x0e, 0xf9, 0x15, 0xbc, 0x63, 0xdb, 0xf2, + 0xfe, 0xbc, 0xf4, 0xe5, 0xbd, 0x92, 0xbd, 0x5f, 0xc4, 0x75, 0x96, 0xbe, 0x45, 0x56, 0x60, 0x0a, + 0x09, 0x25, 0x16, 0x39, 0x09, 0x64, 0x7e, 0x4d, 0xc6, 0x93, 0x6f, 0xb3, 0x39, 0xe3, 0x65, 0x58, + 0x39, 0x87, 0x9d, 0xb4, 0xe2, 0x3d, 0x7e, 0x14, 0xa2, 0x65, 0x95, 0x36, 0x1e, 0x36, 0x50, 0x88, + 0xe9, 0x1b, 0x6d, 0xbb, 0xc1, 0x4b, 0xd3, 0x95, 0x2c, 0x29, 0x00, 0xf3, 0x23, 0x69, 0xe2, 0xd8, + 0xe1, 0x66, 0x67, 0x68, 0xac, 0xc1, 0xea, 0x20, 0x95, 0x92, 0x5e, 0x8b, 0xf7, 0x82, 0xdd, 0x32, + 0xc1, 0x8a, 0xda, 0x17, 0xdf, 0x51, 0x18, 0x77, 0x79, 0xa5, 0x4c, 0xab, 0x95, 0x9c, 0xea, 0xbc, + 0x34, 0xed, 0x21, 0xcf, 0xad, 0xb1, 0x0b, 0x61, 0x5f, 0x60, 0x5c, 0x12, 0x5c, 0xb7, 0xa3, 0x44, + 0x35, 0x52, 0x28, 0x92, 0x54, 0xde, 0xe4, 0xee, 0x31, 0x31, 0x6d, 0xf9, 0x58, 0xf6, 0x28, 0x57, + 0x61, 0x11, 0x5b, 0x9c, 0x96, 0x24, 0xd5, 0xfc, 0x32, 0xcf, 0xbb, 0xa1, 0x3d, 0x26, 0x06, 0x1f, + 0x85, 0xc8, 0xc1, 0x26, 0x69, 0x45, 0x58, 0x7b, 0x1d, 0xc6, 0x51, 0x2b, 0x6a, 0x90, 0xd0, 0x8d, + 0x9e, 0x0a, 0x5d, 0xe7, 0xa4, 0x55, 0x17, 0xaa, 0x19, 0x30, 0xc5, 0x53, 0x35, 0x43, 0x66, 0x82, + 0x4d, 0xee, 0xc5, 0x6e, 0xd9, 0x85, 0xa2, 0xa8, 0x84, 0x56, 0x44, 0xac, 0x10, 0x9f, 0xa0, 0xd0, + 0xb1, 0x54, 0xa9, 0xa1, 0x0b, 0xd4, 0x11, 0x31, 0x39, 0x66, 0x2f, 0x99, 0x28, 0xdf, 0x81, 0xa5, + 0xae, 0x8c, 0x88, 0xf1, 0xce, 0x88, 0x10, 0x89, 0xb3, 0xd8, 0x11, 0xc1, 0x4d, 0x4b, 0x49, 0xa8, + 0x82, 0x68, 0xb8, 0xba, 0x1c, 0x54, 0x8d, 0x11, 0xef, 0xb7, 0xcc, 0x25, 0x86, 0xec, 0xf0, 0x38, + 0xea, 0x69, 0x82, 0xbe, 0x0f, 0x2b, 0x1d, 0x11, 0x1d, 0x32, 0x2a, 0x59, 0xa2, 0x15, 0x2b, 0x0a, + 0x68, 0x4c, 0xa9, 0x57, 0xd8, 0xf7, 0xe0, 0x5e, 0x2c, 0x82, 0x58, 0x82, 0xa0, 0x42, 0xd4, 0x18, + 0x17, 0xf5, 0x12, 0x07, 0x1e, 0x11, 0x76, 0xaa, 0xbd, 0x82, 0x2a, 0x30, 0x1f, 0xb3, 0xe2, 0xfd, + 0xa1, 0x45, 0x02, 0x2e, 0xaf, 0x90, 0xe7, 0x7b, 0x67, 0xc5, 0x1a, 0xef, 0x17, 0xdf, 0x0e, 0x78, + 0xf2, 0x6d, 0xc1, 0x42, 0x76, 0x83, 0x18, 0x17, 0xc6, 0xf9, 0x96, 0xb9, 0xd4, 0x16, 0xe1, 0x0c, + 0x6d, 0x03, 0x6e, 0x67, 0x37, 0x71, 0x56, 0xa2, 0xa5, 0x34, 0xb5, 0xd4, 0x1e, 0x6e, 0x32, 0x7b, + 0x8e, 0x75, 0x5b, 0xdd, 0xee, 0x86, 0x09, 0xf1, 0x1c, 0x93, 0x8d, 0x6f, 0x07, 0xfe, 0x0a, 0x68, + 0x69, 0x38, 0xb7, 0x42, 0xf4, 0xd7, 0xd3, 0x09, 0x34, 0xb7, 0xe1, 0x0e, 0x8c, 0x35, 0x09, 0xe1, + 0x3e, 0x9a, 0x12, 0x17, 0x13, 0x1b, 0x56, 0x1d, 0x6d, 0x1b, 0x74, 0xd6, 0xf2, 0x21, 0xcf, 0x23, + 0x27, 0xd8, 0xb1, 0xe8, 0x09, 0x6a, 0x5a, 0x1e, 0xa1, 0x34, 0xd1, 0xf9, 0xf1, 0xc7, 0xff, 0x8e, + 0x00, 0x1c, 0x9e, 0xa0, 0xe6, 0x03, 0x42, 0x29, 0xaf, 0x92, 0xef, 0xc2, 0x34, 0x6b, 0x4e, 0xf9, + 0x9e, 0xb8, 0x08, 0x4d, 0x5f, 0xa9, 0x08, 0x4d, 0xf9, 0x6e, 0xc0, 0x24, 0xef, 0x88, 0xd7, 0x0d, + 0x93, 0x8b, 0xda, 0x29, 0xb9, 0x33, 0x57, 0x94, 0x8b, 0xda, 0x5d, 0xb9, 0xdb, 0x5f, 0xff, 0xe9, + 0x67, 0x1f, 0xae, 0x75, 0x93, 0xf2, 0x17, 0x9f, 0x7d, 0xb8, 0xf6, 0x72, 0xfc, 0xad, 0xaa, 0xdd, + 0xfd, 0x5a, 0xa5, 0x48, 0xfb, 0xb8, 0xcf, 0xcc, 0x4e, 0xcb, 0x6a, 0xf1, 0xb7, 0x1c, 0xaf, 0x16, + 0xe2, 0xde, 0xbc, 0x86, 0x6a, 0x71, 0x0f, 0x26, 0x93, 0xc1, 0xd3, 0x29, 0x16, 0x89, 0x98, 0x19, + 0xf0, 0x55, 0xe3, 0xe2, 0xa6, 0x66, 0x39, 0xc7, 0xa6, 0x66, 0xa7, 0xa5, 0xa9, 0xff, 0x18, 0xe6, + 0xa6, 0x8a, 0xbb, 0xec, 0xff, 0xc1, 0xd4, 0x64, 0x68, 0x8f, 0x5c, 0x22, 0xb4, 0x6f, 0x5e, 0x36, + 0xb4, 0x47, 0xbf, 0xa0, 0xd0, 0x1e, 0x7b, 0xa1, 0xa1, 0x9d, 0x3d, 0xb8, 0xf8, 0xbc, 0xb3, 0xd3, + 0x9d, 0xf3, 0xde, 0xfc, 0xdd, 0x0c, 0x0c, 0x1f, 0xd0, 0xba, 0xf6, 0x10, 0x26, 0x92, 0x1f, 0xa7, + 0x4a, 0x3d, 0x4d, 0x7b, 0xfa, 0x1b, 0x9a, 0xfe, 0xe5, 0x01, 0x00, 0xf9, 0xe1, 0xe8, 0x47, 0x70, + 0x2b, 0xf3, 0xe1, 0xcb, 0x50, 0x6e, 0x4d, 0x61, 0xf4, 0xb5, 0xc1, 0x18, 0xa9, 0xe1, 0x21, 0x4c, + 0x24, 0xbf, 0xce, 0x28, 0xa9, 0x27, 0x00, 0x6a, 0xea, 0x8a, 0x4f, 0x26, 0xda, 0x63, 0x98, 0xe9, + 0xf9, 0x5c, 0x72, 0x5f, 0xbd, 0x39, 0x8d, 0xd2, 0x5f, 0xbd, 0x08, 0x4a, 0xea, 0x69, 0xc3, 0x42, + 0x9f, 0x27, 0xac, 0xd2, 0x0d, 0x6a, 0xac, 0xbe, 0x79, 0x71, 0xac, 0xd4, 0x4c, 0x60, 0x4e, 0xf5, + 0x20, 0xed, 0xe3, 0xa1, 0x1e, 0xa0, 0x5e, 0xb9, 0x20, 0x50, 0x2a, 0xfc, 0x21, 0x4c, 0xa5, 0x1f, + 0x9a, 0xf7, 0x54, 0x12, 0x52, 0x10, 0xfd, 0x2b, 0x03, 0x21, 0x52, 0x7c, 0x0b, 0x6e, 0xab, 0xdf, + 0x88, 0x4a, 0x19, 0x4a, 0xa8, 0xbe, 0x71, 0x61, 0xa8, 0x54, 0x6b, 0xc3, 0x74, 0xf6, 0x55, 0xb7, + 0xa2, 0x92, 0x92, 0x01, 0xe9, 0xaf, 0x5c, 0x00, 0x24, 0x95, 0xfc, 0x04, 0x0a, 0x7d, 0x5f, 0x66, + 0x7d, 0xe2, 0x4d, 0x8d, 0xd6, 0x5f, 0xbb, 0x0c, 0x5a, 0xea, 0xff, 0x55, 0x0e, 0x96, 0xce, 0x7f, + 0x55, 0x29, 0x3d, 0x77, 0xee, 0x16, 0xfd, 0x1b, 0x97, 0xde, 0x92, 0x8c, 0x5d, 0xd5, 0x8b, 0x45, + 0x19, 0xbb, 0x0a, 0xa0, 0x3a, 0x76, 0xcf, 0x79, 0x9a, 0x68, 0x8f, 0x60, 0x32, 0xf5, 0x2d, 0x7b, + 0x59, 0x9d, 0x70, 0x5d, 0x84, 0xbe, 0x3a, 0x08, 0x91, 0xac, 0x92, 0x99, 0x27, 0xa1, 0xb2, 0x4a, + 0xa6, 0x31, 0xea, 0x2a, 0xa9, 0x7e, 0xe3, 0x69, 0xbf, 0xcd, 0x41, 0x69, 0xd0, 0x3f, 0xc5, 0xb6, + 0xfa, 0x9f, 0x46, 0xdf, 0x4d, 0xfa, 0x37, 0xaf, 0xb0, 0x29, 0x69, 0x77, 0xe6, 0xad, 0x67, 0xf4, + 0x09, 0xce, 0x04, 0x46, 0x6d, 0xb7, 0xfa, 0xa5, 0xc7, 0x8a, 0x78, 0xcf, 0x2b, 0x4f, 0x59, 0xc4, + 0xb3, 0x28, 0x75, 0x11, 0xef, 0xd7, 0x23, 0x32, 0x3d, 0x3d, 0xfd, 0xe1, 0xfd, 0xfe, 0xf9, 0x3d, + 0x48, 0x4f, 0xbf, 0x06, 0x8d, 0xe9, 0xe9, 0x69, 0xce, 0xee, 0xf7, 0x3f, 0x82, 0x41, 0x7a, 0xfa, + 0x35, 0x06, 0xbb, 0x0f, 0x3e, 0x7e, 0x56, 0xcc, 0x7d, 0xf2, 0xac, 0x98, 0xfb, 0xcf, 0xb3, 0x62, + 0xee, 0xd7, 0xcf, 0x8b, 0x43, 0x9f, 0x3c, 0x2f, 0x0e, 0xfd, 0xf3, 0x79, 0x71, 0xe8, 0xd1, 0x66, + 0xa2, 0x85, 0x39, 0xe4, 0x12, 0xd7, 0x1f, 0xa0, 0x1a, 0xad, 0xc4, 0xfd, 0xc8, 0xf1, 0xc6, 0xeb, + 0xc9, 0x9e, 0x84, 0xb7, 0x34, 0xb5, 0x51, 0xfe, 0xcf, 0xd9, 0xad, 0xff, 0x05, 0x00, 0x00, 0xff, + 0xff, 0x9f, 0x21, 0x36, 0x14, 0x67, 0x1e, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -1720,6 +2201,9 @@ type MsgClient interface { UndelegateHost(ctx context.Context, in *MsgUndelegateHost, opts ...grpc.CallOption) (*MsgUndelegateHostResponse, error) UpdateInnerRedemptionRateBounds(ctx context.Context, in *MsgUpdateInnerRedemptionRateBounds, opts ...grpc.CallOption) (*MsgUpdateInnerRedemptionRateBoundsResponse, error) ResumeHostZone(ctx context.Context, in *MsgResumeHostZone, opts ...grpc.CallOption) (*MsgResumeHostZoneResponse, error) + CreateTradeRoute(ctx context.Context, in *MsgCreateTradeRoute, opts ...grpc.CallOption) (*MsgCreateTradeRouteResponse, error) + DeleteTradeRoute(ctx context.Context, in *MsgDeleteTradeRoute, opts ...grpc.CallOption) (*MsgDeleteTradeRouteResponse, error) + UpdateTradeRoute(ctx context.Context, in *MsgUpdateTradeRoute, opts ...grpc.CallOption) (*MsgUpdateTradeRouteResponse, error) } type msgClient struct { @@ -1874,6 +2358,33 @@ func (c *msgClient) ResumeHostZone(ctx context.Context, in *MsgResumeHostZone, o return out, nil } +func (c *msgClient) CreateTradeRoute(ctx context.Context, in *MsgCreateTradeRoute, opts ...grpc.CallOption) (*MsgCreateTradeRouteResponse, error) { + out := new(MsgCreateTradeRouteResponse) + err := c.cc.Invoke(ctx, "/stride.stakeibc.Msg/CreateTradeRoute", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) DeleteTradeRoute(ctx context.Context, in *MsgDeleteTradeRoute, opts ...grpc.CallOption) (*MsgDeleteTradeRouteResponse, error) { + out := new(MsgDeleteTradeRouteResponse) + err := c.cc.Invoke(ctx, "/stride.stakeibc.Msg/DeleteTradeRoute", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) UpdateTradeRoute(ctx context.Context, in *MsgUpdateTradeRoute, opts ...grpc.CallOption) (*MsgUpdateTradeRouteResponse, error) { + out := new(MsgUpdateTradeRouteResponse) + err := c.cc.Invoke(ctx, "/stride.stakeibc.Msg/UpdateTradeRoute", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // MsgServer is the server API for Msg service. type MsgServer interface { LiquidStake(context.Context, *MsgLiquidStake) (*MsgLiquidStakeResponse, error) @@ -1892,6 +2403,9 @@ type MsgServer interface { UndelegateHost(context.Context, *MsgUndelegateHost) (*MsgUndelegateHostResponse, error) UpdateInnerRedemptionRateBounds(context.Context, *MsgUpdateInnerRedemptionRateBounds) (*MsgUpdateInnerRedemptionRateBoundsResponse, error) ResumeHostZone(context.Context, *MsgResumeHostZone) (*MsgResumeHostZoneResponse, error) + CreateTradeRoute(context.Context, *MsgCreateTradeRoute) (*MsgCreateTradeRouteResponse, error) + DeleteTradeRoute(context.Context, *MsgDeleteTradeRoute) (*MsgDeleteTradeRouteResponse, error) + UpdateTradeRoute(context.Context, *MsgUpdateTradeRoute) (*MsgUpdateTradeRouteResponse, error) } // UnimplementedMsgServer can be embedded to have forward compatible implementations. @@ -1946,8 +2460,17 @@ func (*UnimplementedMsgServer) UpdateInnerRedemptionRateBounds(ctx context.Conte func (*UnimplementedMsgServer) ResumeHostZone(ctx context.Context, req *MsgResumeHostZone) (*MsgResumeHostZoneResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ResumeHostZone not implemented") } - -func RegisterMsgServer(s grpc1.Server, srv MsgServer) { +func (*UnimplementedMsgServer) CreateTradeRoute(ctx context.Context, req *MsgCreateTradeRoute) (*MsgCreateTradeRouteResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CreateTradeRoute not implemented") +} +func (*UnimplementedMsgServer) DeleteTradeRoute(ctx context.Context, req *MsgDeleteTradeRoute) (*MsgDeleteTradeRouteResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method DeleteTradeRoute not implemented") +} +func (*UnimplementedMsgServer) UpdateTradeRoute(ctx context.Context, req *MsgUpdateTradeRoute) (*MsgUpdateTradeRouteResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpdateTradeRoute not implemented") +} + +func RegisterMsgServer(s grpc1.Server, srv MsgServer) { s.RegisterService(&_Msg_serviceDesc, srv) } @@ -2239,6 +2762,60 @@ func _Msg_ResumeHostZone_Handler(srv interface{}, ctx context.Context, dec func( return interceptor(ctx, in, info, handler) } +func _Msg_CreateTradeRoute_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgCreateTradeRoute) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).CreateTradeRoute(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/stride.stakeibc.Msg/CreateTradeRoute", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).CreateTradeRoute(ctx, req.(*MsgCreateTradeRoute)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_DeleteTradeRoute_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgDeleteTradeRoute) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).DeleteTradeRoute(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/stride.stakeibc.Msg/DeleteTradeRoute", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).DeleteTradeRoute(ctx, req.(*MsgDeleteTradeRoute)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_UpdateTradeRoute_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgUpdateTradeRoute) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).UpdateTradeRoute(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/stride.stakeibc.Msg/UpdateTradeRoute", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).UpdateTradeRoute(ctx, req.(*MsgUpdateTradeRoute)) + } + return interceptor(ctx, in, info, handler) +} + var _Msg_serviceDesc = grpc.ServiceDesc{ ServiceName: "stride.stakeibc.Msg", HandlerType: (*MsgServer)(nil), @@ -2307,6 +2884,18 @@ var _Msg_serviceDesc = grpc.ServiceDesc{ MethodName: "ResumeHostZone", Handler: _Msg_ResumeHostZone_Handler, }, + { + MethodName: "CreateTradeRoute", + Handler: _Msg_CreateTradeRoute_Handler, + }, + { + MethodName: "DeleteTradeRoute", + Handler: _Msg_DeleteTradeRoute_Handler, + }, + { + MethodName: "UpdateTradeRoute", + Handler: _Msg_UpdateTradeRoute_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "stride/stakeibc/tx.proto", @@ -3199,10 +3788,19 @@ func (m *MsgRestoreInterchainAccount) MarshalToSizedBuffer(dAtA []byte) (int, er _ = i var l int _ = l - if m.AccountType != 0 { - i = encodeVarintTx(dAtA, i, uint64(m.AccountType)) + if len(m.AccountOwner) > 0 { + i -= len(m.AccountOwner) + copy(dAtA[i:], m.AccountOwner) + i = encodeVarintTx(dAtA, i, uint64(len(m.AccountOwner))) i-- - dAtA[i] = 0x18 + dAtA[i] = 0x22 + } + if len(m.ConnectionId) > 0 { + i -= len(m.ConnectionId) + copy(dAtA[i:], m.ConnectionId) + i = encodeVarintTx(dAtA, i, uint64(len(m.ConnectionId))) + i-- + dAtA[i] = 0x1a } if len(m.ChainId) > 0 { i -= len(m.ChainId) @@ -3501,225 +4099,348 @@ func (m *MsgResumeHostZoneResponse) MarshalToSizedBuffer(dAtA []byte) (int, erro return len(dAtA) - i, nil } -func encodeVarintTx(dAtA []byte, offset int, v uint64) int { - offset -= sovTx(v) - base := offset - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ +func (m *MsgCreateTradeRoute) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err } - dAtA[offset] = uint8(v) - return base + return dAtA[:n], nil } -func (m *MsgUpdateInnerRedemptionRateBounds) Size() (n int) { - if m == nil { - return 0 - } + +func (m *MsgCreateTradeRoute) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgCreateTradeRoute) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i var l int _ = l - l = len(m.Creator) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) + { + size := m.MaxSwapAmount.Size() + i -= size + if _, err := m.MaxSwapAmount.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintTx(dAtA, i, uint64(size)) } - l = len(m.ChainId) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x82 + { + size := m.MinSwapAmount.Size() + i -= size + if _, err := m.MinSwapAmount.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintTx(dAtA, i, uint64(size)) } - l = m.MinInnerRedemptionRate.Size() - n += 1 + l + sovTx(uint64(l)) - l = m.MaxInnerRedemptionRate.Size() - n += 1 + l + sovTx(uint64(l)) - return n -} - -func (m *MsgUpdateInnerRedemptionRateBoundsResponse) Size() (n int) { - if m == nil { - return 0 + i-- + dAtA[i] = 0x7a + if len(m.MaxAllowedSwapLossRate) > 0 { + i -= len(m.MaxAllowedSwapLossRate) + copy(dAtA[i:], m.MaxAllowedSwapLossRate) + i = encodeVarintTx(dAtA, i, uint64(len(m.MaxAllowedSwapLossRate))) + i-- + dAtA[i] = 0x72 } - var l int - _ = l - return n -} - -func (m *MsgLiquidStake) Size() (n int) { - if m == nil { - return 0 + if m.PoolId != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.PoolId)) + i-- + dAtA[i] = 0x68 } - var l int - _ = l - l = len(m.Creator) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) + if len(m.HostDenomOnHost) > 0 { + i -= len(m.HostDenomOnHost) + copy(dAtA[i:], m.HostDenomOnHost) + i = encodeVarintTx(dAtA, i, uint64(len(m.HostDenomOnHost))) + i-- + dAtA[i] = 0x62 } - l = m.Amount.Size() - n += 1 + l + sovTx(uint64(l)) - l = len(m.HostDenom) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) + if len(m.HostDenomOnTrade) > 0 { + i -= len(m.HostDenomOnTrade) + copy(dAtA[i:], m.HostDenomOnTrade) + i = encodeVarintTx(dAtA, i, uint64(len(m.HostDenomOnTrade))) + i-- + dAtA[i] = 0x5a } - return n -} - -func (m *MsgLiquidStakeResponse) Size() (n int) { - if m == nil { - return 0 + if len(m.RewardDenomOnTrade) > 0 { + i -= len(m.RewardDenomOnTrade) + copy(dAtA[i:], m.RewardDenomOnTrade) + i = encodeVarintTx(dAtA, i, uint64(len(m.RewardDenomOnTrade))) + i-- + dAtA[i] = 0x52 } - var l int - _ = l - l = m.StToken.Size() - n += 1 + l + sovTx(uint64(l)) - return n -} - -func (m *MsgLSMLiquidStake) Size() (n int) { - if m == nil { - return 0 + if len(m.RewardDenomOnReward) > 0 { + i -= len(m.RewardDenomOnReward) + copy(dAtA[i:], m.RewardDenomOnReward) + i = encodeVarintTx(dAtA, i, uint64(len(m.RewardDenomOnReward))) + i-- + dAtA[i] = 0x4a } - var l int - _ = l - l = len(m.Creator) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) + if len(m.RewardDenomOnHost) > 0 { + i -= len(m.RewardDenomOnHost) + copy(dAtA[i:], m.RewardDenomOnHost) + i = encodeVarintTx(dAtA, i, uint64(len(m.RewardDenomOnHost))) + i-- + dAtA[i] = 0x42 } - l = m.Amount.Size() - n += 1 + l + sovTx(uint64(l)) - l = len(m.LsmTokenIbcDenom) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) + if len(m.TradeToHostTransferChannelId) > 0 { + i -= len(m.TradeToHostTransferChannelId) + copy(dAtA[i:], m.TradeToHostTransferChannelId) + i = encodeVarintTx(dAtA, i, uint64(len(m.TradeToHostTransferChannelId))) + i-- + dAtA[i] = 0x3a } - return n -} - -func (m *MsgLSMLiquidStakeResponse) Size() (n int) { - if m == nil { - return 0 + if len(m.RewardToTradeTransferChannelId) > 0 { + i -= len(m.RewardToTradeTransferChannelId) + copy(dAtA[i:], m.RewardToTradeTransferChannelId) + i = encodeVarintTx(dAtA, i, uint64(len(m.RewardToTradeTransferChannelId))) + i-- + dAtA[i] = 0x32 } - var l int - _ = l - if m.TransactionComplete { - n += 2 + if len(m.HostToRewardTransferChannelId) > 0 { + i -= len(m.HostToRewardTransferChannelId) + copy(dAtA[i:], m.HostToRewardTransferChannelId) + i = encodeVarintTx(dAtA, i, uint64(len(m.HostToRewardTransferChannelId))) + i-- + dAtA[i] = 0x2a } - return n -} - -func (m *MsgClearBalance) Size() (n int) { - if m == nil { - return 0 + if len(m.StrideToTradeConnectionId) > 0 { + i -= len(m.StrideToTradeConnectionId) + copy(dAtA[i:], m.StrideToTradeConnectionId) + i = encodeVarintTx(dAtA, i, uint64(len(m.StrideToTradeConnectionId))) + i-- + dAtA[i] = 0x22 } - var l int - _ = l - l = len(m.Creator) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) + if len(m.StrideToRewardConnectionId) > 0 { + i -= len(m.StrideToRewardConnectionId) + copy(dAtA[i:], m.StrideToRewardConnectionId) + i = encodeVarintTx(dAtA, i, uint64(len(m.StrideToRewardConnectionId))) + i-- + dAtA[i] = 0x1a } - l = len(m.ChainId) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) + if len(m.HostChainId) > 0 { + i -= len(m.HostChainId) + copy(dAtA[i:], m.HostChainId) + i = encodeVarintTx(dAtA, i, uint64(len(m.HostChainId))) + i-- + dAtA[i] = 0x12 } - l = m.Amount.Size() - n += 1 + l + sovTx(uint64(l)) - l = len(m.Channel) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) + if len(m.Authority) > 0 { + i -= len(m.Authority) + copy(dAtA[i:], m.Authority) + i = encodeVarintTx(dAtA, i, uint64(len(m.Authority))) + i-- + dAtA[i] = 0xa } - return n + return len(dAtA) - i, nil } -func (m *MsgClearBalanceResponse) Size() (n int) { - if m == nil { - return 0 +func (m *MsgCreateTradeRouteResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err } - var l int - _ = l - return n + return dAtA[:n], nil } -func (m *MsgRedeemStake) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Creator) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = m.Amount.Size() - n += 1 + l + sovTx(uint64(l)) - l = len(m.HostZone) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = len(m.Receiver) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - return n +func (m *MsgCreateTradeRouteResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *MsgRedeemStakeResponse) Size() (n int) { - if m == nil { - return 0 - } +func (m *MsgCreateTradeRouteResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i var l int _ = l - return n + return len(dAtA) - i, nil } -func (m *MsgRegisterHostZone) Size() (n int) { - if m == nil { - return 0 +func (m *MsgDeleteTradeRoute) 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 *MsgDeleteTradeRoute) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgDeleteTradeRoute) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i var l int _ = l - l = len(m.ConnectionId) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) + if len(m.HostDenom) > 0 { + i -= len(m.HostDenom) + copy(dAtA[i:], m.HostDenom) + i = encodeVarintTx(dAtA, i, uint64(len(m.HostDenom))) + i-- + dAtA[i] = 0x1a } - l = len(m.HostDenom) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) + if len(m.RewardDenom) > 0 { + i -= len(m.RewardDenom) + copy(dAtA[i:], m.RewardDenom) + i = encodeVarintTx(dAtA, i, uint64(len(m.RewardDenom))) + i-- + dAtA[i] = 0x12 } - l = len(m.IbcDenom) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) + if len(m.Authority) > 0 { + i -= len(m.Authority) + copy(dAtA[i:], m.Authority) + i = encodeVarintTx(dAtA, i, uint64(len(m.Authority))) + i-- + dAtA[i] = 0xa } - l = len(m.Creator) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) + return len(dAtA) - i, nil +} + +func (m *MsgDeleteTradeRouteResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err } - l = len(m.TransferChannelId) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) + return dAtA[:n], nil +} + +func (m *MsgDeleteTradeRouteResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgDeleteTradeRouteResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgUpdateTradeRoute) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err } - if m.UnbondingPeriod != 0 { - n += 1 + sovTx(uint64(m.UnbondingPeriod)) + return dAtA[:n], nil +} + +func (m *MsgUpdateTradeRoute) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateTradeRoute) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size := m.MaxSwapAmount.Size() + i -= size + if _, err := m.MaxSwapAmount.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintTx(dAtA, i, uint64(size)) } - l = len(m.Bech32Prefix) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) + i-- + dAtA[i] = 0x3a + { + size := m.MinSwapAmount.Size() + i -= size + if _, err := m.MinSwapAmount.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintTx(dAtA, i, uint64(size)) } - l = m.MinRedemptionRate.Size() - n += 1 + l + sovTx(uint64(l)) - l = m.MaxRedemptionRate.Size() - n += 1 + l + sovTx(uint64(l)) - if m.LsmLiquidStakeEnabled { - n += 2 + i-- + dAtA[i] = 0x32 + if len(m.MaxAllowedSwapLossRate) > 0 { + i -= len(m.MaxAllowedSwapLossRate) + copy(dAtA[i:], m.MaxAllowedSwapLossRate) + i = encodeVarintTx(dAtA, i, uint64(len(m.MaxAllowedSwapLossRate))) + i-- + dAtA[i] = 0x2a } - return n + if m.PoolId != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.PoolId)) + i-- + dAtA[i] = 0x20 + } + if len(m.HostDenom) > 0 { + i -= len(m.HostDenom) + copy(dAtA[i:], m.HostDenom) + i = encodeVarintTx(dAtA, i, uint64(len(m.HostDenom))) + i-- + dAtA[i] = 0x1a + } + if len(m.RewardDenom) > 0 { + i -= len(m.RewardDenom) + copy(dAtA[i:], m.RewardDenom) + i = encodeVarintTx(dAtA, i, uint64(len(m.RewardDenom))) + i-- + dAtA[i] = 0x12 + } + if len(m.Authority) > 0 { + i -= len(m.Authority) + copy(dAtA[i:], m.Authority) + i = encodeVarintTx(dAtA, i, uint64(len(m.Authority))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil } -func (m *MsgRegisterHostZoneResponse) Size() (n int) { - if m == nil { - return 0 +func (m *MsgUpdateTradeRouteResponse) 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 *MsgUpdateTradeRouteResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateTradeRouteResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i var l int _ = l - return n + return len(dAtA) - i, nil } -func (m *MsgClaimUndelegatedTokens) Size() (n int) { +func encodeVarintTx(dAtA []byte, offset int, v uint64) int { + offset -= sovTx(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *MsgUpdateInnerRedemptionRateBounds) Size() (n int) { if m == nil { return 0 } @@ -3729,21 +4450,18 @@ func (m *MsgClaimUndelegatedTokens) Size() (n int) { if l > 0 { n += 1 + l + sovTx(uint64(l)) } - l = len(m.HostZoneId) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - if m.Epoch != 0 { - n += 1 + sovTx(uint64(m.Epoch)) - } - l = len(m.Sender) + l = len(m.ChainId) if l > 0 { n += 1 + l + sovTx(uint64(l)) } + l = m.MinInnerRedemptionRate.Size() + n += 1 + l + sovTx(uint64(l)) + l = m.MaxInnerRedemptionRate.Size() + n += 1 + l + sovTx(uint64(l)) return n } -func (m *MsgClaimUndelegatedTokensResponse) Size() (n int) { +func (m *MsgUpdateInnerRedemptionRateBoundsResponse) Size() (n int) { if m == nil { return 0 } @@ -3752,7 +4470,7 @@ func (m *MsgClaimUndelegatedTokensResponse) Size() (n int) { return n } -func (m *MsgRebalanceValidators) Size() (n int) { +func (m *MsgLiquidStake) Size() (n int) { if m == nil { return 0 } @@ -3762,26 +4480,27 @@ func (m *MsgRebalanceValidators) Size() (n int) { if l > 0 { n += 1 + l + sovTx(uint64(l)) } - l = len(m.HostZone) + l = m.Amount.Size() + n += 1 + l + sovTx(uint64(l)) + l = len(m.HostDenom) if l > 0 { n += 1 + l + sovTx(uint64(l)) } - if m.NumRebalance != 0 { - n += 1 + sovTx(uint64(m.NumRebalance)) - } return n } -func (m *MsgRebalanceValidatorsResponse) Size() (n int) { +func (m *MsgLiquidStakeResponse) Size() (n int) { if m == nil { return 0 } var l int _ = l + l = m.StToken.Size() + n += 1 + l + sovTx(uint64(l)) return n } -func (m *MsgAddValidators) Size() (n int) { +func (m *MsgLSMLiquidStake) Size() (n int) { if m == nil { return 0 } @@ -3791,29 +4510,28 @@ func (m *MsgAddValidators) Size() (n int) { if l > 0 { n += 1 + l + sovTx(uint64(l)) } - l = len(m.HostZone) + l = m.Amount.Size() + n += 1 + l + sovTx(uint64(l)) + l = len(m.LsmTokenIbcDenom) if l > 0 { n += 1 + l + sovTx(uint64(l)) } - if len(m.Validators) > 0 { - for _, e := range m.Validators { - l = e.Size() - n += 1 + l + sovTx(uint64(l)) - } - } return n } -func (m *MsgAddValidatorsResponse) Size() (n int) { +func (m *MsgLSMLiquidStakeResponse) Size() (n int) { if m == nil { return 0 } var l int _ = l + if m.TransactionComplete { + n += 2 + } return n } -func (m *MsgChangeValidatorWeight) Size() (n int) { +func (m *MsgClearBalance) Size() (n int) { if m == nil { return 0 } @@ -3823,21 +4541,20 @@ func (m *MsgChangeValidatorWeight) Size() (n int) { if l > 0 { n += 1 + l + sovTx(uint64(l)) } - l = len(m.HostZone) + l = len(m.ChainId) if l > 0 { n += 1 + l + sovTx(uint64(l)) } - l = len(m.ValAddr) + l = m.Amount.Size() + n += 1 + l + sovTx(uint64(l)) + l = len(m.Channel) if l > 0 { n += 1 + l + sovTx(uint64(l)) } - if m.Weight != 0 { - n += 1 + sovTx(uint64(m.Weight)) - } return n } -func (m *MsgChangeValidatorWeightResponse) Size() (n int) { +func (m *MsgClearBalanceResponse) Size() (n int) { if m == nil { return 0 } @@ -3846,7 +4563,7 @@ func (m *MsgChangeValidatorWeightResponse) Size() (n int) { return n } -func (m *MsgDeleteValidator) Size() (n int) { +func (m *MsgRedeemStake) Size() (n int) { if m == nil { return 0 } @@ -3856,18 +4573,20 @@ func (m *MsgDeleteValidator) Size() (n int) { if l > 0 { n += 1 + l + sovTx(uint64(l)) } + l = m.Amount.Size() + n += 1 + l + sovTx(uint64(l)) l = len(m.HostZone) if l > 0 { n += 1 + l + sovTx(uint64(l)) } - l = len(m.ValAddr) + l = len(m.Receiver) if l > 0 { n += 1 + l + sovTx(uint64(l)) } return n } -func (m *MsgDeleteValidatorResponse) Size() (n int) { +func (m *MsgRedeemStakeResponse) Size() (n int) { if m == nil { return 0 } @@ -3876,27 +4595,50 @@ func (m *MsgDeleteValidatorResponse) Size() (n int) { return n } -func (m *MsgRestoreInterchainAccount) Size() (n int) { +func (m *MsgRegisterHostZone) Size() (n int) { if m == nil { return 0 } var l int _ = l + l = len(m.ConnectionId) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.HostDenom) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.IbcDenom) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } l = len(m.Creator) if l > 0 { n += 1 + l + sovTx(uint64(l)) } - l = len(m.ChainId) + l = len(m.TransferChannelId) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.UnbondingPeriod != 0 { + n += 1 + sovTx(uint64(m.UnbondingPeriod)) + } + l = len(m.Bech32Prefix) if l > 0 { n += 1 + l + sovTx(uint64(l)) } - if m.AccountType != 0 { - n += 1 + sovTx(uint64(m.AccountType)) + l = m.MinRedemptionRate.Size() + n += 1 + l + sovTx(uint64(l)) + l = m.MaxRedemptionRate.Size() + n += 1 + l + sovTx(uint64(l)) + if m.LsmLiquidStakeEnabled { + n += 2 } return n } -func (m *MsgRestoreInterchainAccountResponse) Size() (n int) { +func (m *MsgRegisterHostZoneResponse) Size() (n int) { if m == nil { return 0 } @@ -3905,7 +4647,7 @@ func (m *MsgRestoreInterchainAccountResponse) Size() (n int) { return n } -func (m *MsgUpdateValidatorSharesExchRate) Size() (n int) { +func (m *MsgClaimUndelegatedTokens) Size() (n int) { if m == nil { return 0 } @@ -3915,12 +4657,203 @@ func (m *MsgUpdateValidatorSharesExchRate) Size() (n int) { if l > 0 { n += 1 + l + sovTx(uint64(l)) } - l = len(m.ChainId) + l = len(m.HostZoneId) if l > 0 { n += 1 + l + sovTx(uint64(l)) } - l = len(m.Valoper) - if l > 0 { + if m.Epoch != 0 { + n += 1 + sovTx(uint64(m.Epoch)) + } + l = len(m.Sender) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgClaimUndelegatedTokensResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgRebalanceValidators) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Creator) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.HostZone) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.NumRebalance != 0 { + n += 1 + sovTx(uint64(m.NumRebalance)) + } + return n +} + +func (m *MsgRebalanceValidatorsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgAddValidators) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Creator) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.HostZone) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if len(m.Validators) > 0 { + for _, e := range m.Validators { + l = e.Size() + n += 1 + l + sovTx(uint64(l)) + } + } + return n +} + +func (m *MsgAddValidatorsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgChangeValidatorWeight) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Creator) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.HostZone) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.ValAddr) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.Weight != 0 { + n += 1 + sovTx(uint64(m.Weight)) + } + return n +} + +func (m *MsgChangeValidatorWeightResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgDeleteValidator) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Creator) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.HostZone) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.ValAddr) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgDeleteValidatorResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgRestoreInterchainAccount) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Creator) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.ChainId) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.ConnectionId) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.AccountOwner) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgRestoreInterchainAccountResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgUpdateValidatorSharesExchRate) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Creator) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.ChainId) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Valoper) + if l > 0 { n += 1 + l + sovTx(uint64(l)) } return n @@ -4015,18 +4948,166 @@ func (m *MsgResumeHostZoneResponse) Size() (n int) { return n } -func sovTx(x uint64) (n int) { - return (math_bits.Len64(x|1) + 6) / 7 +func (m *MsgCreateTradeRoute) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Authority) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.HostChainId) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.StrideToRewardConnectionId) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.StrideToTradeConnectionId) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.HostToRewardTransferChannelId) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.RewardToTradeTransferChannelId) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.TradeToHostTransferChannelId) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.RewardDenomOnHost) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.RewardDenomOnReward) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.RewardDenomOnTrade) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.HostDenomOnTrade) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.HostDenomOnHost) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.PoolId != 0 { + n += 1 + sovTx(uint64(m.PoolId)) + } + l = len(m.MaxAllowedSwapLossRate) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = m.MinSwapAmount.Size() + n += 1 + l + sovTx(uint64(l)) + l = m.MaxSwapAmount.Size() + n += 2 + l + sovTx(uint64(l)) + return n } -func sozTx(x uint64) (n int) { - return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63)))) + +func (m *MsgCreateTradeRouteResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n } -func (m *MsgUpdateInnerRedemptionRateBounds) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 + +func (m *MsgDeleteTradeRoute) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Authority) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.RewardDenom) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.HostDenom) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgDeleteTradeRouteResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgUpdateTradeRoute) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Authority) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.RewardDenom) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.HostDenom) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.PoolId != 0 { + n += 1 + sovTx(uint64(m.PoolId)) + } + l = len(m.MaxAllowedSwapLossRate) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = m.MinSwapAmount.Size() + n += 1 + l + sovTx(uint64(l)) + l = m.MaxSwapAmount.Size() + n += 1 + l + sovTx(uint64(l)) + return n +} + +func (m *MsgUpdateTradeRouteResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func sovTx(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTx(x uint64) (n int) { + return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *MsgUpdateInnerRedemptionRateBounds) 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 ErrIntOverflowTx @@ -4052,7 +5133,1327 @@ func (m *MsgUpdateInnerRedemptionRateBounds) Unmarshal(dAtA []byte) error { switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Creator", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Creator", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Creator = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ChainId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MinInnerRedemptionRate", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.MinInnerRedemptionRate.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxInnerRedemptionRate", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.MaxInnerRedemptionRate.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgUpdateInnerRedemptionRateBoundsResponse) 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 ErrIntOverflowTx + } + 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: MsgUpdateInnerRedemptionRateBoundsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUpdateInnerRedemptionRateBoundsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgLiquidStake) 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 ErrIntOverflowTx + } + 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: MsgLiquidStake: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgLiquidStake: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Creator", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Creator = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field HostDenom", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.HostDenom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgLiquidStakeResponse) 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 ErrIntOverflowTx + } + 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: MsgLiquidStakeResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgLiquidStakeResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StToken", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.StToken.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgLSMLiquidStake) 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 ErrIntOverflowTx + } + 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: MsgLSMLiquidStake: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgLSMLiquidStake: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Creator", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Creator = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LsmTokenIbcDenom", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.LsmTokenIbcDenom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgLSMLiquidStakeResponse) 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 ErrIntOverflowTx + } + 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: MsgLSMLiquidStakeResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgLSMLiquidStakeResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TransactionComplete", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.TransactionComplete = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgClearBalance) 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 ErrIntOverflowTx + } + 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: MsgClearBalance: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgClearBalance: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Creator", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Creator = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ChainId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Channel", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Channel = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgClearBalanceResponse) 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 ErrIntOverflowTx + } + 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: MsgClearBalanceResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgClearBalanceResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgRedeemStake) 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 ErrIntOverflowTx + } + 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: MsgRedeemStake: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgRedeemStake: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Creator", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Creator = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field HostZone", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.HostZone = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Receiver", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Receiver = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgRedeemStakeResponse) 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 ErrIntOverflowTx + } + 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: MsgRedeemStakeResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgRedeemStakeResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgRegisterHostZone) 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 ErrIntOverflowTx + } + 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: MsgRegisterHostZone: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgRegisterHostZone: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ConnectionId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ConnectionId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field HostDenom", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.HostDenom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field IbcDenom", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.IbcDenom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Creator", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Creator = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TransferChannelId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.TransferChannelId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 11: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field UnbondingPeriod", wireType) + } + m.UnbondingPeriod = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.UnbondingPeriod |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 12: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Bech32Prefix", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -4080,11 +6481,11 @@ func (m *MsgUpdateInnerRedemptionRateBounds) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Creator = string(dAtA[iNdEx:postIndex]) + m.Bech32Prefix = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 2: + case 13: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field MinRedemptionRate", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -4112,11 +6513,13 @@ func (m *MsgUpdateInnerRedemptionRateBounds) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.ChainId = string(dAtA[iNdEx:postIndex]) + if err := m.MinRedemptionRate.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } iNdEx = postIndex - case 3: + case 14: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field MinInnerRedemptionRate", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field MaxRedemptionRate", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -4144,15 +6547,15 @@ func (m *MsgUpdateInnerRedemptionRateBounds) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.MinInnerRedemptionRate.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if err := m.MaxRedemptionRate.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field MaxInnerRedemptionRate", wireType) + case 15: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field LsmLiquidStakeEnabled", wireType) } - var stringLen uint64 + var v int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTx @@ -4162,26 +6565,12 @@ func (m *MsgUpdateInnerRedemptionRateBounds) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= uint64(b&0x7F) << shift + v |= int(b&0x7F) << shift if b < 0x80 { break } } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.MaxInnerRedemptionRate.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex + m.LsmLiquidStakeEnabled = bool(v != 0) default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:]) @@ -4203,7 +6592,7 @@ func (m *MsgUpdateInnerRedemptionRateBounds) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgUpdateInnerRedemptionRateBoundsResponse) Unmarshal(dAtA []byte) error { +func (m *MsgRegisterHostZoneResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -4226,10 +6615,10 @@ func (m *MsgUpdateInnerRedemptionRateBoundsResponse) Unmarshal(dAtA []byte) erro fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgUpdateInnerRedemptionRateBoundsResponse: wiretype end group for non-group") + return fmt.Errorf("proto: MsgRegisterHostZoneResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgUpdateInnerRedemptionRateBoundsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgRegisterHostZoneResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { default: @@ -4253,7 +6642,7 @@ func (m *MsgUpdateInnerRedemptionRateBoundsResponse) Unmarshal(dAtA []byte) erro } return nil } -func (m *MsgLiquidStake) Unmarshal(dAtA []byte) error { +func (m *MsgClaimUndelegatedTokens) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -4276,10 +6665,10 @@ func (m *MsgLiquidStake) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgLiquidStake: wiretype end group for non-group") + return fmt.Errorf("proto: MsgClaimUndelegatedTokens: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgLiquidStake: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgClaimUndelegatedTokens: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -4316,7 +6705,7 @@ func (m *MsgLiquidStake) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field HostZoneId", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -4344,13 +6733,30 @@ func (m *MsgLiquidStake) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } + m.HostZoneId = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Epoch", wireType) + } + m.Epoch = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Epoch |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field HostDenom", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Sender", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -4378,7 +6784,7 @@ func (m *MsgLiquidStake) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.HostDenom = string(dAtA[iNdEx:postIndex]) + m.Sender = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex default: iNdEx = preIndex @@ -4401,7 +6807,7 @@ func (m *MsgLiquidStake) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgLiquidStakeResponse) Unmarshal(dAtA []byte) error { +func (m *MsgClaimUndelegatedTokensResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -4424,45 +6830,12 @@ func (m *MsgLiquidStakeResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgLiquidStakeResponse: wiretype end group for non-group") + return fmt.Errorf("proto: MsgClaimUndelegatedTokensResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgLiquidStakeResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgClaimUndelegatedTokensResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field StToken", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.StToken.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:]) @@ -4484,7 +6857,7 @@ func (m *MsgLiquidStakeResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgLSMLiquidStake) Unmarshal(dAtA []byte) error { +func (m *MsgRebalanceValidators) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -4507,10 +6880,10 @@ func (m *MsgLSMLiquidStake) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgLSMLiquidStake: wiretype end group for non-group") + return fmt.Errorf("proto: MsgRebalanceValidators: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgLSMLiquidStake: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgRebalanceValidators: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -4547,7 +6920,7 @@ func (m *MsgLSMLiquidStake) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field HostZone", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -4575,15 +6948,13 @@ func (m *MsgLSMLiquidStake) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } + m.HostZone = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field LsmTokenIbcDenom", wireType) + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field NumRebalance", wireType) } - var stringLen uint64 + m.NumRebalance = 0 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTx @@ -4593,24 +6964,11 @@ func (m *MsgLSMLiquidStake) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= uint64(b&0x7F) << shift + m.NumRebalance |= uint64(b&0x7F) << shift if b < 0x80 { break } } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.LsmTokenIbcDenom = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:]) @@ -4632,7 +6990,7 @@ func (m *MsgLSMLiquidStake) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgLSMLiquidStakeResponse) Unmarshal(dAtA []byte) error { +func (m *MsgRebalanceValidatorsResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -4655,32 +7013,12 @@ func (m *MsgLSMLiquidStakeResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgLSMLiquidStakeResponse: wiretype end group for non-group") + return fmt.Errorf("proto: MsgRebalanceValidatorsResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgLSMLiquidStakeResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgRebalanceValidatorsResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { - case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field TransactionComplete", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - m.TransactionComplete = bool(v != 0) default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:]) @@ -4702,7 +7040,7 @@ func (m *MsgLSMLiquidStakeResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgClearBalance) Unmarshal(dAtA []byte) error { +func (m *MsgAddValidators) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -4725,10 +7063,10 @@ func (m *MsgClearBalance) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgClearBalance: wiretype end group for non-group") + return fmt.Errorf("proto: MsgAddValidators: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgClearBalance: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgAddValidators: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -4765,7 +7103,7 @@ func (m *MsgClearBalance) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field HostZone", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -4793,13 +7131,13 @@ func (m *MsgClearBalance) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.ChainId = string(dAtA[iNdEx:postIndex]) + m.HostZone = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 3: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Validators", wireType) } - var stringLen uint64 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTx @@ -4809,58 +7147,26 @@ func (m *MsgClearBalance) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= uint64(b&0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } } - intStringLen := int(stringLen) - if intStringLen < 0 { + if msglen < 0 { return ErrInvalidLengthTx } - postIndex := iNdEx + intStringLen + postIndex := iNdEx + msglen if postIndex < 0 { return ErrInvalidLengthTx } if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + m.Validators = append(m.Validators, &Validator{}) + if err := m.Validators[len(m.Validators)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Channel", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - 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 ErrInvalidLengthTx - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Channel = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:]) @@ -4882,7 +7188,7 @@ func (m *MsgClearBalance) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgClearBalanceResponse) Unmarshal(dAtA []byte) error { +func (m *MsgAddValidatorsResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -4905,10 +7211,10 @@ func (m *MsgClearBalanceResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgClearBalanceResponse: wiretype end group for non-group") + return fmt.Errorf("proto: MsgAddValidatorsResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgClearBalanceResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgAddValidatorsResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { default: @@ -4932,7 +7238,7 @@ func (m *MsgClearBalanceResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgRedeemStake) Unmarshal(dAtA []byte) error { +func (m *MsgChangeValidatorWeight) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -4955,10 +7261,10 @@ func (m *MsgRedeemStake) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgRedeemStake: wiretype end group for non-group") + return fmt.Errorf("proto: MsgChangeValidatorWeight: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgRedeemStake: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgChangeValidatorWeight: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -4995,7 +7301,7 @@ func (m *MsgRedeemStake) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field HostZone", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -5023,13 +7329,11 @@ func (m *MsgRedeemStake) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } + m.HostZone = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 3: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field HostZone", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ValAddr", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -5057,13 +7361,13 @@ func (m *MsgRedeemStake) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.HostZone = string(dAtA[iNdEx:postIndex]) + m.ValAddr = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Receiver", wireType) + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Weight", wireType) } - var stringLen uint64 + m.Weight = 0 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTx @@ -5073,24 +7377,11 @@ func (m *MsgRedeemStake) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= uint64(b&0x7F) << shift + m.Weight |= uint64(b&0x7F) << shift if b < 0x80 { break } } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Receiver = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:]) @@ -5112,7 +7403,7 @@ func (m *MsgRedeemStake) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgRedeemStakeResponse) Unmarshal(dAtA []byte) error { +func (m *MsgChangeValidatorWeightResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -5135,10 +7426,10 @@ func (m *MsgRedeemStakeResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgRedeemStakeResponse: wiretype end group for non-group") + return fmt.Errorf("proto: MsgChangeValidatorWeightResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgRedeemStakeResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgChangeValidatorWeightResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { default: @@ -5162,7 +7453,7 @@ func (m *MsgRedeemStakeResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgRegisterHostZone) Unmarshal(dAtA []byte) error { +func (m *MsgDeleteValidator) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -5185,15 +7476,15 @@ func (m *MsgRegisterHostZone) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgRegisterHostZone: wiretype end group for non-group") + return fmt.Errorf("proto: MsgDeleteValidator: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgRegisterHostZone: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgDeleteValidator: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { - case 2: + case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ConnectionId", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Creator", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -5221,11 +7512,11 @@ func (m *MsgRegisterHostZone) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.ConnectionId = string(dAtA[iNdEx:postIndex]) + m.Creator = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 4: + case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field HostDenom", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field HostZone", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -5253,11 +7544,11 @@ func (m *MsgRegisterHostZone) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.HostDenom = string(dAtA[iNdEx:postIndex]) + m.HostZone = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 5: + case 3: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field IbcDenom", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ValAddr", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -5285,43 +7576,111 @@ func (m *MsgRegisterHostZone) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.IbcDenom = string(dAtA[iNdEx:postIndex]) + m.ValAddr = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 6: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Creator", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err } - intStringLen := int(stringLen) - if intStringLen < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } - postIndex := iNdEx + intStringLen - if postIndex < 0 { + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgDeleteValidatorResponse) 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 ErrIntOverflowTx + } + 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: MsgDeleteValidatorResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgDeleteValidatorResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } - if postIndex > l { + if (iNdEx + skippy) > l { return io.ErrUnexpectedEOF } - m.Creator = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 10: + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgRestoreInterchainAccount) 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 ErrIntOverflowTx + } + 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: MsgRestoreInterchainAccount: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgRestoreInterchainAccount: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field TransferChannelId", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Creator", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -5349,30 +7708,11 @@ func (m *MsgRegisterHostZone) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.TransferChannelId = string(dAtA[iNdEx:postIndex]) + m.Creator = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 11: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field UnbondingPeriod", wireType) - } - m.UnbondingPeriod = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.UnbondingPeriod |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 12: + case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Bech32Prefix", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -5400,11 +7740,11 @@ func (m *MsgRegisterHostZone) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Bech32Prefix = string(dAtA[iNdEx:postIndex]) + m.ChainId = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 13: + case 3: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field MinRedemptionRate", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ConnectionId", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -5432,13 +7772,11 @@ func (m *MsgRegisterHostZone) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.MinRedemptionRate.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } + m.ConnectionId = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 14: + case 4: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field MaxRedemptionRate", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field AccountOwner", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -5466,30 +7804,8 @@ func (m *MsgRegisterHostZone) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.MaxRedemptionRate.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } + m.AccountOwner = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 15: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field LsmLiquidStakeEnabled", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - m.LsmLiquidStakeEnabled = bool(v != 0) default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:]) @@ -5511,7 +7827,7 @@ func (m *MsgRegisterHostZone) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgRegisterHostZoneResponse) Unmarshal(dAtA []byte) error { +func (m *MsgRestoreInterchainAccountResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -5534,10 +7850,10 @@ func (m *MsgRegisterHostZoneResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgRegisterHostZoneResponse: wiretype end group for non-group") + return fmt.Errorf("proto: MsgRestoreInterchainAccountResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgRegisterHostZoneResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgRestoreInterchainAccountResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { default: @@ -5561,7 +7877,7 @@ func (m *MsgRegisterHostZoneResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgClaimUndelegatedTokens) Unmarshal(dAtA []byte) error { +func (m *MsgUpdateValidatorSharesExchRate) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -5584,10 +7900,10 @@ func (m *MsgClaimUndelegatedTokens) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgClaimUndelegatedTokens: wiretype end group for non-group") + return fmt.Errorf("proto: MsgUpdateValidatorSharesExchRate: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgClaimUndelegatedTokens: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgUpdateValidatorSharesExchRate: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -5624,7 +7940,7 @@ func (m *MsgClaimUndelegatedTokens) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field HostZoneId", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -5652,30 +7968,11 @@ func (m *MsgClaimUndelegatedTokens) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.HostZoneId = string(dAtA[iNdEx:postIndex]) + m.ChainId = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Epoch", wireType) - } - m.Epoch = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Epoch |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 4: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Sender", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Valoper", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -5703,7 +8000,7 @@ func (m *MsgClaimUndelegatedTokens) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Sender = string(dAtA[iNdEx:postIndex]) + m.Valoper = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex default: iNdEx = preIndex @@ -5726,7 +8023,7 @@ func (m *MsgClaimUndelegatedTokens) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgClaimUndelegatedTokensResponse) Unmarshal(dAtA []byte) error { +func (m *MsgUpdateValidatorSharesExchRateResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -5749,10 +8046,10 @@ func (m *MsgClaimUndelegatedTokensResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgClaimUndelegatedTokensResponse: wiretype end group for non-group") + return fmt.Errorf("proto: MsgUpdateValidatorSharesExchRateResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgClaimUndelegatedTokensResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgUpdateValidatorSharesExchRateResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { default: @@ -5776,7 +8073,7 @@ func (m *MsgClaimUndelegatedTokensResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgRebalanceValidators) Unmarshal(dAtA []byte) error { +func (m *MsgUndelegateHost) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -5799,10 +8096,10 @@ func (m *MsgRebalanceValidators) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgRebalanceValidators: wiretype end group for non-group") + return fmt.Errorf("proto: MsgUndelegateHost: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgRebalanceValidators: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgUndelegateHost: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -5839,7 +8136,7 @@ func (m *MsgRebalanceValidators) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field HostZone", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -5867,27 +8164,10 @@ func (m *MsgRebalanceValidators) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.HostZone = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field NumRebalance", wireType) - } - m.NumRebalance = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.NumRebalance |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } + if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:]) @@ -5909,7 +8189,7 @@ func (m *MsgRebalanceValidators) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgRebalanceValidatorsResponse) Unmarshal(dAtA []byte) error { +func (m *MsgUndelegateHostResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -5932,10 +8212,10 @@ func (m *MsgRebalanceValidatorsResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgRebalanceValidatorsResponse: wiretype end group for non-group") + return fmt.Errorf("proto: MsgUndelegateHostResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgRebalanceValidatorsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgUndelegateHostResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { default: @@ -5959,7 +8239,7 @@ func (m *MsgRebalanceValidatorsResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgAddValidators) Unmarshal(dAtA []byte) error { +func (m *MsgCalibrateDelegation) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -5982,10 +8262,10 @@ func (m *MsgAddValidators) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgAddValidators: wiretype end group for non-group") + return fmt.Errorf("proto: MsgCalibrateDelegation: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgAddValidators: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgCalibrateDelegation: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -6022,7 +8302,7 @@ func (m *MsgAddValidators) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field HostZone", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -6050,13 +8330,13 @@ func (m *MsgAddValidators) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.HostZone = string(dAtA[iNdEx:postIndex]) + m.ChainId = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 3: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Validators", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Valoper", wireType) } - var msglen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTx @@ -6066,25 +8346,23 @@ func (m *MsgAddValidators) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= int(b&0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } } - if msglen < 0 { + intStringLen := int(stringLen) + if intStringLen < 0 { return ErrInvalidLengthTx } - postIndex := iNdEx + msglen + postIndex := iNdEx + intStringLen if postIndex < 0 { return ErrInvalidLengthTx } if postIndex > l { return io.ErrUnexpectedEOF } - m.Validators = append(m.Validators, &Validator{}) - if err := m.Validators[len(m.Validators)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } + m.Valoper = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex default: iNdEx = preIndex @@ -6107,7 +8385,7 @@ func (m *MsgAddValidators) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgAddValidatorsResponse) Unmarshal(dAtA []byte) error { +func (m *MsgCalibrateDelegationResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -6130,10 +8408,10 @@ func (m *MsgAddValidatorsResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgAddValidatorsResponse: wiretype end group for non-group") + return fmt.Errorf("proto: MsgCalibrateDelegationResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgAddValidatorsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgCalibrateDelegationResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { default: @@ -6157,7 +8435,7 @@ func (m *MsgAddValidatorsResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgChangeValidatorWeight) Unmarshal(dAtA []byte) error { +func (m *MsgResumeHostZone) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -6180,10 +8458,10 @@ func (m *MsgChangeValidatorWeight) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgChangeValidatorWeight: wiretype end group for non-group") + return fmt.Errorf("proto: MsgResumeHostZone: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgChangeValidatorWeight: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgResumeHostZone: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -6220,39 +8498,7 @@ func (m *MsgChangeValidatorWeight) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field HostZone", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - 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 ErrInvalidLengthTx - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.HostZone = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ValAddr", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -6280,27 +8526,8 @@ func (m *MsgChangeValidatorWeight) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.ValAddr = string(dAtA[iNdEx:postIndex]) + m.ChainId = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 4: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Weight", wireType) - } - m.Weight = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Weight |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:]) @@ -6322,7 +8549,7 @@ func (m *MsgChangeValidatorWeight) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgChangeValidatorWeightResponse) Unmarshal(dAtA []byte) error { +func (m *MsgResumeHostZoneResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -6345,10 +8572,10 @@ func (m *MsgChangeValidatorWeightResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgChangeValidatorWeightResponse: wiretype end group for non-group") + return fmt.Errorf("proto: MsgResumeHostZoneResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgChangeValidatorWeightResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgResumeHostZoneResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { default: @@ -6372,7 +8599,7 @@ func (m *MsgChangeValidatorWeightResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgDeleteValidator) Unmarshal(dAtA []byte) error { +func (m *MsgCreateTradeRoute) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -6395,15 +8622,111 @@ func (m *MsgDeleteValidator) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgDeleteValidator: wiretype end group for non-group") + return fmt.Errorf("proto: MsgCreateTradeRoute: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgDeleteValidator: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgCreateTradeRoute: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Creator", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Authority", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Authority = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field HostChainId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.HostChainId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StrideToRewardConnectionId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.StrideToRewardConnectionId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StrideToTradeConnectionId", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -6431,11 +8754,11 @@ func (m *MsgDeleteValidator) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Creator = string(dAtA[iNdEx:postIndex]) + m.StrideToTradeConnectionId = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 2: + case 5: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field HostZone", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field HostToRewardTransferChannelId", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -6463,11 +8786,11 @@ func (m *MsgDeleteValidator) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.HostZone = string(dAtA[iNdEx:postIndex]) + m.HostToRewardTransferChannelId = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 3: + case 6: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ValAddr", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field RewardToTradeTransferChannelId", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -6495,111 +8818,43 @@ func (m *MsgDeleteValidator) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.ValAddr = string(dAtA[iNdEx:postIndex]) + m.RewardToTradeTransferChannelId = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipTx(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *MsgDeleteValidatorResponse) 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 ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TradeToHostTransferChannelId", wireType) } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: MsgDeleteValidatorResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgDeleteValidatorResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - default: - iNdEx = preIndex - skippy, err := skipTx(dAtA[iNdEx:]) - if err != nil { - return err + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } } - if (skippy < 0) || (iNdEx+skippy) < 0 { + intStringLen := int(stringLen) + if intStringLen < 0 { return ErrInvalidLengthTx } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *MsgRestoreInterchainAccount) 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 ErrIntOverflowTx + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx } - if iNdEx >= l { + if postIndex > 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: MsgRestoreInterchainAccount: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgRestoreInterchainAccount: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: + m.TradeToHostTransferChannelId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 8: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Creator", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field RewardDenomOnHost", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -6627,11 +8882,11 @@ func (m *MsgRestoreInterchainAccount) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Creator = string(dAtA[iNdEx:postIndex]) + m.RewardDenomOnHost = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 2: + case 9: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field RewardDenomOnReward", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -6659,13 +8914,13 @@ func (m *MsgRestoreInterchainAccount) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.ChainId = string(dAtA[iNdEx:postIndex]) + m.RewardDenomOnReward = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field AccountType", wireType) + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RewardDenomOnTrade", wireType) } - m.AccountType = 0 + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTx @@ -6675,114 +8930,110 @@ func (m *MsgRestoreInterchainAccount) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.AccountType |= ICAAccountType(b&0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } } - default: - iNdEx = preIndex - skippy, err := skipTx(dAtA[iNdEx:]) - if err != nil { - return err + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx } - if (skippy < 0) || (iNdEx+skippy) < 0 { + postIndex := iNdEx + intStringLen + if postIndex < 0 { return ErrInvalidLengthTx } - if (iNdEx + skippy) > l { + if postIndex > l { return io.ErrUnexpectedEOF } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *MsgRestoreInterchainAccountResponse) 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 ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF + m.RewardDenomOnTrade = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field HostDenomOnTrade", wireType) } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: MsgRestoreInterchainAccountResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgRestoreInterchainAccountResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - default: - iNdEx = preIndex - skippy, err := skipTx(dAtA[iNdEx:]) - if err != nil { - return err + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx } - if (skippy < 0) || (iNdEx+skippy) < 0 { + postIndex := iNdEx + intStringLen + if postIndex < 0 { return ErrInvalidLengthTx } - if (iNdEx + skippy) > l { + if postIndex > l { return io.ErrUnexpectedEOF } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *MsgUpdateValidatorSharesExchRate) 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 ErrIntOverflowTx + m.HostDenomOnTrade = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 12: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field HostDenomOnHost", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } } - if iNdEx >= l { + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { return io.ErrUnexpectedEOF } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break + m.HostDenomOnHost = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 13: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PoolId", wireType) } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: MsgUpdateValidatorSharesExchRate: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgUpdateValidatorSharesExchRate: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: + m.PoolId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PoolId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 14: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Creator", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field MaxAllowedSwapLossRate", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -6810,11 +9061,11 @@ func (m *MsgUpdateValidatorSharesExchRate) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Creator = string(dAtA[iNdEx:postIndex]) + m.MaxAllowedSwapLossRate = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 2: + case 15: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field MinSwapAmount", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -6842,11 +9093,13 @@ func (m *MsgUpdateValidatorSharesExchRate) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.ChainId = string(dAtA[iNdEx:postIndex]) + if err := m.MinSwapAmount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } iNdEx = postIndex - case 3: + case 16: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Valoper", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field MaxSwapAmount", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -6874,7 +9127,9 @@ func (m *MsgUpdateValidatorSharesExchRate) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Valoper = string(dAtA[iNdEx:postIndex]) + if err := m.MaxSwapAmount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } iNdEx = postIndex default: iNdEx = preIndex @@ -6897,7 +9152,7 @@ func (m *MsgUpdateValidatorSharesExchRate) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgUpdateValidatorSharesExchRateResponse) Unmarshal(dAtA []byte) error { +func (m *MsgCreateTradeRouteResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -6920,10 +9175,10 @@ func (m *MsgUpdateValidatorSharesExchRateResponse) Unmarshal(dAtA []byte) error fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgUpdateValidatorSharesExchRateResponse: wiretype end group for non-group") + return fmt.Errorf("proto: MsgCreateTradeRouteResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgUpdateValidatorSharesExchRateResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgCreateTradeRouteResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { default: @@ -6947,7 +9202,7 @@ func (m *MsgUpdateValidatorSharesExchRateResponse) Unmarshal(dAtA []byte) error } return nil } -func (m *MsgUndelegateHost) Unmarshal(dAtA []byte) error { +func (m *MsgDeleteTradeRoute) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -6970,15 +9225,15 @@ func (m *MsgUndelegateHost) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgUndelegateHost: wiretype end group for non-group") + return fmt.Errorf("proto: MsgDeleteTradeRoute: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgUndelegateHost: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgDeleteTradeRoute: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Creator", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Authority", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -7006,11 +9261,11 @@ func (m *MsgUndelegateHost) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Creator = string(dAtA[iNdEx:postIndex]) + m.Authority = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field RewardDenom", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -7038,9 +9293,39 @@ func (m *MsgUndelegateHost) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err + m.RewardDenom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field HostDenom", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.HostDenom = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex default: iNdEx = preIndex @@ -7063,7 +9348,7 @@ func (m *MsgUndelegateHost) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgUndelegateHostResponse) Unmarshal(dAtA []byte) error { +func (m *MsgDeleteTradeRouteResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -7086,10 +9371,10 @@ func (m *MsgUndelegateHostResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgUndelegateHostResponse: wiretype end group for non-group") + return fmt.Errorf("proto: MsgDeleteTradeRouteResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgUndelegateHostResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgDeleteTradeRouteResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { default: @@ -7113,7 +9398,7 @@ func (m *MsgUndelegateHostResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgCalibrateDelegation) Unmarshal(dAtA []byte) error { +func (m *MsgUpdateTradeRoute) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -7136,15 +9421,15 @@ func (m *MsgCalibrateDelegation) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgCalibrateDelegation: wiretype end group for non-group") + return fmt.Errorf("proto: MsgUpdateTradeRoute: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgCalibrateDelegation: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgUpdateTradeRoute: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Creator", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Authority", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -7172,11 +9457,11 @@ func (m *MsgCalibrateDelegation) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Creator = string(dAtA[iNdEx:postIndex]) + m.Authority = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field RewardDenom", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -7204,11 +9489,11 @@ func (m *MsgCalibrateDelegation) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.ChainId = string(dAtA[iNdEx:postIndex]) + m.RewardDenom = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 3: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Valoper", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field HostDenom", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -7236,111 +9521,62 @@ func (m *MsgCalibrateDelegation) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Valoper = string(dAtA[iNdEx:postIndex]) + m.HostDenom = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipTx(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *MsgCalibrateDelegationResponse) 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 ErrIntOverflowTx + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PoolId", wireType) } - if iNdEx >= l { - return io.ErrUnexpectedEOF + m.PoolId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PoolId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxAllowedSwapLossRate", wireType) } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: MsgCalibrateDelegationResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgCalibrateDelegationResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - default: - iNdEx = preIndex - skippy, err := skipTx(dAtA[iNdEx:]) - if err != nil { - return err + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } } - if (skippy < 0) || (iNdEx+skippy) < 0 { + intStringLen := int(stringLen) + if intStringLen < 0 { return ErrInvalidLengthTx } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *MsgResumeHostZone) 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 ErrIntOverflowTx + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx } - if iNdEx >= l { + if postIndex > 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: MsgResumeHostZone: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgResumeHostZone: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: + m.MaxAllowedSwapLossRate = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 6: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Creator", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field MinSwapAmount", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -7368,11 +9604,13 @@ func (m *MsgResumeHostZone) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Creator = string(dAtA[iNdEx:postIndex]) + if err := m.MinSwapAmount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } iNdEx = postIndex - case 2: + case 7: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field MaxSwapAmount", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -7400,7 +9638,9 @@ func (m *MsgResumeHostZone) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.ChainId = string(dAtA[iNdEx:postIndex]) + if err := m.MaxSwapAmount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } iNdEx = postIndex default: iNdEx = preIndex @@ -7423,7 +9663,7 @@ func (m *MsgResumeHostZone) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgResumeHostZoneResponse) Unmarshal(dAtA []byte) error { +func (m *MsgUpdateTradeRouteResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -7446,10 +9686,10 @@ func (m *MsgResumeHostZoneResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgResumeHostZoneResponse: wiretype end group for non-group") + return fmt.Errorf("proto: MsgUpdateTradeRouteResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgResumeHostZoneResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgUpdateTradeRouteResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { default: