diff --git a/app/ante.go b/app/ante.go new file mode 100644 index 00000000000..5cffbe9b377 --- /dev/null +++ b/app/ante.go @@ -0,0 +1,40 @@ +package app + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth/signing" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + + ante "github.com/cosmos/cosmos-sdk/x/auth/ante" + + txfeeskeeper "github.com/osmosis-labs/osmosis/x/txfees/keeper" + txfeestypes "github.com/osmosis-labs/osmosis/x/txfees/types" +) + +// Link to default ante handler used by cosmos sdk: +// https://github.com/cosmos/cosmos-sdk/blob/v0.43.0/x/auth/ante/ante.go#L41 +func NewAnteHandler( + ak ante.AccountKeeper, bankKeeper authtypes.BankKeeper, + txFeesKeeper txfeeskeeper.Keeper, spotPriceCalculator txfeestypes.SpotPriceCalculator, + sigGasConsumer ante.SignatureVerificationGasConsumer, + signModeHandler signing.SignModeHandler, +) sdk.AnteHandler { + return sdk.ChainAnteDecorators( + ante.NewSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first + ante.NewRejectExtensionOptionsDecorator(), + // Use Mempool Fee Decorator from our txfees module instead of default one from auth + // https://github.com/cosmos/cosmos-sdk/blob/master/x/auth/middleware/fee.go#L34 + txfeeskeeper.NewMempoolFeeDecorator(txFeesKeeper), + ante.NewValidateBasicDecorator(), + ante.TxTimeoutHeightDecorator{}, + ante.NewValidateMemoDecorator(ak), + ante.NewConsumeGasForTxSizeDecorator(ak), + ante.NewRejectFeeGranterDecorator(), + ante.NewSetPubKeyDecorator(ak), // SetPubKeyDecorator must be called before all signature verification decorators + ante.NewValidateSigCountDecorator(ak), + ante.NewDeductFeeDecorator(ak, bankKeeper), + ante.NewSigGasConsumeDecorator(ak, sigGasConsumer), + ante.NewSigVerificationDecorator(ak, signModeHandler), + ante.NewIncrementSequenceDecorator(ak), + ) +} diff --git a/app/app.go b/app/app.go index 50732fdb6de..14935fe4259 100644 --- a/app/app.go +++ b/app/app.go @@ -108,6 +108,9 @@ import ( poolincentivesclient "github.com/osmosis-labs/osmosis/x/pool-incentives/client" poolincentiveskeeper "github.com/osmosis-labs/osmosis/x/pool-incentives/keeper" poolincentivestypes "github.com/osmosis-labs/osmosis/x/pool-incentives/types" + "github.com/osmosis-labs/osmosis/x/txfees" + txfeeskeeper "github.com/osmosis-labs/osmosis/x/txfees/keeper" + txfeestypes "github.com/osmosis-labs/osmosis/x/txfees/types" ) const appName = "OsmosisApp" @@ -140,6 +143,7 @@ var ( transfer.AppModuleBasic{}, vesting.AppModuleBasic{}, gamm.AppModuleBasic{}, + txfees.AppModuleBasic{}, incentives.AppModuleBasic{}, lockup.AppModuleBasic{}, poolincentives.AppModuleBasic{}, @@ -162,6 +166,7 @@ var ( incentivestypes.ModuleName: {authtypes.Minter, authtypes.Burner}, lockuptypes.ModuleName: {authtypes.Minter, authtypes.Burner}, poolincentivestypes.ModuleName: nil, + txfeestypes.ModuleName: nil, } // module accounts that are allowed to receive tokens @@ -209,6 +214,7 @@ type OsmosisApp struct { LockupKeeper lockupkeeper.Keeper EpochsKeeper epochskeeper.Keeper PoolIncentivesKeeper poolincentiveskeeper.Keeper + TxFeesKeeper txfeeskeeper.Keeper // make scoped keepers public for test purposes ScopedIBCKeeper capabilitykeeper.ScopedKeeper @@ -251,7 +257,7 @@ func NewOsmosisApp( govtypes.StoreKey, paramstypes.StoreKey, ibchost.StoreKey, upgradetypes.StoreKey, evidencetypes.StoreKey, ibctransfertypes.StoreKey, capabilitytypes.StoreKey, gammtypes.StoreKey, lockuptypes.StoreKey, claimtypes.StoreKey, incentivestypes.StoreKey, - epochstypes.StoreKey, poolincentivestypes.StoreKey, + epochstypes.StoreKey, poolincentivestypes.StoreKey, txfeestypes.StoreKey, ) tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey) memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey) @@ -407,6 +413,12 @@ func NewOsmosisApp( ), ) + app.TxFeesKeeper = txfeeskeeper.NewKeeper( + appCodec, + keys[txfeestypes.StoreKey], + app.GAMMKeeper, + ) + app.LockupKeeper = *lockupKeeper.SetHooks( lockuptypes.NewMultiLockupHooks( // insert lockup hooks receivers here @@ -471,6 +483,7 @@ func NewOsmosisApp( transferModule, claim.NewAppModule(appCodec, *app.ClaimKeeper), gamm.NewAppModule(appCodec, app.GAMMKeeper, app.AccountKeeper, app.BankKeeper), + txfees.NewAppModule(appCodec, app.TxFeesKeeper), incentives.NewAppModule(appCodec, app.IncentivesKeeper, app.AccountKeeper, app.BankKeeper, app.EpochsKeeper), lockup.NewAppModule(appCodec, app.LockupKeeper, app.AccountKeeper, app.BankKeeper), poolincentives.NewAppModule(appCodec, app.PoolIncentivesKeeper), @@ -502,13 +515,15 @@ func NewOsmosisApp( app.mm.SetOrderInitGenesis( capabilitytypes.ModuleName, authtypes.ModuleName, banktypes.ModuleName, distrtypes.ModuleName, stakingtypes.ModuleName, slashingtypes.ModuleName, govtypes.ModuleName, minttypes.ModuleName, crisistypes.ModuleName, - ibchost.ModuleName, genutiltypes.ModuleName, evidencetypes.ModuleName, ibctransfertypes.ModuleName, + ibchost.ModuleName, + gammtypes.ModuleName, + txfeestypes.ModuleName, + genutiltypes.ModuleName, evidencetypes.ModuleName, ibctransfertypes.ModuleName, poolincentivestypes.ModuleName, claimtypes.ModuleName, incentivestypes.ModuleName, epochstypes.ModuleName, lockuptypes.ModuleName, - gammtypes.ModuleName, ) app.mm.RegisterInvariants(&app.CrisisKeeper) @@ -523,6 +538,8 @@ func NewOsmosisApp( auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts), bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper), capability.NewAppModule(appCodec, *app.CapabilityKeeper), + gamm.NewAppModule(appCodec, app.GAMMKeeper, app.AccountKeeper, app.BankKeeper), + txfees.NewAppModule(appCodec, app.TxFeesKeeper), gov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper), mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper), slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper), @@ -531,7 +548,6 @@ func NewOsmosisApp( params.NewAppModule(app.ParamsKeeper), evidence.NewAppModule(app.EvidenceKeeper), ibc.NewAppModule(app.IBCKeeper), - gamm.NewAppModule(appCodec, app.GAMMKeeper, app.AccountKeeper, app.BankKeeper), incentives.NewAppModule(appCodec, app.IncentivesKeeper, app.AccountKeeper, app.BankKeeper, app.EpochsKeeper), lockup.NewAppModule(appCodec, app.LockupKeeper, app.AccountKeeper, app.BankKeeper), poolincentives.NewAppModule(appCodec, app.PoolIncentivesKeeper), @@ -553,8 +569,10 @@ func NewOsmosisApp( app.SetInitChainer(app.InitChainer) app.SetBeginBlocker(app.BeginBlocker) app.SetAnteHandler( - ante.NewAnteHandler( - app.AccountKeeper, app.BankKeeper, ante.DefaultSigVerificationGasConsumer, + NewAnteHandler( + app.AccountKeeper, app.BankKeeper, + app.TxFeesKeeper, app.GAMMKeeper, + ante.DefaultSigVerificationGasConsumer, encodingConfig.TxConfig.SignModeHandler(), ), ) diff --git a/app/params/config.go b/app/params/config.go index 218262c5b0f..4da8d9c6d22 100644 --- a/app/params/config.go +++ b/app/params/config.go @@ -11,6 +11,8 @@ const ( BaseCoinUnit = "uosmo" OsmoExponent = 6 + DefaultBondDenom = BaseCoinUnit + // Bech32PrefixAccAddr defines the Bech32 prefix of an account's address Bech32PrefixAccAddr = "osmo" ) diff --git a/go.mod b/go.mod index 57256fc32bf..43e213a32c2 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/osmosis-labs/osmosis go 1.17 require ( - github.com/cosmos/cosmos-sdk v0.42.9 + github.com/cosmos/cosmos-sdk v0.44.3 github.com/cosmos/go-bip39 v1.0.0 github.com/cosmos/iavl v0.16.0 github.com/gogo/protobuf v1.3.3 @@ -110,7 +110,7 @@ require ( ) replace ( - github.com/cosmos/cosmos-sdk => github.com/osmosis-labs/cosmos-sdk v0.42.10-0.20211008194120-d0e63ff7691b + github.com/cosmos/cosmos-sdk => github.com/osmosis-labs/cosmos-sdk v0.42.10-0.20211028213231-ce6f14aaa6a0 github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 github.com/tendermint/tendermint => github.com/tendermint/tendermint v0.34.14 github.com/tendermint/tm-db => github.com/osmosis-labs/tm-db v0.6.5-0.20210911033928-ba9154613417 diff --git a/go.sum b/go.sum index 71798b42174..46a263d5ba5 100644 --- a/go.sum +++ b/go.sum @@ -438,8 +438,8 @@ github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnh github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA= github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs= -github.com/osmosis-labs/cosmos-sdk v0.42.10-0.20211008194120-d0e63ff7691b h1:kt2khOeVohgBMYoSq1ZCjkzQXstQMH2Fsdn+3zaDHNs= -github.com/osmosis-labs/cosmos-sdk v0.42.10-0.20211008194120-d0e63ff7691b/go.mod h1:QByRyM6mubdL7o30ZuJTFWT2cwjmT+GT19XSYwyS7pc= +github.com/osmosis-labs/cosmos-sdk v0.42.10-0.20211028213231-ce6f14aaa6a0 h1:HgMEtjIjywY20h8F2EBrfEXeZkbb9jstPYhjYunOdxc= +github.com/osmosis-labs/cosmos-sdk v0.42.10-0.20211028213231-ce6f14aaa6a0/go.mod h1:QByRyM6mubdL7o30ZuJTFWT2cwjmT+GT19XSYwyS7pc= github.com/osmosis-labs/tm-db v0.6.5-0.20210911033928-ba9154613417 h1:otchJDd2SjFWfs7Tse3ULblGcVWqMJ50BE02XCaqXOo= github.com/osmosis-labs/tm-db v0.6.5-0.20210911033928-ba9154613417/go.mod h1:dptYhIpJ2M5kUuenLr+Yyf3zQOv1SgBZcl8/BmWlMBw= github.com/otiai10/copy v1.6.0 h1:IinKAryFFuPONZ7cm6T6E2QX/vcJwSnlaA5lfoaXIiQ= diff --git a/proto/osmosis/txfees/v1beta1/feetoken.proto b/proto/osmosis/txfees/v1beta1/feetoken.proto new file mode 100644 index 00000000000..e701933344f --- /dev/null +++ b/proto/osmosis/txfees/v1beta1/feetoken.proto @@ -0,0 +1,17 @@ +syntax = "proto3"; +package osmosis.txfees.v1beta1; + +import "gogoproto/gogo.proto"; + +option go_package = "github.com/osmosis-labs/osmosis/x/txfees/types"; + +// FeeToken is a struct that specifies a coin denom, and pool ID pair. +// This marks the token as eligible for use as a tx fee asset in Osmosis. +// Its price in osmo is derived through looking at the provided pool ID. +// The pool ID must have osmo as one of its assets. +message FeeToken { + option (gogoproto.equal) = true; + + string denom = 1 [ (gogoproto.moretags) = "yaml:\"denom\"" ]; + uint64 poolID = 2 [ (gogoproto.moretags) = "yaml:\"pool_id\"" ]; +} \ No newline at end of file diff --git a/proto/osmosis/txfees/v1beta1/genesis.proto b/proto/osmosis/txfees/v1beta1/genesis.proto new file mode 100644 index 00000000000..40be01f9f5a --- /dev/null +++ b/proto/osmosis/txfees/v1beta1/genesis.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; +package osmosis.txfees.v1beta1; + +import "gogoproto/gogo.proto"; +import "osmosis/txfees/v1beta1/feetoken.proto"; + +option go_package = "github.com/osmosis-labs/osmosis/x/txfees/types"; + +// GenesisState defines the txfees module's genesis state. +message GenesisState { + string basedenom = 1; + repeated FeeToken feetokens = 2 [ (gogoproto.nullable) = false ]; +} diff --git a/proto/osmosis/txfees/v1beta1/gov.proto b/proto/osmosis/txfees/v1beta1/gov.proto new file mode 100644 index 00000000000..06003db8dce --- /dev/null +++ b/proto/osmosis/txfees/v1beta1/gov.proto @@ -0,0 +1,25 @@ +syntax = "proto3"; +package osmosis.txfees.v1beta1; + +import "gogoproto/gogo.proto"; +import "osmosis/txfees/v1beta1/feetoken.proto"; + +option go_package = "github.com/osmosis-labs/osmosis/x/txfees/types"; + +// UpdateFeeTokenProposal is a gov Content type for adding a new whitelisted fee +// token. It must specify a denom along with gamm pool ID to use as a spot price +// calculator. It can be used to add a new denom to the whitelist It can also be +// used to update the Pool to associate with the denom. If Pool ID is set to 0, +// it will remove the denom from the whitelisted set. +message UpdateFeeTokenProposal { + option (gogoproto.equal) = true; + option (gogoproto.goproto_getters) = false; + option (gogoproto.goproto_stringer) = false; + + string title = 1 [ (gogoproto.moretags) = "yaml:\"title\"" ]; + string description = 2 [ (gogoproto.moretags) = "yaml:\"description\"" ]; + FeeToken feetoken = 3 [ + (gogoproto.moretags) = "yaml:\"fee_token\"", + (gogoproto.nullable) = false + ]; +} \ No newline at end of file diff --git a/proto/osmosis/txfees/v1beta1/query.proto b/proto/osmosis/txfees/v1beta1/query.proto new file mode 100644 index 00000000000..042f42be2e1 --- /dev/null +++ b/proto/osmosis/txfees/v1beta1/query.proto @@ -0,0 +1,49 @@ +syntax = "proto3"; +package osmosis.txfees.v1beta1; + +import "gogoproto/gogo.proto"; +import "google/api/annotations.proto"; +import "google/protobuf/duration.proto"; + +import "osmosis/txfees/v1beta1/feetoken.proto"; + +option go_package = "github.com/osmosis-labs/osmosis/x/txfees/types"; + +service Query { + // FeeTokens returns a list of all the whitelisted fee tokens and their + // corresponding pools It does not include the BaseDenom, which has its own + // query endpoint + rpc FeeTokens(QueryFeeTokensRequest) returns (QueryFeeTokensResponse) { + option (google.api.http).get = "/osmosis/txfees/v1beta1/fee_tokens"; + } + + rpc DenomPoolId(QueryDenomPoolIdRequest) returns (QueryDenomPoolIdResponse) { + option (google.api.http).get = + "/osmosis/txfees/v1beta1/denom_pool_id/{denom}"; + } + + rpc BaseDenom(QueryBaseDenomRequest) returns (QueryBaseDenomResponse) { + option (google.api.http).get = "/osmosis/txfees/v1beta1/base_denom"; + } +} + +message QueryFeeTokensRequest {} +message QueryFeeTokensResponse { + + repeated FeeToken fee_tokens = 1 [ + (gogoproto.moretags) = "yaml:\"fee_tokens\"", + (gogoproto.nullable) = false + ]; +} + +message QueryDenomPoolIdRequest { + string denom = 1 [ (gogoproto.moretags) = "yaml:\"denom\"" ]; +} +message QueryDenomPoolIdResponse { + uint64 poolID = 1 [ (gogoproto.moretags) = "yaml:\"pool_id\"" ]; +} + +message QueryBaseDenomRequest {} +message QueryBaseDenomResponse { + string base_denom = 1 [ (gogoproto.moretags) = "yaml:\"base_denom\"" ]; +} diff --git a/x/mint/keeper/keeper.go b/x/mint/keeper/keeper.go index ac16dcb5a03..f6acd98aa91 100644 --- a/x/mint/keeper/keeper.go +++ b/x/mint/keeper/keeper.go @@ -55,6 +55,7 @@ func NewKeeper( func (k Keeper) CreateDeveloperVestingModuleAccount(ctx sdk.Context, amount sdk.Coin) { moduleAcc := authtypes.NewEmptyModuleAccount( types.DeveloperVestingModuleAcctName, authtypes.Minter) + k.accountKeeper.SetModuleAccount(ctx, moduleAcc) err := k.bankKeeper.MintCoins(ctx, types.DeveloperVestingModuleAcctName, sdk.NewCoins(amount)) diff --git a/x/simulation/mod.go b/x/simulation/mod.go index 9e2b8a2b109..794ce118f07 100644 --- a/x/simulation/mod.go +++ b/x/simulation/mod.go @@ -54,6 +54,9 @@ func GenAndDeliverTxWithRandFees( return simtypes.NoOpMsg(moduleName, msg.Type(), "message doesn't leave room for fees"), nil, err } + // Only allow fees in "uosmo" + coins = sdk.NewCoins(sdk.NewCoin("uosmo", coins.AmountOf("uosmo"))) + fees, err = simtypes.RandomFees(r, ctx, coins) if err != nil { return simtypes.NoOpMsg(moduleName, msg.Type(), "unable to generate fees"), nil, err diff --git a/x/txfees/README.md b/x/txfees/README.md new file mode 100644 index 00000000000..3b4559ee0b2 --- /dev/null +++ b/x/txfees/README.md @@ -0,0 +1,3 @@ +# Txfees + +This module allows validators to define their min gas price is a single "base denom", but then allows users to define their tx fees in any whitelisted fee token. It does this by converting the whitelisted fee token to its equivalent value in base denom fee, using a "Spot Price calculator" (such as the gamm keeper). \ No newline at end of file diff --git a/x/txfees/client/cli/query.go b/x/txfees/client/cli/query.go new file mode 100644 index 00000000000..b7a5fe85fd5 --- /dev/null +++ b/x/txfees/client/cli/query.go @@ -0,0 +1,142 @@ +package cli + +import ( + "fmt" + "strings" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/version" + "github.com/osmosis-labs/osmosis/x/txfees/types" + "github.com/spf13/cobra" +) + +// GetQueryCmd returns the cli query commands for this module +func GetQueryCmd(queryRoute string) *cobra.Command { + // Group queries under a subcommand + cmd := &cobra.Command{ + Use: types.ModuleName, + Short: fmt.Sprintf("Querying commands for the %s module", types.ModuleName), + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + cmd.AddCommand( + GetCmdFeeTokens(), + GetCmdDenomPoolID(), + GetCmdBaseDenom(), + ) + + return cmd +} + +// GetCmdFeeTokens takes the pool id and returns the matching gauge ids and durations +func GetCmdFeeTokens() *cobra.Command { + cmd := &cobra.Command{ + Use: "fee-tokens", + Short: "Query the list of non-basedenom fee tokens and their associated pool ids", + Long: strings.TrimSpace( + fmt.Sprintf(`Query the list of non-basedenom fee tokens and their associated pool ids + +Example: +$ %s query txfees fee-tokens +`, + version.AppName, + ), + ), + Args: cobra.ExactArgs(0), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + res, err := queryClient.FeeTokens(cmd.Context(), &types.QueryFeeTokensRequest{}) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} + +// GetCmdDenomPoolID takes the pool id and returns the matching gauge ids and durations +func GetCmdDenomPoolID() *cobra.Command { + cmd := &cobra.Command{ + Use: "denom-pool-id", + Short: "Query the pool id associated with a specific whitelisted fee token", + Long: strings.TrimSpace( + fmt.Sprintf(`Query the pool id associated with a specific fee token + +Example: +$ %s query txfees denom-pool-id [denom] +`, + version.AppName, + ), + ), + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + res, err := queryClient.DenomPoolId(cmd.Context(), &types.QueryDenomPoolIdRequest{ + Denom: args[0], + }) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} + +// GetCmdBaseDenom takes the pool id and returns the matching gauge ids and weights +func GetCmdBaseDenom() *cobra.Command { + cmd := &cobra.Command{ + Use: "base-denom", + Short: "Query the base fee denom", + Long: strings.TrimSpace( + fmt.Sprintf(`Query the base fee denom. + +Example: +$ %s query txfees base-denom +`, + version.AppName, + ), + ), + Args: cobra.ExactArgs(0), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + res, err := queryClient.BaseDenom(cmd.Context(), &types.QueryBaseDenomRequest{}) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} diff --git a/x/txfees/client/cli/tx.go b/x/txfees/client/cli/tx.go new file mode 100644 index 00000000000..d63ea0e2bc9 --- /dev/null +++ b/x/txfees/client/cli/tx.go @@ -0,0 +1,99 @@ +package cli + +import ( + "strconv" + + "github.com/cosmos/cosmos-sdk/client/tx" + + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/gov/client/cli" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + + "github.com/osmosis-labs/osmosis/x/txfees/types" +) + +func NewTxCmd() *cobra.Command { + txCmd := &cobra.Command{ + Use: types.ModuleName, + Short: "txfees transaction subcommands", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + txCmd.AddCommand( + NewCmdSubmitUpdateFeeTokenProposal(), + ) + + return txCmd +} + +func NewCmdSubmitUpdateFeeTokenProposal() *cobra.Command { + cmd := &cobra.Command{ + Use: "update-fee-token [denom] [poolId]", + Args: cobra.ExactArgs(2), + Short: "Submit an update to a fee token to be usable for tx fees", + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + denom := args[0] + pool_id, err := strconv.ParseUint(args[1], 10, 64) + if err != nil { + return err + } + + feeToken := types.FeeToken{ + Denom: denom, + PoolID: pool_id, + } + + title, err := cmd.Flags().GetString(cli.FlagTitle) + if err != nil { + return err + } + + description, err := cmd.Flags().GetString(cli.FlagDescription) + if err != nil { + return err + } + + from := clientCtx.GetFromAddress() + + depositStr, err := cmd.Flags().GetString(cli.FlagDeposit) + if err != nil { + return err + } + deposit, err := sdk.ParseCoinsNormalized(depositStr) + if err != nil { + return err + } + + content := types.NewUpdateFeeTokenProposal(title, description, feeToken) + + msg, err := govtypes.NewMsgSubmitProposal(&content, deposit, from) + if err != nil { + return err + } + + if err = msg.ValidateBasic(); err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + cmd.Flags().String(cli.FlagTitle, "", "title of proposal") + cmd.Flags().String(cli.FlagDescription, "", "description of proposal") + cmd.Flags().String(cli.FlagDeposit, "", "deposit of proposal") + _ = cmd.MarkFlagRequired(cli.FlagTitle) + _ = cmd.MarkFlagRequired(cli.FlagDescription) + + return cmd +} diff --git a/x/txfees/genesis.go b/x/txfees/genesis.go new file mode 100644 index 00000000000..235d8d01749 --- /dev/null +++ b/x/txfees/genesis.go @@ -0,0 +1,28 @@ +package txfees + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/osmosis-labs/osmosis/x/txfees/keeper" + "github.com/osmosis-labs/osmosis/x/txfees/types" +) + +// InitGenesis initializes the txfees module's state from a provided genesis +// state. +func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState) { + err := k.SetBaseDenom(ctx, genState.Basedenom) + if err != nil { + panic(err) + } + err = k.SetFeeTokens(ctx, genState.Feetokens) + if err != nil { + panic(err) + } +} + +// ExportGenesis returns the txfees module's exported genesis. +func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState { + genesis := types.DefaultGenesis() + genesis.Basedenom, _ = k.GetBaseDenom(ctx) + genesis.Feetokens = k.GetFeeTokens(ctx) + return genesis +} diff --git a/x/txfees/keeper/feedecorator.go b/x/txfees/keeper/feedecorator.go new file mode 100644 index 00000000000..c23bf3971bb --- /dev/null +++ b/x/txfees/keeper/feedecorator.go @@ -0,0 +1,98 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + + "github.com/osmosis-labs/osmosis/x/txfees/types" +) + +// MempoolFeeDecorator will check if the transaction's fee is at least as large +// as the local validator's minimum gasFee (defined in validator config). +// If fee is too low, decorator returns error and tx is rejected from mempool. +// Note this only applies when ctx.CheckTx = true +// If fee is high enough or not CheckTx, then call next AnteHandler +// CONTRACT: Tx must implement FeeTx to use MempoolFeeDecorator +type MempoolFeeDecorator struct { + TxFeesKeeper Keeper +} + +func NewMempoolFeeDecorator(txFeesKeeper Keeper) MempoolFeeDecorator { + return MempoolFeeDecorator{ + TxFeesKeeper: txFeesKeeper, + } +} + +func (mfd MempoolFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) { + // The SDK currently requires all txs to be FeeTx's in CheckTx, within its mempool fee decorator. + // See: https://github.com/cosmos/cosmos-sdk/blob/f726a2398a26bdaf71d78dbf56a82621e84fd098/x/auth/middleware/fee.go#L34-L37 + // So this is not a real restriction at the moment. + feeTx, ok := tx.(sdk.FeeTx) + if !ok { + return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx") + } + + feeCoins := feeTx.GetFee() + + if len(feeCoins) > 1 { + return ctx, types.ErrTooManyFeeCoins + } + + baseDenom, err := mfd.TxFeesKeeper.GetBaseDenom(ctx) + if err != nil { + return ctx, err + } + + // If there is a fee attached to the tx, make sure the fee denom is a denom accepted by the chain + if len(feeCoins) == 1 { + feeDenom := feeCoins.GetDenomByIndex(0) + if feeDenom != baseDenom { + _, err := mfd.TxFeesKeeper.GetFeeToken(ctx, feeDenom) + if err != nil { + return ctx, err + } + } + } + + // If we are in CheckTx, this function is ran locally to determine if these fees are sufficient + // to enter our mempool. + // So we ensure that the provided fees meet a minimum threshold for the validator, + // converting every non-osmo specified asset into an osmo-equivalent amount, to determine sufficiency. + if (ctx.IsCheckTx() || ctx.IsReCheckTx()) && !simulate { + minGasPrices := ctx.MinGasPrices() + minBaseGasPrice := minGasPrices.AmountOf(baseDenom) + if !(minBaseGasPrice.IsZero()) { + if len(feeCoins) != 1 { + return ctx, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee, "no fee attached") + } + err = mfd.TxFeesKeeper.IsSufficientFee(ctx, minBaseGasPrice, feeTx.GetGas(), feeCoins[0]) + if err != nil { + return ctx, err + } + } + } + + return next(ctx, tx, simulate) +} + +func (k Keeper) IsSufficientFee(ctx sdk.Context, minBaseGasPrice sdk.Dec, gasRequested uint64, feeCoin sdk.Coin) error { + baseDenom, err := k.GetBaseDenom(ctx) + if err != nil { + return err + } + + // Determine the required fees by multiplying the required minimum gas + // price by the gas limit, where fee = ceil(minGasPrice * gasLimit). + glDec := sdk.NewDec(int64(gasRequested)) + requiredBaseFee := sdk.NewCoin(baseDenom, minBaseGasPrice.Mul(glDec).Ceil().RoundInt()) + + convertedFee, err := k.ConvertToBaseToken(ctx, feeCoin) + if err != nil { + return err + } + if !(convertedFee.IsGTE(requiredBaseFee)) { + return sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee, "insufficient fees; got: %s which converts to %s. required: %s", feeCoin, convertedFee, requiredBaseFee) + } + + return nil +} diff --git a/x/txfees/keeper/feedecorator_test.go b/x/txfees/keeper/feedecorator_test.go new file mode 100644 index 00000000000..cba307da4fc --- /dev/null +++ b/x/txfees/keeper/feedecorator_test.go @@ -0,0 +1,155 @@ +package keeper_test + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx" + + "github.com/osmosis-labs/osmosis/x/txfees/keeper" +) + +func (suite *KeeperTestSuite) TestFeeDecorator() { + suite.SetupTest(false) + + baseDenom, _ := suite.app.TxFeesKeeper.GetBaseDenom(suite.ctx) + + uion := "uion" + + uionPoolId := suite.PreparePoolWithAssets( + sdk.NewInt64Coin(sdk.DefaultBondDenom, 500), + sdk.NewInt64Coin(uion, 500), + ) + suite.ExecuteUpgradeFeeTokenProposal(uion, uionPoolId) + + tests := []struct { + name string + txFee sdk.Coins + minGasPrices sdk.DecCoins + gasRequested uint64 + isCheckTx bool + expectPass bool + }{ + { + name: "no min gas price - checktx", + txFee: sdk.NewCoins(), + minGasPrices: sdk.NewDecCoins(), + gasRequested: 10000, + isCheckTx: true, + expectPass: true, + }, + { + name: "no min gas price - delivertx", + txFee: sdk.NewCoins(), + minGasPrices: sdk.NewDecCoins(), + gasRequested: 10000, + isCheckTx: false, + expectPass: true, + }, + { + name: "works with valid basedenom fee", + txFee: sdk.NewCoins(sdk.NewInt64Coin(baseDenom, 1000)), + minGasPrices: sdk.NewDecCoins(sdk.NewDecCoinFromDec(baseDenom, + sdk.MustNewDecFromStr("0.1"))), + gasRequested: 10000, + isCheckTx: true, + expectPass: true, + }, + { + name: "doesn't work with not enough fee in checktx", + txFee: sdk.NewCoins(sdk.NewInt64Coin(baseDenom, 1)), + minGasPrices: sdk.NewDecCoins(sdk.NewDecCoinFromDec(baseDenom, + sdk.MustNewDecFromStr("0.1"))), + gasRequested: 10000, + isCheckTx: true, + expectPass: false, + }, + { + name: "works with not enough fee in delivertx", + txFee: sdk.NewCoins(sdk.NewInt64Coin(baseDenom, 1)), + minGasPrices: sdk.NewDecCoins(sdk.NewDecCoinFromDec(baseDenom, + sdk.MustNewDecFromStr("0.1"))), + gasRequested: 10000, + isCheckTx: false, + expectPass: true, + }, + { + name: "works with valid converted fee", + txFee: sdk.NewCoins(sdk.NewInt64Coin(uion, 1000)), + minGasPrices: sdk.NewDecCoins(sdk.NewDecCoinFromDec(baseDenom, + sdk.MustNewDecFromStr("0.1"))), + gasRequested: 10000, + isCheckTx: true, + expectPass: true, + }, + { + name: "doesn't work with not enough converted fee in checktx", + txFee: sdk.NewCoins(sdk.NewInt64Coin(uion, 1)), + minGasPrices: sdk.NewDecCoins(sdk.NewDecCoinFromDec(baseDenom, + sdk.MustNewDecFromStr("0.1"))), + gasRequested: 10000, + isCheckTx: true, + expectPass: false, + }, + { + name: "works with not enough converted fee in delivertx", + txFee: sdk.NewCoins(sdk.NewInt64Coin(uion, 1)), + minGasPrices: sdk.NewDecCoins(sdk.NewDecCoinFromDec(baseDenom, + sdk.MustNewDecFromStr("0.1"))), + gasRequested: 10000, + isCheckTx: false, + expectPass: true, + }, + { + name: "multiple fee coins - checktx", + txFee: sdk.NewCoins(sdk.NewInt64Coin(baseDenom, 1), sdk.NewInt64Coin(uion, 1)), + minGasPrices: sdk.NewDecCoins(), + gasRequested: 10000, + isCheckTx: true, + expectPass: false, + }, + { + name: "multiple fee coins - delivertx", + txFee: sdk.NewCoins(sdk.NewInt64Coin(baseDenom, 1), sdk.NewInt64Coin(uion, 1)), + minGasPrices: sdk.NewDecCoins(), + gasRequested: 10000, + isCheckTx: false, + expectPass: false, + }, + { + name: "invalid fee denom", + txFee: sdk.NewCoins(sdk.NewInt64Coin("moo", 1)), + minGasPrices: sdk.NewDecCoins(), + gasRequested: 10000, + isCheckTx: false, + expectPass: false, + }, + { + name: "mingasprice not containing basedenom gets treated as min gas price 0", + txFee: sdk.NewCoins(sdk.NewInt64Coin(uion, 100000000)), + minGasPrices: sdk.NewDecCoins(sdk.NewInt64DecCoin(uion, 1)), + gasRequested: 10000, + isCheckTx: true, + expectPass: true, + }, + } + + for _, tc := range tests { + + suite.ctx = suite.ctx.WithIsCheckTx(tc.isCheckTx) + suite.ctx = suite.ctx.WithMinGasPrices(tc.minGasPrices) + + tx := legacytx.NewStdTx([]sdk.Msg{}, legacytx.NewStdFee( + tc.gasRequested, + tc.txFee, + ), []legacytx.StdSignature{}, "") + + mfd := keeper.NewMempoolFeeDecorator(suite.app.TxFeesKeeper) + antehandler := sdk.ChainAnteDecorators(mfd) + _, err := antehandler(suite.ctx, tx, false) + if tc.expectPass { + suite.Require().NoError(err, "test: %s", tc.name) + } else { + suite.Require().Error(err, "test: %s", tc.name) + } + } +} diff --git a/x/txfees/keeper/feetokens.go b/x/txfees/keeper/feetokens.go new file mode 100644 index 00000000000..203edea7bc0 --- /dev/null +++ b/x/txfees/keeper/feetokens.go @@ -0,0 +1,158 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/gogo/protobuf/proto" + "github.com/osmosis-labs/osmosis/x/txfees/types" +) + +// ConvertToBaseToken converts a fee amount in a whitelisted fee token to the base fee token amount +func (k Keeper) ConvertToBaseToken(ctx sdk.Context, inputFee sdk.Coin) (sdk.Coin, error) { + baseDenom, err := k.GetBaseDenom(ctx) + if err != nil { + return sdk.Coin{}, err + } + + if inputFee.Denom == baseDenom { + return inputFee, nil + } + + feeToken, err := k.GetFeeToken(ctx, inputFee.Denom) + if err != nil { + return sdk.Coin{}, err + } + + spotPrice, err := k.spotPriceCalculator.CalculateSpotPrice(ctx, feeToken.PoolID, feeToken.Denom, baseDenom) + if err != nil { + return sdk.Coin{}, err + } + + return sdk.NewCoin(baseDenom, spotPrice.MulInt(inputFee.Amount).Ceil().RoundInt()), nil +} + +// GetFeeToken returns the fee token record for a specific denom +func (k Keeper) GetBaseDenom(ctx sdk.Context) (denom string, err error) { + store := ctx.KVStore(k.storeKey) + + if !store.Has(types.BaseDenomKey) { + return "", types.ErrNoBaseDenom + } + + bz := store.Get(types.BaseDenomKey) + + return string(bz), nil +} + +// SetBaseDenom sets the base fee denom for the chain. Should only be used once. +func (k Keeper) SetBaseDenom(ctx sdk.Context, denom string) error { + store := ctx.KVStore(k.storeKey) + + err := sdk.ValidateDenom(denom) + if err != nil { + return err + } + + store.Set(types.BaseDenomKey, []byte(denom)) + return nil +} + +// ValidateFeeToken validates that a fee token record is valid +// It checks: +// - The denom exists +// - The denom is not the base denom +// - The gamm pool exists +// - The gamm pool includes the base token and fee token +func (k Keeper) ValidateFeeToken(ctx sdk.Context, feeToken types.FeeToken) error { + baseDenom, err := k.GetBaseDenom(ctx) + if err != nil { + return err + } + if baseDenom == feeToken.Denom { + return sdkerrors.Wrap(types.ErrInvalidFeeToken, "cannot add basedenom as a whitelisted fee token") + } + // This not returning an error implies that: + // - feeToken.Denom exists + // - feeToken.PoolID exists + // - feeToken.PoolID has both feeToken.Denom and baseDenom + _, err = k.spotPriceCalculator.CalculateSpotPrice(ctx, feeToken.PoolID, feeToken.Denom, baseDenom) + + return err +} + +// GetFeeToken returns the fee token record for a specific denom. +// If the denom doesn't exist, returns an error. +func (k Keeper) GetFeeToken(ctx sdk.Context, denom string) (types.FeeToken, error) { + prefixStore := k.GetFeeTokensStore(ctx) + if !prefixStore.Has([]byte(denom)) { + return types.FeeToken{}, sdkerrors.Wrapf(types.ErrInvalidFeeToken, "%s", denom) + } + bz := prefixStore.Get([]byte(denom)) + + feeToken := types.FeeToken{} + err := proto.Unmarshal(bz, &feeToken) + if err != nil { + return types.FeeToken{}, err + } + + return feeToken, nil +} + +// setFeeToken sets a new fee token record for a specific denom. +// If the feeToken pool ID is 0, deletes the fee Token entry. +func (k Keeper) setFeeToken(ctx sdk.Context, feeToken types.FeeToken) error { + prefixStore := k.GetFeeTokensStore(ctx) + + if feeToken.PoolID == 0 { + if prefixStore.Has([]byte(feeToken.Denom)) { + prefixStore.Delete([]byte(feeToken.Denom)) + } + return nil + } + + err := k.ValidateFeeToken(ctx, feeToken) + if err != nil { + return err + } + + bz, err := proto.Marshal(&feeToken) + if err != nil { + return err + } + + prefixStore.Set([]byte(feeToken.Denom), bz) + return nil +} + +func (k Keeper) GetFeeTokens(ctx sdk.Context) (feetokens []types.FeeToken) { + prefixStore := k.GetFeeTokensStore(ctx) + + // this entire store just contains FeeTokens, so iterate over all entries. + iterator := prefixStore.Iterator(nil, nil) + defer iterator.Close() + + feeTokens := []types.FeeToken{} + + for ; iterator.Valid(); iterator.Next() { + + feeToken := types.FeeToken{} + + err := proto.Unmarshal(iterator.Value(), &feeToken) + if err != nil { + panic(err) + } + + feeTokens = append(feeTokens, feeToken) + } + return feeTokens +} + +func (k Keeper) SetFeeTokens(ctx sdk.Context, feetokens []types.FeeToken) error { + for _, feeToken := range feetokens { + err := k.setFeeToken(ctx, feeToken) + if err != nil { + return err + } + } + return nil +} diff --git a/x/txfees/keeper/feetokens_test.go b/x/txfees/keeper/feetokens_test.go new file mode 100644 index 00000000000..341b3fdf6eb --- /dev/null +++ b/x/txfees/keeper/feetokens_test.go @@ -0,0 +1,220 @@ +package keeper_test + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/osmosis-labs/osmosis/x/txfees/types" +) + +func (suite *KeeperTestSuite) TestBaseDenom() { + suite.SetupTest(false) + + // Test getting basedenom (should be default from genesis) + baseDenom, err := suite.app.TxFeesKeeper.GetBaseDenom(suite.ctx) + suite.Require().NoError(err) + suite.Require().Equal(sdk.DefaultBondDenom, baseDenom) + + converted, err := suite.app.TxFeesKeeper.ConvertToBaseToken(suite.ctx, sdk.NewInt64Coin(sdk.DefaultBondDenom, 10)) + suite.Require().True(converted.IsEqual(sdk.NewInt64Coin(sdk.DefaultBondDenom, 10))) + suite.Require().NoError(err) +} + +func (suite *KeeperTestSuite) TestUpgradeFeeTokenProposals() { + suite.SetupTest(false) + + uionPoolId := suite.PreparePoolWithAssets( + sdk.NewInt64Coin(sdk.DefaultBondDenom, 500), + sdk.NewInt64Coin("uion", 500), + ) + + uionPoolId2 := suite.PreparePoolWithAssets( + sdk.NewInt64Coin(sdk.DefaultBondDenom, 500), + sdk.NewInt64Coin("uion", 500), + ) + + // Make pool with fee token but no OSMO and make sure governance proposal fails + noBasePoolId := suite.PreparePoolWithAssets( + sdk.NewInt64Coin("uion", 500), + sdk.NewInt64Coin("foo", 500), + ) + + // Create correct pool and governance proposal + fooPoolId := suite.PreparePoolWithAssets( + sdk.NewInt64Coin(sdk.DefaultBondDenom, 500), + sdk.NewInt64Coin("foo", 1000), + ) + + tests := []struct { + name string + feeToken string + poolId uint64 + expectPass bool + }{ + { + name: "uion pool", + feeToken: "uion", + poolId: uionPoolId, + expectPass: true, + }, + { + name: "try with basedenom", + feeToken: sdk.DefaultBondDenom, + poolId: uionPoolId, + expectPass: false, + }, + { + name: "proposal with non-existent pool", + feeToken: "foo", + poolId: 100000000000, + expectPass: false, + }, + { + name: "proposal with wrong pool for fee token", + feeToken: "foo", + poolId: uionPoolId, + expectPass: false, + }, + { + name: "proposal with pool with no base denom", + feeToken: "foo", + poolId: noBasePoolId, + expectPass: false, + }, + { + name: "proposal to add foo correctly", + feeToken: "foo", + poolId: fooPoolId, + expectPass: true, + }, + { + name: "proposal to replace pool for fee token", + feeToken: "uion", + poolId: uionPoolId2, + expectPass: true, + }, + { + name: "proposal to replace uion as fee denom", + feeToken: "uion", + poolId: 0, + expectPass: true, + }, + } + + for _, tc := range tests { + + feeTokensBefore := suite.app.TxFeesKeeper.GetFeeTokens(suite.ctx) + + // Add a new whitelisted fee token via a governance proposal + err := suite.ExecuteUpgradeFeeTokenProposal(tc.feeToken, tc.poolId) + + feeTokensAfter := suite.app.TxFeesKeeper.GetFeeTokens(suite.ctx) + + if tc.expectPass { + // Make sure no error during setting of proposal + suite.Require().NoError(err, "test: %s", tc.name) + + // For a proposal that adds a feetoken + if tc.poolId != 0 { + // Make sure the length of fee tokens is >= before + suite.Require().GreaterOrEqual(len(feeTokensAfter), len(feeTokensBefore), "test: %s", tc.name) + // Ensure that the fee token is convertable to base token + _, err := suite.app.TxFeesKeeper.ConvertToBaseToken(suite.ctx, sdk.NewInt64Coin(tc.feeToken, 10)) + suite.Require().NoError(err, "test: %s", tc.name) + // make sure the queried poolId is the same as expected + queriedPoolId, err := suite.queryClient.DenomPoolId(suite.ctx.Context(), + &types.QueryDenomPoolIdRequest{ + Denom: tc.feeToken, + }, + ) + suite.Require().NoError(err, "test: %s", tc.name) + suite.Require().Equal(tc.poolId, queriedPoolId.GetPoolID(), "test: %s", tc.name) + } else { + // if this proposal deleted a fee token + // ensure that the length of fee tokens is <= to before + suite.Require().LessOrEqual(len(feeTokensAfter), len(feeTokensBefore), "test: %s", tc.name) + // Ensure that the fee token is not convertable to base token + _, err := suite.app.TxFeesKeeper.ConvertToBaseToken(suite.ctx, sdk.NewInt64Coin(tc.feeToken, 10)) + suite.Require().Error(err, "test: %s", tc.name) + // make sure the queried poolId errors + _, err = suite.queryClient.DenomPoolId(suite.ctx.Context(), + &types.QueryDenomPoolIdRequest{ + Denom: tc.feeToken, + }, + ) + suite.Require().Error(err, "test: %s", tc.name) + } + } else { + // Make sure errors during setting of proposal + suite.Require().Error(err, "test: %s", tc.name) + // fee tokens should be the same + suite.Require().Equal(len(feeTokensAfter), len(feeTokensBefore), "test: %s", tc.name) + } + } +} + +func (suite *KeeperTestSuite) TestFeeTokenConversions() { + suite.SetupTest(false) + + baseDenom, _ := suite.app.TxFeesKeeper.GetBaseDenom(suite.ctx) + + tests := []struct { + name string + baseDenomPoolInput sdk.Coin + feeTokenPoolInput sdk.Coin + inputFee sdk.Coin + expectedConvertable bool + expectedOutput sdk.Coin + }{ + { + name: "equal value", + baseDenomPoolInput: sdk.NewInt64Coin(baseDenom, 100), + feeTokenPoolInput: sdk.NewInt64Coin("uion", 100), + inputFee: sdk.NewInt64Coin("uion", 10), + expectedOutput: sdk.NewInt64Coin(baseDenom, 10), + expectedConvertable: true, + }, + { + name: "unequal value", + baseDenomPoolInput: sdk.NewInt64Coin(baseDenom, 100), + feeTokenPoolInput: sdk.NewInt64Coin("foo", 200), + inputFee: sdk.NewInt64Coin("foo", 10), + expectedOutput: sdk.NewInt64Coin(baseDenom, 20), + expectedConvertable: true, + }, + { + name: "basedenom value", + baseDenomPoolInput: sdk.NewInt64Coin(baseDenom, 100), + feeTokenPoolInput: sdk.NewInt64Coin("foo", 200), + inputFee: sdk.NewInt64Coin(baseDenom, 10), + expectedOutput: sdk.NewInt64Coin(baseDenom, 10), + expectedConvertable: true, + }, + { + name: "convert non-existent", + baseDenomPoolInput: sdk.NewInt64Coin(baseDenom, 100), + feeTokenPoolInput: sdk.NewInt64Coin("uion", 200), + inputFee: sdk.NewInt64Coin("foo", 10), + expectedOutput: sdk.Coin{}, + expectedConvertable: false, + }, + } + + for _, tc := range tests { + suite.SetupTest(false) + + poolId := suite.PreparePoolWithAssets( + tc.baseDenomPoolInput, + tc.feeTokenPoolInput, + ) + + suite.ExecuteUpgradeFeeTokenProposal(tc.feeTokenPoolInput.Denom, poolId) + + converted, err := suite.app.TxFeesKeeper.ConvertToBaseToken(suite.ctx, tc.inputFee) + if tc.expectedConvertable { + suite.Require().NoError(err, "test: %s", tc.name) + suite.Require().True(converted.IsEqual(tc.expectedOutput), "test: %s", tc.name) + } else { + suite.Require().Error(err, "test: %s", tc.name) + } + } + +} diff --git a/x/txfees/keeper/gov.go b/x/txfees/keeper/gov.go new file mode 100644 index 00000000000..449bae918e5 --- /dev/null +++ b/x/txfees/keeper/gov.go @@ -0,0 +1,12 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/osmosis-labs/osmosis/x/txfees/types" +) + +func (k Keeper) HandleUpdateFeeTokenProposal(ctx sdk.Context, p *types.UpdateFeeTokenProposal) error { + // setFeeToken internally calls ValidateFeeToken + return k.setFeeToken(ctx, p.Feetoken) +} diff --git a/x/txfees/keeper/grpc_query.go b/x/txfees/keeper/grpc_query.go new file mode 100644 index 00000000000..71320289c1e --- /dev/null +++ b/x/txfees/keeper/grpc_query.go @@ -0,0 +1,48 @@ +package keeper + +import ( + "context" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/osmosis-labs/osmosis/x/txfees/types" +) + +var _ types.QueryServer = Keeper{} + +func (k Keeper) FeeTokens(ctx context.Context, _ *types.QueryFeeTokensRequest) (*types.QueryFeeTokensResponse, error) { + sdkCtx := sdk.UnwrapSDKContext(ctx) + + feeTokens := k.GetFeeTokens(sdkCtx) + + return &types.QueryFeeTokensResponse{FeeTokens: feeTokens}, nil +} + +func (k Keeper) DenomPoolId(ctx context.Context, req *types.QueryDenomPoolIdRequest) (*types.QueryDenomPoolIdResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + + sdkCtx := sdk.UnwrapSDKContext(ctx) + + feeToken, err := k.GetFeeToken(sdkCtx, req.GetDenom()) + if err != nil { + return nil, err + } + + return &types.QueryDenomPoolIdResponse{PoolID: feeToken.GetPoolID()}, nil +} + +func (k Keeper) BaseDenom(ctx context.Context, _ *types.QueryBaseDenomRequest) (*types.QueryBaseDenomResponse, error) { + sdkCtx := sdk.UnwrapSDKContext(ctx) + + baseDenom, err := k.GetBaseDenom(sdkCtx) + if err != nil { + return nil, err + } + + return &types.QueryBaseDenomResponse{BaseDenom: baseDenom}, nil +} diff --git a/x/txfees/keeper/keeper.go b/x/txfees/keeper/keeper.go new file mode 100644 index 00000000000..698e96e84fc --- /dev/null +++ b/x/txfees/keeper/keeper.go @@ -0,0 +1,43 @@ +package keeper + +import ( + "fmt" + + "github.com/tendermint/tendermint/libs/log" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/osmosis-labs/osmosis/x/txfees/types" +) + +type ( + Keeper struct { + cdc codec.Marshaler + storeKey sdk.StoreKey + + spotPriceCalculator types.SpotPriceCalculator + } +) + +func NewKeeper( + cdc codec.Marshaler, + storeKey sdk.StoreKey, + spotPriceCalculator types.SpotPriceCalculator, +) Keeper { + return Keeper{ + cdc: cdc, + storeKey: storeKey, + spotPriceCalculator: spotPriceCalculator, + } +} + +func (k Keeper) Logger(ctx sdk.Context) log.Logger { + return ctx.Logger().With("module", fmt.Sprintf("x/%s", types.ModuleName)) +} + +func (k Keeper) GetFeeTokensStore(ctx sdk.Context) sdk.KVStore { + store := ctx.KVStore(k.storeKey) + return prefix.NewStore(store, []byte(types.FeeTokensStorePrefix)) +} diff --git a/x/txfees/keeper/keeper_test.go b/x/txfees/keeper/keeper_test.go new file mode 100644 index 00000000000..f13a005f5ae --- /dev/null +++ b/x/txfees/keeper/keeper_test.go @@ -0,0 +1,117 @@ +package keeper_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/suite" + + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/client" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/tendermint/tendermint/crypto/ed25519" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + + "github.com/osmosis-labs/osmosis/app" + gammtypes "github.com/osmosis-labs/osmosis/x/gamm/types" + "github.com/osmosis-labs/osmosis/x/txfees/types" +) + +type KeeperTestSuite struct { + suite.Suite + + ctx sdk.Context + app *app.OsmosisApp + + clientCtx client.Context + + queryClient types.QueryClient +} + +var ( + acc1 = sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address().Bytes()) + acc2 = sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address().Bytes()) + acc3 = sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address().Bytes()) +) + +func (suite *KeeperTestSuite) SetupTest(isCheckTx bool) { + app := app.Setup(isCheckTx) + ctx := app.BaseApp.NewContext(isCheckTx, tmproto.Header{Height: 1, ChainID: "osmosis-1", Time: time.Now().UTC()}) + + queryHelper := baseapp.NewQueryServerTestHelper(ctx, app.InterfaceRegistry()) + types.RegisterQueryServer(queryHelper, app.TxFeesKeeper) + queryClient := types.NewQueryClient(queryHelper) + + suite.app = app + suite.ctx = ctx + + suite.queryClient = queryClient + + // Mint some assets to the accounts. + for _, acc := range []sdk.AccAddress{acc1, acc2, acc3} { + err := suite.app.BankKeeper.AddCoins( + suite.ctx, + acc, + sdk.NewCoins( + sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(10000000000)), + sdk.NewCoin("uosmo", sdk.NewInt(100000000000000000)), // Needed for pool creation fee + sdk.NewCoin("uion", sdk.NewInt(10000000)), + sdk.NewCoin("foo", sdk.NewInt(10000000)), + sdk.NewCoin("bar", sdk.NewInt(10000000)), + ), + ) + if err != nil { + panic(err) + } + } +} + +func TestKeeperTestSuite(t *testing.T) { + suite.Run(t, new(KeeperTestSuite)) +} + +func (suite *KeeperTestSuite) ExecuteUpgradeFeeTokenProposal(feeToken string, poolId uint64) error { + upgradeProp := types.NewUpdateFeeTokenProposal( + "Test Proposal", + "test", + types.FeeToken{ + Denom: feeToken, + PoolID: poolId, + }, + ) + return suite.app.TxFeesKeeper.HandleUpdateFeeTokenProposal(suite.ctx, &upgradeProp) +} + +func (suite *KeeperTestSuite) PreparePoolWithAssets(asset1, asset2 sdk.Coin) uint64 { + return suite.preparePool( + []gammtypes.PoolAsset{ + { + Weight: sdk.NewInt(1), + Token: asset1, + }, + { + Weight: sdk.NewInt(1), + Token: asset2, + }, + }, + ) +} + +func (suite *KeeperTestSuite) preparePool(assets []gammtypes.PoolAsset) uint64 { + suite.Require().Len(assets, 2) + + poolId, err := suite.app.GAMMKeeper.CreateBalancerPool(suite.ctx, acc1, + gammtypes.BalancerPoolParams{ + SwapFee: sdk.NewDec(0), + ExitFee: sdk.NewDec(0), + }, assets, "") + suite.NoError(err) + + _, err = suite.app.GAMMKeeper.CalculateSpotPrice(suite.ctx, poolId, assets[0].Token.Denom, assets[1].Token.Denom) + suite.NoError(err) + + _, err = suite.app.GAMMKeeper.CalculateSpotPrice(suite.ctx, poolId, assets[1].Token.Denom, assets[0].Token.Denom) + suite.NoError(err) + + return poolId +} diff --git a/x/txfees/module.go b/x/txfees/module.go new file mode 100644 index 00000000000..bc2e90692e0 --- /dev/null +++ b/x/txfees/module.go @@ -0,0 +1,196 @@ +package txfees + +import ( + "context" + "encoding/json" + "fmt" + "math/rand" + + "github.com/gorilla/mux" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/spf13/cobra" + + abci "github.com/tendermint/tendermint/abci/types" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + cdctypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + + "github.com/osmosis-labs/osmosis/x/txfees/client/cli" + "github.com/osmosis-labs/osmosis/x/txfees/keeper" + "github.com/osmosis-labs/osmosis/x/txfees/types" +) + +var ( + _ module.AppModule = AppModule{} + _ module.AppModuleBasic = AppModuleBasic{} +) + +// ---------------------------------------------------------------------------- +// AppModuleBasic +// ---------------------------------------------------------------------------- + +// AppModuleBasic implements the AppModuleBasic interface for the txfees module. +type AppModuleBasic struct { + cdc codec.Marshaler +} + +func NewAppModuleBasic(cdc codec.Marshaler) AppModuleBasic { + return AppModuleBasic{cdc: cdc} +} + +// Name returns the txfees module's name. +func (AppModuleBasic) Name() string { + return types.ModuleName +} + +func (AppModuleBasic) RegisterCodec(cdc *codec.LegacyAmino) { + types.RegisterLegacyAminoCodec(cdc) +} + +func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + types.RegisterLegacyAminoCodec(cdc) +} + +// RegisterInterfaces registers the module's interface types +func (a AppModuleBasic) RegisterInterfaces(reg cdctypes.InterfaceRegistry) { + types.RegisterInterfaces(reg) +} + +// DefaultGenesis returns the txfees module's default genesis state. +func (AppModuleBasic) DefaultGenesis(cdc codec.JSONMarshaler) json.RawMessage { + return cdc.MustMarshalJSON(types.DefaultGenesis()) +} + +// ValidateGenesis performs genesis state validation for the txfee module. +func (AppModuleBasic) ValidateGenesis(cdc codec.JSONMarshaler, config client.TxEncodingConfig, bz json.RawMessage) error { + var genState types.GenesisState + if err := cdc.UnmarshalJSON(bz, &genState); err != nil { + return fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err) + } + return genState.Validate() +} + +// RegisterRESTRoutes is a no-op. Needed to meet AppModuleBasic interface. +func (AppModuleBasic) RegisterRESTRoutes(clientCtx client.Context, rtr *mux.Router) {} + +// RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the module. +func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) { + //nolint:errcheck + types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx)) +} + +// GetTxCmd returns the txfees module's root tx command. +func (a AppModuleBasic) GetTxCmd() *cobra.Command { + return cli.NewTxCmd() +} + +// GetQueryCmd returns the txfees module's root query command. +func (AppModuleBasic) GetQueryCmd() *cobra.Command { + return cli.GetQueryCmd(types.StoreKey) +} + +// ---------------------------------------------------------------------------- +// AppModule +// ---------------------------------------------------------------------------- + +// AppModule implements the AppModule interface for the txfees module. +type AppModule struct { + AppModuleBasic + + keeper keeper.Keeper +} + +func NewAppModule(cdc codec.Marshaler, keeper keeper.Keeper) AppModule { + return AppModule{ + AppModuleBasic: NewAppModuleBasic(cdc), + keeper: keeper, + } +} + +// Name returns the txfees module's name. +func (am AppModule) Name() string { + return am.AppModuleBasic.Name() +} + +// Route returns the txfees module's message routing key. +func (am AppModule) Route() sdk.Route { + return sdk.Route{} +} + +// QuerierRoute returns the txfees module's query routing key. +func (AppModule) QuerierRoute() string { return "" } + +// LegacyQuerierHandler is a no-op. Needed to meet AppModule interface. +func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sdk.Querier { + return nil +} + +// RegisterServices registers a GRPC query service to respond to the +// module-specific GRPC queries. +func (am AppModule) RegisterServices(cfg module.Configurator) { + types.RegisterQueryServer(cfg.QueryServer(), am.keeper) +} + +// RegisterInvariants registers the txfees module's invariants. +func (am AppModule) RegisterInvariants(_ sdk.InvariantRegistry) {} + +// InitGenesis performs the txfees module's genesis initialization It returns +// no validator updates. +func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONMarshaler, gs json.RawMessage) []abci.ValidatorUpdate { + var genState types.GenesisState + // Initialize global index to index in genesis state + cdc.MustUnmarshalJSON(gs, &genState) + + InitGenesis(ctx, am.keeper, genState) + + return []abci.ValidatorUpdate{} +} + +// ExportGenesis returns the txfees module's exported genesis state as raw JSON bytes. +func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json.RawMessage { + genState := ExportGenesis(ctx, am.keeper) + return cdc.MustMarshalJSON(genState) +} + +// BeginBlock executes all ABCI BeginBlock logic respective to the txfees module. +func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} + +// EndBlock executes all ABCI EndBlock logic respective to the txfees module. It +// returns no validator updates. +func (am AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate { + return []abci.ValidatorUpdate{} +} + +// ___________________________________________________________________________ + +// AppModuleSimulation functions + +// GenerateGenesisState creates a randomized GenState of the pool-incentives module. +func (am AppModule) GenerateGenesisState(simState *module.SimulationState) { + // gen := types.DefaultGenesis() + // gen.Basedenom = sdk.DefaultBondDenom + simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(types.DefaultGenesis()) +} + +// ProposalContents doesn't return any content functions for governance proposals. +func (am AppModule) ProposalContents(simState module.SimulationState) []simtypes.WeightedProposalContent { + return nil +} + +// RandomizedParams creates randomized txfees param changes for the simulator. +func (am AppModule) RandomizedParams(r *rand.Rand) []simtypes.ParamChange { + return nil +} + +// RegisterStoreDecoder registers a decoder for supply module's types +func (am AppModule) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) { +} + +// WeightedOperations returns the all the gov module operations with their respective weights. +func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { + return nil // TODO +} diff --git a/x/txfees/module_test.go b/x/txfees/module_test.go new file mode 100644 index 00000000000..b4c3d278534 --- /dev/null +++ b/x/txfees/module_test.go @@ -0,0 +1,27 @@ +package txfees_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + abcitypes "github.com/tendermint/tendermint/abci/types" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + + simapp "github.com/osmosis-labs/osmosis/app" +) + +func TestSetBaseDenomOnInitBlock(t *testing.T) { + app := simapp.Setup(false) + ctx := app.BaseApp.NewContext(false, tmproto.Header{}) + + app.InitChain( + abcitypes.RequestInitChain{ + AppStateBytes: []byte("{}"), + ChainId: "test-chain-id", + }, + ) + + baseDenom, err := app.TxFeesKeeper.GetBaseDenom(ctx) + require.Nil(t, err) + require.NotEmpty(t, baseDenom) +} diff --git a/x/txfees/types/codec.go b/x/txfees/types/codec.go new file mode 100644 index 00000000000..fd5bb245339 --- /dev/null +++ b/x/txfees/types/codec.go @@ -0,0 +1,23 @@ +package types + +import ( + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" +) + +func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + cdc.RegisterConcrete(&UpdateFeeTokenProposal{}, "osmosis/UpdateFeeTokenProposal", nil) +} + +func RegisterInterfaces(registry types.InterfaceRegistry) { + registry.RegisterImplementations( + (*govtypes.Content)(nil), + &UpdateFeeTokenProposal{}, + ) +} + +var ( + amino = codec.NewLegacyAmino() + ModuleCdc = codec.NewAminoCodec(amino) +) diff --git a/x/txfees/types/errors.go b/x/txfees/types/errors.go new file mode 100644 index 00000000000..335f1c6f201 --- /dev/null +++ b/x/txfees/types/errors.go @@ -0,0 +1,14 @@ +package types + +// DONTCOVER + +import ( + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +// x/txfees module errors +var ( + ErrNoBaseDenom = sdkerrors.Register(ModuleName, 1, "no base denom was set") + ErrTooManyFeeCoins = sdkerrors.Register(ModuleName, 2, "too many fee coins. only accepts fees in one denom") + ErrInvalidFeeToken = sdkerrors.Register(ModuleName, 3, "invalid fee token") +) diff --git a/x/txfees/types/expected_keepers.go b/x/txfees/types/expected_keepers.go new file mode 100644 index 00000000000..713d485cf4e --- /dev/null +++ b/x/txfees/types/expected_keepers.go @@ -0,0 +1,11 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// SpotPriceCalculator defines the contract that must be fulfilled by a spot price calculator +// The x/gamm keeper is expected to satisfy this interface +type SpotPriceCalculator interface { + CalculateSpotPrice(ctx sdk.Context, poolId uint64, tokenInDenom, tokenOutDenom string) (sdk.Dec, error) +} diff --git a/x/txfees/types/feetoken.pb.go b/x/txfees/types/feetoken.pb.go new file mode 100644 index 00000000000..e2280605d57 --- /dev/null +++ b/x/txfees/types/feetoken.pb.go @@ -0,0 +1,388 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: osmosis/txfees/v1beta1/feetoken.proto + +package types + +import ( + fmt "fmt" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/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 + +// FeeToken is a struct that specifies a coin denom, and pool ID pair. +// This marks the token as eligible for use as a tx fee asset in Osmosis. +// Its price in osmo is derived through looking at the provided pool ID. +// The pool ID must have osmo as one of its assets. +type FeeToken struct { + Denom string `protobuf:"bytes,1,opt,name=denom,proto3" json:"denom,omitempty" yaml:"denom"` + PoolID uint64 `protobuf:"varint,2,opt,name=poolID,proto3" json:"poolID,omitempty" yaml:"pool_id"` +} + +func (m *FeeToken) Reset() { *m = FeeToken{} } +func (m *FeeToken) String() string { return proto.CompactTextString(m) } +func (*FeeToken) ProtoMessage() {} +func (*FeeToken) Descriptor() ([]byte, []int) { + return fileDescriptor_c50689857adfcfe0, []int{0} +} +func (m *FeeToken) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *FeeToken) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_FeeToken.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 *FeeToken) XXX_Merge(src proto.Message) { + xxx_messageInfo_FeeToken.Merge(m, src) +} +func (m *FeeToken) XXX_Size() int { + return m.Size() +} +func (m *FeeToken) XXX_DiscardUnknown() { + xxx_messageInfo_FeeToken.DiscardUnknown(m) +} + +var xxx_messageInfo_FeeToken proto.InternalMessageInfo + +func (m *FeeToken) GetDenom() string { + if m != nil { + return m.Denom + } + return "" +} + +func (m *FeeToken) GetPoolID() uint64 { + if m != nil { + return m.PoolID + } + return 0 +} + +func init() { + proto.RegisterType((*FeeToken)(nil), "osmosis.txfees.v1beta1.FeeToken") +} + +func init() { + proto.RegisterFile("osmosis/txfees/v1beta1/feetoken.proto", fileDescriptor_c50689857adfcfe0) +} + +var fileDescriptor_c50689857adfcfe0 = []byte{ + // 232 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0xcd, 0x2f, 0xce, 0xcd, + 0x2f, 0xce, 0x2c, 0xd6, 0x2f, 0xa9, 0x48, 0x4b, 0x4d, 0x2d, 0xd6, 0x2f, 0x33, 0x4c, 0x4a, 0x2d, + 0x49, 0x34, 0xd4, 0x4f, 0x4b, 0x4d, 0x2d, 0xc9, 0xcf, 0x4e, 0xcd, 0xd3, 0x2b, 0x28, 0xca, 0x2f, + 0xc9, 0x17, 0x12, 0x83, 0x2a, 0xd3, 0x83, 0x28, 0xd3, 0x83, 0x2a, 0x93, 0x12, 0x49, 0xcf, 0x4f, + 0xcf, 0x07, 0x2b, 0xd1, 0x07, 0xb1, 0x20, 0xaa, 0x95, 0x52, 0xb8, 0x38, 0xdc, 0x52, 0x53, 0x43, + 0x40, 0xfa, 0x85, 0xd4, 0xb8, 0x58, 0x53, 0x52, 0xf3, 0xf2, 0x73, 0x25, 0x18, 0x15, 0x18, 0x35, + 0x38, 0x9d, 0x04, 0x3e, 0xdd, 0x93, 0xe7, 0xa9, 0x4c, 0xcc, 0xcd, 0xb1, 0x52, 0x02, 0x0b, 0x2b, + 0x05, 0x41, 0xa4, 0x85, 0xb4, 0xb8, 0xd8, 0x0a, 0xf2, 0xf3, 0x73, 0x3c, 0x5d, 0x24, 0x98, 0x14, + 0x18, 0x35, 0x58, 0x9c, 0x84, 0x3e, 0xdd, 0x93, 0xe7, 0x83, 0x28, 0x04, 0x89, 0xc7, 0x67, 0xa6, + 0x28, 0x05, 0x41, 0x55, 0x58, 0xb1, 0xbc, 0x58, 0x20, 0xcf, 0xe8, 0xe4, 0x71, 0xe2, 0x91, 0x1c, + 0xe3, 0x85, 0x47, 0x72, 0x8c, 0x0f, 0x1e, 0xc9, 0x31, 0x4e, 0x78, 0x2c, 0xc7, 0x70, 0xe1, 0xb1, + 0x1c, 0xc3, 0x8d, 0xc7, 0x72, 0x0c, 0x51, 0x7a, 0xe9, 0x99, 0x25, 0x19, 0xa5, 0x49, 0x7a, 0xc9, + 0xf9, 0xb9, 0xfa, 0x50, 0x87, 0xeb, 0xe6, 0x24, 0x26, 0x15, 0xc3, 0x38, 0xfa, 0x15, 0x30, 0xef, + 0x96, 0x54, 0x16, 0xa4, 0x16, 0x27, 0xb1, 0x81, 0x9d, 0x6d, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, + 0xbc, 0x13, 0x05, 0xd8, 0x0d, 0x01, 0x00, 0x00, +} + +func (this *FeeToken) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*FeeToken) + if !ok { + that2, ok := that.(FeeToken) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Denom != that1.Denom { + return false + } + if this.PoolID != that1.PoolID { + return false + } + return true +} +func (m *FeeToken) 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 *FeeToken) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *FeeToken) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.PoolID != 0 { + i = encodeVarintFeetoken(dAtA, i, uint64(m.PoolID)) + i-- + dAtA[i] = 0x10 + } + if len(m.Denom) > 0 { + i -= len(m.Denom) + copy(dAtA[i:], m.Denom) + i = encodeVarintFeetoken(dAtA, i, uint64(len(m.Denom))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintFeetoken(dAtA []byte, offset int, v uint64) int { + offset -= sovFeetoken(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *FeeToken) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Denom) + if l > 0 { + n += 1 + l + sovFeetoken(uint64(l)) + } + if m.PoolID != 0 { + n += 1 + sovFeetoken(uint64(m.PoolID)) + } + return n +} + +func sovFeetoken(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozFeetoken(x uint64) (n int) { + return sovFeetoken(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *FeeToken) 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 ErrIntOverflowFeetoken + } + 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: FeeToken: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: FeeToken: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Denom", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowFeetoken + } + 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 ErrInvalidLengthFeetoken + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthFeetoken + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Denom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + 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 ErrIntOverflowFeetoken + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PoolID |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipFeetoken(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthFeetoken + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipFeetoken(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, ErrIntOverflowFeetoken + } + 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, ErrIntOverflowFeetoken + } + 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, ErrIntOverflowFeetoken + } + 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, ErrInvalidLengthFeetoken + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupFeetoken + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthFeetoken + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthFeetoken = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowFeetoken = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupFeetoken = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/txfees/types/genesis.go b/x/txfees/types/genesis.go new file mode 100644 index 00000000000..c71cb4f8b1f --- /dev/null +++ b/x/txfees/types/genesis.go @@ -0,0 +1,30 @@ +package types + +import sdk "github.com/cosmos/cosmos-sdk/types" + +// DefaultGenesis returns the default txfee genesis state +func DefaultGenesis() *GenesisState { + return &GenesisState{ + Basedenom: sdk.DefaultBondDenom, + Feetokens: []FeeToken{}, + } +} + +// Validate performs basic genesis state validation returning an error upon any +// failure. It does not verify that the corresponding pool IDs actually exist. +// This is done in InitGenesis +func (gs GenesisState) Validate() error { + err := sdk.ValidateDenom(gs.Basedenom) + if err != nil { + return err + } + + for _, feeToken := range gs.Feetokens { + err := sdk.ValidateDenom(feeToken.Denom) + if err != nil { + return err + } + } + + return nil +} diff --git a/x/txfees/types/genesis.pb.go b/x/txfees/types/genesis.pb.go new file mode 100644 index 00000000000..eeabe8be8e5 --- /dev/null +++ b/x/txfees/types/genesis.pb.go @@ -0,0 +1,385 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: osmosis/txfees/v1beta1/genesis.proto + +package types + +import ( + fmt "fmt" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/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 + +// GenesisState defines the txfees module's genesis state. +type GenesisState struct { + Basedenom string `protobuf:"bytes,1,opt,name=basedenom,proto3" json:"basedenom,omitempty"` + Feetokens []FeeToken `protobuf:"bytes,2,rep,name=feetokens,proto3" json:"feetokens"` +} + +func (m *GenesisState) Reset() { *m = GenesisState{} } +func (m *GenesisState) String() string { return proto.CompactTextString(m) } +func (*GenesisState) ProtoMessage() {} +func (*GenesisState) Descriptor() ([]byte, []int) { + return fileDescriptor_4423c18e3d020b37, []int{0} +} +func (m *GenesisState) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GenesisState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GenesisState.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 *GenesisState) XXX_Merge(src proto.Message) { + xxx_messageInfo_GenesisState.Merge(m, src) +} +func (m *GenesisState) XXX_Size() int { + return m.Size() +} +func (m *GenesisState) XXX_DiscardUnknown() { + xxx_messageInfo_GenesisState.DiscardUnknown(m) +} + +var xxx_messageInfo_GenesisState proto.InternalMessageInfo + +func (m *GenesisState) GetBasedenom() string { + if m != nil { + return m.Basedenom + } + return "" +} + +func (m *GenesisState) GetFeetokens() []FeeToken { + if m != nil { + return m.Feetokens + } + return nil +} + +func init() { + proto.RegisterType((*GenesisState)(nil), "osmosis.txfees.v1beta1.GenesisState") +} + +func init() { + proto.RegisterFile("osmosis/txfees/v1beta1/genesis.proto", fileDescriptor_4423c18e3d020b37) +} + +var fileDescriptor_4423c18e3d020b37 = []byte{ + // 232 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0xc9, 0x2f, 0xce, 0xcd, + 0x2f, 0xce, 0x2c, 0xd6, 0x2f, 0xa9, 0x48, 0x4b, 0x4d, 0x2d, 0xd6, 0x2f, 0x33, 0x4c, 0x4a, 0x2d, + 0x49, 0x34, 0xd4, 0x4f, 0x4f, 0xcd, 0x4b, 0x2d, 0xce, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, + 0x17, 0x12, 0x83, 0xaa, 0xd2, 0x83, 0xa8, 0xd2, 0x83, 0xaa, 0x92, 0x12, 0x49, 0xcf, 0x4f, 0xcf, + 0x07, 0x2b, 0xd1, 0x07, 0xb1, 0x20, 0xaa, 0xa5, 0x54, 0x71, 0x98, 0x99, 0x96, 0x9a, 0x5a, 0x92, + 0x9f, 0x9d, 0x9a, 0x07, 0x51, 0xa6, 0x54, 0xc4, 0xc5, 0xe3, 0x0e, 0xb1, 0x25, 0xb8, 0x24, 0xb1, + 0x24, 0x55, 0x48, 0x86, 0x8b, 0x33, 0x29, 0xb1, 0x38, 0x35, 0x25, 0x35, 0x2f, 0x3f, 0x57, 0x82, + 0x51, 0x81, 0x51, 0x83, 0x33, 0x08, 0x21, 0x20, 0xe4, 0xc2, 0xc5, 0x09, 0xd3, 0x5f, 0x2c, 0xc1, + 0xa4, 0xc0, 0xac, 0xc1, 0x6d, 0xa4, 0xa0, 0x87, 0xdd, 0x59, 0x7a, 0x6e, 0xa9, 0xa9, 0x21, 0x20, + 0x85, 0x4e, 0x2c, 0x27, 0xee, 0xc9, 0x33, 0x04, 0x21, 0x34, 0x3a, 0x79, 0x9c, 0x78, 0x24, 0xc7, + 0x78, 0xe1, 0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x13, 0x1e, 0xcb, 0x31, 0x5c, 0x78, 0x2c, + 0xc7, 0x70, 0xe3, 0xb1, 0x1c, 0x43, 0x94, 0x5e, 0x7a, 0x66, 0x49, 0x46, 0x69, 0x92, 0x5e, 0x72, + 0x7e, 0xae, 0x3e, 0xd4, 0x58, 0xdd, 0x9c, 0xc4, 0xa4, 0x62, 0x18, 0x47, 0xbf, 0x02, 0xe6, 0x9d, + 0x92, 0xca, 0x82, 0xd4, 0xe2, 0x24, 0x36, 0xb0, 0x27, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, + 0x3d, 0x5c, 0xe7, 0x43, 0x41, 0x01, 0x00, 0x00, +} + +func (m *GenesisState) 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 *GenesisState) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Feetokens) > 0 { + for iNdEx := len(m.Feetokens) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Feetokens[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if len(m.Basedenom) > 0 { + i -= len(m.Basedenom) + copy(dAtA[i:], m.Basedenom) + i = encodeVarintGenesis(dAtA, i, uint64(len(m.Basedenom))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int { + offset -= sovGenesis(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *GenesisState) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Basedenom) + if l > 0 { + n += 1 + l + sovGenesis(uint64(l)) + } + if len(m.Feetokens) > 0 { + for _, e := range m.Feetokens { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + return n +} + +func sovGenesis(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozGenesis(x uint64) (n int) { + return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *GenesisState) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GenesisState: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GenesisState: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Basedenom", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Basedenom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Feetokens", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Feetokens = append(m.Feetokens, FeeToken{}) + if err := m.Feetokens[len(m.Feetokens)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipGenesis(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, ErrIntOverflowGenesis + } + 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, ErrIntOverflowGenesis + } + 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, ErrIntOverflowGenesis + } + 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, ErrInvalidLengthGenesis + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupGenesis + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthGenesis + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthGenesis = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowGenesis = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupGenesis = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/txfees/types/gov.go b/x/txfees/types/gov.go new file mode 100644 index 00000000000..7670d454f41 --- /dev/null +++ b/x/txfees/types/gov.go @@ -0,0 +1,57 @@ +package types + +import ( + "fmt" + "strings" + + sdk "github.com/cosmos/cosmos-sdk/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" +) + +const ( + ProposalTypeUpdateFeeToken = "UpdateFeeToken" +) + +func init() { + govtypes.RegisterProposalType(ProposalTypeUpdateFeeToken) + govtypes.RegisterProposalTypeCodec(&UpdateFeeTokenProposal{}, "osmosis/UpdateFeeTokenProposal") +} + +var _ govtypes.Content = &UpdateFeeTokenProposal{} + +func NewUpdateFeeTokenProposal(title, description string, feeToken FeeToken) UpdateFeeTokenProposal { + return UpdateFeeTokenProposal{ + Title: title, + Description: description, + Feetoken: feeToken, + } +} + +func (p *UpdateFeeTokenProposal) GetTitle() string { return p.Title } + +func (p *UpdateFeeTokenProposal) GetDescription() string { return p.Description } + +func (p *UpdateFeeTokenProposal) ProposalRoute() string { return RouterKey } + +func (p *UpdateFeeTokenProposal) ProposalType() string { + return ProposalTypeUpdateFeeToken +} + +func (p *UpdateFeeTokenProposal) ValidateBasic() error { + err := govtypes.ValidateAbstract(p) + if err != nil { + return err + } + + return sdk.ValidateDenom(p.Feetoken.Denom) +} + +func (p UpdateFeeTokenProposal) String() string { + var b strings.Builder + b.WriteString(fmt.Sprintf(`Update Fee Token Proposal: + Title: %s + Description: %s + Records: %s +`, p.Title, p.Description, p.Feetoken.String())) + return b.String() +} diff --git a/x/txfees/types/gov.pb.go b/x/txfees/types/gov.pb.go new file mode 100644 index 00000000000..c8142eeb056 --- /dev/null +++ b/x/txfees/types/gov.pb.go @@ -0,0 +1,442 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: osmosis/txfees/v1beta1/gov.proto + +package types + +import ( + fmt "fmt" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/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 + +// UpdateFeeTokenProposal is a gov Content type for adding a new whitelisted fee +// token. It must specify a denom along with gamm pool ID to use as a spot price +// calculator. It can be used to add a new denom to the whitelist It can also be +// used to update the Pool to associate with the denom. If Pool ID is set to 0, +// it will remove the denom from the whitelisted set. +type UpdateFeeTokenProposal struct { + Title string `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty" yaml:"title"` + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty" yaml:"description"` + Feetoken FeeToken `protobuf:"bytes,3,opt,name=feetoken,proto3" json:"feetoken" yaml:"fee_token"` +} + +func (m *UpdateFeeTokenProposal) Reset() { *m = UpdateFeeTokenProposal{} } +func (*UpdateFeeTokenProposal) ProtoMessage() {} +func (*UpdateFeeTokenProposal) Descriptor() ([]byte, []int) { + return fileDescriptor_2c4a51bafc82863d, []int{0} +} +func (m *UpdateFeeTokenProposal) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *UpdateFeeTokenProposal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_UpdateFeeTokenProposal.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 *UpdateFeeTokenProposal) XXX_Merge(src proto.Message) { + xxx_messageInfo_UpdateFeeTokenProposal.Merge(m, src) +} +func (m *UpdateFeeTokenProposal) XXX_Size() int { + return m.Size() +} +func (m *UpdateFeeTokenProposal) XXX_DiscardUnknown() { + xxx_messageInfo_UpdateFeeTokenProposal.DiscardUnknown(m) +} + +var xxx_messageInfo_UpdateFeeTokenProposal proto.InternalMessageInfo + +func init() { + proto.RegisterType((*UpdateFeeTokenProposal)(nil), "osmosis.txfees.v1beta1.UpdateFeeTokenProposal") +} + +func init() { proto.RegisterFile("osmosis/txfees/v1beta1/gov.proto", fileDescriptor_2c4a51bafc82863d) } + +var fileDescriptor_2c4a51bafc82863d = []byte{ + // 308 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0xc8, 0x2f, 0xce, 0xcd, + 0x2f, 0xce, 0x2c, 0xd6, 0x2f, 0xa9, 0x48, 0x4b, 0x4d, 0x2d, 0xd6, 0x2f, 0x33, 0x4c, 0x4a, 0x2d, + 0x49, 0x34, 0xd4, 0x4f, 0xcf, 0x2f, 0xd3, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x83, 0xaa, + 0xd0, 0x83, 0xa8, 0xd0, 0x83, 0xaa, 0x90, 0x12, 0x49, 0xcf, 0x4f, 0xcf, 0x07, 0x2b, 0xd1, 0x07, + 0xb1, 0x20, 0xaa, 0xa5, 0x54, 0x71, 0x98, 0x97, 0x96, 0x9a, 0x5a, 0x92, 0x9f, 0x9d, 0x9a, 0x07, + 0x51, 0xa6, 0xf4, 0x80, 0x91, 0x4b, 0x2c, 0xb4, 0x20, 0x25, 0xb1, 0x24, 0xd5, 0x2d, 0x35, 0x35, + 0x04, 0x24, 0x11, 0x50, 0x94, 0x5f, 0x90, 0x5f, 0x9c, 0x98, 0x23, 0xa4, 0xc6, 0xc5, 0x5a, 0x92, + 0x59, 0x92, 0x93, 0x2a, 0xc1, 0xa8, 0xc0, 0xa8, 0xc1, 0xe9, 0x24, 0xf0, 0xe9, 0x9e, 0x3c, 0x4f, + 0x65, 0x62, 0x6e, 0x8e, 0x95, 0x12, 0x58, 0x58, 0x29, 0x08, 0x22, 0x2d, 0x64, 0xc1, 0xc5, 0x9d, + 0x92, 0x5a, 0x9c, 0x5c, 0x94, 0x59, 0x50, 0x92, 0x99, 0x9f, 0x27, 0xc1, 0x04, 0x56, 0x2d, 0xf6, + 0xe9, 0x9e, 0xbc, 0x10, 0x44, 0x35, 0x92, 0xa4, 0x52, 0x10, 0xb2, 0x52, 0xa1, 0x30, 0x2e, 0x0e, + 0x98, 0x73, 0x24, 0x98, 0x15, 0x18, 0x35, 0xb8, 0x8d, 0x14, 0xf4, 0xb0, 0x7b, 0x52, 0x0f, 0xe6, + 0x3a, 0x27, 0x89, 0x13, 0xf7, 0xe4, 0x19, 0x3e, 0xdd, 0x93, 0x17, 0x80, 0x18, 0x9e, 0x96, 0x9a, + 0x1a, 0x0f, 0x36, 0x40, 0x29, 0x08, 0x6e, 0x96, 0x15, 0x4f, 0xc7, 0x02, 0x79, 0x86, 0x19, 0x0b, + 0xe4, 0x19, 0x5e, 0x2c, 0x90, 0x67, 0x74, 0xf2, 0x38, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, + 0xc6, 0x07, 0x8f, 0xe4, 0x18, 0x27, 0x3c, 0x96, 0x63, 0xb8, 0xf0, 0x58, 0x8e, 0xe1, 0xc6, 0x63, + 0x39, 0x86, 0x28, 0xbd, 0xf4, 0xcc, 0x92, 0x8c, 0xd2, 0x24, 0xbd, 0xe4, 0xfc, 0x5c, 0x7d, 0xa8, + 0xbd, 0xba, 0x39, 0x89, 0x49, 0xc5, 0x30, 0x8e, 0x7e, 0x05, 0x2c, 0xf4, 0x4a, 0x2a, 0x0b, 0x52, + 0x8b, 0x93, 0xd8, 0xc0, 0x61, 0x66, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0xf9, 0xcd, 0xf6, 0xeb, + 0xac, 0x01, 0x00, 0x00, +} + +func (this *UpdateFeeTokenProposal) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*UpdateFeeTokenProposal) + if !ok { + that2, ok := that.(UpdateFeeTokenProposal) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Title != that1.Title { + return false + } + if this.Description != that1.Description { + return false + } + if !this.Feetoken.Equal(&that1.Feetoken) { + return false + } + return true +} +func (m *UpdateFeeTokenProposal) 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 *UpdateFeeTokenProposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *UpdateFeeTokenProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Feetoken.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGov(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + if len(m.Description) > 0 { + i -= len(m.Description) + copy(dAtA[i:], m.Description) + i = encodeVarintGov(dAtA, i, uint64(len(m.Description))) + i-- + dAtA[i] = 0x12 + } + if len(m.Title) > 0 { + i -= len(m.Title) + copy(dAtA[i:], m.Title) + i = encodeVarintGov(dAtA, i, uint64(len(m.Title))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintGov(dAtA []byte, offset int, v uint64) int { + offset -= sovGov(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *UpdateFeeTokenProposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Title) + if l > 0 { + n += 1 + l + sovGov(uint64(l)) + } + l = len(m.Description) + if l > 0 { + n += 1 + l + sovGov(uint64(l)) + } + l = m.Feetoken.Size() + n += 1 + l + sovGov(uint64(l)) + return n +} + +func sovGov(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozGov(x uint64) (n int) { + return sovGov(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *UpdateFeeTokenProposal) 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 ErrIntOverflowGov + } + 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: UpdateFeeTokenProposal: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: UpdateFeeTokenProposal: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Title", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + 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 ErrInvalidLengthGov + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGov + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Title = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Description", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + 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 ErrInvalidLengthGov + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGov + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Description = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Feetoken", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGov + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGov + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Feetoken.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGov(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGov + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipGov(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, ErrIntOverflowGov + } + 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, ErrIntOverflowGov + } + 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, ErrIntOverflowGov + } + 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, ErrInvalidLengthGov + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupGov + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthGov + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthGov = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowGov = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupGov = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/txfees/types/keys.go b/x/txfees/types/keys.go new file mode 100644 index 00000000000..af4946db8c3 --- /dev/null +++ b/x/txfees/types/keys.go @@ -0,0 +1,20 @@ +package types + +const ( + // ModuleName defines the module name + ModuleName = "txfees" + + // StoreKey defines the primary module store key + StoreKey = ModuleName + + // RouterKey is the message route for slashing + RouterKey = ModuleName + + // QuerierRoute defines the module's query routing key + QuerierRoute = ModuleName +) + +var ( + BaseDenomKey = []byte("base_denom") + FeeTokensStorePrefix = []byte("fee_tokens") +) diff --git a/x/txfees/types/query.pb.go b/x/txfees/types/query.pb.go new file mode 100644 index 00000000000..f0426c35caa --- /dev/null +++ b/x/txfees/types/query.pb.go @@ -0,0 +1,1246 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: osmosis/txfees/v1beta1/query.proto + +package types + +import ( + context "context" + fmt "fmt" + _ "github.com/gogo/protobuf/gogoproto" + grpc1 "github.com/gogo/protobuf/grpc" + proto "github.com/gogo/protobuf/proto" + _ "google.golang.org/genproto/googleapis/api/annotations" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + _ "google.golang.org/protobuf/types/known/durationpb" + 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 + +type QueryFeeTokensRequest struct { +} + +func (m *QueryFeeTokensRequest) Reset() { *m = QueryFeeTokensRequest{} } +func (m *QueryFeeTokensRequest) String() string { return proto.CompactTextString(m) } +func (*QueryFeeTokensRequest) ProtoMessage() {} +func (*QueryFeeTokensRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_6cbc1b48c44dfdd6, []int{0} +} +func (m *QueryFeeTokensRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryFeeTokensRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryFeeTokensRequest.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 *QueryFeeTokensRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryFeeTokensRequest.Merge(m, src) +} +func (m *QueryFeeTokensRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryFeeTokensRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryFeeTokensRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryFeeTokensRequest proto.InternalMessageInfo + +type QueryFeeTokensResponse struct { + FeeTokens []FeeToken `protobuf:"bytes,1,rep,name=fee_tokens,json=feeTokens,proto3" json:"fee_tokens" yaml:"fee_tokens"` +} + +func (m *QueryFeeTokensResponse) Reset() { *m = QueryFeeTokensResponse{} } +func (m *QueryFeeTokensResponse) String() string { return proto.CompactTextString(m) } +func (*QueryFeeTokensResponse) ProtoMessage() {} +func (*QueryFeeTokensResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_6cbc1b48c44dfdd6, []int{1} +} +func (m *QueryFeeTokensResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryFeeTokensResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryFeeTokensResponse.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 *QueryFeeTokensResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryFeeTokensResponse.Merge(m, src) +} +func (m *QueryFeeTokensResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryFeeTokensResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryFeeTokensResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryFeeTokensResponse proto.InternalMessageInfo + +func (m *QueryFeeTokensResponse) GetFeeTokens() []FeeToken { + if m != nil { + return m.FeeTokens + } + return nil +} + +type QueryDenomPoolIdRequest struct { + Denom string `protobuf:"bytes,1,opt,name=denom,proto3" json:"denom,omitempty" yaml:"denom"` +} + +func (m *QueryDenomPoolIdRequest) Reset() { *m = QueryDenomPoolIdRequest{} } +func (m *QueryDenomPoolIdRequest) String() string { return proto.CompactTextString(m) } +func (*QueryDenomPoolIdRequest) ProtoMessage() {} +func (*QueryDenomPoolIdRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_6cbc1b48c44dfdd6, []int{2} +} +func (m *QueryDenomPoolIdRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryDenomPoolIdRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryDenomPoolIdRequest.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 *QueryDenomPoolIdRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryDenomPoolIdRequest.Merge(m, src) +} +func (m *QueryDenomPoolIdRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryDenomPoolIdRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryDenomPoolIdRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryDenomPoolIdRequest proto.InternalMessageInfo + +func (m *QueryDenomPoolIdRequest) GetDenom() string { + if m != nil { + return m.Denom + } + return "" +} + +type QueryDenomPoolIdResponse struct { + PoolID uint64 `protobuf:"varint,1,opt,name=poolID,proto3" json:"poolID,omitempty" yaml:"pool_id"` +} + +func (m *QueryDenomPoolIdResponse) Reset() { *m = QueryDenomPoolIdResponse{} } +func (m *QueryDenomPoolIdResponse) String() string { return proto.CompactTextString(m) } +func (*QueryDenomPoolIdResponse) ProtoMessage() {} +func (*QueryDenomPoolIdResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_6cbc1b48c44dfdd6, []int{3} +} +func (m *QueryDenomPoolIdResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryDenomPoolIdResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryDenomPoolIdResponse.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 *QueryDenomPoolIdResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryDenomPoolIdResponse.Merge(m, src) +} +func (m *QueryDenomPoolIdResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryDenomPoolIdResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryDenomPoolIdResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryDenomPoolIdResponse proto.InternalMessageInfo + +func (m *QueryDenomPoolIdResponse) GetPoolID() uint64 { + if m != nil { + return m.PoolID + } + return 0 +} + +type QueryBaseDenomRequest struct { +} + +func (m *QueryBaseDenomRequest) Reset() { *m = QueryBaseDenomRequest{} } +func (m *QueryBaseDenomRequest) String() string { return proto.CompactTextString(m) } +func (*QueryBaseDenomRequest) ProtoMessage() {} +func (*QueryBaseDenomRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_6cbc1b48c44dfdd6, []int{4} +} +func (m *QueryBaseDenomRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryBaseDenomRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryBaseDenomRequest.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 *QueryBaseDenomRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryBaseDenomRequest.Merge(m, src) +} +func (m *QueryBaseDenomRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryBaseDenomRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryBaseDenomRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryBaseDenomRequest proto.InternalMessageInfo + +type QueryBaseDenomResponse struct { + BaseDenom string `protobuf:"bytes,1,opt,name=base_denom,json=baseDenom,proto3" json:"base_denom,omitempty" yaml:"base_denom"` +} + +func (m *QueryBaseDenomResponse) Reset() { *m = QueryBaseDenomResponse{} } +func (m *QueryBaseDenomResponse) String() string { return proto.CompactTextString(m) } +func (*QueryBaseDenomResponse) ProtoMessage() {} +func (*QueryBaseDenomResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_6cbc1b48c44dfdd6, []int{5} +} +func (m *QueryBaseDenomResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryBaseDenomResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryBaseDenomResponse.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 *QueryBaseDenomResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryBaseDenomResponse.Merge(m, src) +} +func (m *QueryBaseDenomResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryBaseDenomResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryBaseDenomResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryBaseDenomResponse proto.InternalMessageInfo + +func (m *QueryBaseDenomResponse) GetBaseDenom() string { + if m != nil { + return m.BaseDenom + } + return "" +} + +func init() { + proto.RegisterType((*QueryFeeTokensRequest)(nil), "osmosis.txfees.v1beta1.QueryFeeTokensRequest") + proto.RegisterType((*QueryFeeTokensResponse)(nil), "osmosis.txfees.v1beta1.QueryFeeTokensResponse") + proto.RegisterType((*QueryDenomPoolIdRequest)(nil), "osmosis.txfees.v1beta1.QueryDenomPoolIdRequest") + proto.RegisterType((*QueryDenomPoolIdResponse)(nil), "osmosis.txfees.v1beta1.QueryDenomPoolIdResponse") + proto.RegisterType((*QueryBaseDenomRequest)(nil), "osmosis.txfees.v1beta1.QueryBaseDenomRequest") + proto.RegisterType((*QueryBaseDenomResponse)(nil), "osmosis.txfees.v1beta1.QueryBaseDenomResponse") +} + +func init() { + proto.RegisterFile("osmosis/txfees/v1beta1/query.proto", fileDescriptor_6cbc1b48c44dfdd6) +} + +var fileDescriptor_6cbc1b48c44dfdd6 = []byte{ + // 496 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x53, 0x41, 0x6b, 0x13, 0x41, + 0x18, 0xcd, 0x5a, 0x5b, 0xc8, 0x54, 0x44, 0x07, 0xdb, 0xc6, 0x20, 0x9b, 0x30, 0xa8, 0x94, 0x42, + 0x66, 0x6c, 0xd5, 0x8b, 0x37, 0x97, 0x52, 0xf4, 0x22, 0xba, 0x78, 0xea, 0x25, 0xcc, 0x9a, 0x6f, + 0xd7, 0xc5, 0x64, 0xbf, 0x6d, 0x66, 0x56, 0x1a, 0xc4, 0x8b, 0xbf, 0x40, 0x10, 0xfc, 0x0b, 0xfe, + 0x95, 0x1e, 0x0b, 0x5e, 0x3c, 0x05, 0x49, 0xfc, 0x05, 0xf9, 0x05, 0xb2, 0xb3, 0xb3, 0x49, 0x68, + 0x9a, 0xa6, 0xb7, 0xcc, 0xf7, 0xde, 0xbc, 0xef, 0xcd, 0x7b, 0x59, 0xc2, 0x50, 0xf5, 0x50, 0xc5, + 0x4a, 0xe8, 0xd3, 0x10, 0x40, 0x89, 0xcf, 0xfb, 0x01, 0x68, 0xb9, 0x2f, 0x4e, 0x32, 0xe8, 0x0f, + 0x78, 0xda, 0x47, 0x8d, 0x74, 0xdb, 0x72, 0x78, 0xc1, 0xe1, 0x96, 0x53, 0xbf, 0x17, 0x61, 0x84, + 0x86, 0x22, 0xf2, 0x5f, 0x05, 0xbb, 0xfe, 0x20, 0x42, 0x8c, 0xba, 0x20, 0x64, 0x1a, 0x0b, 0x99, + 0x24, 0xa8, 0xa5, 0x8e, 0x31, 0x51, 0x16, 0x75, 0x2d, 0x6a, 0x4e, 0x41, 0x16, 0x8a, 0x4e, 0xd6, + 0x37, 0x04, 0x8b, 0x3f, 0x5a, 0xe2, 0x27, 0x04, 0xd0, 0xf8, 0x09, 0x2c, 0x8d, 0xed, 0x90, 0xad, + 0x77, 0xb9, 0xc3, 0x23, 0x80, 0xf7, 0xf9, 0x58, 0xf9, 0x70, 0x92, 0x81, 0xd2, 0x4c, 0x93, 0xed, + 0x8b, 0x80, 0x4a, 0x31, 0x51, 0x40, 0x8f, 0x09, 0x09, 0x01, 0xda, 0x46, 0x45, 0xd5, 0x9c, 0xe6, + 0xda, 0xee, 0xe6, 0x41, 0x93, 0x5f, 0xfe, 0x34, 0x5e, 0x5e, 0xf7, 0xee, 0x9f, 0x0d, 0x1b, 0x95, + 0xc9, 0xb0, 0x71, 0x77, 0x20, 0x7b, 0xdd, 0x17, 0x6c, 0xa6, 0xc0, 0xfc, 0x6a, 0x58, 0xee, 0x60, + 0x2f, 0xc9, 0x8e, 0xd9, 0x7a, 0x08, 0x09, 0xf6, 0xde, 0x22, 0x76, 0x5f, 0x77, 0xac, 0x21, 0xfa, + 0x98, 0xac, 0x77, 0xf2, 0x69, 0xcd, 0x69, 0x3a, 0xbb, 0x55, 0xef, 0xce, 0x64, 0xd8, 0xb8, 0x55, + 0x68, 0x99, 0x31, 0xf3, 0x0b, 0x98, 0x1d, 0x91, 0xda, 0xa2, 0x84, 0xb5, 0xbe, 0x47, 0x36, 0xd2, + 0x7c, 0x72, 0x68, 0x44, 0x6e, 0x7a, 0x74, 0x32, 0x6c, 0xdc, 0x2e, 0x44, 0xf2, 0x79, 0x3b, 0xee, + 0x30, 0xdf, 0x32, 0xa6, 0xc9, 0x78, 0x52, 0x81, 0xd1, 0x2a, 0x93, 0x79, 0x63, 0x93, 0x99, 0x03, + 0xac, 0xfc, 0x33, 0x42, 0x02, 0xa9, 0xa0, 0x3d, 0xef, 0x73, 0x6b, 0xf6, 0xe6, 0x19, 0xc6, 0xfc, + 0x6a, 0x50, 0xde, 0x3e, 0x18, 0xaf, 0x91, 0x75, 0x23, 0x48, 0x7f, 0x3a, 0xa4, 0x3a, 0xcd, 0x9b, + 0xb6, 0x96, 0x65, 0x7a, 0x69, 0x61, 0x75, 0x7e, 0x5d, 0x7a, 0x61, 0x96, 0xed, 0x7d, 0xfb, 0xfd, + 0xef, 0xc7, 0x8d, 0x87, 0x94, 0x89, 0xe5, 0xff, 0x14, 0x5b, 0x11, 0xfd, 0xe5, 0x90, 0xcd, 0xb9, + 0x3c, 0xa9, 0xb8, 0x72, 0xd7, 0x62, 0x79, 0xf5, 0x27, 0xd7, 0xbf, 0x60, 0xed, 0x3d, 0x37, 0xf6, + 0x04, 0x6d, 0x2d, 0xb3, 0x67, 0x82, 0x6c, 0xdb, 0xda, 0xc4, 0x17, 0x73, 0xfc, 0x6a, 0x22, 0x9c, + 0x16, 0xb3, 0x22, 0xc2, 0x8b, 0xcd, 0xae, 0x88, 0x70, 0xa1, 0xef, 0xd5, 0x11, 0xce, 0x1a, 0xf7, + 0x5e, 0x9d, 0x8d, 0x5c, 0xe7, 0x7c, 0xe4, 0x3a, 0x7f, 0x47, 0xae, 0xf3, 0x7d, 0xec, 0x56, 0xce, + 0xc7, 0x6e, 0xe5, 0xcf, 0xd8, 0xad, 0x1c, 0xf3, 0x28, 0xd6, 0x1f, 0xb3, 0x80, 0x7f, 0xc0, 0x5e, + 0xa9, 0xd3, 0xea, 0xca, 0x40, 0x4d, 0x45, 0x4f, 0x4b, 0x59, 0x3d, 0x48, 0x41, 0x05, 0x1b, 0xe6, + 0xcb, 0x7d, 0xfa, 0x3f, 0x00, 0x00, 0xff, 0xff, 0x10, 0xa1, 0xf9, 0xc5, 0x72, 0x04, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// QueryClient is the client API for Query service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type QueryClient interface { + // FeeTokens returns a list of all the whitelisted fee tokens and their + // corresponding pools It does not include the BaseDenom, which has its own + // query endpoint + FeeTokens(ctx context.Context, in *QueryFeeTokensRequest, opts ...grpc.CallOption) (*QueryFeeTokensResponse, error) + DenomPoolId(ctx context.Context, in *QueryDenomPoolIdRequest, opts ...grpc.CallOption) (*QueryDenomPoolIdResponse, error) + BaseDenom(ctx context.Context, in *QueryBaseDenomRequest, opts ...grpc.CallOption) (*QueryBaseDenomResponse, error) +} + +type queryClient struct { + cc grpc1.ClientConn +} + +func NewQueryClient(cc grpc1.ClientConn) QueryClient { + return &queryClient{cc} +} + +func (c *queryClient) FeeTokens(ctx context.Context, in *QueryFeeTokensRequest, opts ...grpc.CallOption) (*QueryFeeTokensResponse, error) { + out := new(QueryFeeTokensResponse) + err := c.cc.Invoke(ctx, "/osmosis.txfees.v1beta1.Query/FeeTokens", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) DenomPoolId(ctx context.Context, in *QueryDenomPoolIdRequest, opts ...grpc.CallOption) (*QueryDenomPoolIdResponse, error) { + out := new(QueryDenomPoolIdResponse) + err := c.cc.Invoke(ctx, "/osmosis.txfees.v1beta1.Query/DenomPoolId", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) BaseDenom(ctx context.Context, in *QueryBaseDenomRequest, opts ...grpc.CallOption) (*QueryBaseDenomResponse, error) { + out := new(QueryBaseDenomResponse) + err := c.cc.Invoke(ctx, "/osmosis.txfees.v1beta1.Query/BaseDenom", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// QueryServer is the server API for Query service. +type QueryServer interface { + // FeeTokens returns a list of all the whitelisted fee tokens and their + // corresponding pools It does not include the BaseDenom, which has its own + // query endpoint + FeeTokens(context.Context, *QueryFeeTokensRequest) (*QueryFeeTokensResponse, error) + DenomPoolId(context.Context, *QueryDenomPoolIdRequest) (*QueryDenomPoolIdResponse, error) + BaseDenom(context.Context, *QueryBaseDenomRequest) (*QueryBaseDenomResponse, error) +} + +// UnimplementedQueryServer can be embedded to have forward compatible implementations. +type UnimplementedQueryServer struct { +} + +func (*UnimplementedQueryServer) FeeTokens(ctx context.Context, req *QueryFeeTokensRequest) (*QueryFeeTokensResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method FeeTokens not implemented") +} +func (*UnimplementedQueryServer) DenomPoolId(ctx context.Context, req *QueryDenomPoolIdRequest) (*QueryDenomPoolIdResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method DenomPoolId not implemented") +} +func (*UnimplementedQueryServer) BaseDenom(ctx context.Context, req *QueryBaseDenomRequest) (*QueryBaseDenomResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method BaseDenom not implemented") +} + +func RegisterQueryServer(s grpc1.Server, srv QueryServer) { + s.RegisterService(&_Query_serviceDesc, srv) +} + +func _Query_FeeTokens_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryFeeTokensRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).FeeTokens(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/osmosis.txfees.v1beta1.Query/FeeTokens", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).FeeTokens(ctx, req.(*QueryFeeTokensRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_DenomPoolId_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryDenomPoolIdRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).DenomPoolId(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/osmosis.txfees.v1beta1.Query/DenomPoolId", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).DenomPoolId(ctx, req.(*QueryDenomPoolIdRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_BaseDenom_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryBaseDenomRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).BaseDenom(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/osmosis.txfees.v1beta1.Query/BaseDenom", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).BaseDenom(ctx, req.(*QueryBaseDenomRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Query_serviceDesc = grpc.ServiceDesc{ + ServiceName: "osmosis.txfees.v1beta1.Query", + HandlerType: (*QueryServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "FeeTokens", + Handler: _Query_FeeTokens_Handler, + }, + { + MethodName: "DenomPoolId", + Handler: _Query_DenomPoolId_Handler, + }, + { + MethodName: "BaseDenom", + Handler: _Query_BaseDenom_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "osmosis/txfees/v1beta1/query.proto", +} + +func (m *QueryFeeTokensRequest) 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 *QueryFeeTokensRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryFeeTokensRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryFeeTokensResponse) 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 *QueryFeeTokensResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryFeeTokensResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.FeeTokens) > 0 { + for iNdEx := len(m.FeeTokens) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.FeeTokens[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 (m *QueryDenomPoolIdRequest) 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 *QueryDenomPoolIdRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryDenomPoolIdRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Denom) > 0 { + i -= len(m.Denom) + copy(dAtA[i:], m.Denom) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Denom))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryDenomPoolIdResponse) 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 *QueryDenomPoolIdResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryDenomPoolIdResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.PoolID != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.PoolID)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *QueryBaseDenomRequest) 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 *QueryBaseDenomRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryBaseDenomRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryBaseDenomResponse) 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 *QueryBaseDenomResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryBaseDenomResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.BaseDenom) > 0 { + i -= len(m.BaseDenom) + copy(dAtA[i:], m.BaseDenom) + i = encodeVarintQuery(dAtA, i, uint64(len(m.BaseDenom))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { + offset -= sovQuery(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *QueryFeeTokensRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryFeeTokensResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.FeeTokens) > 0 { + for _, e := range m.FeeTokens { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + return n +} + +func (m *QueryDenomPoolIdRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Denom) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryDenomPoolIdResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PoolID != 0 { + n += 1 + sovQuery(uint64(m.PoolID)) + } + return n +} + +func (m *QueryBaseDenomRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryBaseDenomResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.BaseDenom) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func sovQuery(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozQuery(x uint64) (n int) { + return sovQuery(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *QueryFeeTokensRequest) 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: QueryFeeTokensRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryFeeTokensRequest: 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 *QueryFeeTokensResponse) 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: QueryFeeTokensResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryFeeTokensResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field FeeTokens", 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.FeeTokens = append(m.FeeTokens, FeeToken{}) + if err := m.FeeTokens[len(m.FeeTokens)-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 (m *QueryDenomPoolIdRequest) 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: QueryDenomPoolIdRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryDenomPoolIdRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Denom", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Denom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryDenomPoolIdResponse) 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: QueryDenomPoolIdResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryDenomPoolIdResponse: 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 ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PoolID |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + 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 *QueryBaseDenomRequest) 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: QueryBaseDenomRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryBaseDenomRequest: 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 *QueryBaseDenomResponse) 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: QueryBaseDenomResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryBaseDenomResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BaseDenom", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.BaseDenom = string(dAtA[iNdEx:postIndex]) + 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 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + 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, ErrIntOverflowQuery + } + 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, ErrIntOverflowQuery + } + 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, ErrInvalidLengthQuery + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupQuery + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthQuery + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthQuery = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowQuery = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupQuery = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/txfees/types/query.pb.gw.go b/x/txfees/types/query.pb.gw.go new file mode 100644 index 00000000000..ab03c7daa51 --- /dev/null +++ b/x/txfees/types/query.pb.gw.go @@ -0,0 +1,308 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: osmosis/txfees/v1beta1/query.proto + +/* +Package types is a reverse proxy. + +It translates gRPC into RESTful JSON APIs. +*/ +package types + +import ( + "context" + "io" + "net/http" + + "github.com/golang/protobuf/descriptor" + "github.com/golang/protobuf/proto" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/grpc-ecosystem/grpc-gateway/utilities" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/status" +) + +// Suppress "imported and not used" errors +var _ codes.Code +var _ io.Reader +var _ status.Status +var _ = runtime.String +var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage + +func request_Query_FeeTokens_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryFeeTokensRequest + var metadata runtime.ServerMetadata + + msg, err := client.FeeTokens(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_FeeTokens_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryFeeTokensRequest + var metadata runtime.ServerMetadata + + msg, err := server.FeeTokens(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_DenomPoolId_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryDenomPoolIdRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["denom"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "denom") + } + + protoReq.Denom, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "denom", err) + } + + msg, err := client.DenomPoolId(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_DenomPoolId_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryDenomPoolIdRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["denom"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "denom") + } + + protoReq.Denom, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "denom", err) + } + + msg, err := server.DenomPoolId(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_BaseDenom_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryBaseDenomRequest + var metadata runtime.ServerMetadata + + msg, err := client.BaseDenom(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_BaseDenom_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryBaseDenomRequest + var metadata runtime.ServerMetadata + + msg, err := server.BaseDenom(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. +// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_FeeTokens_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_FeeTokens_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_FeeTokens_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_DenomPoolId_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_DenomPoolId_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_DenomPoolId_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_BaseDenom_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_BaseDenom_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_BaseDenom_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +// RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but +// automatically dials to "endpoint" and closes the connection when "ctx" gets done. +func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { + conn, err := grpc.Dial(endpoint, opts...) + if err != nil { + return err + } + defer func() { + if err != nil { + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + return + } + go func() { + <-ctx.Done() + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + }() + }() + + return RegisterQueryHandler(ctx, mux, conn) +} + +// RegisterQueryHandler registers the http handlers for service Query to "mux". +// The handlers forward requests to the grpc endpoint over "conn". +func RegisterQueryHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { + return RegisterQueryHandlerClient(ctx, mux, NewQueryClient(conn)) +} + +// RegisterQueryHandlerClient registers the http handlers for service Query +// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "QueryClient". +// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "QueryClient" +// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in +// "QueryClient" to call the correct interceptors. +func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, client QueryClient) error { + + mux.Handle("GET", pattern_Query_FeeTokens_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_FeeTokens_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_FeeTokens_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_DenomPoolId_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_DenomPoolId_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_DenomPoolId_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_BaseDenom_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_BaseDenom_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_BaseDenom_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +var ( + pattern_Query_FeeTokens_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"osmosis", "txfees", "v1beta1", "fee_tokens"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_DenomPoolId_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"osmosis", "txfees", "v1beta1", "denom_pool_id", "denom"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_BaseDenom_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"osmosis", "txfees", "v1beta1", "base_denom"}, "", runtime.AssumeColonVerbOpt(true))) +) + +var ( + forward_Query_FeeTokens_0 = runtime.ForwardResponseMessage + + forward_Query_DenomPoolId_0 = runtime.ForwardResponseMessage + + forward_Query_BaseDenom_0 = runtime.ForwardResponseMessage +)