diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 5545cd23..4e751977 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -17,4 +17,4 @@ jobs: - name: 'Checkout Repository' uses: actions/checkout@v4 - name: 'Dependency Review' - uses: actions/dependency-review-action@v2 + uses: actions/dependency-review-action@v3 diff --git a/.github/workflows/interchaintest-E2E.yml b/.github/workflows/interchaintest-E2E.yml index d48ec4c4..61171a48 100644 --- a/.github/workflows/interchaintest-E2E.yml +++ b/.github/workflows/interchaintest-E2E.yml @@ -68,7 +68,6 @@ jobs: - "ictest-ibc" # - "ictest-pob" # - "ictest-drip" - - "ictest-burn" # - "ictest-cwhooks" # - "ictest-clock" fail-fast: false diff --git a/Makefile b/Makefile index e143904b..40226cd7 100644 --- a/Makefile +++ b/Makefile @@ -207,9 +207,6 @@ ictest-pfm: rm-testcache ictest-tokenfactory: rm-testcache cd interchaintest && go test -race -v -run TestTerpTokenFactory . -ictest-burn: rm-testcache - cd interchaintest && go test -race -v -run TestTerpBurnModule . - # ictest-clock: rm-testcache # cd interchaintest && go test -race -v -run TestTerpClock . diff --git a/README.md b/README.md index a7a7c300..dd0ef659 100644 --- a/README.md +++ b/README.md @@ -61,3 +61,6 @@ This framework is like a craft genetics lineage, one that has been fine tuned wi If we forgot you in this list, let us know or open a PR ::) +## DISCLAIMER +# Disclaimer +TERP-CORE SOFTWARE IS PROVIDED “AS IS”, AT YOUR OWN RISK, AND WITHOUT WARRANTIES OF ANY KIND. No developer or entity involved in running terp-core software will be liable for any claims or damages whatsoever associated with your use, inability to use, or your interaction with other users of Stargaze, including any direct, indirect, incidental, special, exemplary, punitive or consequential damages, or loss of profits, cryptocurrencies, tokens, or anything else of value. Although Discover Decentralization, LLC and it's affiliates developed the initial code for Terp-Core, it does not own or control the Terp Network, which is run by a decentralized validator set. \ No newline at end of file diff --git a/SECURITY.md b/SECURITY.md index f3326aa8..1cc01ada 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -47,3 +47,4 @@ Please assist the Terp Network Security team by following these guidelines: - Demonstrate good faith by not disrupting the Terp Network's networks, data, services or communities; _Every effort will be made to handle and address security issues as quickly and efficiently as possible._ + diff --git a/app/app.go b/app/app.go index 14309f94..dfbcad80 100644 --- a/app/app.go +++ b/app/app.go @@ -65,7 +65,7 @@ import ( "github.com/terpnetwork/terp-core/v4/app/openapiconsole" v2 "github.com/terpnetwork/terp-core/v4/app/upgrades/v2" v3 "github.com/terpnetwork/terp-core/v4/app/upgrades/v3" - v4 "github.com/terpnetwork/terp-core/v4/app/upgrades/v4" + "github.com/terpnetwork/terp-core/v4/app/upgrades/v4_1" "github.com/terpnetwork/terp-core/v4/docs" "github.com/CosmWasm/wasmd/x/wasm" @@ -100,7 +100,8 @@ var ( Upgrades = []upgrades.Upgrade{ v2.Upgrade, v3.Upgrade, - v4.Upgrade, + // v4.Upgrade, patched for v4_1 + v4_1.Upgrade, } ) diff --git a/app/keepers/keepers.go b/app/keepers/keepers.go index a89d132c..0054ba0d 100644 --- a/app/keepers/keepers.go +++ b/app/keepers/keepers.go @@ -92,9 +92,10 @@ import ( upgradekeeper "github.com/cosmos/cosmos-sdk/x/upgrade/keeper" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" - denomburn "github.com/terpnetwork/terp-core/v4/x/burn" - // clockkeeper "github.com/terpnetwork/terp-core/v4/x/clock/keeper" - // clocktypes "github.com/terpnetwork/terp-core/v4/x/clock/types" + clockkeeper "github.com/terpnetwork/terp-core/v4/x/clock/keeper" + clocktypes "github.com/terpnetwork/terp-core/v4/x/clock/types" + dripkeeper "github.com/terpnetwork/terp-core/v4/x/drip/keeper" + driptypes "github.com/terpnetwork/terp-core/v4/x/drip/types" feesharekeeper "github.com/terpnetwork/terp-core/v4/x/feeshare/keeper" feesharetypes "github.com/terpnetwork/terp-core/v4/x/feeshare/types" @@ -102,7 +103,8 @@ import ( globalfeekeeper "github.com/terpnetwork/terp-core/v4/x/globalfee/keeper" globalfeetypes "github.com/terpnetwork/terp-core/v4/x/globalfee/types" - // token factory + // cwhookskeeper "github.com/terpnetwork/terp-core/v4/x/cw-hooks/keeper" + // cwhookstypes "github.com/terpnetwork/terp-core/v4/x/cw-hooks/types" "github.com/terpnetwork/terp-core/v4/x/tokenfactory/bindings" tokenfactorykeeper "github.com/terpnetwork/terp-core/v4/x/tokenfactory/keeper" @@ -110,7 +112,7 @@ import ( ) var ( - wasmCapabilities = "iterator,staking,stargate,token_factory,cosmwasm_1_1,cosmwasm_1_2,cosmwasm_1_3,cosmwasm_1_4,tokenfactory" + wasmCapabilities = "iterator,staking,stargate,token_factory,cosmwasm_1_1,cosmwasm_1_2,cosmwasm_1_3,cosmwasm_1_4,cosmwasm_1_5,tokenfactory" tokenFactoryCapabilities = []string{ tokenfactorytypes.EnableBurnFrom, @@ -135,7 +137,6 @@ var maccPerms = map[string][]string{ globalfee.ModuleName: nil, wasmtypes.ModuleName: {authtypes.Burner}, tokenfactorytypes.ModuleName: {authtypes.Minter, authtypes.Burner}, - denomburn.ModuleName: {authtypes.Burner}, } type AppKeepers struct { @@ -175,9 +176,10 @@ type AppKeepers struct { PacketForwardKeeper *packetforwardkeeper.Keeper ICQKeeper icqkeeper.Keeper ICAHostKeeper icahostkeeper.Keeper - // ClockKeeper clockkeeper.Keeper - TransferKeeper ibctransferkeeper.Keeper - WasmKeeper wasmkeeper.Keeper + ClockKeeper clockkeeper.Keeper + TransferKeeper ibctransferkeeper.Keeper + // CWHooksKeeper cwhookskeeper.Keeper + WasmKeeper wasmkeeper.Keeper ScopedIBCKeeper capabilitykeeper.ScopedKeeper ScopedICAHostKeeper capabilitykeeper.ScopedKeeper @@ -187,6 +189,8 @@ type AppKeepers struct { ScopedWasmKeeper capabilitykeeper.ScopedKeeper ScopedICQKeeper capabilitykeeper.ScopedKeeper + DripKeeper dripkeeper.Keeper + // Middleware wrapper Ics20WasmHooks *ibchooks.WasmHooks HooksICS4Wrapper ibchooks.ICS4Middleware @@ -324,7 +328,10 @@ func NewAppKeepers( // register the staking hooks // NOTE: stakingKeeper above is passed by reference, so that it will contain these hooks stakingKeeper.SetHooks( - stakingtypes.NewMultiStakingHooks(appKeepers.DistrKeeper.Hooks(), appKeepers.SlashingKeeper.Hooks()), + stakingtypes.NewMultiStakingHooks(appKeepers.DistrKeeper.Hooks(), + appKeepers.SlashingKeeper.Hooks(), + // appKeepers.CWHooksKeeper.StakingHooks(), + ), ) appKeepers.StakingKeeper = stakingKeeper @@ -364,7 +371,7 @@ func NewAppKeepers( ) appKeepers.GovKeeper = *govKeeper.SetHooks( govtypes.NewMultiGovHooks( - // register the governance hooks + // appKeepers.CWHooksKeeper.GovHooks(), ), ) @@ -530,10 +537,6 @@ func NewAppKeepers( }) wasmOpts = append(wasmOpts, querierOpts) - denomBurnerPlugin := denomburn.NewBurnerPlugin(appKeepers.BankKeeper, appKeepers.MintKeeper) - burnOverride := wasmkeeper.WithMessageHandler(wasmkeeper.NewBurnCoinMessageHandler(denomBurnerPlugin)) - wasmOpts = append(wasmOpts, burnOverride) - appKeepers.WasmKeeper = wasmkeeper.NewKeeper( appCodec, appKeepers.keys[wasmtypes.StoreKey], @@ -574,9 +577,28 @@ func NewAppKeepers( appKeepers.keys[globalfeetypes.StoreKey], govModAddress, ) - // appKeepers.ClockKeeper = clockkeeper.NewKeeper( - // appKeepers.keys[clocktypes.StoreKey], + + appKeepers.DripKeeper = dripkeeper.NewKeeper( + appKeepers.keys[driptypes.StoreKey], + appCodec, + appKeepers.BankKeeper, + authtypes.FeeCollectorName, + govModAddress, + ) + + appKeepers.ClockKeeper = clockkeeper.NewKeeper( + appKeepers.keys[clocktypes.StoreKey], + appCodec, + *appKeepers.ContractKeeper, + govModAddress, + ) + + // appKeepers.CWHooksKeeper = cwhookskeeper.NewKeeper( + // appKeepers.keys[cwhookstypes.StoreKey], // appCodec, + // stakingKeeper, + // *govKeeper, + // appKeepers.WasmKeeper, // *appKeepers.ContractKeeper, // govModAddress, // ) diff --git a/app/keepers/keys.go b/app/keepers/keys.go index 75047a6e..22200906 100644 --- a/app/keepers/keys.go +++ b/app/keepers/keys.go @@ -34,7 +34,10 @@ import ( icqtypes "github.com/cosmos/ibc-apps/modules/async-icq/v7/types" ibchookstypes "github.com/cosmos/ibc-apps/modules/ibc-hooks/v7/types" ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" - // clocktypes "github.com/terpnetwork/terp-core/v4/x/clock/types" + clocktypes "github.com/terpnetwork/terp-core/v4/x/clock/types" + + // cwhookstypes "github.com/terpnetwork/terp-core/v4/x/cw-hooks/types" + driptypes "github.com/terpnetwork/terp-core/v4/x/drip/types" ) func (appKeepers *AppKeepers) GenerateKeys() { @@ -68,7 +71,9 @@ func (appKeepers *AppKeepers) GenerateKeys() { ibchookstypes.StoreKey, feesharetypes.StoreKey, globalfeetypes.StoreKey, - // clocktypes.StoreKey, + clocktypes.StoreKey, + driptypes.StoreKey, + // cwhookstypes.StoreKey, tokenfactorytypes.StoreKey, ) diff --git a/app/modules.go b/app/modules.go index d65accaa..f711fcdd 100644 --- a/app/modules.go +++ b/app/modules.go @@ -20,8 +20,8 @@ import ( ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" ibctm "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint" - // "github.com/terpnetwork/terp-core/v4/x/clock" - // clocktypes "github.com/terpnetwork/terp-core/v4/x/clock/types" + "github.com/terpnetwork/terp-core/v4/x/clock" + clocktypes "github.com/terpnetwork/terp-core/v4/x/clock/types" "github.com/cosmos/cosmos-sdk/types/module" "github.com/cosmos/cosmos-sdk/x/auth" @@ -66,10 +66,15 @@ import ( "github.com/terpnetwork/terp-core/v4/x/globalfee" "github.com/terpnetwork/terp-core/v4/x/tokenfactory" + "github.com/terpnetwork/terp-core/v4/x/drip" + driptypes "github.com/terpnetwork/terp-core/v4/x/drip/types" + "github.com/cosmos/cosmos-sdk/x/group" ibchooks "github.com/cosmos/ibc-apps/modules/ibc-hooks/v7" ibchookstypes "github.com/cosmos/ibc-apps/modules/ibc-hooks/v7/types" + // cwhooks "github.com/terpnetwork/terp-core/v4/x/cw-hooks" + tokenfactorytypes "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types" groupmodule "github.com/cosmos/cosmos-sdk/x/group/module" @@ -110,8 +115,10 @@ var ModuleBasics = module.NewBasicManager( packetforward.AppModuleBasic{}, feeshare.AppModuleBasic{}, globalfee.AppModuleBasic{}, - // clock.AppModuleBasic{}, + clock.AppModuleBasic{}, + drip.AppModuleBasic{}, tokenfactory.AppModuleBasic{}, + // cwhooks.AppModuleBasic{}, ) func appModules( @@ -157,7 +164,8 @@ func appModules( ica.NewAppModule(&app.AppKeepers.ICAControllerKeeper, &app.AppKeepers.ICAHostKeeper), icq.NewAppModule(app.AppKeepers.ICQKeeper), packetforward.NewAppModule(app.AppKeepers.PacketForwardKeeper), - // clock.NewAppModule(appCodec, app.AppKeepers.ClockKeeper), + clock.NewAppModule(appCodec, app.AppKeepers.ClockKeeper), + // cwhooks.NewAppModule(appCodec, app.AppKeepers.CWHooksKeeper), ibchooks.NewAppModule(app.AppKeepers.AccountKeeper), crisis.NewAppModule(app.AppKeepers.CrisisKeeper, skipGenesisInvariants, app.GetSubspace(crisistypes.ModuleName)), // always be last to make sure that it checks for all invariants and not only part of them } @@ -189,6 +197,7 @@ func simulationModules( ibc.NewAppModule(app.AppKeepers.IBCKeeper), transfer.NewAppModule(app.AppKeepers.TransferKeeper), feeshare.NewAppModule(app.AppKeepers.FeeShareKeeper, app.AppKeepers.AccountKeeper, app.GetSubspace(feesharetypes.ModuleName)), + drip.NewAppModule(app.AppKeepers.DripKeeper, app.AppKeepers.AccountKeeper), ibcfee.NewAppModule(app.AppKeepers.IBCFeeKeeper), } } @@ -221,11 +230,13 @@ func orderBeginBlockers() []string { ibcfeetypes.ModuleName, icqtypes.ModuleName, packetforwardtypes.ModuleName, + driptypes.ModuleName, feesharetypes.ModuleName, globalfee.ModuleName, - // clocktypes.ModuleName, + clocktypes.ModuleName, ibchookstypes.ModuleName, tokenfactorytypes.ModuleName, + // cwhooks.ModuleName, wasmtypes.ModuleName, } } @@ -258,11 +269,13 @@ func orderEndBlockers() []string { ibcfeetypes.ModuleName, icqtypes.ModuleName, packetforwardtypes.ModuleName, + driptypes.ModuleName, feesharetypes.ModuleName, globalfee.ModuleName, - // clocktypes.ModuleName, + clocktypes.ModuleName, ibchookstypes.ModuleName, tokenfactorytypes.ModuleName, + // cwhooks.ModuleName, wasmtypes.ModuleName, } } @@ -280,13 +293,15 @@ func orderInitBlockers() []string { icatypes.ModuleName, ibcfeetypes.ModuleName, // wasm after ibc transfer + driptypes.ModuleName, feesharetypes.ModuleName, globalfee.ModuleName, icqtypes.ModuleName, packetforwardtypes.ModuleName, ibchookstypes.ModuleName, tokenfactorytypes.ModuleName, - // clocktypes.ModuleName, + clocktypes.ModuleName, + // cwhooks.ModuleName, wasmtypes.ModuleName, } } diff --git a/app/upgrades/v4/headstash-contract.go b/app/upgrades/v4/headstash-contract.go index 4430fc3a..d370cf77 100644 --- a/app/upgrades/v4/headstash-contract.go +++ b/app/upgrades/v4/headstash-contract.go @@ -1,80 +1,64 @@ package v4 -import ( - "embed" - "fmt" +// func setupHeadstashContract(ctx sdk.Context, keepers *keepers.AppKeepers) error { +// logger := ctx.Logger() +// // set the gov module address +// govModule := keepers.AccountKeeper.GetModuleAddress(govtypes.ModuleName) +// // define the headstash patch contract +// code, err := embedFs.ReadFile("headstash_contract.wasm") +// if err != nil { +// return err +// } +// // define instantiate permissions +// instantiateConfig := wasmtypes.AccessConfig{Permission: wasmtypes.AccessTypeEverybody} +// contractKeeper := wasmkeeper.NewDefaultPermissionKeeper(keepers.WasmKeeper) +// // store wasm contract +// codeID, _, err := contractKeeper.Create(ctx, govModule, code, &instantiateConfig) +// if err != nil { +// return err +// } +// // define claim_msg +// const claimMsg = "{wallet}" +// // define merkle_root string +// const merkleRoot = "77fb25152b72ac67f5a155461e396b0788dd0567ec32a96f8201b899ad516b02" +// // define instantiate msg +// initMsgBz := []byte(fmt.Sprintf(`{ +// "owner": "%s", +// "claim_msg_plaintext": "%s", +// "merkle_root": "%s" +// }`, +// govModule, claimMsg, merkleRoot)) +// // instantiate contract +// addr, _, err := contractKeeper.Instantiate(ctx, codeID, govModule, govModule, initMsgBz, "headstash patch contract", nil) +// if err != nil { +// return err +// } +// // format contract bytes to bech32 addr +// addrStr, err := sdk.Bech32ifyAddressBytes("terp", addr) +// if err != nil { +// return err +// } +// // print results +// logger.Info(fmt.Sprintf("instantiated headstash patch contract: %s", addrStr)) - sdk "github.com/cosmos/cosmos-sdk/types" - govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" +// // define token denominations +// nativeDenom := upgrades.GetChainsDenomToken(ctx.ChainID()) +// nativeFeeDenom := upgrades.GetChainsFeeDenomToken(ctx.ChainID()) - wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" - wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" - "github.com/terpnetwork/terp-core/v4/app/keepers" - "github.com/terpnetwork/terp-core/v4/app/upgrades" -) - -//go:embed headstash_contract.wasm -var embedFs embed.FS - -func setupHeadstashContract(ctx sdk.Context, keepers *keepers.AppKeepers) error { - logger := ctx.Logger() - // set the gov module address - govModule := keepers.AccountKeeper.GetModuleAddress(govtypes.ModuleName) - // define the headstash patch contract - code, err := embedFs.ReadFile("headstash_contract.wasm") - if err != nil { - return err - } - // define instantiate permissions - instantiateConfig := wasmtypes.AccessConfig{Permission: wasmtypes.AccessTypeEverybody} - contractKeeper := wasmkeeper.NewDefaultPermissionKeeper(keepers.WasmKeeper) - // store wasm contract - codeID, _, err := contractKeeper.Create(ctx, govModule, code, &instantiateConfig) - if err != nil { - return err - } - // define claim_msg - const claimMsg = "{wallet}" - // define merkle_root string - const merkleRoot = "77fb25152b72ac67f5a155461e396b0788dd0567ec32a96f8201b899ad516b02" - // define instantiate msg - initMsgBz := []byte(fmt.Sprintf(`{ - "owner": "%s", - "claim_msg_plaintext": "%s", - "merkle_root": "%s" - }`, - govModule, claimMsg, merkleRoot)) - // instantiate contract - addr, _, err := contractKeeper.Instantiate(ctx, codeID, govModule, govModule, initMsgBz, "headstash patch contract", nil) - if err != nil { - return err - } - // format contract bytes to bech32 addr - addrStr, err := sdk.Bech32ifyAddressBytes("terp", addr) - if err != nil { - return err - } - // print results - logger.Info(fmt.Sprintf("instantiated headstash patch contract: %s", addrStr)) - - // define token denominations - nativeDenom := upgrades.GetChainsDenomToken(ctx.ChainID()) - nativeFeeDenom := upgrades.GetChainsFeeDenomToken(ctx.ChainID()) - - // define total amount of tokens per each denom - amount := int64(123456789) - terpcoins := sdk.NewCoins( - sdk.NewInt64Coin(nativeDenom, amount), - ) - thiolcoins := sdk.NewCoins( - sdk.NewInt64Coin(nativeFeeDenom, amount), - ) - // send tokens from gov module to headstash-contract - if err := keepers.DistrKeeper.DistributeFromFeePool(ctx, terpcoins, addr); err != nil { - panic(err) - } - if err := keepers.DistrKeeper.DistributeFromFeePool(ctx, thiolcoins, addr); err != nil { - panic(err) - } - return nil -} +// // define total amount of tokens per each denom +// amount := int64(123456789) +// terpcoins := sdk.NewCoins( +// sdk.NewInt64Coin(nativeDenom, amount), +// ) +// thiolcoins := sdk.NewCoins( +// sdk.NewInt64Coin(nativeFeeDenom, amount), +// ) +// // send tokens from gov module to headstash-contract +// if err := keepers.DistrKeeper.DistributeFromFeePool(ctx, terpcoins, addr); err != nil { +// panic(err) +// } +// if err := keepers.DistrKeeper.DistributeFromFeePool(ctx, thiolcoins, addr); err != nil { +// panic(err) +// } +// return nil +// } diff --git a/app/upgrades/v4/headstash_contract.wasm b/app/upgrades/v4/headstash_contract.wasm deleted file mode 100644 index 61795253..00000000 Binary files a/app/upgrades/v4/headstash_contract.wasm and /dev/null differ diff --git a/app/upgrades/v4/upgrade.go b/app/upgrades/v4/upgrade.go index 2de77013..5c3dbd8e 100644 --- a/app/upgrades/v4/upgrade.go +++ b/app/upgrades/v4/upgrade.go @@ -9,7 +9,6 @@ import ( "github.com/terpnetwork/terp-core/v4/app/keepers" "github.com/terpnetwork/terp-core/v4/app/upgrades" - "github.com/terpnetwork/terp-core/v4/x/burn" globalfeetypes "github.com/terpnetwork/terp-core/v4/x/globalfee/types" ) @@ -42,14 +41,15 @@ func CreateV4UpgradeHandler( // revert headstash allocation returnFundsToCommunityPool(ctx, keepers.DistrKeeper) + // archived & removed burn module [#155](https://github.com/terpnetwork/terp-core/issues/155), reverted to [default denom burning function](https://pkg.go.dev/github.com/CosmWasm/wasmd@v0.43.0/x/wasm/types#Burner.BurnCoins) // print the burn module address - burnModule := keepers.AccountKeeper.GetModuleAddress(burn.ModuleName) - logger.Info(fmt.Sprintf("burn module address %s", burnModule)) + // burnModule := keepers.AccountKeeper.GetModuleAddress(burn.ModuleName) + // logger.Info(fmt.Sprintf("burn module address %s", burnModule)) // deployment & instantiation of headstash patch contract - if err := setupHeadstashContract(ctx, keepers); err != nil { - return nil, err - } + // if err := setupHeadstashContract(ctx, keepers); err != nil { + // return nil, err + // } return vm, nil } diff --git a/app/upgrades/v4_1/constants.go b/app/upgrades/v4_1/constants.go new file mode 100644 index 00000000..93a66e79 --- /dev/null +++ b/app/upgrades/v4_1/constants.go @@ -0,0 +1,22 @@ +package v4_1 + +import ( + store "github.com/cosmos/cosmos-sdk/store/types" + "github.com/terpnetwork/terp-core/v4/app/upgrades" + clocktypes "github.com/terpnetwork/terp-core/v4/x/clock/types" + driptypes "github.com/terpnetwork/terp-core/v4/x/drip/types" +) + +// UpgradeName defines the on-chain upgrade name for the Terp v4 upgrade. +const UpgradeName = "v4.1.0" + +var Upgrade = upgrades.Upgrade{ + UpgradeName: UpgradeName, + CreateUpgradeHandler: CreateV4_1UpgradeHandler, + StoreUpgrades: store.StoreUpgrades{ + Added: []string{ + driptypes.ModuleName, + clocktypes.ModuleName, + }, + }, +} diff --git a/app/upgrades/v4_1/headstash-patch.go b/app/upgrades/v4_1/headstash-patch.go new file mode 100644 index 00000000..71978966 --- /dev/null +++ b/app/upgrades/v4_1/headstash-patch.go @@ -0,0 +1,52 @@ +package v4_1 + +import ( + "strconv" + "strings" + + sdk "github.com/cosmos/cosmos-sdk/types" + + distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" + "github.com/terpnetwork/terp-core/v4/app/upgrades" + + v3 "github.com/terpnetwork/terp-core/v4/app/upgrades/v3" +) + +// revert headstash allocation by depositing funds back into community pool +func returnFundsToCommunityPool( + ctx sdk.Context, + dk distrkeeper.Keeper, +) { + headstashes := v3.GetHeadstashPayments() + total := int64(0) + + nativeDenom := upgrades.GetChainsDenomToken(ctx.ChainID()) + nativeFeeDenom := upgrades.GetChainsFeeDenomToken(ctx.ChainID()) + + for _, headstash := range headstashes { + addr, err := sdk.AccAddressFromBech32(headstash[0]) + if err != nil { + panic(err) + } + // defines the value associated with a given address + amount, err := strconv.ParseInt(strings.TrimSpace(headstash[1]), 10, 64) + if err != nil { + panic(err) + } + terpcoins := sdk.NewCoins( + sdk.NewInt64Coin(nativeDenom, amount), + ) + thiolcoins := sdk.NewCoins( + sdk.NewInt64Coin(nativeFeeDenom, amount), + ) + if err := dk.FundCommunityPool(ctx, terpcoins, addr); err != nil { + panic(err) + } + if err := dk.FundCommunityPool(ctx, thiolcoins, addr); err != nil { + panic(err) + } + total += amount + } +} + +// TODO: handle headstash-patch contract upload & instantiation diff --git a/app/upgrades/v4_1/upgrade.go b/app/upgrades/v4_1/upgrade.go new file mode 100644 index 00000000..d532766a --- /dev/null +++ b/app/upgrades/v4_1/upgrade.go @@ -0,0 +1,65 @@ +package v4_1 + +import ( + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + + "github.com/terpnetwork/terp-core/v4/app/keepers" + "github.com/terpnetwork/terp-core/v4/app/upgrades" + clocktypes "github.com/terpnetwork/terp-core/v4/x/clock/types" + driptypes "github.com/terpnetwork/terp-core/v4/x/drip/types" + globalfeetypes "github.com/terpnetwork/terp-core/v4/x/globalfee/types" +) + +// CreateUpgradeHandler creates an SDK upgrade handler for v4.1 +func CreateV4_1UpgradeHandler( + mm *module.Manager, + cfg module.Configurator, + keepers *keepers.AppKeepers, +) upgradetypes.UpgradeHandler { + return func(ctx sdk.Context, _ upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) { + logger := ctx.Logger().With("upgrade", UpgradeName) + + ctx.Logger().Info(` + ::: ::: ::: ::: :::::::::: ::: ::::::::: :::: ::: :::::::::: :::::::: :::::::::: :::: ::: :::::::::: + :+: :+: :+: :+:+: :+: :+: :+: :+: :+: :+:+: :+: :+: :+: :+: :+: :+:+: :+: :+: + +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ :+:+:+ +:+ +:+ +:+ +:+ :+:+:+ +:+ +:+ + +#+ +:+ +#+ +:+ +#+ :#::+::# +#++:++#++: +#++:++#: +#+ +:+ +#+ +#++:++# +#++:++#++ +#++:++# +#+ +:+ +#+ +#++:++# + +#+ +#+ +#+#+#+#+#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+#+# +#+ +#+ +#+ +#+ +#+#+# +#+ + #+#+#+# #+# #+# #+# #+# #+# #+# #+# #+# #+# #+#+# #+# #+# #+# #+# #+# #+#+# #+# + ### ### ### ####### ### ### ### ### ### ### #### ########## ######## ########## ### #### ########## + + + `) + // GlobalFee + nativeFeeDenom := upgrades.GetChainsFeeDenomToken(ctx.ChainID()) + minGasPrices := sdk.DecCoins{ + // 0.05uthiol + sdk.NewDecCoinFromDec(nativeFeeDenom, sdk.NewDecWithPrec(5, 2)), + } + newGlobalFeeParams := globalfeetypes.Params{ + MinimumGasPrices: minGasPrices, + } + if err := keepers.GlobalFeeKeeper.SetParams(ctx, newGlobalFeeParams); err != nil { + return nil, err + } + logger.Info(fmt.Sprintf("upgraded global fee params to %s", minGasPrices)) + + // revert headstash allocation + returnFundsToCommunityPool(ctx, keepers.DistrKeeper) + + // x/clock + if err := keepers.ClockKeeper.SetParams(ctx, clocktypes.DefaultParams()); err != nil { + return nil, err + } + // x/drip + if err := keepers.DripKeeper.SetParams(ctx, driptypes.DefaultParams()); err != nil { + return nil, err + } + + return vm, nil + } +} diff --git a/config.yml b/config.yml deleted file mode 100644 index 77b0d9b1..00000000 --- a/config.yml +++ /dev/null @@ -1,20 +0,0 @@ -accounts: - - name: alex - coins: ["444token", "444stake"] - - name: athena - coins: ["10000token", "100000000stake"] - - name: bob - oins: ["10000token", "100000000stake"] - - name: jen - coins: ["10000token", "100000000stake"] -validator: - name: athena - staked: "100000000stake" -client: - openapi: - path: "docs/static/openapi.yml" -faucet: - name: bob - coins: ["5token", "100000stake"] -build: - main: "cmd/terpd" diff --git a/go.mod b/go.mod index 7825f31c..b2ce9cbb 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/terpnetwork/terp-core/v4 go 1.19 require ( - github.com/CosmWasm/wasmd v0.43.0 + github.com/CosmWasm/wasmd v0.45.0 github.com/CosmWasm/wasmvm v1.5.0 github.com/cometbft/cometbft v0.37.2 github.com/cometbft/cometbft-db v0.8.0 diff --git a/go.sum b/go.sum index 998cc597..36c363da 100644 --- a/go.sum +++ b/go.sum @@ -211,8 +211,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= -github.com/CosmWasm/wasmd v0.43.0 h1:4xQAiNf6Ej+TuYe4PXwrtVJ9C+xyFrbsdqHH/kU9Vxk= -github.com/CosmWasm/wasmd v0.43.0/go.mod h1:gpri8YvkRErBz+qDme5jOThGZmSlHfyN532bWibXOl4= +github.com/CosmWasm/wasmd v0.45.0 h1:9zBqrturKJwC2kVsfHvbrA++EN0PS7UTXCffCGbg6JI= +github.com/CosmWasm/wasmd v0.45.0/go.mod h1:RnSAiqbNIZu4QhO+0pd7qGZgnYAMBPGmXpzTADag944= github.com/CosmWasm/wasmvm v1.5.0 h1:3hKeT9SfwfLhxTGKH3vXaKFzBz1yuvP8SlfwfQXbQfw= github.com/CosmWasm/wasmvm v1.5.0/go.mod h1:fXB+m2gyh4v9839zlIXdMZGeLAxqUdYdFQqYsTha2hc= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= diff --git a/interchaintest/go.mod b/interchaintest/go.mod index 400df6ab..d96838ca 100644 --- a/interchaintest/go.mod +++ b/interchaintest/go.mod @@ -16,7 +16,7 @@ replace ( ) require ( - github.com/CosmWasm/wasmd v0.43.0 + github.com/CosmWasm/wasmd v0.45.0 github.com/cosmos/cosmos-sdk v0.47.5 github.com/cosmos/gogoproto v1.4.10 github.com/cosmos/ibc-go/v7 v7.3.0 diff --git a/interchaintest/go.sum b/interchaintest/go.sum index 5318d66a..8b9d24c9 100644 --- a/interchaintest/go.sum +++ b/interchaintest/go.sum @@ -219,8 +219,8 @@ github.com/ChainSafe/go-schnorrkel v1.0.0 h1:3aDA67lAykLaG1y3AOjs88dMxC88PgUuHRr github.com/ChainSafe/go-schnorrkel v1.0.0/go.mod h1:dpzHYVxLZcp8pjlV+O+UR8K0Hp/z7vcchBSbMBEhCw4= github.com/ComposableFi/go-subkey/v2 v2.0.0-tm03420 h1:oknQF/iIhf5lVjbwjsVDzDByupRhga8nhA3NAmwyHDA= github.com/ComposableFi/go-subkey/v2 v2.0.0-tm03420/go.mod h1:KYkiMX5AbOlXXYfxkrYPrRPV6EbVUALTQh5ptUOJzu8= -github.com/CosmWasm/wasmd v0.43.0 h1:4xQAiNf6Ej+TuYe4PXwrtVJ9C+xyFrbsdqHH/kU9Vxk= -github.com/CosmWasm/wasmd v0.43.0/go.mod h1:gpri8YvkRErBz+qDme5jOThGZmSlHfyN532bWibXOl4= +github.com/CosmWasm/wasmd v0.45.0 h1:9zBqrturKJwC2kVsfHvbrA++EN0PS7UTXCffCGbg6JI= +github.com/CosmWasm/wasmd v0.45.0/go.mod h1:RnSAiqbNIZu4QhO+0pd7qGZgnYAMBPGmXpzTADag944= github.com/CosmWasm/wasmvm v1.5.0 h1:3hKeT9SfwfLhxTGKH3vXaKFzBz1yuvP8SlfwfQXbQfw= github.com/CosmWasm/wasmvm v1.5.0/go.mod h1:fXB+m2gyh4v9839zlIXdMZGeLAxqUdYdFQqYsTha2hc= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= diff --git a/interchaintest/helpers/drip.go b/interchaintest/helpers/drip.go new file mode 100644 index 00000000..e31debc7 --- /dev/null +++ b/interchaintest/helpers/drip.go @@ -0,0 +1,34 @@ +package helpers + +import ( + "context" + "testing" + + "github.com/cosmos/cosmos-sdk/crypto/keyring" + "github.com/strangelove-ventures/interchaintest/v7/chain/cosmos" + "github.com/strangelove-ventures/interchaintest/v7/ibc" + "github.com/strangelove-ventures/interchaintest/v7/testutil" + "github.com/stretchr/testify/require" +) + +func DripTokens(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, user ibc.Wallet, coinAmt string) { + // amount is #utoken + cmd := []string{"terpd", "tx", "drip", "distribute-tokens", coinAmt, + "--node", chain.GetRPCAddress(), + "--home", chain.HomeDir(), + "--chain-id", chain.Config().ChainID, + "--from", user.KeyName(), + "--gas", "500000", + "--keyring-dir", chain.HomeDir(), + "--keyring-backend", keyring.BackendTest, + "-y", + } + stdout, _, err := chain.Exec(ctx, cmd, nil) + require.NoError(t, err) + + debugOutput(t, string(stdout)) + + if err := testutil.WaitForBlocks(ctx, 2, chain); err != nil { + t.Fatal(err) + } +} diff --git a/interchaintest/helpers/query_helpers.go b/interchaintest/helpers/query_helpers.go index e7079917..881487e8 100644 --- a/interchaintest/helpers/query_helpers.go +++ b/interchaintest/helpers/query_helpers.go @@ -2,7 +2,10 @@ package helpers import ( "context" + "encoding/json" + "fmt" "testing" + "time" "github.com/strangelove-ventures/interchaintest/v7/chain/cosmos" "github.com/stretchr/testify/require" @@ -21,3 +24,65 @@ func GetClockContractValue(t *testing.T, ctx context.Context, chain *cosmos.Cosm require.NoError(t, err) return res } + +// From stakingtypes.Validator +type Vals struct { + Validators []struct { + OperatorAddress string `json:"operator_address"` + ConsensusPubkey struct { + Type string `json:"@type"` + Key string `json:"key"` + } `json:"consensus_pubkey"` + Jailed bool `json:"jailed"` + Status string `json:"status"` + Tokens string `json:"tokens"` + DelegatorShares string `json:"delegator_shares"` + Description struct { + Moniker string `json:"moniker"` + Identity string `json:"identity"` + Website string `json:"website"` + SecurityContact string `json:"security_contact"` + Details string `json:"details"` + } `json:"description"` + UnbondingHeight string `json:"unbonding_height"` + UnbondingTime time.Time `json:"unbonding_time"` + Commission struct { + CommissionRates struct { + Rate string `json:"rate"` + MaxRate string `json:"max_rate"` + MaxChangeRate string `json:"max_change_rate"` + } `json:"commission_rates"` + UpdateTime time.Time `json:"update_time"` + } `json:"commission"` + MinSelfDelegation string `json:"min_self_delegation"` + UnbondingOnHoldRefCount string `json:"unbonding_on_hold_ref_count"` + UnbondingIds []any `json:"unbonding_ids"` + } `json:"validators"` + Pagination struct { + NextKey any `json:"next_key"` + Total string `json:"total"` + } `json:"pagination"` +} + +func GetValidators(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain) Vals { + var res Vals + + cmd := []string{"terpd", "query", "staking", "validators", + "--node", chain.GetRPCAddress(), + "--chain-id", chain.Config().ChainID, + "--output", "json", + } + + stdout, _, err := chain.Exec(ctx, cmd, nil) + require.NoError(t, err) + + // print stdout + fmt.Println(string(stdout)) + + // put the stdout json into res + if err := json.Unmarshal(stdout, &res); err != nil { + t.Fatal(err) + } + + return res +} diff --git a/interchaintest/helpers/staking.go b/interchaintest/helpers/staking.go new file mode 100644 index 00000000..4a9e79d6 --- /dev/null +++ b/interchaintest/helpers/staking.go @@ -0,0 +1,55 @@ +package helpers + +import ( + "context" + "testing" + + "github.com/cosmos/cosmos-sdk/crypto/keyring" + "github.com/strangelove-ventures/interchaintest/v7/chain/cosmos" + "github.com/strangelove-ventures/interchaintest/v7/ibc" + "github.com/strangelove-ventures/interchaintest/v7/testutil" + "github.com/stretchr/testify/require" +) + +func StakeTokens(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, user ibc.Wallet, valoper, coinAmt string) { + // amount is #utoken + cmd := []string{"terpd", "tx", "staking", "delegate", valoper, coinAmt, + "--node", chain.GetRPCAddress(), + "--home", chain.HomeDir(), + "--chain-id", chain.Config().ChainID, + "--from", user.KeyName(), + "--gas", "500000", + "--keyring-dir", chain.HomeDir(), + "--keyring-backend", keyring.BackendTest, + "-y", + } + stdout, _, err := chain.Exec(ctx, cmd, nil) + require.NoError(t, err) + + debugOutput(t, string(stdout)) + + if err := testutil.WaitForBlocks(ctx, 2, chain); err != nil { + t.Fatal(err) + } +} + +func ClaimStakingRewards(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, user ibc.Wallet, valoper string) { + cmd := []string{"terpd", "tx", "distribution", "withdraw-rewards", valoper, + "--node", chain.GetRPCAddress(), + "--home", chain.HomeDir(), + "--chain-id", chain.Config().ChainID, + "--from", user.KeyName(), + "--gas", "500000", + "--keyring-dir", chain.HomeDir(), + "--keyring-backend", keyring.BackendTest, + "-y", + } + stdout, _, err := chain.Exec(ctx, cmd, nil) + require.NoError(t, err) + + debugOutput(t, string(stdout)) + + if err := testutil.WaitForBlocks(ctx, 2, chain); err != nil { + t.Fatal(err) + } +} diff --git a/interchaintest/module_burn_test.go b/interchaintest/module_burn_test.go deleted file mode 100644 index 936eeaf2..00000000 --- a/interchaintest/module_burn_test.go +++ /dev/null @@ -1,59 +0,0 @@ -package interchaintest - -import ( - "fmt" - "strconv" - "testing" - - "github.com/strangelove-ventures/interchaintest/v7" - "github.com/strangelove-ventures/interchaintest/v7/chain/cosmos" - "github.com/stretchr/testify/assert" - - helpers "github.com/terpnetwork/terp-core/tests/interchaintest/helpers" -) - -// TestTerpBurnModule ensures the terpburn module register and execute sharing functions work properly on smart contracts. -// It is purely for developers ::BurnTokens to function as expected. -func TestTerpBurnModule(t *testing.T) { - t.Parallel() - - // Base setup - chains := CreateThisBranchChain(t, 1, 0) - ic, ctx, _, _ := BuildInitialChain(t, chains) - - // Chains - terp := chains[0].(*cosmos.CosmosChain) - - nativeDenom := terp.Config().Denom - - // Users - users := interchaintest.GetAndFundTestUsers(t, ctx, "default", int64(10_000_000), terp, terp) - user := users[0] - - // Upload & init contract - _, contractAddr := helpers.SetupContract(t, ctx, terp, user.KeyName(), "contracts/cw_testburn.wasm", `{}`) - - // get balance before execute - balance, err := terp.GetBalance(ctx, user.FormattedAddress(), nativeDenom) - if err != nil { - t.Fatal(err) - } - - // execute burn of tokens - burnAmt := int64(1_000_000) - helpers.ExecuteMsgWithAmount(t, ctx, terp, user, contractAddr, strconv.Itoa(int(burnAmt))+nativeDenom, `{"burn_token":{}}`) - - // verify it is down 1_000_000 tokens since the burn - updatedBal, err := terp.GetBalance(ctx, user.FormattedAddress(), nativeDenom) - if err != nil { - t.Fatal(err) - } - - // Verify the funds were sent, and burned. - fmt.Println(balance, updatedBal) - assert.Equal(t, burnAmt, balance-updatedBal, fmt.Sprintf("balance should be %d less than updated balance", burnAmt)) - - t.Cleanup(func() { - _ = ic.Close() - }) -} diff --git a/interchaintest/module_clock_test.go b/interchaintest/module_clock_test.go index 1b2e5666..fc4b00d0 100644 --- a/interchaintest/module_clock_test.go +++ b/interchaintest/module_clock_test.go @@ -1,85 +1,85 @@ package interchaintest -// import ( -// "context" -// "fmt" -// "testing" +import ( + "context" + "fmt" + "testing" -// cosmosproto "github.com/cosmos/gogoproto/proto" -// "github.com/strangelove-ventures/interchaintest/v7" -// "github.com/strangelove-ventures/interchaintest/v7/chain/cosmos" -// "github.com/strangelove-ventures/interchaintest/v7/ibc" -// "github.com/strangelove-ventures/interchaintest/v7/testutil" -// "github.com/stretchr/testify/require" -// clocktypes "github.com/terpnetwork/terp-core/v4/x/clock/types" + cosmosproto "github.com/cosmos/gogoproto/proto" + "github.com/strangelove-ventures/interchaintest/v7" + "github.com/strangelove-ventures/interchaintest/v7/chain/cosmos" + "github.com/strangelove-ventures/interchaintest/v7/ibc" + "github.com/strangelove-ventures/interchaintest/v7/testutil" + "github.com/stretchr/testify/require" + clocktypes "github.com/terpnetwork/terp-core/v4/x/clock/types" -// helpers "github.com/terpnetwork/terp-core/tests/interchaintest/helpers" -// ) + helpers "github.com/terpnetwork/terp-core/tests/interchaintest/helpers" +) -// // TestJunoClock ensures the clock module auto executes allowed contracts. -// func TestTerpClock(t *testing.T) { -// t.Parallel() +// TestTerpClock ensures the clock module auto executes allowed contracts. +func TestTerpClock(t *testing.T) { + t.Parallel() -// cfg := terpConfig + cfg := terpConfig -// // Base setup -// chains := CreateChainWithCustomConfig(t, 1, 0, cfg) -// ic, ctx, _, _ := BuildInitialChain(t, chains) + // Base setup + chains := CreateChainWithCustomConfig(t, 1, 0, cfg) + ic, ctx, _, _ := BuildInitialChain(t, chains) -// // Chains -// terp := chains[0].(*cosmos.CosmosChain) + // Chains + terp := chains[0].(*cosmos.CosmosChain) -// // Users -// users := interchaintest.GetAndFundTestUsers(t, ctx, "default", int64(10_000_000_000), terp, terp) -// user := users[0] + // Users + users := interchaintest.GetAndFundTestUsers(t, ctx, "default", int64(10_000_000_000), terp, terp) + user := users[0] -// // Upload & init contract payment to another address -// _, contractAddr := helpers.SetupContract(t, ctx, terp, user.KeyName(), "contracts/clock_example.wasm", `{}`) + // Upload & init contract payment to another address + _, contractAddr := helpers.SetupContract(t, ctx, terp, user.KeyName(), "contracts/clock_example.wasm", `{}`) -// // Ensure config is 0 -// res := helpers.GetClockContractValue(t, ctx, terp, contractAddr) -// fmt.Printf("- res: %v\n", res.Data.Val) -// require.Equal(t, uint32(0), res.Data.Val) + // Ensure config is 0 + res := helpers.GetClockContractValue(t, ctx, terp, contractAddr) + fmt.Printf("- res: %v\n", res.Data.Val) + require.Equal(t, uint32(0), res.Data.Val) -// // Submit the proposal to add it to the allowed contracts list -// SubmitParamChangeProp(t, ctx, terp, user, []string{contractAddr}) + // Submit the proposal to add it to the allowed contracts list + SubmitParamChangeProp(t, ctx, terp, user, []string{contractAddr}) -// // Wait 1 block -// _ = testutil.WaitForBlocks(ctx, 1, terp) + // Wait 1 block + _ = testutil.WaitForBlocks(ctx, 1, terp) -// // Validate the contract is now auto incrementing from the end blocker -// res = helpers.GetClockContractValue(t, ctx, terp, contractAddr) -// fmt.Printf("- res: %v\n", res.Data.Val) -// require.GreaterOrEqual(t, res.Data.Val, uint32(1)) + // Validate the contract is now auto incrementing from the end blocker + res = helpers.GetClockContractValue(t, ctx, terp, contractAddr) + fmt.Printf("- res: %v\n", res.Data.Val) + require.GreaterOrEqual(t, res.Data.Val, uint32(1)) -// t.Cleanup(func() { -// _ = ic.Close() -// }) -// } + t.Cleanup(func() { + _ = ic.Close() + }) +} -// func SubmitParamChangeProp(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, user ibc.Wallet, contracts []string) string { -// govAcc := "terp10d07y265gmmuvt4z0w9aw880jnsr700jag6fuq" -// updateParams := []cosmosproto.Message{ -// &clocktypes.MsgUpdateParams{ -// Authority: govAcc, -// Params: clocktypes.NewParams(contracts, 1_000_000_000), -// }, -// } +func SubmitParamChangeProp(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, user ibc.Wallet, contracts []string) string { + govAcc := "terp10d07y265gmmuvt4z0w9aw880jnsr700jag6fuq" + updateParams := []cosmosproto.Message{ + &clocktypes.MsgUpdateParams{ + Authority: govAcc, + Params: clocktypes.NewParams(contracts, 1_000_000_000), + }, + } -// proposal, err := chain.BuildProposal(updateParams, "Params Add Contract", "params", "ipfs://CID", fmt.Sprintf(`500000000%s`, chain.Config().Denom)) -// require.NoError(t, err, "error building proposal") + proposal, err := chain.BuildProposal(updateParams, "Params Add Contract", "params", "ipfs://CID", fmt.Sprintf(`500000000%s`, chain.Config().Denom)) + require.NoError(t, err, "error building proposal") -// txProp, err := chain.SubmitProposal(ctx, user.KeyName(), proposal) -// t.Log("txProp", txProp) -// require.NoError(t, err, "error submitting proposal") + txProp, err := chain.SubmitProposal(ctx, user.KeyName(), proposal) + t.Log("txProp", txProp) + require.NoError(t, err, "error submitting proposal") -// height, _ := chain.Height(ctx) + height, _ := chain.Height(ctx) -// err = chain.VoteOnProposalAllValidators(ctx, txProp.ProposalID, cosmos.ProposalVoteYes) -// require.NoError(t, err, "failed to submit votes") + err = chain.VoteOnProposalAllValidators(ctx, txProp.ProposalID, cosmos.ProposalVoteYes) + require.NoError(t, err, "failed to submit votes") -// _, err = cosmos.PollForProposalStatus(ctx, chain, height, height+haltHeightDelta, txProp.ProposalID, cosmos.ProposalStatusPassed) -// require.NoError(t, err, "proposal status did not change to passed in expected number of blocks") + _, err = cosmos.PollForProposalStatus(ctx, chain, height, height+haltHeightDelta, txProp.ProposalID, cosmos.ProposalStatusPassed) + require.NoError(t, err, "proposal status did not change to passed in expected number of blocks") -// return txProp.ProposalID -// } + return txProp.ProposalID +} diff --git a/interchaintest/module_drip_test.go b/interchaintest/module_drip_test.go new file mode 100644 index 00000000..483273f3 --- /dev/null +++ b/interchaintest/module_drip_test.go @@ -0,0 +1,85 @@ +package interchaintest + +import ( + "fmt" + "testing" + + "github.com/strangelove-ventures/interchaintest/v7" + "github.com/strangelove-ventures/interchaintest/v7/chain/cosmos" + + helpers "github.com/terpnetwork/terp-core/tests/interchaintest/helpers" +) + +// TestJunoDrip ensures the drip module properly distributes tokens from whitelisted accounts. +func TestTerpDrip(t *testing.T) { + t.Parallel() + + // Setup new pre determined user (from test_node.sh) + mnemonic := "decorate bright ozone fork gallery riot bus exhaust worth way bone indoor calm squirrel merry zero scheme cotton until shop any excess stage laundry" + addr := "terp1hj5fveer5cjtn4wd6wstzugjfdxzl0xppxm7xs" + + // Base setup + newCfg := terpConfig + newCfg.ModifyGenesis = cosmos.ModifyGenesis(append(defaultGenesisKV, []cosmos.GenesisKV{ + { + Key: "app_state.drip.params.allowed_addresses", + Value: []string{addr}, + }, + }...)) + + chains := CreateChainWithCustomConfig(t, 1, 0, newCfg) + ic, ctx, _, _ := BuildInitialChain(t, chains) + + // Chains + terp := chains[0].(*cosmos.CosmosChain) + nativeDenom := terp.Config().Denom + + // User + user, err := interchaintest.GetAndFundTestUserWithMnemonic(ctx, "default", mnemonic, int64(1000000_000_000), terp) + if err != nil { + t.Fatal(err) + } + + // New TF token to distributes + tfDenom := helpers.CreateTokenFactoryDenom(t, ctx, terp, user, "dripme", fmt.Sprintf("0%s", Denom)) + distributeAmt := uint64(1_000_000) + helpers.MintTokenFactoryDenom(t, ctx, terp, user, distributeAmt, tfDenom) + if balance, err := terp.GetBalance(ctx, user.FormattedAddress(), tfDenom); err != nil { + t.Fatal(err) + } else if uint64(balance) != distributeAmt { + t.Fatalf("balance not %d, got %d", distributeAmt, balance) + } + + // Stake some tokens + vals := helpers.GetValidators(t, ctx, terp) + valoper := vals.Validators[0].OperatorAddress + + stakeAmt := 100000_000_000 + helpers.StakeTokens(t, ctx, terp, user, valoper, fmt.Sprintf("%d%s", stakeAmt, nativeDenom)) + + // Drip the TF Tokens to all stakers + distribute := int64(1_000_000) + helpers.DripTokens(t, ctx, terp, user, fmt.Sprintf("%d%s", distribute, tfDenom)) + + // Claim staking rewards to capture the drip + helpers.ClaimStakingRewards(t, ctx, terp, user, valoper) + + // Check balances has the TF Denom from the claim + bals, _ := terp.AllBalances(ctx, user.FormattedAddress()) + fmt.Println("balances", bals) + + found := false + for _, bal := range bals { + if bal.Denom == tfDenom { + found = true + break + } + } + if !found { + t.Fatal("did not find drip token") + } + + t.Cleanup(func() { + _ = ic.Close() + }) +} diff --git a/interchaintest/setup.go b/interchaintest/setup.go index ea479a89..b4eadfca 100644 --- a/interchaintest/setup.go +++ b/interchaintest/setup.go @@ -15,7 +15,7 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/zap/zaptest" - // clocktypes "github.com/terpnetwork/terp-core/v4/x/clock/types" + clocktypes "github.com/terpnetwork/terp-core/v4/x/clock/types" feesharetypes "github.com/terpnetwork/terp-core/v4/x/feeshare/types" tokenfactorytypes "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types" @@ -94,7 +94,7 @@ func terpEncoding() *testutil.TestEncodingConfig { wasmtypes.RegisterInterfaces(cfg.InterfaceRegistry) feesharetypes.RegisterInterfaces(cfg.InterfaceRegistry) tokenfactorytypes.RegisterInterfaces(cfg.InterfaceRegistry) - // clocktypes.RegisterInterfaces(cfg.InterfaceRegistry) + clocktypes.RegisterInterfaces(cfg.InterfaceRegistry) // github.com/cosmos/cosmos-sdk/types/module/testutil diff --git a/proto/terp/drip/v1/genesis.proto b/proto/terp/drip/v1/genesis.proto new file mode 100644 index 00000000..4075e137 --- /dev/null +++ b/proto/terp/drip/v1/genesis.proto @@ -0,0 +1,20 @@ +syntax = "proto3"; +package terp.drip.v1; + +import "gogoproto/gogo.proto"; +option go_package = "github.com/terpnetwork/terp-core/x/drip/types"; + +// GenesisState defines the module's genesis state. +message GenesisState { + // params are the drip module parameters + Params params = 1 [ (gogoproto.nullable) = false ]; +} + +// Params defines the drip module params +message Params { + // enable_drip defines a parameter to enable the drip module + bool enable_drip = 1; + + // allowed_addresses defines the list of addresses authorized to use the module + repeated string allowed_addresses = 3 [ (gogoproto.moretags) = "yaml:\"addresses\"" ]; +} diff --git a/proto/terp/drip/v1/query.proto b/proto/terp/drip/v1/query.proto new file mode 100644 index 00000000..4a901d99 --- /dev/null +++ b/proto/terp/drip/v1/query.proto @@ -0,0 +1,27 @@ +syntax = "proto3"; +package terp.drip.v1; + +import "cosmos/base/query/v1beta1/pagination.proto"; +import "terp/drip/v1/genesis.proto"; +import "gogoproto/gogo.proto"; +import "google/api/annotations.proto"; + +option go_package = "github.com/terpnetwork/terp-core/x/drip/types"; + +// Query defines the gRPC querier service. +service Query { + + // Params retrieves the Drip module params + rpc Params(QueryParamsRequest) returns (QueryParamsResponse) { + option (google.api.http).get = "/terp/drip/v1/params"; + } + +} +// QueryParamsRequest is the request type for the Query/Params RPC method. +message QueryParamsRequest {} + +// QueryParamsResponse is the response type for the Query/Params RPC method. +message QueryParamsResponse { + // params is the returned parameter from the module + Params params = 1 [ (gogoproto.nullable) = false ]; +} diff --git a/proto/terp/drip/v1/tx.proto b/proto/terp/drip/v1/tx.proto new file mode 100644 index 00000000..0f305bf3 --- /dev/null +++ b/proto/terp/drip/v1/tx.proto @@ -0,0 +1,59 @@ +syntax = "proto3"; +package terp.drip.v1; + +import "gogoproto/gogo.proto"; +import "google/api/annotations.proto"; +import "amino/amino.proto"; +import "cosmos/base/v1beta1/coin.proto"; +import "cosmos/msg/v1/msg.proto"; +import "cosmos_proto/cosmos.proto"; +import "terp/drip/v1/genesis.proto"; + +option go_package = "github.com/terpnetwork/terp-core/x/drip/types"; + +// Msg defines the fees Msg service. +service Msg { + // DistributeTokens distribute the sent tokens to all stakers in the next block + rpc DistributeTokens(MsgDistributeTokens) + returns (MsgDistributeTokensResponse) { + option (google.api.http).post = "/terp/drip/v1/tx/distribute_tokens"; + }; + + rpc UpdateParams(MsgUpdateParams) returns (MsgUpdateParamsResponse); +} + +// MsgDistributeTokens defines a message that registers a Distribution of tokens. +message MsgDistributeTokens { + option (gogoproto.equal) = false; + // sender_address is the bech32 address of message sender. + string sender_address = 1; + + // amount is the amount being airdropped to stakers + repeated cosmos.base.v1beta1.Coin amount = 2 [ + (gogoproto.nullable) = false, + (amino.dont_omitempty) = true, + (amino.encoding) = "legacy_coins", + (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins" + ]; +} + +// MsgDistributeTokensResponse defines the MsgDistributeTokens response type +message MsgDistributeTokensResponse {} + +// MsgUpdateParams is the Msg/UpdateParams request type. +// +// Since: cosmos-sdk 0.47 +message MsgUpdateParams { + option (cosmos.msg.v1.signer) = "authority"; + option (amino.name) = "cosmos-sdk/x/auth/MsgUpdateParams"; + + // authority is the address that controls the module (defaults to x/gov unless overwritten). + string authority = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + + // params defines the x/auth parameters to update. + // + // NOTE: All parameters must be supplied. + Params params = 2 [(gogoproto.nullable) = false, (amino.dont_omitempty) = true]; +} + +message MsgUpdateParamsResponse {} diff --git a/x/burn/README.md b/x/burn/README.md deleted file mode 100644 index dab52c38..00000000 --- a/x/burn/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# x/burn - -This is a 'module' used solely to burn tokens properly in line with our x/mint module requirements. - -## Burn address - -- diff --git a/x/burn/burner.go b/x/burn/burner.go deleted file mode 100644 index 97ce3a5f..00000000 --- a/x/burn/burner.go +++ /dev/null @@ -1,50 +0,0 @@ -package burn - -import ( - wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" - - sdk "github.com/cosmos/cosmos-sdk/types" - bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" - - mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper" -) - -// used to override Wasmd's NewBurnCoinMessageHandler - -type BurnerWasmPlugin struct { - bk bankkeeper.Keeper - mk mintkeeper.Keeper -} - -var _ wasmtypes.Burner = &BurnerWasmPlugin{} - -func NewBurnerPlugin(bk bankkeeper.Keeper, mk mintkeeper.Keeper) *BurnerWasmPlugin { - return &BurnerWasmPlugin{bk: bk, mk: mk} -} - -func (k *BurnerWasmPlugin) BurnCoins(ctx sdk.Context, _ string, amt sdk.Coins) error { - // first, try to burn the coins on bank module - err := k.bk.BurnCoins(ctx, ModuleName, amt) - if err != nil { - return err - } - - // get mint params - // params := k.mk.GetParams(ctx) - - // // loop the burned coins - // for _, amount := range amt { - // // if we are burning mint denom, reduce the target staking supply - // if amount.Denom == params.MintDenom { - // if err := k.mk.ReduceTargetSupply(ctx, amount); err != nil { - // return err - // } - // } - // } - - return nil -} - -func (k *BurnerWasmPlugin) SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, _ string, amt sdk.Coins) error { - return k.bk.SendCoinsFromAccountToModule(ctx, senderAddr, ModuleName, amt) -} diff --git a/x/burn/constants.go b/x/burn/constants.go deleted file mode 100644 index 8dc829fd..00000000 --- a/x/burn/constants.go +++ /dev/null @@ -1,5 +0,0 @@ -package burn - -const ( - ModuleName = "burner" -) diff --git a/x/clock/README.md b/x/clock/README.md new file mode 100644 index 00000000..ba05f64b --- /dev/null +++ b/x/clock/README.md @@ -0,0 +1,5 @@ +# Clock + +This module allows smart contracts to execute logic at the end of every block without an external bot. + +[Clock Spec](./spec/README.md) diff --git a/x/clock/abci.go b/x/clock/abci.go new file mode 100644 index 00000000..cfc10caf --- /dev/null +++ b/x/clock/abci.go @@ -0,0 +1,42 @@ +package clock + +import ( + "log" + "time" + + "github.com/cosmos/cosmos-sdk/telemetry" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/terpnetwork/terp-core/v4/x/clock/keeper" + "github.com/terpnetwork/terp-core/v4/x/clock/types" +) + +// EndBlocker executes on contracts at the end of the block. +func EndBlocker(ctx sdk.Context, k keeper.Keeper) { + defer telemetry.ModuleMeasureSince(types.ModuleName, time.Now(), telemetry.MetricKeyEndBlocker) + + message := []byte(types.EndBlockSudoMessage) + + p := k.GetParams(ctx) + + errorExecs := make([]string, len(p.ContractAddresses)) + + for idx, addr := range p.ContractAddresses { + contract, err := sdk.AccAddressFromBech32(addr) + if err != nil { + errorExecs[idx] = addr + continue + } + + childCtx := ctx.WithGasMeter(sdk.NewGasMeter(p.ContractGasLimit)) + _, err = k.GetContractKeeper().Sudo(childCtx, contract, message) + if err != nil { + errorExecs[idx] = addr + continue + } + } + + if len(errorExecs) > 0 { + log.Printf("[x/clock] Execute Errors: %v", errorExecs) + } +} diff --git a/x/clock/client/cli/query.go b/x/clock/client/cli/query.go new file mode 100644 index 00000000..b3f1121b --- /dev/null +++ b/x/clock/client/cli/query.go @@ -0,0 +1,73 @@ +package cli + +import ( + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + + "github.com/terpnetwork/terp-core/v4/x/clock/types" +) + +func GetQueryCmd() *cobra.Command { + queryCmd := &cobra.Command{ + Use: types.ModuleName, + Short: "Querying commands for cosmwasm modules", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + queryCmd.AddCommand( + GetCmdShowContracts(), + GetCmdParams(), + ) + return queryCmd +} + +func GetCmdShowContracts() *cobra.Command { + cmd := &cobra.Command{ + Use: "contracts", + Short: "Show addresses of all current contract modules", + 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.ClockContracts(cmd.Context(), &types.QueryClockContracts{}) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + flags.AddQueryFlagsToCmd(cmd) + return cmd +} + +func GetCmdParams() *cobra.Command { + cmd := &cobra.Command{ + Use: "params", + Short: "Show all module params", + 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.Params(cmd.Context(), &types.QueryParamsRequest{}) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + flags.AddQueryFlagsToCmd(cmd) + return cmd +} diff --git a/x/clock/genesis.go b/x/clock/genesis.go new file mode 100644 index 00000000..3d251871 --- /dev/null +++ b/x/clock/genesis.go @@ -0,0 +1,61 @@ +package clock + +import ( + "encoding/json" + + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/terpnetwork/terp-core/v4/x/clock/keeper" + "github.com/terpnetwork/terp-core/v4/x/clock/types" +) + +// NewGenesisState - Create a new genesis state +func NewGenesisState(params types.Params) *types.GenesisState { + return &types.GenesisState{ + Params: params, + } +} + +// DefaultGenesisState - Return a default genesis state +func DefaultGenesisState() *types.GenesisState { + return NewGenesisState(types.DefaultParams()) +} + +// GetGenesisStateFromAppState returns x/auth GenesisState given raw application +// genesis state. +func GetGenesisStateFromAppState(cdc codec.Codec, appState map[string]json.RawMessage) *types.GenesisState { + var genesisState types.GenesisState + + if appState[ModuleName] != nil { + cdc.MustUnmarshalJSON(appState[ModuleName], &genesisState) + } + + return &genesisState +} + +func ValidateGenesis(data types.GenesisState) error { + return data.Params.Validate() +} + +// InitGenesis import module genesis +func InitGenesis( + ctx sdk.Context, + k keeper.Keeper, + data types.GenesisState, +) { + if err := ValidateGenesis(data); err != nil { + panic(err) + } + + if err := k.SetParams(ctx, data.Params); err != nil { + panic(err) + } +} + +// ExportGenesis export module state +func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState { + return &types.GenesisState{ + Params: k.GetParams(ctx), + } +} diff --git a/x/clock/genesis_test.go b/x/clock/genesis_test.go new file mode 100644 index 00000000..fbbaa015 --- /dev/null +++ b/x/clock/genesis_test.go @@ -0,0 +1,107 @@ +package clock_test + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/suite" + + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" + + "github.com/cosmos/cosmos-sdk/testutil/testdata" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/terpnetwork/terp-core/v4/app" + clock "github.com/terpnetwork/terp-core/v4/x/clock" + "github.com/terpnetwork/terp-core/v4/x/clock/types" +) + +type GenesisTestSuite struct { + suite.Suite + + ctx sdk.Context + + app *app.TerpApp +} + +func TestGenesisTestSuite(t *testing.T) { + suite.Run(t, new(GenesisTestSuite)) +} + +func (suite *GenesisTestSuite) SetupTest() { + app := app.Setup(suite.T()) + ctx := app.BaseApp.NewContext(false, tmproto.Header{ + ChainID: "testing", + }) + + suite.app = app + suite.ctx = ctx +} + +func (suite *GenesisTestSuite) TestClockInitGenesis() { + _, _, addr := testdata.KeyTestPubAddr() + _, _, addr2 := testdata.KeyTestPubAddr() + + defaultParams := types.DefaultParams() + + testCases := []struct { + name string + genesis types.GenesisState + expPanic bool + }{ + { + "default genesis", + *clock.DefaultGenesisState(), + false, + }, + { + "custom genesis - none", + types.GenesisState{ + Params: types.Params{ + ContractAddresses: []string(nil), + ContractGasLimit: defaultParams.ContractGasLimit, + }, + }, + false, + }, + { + "custom genesis - incorrect addr", + types.GenesisState{ + Params: types.Params{ + ContractAddresses: []string{"incorrectaddr"}, + ContractGasLimit: defaultParams.ContractGasLimit, + }, + }, + true, + }, + { + "custom genesis - only one addr allowed", + types.GenesisState{ + Params: types.Params{ + ContractAddresses: []string{addr.String(), addr2.String()}, + ContractGasLimit: defaultParams.ContractGasLimit, + }, + }, + false, + }, + } + + for _, tc := range testCases { + suite.Run(fmt.Sprintf("Case %s", tc.name), func() { + suite.SetupTest() // reset + + if tc.expPanic { + suite.Require().Panics(func() { + clock.InitGenesis(suite.ctx, suite.app.AppKeepers.ClockKeeper, tc.genesis) + }) + } else { + suite.Require().NotPanics(func() { + clock.InitGenesis(suite.ctx, suite.app.AppKeepers.ClockKeeper, tc.genesis) + }) + + params := suite.app.AppKeepers.ClockKeeper.GetParams(suite.ctx) + suite.Require().Equal(tc.genesis.Params, params) + } + }) + } +} diff --git a/x/clock/keeper/keeper.go b/x/clock/keeper/keeper.go new file mode 100644 index 00000000..757cd4c1 --- /dev/null +++ b/x/clock/keeper/keeper.go @@ -0,0 +1,70 @@ +package keeper + +import ( + wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" + + "github.com/cosmos/cosmos-sdk/codec" + storetypes "github.com/cosmos/cosmos-sdk/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/terpnetwork/terp-core/v4/x/clock/types" +) + +// Keeper of the clock store +type Keeper struct { + storeKey storetypes.StoreKey + cdc codec.BinaryCodec + + contractKeeper wasmkeeper.PermissionedKeeper + + authority string +} + +func NewKeeper( + key storetypes.StoreKey, + cdc codec.BinaryCodec, + contractKeeper wasmkeeper.PermissionedKeeper, + authority string, +) Keeper { + return Keeper{ + cdc: cdc, + storeKey: key, + contractKeeper: contractKeeper, + authority: authority, + } +} + +// GetAuthority returns the x/clock module's authority. +func (k Keeper) GetAuthority() string { + return k.authority +} + +// SetParams sets the x/clock module parameters. +func (k Keeper) SetParams(ctx sdk.Context, p types.Params) error { + if err := p.Validate(); err != nil { + return err + } + + store := ctx.KVStore(k.storeKey) + bz := k.cdc.MustMarshal(&p) + store.Set(types.ParamsKey, bz) + + return nil +} + +// GetParams returns the current x/clock module parameters. +func (k Keeper) GetParams(ctx sdk.Context) (p types.Params) { + store := ctx.KVStore(k.storeKey) + bz := store.Get(types.ParamsKey) + if bz == nil { + return p + } + + k.cdc.MustUnmarshal(bz, &p) + return p +} + +// GetContractKeeper returns the x/wasm module's contract keeper. +func (k Keeper) GetContractKeeper() wasmkeeper.PermissionedKeeper { + return k.contractKeeper +} diff --git a/x/clock/keeper/keeper_test.go b/x/clock/keeper/keeper_test.go new file mode 100644 index 00000000..6041d955 --- /dev/null +++ b/x/clock/keeper/keeper_test.go @@ -0,0 +1,59 @@ +package keeper_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/suite" + + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" + + "github.com/cosmos/cosmos-sdk/baseapp" + sdk "github.com/cosmos/cosmos-sdk/types" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" + + "github.com/terpnetwork/terp-core/v4/app" + "github.com/terpnetwork/terp-core/v4/x/clock/keeper" + "github.com/terpnetwork/terp-core/v4/x/clock/types" +) + +type IntegrationTestSuite struct { + suite.Suite + + ctx sdk.Context + app *app.TerpApp + bankKeeper bankkeeper.Keeper + queryClient types.QueryClient + clockMsgServer types.MsgServer +} + +func (s *IntegrationTestSuite) SetupTest() { + isCheckTx := false + s.app = app.Setup(s.T()) + + s.ctx = s.app.BaseApp.NewContext(isCheckTx, tmproto.Header{ + ChainID: "testing", + Height: 1, + Time: time.Now().UTC(), + }) + + queryHelper := baseapp.NewQueryServerTestHelper(s.ctx, s.app.InterfaceRegistry()) + types.RegisterQueryServer(queryHelper, keeper.NewQuerier(s.app.AppKeepers.ClockKeeper)) + + s.queryClient = types.NewQueryClient(queryHelper) + s.bankKeeper = s.app.AppKeepers.BankKeeper + s.clockMsgServer = keeper.NewMsgServerImpl(s.app.AppKeepers.ClockKeeper) +} + +func (s *IntegrationTestSuite) FundAccount(ctx sdk.Context, addr sdk.AccAddress, amounts sdk.Coins) error { + if err := s.bankKeeper.MintCoins(ctx, minttypes.ModuleName, amounts); err != nil { + return err + } + + return s.bankKeeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, addr, amounts) +} + +func TestKeeperTestSuite(t *testing.T) { + suite.Run(t, new(IntegrationTestSuite)) +} diff --git a/x/clock/keeper/msg_server.go b/x/clock/keeper/msg_server.go new file mode 100644 index 00000000..78543509 --- /dev/null +++ b/x/clock/keeper/msg_server.go @@ -0,0 +1,39 @@ +package keeper + +import ( + "context" + + errorsmod "cosmossdk.io/errors" + + sdk "github.com/cosmos/cosmos-sdk/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + + "github.com/terpnetwork/terp-core/v4/x/clock/types" +) + +var _ types.MsgServer = &msgServer{} + +// msgServer is a wrapper of Keeper. +type msgServer struct { + Keeper +} + +// NewMsgServerImpl returns an implementation of the x/clock MsgServer interface. +func NewMsgServerImpl(k Keeper) types.MsgServer { + return &msgServer{ + Keeper: k, + } +} + +func (k msgServer) UpdateParams(goCtx context.Context, req *types.MsgUpdateParams) (*types.MsgUpdateParamsResponse, error) { + if k.authority != req.Authority { + return nil, errorsmod.Wrapf(govtypes.ErrInvalidSigner, "invalid authority; expected %s, got %s", k.authority, req.Authority) + } + + ctx := sdk.UnwrapSDKContext(goCtx) + if err := k.SetParams(ctx, req.Params); err != nil { + return nil, err + } + + return &types.MsgUpdateParamsResponse{}, nil +} diff --git a/x/clock/keeper/msg_server_test.go b/x/clock/keeper/msg_server_test.go new file mode 100644 index 00000000..26c0513e --- /dev/null +++ b/x/clock/keeper/msg_server_test.go @@ -0,0 +1,72 @@ +package keeper_test + +import ( + _ "embed" + + "github.com/cosmos/cosmos-sdk/testutil/testdata" + + "github.com/terpnetwork/terp-core/v4/x/clock/types" +) + +func (s *IntegrationTestSuite) TestUpdateClockParams() { + _, _, addr := testdata.KeyTestPubAddr() + _, _, addr2 := testdata.KeyTestPubAddr() + + for _, tc := range []struct { + desc string + isEnabled bool + ContractAddresses []string + success bool + }{ + { + desc: "Success - Valid on", + isEnabled: true, + ContractAddresses: []string{}, + success: true, + }, + { + desc: "Success - Valid off", + isEnabled: false, + ContractAddresses: []string{}, + success: true, + }, + { + desc: "Success - On and 1 allowed address", + isEnabled: true, + ContractAddresses: []string{addr.String()}, + success: true, + }, + { + desc: "Fail - On and 2 duplicate addresses", + isEnabled: true, + ContractAddresses: []string{addr.String(), addr.String()}, + success: false, + }, + { + desc: "Success - On and 2 unique", + isEnabled: true, + ContractAddresses: []string{addr.String(), addr2.String()}, + success: true, + }, + { + desc: "Success - On and 2 duplicate 1 unique", + isEnabled: true, + ContractAddresses: []string{addr.String(), addr2.String(), addr.String()}, + success: false, + }, + } { + tc := tc + s.Run(tc.desc, func() { + params := types.DefaultParams() + params.ContractAddresses = tc.ContractAddresses + + err := s.app.AppKeepers.ClockKeeper.SetParams(s.ctx, params) + + if !tc.success { + s.Require().Error(err) + } else { + s.Require().NoError(err) + } + }) + } +} diff --git a/x/clock/keeper/querier.go b/x/clock/keeper/querier.go new file mode 100644 index 00000000..75f9d566 --- /dev/null +++ b/x/clock/keeper/querier.go @@ -0,0 +1,43 @@ +package keeper + +import ( + "context" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/terpnetwork/terp-core/v4/x/clock/types" +) + +var _ types.QueryServer = &Querier{} + +type Querier struct { + keeper Keeper +} + +func NewQuerier(k Keeper) Querier { + return Querier{ + keeper: k, + } +} + +// ContractModules returns contract addresses which are using the clock +func (q Querier) ClockContracts(stdCtx context.Context, _ *types.QueryClockContracts) (*types.QueryClockContractsResponse, error) { + ctx := sdk.UnwrapSDKContext(stdCtx) + + p := q.keeper.GetParams(ctx) + + return &types.QueryClockContractsResponse{ + ContractAddresses: p.ContractAddresses, + }, nil +} + +// Params returns the total set of clock parameters. +func (q Querier) Params(stdCtx context.Context, _ *types.QueryParamsRequest) (*types.QueryParamsResponse, error) { + ctx := sdk.UnwrapSDKContext(stdCtx) + + p := q.keeper.GetParams(ctx) + + return &types.QueryParamsResponse{ + Params: &p, + }, nil +} diff --git a/x/clock/keeper/querier_test.go b/x/clock/keeper/querier_test.go new file mode 100644 index 00000000..6a38f4ad --- /dev/null +++ b/x/clock/keeper/querier_test.go @@ -0,0 +1,60 @@ +package keeper_test + +import ( + "github.com/cosmos/cosmos-sdk/testutil/testdata" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/terpnetwork/terp-core/v4/x/clock/types" +) + +func (s *IntegrationTestSuite) TestClockQueryParams() { + _, _, addr := testdata.KeyTestPubAddr() + _, _, addr2 := testdata.KeyTestPubAddr() + + defaultParams := types.DefaultParams() + + for _, tc := range []struct { + desc string + Expected types.Params + }{ + { + desc: "On empty", + Expected: types.Params{ + ContractAddresses: []string(nil), + ContractGasLimit: defaultParams.ContractGasLimit, + }, + }, + { + desc: "On 1 address", + Expected: types.Params{ + ContractAddresses: []string{addr.String()}, + ContractGasLimit: defaultParams.ContractGasLimit, + }, + }, + { + desc: "On 2 Unique", + Expected: types.Params{ + ContractAddresses: []string{addr.String(), addr2.String()}, + ContractGasLimit: defaultParams.ContractGasLimit, + }, + }, + } { + tc := tc + s.Run(tc.desc, func() { + // Set the params to what is expected, then query and ensure the query is the same + err := s.app.AppKeepers.ClockKeeper.SetParams(s.ctx, tc.Expected) + s.Require().NoError(err) + + // Contracts check + goCtx := sdk.WrapSDKContext(s.ctx) + resp, err := s.queryClient.ClockContracts(goCtx, &types.QueryClockContracts{}) + s.Require().NoError(err) + s.Require().Equal(tc.Expected.ContractAddresses, resp.ContractAddresses) + + // All Params Check + resp2, err := s.queryClient.Params(goCtx, &types.QueryParamsRequest{}) + s.Require().NoError(err) + s.Require().Equal(tc.Expected, *resp2.Params) + }) + } +} diff --git a/x/clock/module.go b/x/clock/module.go new file mode 100644 index 00000000..a1f376c9 --- /dev/null +++ b/x/clock/module.go @@ -0,0 +1,149 @@ +package clock + +import ( + "context" + "encoding/json" + + "github.com/gorilla/mux" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/spf13/cobra" + + abci "github.com/cometbft/cometbft/abci/types" + + errorsmod "cosmossdk.io/errors" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + + "github.com/terpnetwork/terp-core/v4/x/clock/client/cli" + "github.com/terpnetwork/terp-core/v4/x/clock/keeper" + "github.com/terpnetwork/terp-core/v4/x/clock/types" +) + +const ( + ModuleName = types.ModuleName + + // ConsensusVersion defines the current x/clock module consensus version. + ConsensusVersion = 1 +) + +var ( + _ module.AppModuleBasic = AppModuleBasic{} + _ module.AppModuleGenesis = AppModule{} + _ module.AppModule = AppModule{} +) + +// AppModuleBasic defines the basic application module used by the wasm module. +type AppModuleBasic struct { + cdc codec.Codec +} + +func (a AppModuleBasic) Name() string { + return types.ModuleName +} + +func (a AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage { + return cdc.MustMarshalJSON(&types.GenesisState{ + Params: types.DefaultParams(), + }) +} + +func (a AppModuleBasic) ValidateGenesis(marshaler codec.JSONCodec, _ client.TxEncodingConfig, message json.RawMessage) error { + var data types.GenesisState + err := marshaler.UnmarshalJSON(message, &data) + if err != nil { + return err + } + if err := data.Params.Validate(); err != nil { + return errorsmod.Wrap(err, "params") + } + return nil +} + +func (a AppModuleBasic) RegisterRESTRoutes(_ client.Context, _ *mux.Router) { +} + +func (a AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) { + err := types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx)) + if err != nil { + // same behavior as in cosmos-sdk + panic(err) + } +} + +func (a AppModuleBasic) GetTxCmd() *cobra.Command { + return nil +} + +func (a AppModuleBasic) GetQueryCmd() *cobra.Command { + return cli.GetQueryCmd() +} + +func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + types.RegisterLegacyAminoCodec(cdc) +} + +func (a AppModuleBasic) RegisterInterfaces(r codectypes.InterfaceRegistry) { + types.RegisterInterfaces(r) +} + +type AppModule struct { + AppModuleBasic + + keeper keeper.Keeper +} + +// NewAppModule constructor +func NewAppModule( + cdc codec.Codec, + keeper keeper.Keeper, +) *AppModule { + return &AppModule{ + AppModuleBasic: AppModuleBasic{cdc: cdc}, + keeper: keeper, + } +} + +func (a AppModule) InitGenesis(ctx sdk.Context, marshaler codec.JSONCodec, message json.RawMessage) []abci.ValidatorUpdate { + var genesisState types.GenesisState + marshaler.MustUnmarshalJSON(message, &genesisState) + _ = a.keeper.SetParams(ctx, genesisState.Params) + return nil +} + +func (a AppModule) ExportGenesis(ctx sdk.Context, marshaler codec.JSONCodec) json.RawMessage { + params := a.keeper.GetParams(ctx) + genState := NewGenesisState(params) + return marshaler.MustMarshalJSON(genState) +} + +func (a AppModule) RegisterInvariants(_ sdk.InvariantRegistry) { +} + +func (a AppModule) QuerierRoute() string { + return types.QuerierRoute +} + +func (a AppModule) RegisterServices(cfg module.Configurator) { + types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(a.keeper)) + types.RegisterQueryServer(cfg.QueryServer(), keeper.NewQuerier(a.keeper)) +} + +func (a AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) { +} + +func (a AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate { + EndBlocker(ctx, a.keeper) + return nil +} + +// ConsensusVersion is a sequence number for state-breaking change of the +// module. It should be incremented on each consensus-breaking change +// introduced by the module. To avoid wrong/empty versions, the initial version +// should be set to 1. +func (a AppModule) ConsensusVersion() uint64 { + return ConsensusVersion +} diff --git a/x/clock/spec/01_authorization.md b/x/clock/spec/01_authorization.md new file mode 100644 index 00000000..30ccca13 --- /dev/null +++ b/x/clock/spec/01_authorization.md @@ -0,0 +1,39 @@ +# Authorization + +For security purposes, only the governance module can add new contracts to the EndBlocker executes. + +## Query contracts + +You can query the list of contracts that are 'ticked' every block with the following command: + +```bash + terpd q clock contracts --output json + # {"contract_addresses":[]} +``` + +## Governance proposal + +To update the authorized address is possible to create an onchain new proposal. You can use the following example `proposal.json` file + +```json +{ + "messages": [ + { + "@type": "/terp.clock.v1.MsgUpdateParams", + "authority": "terp10d07y265gmmuvt4z0w9aw880jnsr700jag6fuq", + "params": { + "contract_addresses": [ + "terp14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9skqhzr5" + ], + "contract_gas_limit": "1000000" + } + } + ], + "metadata": "{\"title\": \"Allow a new contract to use the x/clock module for our features\", \"authors\": [\"Reece\"], \"summary\": \"If this proposal passes terp14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9skqhzr5 will be added to the authorized addresses of the clock module\", \"details\": \"If this proposal passes terp14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9skqhzr5 will be added to the authorized addresses of the clock module\", \"proposal_forum_url\": \"https://commonwealth.im/terp-network/discussion/\", \"vote_option_context\": \"yes\"}", + "deposit": "1000000uterp", + "title": "Allow a new contract to use the x/clock module for our features", + "summary": "If this proposal passes terp14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9skqhzr5 will be allowed to use the x/clock module to perform XYZ actions" +} +``` + +It can be submitted with the standard `terpd tx gov submit-proposal proposal.json --from=YOURKEY` command. diff --git a/x/clock/spec/02_integration.md b/x/clock/spec/02_integration.md new file mode 100644 index 00000000..fa764633 --- /dev/null +++ b/x/clock/spec/02_integration.md @@ -0,0 +1,56 @@ +# CosmWasm Integration + +This module does not require any custom bindings. Rather, you must just add the following Sudo message to your contract. If your contract is not whitelisted, you can still upload it to the chain. However, to get it to execute, you must submit a proposal to add your contract to the whitelist. + +You can find a basic [cw-clock contract here](https://github.com/Reecepbcups/cw-clock-example) + +## Implementation + +Add the following to your Rust Contract: + +```rust +// msg.rs +#[cw_serde] +pub enum SudoMsg { + ClockEndBlock { }, +} + +// contract.rs +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn sudo(deps: DepsMut, _env: Env, msg: SudoMsg) -> Result { + match msg { + SudoMsg::ClockEndBlock { } => { + let mut config = CONFIG.load(deps.storage)?; + config.val += 1; + CONFIG.save(deps.storage, &config)?; + + Ok(Response::new()) + } + } +} +``` + +Using the above example, for every block the module will increase the `val` Config variable by 1. This is a simple example, but you can use this to perform any action you want (ex: cleanup, auto compounding, etc). + +If you wish not to have your action performed every block, you can use the `env` variable in the Sudo message to check the block height and only perform an action every X blocks. + +```rust +// contract.rs +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn sudo(deps: DepsMut, env: Env, msg: SudoMsg) -> Result { + match msg { + SudoMsg::ClockEndBlock { } => { + // If the block is not divisible by ten, do nothing. + if env.block.height % 10 != 0 { + return Ok(Response::new()); + } + + let mut config = CONFIG.load(deps.storage)?; + config.val += 1; + CONFIG.save(deps.storage, &config)?; + + Ok(Response::new()) + } + } +} +``` diff --git a/x/clock/spec/README.md b/x/clock/spec/README.md new file mode 100644 index 00000000..982d7ec3 --- /dev/null +++ b/x/clock/spec/README.md @@ -0,0 +1,14 @@ +# `clock` + +## Abstract + +This document specifies the internal `x/clock` module of Juno Network. + +The `x/clock` module allows specific contracts to be executed at the end of every block. This allows the smart contract to perform actions that may need to happen every block, or at set block intervals. + +By using this module, your application can remove the headache of external whitelisted bots and instead depend on the chain itself for constant executions. + +## Contents + +1. **[Authorization](01_authorization.md)** +2. **[Contract Integration](02_integration.md)** diff --git a/x/clock/types/codec.go b/x/clock/types/codec.go new file mode 100644 index 00000000..46ccaa47 --- /dev/null +++ b/x/clock/types/codec.go @@ -0,0 +1,44 @@ +package types + +import ( + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/legacy" + "github.com/cosmos/cosmos-sdk/codec/types" + cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" + authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" + govcodec "github.com/cosmos/cosmos-sdk/x/gov/codec" +) + +var ( + amino = codec.NewLegacyAmino() + AminoCdc = codec.NewAminoCodec(amino) +) + +func init() { + RegisterLegacyAminoCodec(amino) + cryptocodec.RegisterCrypto(amino) + sdk.RegisterLegacyAminoCodec(amino) + + // Register all Amino interfaces and concrete types on the authz and gov Amino codec + // so that this can later be used to properly serialize MsgGrant and MsgExec + // instances. + RegisterLegacyAminoCodec(authzcodec.Amino) + RegisterLegacyAminoCodec(govcodec.Amino) +} + +// RegisterLegacyAminoCodec registers concrete types on the LegacyAmino codec +func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + cdc.RegisterConcrete(Params{}, "terp/x/clock/Params", nil) + legacy.RegisterAminoMsg(cdc, &MsgUpdateParams{}, "terp/x/clock/MsgUpdateParams") +} + +func RegisterInterfaces(registry types.InterfaceRegistry) { + registry.RegisterImplementations( + (*sdk.Msg)(nil), + &MsgUpdateParams{}, + ) + + msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) +} diff --git a/x/clock/types/codec_test.go b/x/clock/types/codec_test.go new file mode 100644 index 00000000..92c1c18c --- /dev/null +++ b/x/clock/types/codec_test.go @@ -0,0 +1,30 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +type CodecTestSuite struct { + suite.Suite +} + +func TestCodecSuite(t *testing.T) { + suite.Run(t, new(CodecTestSuite)) +} + +func (suite *CodecTestSuite) TestRegisterInterfaces() { + registry := codectypes.NewInterfaceRegistry() + registry.RegisterInterface(sdk.MsgInterfaceProtoName, (*sdk.Msg)(nil)) + RegisterInterfaces(registry) + + impls := registry.ListImplementations(sdk.MsgInterfaceProtoName) + suite.Require().Equal(1, len(impls)) + suite.Require().ElementsMatch([]string{ + "/terp.clock.v1.MsgUpdateParams", + }, impls) +} diff --git a/x/clock/types/genesis.pb.go b/x/clock/types/genesis.pb.go new file mode 100644 index 00000000..c3c51227 --- /dev/null +++ b/x/clock/types/genesis.pb.go @@ -0,0 +1,542 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: terp/clock/v1/genesis.proto + +package types + +import ( + fmt "fmt" + _ "github.com/cosmos/cosmos-sdk/types" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// GenesisState - initial state of module +type GenesisState struct { + // Params of this module + Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params,omitempty"` +} + +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_5814f6c7e1ff453c, []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) GetParams() Params { + if m != nil { + return m.Params + } + return Params{} +} + +// Params defines the set of module parameters. +type Params struct { + // contract_addresses stores the list of executable contracts to be ticked on every block. + ContractAddresses []string `protobuf:"bytes,1,rep,name=contract_addresses,json=contractAddresses,proto3" json:"contract_addresses,omitempty" yaml:"contract_addresses"` + ContractGasLimit uint64 `protobuf:"varint,2,opt,name=contract_gas_limit,json=contractGasLimit,proto3" json:"contract_gas_limit,omitempty" yaml:"contract_gas_limit"` +} + +func (m *Params) Reset() { *m = Params{} } +func (m *Params) String() string { return proto.CompactTextString(m) } +func (*Params) ProtoMessage() {} +func (*Params) Descriptor() ([]byte, []int) { + return fileDescriptor_5814f6c7e1ff453c, []int{1} +} +func (m *Params) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Params) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Params.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 *Params) XXX_Merge(src proto.Message) { + xxx_messageInfo_Params.Merge(m, src) +} +func (m *Params) XXX_Size() int { + return m.Size() +} +func (m *Params) XXX_DiscardUnknown() { + xxx_messageInfo_Params.DiscardUnknown(m) +} + +var xxx_messageInfo_Params proto.InternalMessageInfo + +func (m *Params) GetContractAddresses() []string { + if m != nil { + return m.ContractAddresses + } + return nil +} + +func (m *Params) GetContractGasLimit() uint64 { + if m != nil { + return m.ContractGasLimit + } + return 0 +} + +func init() { + proto.RegisterType((*GenesisState)(nil), "terp.clock.v1.GenesisState") + proto.RegisterType((*Params)(nil), "terp.clock.v1.Params") +} + +func init() { proto.RegisterFile("terp/clock/v1/genesis.proto", fileDescriptor_5814f6c7e1ff453c) } + +var fileDescriptor_5814f6c7e1ff453c = []byte{ + // 332 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x91, 0x3f, 0x4b, 0xc3, 0x40, + 0x18, 0xc6, 0x73, 0x2a, 0x05, 0xa3, 0x42, 0x0d, 0x0a, 0xb5, 0xca, 0xa5, 0x64, 0xea, 0xa0, 0x77, + 0x44, 0x37, 0xc1, 0xc1, 0x2e, 0x75, 0x70, 0x90, 0x3a, 0x08, 0x2e, 0xe5, 0x72, 0x3d, 0x62, 0x68, + 0x2e, 0x17, 0xee, 0x5e, 0xab, 0xfd, 0x16, 0x7e, 0xac, 0x8e, 0x1d, 0x9d, 0x82, 0x34, 0x5b, 0x47, + 0x3f, 0x81, 0x24, 0x69, 0xeb, 0x9f, 0x82, 0xdb, 0xcb, 0xf3, 0xfb, 0xdd, 0xfb, 0xc0, 0xbd, 0xf6, + 0x31, 0x08, 0x9d, 0x52, 0x1e, 0x2b, 0x3e, 0xa4, 0x23, 0x9f, 0x86, 0x22, 0x11, 0x26, 0x32, 0x24, + 0xd5, 0x0a, 0x94, 0xb3, 0x57, 0x40, 0x52, 0x42, 0x32, 0xf2, 0x9b, 0x07, 0xa1, 0x0a, 0x55, 0x49, + 0x68, 0x31, 0x55, 0x52, 0x13, 0x73, 0x65, 0xa4, 0x32, 0x34, 0x60, 0x46, 0xd0, 0x91, 0x1f, 0x08, + 0x60, 0x3e, 0xe5, 0x2a, 0x4a, 0x2a, 0xee, 0x3d, 0xd8, 0xbb, 0xdd, 0x6a, 0xeb, 0x3d, 0x30, 0x10, + 0x4e, 0xd7, 0xae, 0xa5, 0x4c, 0x33, 0x69, 0x1a, 0xa8, 0x85, 0xda, 0x3b, 0xe7, 0x87, 0xe4, 0x57, + 0x0b, 0xb9, 0x2b, 0x61, 0xa7, 0x31, 0xc9, 0x5c, 0x6b, 0x9e, 0xb9, 0xf5, 0x4a, 0x3e, 0x55, 0x32, + 0x02, 0x21, 0x53, 0x18, 0xf7, 0x16, 0xcf, 0xbd, 0x1c, 0xd9, 0xb5, 0x4a, 0x76, 0x62, 0xdb, 0xe1, + 0x2a, 0x01, 0xcd, 0x38, 0xf4, 0xd9, 0x60, 0xa0, 0x85, 0x31, 0xa2, 0xd8, 0xbf, 0xd9, 0xde, 0xee, + 0x5c, 0xcd, 0x33, 0xf7, 0x64, 0x9d, 0x7e, 0x2f, 0xfc, 0xcc, 0xdc, 0xa3, 0x31, 0x93, 0xf1, 0xa5, + 0xb7, 0x6e, 0x79, 0xbd, 0xfd, 0x65, 0x78, 0xbd, 0xcc, 0x9c, 0xe1, 0x8f, 0xb6, 0x90, 0x99, 0x7e, + 0x1c, 0xc9, 0x08, 0x1a, 0x1b, 0x2d, 0xd4, 0xde, 0xfa, 0xd3, 0xb6, 0xa2, 0xff, 0xb6, 0xad, 0x2c, + 0xaf, 0x57, 0x5f, 0x86, 0x5d, 0x66, 0x6e, 0x8b, 0xa8, 0x73, 0x33, 0x99, 0x61, 0x34, 0x9d, 0x61, + 0xf4, 0x31, 0xc3, 0xe8, 0x2d, 0xc7, 0xd6, 0x34, 0xc7, 0xd6, 0x7b, 0x8e, 0xad, 0x47, 0x12, 0x46, + 0xf0, 0xf4, 0x1c, 0x10, 0xae, 0x24, 0x2d, 0xbe, 0x30, 0x11, 0xf0, 0xa2, 0xf4, 0xb0, 0x9c, 0xcf, + 0xb8, 0xd2, 0x82, 0xbe, 0x2e, 0x0e, 0x0b, 0xe3, 0x54, 0x98, 0xa0, 0x56, 0xde, 0xe3, 0xe2, 0x2b, + 0x00, 0x00, 0xff, 0xff, 0xcc, 0xa3, 0xd5, 0x20, 0xf3, 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 + { + size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *Params) 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 *Params) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.ContractGasLimit != 0 { + i = encodeVarintGenesis(dAtA, i, uint64(m.ContractGasLimit)) + i-- + dAtA[i] = 0x10 + } + if len(m.ContractAddresses) > 0 { + for iNdEx := len(m.ContractAddresses) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.ContractAddresses[iNdEx]) + copy(dAtA[i:], m.ContractAddresses[iNdEx]) + i = encodeVarintGenesis(dAtA, i, uint64(len(m.ContractAddresses[iNdEx]))) + 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 = m.Params.Size() + n += 1 + l + sovGenesis(uint64(l)) + return n +} + +func (m *Params) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.ContractAddresses) > 0 { + for _, s := range m.ContractAddresses { + l = len(s) + n += 1 + l + sovGenesis(uint64(l)) + } + } + if m.ContractGasLimit != 0 { + n += 1 + sovGenesis(uint64(m.ContractGasLimit)) + } + 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 Params", 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 + } + if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Params) 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: Params: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Params: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ContractAddresses", 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.ContractAddresses = append(m.ContractAddresses, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ContractGasLimit", wireType) + } + m.ContractGasLimit = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ContractGasLimit |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + 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/clock/types/keys.go b/x/clock/types/keys.go new file mode 100644 index 00000000..3b97c283 --- /dev/null +++ b/x/clock/types/keys.go @@ -0,0 +1,11 @@ +package types + +var ParamsKey = []byte{0x00} + +const ( + ModuleName = "clock" + + StoreKey = ModuleName + + QuerierRoute = ModuleName +) diff --git a/x/clock/types/msgs.go b/x/clock/types/msgs.go new file mode 100644 index 00000000..96cea69e --- /dev/null +++ b/x/clock/types/msgs.go @@ -0,0 +1,56 @@ +package types + +import ( + "cosmossdk.io/errors" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/terpnetwork/terp-core/v4/x/drip/types" +) + +const ( + // Sudo Message called on the contracts + EndBlockSudoMessage = `{"clock_end_block":{}}` +) + +// == MsgUpdateParams == +const TypeMsgUpdateParams = "update_clock_params" + +var _ sdk.Msg = &MsgUpdateParams{} + +// NewMsgUpdateParams creates new instance of MsgUpdateParams +func NewMsgUpdateParams( + sender sdk.Address, + contracts []string, +) *MsgUpdateParams { + return &MsgUpdateParams{ + Authority: sender.String(), + Params: Params{ContractAddresses: contracts}, + } +} + +// Route returns the name of the module +func (msg MsgUpdateParams) Route() string { return types.RouterKey } + +// Type returns the the action +func (msg MsgUpdateParams) Type() string { return TypeMsgUpdateParams } + +// GetSignBytes implements the LegacyMsg interface. +func (msg MsgUpdateParams) GetSignBytes() []byte { + return sdk.MustSortJSON(AminoCdc.MustMarshalJSON(&msg)) +} + +// GetSigners returns the expected signers for a MsgUpdateParams message. +func (msg *MsgUpdateParams) GetSigners() []sdk.AccAddress { + addr, _ := sdk.AccAddressFromBech32(msg.Authority) + return []sdk.AccAddress{addr} +} + +// ValidateBasic does a sanity check on the provided data. +func (msg *MsgUpdateParams) ValidateBasic() error { + if _, err := sdk.AccAddressFromBech32(msg.Authority); err != nil { + return errors.Wrap(err, "invalid authority address") + } + + return msg.Params.Validate() +} diff --git a/x/clock/types/msgs_test.go b/x/clock/types/msgs_test.go new file mode 100644 index 00000000..d9736d96 --- /dev/null +++ b/x/clock/types/msgs_test.go @@ -0,0 +1,41 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/terpnetwork/terp-core/v4/x/drip/types" +) + +type MsgsTestSuite struct { + suite.Suite + govModule string +} + +func TestMsgsTestSuite(t *testing.T) { + suite.Run(t, new(MsgsTestSuite)) +} + +func (suite *MsgsTestSuite) SetupTest() { + suite.govModule = "terp10d07y265gmmuvt4z0w9aw880jnsr700jag6fuq" +} + +func (suite *MsgsTestSuite) TestMsgUpdateParams() { + p := MsgUpdateParams{ + Authority: suite.govModule, + Params: Params{ + ContractAddresses: []string{}, + }, + } + + acc, _ := sdk.AccAddressFromBech32(p.Authority) + + msg := NewMsgUpdateParams(acc, []string(nil)) + + suite.Require().Equal(types.RouterKey, msg.Route()) + suite.Require().Equal(TypeMsgUpdateParams, msg.Type()) + suite.Require().NotNil(msg.GetSigners()) +} diff --git a/x/clock/types/params.go b/x/clock/types/params.go new file mode 100644 index 00000000..46b5dfb7 --- /dev/null +++ b/x/clock/types/params.go @@ -0,0 +1,65 @@ +package types + +import ( + errorsmod "cosmossdk.io/errors" + + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +// DefaultParams returns default parameters +func DefaultParams() Params { + return Params{ + ContractAddresses: []string(nil), + ContractGasLimit: 1_000_000_000, // 1 billion + } +} + +// NewParams creates a new Params object +func NewParams( + contracts []string, + contractGasLimit uint64, +) Params { + return Params{ + ContractAddresses: contracts, + ContractGasLimit: contractGasLimit, + } +} + +// Validate performs basic validation. +func (p Params) Validate() error { + minimumGas := uint64(100_000) + if p.ContractGasLimit < minimumGas { + return errorsmod.Wrapf( + sdkerrors.ErrInvalidRequest, + "invalid contract gas limit: %d. Must be above %d", p.ContractGasLimit, minimumGas, + ) + } + + for _, addr := range p.ContractAddresses { + // Valid address check + if _, err := sdk.AccAddressFromBech32(addr); err != nil { + return errorsmod.Wrapf( + sdkerrors.ErrInvalidAddress, + "invalid contract address: %s", err.Error(), + ) + } + + // duplicate address check + count := 0 + for _, addr2 := range p.ContractAddresses { + if addr == addr2 { + count++ + } + + if count > 1 { + return errorsmod.Wrapf( + sdkerrors.ErrInvalidAddress, + "duplicate contract address: %s", addr, + ) + } + } + } + + return nil +} diff --git a/x/clock/types/params_test.go b/x/clock/types/params_test.go new file mode 100644 index 00000000..016f1832 --- /dev/null +++ b/x/clock/types/params_test.go @@ -0,0 +1,44 @@ +package types_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/terpnetwork/terp-core/v4/x/clock/types" +) + +func TestParamsValidate(t *testing.T) { + testCases := []struct { + name string + params types.Params + expError bool + }{ + {"default", types.DefaultParams(), false}, + { + "valid: no contracts, enough gas", + types.NewParams([]string(nil), 100_000), + false, + }, + { + "invalid: address malformed", + types.NewParams([]string{"invalid address"}, 100_000), + true, + }, + { + "invalid: not enough gas", + types.NewParams([]string(nil), 1), + true, + }, + } + + for _, tc := range testCases { + err := tc.params.Validate() + + if tc.expError { + require.Error(t, err, tc.name) + } else { + require.NoError(t, err, tc.name) + } + } +} diff --git a/x/clock/types/query.pb.go b/x/clock/types/query.pb.go new file mode 100644 index 00000000..2d92ef01 --- /dev/null +++ b/x/clock/types/query.pb.go @@ -0,0 +1,884 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: terp/clock/v1/query.proto + +package types + +import ( + context "context" + fmt "fmt" + _ "github.com/cosmos/cosmos-sdk/types" + _ "github.com/cosmos/gogoproto/gogoproto" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/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" + 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 + +// QueryClockContracts is the request type to get all contracts. +type QueryClockContracts struct { +} + +func (m *QueryClockContracts) Reset() { *m = QueryClockContracts{} } +func (m *QueryClockContracts) String() string { return proto.CompactTextString(m) } +func (*QueryClockContracts) ProtoMessage() {} +func (*QueryClockContracts) Descriptor() ([]byte, []int) { + return fileDescriptor_06ba6c07aa2f39a1, []int{0} +} +func (m *QueryClockContracts) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryClockContracts) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryClockContracts.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 *QueryClockContracts) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryClockContracts.Merge(m, src) +} +func (m *QueryClockContracts) XXX_Size() int { + return m.Size() +} +func (m *QueryClockContracts) XXX_DiscardUnknown() { + xxx_messageInfo_QueryClockContracts.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryClockContracts proto.InternalMessageInfo + +// QueryClockContractsResponse is the response type for the Query/ClockContracts RPC method. +type QueryClockContractsResponse struct { + ContractAddresses []string `protobuf:"bytes,1,rep,name=contract_addresses,json=contractAddresses,proto3" json:"contract_addresses,omitempty" yaml:"contract_addresses"` +} + +func (m *QueryClockContractsResponse) Reset() { *m = QueryClockContractsResponse{} } +func (m *QueryClockContractsResponse) String() string { return proto.CompactTextString(m) } +func (*QueryClockContractsResponse) ProtoMessage() {} +func (*QueryClockContractsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_06ba6c07aa2f39a1, []int{1} +} +func (m *QueryClockContractsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryClockContractsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryClockContractsResponse.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 *QueryClockContractsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryClockContractsResponse.Merge(m, src) +} +func (m *QueryClockContractsResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryClockContractsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryClockContractsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryClockContractsResponse proto.InternalMessageInfo + +func (m *QueryClockContractsResponse) GetContractAddresses() []string { + if m != nil { + return m.ContractAddresses + } + return nil +} + +// QueryParams is the request type to get all module params. +type QueryParamsRequest struct { +} + +func (m *QueryParamsRequest) Reset() { *m = QueryParamsRequest{} } +func (m *QueryParamsRequest) String() string { return proto.CompactTextString(m) } +func (*QueryParamsRequest) ProtoMessage() {} +func (*QueryParamsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_06ba6c07aa2f39a1, []int{2} +} +func (m *QueryParamsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryParamsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryParamsRequest.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 *QueryParamsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryParamsRequest.Merge(m, src) +} +func (m *QueryParamsRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryParamsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryParamsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryParamsRequest proto.InternalMessageInfo + +// QueryClockContractsResponse is the response type for the Query/ClockContracts RPC method. +type QueryParamsResponse struct { + Params *Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params" yaml:"params"` +} + +func (m *QueryParamsResponse) Reset() { *m = QueryParamsResponse{} } +func (m *QueryParamsResponse) String() string { return proto.CompactTextString(m) } +func (*QueryParamsResponse) ProtoMessage() {} +func (*QueryParamsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_06ba6c07aa2f39a1, []int{3} +} +func (m *QueryParamsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryParamsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryParamsResponse.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 *QueryParamsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryParamsResponse.Merge(m, src) +} +func (m *QueryParamsResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryParamsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryParamsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryParamsResponse proto.InternalMessageInfo + +func (m *QueryParamsResponse) GetParams() *Params { + if m != nil { + return m.Params + } + return nil +} + +func init() { + proto.RegisterType((*QueryClockContracts)(nil), "terp.clock.v1.QueryClockContracts") + proto.RegisterType((*QueryClockContractsResponse)(nil), "terp.clock.v1.QueryClockContractsResponse") + proto.RegisterType((*QueryParamsRequest)(nil), "terp.clock.v1.QueryParamsRequest") + proto.RegisterType((*QueryParamsResponse)(nil), "terp.clock.v1.QueryParamsResponse") +} + +func init() { proto.RegisterFile("terp/clock/v1/query.proto", fileDescriptor_06ba6c07aa2f39a1) } + +var fileDescriptor_06ba6c07aa2f39a1 = []byte{ + // 427 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x92, 0xb1, 0x6f, 0xd3, 0x40, + 0x14, 0xc6, 0x73, 0x20, 0x22, 0x71, 0xa8, 0x48, 0x1c, 0x8d, 0x48, 0x9d, 0xe2, 0x84, 0x9b, 0x2a, + 0x04, 0x3e, 0xa5, 0x6c, 0x48, 0x0c, 0xa4, 0x0b, 0x62, 0x82, 0x8c, 0x2c, 0xe8, 0x72, 0x7d, 0x32, + 0x56, 0xe3, 0x7b, 0xee, 0xdd, 0x25, 0x90, 0xb5, 0x2b, 0x0b, 0x12, 0xff, 0x14, 0x63, 0x25, 0x16, + 0x26, 0x0b, 0x25, 0x4c, 0x1d, 0x3b, 0x33, 0x20, 0x9f, 0x2f, 0x95, 0xdc, 0x44, 0x74, 0x3b, 0x7f, + 0xbf, 0xef, 0xde, 0xf7, 0xf9, 0xd9, 0x74, 0xcf, 0x81, 0x29, 0x84, 0x9a, 0xa2, 0x3a, 0x11, 0xf3, + 0xa1, 0x38, 0x9d, 0x81, 0x59, 0x24, 0x85, 0x41, 0x87, 0x6c, 0xa7, 0x42, 0x89, 0x47, 0xc9, 0x7c, + 0x18, 0xed, 0xa6, 0x98, 0xa2, 0x27, 0xa2, 0x3a, 0xd5, 0xa6, 0x68, 0x3f, 0x45, 0x4c, 0xa7, 0x20, + 0x64, 0x91, 0x09, 0xa9, 0x35, 0x3a, 0xe9, 0x32, 0xd4, 0x36, 0xd0, 0x58, 0xa1, 0xcd, 0xd1, 0x8a, + 0x89, 0xb4, 0x20, 0xe6, 0xc3, 0x09, 0x38, 0x39, 0x14, 0x0a, 0x33, 0x1d, 0x78, 0xaf, 0x99, 0x9e, + 0x82, 0x06, 0x9b, 0x85, 0xcb, 0xbc, 0x43, 0x1f, 0xbe, 0xaf, 0xea, 0x1c, 0x55, 0xf8, 0x08, 0xb5, + 0x33, 0x52, 0x39, 0xcb, 0xbf, 0x12, 0xda, 0xdb, 0xa2, 0x8f, 0xc1, 0x16, 0xa8, 0x2d, 0xb0, 0x29, + 0x65, 0x2a, 0x88, 0x1f, 0xe5, 0xf1, 0xb1, 0x01, 0x6b, 0xc1, 0x76, 0xc9, 0xe0, 0xf6, 0xc1, 0xdd, + 0xd1, 0xab, 0x8b, 0xb2, 0xbf, 0xbf, 0x49, 0x9f, 0x61, 0x9e, 0x39, 0xc8, 0x0b, 0xb7, 0xb8, 0x2c, + 0xfb, 0x7b, 0x0b, 0x99, 0x4f, 0x5f, 0xf2, 0x4d, 0x17, 0x1f, 0x3f, 0x58, 0x8b, 0xaf, 0xaf, 0xb4, + 0x5d, 0xca, 0x7c, 0x99, 0x77, 0xd2, 0xc8, 0xdc, 0x8e, 0xe1, 0x74, 0x06, 0xd6, 0x71, 0x19, 0xaa, + 0xaf, 0xd5, 0x50, 0xed, 0x2d, 0x6d, 0x17, 0x5e, 0xe9, 0x92, 0x01, 0x39, 0xb8, 0x77, 0xd8, 0x49, + 0x1a, 0x2b, 0x4e, 0x6a, 0xfb, 0xa8, 0x77, 0x51, 0xf6, 0x83, 0xf1, 0xb2, 0xec, 0xef, 0xd4, 0x7d, + 0xea, 0x67, 0x3e, 0x0e, 0xe0, 0xf0, 0x2f, 0xa1, 0x77, 0x7c, 0x06, 0x3b, 0x23, 0xf4, 0x7e, 0x73, + 0x17, 0x8c, 0x5f, 0x1b, 0xbc, 0x65, 0x5f, 0xd1, 0xd3, 0x9b, 0x3d, 0xeb, 0xe2, 0x7c, 0x70, 0xf6, + 0xf3, 0xcf, 0xf7, 0x5b, 0x11, 0xeb, 0x8a, 0xe6, 0x07, 0x53, 0x57, 0x89, 0x9a, 0xb6, 0xeb, 0xf6, + 0xec, 0xc9, 0xb6, 0xb9, 0x8d, 0xf5, 0x44, 0xfc, 0x7f, 0x96, 0x10, 0xf9, 0xd8, 0x47, 0x3e, 0x62, + 0x9d, 0x6b, 0x91, 0xf5, 0xeb, 0x8f, 0xde, 0xfc, 0x58, 0xc6, 0xe4, 0x7c, 0x19, 0x93, 0xdf, 0xcb, + 0x98, 0x7c, 0x5b, 0xc5, 0xad, 0xf3, 0x55, 0xdc, 0xfa, 0xb5, 0x8a, 0x5b, 0x1f, 0x92, 0x34, 0x73, + 0x9f, 0x66, 0x93, 0x44, 0x61, 0xee, 0xaf, 0x6a, 0x70, 0x9f, 0xd1, 0x9c, 0xf8, 0xf3, 0x73, 0x85, + 0x06, 0xc4, 0x97, 0x30, 0xcd, 0x2d, 0x0a, 0xb0, 0x93, 0xb6, 0xff, 0xdb, 0x5e, 0xfc, 0x0b, 0x00, + 0x00, 0xff, 0xff, 0xda, 0x94, 0x2b, 0xdd, 0x0a, 0x03, 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 { + // ClockContracts + ClockContracts(ctx context.Context, in *QueryClockContracts, opts ...grpc.CallOption) (*QueryClockContractsResponse, error) + // Params + Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) +} + +type queryClient struct { + cc grpc1.ClientConn +} + +func NewQueryClient(cc grpc1.ClientConn) QueryClient { + return &queryClient{cc} +} + +func (c *queryClient) ClockContracts(ctx context.Context, in *QueryClockContracts, opts ...grpc.CallOption) (*QueryClockContractsResponse, error) { + out := new(QueryClockContractsResponse) + err := c.cc.Invoke(ctx, "/terp.clock.v1.Query/ClockContracts", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) { + out := new(QueryParamsResponse) + err := c.cc.Invoke(ctx, "/terp.clock.v1.Query/Params", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// QueryServer is the server API for Query service. +type QueryServer interface { + // ClockContracts + ClockContracts(context.Context, *QueryClockContracts) (*QueryClockContractsResponse, error) + // Params + Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error) +} + +// UnimplementedQueryServer can be embedded to have forward compatible implementations. +type UnimplementedQueryServer struct { +} + +func (*UnimplementedQueryServer) ClockContracts(ctx context.Context, req *QueryClockContracts) (*QueryClockContractsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ClockContracts not implemented") +} +func (*UnimplementedQueryServer) Params(ctx context.Context, req *QueryParamsRequest) (*QueryParamsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Params not implemented") +} + +func RegisterQueryServer(s grpc1.Server, srv QueryServer) { + s.RegisterService(&_Query_serviceDesc, srv) +} + +func _Query_ClockContracts_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryClockContracts) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).ClockContracts(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/terp.clock.v1.Query/ClockContracts", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).ClockContracts(ctx, req.(*QueryClockContracts)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_Params_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryParamsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Params(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/terp.clock.v1.Query/Params", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Params(ctx, req.(*QueryParamsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Query_serviceDesc = grpc.ServiceDesc{ + ServiceName: "terp.clock.v1.Query", + HandlerType: (*QueryServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "ClockContracts", + Handler: _Query_ClockContracts_Handler, + }, + { + MethodName: "Params", + Handler: _Query_Params_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "terp/clock/v1/query.proto", +} + +func (m *QueryClockContracts) 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 *QueryClockContracts) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryClockContracts) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryClockContractsResponse) 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 *QueryClockContractsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryClockContractsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ContractAddresses) > 0 { + for iNdEx := len(m.ContractAddresses) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.ContractAddresses[iNdEx]) + copy(dAtA[i:], m.ContractAddresses[iNdEx]) + i = encodeVarintQuery(dAtA, i, uint64(len(m.ContractAddresses[iNdEx]))) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *QueryParamsRequest) 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 *QueryParamsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryParamsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryParamsResponse) 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 *QueryParamsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Params != nil { + { + size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { + offset -= sovQuery(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *QueryClockContracts) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryClockContractsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.ContractAddresses) > 0 { + for _, s := range m.ContractAddresses { + l = len(s) + n += 1 + l + sovQuery(uint64(l)) + } + } + return n +} + +func (m *QueryParamsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryParamsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Params != nil { + l = m.Params.Size() + 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 *QueryClockContracts) 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: QueryClockContracts: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryClockContracts: 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 *QueryClockContractsResponse) 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: QueryClockContractsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryClockContractsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ContractAddresses", 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.ContractAddresses = append(m.ContractAddresses, 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 *QueryParamsRequest) 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: QueryParamsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryParamsRequest: 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 *QueryParamsResponse) 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: QueryParamsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Params == nil { + m.Params = &Params{} + } + if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipQuery(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + 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/clock/types/query.pb.gw.go b/x/clock/types/query.pb.gw.go new file mode 100644 index 00000000..5adb17cb --- /dev/null +++ b/x/clock/types/query.pb.gw.go @@ -0,0 +1,218 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: terp/clock/v1/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/metadata" + "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 +var _ = metadata.Join + +func request_Query_ClockContracts_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryClockContracts + var metadata runtime.ServerMetadata + + msg, err := client.ClockContracts(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_ClockContracts_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryClockContracts + var metadata runtime.ServerMetadata + + msg, err := server.ClockContracts(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryParamsRequest + var metadata runtime.ServerMetadata + + msg, err := client.Params(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryParamsRequest + var metadata runtime.ServerMetadata + + msg, err := server.Params(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 to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_ClockContracts_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_ClockContracts_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ClockContracts_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Params_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Params_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_ClockContracts_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_ClockContracts_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_ClockContracts_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Params_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_Params_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_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +var ( + pattern_Query_ClockContracts_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"terp", "clock", "v1", "contracts"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"terp", "clock", "v1", "params"}, "", runtime.AssumeColonVerbOpt(false))) +) + +var ( + forward_Query_ClockContracts_0 = runtime.ForwardResponseMessage + + forward_Query_Params_0 = runtime.ForwardResponseMessage +) diff --git a/x/clock/types/tx.pb.go b/x/clock/types/tx.pb.go new file mode 100644 index 00000000..c07bee48 --- /dev/null +++ b/x/clock/types/tx.pb.go @@ -0,0 +1,605 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: terp/clock/v1/tx.proto + +package types + +import ( + context "context" + fmt "fmt" + _ "github.com/cosmos/cosmos-proto" + _ "github.com/cosmos/cosmos-sdk/types/msgservice" + _ "github.com/cosmos/cosmos-sdk/types/tx/amino" + _ "github.com/cosmos/gogoproto/gogoproto" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + 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 + +// MsgUpdateParams is the Msg/UpdateParams request type. +// +// Since: cosmos-sdk 0.47 +type MsgUpdateParams struct { + // authority is the address of the governance account. + Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` + // params defines the x/clock parameters to update. + // + // NOTE: All parameters must be supplied. + Params Params `protobuf:"bytes,2,opt,name=params,proto3" json:"params"` +} + +func (m *MsgUpdateParams) Reset() { *m = MsgUpdateParams{} } +func (m *MsgUpdateParams) String() string { return proto.CompactTextString(m) } +func (*MsgUpdateParams) ProtoMessage() {} +func (*MsgUpdateParams) Descriptor() ([]byte, []int) { + return fileDescriptor_ad9dd5417a79a74f, []int{0} +} +func (m *MsgUpdateParams) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateParams.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 *MsgUpdateParams) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateParams.Merge(m, src) +} +func (m *MsgUpdateParams) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateParams) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateParams.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUpdateParams proto.InternalMessageInfo + +func (m *MsgUpdateParams) GetAuthority() string { + if m != nil { + return m.Authority + } + return "" +} + +func (m *MsgUpdateParams) GetParams() Params { + if m != nil { + return m.Params + } + return Params{} +} + +// MsgUpdateParamsResponse defines the response structure for executing a +// MsgUpdateParams message. +// +// Since: cosmos-sdk 0.47 +type MsgUpdateParamsResponse struct { +} + +func (m *MsgUpdateParamsResponse) Reset() { *m = MsgUpdateParamsResponse{} } +func (m *MsgUpdateParamsResponse) String() string { return proto.CompactTextString(m) } +func (*MsgUpdateParamsResponse) ProtoMessage() {} +func (*MsgUpdateParamsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_ad9dd5417a79a74f, []int{1} +} +func (m *MsgUpdateParamsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateParamsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateParamsResponse.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 *MsgUpdateParamsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateParamsResponse.Merge(m, src) +} +func (m *MsgUpdateParamsResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateParamsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateParamsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUpdateParamsResponse proto.InternalMessageInfo + +func init() { + proto.RegisterType((*MsgUpdateParams)(nil), "terp.clock.v1.MsgUpdateParams") + proto.RegisterType((*MsgUpdateParamsResponse)(nil), "terp.clock.v1.MsgUpdateParamsResponse") +} + +func init() { proto.RegisterFile("terp/clock/v1/tx.proto", fileDescriptor_ad9dd5417a79a74f) } + +var fileDescriptor_ad9dd5417a79a74f = []byte{ + // 334 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x2b, 0x49, 0x2d, 0x2a, + 0xd0, 0x4f, 0xce, 0xc9, 0x4f, 0xce, 0xd6, 0x2f, 0x33, 0xd4, 0x2f, 0xa9, 0xd0, 0x2b, 0x28, 0xca, + 0x2f, 0xc9, 0x17, 0xe2, 0x05, 0x89, 0xeb, 0x81, 0xc5, 0xf5, 0xca, 0x0c, 0xa5, 0xc4, 0x93, 0xf3, + 0x8b, 0x73, 0xf3, 0x8b, 0xf5, 0x73, 0x8b, 0xd3, 0x41, 0xca, 0x72, 0x8b, 0xd3, 0x21, 0xea, 0xa4, + 0xa4, 0x51, 0xf5, 0xa7, 0xa7, 0xe6, 0xa5, 0x16, 0x67, 0x16, 0x43, 0x25, 0x45, 0xd2, 0xf3, 0xd3, + 0xf3, 0xc1, 0x4c, 0x7d, 0x10, 0x0b, 0x2a, 0x2a, 0x09, 0x31, 0x2b, 0x1e, 0x22, 0x01, 0xe1, 0x40, + 0xa5, 0x04, 0x13, 0x73, 0x33, 0xf3, 0xf2, 0xf5, 0xc1, 0x24, 0x44, 0x48, 0xa9, 0x8f, 0x91, 0x8b, + 0xdf, 0xb7, 0x38, 0x3d, 0xb4, 0x20, 0x25, 0xb1, 0x24, 0x35, 0x20, 0xb1, 0x28, 0x31, 0xb7, 0x58, + 0xc8, 0x8c, 0x8b, 0x33, 0xb1, 0xb4, 0x24, 0x23, 0xbf, 0x28, 0xb3, 0xa4, 0x52, 0x82, 0x51, 0x81, + 0x51, 0x83, 0xd3, 0x49, 0xe2, 0xd2, 0x16, 0x5d, 0x11, 0xa8, 0x59, 0x8e, 0x29, 0x29, 0x45, 0xa9, + 0xc5, 0xc5, 0xc1, 0x25, 0x45, 0x99, 0x79, 0xe9, 0x41, 0x08, 0xa5, 0x42, 0xc6, 0x5c, 0x6c, 0x05, + 0x60, 0x13, 0x24, 0x98, 0x14, 0x18, 0x35, 0xb8, 0x8d, 0x44, 0xf5, 0x50, 0x7c, 0xa9, 0x07, 0x31, + 0xde, 0x89, 0xe5, 0xc4, 0x3d, 0x79, 0x86, 0x20, 0xa8, 0x52, 0x2b, 0xbe, 0xa6, 0xe7, 0x1b, 0xb4, + 0x10, 0x86, 0x28, 0x49, 0x72, 0x89, 0xa3, 0xb9, 0x27, 0x28, 0xb5, 0xb8, 0x20, 0x3f, 0xaf, 0x38, + 0xd5, 0x28, 0x96, 0x8b, 0xd9, 0xb7, 0x38, 0x5d, 0x28, 0x8c, 0x8b, 0x07, 0xc5, 0xb9, 0x72, 0x68, + 0xd6, 0xa0, 0x69, 0x97, 0x52, 0xc3, 0x2f, 0x0f, 0x33, 0xde, 0xc9, 0xe3, 0xc4, 0x23, 0x39, 0xc6, + 0x0b, 0x8f, 0xe4, 0x18, 0x1f, 0x3c, 0x92, 0x63, 0x9c, 0xf0, 0x58, 0x8e, 0xe1, 0xc2, 0x63, 0x39, + 0x86, 0x1b, 0x8f, 0xe5, 0x18, 0xa2, 0xf4, 0xd2, 0x33, 0x4b, 0x32, 0x4a, 0x93, 0xf4, 0x92, 0xf3, + 0x73, 0xf5, 0x41, 0x66, 0xe5, 0xa5, 0x96, 0x94, 0xe7, 0x17, 0x65, 0x83, 0xd9, 0xba, 0xc9, 0xf9, + 0x45, 0xa9, 0xfa, 0x15, 0xd0, 0x38, 0x2a, 0xa9, 0x2c, 0x48, 0x2d, 0x4e, 0x62, 0x03, 0x87, 0xad, + 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0x12, 0xb9, 0xe4, 0x93, 0xfe, 0x01, 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 + +// MsgClient is the client API for Msg service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type MsgClient interface { + // UpdateParams defines a governance operation for updating the x/clock module + // parameters. The authority is hard-coded to the x/gov module account. + // + // Since: cosmos-sdk 0.47 + UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error) +} + +type msgClient struct { + cc grpc1.ClientConn +} + +func NewMsgClient(cc grpc1.ClientConn) MsgClient { + return &msgClient{cc} +} + +func (c *msgClient) UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error) { + out := new(MsgUpdateParamsResponse) + err := c.cc.Invoke(ctx, "/terp.clock.v1.Msg/UpdateParams", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// MsgServer is the server API for Msg service. +type MsgServer interface { + // UpdateParams defines a governance operation for updating the x/clock module + // parameters. The authority is hard-coded to the x/gov module account. + // + // Since: cosmos-sdk 0.47 + UpdateParams(context.Context, *MsgUpdateParams) (*MsgUpdateParamsResponse, error) +} + +// UnimplementedMsgServer can be embedded to have forward compatible implementations. +type UnimplementedMsgServer struct { +} + +func (*UnimplementedMsgServer) UpdateParams(ctx context.Context, req *MsgUpdateParams) (*MsgUpdateParamsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpdateParams not implemented") +} + +func RegisterMsgServer(s grpc1.Server, srv MsgServer) { + s.RegisterService(&_Msg_serviceDesc, srv) +} + +func _Msg_UpdateParams_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgUpdateParams) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).UpdateParams(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/terp.clock.v1.Msg/UpdateParams", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).UpdateParams(ctx, req.(*MsgUpdateParams)) + } + return interceptor(ctx, in, info, handler) +} + +var _Msg_serviceDesc = grpc.ServiceDesc{ + ServiceName: "terp.clock.v1.Msg", + HandlerType: (*MsgServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "UpdateParams", + Handler: _Msg_UpdateParams_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "terp/clock/v1/tx.proto", +} + +func (m *MsgUpdateParams) 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 *MsgUpdateParams) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.Authority) > 0 { + i -= len(m.Authority) + copy(dAtA[i:], m.Authority) + i = encodeVarintTx(dAtA, i, uint64(len(m.Authority))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgUpdateParamsResponse) 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 *MsgUpdateParamsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func encodeVarintTx(dAtA []byte, offset int, v uint64) int { + offset -= sovTx(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *MsgUpdateParams) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Authority) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = m.Params.Size() + n += 1 + l + sovTx(uint64(l)) + return n +} + +func (m *MsgUpdateParamsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func sovTx(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTx(x uint64) (n int) { + return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *MsgUpdateParams) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgUpdateParams: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUpdateParams: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Authority", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Authority = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgUpdateParamsResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgUpdateParamsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUpdateParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTx(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, ErrIntOverflowTx + } + 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, ErrIntOverflowTx + } + 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, ErrIntOverflowTx + } + 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, ErrInvalidLengthTx + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTx + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTx + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTx = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTx = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTx = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/drip/README.md b/x/drip/README.md new file mode 100644 index 00000000..52943b8b --- /dev/null +++ b/x/drip/README.md @@ -0,0 +1,7 @@ +# Drip + +This module allows specific addresses (usually smart contracts) to send tokens to the fee_pool module in order to perform a live airdrop to Juno Stakers. + +[Drip Spec](spec/README.md) + +--- diff --git a/x/drip/client/cli/query.go b/x/drip/client/cli/query.go new file mode 100644 index 00000000..d3cd7931 --- /dev/null +++ b/x/drip/client/cli/query.go @@ -0,0 +1,59 @@ +package cli + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + + "github.com/terpnetwork/terp-core/v4/x/drip/types" +) + +// GetQueryCmd returns the cli query commands for this module +func GetQueryCmd() *cobra.Command { + feesQueryCmd := &cobra.Command{ + Use: types.ModuleName, + Short: fmt.Sprintf("Querying commands for the %s module", types.ModuleName), + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + feesQueryCmd.AddCommand( + GetCmdQueryParams(), + ) + + return feesQueryCmd +} + +// GetCmdQueryParams implements a command to return the current parameters. +func GetCmdQueryParams() *cobra.Command { + cmd := &cobra.Command{ + Use: "params", + Short: "Query the current feeshare module parameters", + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, _ []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + params := &types.QueryParamsRequest{} + + res, err := queryClient.Params(context.Background(), params) + if err != nil { + return err + } + + return clientCtx.PrintProto(&res.Params) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} diff --git a/x/drip/client/cli/tx.go b/x/drip/client/cli/tx.go new file mode 100644 index 00000000..2260e455 --- /dev/null +++ b/x/drip/client/cli/tx.go @@ -0,0 +1,64 @@ +package cli + +import ( + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/tx" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/terpnetwork/terp-core/v4/x/drip/types" +) + +// NewTxCmd returns a root CLI command handler for certain modules transaction commands. +func NewTxCmd() *cobra.Command { + txCmd := &cobra.Command{ + Use: types.ModuleName, + Short: "Drip subcommands", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + txCmd.AddCommand( + NewDistributeToken(), + ) + return txCmd +} + +// NewDistributeToken returns a CLI command handler for distributing tokens. +func NewDistributeToken() *cobra.Command { + cmd := &cobra.Command{ + Use: "distribute-tokens [amount]", + Short: "Distribute tokens to all stakers in the next block.", + Long: "Distribute tokens to all stakers in the next block **NOTE** ALL the tokens sent will be distributed to stakers in one shot at the next block. If you want to do a gradual airdrop, execute this transaction multiple times splitting the amount. This message can be executed only by authorized addresses.", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + cliCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + sender := cliCtx.GetFromAddress() + amount, err := sdk.ParseCoinsNormalized(args[0]) + if err != nil { + return err + } + + msg := &types.MsgDistributeTokens{ + SenderAddress: sender.String(), + Amount: amount, + } + + if err := msg.ValidateBasic(); err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(cliCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + return cmd +} diff --git a/x/drip/genesis.go b/x/drip/genesis.go new file mode 100644 index 00000000..7ba1bff5 --- /dev/null +++ b/x/drip/genesis.go @@ -0,0 +1,26 @@ +package drip + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/terpnetwork/terp-core/v4/x/drip/keeper" + "github.com/terpnetwork/terp-core/v4/x/drip/types" +) + +// InitGenesis import module genesis +func InitGenesis( + ctx sdk.Context, + k keeper.Keeper, + data types.GenesisState, +) { + if err := k.SetParams(ctx, data.Params); err != nil { + panic(err) + } +} + +// ExportGenesis export module state +func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState { + return &types.GenesisState{ + Params: k.GetParams(ctx), + } +} diff --git a/x/drip/genesis_test.go b/x/drip/genesis_test.go new file mode 100644 index 00000000..0c8e1be7 --- /dev/null +++ b/x/drip/genesis_test.go @@ -0,0 +1,114 @@ +package drip_test + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/suite" + + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/terpnetwork/terp-core/v4/app" + drip "github.com/terpnetwork/terp-core/v4/x/drip" + "github.com/terpnetwork/terp-core/v4/x/drip/types" +) + +type GenesisTestSuite struct { + suite.Suite + + ctx sdk.Context + + app *app.TerpApp + genesis types.GenesisState +} + +func TestGenesisTestSuite(t *testing.T) { + suite.Run(t, new(GenesisTestSuite)) +} + +func (suite *GenesisTestSuite) SetupTest() { + app := app.Setup(suite.T()) + ctx := app.BaseApp.NewContext(false, tmproto.Header{ + ChainID: "testing", + }) + + suite.app = app + suite.ctx = ctx + + suite.genesis = *types.DefaultGenesisState() +} + +func (suite *GenesisTestSuite) TestDripInitGenesis() { + testCases := []struct { + name string + genesis types.GenesisState + expPanic bool + }{ + { + "default genesis", + suite.genesis, + false, + }, + { + "custom genesis - drip enabled, no one allowed", + types.GenesisState{ + Params: types.Params{ + EnableDrip: true, + AllowedAddresses: []string(nil), + }, + }, + false, + }, + { + "custom genesis - drip enabled, only one addr allowed", + types.GenesisState{ + Params: types.Params{ + EnableDrip: true, + AllowedAddresses: []string{"terp1v6vlpuqlhhpwujvaqs4pe5dmljapdev4plqfds"}, + }, + }, + false, + }, + { + "custom genesis - drip enabled, 2 addr allowed", + types.GenesisState{ + Params: types.Params{ + EnableDrip: true, + AllowedAddresses: []string{"terp1v6vlpuqlhhpwujvaqs4pe5dmljapdev4plqfds", "terp1hq2p69p4kmwndxlss7dqk0sr5pe5mmcpcxyh5h"}, + }, + }, + false, + }, + { + "custom genesis - drip enabled, address invalid", + types.GenesisState{ + Params: types.Params{ + EnableDrip: true, + AllowedAddresses: []string{"terp1v6vllollollollollolloldmljapdev4s827ql"}, + }, + }, + true, + }, + } + + for _, tc := range testCases { + suite.Run(fmt.Sprintf("Case %s", tc.name), func() { + suite.SetupTest() // reset + + if tc.expPanic { + suite.Require().Panics(func() { + drip.InitGenesis(suite.ctx, suite.app.AppKeepers.DripKeeper, tc.genesis) + }) + } else { + suite.Require().NotPanics(func() { + drip.InitGenesis(suite.ctx, suite.app.AppKeepers.DripKeeper, tc.genesis) + }) + + params := suite.app.AppKeepers.DripKeeper.GetParams(suite.ctx) + suite.Require().Equal(tc.genesis.Params, params) + } + }) + } +} diff --git a/x/drip/keeper/grpc_query.go b/x/drip/keeper/grpc_query.go new file mode 100644 index 00000000..433a3233 --- /dev/null +++ b/x/drip/keeper/grpc_query.go @@ -0,0 +1,31 @@ +package keeper + +import ( + "context" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/terpnetwork/terp-core/v4/x/drip/types" +) + +var _ types.QueryServer = Querier{} + +// Querier defines a wrapper around the x/FeeShare keeper providing gRPC method +// handlers. +type Querier struct { + Keeper +} + +func NewQuerier(k Keeper) Querier { + return Querier{Keeper: k} +} + +// Params returns the fees module params +func (q Querier) Params( + c context.Context, + _ *types.QueryParamsRequest, +) (*types.QueryParamsResponse, error) { + ctx := sdk.UnwrapSDKContext(c) + params := q.GetParams(ctx) + return &types.QueryParamsResponse{Params: params}, nil +} diff --git a/x/drip/keeper/grpc_query_test.go b/x/drip/keeper/grpc_query_test.go new file mode 100644 index 00000000..f3ba91c7 --- /dev/null +++ b/x/drip/keeper/grpc_query_test.go @@ -0,0 +1,59 @@ +package keeper_test + +import ( + "github.com/cosmos/cosmos-sdk/testutil/testdata" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/terpnetwork/terp-core/v4/x/drip/types" +) + +func (s *IntegrationTestSuite) TestDripQueryParams() { + _, _, addr := testdata.KeyTestPubAddr() + _, _, addr2 := testdata.KeyTestPubAddr() + + for _, tc := range []struct { + desc string + Expected types.Params + }{ + { + desc: "On empty", + Expected: types.Params{ + EnableDrip: true, + AllowedAddresses: []string(nil), + }, + }, + { + desc: "off empty", + Expected: types.Params{ + EnableDrip: false, + AllowedAddresses: []string(nil), + }, + }, + { + desc: "On 1 address", + Expected: types.Params{ + EnableDrip: true, + AllowedAddresses: []string{addr.String()}, + }, + }, + { + desc: "On 2 Unique", + Expected: types.Params{ + EnableDrip: true, + AllowedAddresses: []string{addr.String(), addr2.String()}, + }, + }, + } { + tc := tc + s.Run(tc.desc, func() { + // Set the params to what is expected, then query and ensure the query is the same + err := s.app.AppKeepers.DripKeeper.SetParams(s.ctx, tc.Expected) + s.Require().NoError(err) + + goCtx := sdk.WrapSDKContext(s.ctx) + resp, err := s.queryClient.Params(goCtx, &types.QueryParamsRequest{}) + s.Require().NoError(err) + s.Require().Equal(tc.Expected, resp.Params) + }) + } +} diff --git a/x/drip/keeper/keeper.go b/x/drip/keeper/keeper.go new file mode 100644 index 00000000..3759c4da --- /dev/null +++ b/x/drip/keeper/keeper.go @@ -0,0 +1,49 @@ +package keeper + +import ( + "github.com/cosmos/cosmos-sdk/codec" + storetypes "github.com/cosmos/cosmos-sdk/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" + + driptypes "github.com/terpnetwork/terp-core/v4/x/drip/types" +) + +// Keeper of this module maintains distributing tokens to all stakers. +type Keeper struct { + storeKey storetypes.StoreKey + cdc codec.BinaryCodec + + bankKeeper driptypes.BankKeeper + + feeCollectorName string + // the address capable of executing a MsgUpdateParams message. Typically, this + // should be the x/gov module account. + authority string +} + +// NewKeeper creates new instances of the Keeper +func NewKeeper( + storeKey storetypes.StoreKey, + cdc codec.BinaryCodec, + bk driptypes.BankKeeper, + feeCollector string, + authority string, +) Keeper { + return Keeper{ + storeKey: storeKey, + cdc: cdc, + bankKeeper: bk, + feeCollectorName: feeCollector, + authority: authority, + } +} + +// GetAuthority returns the x/mint module's authority. +func (k Keeper) GetAuthority() string { + return k.authority +} + +// SendCoinsFromAccountToFeeCollector transfers amt to the fee collector account, where it will be catch up by the distribution module at the next block +func (k Keeper) SendCoinsFromAccountToFeeCollector(ctx sdk.Context, senderAddr sdk.AccAddress, amt sdk.Coins) error { + return k.bankKeeper.SendCoinsFromAccountToModule(ctx, senderAddr, k.feeCollectorName, amt) +} diff --git a/x/drip/keeper/keeper_test.go b/x/drip/keeper/keeper_test.go new file mode 100644 index 00000000..1fb64be2 --- /dev/null +++ b/x/drip/keeper/keeper_test.go @@ -0,0 +1,58 @@ +package keeper_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/suite" + + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" + + "github.com/cosmos/cosmos-sdk/baseapp" + sdk "github.com/cosmos/cosmos-sdk/types" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" + + "github.com/terpnetwork/terp-core/v4/app" + "github.com/terpnetwork/terp-core/v4/x/drip/keeper" + "github.com/terpnetwork/terp-core/v4/x/drip/types" +) + +type IntegrationTestSuite struct { + suite.Suite + + ctx sdk.Context + app *app.TerpApp + bankKeeper types.BankKeeper + queryClient types.QueryClient + dripMsgServer types.MsgServer +} + +func (s *IntegrationTestSuite) SetupTest() { + isCheckTx := false + s.app = app.Setup(s.T()) + + s.ctx = s.app.BaseApp.NewContext(isCheckTx, tmproto.Header{ + ChainID: "testing", + Height: 9, + Time: time.Now().UTC(), + }) + + queryHelper := baseapp.NewQueryServerTestHelper(s.ctx, s.app.InterfaceRegistry()) + types.RegisterQueryServer(queryHelper, keeper.NewQuerier(s.app.AppKeepers.DripKeeper)) + + s.queryClient = types.NewQueryClient(queryHelper) + s.bankKeeper = s.app.AppKeepers.BankKeeper + s.dripMsgServer = s.app.AppKeepers.DripKeeper +} + +func (s *IntegrationTestSuite) FundAccount(ctx sdk.Context, addr sdk.AccAddress, amounts sdk.Coins) error { + if err := s.bankKeeper.MintCoins(ctx, minttypes.ModuleName, amounts); err != nil { + return err + } + + return s.bankKeeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, addr, amounts) +} + +func TestKeeperTestSuite(t *testing.T) { + suite.Run(t, new(IntegrationTestSuite)) +} diff --git a/x/drip/keeper/msg_server.go b/x/drip/keeper/msg_server.go new file mode 100644 index 00000000..e496b9ac --- /dev/null +++ b/x/drip/keeper/msg_server.go @@ -0,0 +1,69 @@ +package keeper + +import ( + "context" + + errorsmod "cosmossdk.io/errors" + + sdk "github.com/cosmos/cosmos-sdk/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + + "github.com/terpnetwork/terp-core/v4/x/drip/types" +) + +var _ types.MsgServer = &Keeper{} + +// DistributeTokens distribute tokens to all stakers at the next block +func (k Keeper) DistributeTokens( + goCtx context.Context, + msg *types.MsgDistributeTokens, +) (*types.MsgDistributeTokensResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + if err := msg.ValidateBasic(); err != nil { + return nil, err + } + + params := k.GetParams(ctx) + if !params.EnableDrip { + return nil, types.ErrDripDisabled + } + + // Check if sender is allowed + authorized := false + for _, addr := range params.AllowedAddresses { + if msg.SenderAddress == addr { + authorized = true + break + } + } + + if !authorized { + return nil, types.ErrDripNotAllowed + } + + // Get sender + sender, err := sdk.AccAddressFromBech32(msg.SenderAddress) + if err != nil { + return nil, err + } + + if err := k.SendCoinsFromAccountToFeeCollector(ctx, sender, msg.Amount); err != nil { + return nil, err + } + + return &types.MsgDistributeTokensResponse{}, nil +} + +func (k Keeper) UpdateParams(goCtx context.Context, req *types.MsgUpdateParams) (*types.MsgUpdateParamsResponse, error) { + if k.authority != req.Authority { + return nil, errorsmod.Wrapf(govtypes.ErrInvalidSigner, "invalid authority; expected %s, got %s", k.authority, req.Authority) + } + + ctx := sdk.UnwrapSDKContext(goCtx) + if err := k.SetParams(ctx, req.Params); err != nil { + return nil, err + } + + return &types.MsgUpdateParamsResponse{}, nil +} diff --git a/x/drip/keeper/msg_server_test.go b/x/drip/keeper/msg_server_test.go new file mode 100644 index 00000000..8cd1e306 --- /dev/null +++ b/x/drip/keeper/msg_server_test.go @@ -0,0 +1,153 @@ +package keeper_test + +import ( + _ "embed" + + "github.com/cosmos/cosmos-sdk/testutil/testdata" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/terpnetwork/terp-core/v4/x/drip/types" +) + +func (s *IntegrationTestSuite) TestDripDistributeTokensMsgs() { + _, _, allowedSender := testdata.KeyTestPubAddr() + _, _, notAllowedSender := testdata.KeyTestPubAddr() + _ = s.FundAccount(s.ctx, allowedSender, sdk.NewCoins(sdk.NewCoin("stake", sdk.NewInt(1_000_000)))) + _ = s.FundAccount(s.ctx, notAllowedSender, sdk.NewCoins(sdk.NewCoin("stake", sdk.NewInt(1_000_000)))) + + _ = s.app.AppKeepers.DripKeeper.SetParams(s.ctx, types.Params{ + EnableDrip: true, + AllowedAddresses: []string{ + allowedSender.String(), + }, + }) + + for _, tc := range []struct { + desc string + senderAddr string + coins sdk.Coins + success bool + }{ + { + desc: "Success - Allowed sender with proper funds", + senderAddr: allowedSender.String(), + coins: sdk.NewCoins(sdk.NewCoin("stake", sdk.NewInt(1))), + success: true, + }, + { + desc: "Fail - Allowed sender no proper funds", + senderAddr: allowedSender.String(), + coins: sdk.NewCoins(sdk.NewCoin("notarealtoken", sdk.NewInt(1))), + success: false, + }, + { + desc: "Fail - Allowed sender no tokens", + senderAddr: allowedSender.String(), + coins: nil, + success: false, + }, + { + desc: "Fail - Allowed sender empty tokens", + senderAddr: allowedSender.String(), + coins: sdk.NewCoins(), + success: false, + }, + { + desc: "Fail - No sender withproper funds", + senderAddr: "", + coins: sdk.NewCoins(sdk.NewCoin("stake", sdk.NewInt(1))), + success: false, + }, + { + desc: "Fail - Non Allowed sender proper funds", + senderAddr: notAllowedSender.String(), + coins: sdk.NewCoins(sdk.NewCoin("stake", sdk.NewInt(1))), + success: false, + }, + { + desc: "Fail - Non Allowed sender improper funds", + senderAddr: notAllowedSender.String(), + coins: sdk.NewCoins(sdk.NewCoin("notarealtoken", sdk.NewInt(1))), + success: false, + }, + } { + tc := tc + s.Run(tc.desc, func() { + msg := types.MsgDistributeTokens{ + SenderAddress: tc.senderAddr, + Amount: tc.coins, + } + _, err := s.app.AppKeepers.DripKeeper.DistributeTokens(s.ctx, &msg) + + if !tc.success { + s.Require().Error(err) + } else { + s.Require().NoError(err) + } + }) + } +} + +func (s *IntegrationTestSuite) TestUpdateDripParams() { + _, _, addr := testdata.KeyTestPubAddr() + _, _, addr2 := testdata.KeyTestPubAddr() + + for _, tc := range []struct { + desc string + isEnabled bool + AllowedAddresses []string + success bool + }{ + { + desc: "Success - Valid on", + isEnabled: true, + AllowedAddresses: []string{}, + success: true, + }, + { + desc: "Success - Valid off", + isEnabled: false, + AllowedAddresses: []string{}, + success: true, + }, + { + desc: "Success - On and 1 allowed address", + isEnabled: true, + AllowedAddresses: []string{addr.String()}, + success: true, + }, + { + desc: "Fail - On and 2 duplicate addresses", + isEnabled: true, + AllowedAddresses: []string{addr.String(), addr.String()}, + success: false, + }, + { + desc: "Success - On and 2 unique", + isEnabled: true, + AllowedAddresses: []string{addr.String(), addr2.String()}, + success: true, + }, + { + desc: "Success - On and 2 duplicate 1 unique", + isEnabled: true, + AllowedAddresses: []string{addr.String(), addr2.String(), addr.String()}, + success: false, + }, + } { + tc := tc + s.Run(tc.desc, func() { + params := types.Params{ + EnableDrip: tc.isEnabled, + AllowedAddresses: tc.AllowedAddresses, + } + err := s.app.AppKeepers.DripKeeper.SetParams(s.ctx, params) + + if !tc.success { + s.Require().Error(err) + } else { + s.Require().NoError(err) + } + }) + } +} diff --git a/x/drip/keeper/params.go b/x/drip/keeper/params.go new file mode 100644 index 00000000..97c06d16 --- /dev/null +++ b/x/drip/keeper/params.go @@ -0,0 +1,31 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/terpnetwork/terp-core/v4/x/drip/types" +) + +// GetParams returns the current x/drip module parameters. +func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) { + store := ctx.KVStore(k.storeKey) + bz := store.Get(types.ParamsKey) + if bz == nil { + return params + } + k.cdc.MustUnmarshal(bz, ¶ms) + return params +} + +// SetParams sets the x/drip module parameters. +func (k Keeper) SetParams(ctx sdk.Context, params types.Params) error { + if err := params.Validate(); err != nil { + return err + } + + store := ctx.KVStore(k.storeKey) + bz := k.cdc.MustMarshal(¶ms) + store.Set(types.ParamsKey, bz) + + return nil +} diff --git a/x/drip/module.go b/x/drip/module.go new file mode 100644 index 00000000..80dac8f5 --- /dev/null +++ b/x/drip/module.go @@ -0,0 +1,189 @@ +package drip + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/gorilla/mux" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/spf13/cobra" + + abci "github.com/cometbft/cometbft/abci/types" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "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" + authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" + + "github.com/terpnetwork/terp-core/v4/x/drip/client/cli" + "github.com/terpnetwork/terp-core/v4/x/drip/keeper" + "github.com/terpnetwork/terp-core/v4/x/drip/types" +) + +// type check to ensure the interface is properly implemented +var ( + _ module.AppModule = AppModule{} + _ module.AppModuleBasic = AppModuleBasic{} + _ module.AppModuleSimulation = AppModule{} +) + +// AppModuleBasic type for the fees module +type AppModuleBasic struct{} + +// Name returns the fees module's name. +func (AppModuleBasic) Name() string { + return types.ModuleName +} + +// RegisterLegacyAminoCodec performs a no-op as the fees do not support Amino +// encoding. +func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + types.RegisterLegacyAminoCodec(cdc) +} + +// ConsensusVersion returns the consensus state-breaking version for the module. +func (AppModuleBasic) ConsensusVersion() uint64 { + return 1 +} + +// RegisterInterfaces registers interfaces and implementations of the fees +// module. +func (AppModuleBasic) RegisterInterfaces(interfaceRegistry codectypes.InterfaceRegistry) { + types.RegisterInterfaces(interfaceRegistry) +} + +// DefaultGenesis returns default genesis state as raw bytes for the fees +// module. +func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage { + return cdc.MustMarshalJSON(types.DefaultGenesisState()) +} + +// ValidateGenesis performs genesis state validation for the fees module. +func (b AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, _ client.TxEncodingConfig, bz json.RawMessage) error { + var genesisState types.GenesisState + if err := cdc.UnmarshalJSON(bz, &genesisState); err != nil { + return fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err) + } + + return genesisState.Validate() +} + +// RegisterRESTRoutes performs a no-op as the fees module doesn't expose REST +// endpoints +func (AppModuleBasic) RegisterRESTRoutes(_ client.Context, _ *mux.Router) {} + +// RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the fees +// module. +func (b AppModuleBasic) RegisterGRPCGatewayRoutes(c client.Context, serveMux *runtime.ServeMux) { + if err := types.RegisterQueryHandlerClient(context.Background(), serveMux, types.NewQueryClient(c)); err != nil { + panic(err) + } +} + +// GetTxCmd returns the root tx command for the fees module. +func (AppModuleBasic) GetTxCmd() *cobra.Command { + return cli.NewTxCmd() +} + +// GetQueryCmd returns the fees module's root query command. +func (AppModuleBasic) GetQueryCmd() *cobra.Command { + return cli.GetQueryCmd() +} + +// ___________________________________________________________________________ + +// AppModule implements the AppModule interface for the fees module. +type AppModule struct { + AppModuleBasic + keeper keeper.Keeper + ak authkeeper.AccountKeeper +} + +// NewAppModule creates a new AppModule Object +func NewAppModule( + k keeper.Keeper, + ak authkeeper.AccountKeeper, +) AppModule { + return AppModule{ + AppModuleBasic: AppModuleBasic{}, + keeper: k, + ak: ak, + } +} + +// Name returns the fees module's name. +func (AppModule) Name() string { + return types.ModuleName +} + +// RegisterInvariants registers the fees module's invariants. +func (am AppModule) RegisterInvariants(_ sdk.InvariantRegistry) {} + +// NewHandler returns nil - fees module doesn't expose tx gRPC endpoints +func (am AppModule) NewHandler() sdk.Handler { + return nil +} + +// QuerierRoute returns the claim module's query routing key. +func (am AppModule) QuerierRoute() string { + return types.RouterKey +} + +// RegisterServices registers a GRPC query service to respond to the +// module-specific GRPC queries. +func (am AppModule) RegisterServices(cfg module.Configurator) { + types.RegisterMsgServer(cfg.MsgServer(), am.keeper) + types.RegisterQueryServer(cfg.QueryServer(), keeper.NewQuerier(am.keeper)) +} + +// BeginBlock executes all ABCI BeginBlock logic respective to the fees module. +func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) { +} + +// EndBlock executes all ABCI EndBlock logic respective to the fee-share module. It +// returns no validator updates. +func (am AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate { + return []abci.ValidatorUpdate{} +} + +// InitGenesis performs the fees module's genesis initialization. It returns +// no validator updates. +func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, data json.RawMessage) []abci.ValidatorUpdate { + var genesisState types.GenesisState + + cdc.MustUnmarshalJSON(data, &genesisState) + InitGenesis(ctx, am.keeper, genesisState) + return []abci.ValidatorUpdate{} +} + +// ExportGenesis returns the fees module's exported genesis state as raw JSON bytes. +func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage { + gs := ExportGenesis(ctx, am.keeper) + return cdc.MustMarshalJSON(gs) +} + +// ___________________________________________________________________________ + +// AppModuleSimulation functions + +// GenerateGenesisState creates a randomized GenState of the fees module. +func (am AppModule) GenerateGenesisState(_ *module.SimulationState) { +} + +// ProposalContents returns content functions for governance proposals. +func (am AppModule) ProposalContents(_ module.SimulationState) []simtypes.WeightedProposalMsg { + return []simtypes.WeightedProposalMsg{} +} + +// RegisterStoreDecoder registers a decoder for fees module's types. +func (am AppModule) RegisterStoreDecoder(_ sdk.StoreDecoderRegistry) { +} + +// WeightedOperations returns fees module weighted operations +func (am AppModule) WeightedOperations(_ module.SimulationState) []simtypes.WeightedOperation { + return []simtypes.WeightedOperation{} +} diff --git a/x/drip/spec/01_authorization.md b/x/drip/spec/01_authorization.md new file mode 100644 index 00000000..b447c9f2 --- /dev/null +++ b/x/drip/spec/01_authorization.md @@ -0,0 +1,43 @@ + + +# Authorization + +For security reasons, only specific addresses can distribute tokens to $JUNO stakers. We accept any kind of address: multisig, smart contracts, regular and [https://daodao.zone](DAODAO) DAOs. + +Governance can decide wether to approve or deny a new address to be added to the authorized list. + +## Query the allowed addresses + +You can query the list of allowed addresses directly from x/drip params + +``` +% terpd q drip params --output json +{"enable_drip":true,"allowed_addresses":[]} +``` + +## Governance proposal + +To update the authorized address is possible to create a onchain new proposal. You can use the following example `proposal.json` file + +```json +{ + "messages": [ + { + "@type": "/juno.drip.v1.MsgUpdateParams", + "authority": "juno10d07y265gmmuvt4z0w9aw880jnsr700jvss730", + "params": { + "enable_drip": false, + "allowed_addresses": ["juno1j0a9ymgngasfn3l5me8qpd53l5zlm9wurfdk7r65s5mg6tkxal3qpgf5se"] + } + } + ], + "metadata": "{\"title\": \"Allow an amazing contract to distribute tokens using drip\", \"authors\": [\"dimi\"], \"summary\": \"If this proposal passes juno1j0a9ymgngasfn3l5me8qpd53l5zlm9wurfdk7r65s5mg6tkxal3qpgf5se will be added to the authorized addresses of the drip module\", \"details\": \"If this proposal passes juno1j0a9ymgngasfn3l5me8qpd53l5zlm9wurfdk7r65s5mg6tkxal3qpgf5se will be added to the authorized addresses of the drip module\", \"proposal_forum_url\": \"https://commonwealth.im/juno/discussion/9697-juno-protocol-level-defi-incentives\", \"vote_option_context\": \"yes\"}", + "deposit": "1000ujuno", + "title": "Allow an amazing contract to distribute tokens using drip", + "summary": "If this proposal passes juno1j0a9ymgngasfn3l5me8qpd53l5zlm9wurfdk7r65s5mg6tkxal3qpgf5se will be added to the authorized addresses of the drip module" +} +``` + +It can be submitted with the standard `terpd tx gov submit-proposal proposal.json --from yourkey` command. diff --git a/x/drip/spec/02_distribute_tokens.md b/x/drip/spec/02_distribute_tokens.md new file mode 100644 index 00000000..f7fd29f9 --- /dev/null +++ b/x/drip/spec/02_distribute_tokens.md @@ -0,0 +1,17 @@ + + +# Distributing Tokens + +Once an address is authorized, at any time it can use the `MsgDistributToken` message to distribute all the attached funds at the next block. + +From command line is as easy as running the follwing instruction + +``` +terpd tx drip distribute-tokens 100000tf/yourcontract/yourtoken +``` + +Only native tokens and the ones made with tokenfactory are allowed. + +If you have a CW-20 token, you can wrap it to native using [https://github.com/CosmosContracts/tokenfactory-contracts/tree/main/contracts/migrate](this contract). \ No newline at end of file diff --git a/x/drip/spec/03_example.md b/x/drip/spec/03_example.md new file mode 100644 index 00000000..340d70ed --- /dev/null +++ b/x/drip/spec/03_example.md @@ -0,0 +1,33 @@ + + +# Example contract + +The following code is an example function to encode a `MsgDistributeTokens` message in CosmWasm + +```rust +fn encode_msg_create_vesting_acct(vest_to: &Addr, env: Env) -> Result { + + // Test with 1 ucosm + let one_cosm: Coin = coin(1_000_000, "ucosm"); + + // MsgDistributeTokens + + let proto = Anybuf::new() + .append_string(1, &env.contract.address) + .append_message(2, &Anybuf::new() + .append_string(1, &one_cosm.denom) + .append_string(2, &one_cosm.amount.to_string()) + ) + .into_vec(); + + let msg = CosmosMsg::Stargate { + type_url: "/juno.drip.v1.MsgDistributeTokens".to_string(), + value: proto.into() + }; + +} +``` + +More information about [https://lib.rs/crates/anybuf](Anybuf) \ No newline at end of file diff --git a/x/drip/spec/README.md b/x/drip/spec/README.md new file mode 100644 index 00000000..79b596ee --- /dev/null +++ b/x/drip/spec/README.md @@ -0,0 +1,24 @@ + + +# `drip` + +## Abstract + +This document specifies the internal `x/drip` module of Juno Network. + +The `x/drip` allows specific addresses (usually smart contracts) to send tokens to the fee_pool module in order to perform a live airdrop to Juno Stakers. + +It consists only on one new message `MsgDistributeTokens`, when called from an authorized address all the funds sent with it are distributed at the next block. + +On an ideal scenario, projects are allocating tokens to a smart contract that then split the amount over a custom schedule, using for example [https://www.cron.cat/](CronCat). + +## Contents + +1. **[Authorization](01_authorization.md)** +2. **[Distribute Tokens](02_distribute_tokens.md)** +3. **[Example Contract](03_example.md)** \ No newline at end of file diff --git a/x/drip/types/codec.go b/x/drip/types/codec.go new file mode 100644 index 00000000..21193656 --- /dev/null +++ b/x/drip/types/codec.go @@ -0,0 +1,57 @@ +package types + +import ( + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" + authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" +) + +var ( + amino = codec.NewLegacyAmino() + + // ModuleCdc references the global erc20 module codec. Note, the codec should + // ONLY be used in certain instances of tests and for JSON encoding. + // + // The actual codec used for serialization should be provided to modules/erc20 and + // defined at the application level. + ModuleCdc = codec.NewProtoCodec(codectypes.NewInterfaceRegistry()) + + // AminoCdc is a amino codec created to support amino JSON compatible msgs. + AminoCdc = codec.NewAminoCodec(amino) +) + +const ( + // Amino names + distributeTokensName = "juno/MsgDistributeTokens" //nolint:gosec // these are not hard coded credentials +) + +// NOTE: This is required for the GetSignBytes function +func init() { + RegisterLegacyAminoCodec(amino) + sdk.RegisterLegacyAminoCodec(amino) + amino.Seal() + + // Register all Amino interfaces and concrete types on the authz Amino codec + // so that this can later be used to properly serialize MsgGrant and MsgExec + // instances. + RegisterLegacyAminoCodec(authzcodec.Amino) +} + +// RegisterInterfaces register implementations +func RegisterInterfaces(registry codectypes.InterfaceRegistry) { + registry.RegisterImplementations( + (*sdk.Msg)(nil), + &MsgDistributeTokens{}, + ) + + msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) +} + +// RegisterLegacyAminoCodec registers the necessary x/FeeShare interfaces and +// concrete types on the provided LegacyAmino codec. These types are used for +// Amino JSON serialization and EIP-712 compatibility. +func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + cdc.RegisterConcrete(&MsgDistributeTokens{}, distributeTokensName, nil) +} diff --git a/x/drip/types/codec_test.go b/x/drip/types/codec_test.go new file mode 100644 index 00000000..91e31bd4 --- /dev/null +++ b/x/drip/types/codec_test.go @@ -0,0 +1,31 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +type CodecTestSuite struct { + suite.Suite +} + +func TestCodecSuite(t *testing.T) { + suite.Run(t, new(CodecTestSuite)) +} + +func (suite *CodecTestSuite) TestRegisterInterfaces() { + registry := codectypes.NewInterfaceRegistry() + registry.RegisterInterface(sdk.MsgInterfaceProtoName, (*sdk.Msg)(nil)) + RegisterInterfaces(registry) + + impls := registry.ListImplementations(sdk.MsgInterfaceProtoName) + suite.Require().Equal(2, len(impls)) + suite.Require().ElementsMatch([]string{ + "/terp.drip.v1.MsgDistributeTokens", + "/terp.drip.v1.MsgUpdateParams", + }, impls) +} diff --git a/x/drip/types/errors.go b/x/drip/types/errors.go new file mode 100644 index 00000000..15348c3c --- /dev/null +++ b/x/drip/types/errors.go @@ -0,0 +1,13 @@ +package types + +import ( + errorsmod "cosmossdk.io/errors" +) + +var ( + ErrDripDisabled = errorsmod.Register(ModuleName, 1, "drip module is disabled by governance") + ErrDripNotAllowed = errorsmod.Register(ModuleName, 2, "this address is not allowed to use the module, you can request access from governance") + ErrEmpty = errorsmod.Register(ModuleName, 3, "empty") + ErrDuplicate = errorsmod.Register(ModuleName, 4, "duplicate") + ErrBlank = errorsmod.Register(ModuleName, 5, "address cannot be blank") +) diff --git a/x/drip/types/expected_keepers.go b/x/drip/types/expected_keepers.go new file mode 100644 index 00000000..8669c874 --- /dev/null +++ b/x/drip/types/expected_keepers.go @@ -0,0 +1,13 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// BankKeeper defines the expected interface needed to retrieve account balances. +type BankKeeper interface { + SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error + + MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error + SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error +} diff --git a/x/drip/types/genesis.go b/x/drip/types/genesis.go new file mode 100644 index 00000000..0b122569 --- /dev/null +++ b/x/drip/types/genesis.go @@ -0,0 +1,22 @@ +package types + +// NewGenesisState creates a new genesis state. +func NewGenesisState(params Params) GenesisState { + return GenesisState{ + Params: params, + } +} + +// DefaultGenesisState sets default evm genesis state with empty accounts and +// default params and chain config values. +func DefaultGenesisState() *GenesisState { + return &GenesisState{ + Params: DefaultParams(), + } +} + +// Validate performs basic genesis state validation returning an error upon any +// failure. +func (gs GenesisState) Validate() error { + return gs.Params.Validate() +} diff --git a/x/drip/types/genesis.pb.go b/x/drip/types/genesis.pb.go new file mode 100644 index 00000000..c593ff93 --- /dev/null +++ b/x/drip/types/genesis.pb.go @@ -0,0 +1,544 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: terp/drip/v1/genesis.proto + +package types + +import ( + fmt "fmt" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// GenesisState defines the module's genesis state. +type GenesisState struct { + // params are the drip module parameters + Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` +} + +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_b842c18af9c609d4, []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) GetParams() Params { + if m != nil { + return m.Params + } + return Params{} +} + +// Params defines the drip module params +type Params struct { + // enable_drip defines a parameter to enable the drip module + EnableDrip bool `protobuf:"varint,1,opt,name=enable_drip,json=enableDrip,proto3" json:"enable_drip,omitempty"` + // allowed_addresses defines the list of addresses authorized to use the module + AllowedAddresses []string `protobuf:"bytes,3,rep,name=allowed_addresses,json=allowedAddresses,proto3" json:"allowed_addresses,omitempty" yaml:"addresses"` +} + +func (m *Params) Reset() { *m = Params{} } +func (m *Params) String() string { return proto.CompactTextString(m) } +func (*Params) ProtoMessage() {} +func (*Params) Descriptor() ([]byte, []int) { + return fileDescriptor_b842c18af9c609d4, []int{1} +} +func (m *Params) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Params) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Params.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 *Params) XXX_Merge(src proto.Message) { + xxx_messageInfo_Params.Merge(m, src) +} +func (m *Params) XXX_Size() int { + return m.Size() +} +func (m *Params) XXX_DiscardUnknown() { + xxx_messageInfo_Params.DiscardUnknown(m) +} + +var xxx_messageInfo_Params proto.InternalMessageInfo + +func (m *Params) GetEnableDrip() bool { + if m != nil { + return m.EnableDrip + } + return false +} + +func (m *Params) GetAllowedAddresses() []string { + if m != nil { + return m.AllowedAddresses + } + return nil +} + +func init() { + proto.RegisterType((*GenesisState)(nil), "terp.drip.v1.GenesisState") + proto.RegisterType((*Params)(nil), "terp.drip.v1.Params") +} + +func init() { proto.RegisterFile("terp/drip/v1/genesis.proto", fileDescriptor_b842c18af9c609d4) } + +var fileDescriptor_b842c18af9c609d4 = []byte{ + // 271 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x2a, 0x49, 0x2d, 0x2a, + 0xd0, 0x4f, 0x29, 0xca, 0x2c, 0xd0, 0x2f, 0x33, 0xd4, 0x4f, 0x4f, 0xcd, 0x4b, 0x2d, 0xce, 0x2c, + 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x01, 0xc9, 0xe9, 0x81, 0xe4, 0xf4, 0xca, 0x0c, + 0xa5, 0x44, 0xd2, 0xf3, 0xd3, 0xf3, 0xc1, 0x12, 0xfa, 0x20, 0x16, 0x44, 0x8d, 0x92, 0x13, 0x17, + 0x8f, 0x3b, 0x44, 0x53, 0x70, 0x49, 0x62, 0x49, 0xaa, 0x90, 0x11, 0x17, 0x5b, 0x41, 0x62, 0x51, + 0x62, 0x6e, 0xb1, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0xb7, 0x91, 0x88, 0x1e, 0xb2, 0x21, 0x7a, 0x01, + 0x60, 0x39, 0x27, 0x96, 0x13, 0xf7, 0xe4, 0x19, 0x82, 0xa0, 0x2a, 0x95, 0x72, 0xb8, 0xd8, 0x20, + 0xe2, 0x42, 0xf2, 0x5c, 0xdc, 0xa9, 0x79, 0x89, 0x49, 0x39, 0xa9, 0xf1, 0x20, 0x0d, 0x60, 0x23, + 0x38, 0x82, 0xb8, 0x20, 0x42, 0x2e, 0x45, 0x99, 0x05, 0x42, 0x8e, 0x5c, 0x82, 0x89, 0x39, 0x39, + 0xf9, 0xe5, 0xa9, 0x29, 0xf1, 0x89, 0x29, 0x29, 0x45, 0xa9, 0xc5, 0xc5, 0xa9, 0xc5, 0x12, 0xcc, + 0x0a, 0xcc, 0x1a, 0x9c, 0x4e, 0x22, 0x9f, 0xee, 0xc9, 0x0b, 0x54, 0x26, 0xe6, 0xe6, 0x58, 0x29, + 0xc1, 0xa5, 0x94, 0x82, 0x04, 0xa0, 0xca, 0x1d, 0x61, 0x42, 0x4e, 0xee, 0x27, 0x1e, 0xc9, 0x31, + 0x5e, 0x78, 0x24, 0xc7, 0xf8, 0xe0, 0x91, 0x1c, 0xe3, 0x84, 0xc7, 0x72, 0x0c, 0x17, 0x1e, 0xcb, + 0x31, 0xdc, 0x78, 0x2c, 0xc7, 0x10, 0xa5, 0x9b, 0x9e, 0x59, 0x92, 0x51, 0x9a, 0xa4, 0x97, 0x9c, + 0x9f, 0xab, 0x0f, 0x72, 0x75, 0x5e, 0x6a, 0x49, 0x79, 0x7e, 0x51, 0x36, 0x98, 0xad, 0x9b, 0x9c, + 0x5f, 0x94, 0xaa, 0x5f, 0x01, 0x09, 0xa9, 0x92, 0xca, 0x82, 0xd4, 0xe2, 0x24, 0x36, 0x70, 0x08, + 0x18, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0x49, 0x28, 0x65, 0xc1, 0x43, 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 + { + size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *Params) 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 *Params) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.AllowedAddresses) > 0 { + for iNdEx := len(m.AllowedAddresses) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.AllowedAddresses[iNdEx]) + copy(dAtA[i:], m.AllowedAddresses[iNdEx]) + i = encodeVarintGenesis(dAtA, i, uint64(len(m.AllowedAddresses[iNdEx]))) + i-- + dAtA[i] = 0x1a + } + } + if m.EnableDrip { + i-- + if m.EnableDrip { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x8 + } + 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 = m.Params.Size() + n += 1 + l + sovGenesis(uint64(l)) + return n +} + +func (m *Params) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.EnableDrip { + n += 2 + } + if len(m.AllowedAddresses) > 0 { + for _, s := range m.AllowedAddresses { + l = len(s) + 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 Params", 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 + } + if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Params) 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: Params: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Params: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field EnableDrip", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.EnableDrip = bool(v != 0) + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AllowedAddresses", 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.AllowedAddresses = append(m.AllowedAddresses, string(dAtA[iNdEx:postIndex])) + 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/drip/types/keys.go b/x/drip/types/keys.go new file mode 100644 index 00000000..75a829fd --- /dev/null +++ b/x/drip/types/keys.go @@ -0,0 +1,17 @@ +package types + +const ( + // module name + ModuleName = "drip" + + // StoreKey to be used when creating the KVStore + StoreKey = ModuleName + + // RouterKey to be used for message routing + RouterKey = ModuleName +) + +// KVStore key prefixes +var ( + ParamsKey = []byte{0x00} // Prefix for params key +) diff --git a/x/drip/types/msg.go b/x/drip/types/msg.go new file mode 100644 index 00000000..e0b82597 --- /dev/null +++ b/x/drip/types/msg.go @@ -0,0 +1,89 @@ +package types + +import ( + fmt "fmt" + + errorsmod "cosmossdk.io/errors" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +var ( + _ sdk.Msg = &MsgDistributeTokens{} + _ sdk.Msg = &MsgUpdateParams{} +) + +const ( + TypeMsgDistributeTokens = "distribute_tokens" +) + +// NewMsgDistributeTokens creates new instance of MsgDistributeTokens +func NewMsgDistributeTokens( + amount sdk.Coins, + sender sdk.Address, +) *MsgDistributeTokens { + return &MsgDistributeTokens{ + SenderAddress: sender.String(), + Amount: amount, + } +} + +// Route returns the name of the module +func (msg MsgDistributeTokens) Route() string { return RouterKey } + +// Type returns the the action +func (msg MsgDistributeTokens) Type() string { return TypeMsgDistributeTokens } + +// ValidateBasic runs stateless checks on the message +func (msg MsgDistributeTokens) ValidateBasic() error { + if msg.SenderAddress == "" { + return fmt.Errorf("sender address cannot be empty") + } + + if _, err := sdk.AccAddressFromBech32(msg.SenderAddress); err != nil { + return errorsmod.Wrapf(err, "invalid sender address: %s", err.Error()) + } + + if msg.Amount == nil || msg.Amount.Empty() { + return fmt.Errorf("invalid coins: %s", msg.Amount.String()) + } + + if !msg.Amount.IsValid() { + return fmt.Errorf("invalid coins: %s", msg.Amount.String()) + } + + return nil +} + +// GetSignBytes encodes the message for signing +func (msg *MsgDistributeTokens) GetSignBytes() []byte { + return sdk.MustSortJSON(AminoCdc.MustMarshalJSON(msg)) +} + +// GetSigners defines whose signature is required +func (msg MsgDistributeTokens) GetSigners() []sdk.AccAddress { + from, _ := sdk.AccAddressFromBech32(msg.SenderAddress) + return []sdk.AccAddress{from} +} + +// GetSignBytes implements the LegacyMsg interface. +func (msg MsgUpdateParams) GetSignBytes() []byte { + return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&msg)) +} + +// GetSigners returns the expected signers for a MsgUpdateParams message. +func (msg *MsgUpdateParams) GetSigners() []sdk.AccAddress { + addr, _ := sdk.AccAddressFromBech32(msg.Authority) + return []sdk.AccAddress{addr} +} + +// ValidateBasic does a sanity check on the provided data. +func (msg *MsgUpdateParams) ValidateBasic() error { + if _, err := sdk.AccAddressFromBech32(msg.Authority); err != nil { + return errorsmod.Wrap(err, "invalid authority address") + } + + err := msg.Params.Validate() + + return err +} diff --git a/x/drip/types/msg_test.go b/x/drip/types/msg_test.go new file mode 100644 index 00000000..8b60a620 --- /dev/null +++ b/x/drip/types/msg_test.go @@ -0,0 +1,81 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +type MsgsTestSuite struct { + suite.Suite + amount sdk.Coins + sender sdk.AccAddress +} + +func TestMsgsTestSuite(t *testing.T) { + suite.Run(t, new(MsgsTestSuite)) +} + +func (suite *MsgsTestSuite) SetupTest() { + sender := "cosmos1" + suite.sender = sdk.AccAddress([]byte(sender)) + suite.amount = sdk.NewCoins(sdk.NewCoin("ujuice", sdk.NewInt(1000000))) +} + +func (suite *MsgsTestSuite) TestMsgDistributeTokensGetters() { + msgInvalid := MsgDistributeTokens{} + msg := NewMsgDistributeTokens( + suite.amount, + suite.sender, + ) + suite.Require().Equal(RouterKey, msg.Route()) + suite.Require().Equal(TypeMsgDistributeTokens, msg.Type()) + suite.Require().NotNil(msgInvalid.GetSignBytes()) + suite.Require().NotNil(msg.GetSigners()) +} + +func (suite *MsgsTestSuite) TestMsgDistributeTokensNew() { + testCases := []struct { + msg string + amount sdk.Coins + sender string + expectPass bool + }{ + { + "pass", + suite.amount, + suite.sender.String(), + true, + }, + { + "sender address cannot be empty", + suite.amount, + "", + false, + }, + { + "invalid coins", + nil, + suite.sender.String(), + false, + }, + } + + for i, tc := range testCases { + tx := MsgDistributeTokens{ + Amount: tc.amount, + SenderAddress: tc.sender, + } + + err := tx.ValidateBasic() + + if tc.expectPass { + suite.Require().NoError(err, "valid test %d failed: %s", i, tc.msg) + } else { + suite.Require().Error(err, "invalid test %d passed: %s", i, tc.msg) + suite.Require().Contains(err.Error(), tc.msg) + } + } +} diff --git a/x/drip/types/params.go b/x/drip/types/params.go new file mode 100644 index 00000000..b7276006 --- /dev/null +++ b/x/drip/types/params.go @@ -0,0 +1,80 @@ +package types + +import ( + "fmt" + + errorsmod "cosmossdk.io/errors" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +var ( + DefaultEnableDrip = true + DefaultAllowedAddresses = []string(nil) // no one allowed +) + +// NewParams creates a new Params object +func NewParams( + enableDrip bool, + allowedAddresses []string, +) Params { + return Params{ + EnableDrip: enableDrip, + AllowedAddresses: allowedAddresses, + } +} + +// DefaultParams returns default x/drip module parameters. +func DefaultParams() Params { + return Params{ + EnableDrip: DefaultEnableDrip, + AllowedAddresses: DefaultAllowedAddresses, + } +} + +func validateBool(i interface{}) error { + _, ok := i.(bool) + if !ok { + return fmt.Errorf("invalid parameter type: %T", i) + } + + return nil +} + +func validateArray(i interface{}) error { + _, ok := i.([]string) + if !ok { + return fmt.Errorf("invalid parameter type: %T", i) + } + + return nil +} + +func (p Params) Validate() error { + if err := validateBool(p.EnableDrip); err != nil { + return err + } + + if err := validateArray(p.AllowedAddresses); err != nil { + return err + } + + return assertValidAddresses(p.AllowedAddresses) +} + +func assertValidAddresses(addrs []string) error { + idx := make(map[string]struct{}, len(addrs)) + for _, a := range addrs { + if a == "" { + return ErrBlank.Wrapf("address: %s", a) + } + if _, err := sdk.AccAddressFromBech32(a); err != nil { + return errorsmod.Wrapf(err, "address: %s", a) + } + if _, exists := idx[a]; exists { + return ErrDuplicate.Wrapf("address: %s", a) + } + idx[a] = struct{}{} + } + return nil +} diff --git a/x/drip/types/params_test.go b/x/drip/types/params_test.go new file mode 100644 index 00000000..8666e15f --- /dev/null +++ b/x/drip/types/params_test.go @@ -0,0 +1,50 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestParamsValidate(t *testing.T) { + testCases := []struct { + name string + params Params + expError bool + }{ + {"default", DefaultParams(), false}, + { + "valid: disabled, no one allowed", + NewParams(false, []string(nil)), + false, + }, + { + "invalid: enabled, address malformed", + NewParams(false, []string{"invalid address"}), + true, + }, + } + + for _, tc := range testCases { + err := tc.params.Validate() + + if tc.expError { + require.Error(t, err, tc.name) + } else { + require.NoError(t, err, tc.name) + } + } +} + +func TestParamsValidateBool(t *testing.T) { + err := validateBool(DefaultEnableDrip) + require.NoError(t, err) + err = validateBool(true) + require.NoError(t, err) + err = validateBool(false) + require.NoError(t, err) + err = validateBool("") + require.Error(t, err) + err = validateBool(int64(123)) + require.Error(t, err) +} diff --git a/x/drip/types/query.pb.go b/x/drip/types/query.pb.go new file mode 100644 index 00000000..61763e91 --- /dev/null +++ b/x/drip/types/query.pb.go @@ -0,0 +1,537 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: terp/drip/v1/query.proto + +package types + +import ( + context "context" + fmt "fmt" + _ "github.com/cosmos/cosmos-sdk/types/query" + _ "github.com/cosmos/gogoproto/gogoproto" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/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" + 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 + +// QueryParamsRequest is the request type for the Query/Params RPC method. +type QueryParamsRequest struct { +} + +func (m *QueryParamsRequest) Reset() { *m = QueryParamsRequest{} } +func (m *QueryParamsRequest) String() string { return proto.CompactTextString(m) } +func (*QueryParamsRequest) ProtoMessage() {} +func (*QueryParamsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_49d98c9a9d63ede3, []int{0} +} +func (m *QueryParamsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryParamsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryParamsRequest.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 *QueryParamsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryParamsRequest.Merge(m, src) +} +func (m *QueryParamsRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryParamsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryParamsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryParamsRequest proto.InternalMessageInfo + +// QueryParamsResponse is the response type for the Query/Params RPC method. +type QueryParamsResponse struct { + // params is the returned parameter from the module + Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` +} + +func (m *QueryParamsResponse) Reset() { *m = QueryParamsResponse{} } +func (m *QueryParamsResponse) String() string { return proto.CompactTextString(m) } +func (*QueryParamsResponse) ProtoMessage() {} +func (*QueryParamsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_49d98c9a9d63ede3, []int{1} +} +func (m *QueryParamsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryParamsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryParamsResponse.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 *QueryParamsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryParamsResponse.Merge(m, src) +} +func (m *QueryParamsResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryParamsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryParamsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryParamsResponse proto.InternalMessageInfo + +func (m *QueryParamsResponse) GetParams() Params { + if m != nil { + return m.Params + } + return Params{} +} + +func init() { + proto.RegisterType((*QueryParamsRequest)(nil), "terp.drip.v1.QueryParamsRequest") + proto.RegisterType((*QueryParamsResponse)(nil), "terp.drip.v1.QueryParamsResponse") +} + +func init() { proto.RegisterFile("terp/drip/v1/query.proto", fileDescriptor_49d98c9a9d63ede3) } + +var fileDescriptor_49d98c9a9d63ede3 = []byte{ + // 301 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x50, 0xbf, 0x4a, 0x03, 0x31, + 0x18, 0xbf, 0x13, 0xed, 0x70, 0x3a, 0x9d, 0x87, 0x94, 0xa3, 0xc4, 0xda, 0x49, 0x84, 0x26, 0x5c, + 0x7d, 0x83, 0x2e, 0xe2, 0xa6, 0x1d, 0xdd, 0x72, 0xf5, 0x23, 0x86, 0xda, 0x7c, 0x69, 0x92, 0x56, + 0xbb, 0xfa, 0x04, 0x82, 0x2f, 0xd5, 0xb1, 0xe0, 0xe2, 0x24, 0xd2, 0xf3, 0x41, 0xe4, 0x92, 0x1b, + 0x3c, 0x04, 0xb7, 0x1f, 0xbf, 0xbf, 0xc9, 0x97, 0x74, 0x1d, 0x18, 0xcd, 0xee, 0x8d, 0xd4, 0x6c, + 0x55, 0xb0, 0xc5, 0x12, 0xcc, 0x9a, 0x6a, 0x83, 0x0e, 0xd3, 0xa3, 0x5a, 0xa1, 0xb5, 0x42, 0x57, + 0x45, 0x7e, 0x31, 0x45, 0x3b, 0x47, 0xcb, 0x4a, 0x6e, 0x21, 0xd8, 0xd8, 0xaa, 0x28, 0xc1, 0xf1, + 0x82, 0x69, 0x2e, 0xa4, 0xe2, 0x4e, 0xa2, 0x0a, 0xc9, 0x3c, 0x6f, 0x75, 0x0a, 0x50, 0x60, 0xa5, + 0x6d, 0xb4, 0x4c, 0xa0, 0x40, 0x0f, 0x59, 0x8d, 0x1a, 0xb6, 0x27, 0x10, 0xc5, 0x23, 0x30, 0xae, + 0x25, 0xe3, 0x4a, 0xa1, 0xf3, 0x75, 0x4d, 0x66, 0x90, 0x25, 0xe9, 0x6d, 0xbd, 0x78, 0xc3, 0x0d, + 0x9f, 0xdb, 0x09, 0x2c, 0x96, 0x60, 0xdd, 0xe0, 0x3a, 0x39, 0x6e, 0xb1, 0x56, 0xa3, 0xb2, 0x90, + 0x8e, 0x92, 0x8e, 0xf6, 0x4c, 0x37, 0xee, 0xc7, 0xe7, 0x87, 0xa3, 0x8c, 0xfe, 0xfe, 0x07, 0x0d, + 0xee, 0xf1, 0xfe, 0xe6, 0xf3, 0x34, 0x9a, 0x34, 0xce, 0x91, 0x4b, 0x0e, 0x7c, 0x55, 0x3a, 0x4b, + 0x3a, 0xc1, 0x90, 0xf6, 0xdb, 0xb1, 0xbf, 0xfb, 0xf9, 0xd9, 0x3f, 0x8e, 0xf0, 0x96, 0x41, 0xef, + 0xe5, 0xfd, 0xfb, 0x6d, 0xef, 0x24, 0xcd, 0x58, 0xeb, 0x22, 0x61, 0x75, 0x7c, 0xb5, 0xd9, 0x91, + 0x78, 0xbb, 0x23, 0xf1, 0xd7, 0x8e, 0xc4, 0xaf, 0x15, 0x89, 0xb6, 0x15, 0x89, 0x3e, 0x2a, 0x12, + 0xdd, 0x0d, 0x85, 0x74, 0x0f, 0xcb, 0x92, 0x4e, 0x71, 0xee, 0x93, 0x0a, 0xdc, 0x13, 0x9a, 0x99, + 0xc7, 0xc3, 0x29, 0x1a, 0x60, 0xcf, 0xa1, 0xcc, 0xad, 0x35, 0xd8, 0xb2, 0xe3, 0xcf, 0x74, 0xf9, + 0x13, 0x00, 0x00, 0xff, 0xff, 0xc1, 0x04, 0x80, 0x27, 0xcc, 0x01, 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 { + // Params retrieves the Drip module params + Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) +} + +type queryClient struct { + cc grpc1.ClientConn +} + +func NewQueryClient(cc grpc1.ClientConn) QueryClient { + return &queryClient{cc} +} + +func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) { + out := new(QueryParamsResponse) + err := c.cc.Invoke(ctx, "/terp.drip.v1.Query/Params", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// QueryServer is the server API for Query service. +type QueryServer interface { + // Params retrieves the Drip module params + Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error) +} + +// UnimplementedQueryServer can be embedded to have forward compatible implementations. +type UnimplementedQueryServer struct { +} + +func (*UnimplementedQueryServer) Params(ctx context.Context, req *QueryParamsRequest) (*QueryParamsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Params not implemented") +} + +func RegisterQueryServer(s grpc1.Server, srv QueryServer) { + s.RegisterService(&_Query_serviceDesc, srv) +} + +func _Query_Params_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryParamsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Params(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/terp.drip.v1.Query/Params", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Params(ctx, req.(*QueryParamsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Query_serviceDesc = grpc.ServiceDesc{ + ServiceName: "terp.drip.v1.Query", + HandlerType: (*QueryServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Params", + Handler: _Query_Params_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "terp/drip/v1/query.proto", +} + +func (m *QueryParamsRequest) 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 *QueryParamsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryParamsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryParamsResponse) 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 *QueryParamsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { + offset -= sovQuery(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *QueryParamsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryParamsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Params.Size() + 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 *QueryParamsRequest) 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: QueryParamsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryParamsRequest: 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 *QueryParamsResponse) 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: QueryParamsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipQuery(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + 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/drip/types/query.pb.gw.go b/x/drip/types/query.pb.gw.go new file mode 100644 index 00000000..62b14aea --- /dev/null +++ b/x/drip/types/query.pb.gw.go @@ -0,0 +1,153 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: terp/drip/v1/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/metadata" + "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 +var _ = metadata.Join + +func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryParamsRequest + var metadata runtime.ServerMetadata + + msg, err := client.Params(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryParamsRequest + var metadata runtime.ServerMetadata + + msg, err := server.Params(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 to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Params_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Params_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_Params_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_Params_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_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +var ( + pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"terp", "drip", "v1", "params"}, "", runtime.AssumeColonVerbOpt(false))) +) + +var ( + forward_Query_Params_0 = runtime.ForwardResponseMessage +) diff --git a/x/drip/types/tx.pb.go b/x/drip/types/tx.pb.go new file mode 100644 index 00000000..1c6c0b85 --- /dev/null +++ b/x/drip/types/tx.pb.go @@ -0,0 +1,1003 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: terp/drip/v1/tx.proto + +package types + +import ( + context "context" + fmt "fmt" + _ "github.com/cosmos/cosmos-proto" + github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" + types "github.com/cosmos/cosmos-sdk/types" + _ "github.com/cosmos/cosmos-sdk/types/msgservice" + _ "github.com/cosmos/cosmos-sdk/types/tx/amino" + _ "github.com/cosmos/gogoproto/gogoproto" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + _ "google.golang.org/genproto/googleapis/api/annotations" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + 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 + +// MsgDistributeTokens defines a message that registers a Distribution of tokens. +type MsgDistributeTokens struct { + // sender_address is the bech32 address of message sender. + SenderAddress string `protobuf:"bytes,1,opt,name=sender_address,json=senderAddress,proto3" json:"sender_address,omitempty"` + // amount is the amount being airdropped to stakers + Amount github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,2,rep,name=amount,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"amount"` +} + +func (m *MsgDistributeTokens) Reset() { *m = MsgDistributeTokens{} } +func (m *MsgDistributeTokens) String() string { return proto.CompactTextString(m) } +func (*MsgDistributeTokens) ProtoMessage() {} +func (*MsgDistributeTokens) Descriptor() ([]byte, []int) { + return fileDescriptor_a3811651dcd5f057, []int{0} +} +func (m *MsgDistributeTokens) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgDistributeTokens) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgDistributeTokens.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 *MsgDistributeTokens) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgDistributeTokens.Merge(m, src) +} +func (m *MsgDistributeTokens) XXX_Size() int { + return m.Size() +} +func (m *MsgDistributeTokens) XXX_DiscardUnknown() { + xxx_messageInfo_MsgDistributeTokens.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgDistributeTokens proto.InternalMessageInfo + +func (m *MsgDistributeTokens) GetSenderAddress() string { + if m != nil { + return m.SenderAddress + } + return "" +} + +func (m *MsgDistributeTokens) GetAmount() github_com_cosmos_cosmos_sdk_types.Coins { + if m != nil { + return m.Amount + } + return nil +} + +// MsgDistributeTokensResponse defines the MsgDistributeTokens response type +type MsgDistributeTokensResponse struct { +} + +func (m *MsgDistributeTokensResponse) Reset() { *m = MsgDistributeTokensResponse{} } +func (m *MsgDistributeTokensResponse) String() string { return proto.CompactTextString(m) } +func (*MsgDistributeTokensResponse) ProtoMessage() {} +func (*MsgDistributeTokensResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_a3811651dcd5f057, []int{1} +} +func (m *MsgDistributeTokensResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgDistributeTokensResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgDistributeTokensResponse.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 *MsgDistributeTokensResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgDistributeTokensResponse.Merge(m, src) +} +func (m *MsgDistributeTokensResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgDistributeTokensResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgDistributeTokensResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgDistributeTokensResponse proto.InternalMessageInfo + +// MsgUpdateParams is the Msg/UpdateParams request type. +// +// Since: cosmos-sdk 0.47 +type MsgUpdateParams struct { + // authority is the address that controls the module (defaults to x/gov unless overwritten). + Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` + // params defines the x/auth parameters to update. + // + // NOTE: All parameters must be supplied. + Params Params `protobuf:"bytes,2,opt,name=params,proto3" json:"params"` +} + +func (m *MsgUpdateParams) Reset() { *m = MsgUpdateParams{} } +func (m *MsgUpdateParams) String() string { return proto.CompactTextString(m) } +func (*MsgUpdateParams) ProtoMessage() {} +func (*MsgUpdateParams) Descriptor() ([]byte, []int) { + return fileDescriptor_a3811651dcd5f057, []int{2} +} +func (m *MsgUpdateParams) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateParams.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 *MsgUpdateParams) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateParams.Merge(m, src) +} +func (m *MsgUpdateParams) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateParams) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateParams.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUpdateParams proto.InternalMessageInfo + +func (m *MsgUpdateParams) GetAuthority() string { + if m != nil { + return m.Authority + } + return "" +} + +func (m *MsgUpdateParams) GetParams() Params { + if m != nil { + return m.Params + } + return Params{} +} + +type MsgUpdateParamsResponse struct { +} + +func (m *MsgUpdateParamsResponse) Reset() { *m = MsgUpdateParamsResponse{} } +func (m *MsgUpdateParamsResponse) String() string { return proto.CompactTextString(m) } +func (*MsgUpdateParamsResponse) ProtoMessage() {} +func (*MsgUpdateParamsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_a3811651dcd5f057, []int{3} +} +func (m *MsgUpdateParamsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateParamsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateParamsResponse.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 *MsgUpdateParamsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateParamsResponse.Merge(m, src) +} +func (m *MsgUpdateParamsResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateParamsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateParamsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUpdateParamsResponse proto.InternalMessageInfo + +func init() { + proto.RegisterType((*MsgDistributeTokens)(nil), "terp.drip.v1.MsgDistributeTokens") + proto.RegisterType((*MsgDistributeTokensResponse)(nil), "terp.drip.v1.MsgDistributeTokensResponse") + proto.RegisterType((*MsgUpdateParams)(nil), "terp.drip.v1.MsgUpdateParams") + proto.RegisterType((*MsgUpdateParamsResponse)(nil), "terp.drip.v1.MsgUpdateParamsResponse") +} + +func init() { proto.RegisterFile("terp/drip/v1/tx.proto", fileDescriptor_a3811651dcd5f057) } + +var fileDescriptor_a3811651dcd5f057 = []byte{ + // 559 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x93, 0x3f, 0x6f, 0x13, 0x4d, + 0x10, 0xc6, 0x7d, 0xc9, 0xab, 0x48, 0xde, 0xf8, 0xe5, 0xcf, 0x61, 0x14, 0xdb, 0x90, 0xb3, 0x73, + 0x22, 0x92, 0xb1, 0xe4, 0x5b, 0xd9, 0x20, 0x90, 0xd2, 0x61, 0x10, 0x54, 0x96, 0x90, 0x09, 0x0d, + 0x8d, 0xb5, 0xf6, 0xad, 0x36, 0x2b, 0xe7, 0x76, 0x4f, 0x37, 0x6b, 0x63, 0xb7, 0x29, 0x11, 0x05, + 0x12, 0x1d, 0x15, 0x25, 0xa2, 0x72, 0x41, 0x41, 0x43, 0x9f, 0x32, 0x82, 0x86, 0x0a, 0x90, 0x8d, + 0x64, 0xc4, 0xa7, 0x40, 0x77, 0xbb, 0x49, 0x6c, 0x27, 0x82, 0xc6, 0xde, 0x7b, 0x9e, 0xd9, 0x99, + 0xdf, 0xcc, 0xcd, 0xa1, 0xab, 0x8a, 0x46, 0x21, 0xf6, 0x23, 0x1e, 0xe2, 0x41, 0x0d, 0xab, 0xa1, + 0x17, 0x46, 0x52, 0x49, 0x3b, 0x13, 0xcb, 0x5e, 0x2c, 0x7b, 0x83, 0x5a, 0x21, 0xcb, 0x24, 0x93, + 0x89, 0x81, 0xe3, 0x93, 0x8e, 0x29, 0x5c, 0x67, 0x52, 0xb2, 0x7d, 0x8a, 0x49, 0xc8, 0x31, 0x11, + 0x42, 0x2a, 0xa2, 0xb8, 0x14, 0x60, 0xdc, 0xcb, 0x24, 0xe0, 0x42, 0xe2, 0xe4, 0xd7, 0x48, 0x4e, + 0x57, 0x42, 0x20, 0x01, 0x77, 0x08, 0x50, 0x3c, 0xa8, 0x75, 0xa8, 0x22, 0x35, 0xdc, 0x95, 0x5c, + 0x18, 0x7f, 0xc3, 0xf8, 0x01, 0xb0, 0x18, 0x26, 0x00, 0x66, 0x8c, 0xbc, 0x36, 0xda, 0x1a, 0x41, + 0x3f, 0x18, 0xab, 0xb0, 0xc0, 0xcf, 0xa8, 0xa0, 0xc0, 0x8d, 0xe7, 0x7e, 0xb2, 0xd0, 0x95, 0x26, + 0xb0, 0x07, 0x1c, 0x54, 0xc4, 0x3b, 0x7d, 0x45, 0x77, 0x65, 0x8f, 0x0a, 0xb0, 0xb7, 0xd1, 0x05, + 0xa0, 0xc2, 0xa7, 0x51, 0x9b, 0xf8, 0x7e, 0x44, 0x01, 0x72, 0x56, 0xc9, 0x2a, 0xa7, 0x5b, 0xff, + 0x6b, 0xf5, 0x9e, 0x16, 0xed, 0x11, 0x5a, 0x23, 0x81, 0xec, 0x0b, 0x95, 0x5b, 0x29, 0xad, 0x96, + 0xd7, 0xeb, 0x79, 0xcf, 0x54, 0x8e, 0xf9, 0x3d, 0xc3, 0xef, 0xdd, 0x97, 0x5c, 0x34, 0x1e, 0x1e, + 0x7e, 0x2b, 0xa6, 0xde, 0x7f, 0x2f, 0x96, 0x19, 0x57, 0x7b, 0xfd, 0x8e, 0xd7, 0x95, 0x81, 0xc1, + 0x34, 0x7f, 0x55, 0xf0, 0x7b, 0x58, 0x8d, 0x42, 0x0a, 0xc9, 0x05, 0x78, 0x33, 0x1b, 0x57, 0x32, + 0xfb, 0x94, 0x91, 0xee, 0xa8, 0x1d, 0x4f, 0x00, 0xde, 0xcd, 0xc6, 0x15, 0xab, 0x65, 0x0a, 0xee, + 0xfc, 0xf7, 0xeb, 0x6d, 0x31, 0xe5, 0x6e, 0xa2, 0x6b, 0xe7, 0xe0, 0xb7, 0x28, 0x84, 0x52, 0x00, + 0x75, 0x3f, 0x5a, 0xe8, 0x62, 0x13, 0xd8, 0xd3, 0xd0, 0x27, 0x8a, 0x3e, 0x26, 0x11, 0x09, 0xc0, + 0xbe, 0x83, 0xd2, 0xa4, 0xaf, 0xf6, 0x64, 0xc4, 0xd5, 0x48, 0x77, 0xd5, 0xc8, 0x7d, 0xfe, 0x50, + 0xcd, 0x1a, 0x72, 0xd3, 0xda, 0x13, 0x15, 0x71, 0xc1, 0x5a, 0xa7, 0xa1, 0xf6, 0x5d, 0xb4, 0x16, + 0x26, 0x19, 0x72, 0x2b, 0x25, 0xab, 0xbc, 0x5e, 0xcf, 0x7a, 0xf3, 0x0b, 0xe0, 0xe9, 0xec, 0x8d, + 0x74, 0xdc, 0xa6, 0x21, 0xd5, 0xe1, 0x3b, 0xb7, 0x0f, 0x66, 0xe3, 0xca, 0x69, 0xa2, 0x17, 0xb3, + 0x71, 0x65, 0x6b, 0xae, 0xe5, 0x21, 0x8e, 0x2d, 0xbc, 0x84, 0xe9, 0xe6, 0xd1, 0xc6, 0x92, 0x74, + 0xdc, 0x55, 0xfd, 0xb7, 0x85, 0x56, 0x9b, 0xc0, 0xec, 0x97, 0x16, 0xba, 0x74, 0xe6, 0xcd, 0x6d, + 0x2d, 0x62, 0x9d, 0x33, 0x9d, 0xc2, 0xcd, 0x7f, 0x86, 0x9c, 0x0c, 0xb0, 0x72, 0xf0, 0xe5, 0xe7, + 0xeb, 0x95, 0x1b, 0xae, 0x8b, 0x97, 0x3e, 0x02, 0xec, 0x9f, 0x5c, 0x69, 0x2b, 0x5d, 0x79, 0x17, + 0x65, 0x16, 0x06, 0xbd, 0x79, 0xa6, 0xcc, 0xbc, 0x5d, 0xd8, 0xfe, 0xab, 0x7d, 0x4c, 0xd0, 0x78, + 0x74, 0x38, 0x71, 0xac, 0xa3, 0x89, 0x63, 0xfd, 0x98, 0x38, 0xd6, 0xab, 0xa9, 0x93, 0x3a, 0x9a, + 0x3a, 0xa9, 0xaf, 0x53, 0x27, 0xf5, 0xac, 0x3a, 0xb7, 0x49, 0x71, 0x2a, 0x41, 0xd5, 0x73, 0x19, + 0xf5, 0x92, 0x73, 0xb5, 0x2b, 0x23, 0x8a, 0x87, 0x1a, 0x38, 0x59, 0xaa, 0xce, 0x5a, 0xb2, 0xf1, + 0xb7, 0xfe, 0x04, 0x00, 0x00, 0xff, 0xff, 0x99, 0xb0, 0x70, 0x12, 0xcf, 0x03, 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 + +// MsgClient is the client API for Msg service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type MsgClient interface { + // DistributeTokens distribute the sent tokens to all stakers in the next block + DistributeTokens(ctx context.Context, in *MsgDistributeTokens, opts ...grpc.CallOption) (*MsgDistributeTokensResponse, error) + UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error) +} + +type msgClient struct { + cc grpc1.ClientConn +} + +func NewMsgClient(cc grpc1.ClientConn) MsgClient { + return &msgClient{cc} +} + +func (c *msgClient) DistributeTokens(ctx context.Context, in *MsgDistributeTokens, opts ...grpc.CallOption) (*MsgDistributeTokensResponse, error) { + out := new(MsgDistributeTokensResponse) + err := c.cc.Invoke(ctx, "/terp.drip.v1.Msg/DistributeTokens", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error) { + out := new(MsgUpdateParamsResponse) + err := c.cc.Invoke(ctx, "/terp.drip.v1.Msg/UpdateParams", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// MsgServer is the server API for Msg service. +type MsgServer interface { + // DistributeTokens distribute the sent tokens to all stakers in the next block + DistributeTokens(context.Context, *MsgDistributeTokens) (*MsgDistributeTokensResponse, error) + UpdateParams(context.Context, *MsgUpdateParams) (*MsgUpdateParamsResponse, error) +} + +// UnimplementedMsgServer can be embedded to have forward compatible implementations. +type UnimplementedMsgServer struct { +} + +func (*UnimplementedMsgServer) DistributeTokens(ctx context.Context, req *MsgDistributeTokens) (*MsgDistributeTokensResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method DistributeTokens not implemented") +} +func (*UnimplementedMsgServer) UpdateParams(ctx context.Context, req *MsgUpdateParams) (*MsgUpdateParamsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpdateParams not implemented") +} + +func RegisterMsgServer(s grpc1.Server, srv MsgServer) { + s.RegisterService(&_Msg_serviceDesc, srv) +} + +func _Msg_DistributeTokens_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgDistributeTokens) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).DistributeTokens(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/terp.drip.v1.Msg/DistributeTokens", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).DistributeTokens(ctx, req.(*MsgDistributeTokens)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_UpdateParams_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgUpdateParams) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).UpdateParams(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/terp.drip.v1.Msg/UpdateParams", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).UpdateParams(ctx, req.(*MsgUpdateParams)) + } + return interceptor(ctx, in, info, handler) +} + +var _Msg_serviceDesc = grpc.ServiceDesc{ + ServiceName: "terp.drip.v1.Msg", + HandlerType: (*MsgServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "DistributeTokens", + Handler: _Msg_DistributeTokens_Handler, + }, + { + MethodName: "UpdateParams", + Handler: _Msg_UpdateParams_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "terp/drip/v1/tx.proto", +} + +func (m *MsgDistributeTokens) 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 *MsgDistributeTokens) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgDistributeTokens) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Amount) > 0 { + for iNdEx := len(m.Amount) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Amount[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if len(m.SenderAddress) > 0 { + i -= len(m.SenderAddress) + copy(dAtA[i:], m.SenderAddress) + i = encodeVarintTx(dAtA, i, uint64(len(m.SenderAddress))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgDistributeTokensResponse) 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 *MsgDistributeTokensResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgDistributeTokensResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgUpdateParams) 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 *MsgUpdateParams) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.Authority) > 0 { + i -= len(m.Authority) + copy(dAtA[i:], m.Authority) + i = encodeVarintTx(dAtA, i, uint64(len(m.Authority))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgUpdateParamsResponse) 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 *MsgUpdateParamsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func encodeVarintTx(dAtA []byte, offset int, v uint64) int { + offset -= sovTx(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *MsgDistributeTokens) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.SenderAddress) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if len(m.Amount) > 0 { + for _, e := range m.Amount { + l = e.Size() + n += 1 + l + sovTx(uint64(l)) + } + } + return n +} + +func (m *MsgDistributeTokensResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgUpdateParams) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Authority) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = m.Params.Size() + n += 1 + l + sovTx(uint64(l)) + return n +} + +func (m *MsgUpdateParamsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func sovTx(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTx(x uint64) (n int) { + return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *MsgDistributeTokens) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgDistributeTokens: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgDistributeTokens: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SenderAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SenderAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Amount = append(m.Amount, types.Coin{}) + if err := m.Amount[len(m.Amount)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgDistributeTokensResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgDistributeTokensResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgDistributeTokensResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgUpdateParams) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgUpdateParams: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUpdateParams: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Authority", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Authority = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgUpdateParamsResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgUpdateParamsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUpdateParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTx(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, ErrIntOverflowTx + } + 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, ErrIntOverflowTx + } + 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, ErrIntOverflowTx + } + 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, ErrInvalidLengthTx + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTx + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTx + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTx = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTx = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTx = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/drip/types/tx.pb.gw.go b/x/drip/types/tx.pb.gw.go new file mode 100644 index 00000000..348542b1 --- /dev/null +++ b/x/drip/types/tx.pb.gw.go @@ -0,0 +1,171 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: terp/drip/v1/tx.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/metadata" + "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 +var _ = metadata.Join + +var ( + filter_Msg_DistributeTokens_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_Msg_DistributeTokens_0(ctx context.Context, marshaler runtime.Marshaler, client MsgClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq MsgDistributeTokens + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Msg_DistributeTokens_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.DistributeTokens(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Msg_DistributeTokens_0(ctx context.Context, marshaler runtime.Marshaler, server MsgServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq MsgDistributeTokens + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Msg_DistributeTokens_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.DistributeTokens(ctx, &protoReq) + return msg, metadata, err + +} + +// RegisterMsgHandlerServer registers the http handlers for service Msg to "mux". +// UnaryRPC :call MsgServer 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 to stop working. Consider using RegisterMsgHandlerFromEndpoint instead. +func RegisterMsgHandlerServer(ctx context.Context, mux *runtime.ServeMux, server MsgServer) error { + + mux.Handle("POST", pattern_Msg_DistributeTokens_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Msg_DistributeTokens_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Msg_DistributeTokens_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +// RegisterMsgHandlerFromEndpoint is same as RegisterMsgHandler but +// automatically dials to "endpoint" and closes the connection when "ctx" gets done. +func RegisterMsgHandlerFromEndpoint(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 RegisterMsgHandler(ctx, mux, conn) +} + +// RegisterMsgHandler registers the http handlers for service Msg to "mux". +// The handlers forward requests to the grpc endpoint over "conn". +func RegisterMsgHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { + return RegisterMsgHandlerClient(ctx, mux, NewMsgClient(conn)) +} + +// RegisterMsgHandlerClient registers the http handlers for service Msg +// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "MsgClient". +// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "MsgClient" +// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in +// "MsgClient" to call the correct interceptors. +func RegisterMsgHandlerClient(ctx context.Context, mux *runtime.ServeMux, client MsgClient) error { + + mux.Handle("POST", pattern_Msg_DistributeTokens_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_Msg_DistributeTokens_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Msg_DistributeTokens_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +var ( + pattern_Msg_DistributeTokens_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"terp", "drip", "v1", "tx", "distribute_tokens"}, "", runtime.AssumeColonVerbOpt(false))) +) + +var ( + forward_Msg_DistributeTokens_0 = runtime.ForwardResponseMessage +)