Add basic Earn module vault deposit/withdraw (#1277)

* Add basic earn types and interfaces

* Add VaultStrategy type

* Update params with allowedVaults, deposit/withdraw msgs

* Fill in Deposit method, add keeper methods

* Add testutil, params, codec

* Add withdraw

* emit vault events

* Implement vault viewer methods

* Update doc comments, strategies

* Add earn cli query/tx commands

* Add successfull balance withdraw tests

* Add ukava vault to dev genesis

* Add vault keeper method doc comments

* Update stablecoin strategy to only accept usdx

* Vault state tests

* VaultTotalSupplied tests

* msg server test
This commit is contained in:
Derrick Lee 2022-07-20 16:14:43 -07:00 committed by GitHub
parent 68315e1636
commit ae181604ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 4481 additions and 171 deletions

View File

@ -33,6 +33,7 @@ import (
bep3keeper "github.com/kava-labs/kava/x/bep3/keeper" bep3keeper "github.com/kava-labs/kava/x/bep3/keeper"
cdpkeeper "github.com/kava-labs/kava/x/cdp/keeper" cdpkeeper "github.com/kava-labs/kava/x/cdp/keeper"
committeekeeper "github.com/kava-labs/kava/x/committee/keeper" committeekeeper "github.com/kava-labs/kava/x/committee/keeper"
earnkeeper "github.com/kava-labs/kava/x/earn/keeper"
evmutilkeeper "github.com/kava-labs/kava/x/evmutil/keeper" evmutilkeeper "github.com/kava-labs/kava/x/evmutil/keeper"
hardkeeper "github.com/kava-labs/kava/x/hard/keeper" hardkeeper "github.com/kava-labs/kava/x/hard/keeper"
incentivekeeper "github.com/kava-labs/kava/x/incentive/keeper" incentivekeeper "github.com/kava-labs/kava/x/incentive/keeper"
@ -106,6 +107,7 @@ func (tApp TestApp) GetIncentiveKeeper() incentivekeeper.Keeper { return tApp.in
func (tApp TestApp) GetEvmutilKeeper() evmutilkeeper.Keeper { return tApp.evmutilKeeper } func (tApp TestApp) GetEvmutilKeeper() evmutilkeeper.Keeper { return tApp.evmutilKeeper }
func (tApp TestApp) GetEvmKeeper() *evmkeeper.Keeper { return tApp.evmKeeper } func (tApp TestApp) GetEvmKeeper() *evmkeeper.Keeper { return tApp.evmKeeper }
func (tApp TestApp) GetSavingsKeeper() savingskeeper.Keeper { return tApp.savingsKeeper } func (tApp TestApp) GetSavingsKeeper() savingskeeper.Keeper { return tApp.savingsKeeper }
func (tApp TestApp) GetEarnKeeper() earnkeeper.Keeper { return tApp.earnKeeper }
// LegacyAmino returns the app's amino codec. // LegacyAmino returns the app's amino codec.
func (app *App) LegacyAmino() *codec.LegacyAmino { func (app *App) LegacyAmino() *codec.LegacyAmino {

View File

@ -115,3 +115,9 @@ jq '.app_state.bridge.params.enabled_conversion_pairs = [
denom: "erc20/weth", denom: "erc20/weth",
}]' $DATA/config/genesis.json | sponge $DATA/config/genesis.json }]' $DATA/config/genesis.json | sponge $DATA/config/genesis.json
# Add earn vault
jq '.app_state.earn.params.allowed_vaults = [
{
denom: "ukava",
vault_strategy: 2,
}]' $DATA/config/genesis.json | sponge $DATA/config/genesis.json

View File

@ -178,9 +178,19 @@
- [Msg](#kava.committee.v1beta1.Msg) - [Msg](#kava.committee.v1beta1.Msg)
- [kava/earn/v1beta1/strategy.proto](#kava/earn/v1beta1/strategy.proto)
- [StrategyType](#kava.earn.v1beta1.StrategyType)
- [kava/earn/v1beta1/vault.proto](#kava/earn/v1beta1/vault.proto)
- [AllowedVault](#kava.earn.v1beta1.AllowedVault)
- [VaultRecord](#kava.earn.v1beta1.VaultRecord)
- [VaultShareRecord](#kava.earn.v1beta1.VaultShareRecord)
- [kava/earn/v1beta1/params.proto](#kava/earn/v1beta1/params.proto)
- [Params](#kava.earn.v1beta1.Params)
- [kava/earn/v1beta1/genesis.proto](#kava/earn/v1beta1/genesis.proto) - [kava/earn/v1beta1/genesis.proto](#kava/earn/v1beta1/genesis.proto)
- [GenesisState](#kava.earn.v1beta1.GenesisState) - [GenesisState](#kava.earn.v1beta1.GenesisState)
- [Params](#kava.earn.v1beta1.Params)
- [kava/earn/v1beta1/query.proto](#kava/earn/v1beta1/query.proto) - [kava/earn/v1beta1/query.proto](#kava/earn/v1beta1/query.proto)
- [QueryParamsRequest](#kava.earn.v1beta1.QueryParamsRequest) - [QueryParamsRequest](#kava.earn.v1beta1.QueryParamsRequest)
@ -189,6 +199,11 @@
- [Query](#kava.earn.v1beta1.Query) - [Query](#kava.earn.v1beta1.Query)
- [kava/earn/v1beta1/tx.proto](#kava/earn/v1beta1/tx.proto) - [kava/earn/v1beta1/tx.proto](#kava/earn/v1beta1/tx.proto)
- [MsgDeposit](#kava.earn.v1beta1.MsgDeposit)
- [MsgDepositResponse](#kava.earn.v1beta1.MsgDepositResponse)
- [MsgWithdraw](#kava.earn.v1beta1.MsgWithdraw)
- [MsgWithdrawResponse](#kava.earn.v1beta1.MsgWithdrawResponse)
- [Msg](#kava.earn.v1beta1.Msg) - [Msg](#kava.earn.v1beta1.Msg)
- [kava/evmutil/v1beta1/genesis.proto](#kava/evmutil/v1beta1/genesis.proto) - [kava/evmutil/v1beta1/genesis.proto](#kava/evmutil/v1beta1/genesis.proto)
@ -2720,6 +2735,133 @@ Msg defines the committee Msg service
<a name="kava/earn/v1beta1/strategy.proto"></a>
<p align="right"><a href="#top">Top</a></p>
## kava/earn/v1beta1/strategy.proto
<!-- end messages -->
<a name="kava.earn.v1beta1.StrategyType"></a>
### StrategyType
| Name | Number | Description |
| ---- | ------ | ----------- |
| STRATEGY_TYPE_UNKNOWN | 0 | |
| STRATEGY_TYPE_KAVA_STAKERS | 1 | |
| STRATEGY_TYPE_STABLECOIN_STAKERS | 2 | USDC / BUSD vaults use the same strategy but with the denom set in VaultRecord |
| STRATEGY_TYPE_KAVA_FOUNDATION | 3 | |
<!-- end enums -->
<!-- end HasExtensions -->
<!-- end services -->
<a name="kava/earn/v1beta1/vault.proto"></a>
<p align="right"><a href="#top">Top</a></p>
## kava/earn/v1beta1/vault.proto
<a name="kava.earn.v1beta1.AllowedVault"></a>
### AllowedVault
AllowedVault is a vault that is allowed to be created. These can be
modified via parameter governance.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `denom` | [string](#string) | | Denom is the only supported denomination of the vault for deposits and withdrawals. |
| `vault_strategy` | [StrategyType](#kava.earn.v1beta1.StrategyType) | | VaultStrategy is the strategies to use for this vault. |
<a name="kava.earn.v1beta1.VaultRecord"></a>
### VaultRecord
VaultRecord is the state of a vault and is used to store the state of a
vault.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `denom` | [string](#string) | | Denom is the only supported denomination of the vault for deposits and withdrawals. |
| `total_supply` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | TotalSupply is the total supply of the vault, denominated **only** in the user deposit/withdrawal denom, must be the same as the Denom field. |
<a name="kava.earn.v1beta1.VaultShareRecord"></a>
### VaultShareRecord
VaultShareRecord defines the shares owned by a depositor and vault.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `depositor` | [bytes](#bytes) | | depositor represents the owner of the shares |
| `amount_supplied` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | amount_supplied represents the total amount a depositor has supplied to the vault. The vault is determined by the coin denom. |
<!-- end messages -->
<!-- end enums -->
<!-- end HasExtensions -->
<!-- end services -->
<a name="kava/earn/v1beta1/params.proto"></a>
<p align="right"><a href="#top">Top</a></p>
## kava/earn/v1beta1/params.proto
<a name="kava.earn.v1beta1.Params"></a>
### Params
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `allowed_vaults` | [AllowedVault](#kava.earn.v1beta1.AllowedVault) | repeated | |
<!-- end messages -->
<!-- end enums -->
<!-- end HasExtensions -->
<!-- end services -->
<a name="kava/earn/v1beta1/genesis.proto"></a> <a name="kava/earn/v1beta1/genesis.proto"></a>
<p align="right"><a href="#top">Top</a></p> <p align="right"><a href="#top">Top</a></p>
@ -2730,22 +2872,14 @@ Msg defines the committee Msg service
<a name="kava.earn.v1beta1.GenesisState"></a> <a name="kava.earn.v1beta1.GenesisState"></a>
### GenesisState ### GenesisState
GenesisState defines the earn module's genesis state. GenesisState defines the swap module's genesis state.
| Field | Type | Label | Description | | Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- | | ----- | ---- | ----- | ----------- |
| `params` | [Params](#kava.earn.v1beta1.Params) | | params defines all the paramaters related to earn | | `params` | [Params](#kava.earn.v1beta1.Params) | | params defines all the paramaters related to earn |
| `vault_records` | [VaultRecord](#kava.earn.v1beta1.VaultRecord) | repeated | vault_records defines the available vaults |
| `vault_share_records` | [VaultShareRecord](#kava.earn.v1beta1.VaultShareRecord) | repeated | share_records defines the owned shares of each vault |
<a name="kava.earn.v1beta1.Params"></a>
### Params
Params defines the parameters for the earn module.
@ -2818,6 +2952,58 @@ Query defines the gRPC querier service for earn module
## kava/earn/v1beta1/tx.proto ## kava/earn/v1beta1/tx.proto
<a name="kava.earn.v1beta1.MsgDeposit"></a>
### MsgDeposit
MsgDeposit represents a message for depositing assedts into a vault
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `depositor` | [string](#string) | | depositor represents the address to deposit funds from |
| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | Amount represents the token to deposit. The vault corresponds to the denom of the amount coin. |
<a name="kava.earn.v1beta1.MsgDepositResponse"></a>
### MsgDepositResponse
MsgDepositResponse defines the Msg/Deposit response type.
<a name="kava.earn.v1beta1.MsgWithdraw"></a>
### MsgWithdraw
MsgWithdraw represents a message for withdrawing liquidity from a vault
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `from` | [string](#string) | | from represents the address we are withdrawing for |
| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | Amount represents the token to withdraw. The vault corresponds to the denom of the amount coin. |
<a name="kava.earn.v1beta1.MsgWithdrawResponse"></a>
### MsgWithdrawResponse
MsgWithdrawResponse defines the Msg/Withdraw response type.
<!-- end messages --> <!-- end messages -->
<!-- end enums --> <!-- end enums -->
@ -2832,6 +3018,8 @@ Msg defines the earn Msg service.
| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | | Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint |
| ----------- | ------------ | ------------- | ------------| ------- | -------- | | ----------- | ------------ | ------------- | ------------| ------- | -------- |
| `Deposit` | [MsgDeposit](#kava.earn.v1beta1.MsgDeposit) | [MsgDepositResponse](#kava.earn.v1beta1.MsgDepositResponse) | Deposit defines a method for depositing assets into a vault | |
| `Withdraw` | [MsgWithdraw](#kava.earn.v1beta1.MsgWithdraw) | [MsgWithdrawResponse](#kava.earn.v1beta1.MsgWithdrawResponse) | Withdraw defines a method for withdrawing assets into a vault | |
<!-- end services --> <!-- end services -->

View File

@ -3,13 +3,17 @@ package kava.earn.v1beta1;
option go_package = "github.com/kava-labs/kava/x/earn/types"; option go_package = "github.com/kava-labs/kava/x/earn/types";
import "kava/earn/v1beta1/vault.proto";
import "kava/earn/v1beta1/params.proto";
import "gogoproto/gogo.proto"; import "gogoproto/gogo.proto";
// GenesisState defines the earn module's genesis state. // GenesisState defines the swap module's genesis state.
message GenesisState { message GenesisState {
// params defines all the paramaters related to earn // params defines all the paramaters related to earn
Params params = 1 [(gogoproto.nullable) = false]; Params params = 1 [(gogoproto.nullable) = false];
// vault_records defines the available vaults
repeated VaultRecord vault_records = 2 [(gogoproto.castrepeated) = "VaultRecords", (gogoproto.nullable) = false];
// share_records defines the owned shares of each vault
repeated VaultShareRecord vault_share_records = 3
[(gogoproto.castrepeated) = "VaultShareRecords", (gogoproto.nullable) = false];
} }
// Params defines the parameters for the earn module.
message Params {}

View File

@ -0,0 +1,11 @@
syntax = "proto3";
package kava.earn.v1beta1;
option go_package = "github.com/kava-labs/kava/x/earn/types";
import "gogoproto/gogo.proto";
import "kava/earn/v1beta1/vault.proto";
message Params {
repeated AllowedVault allowed_vaults = 1 [(gogoproto.castrepeated) = "AllowedVaults", (gogoproto.nullable) = false];
}

View File

@ -6,7 +6,7 @@ option go_package = "github.com/kava-labs/kava/x/earn/types";
import "gogoproto/gogo.proto"; import "gogoproto/gogo.proto";
import "google/api/annotations.proto"; import "google/api/annotations.proto";
import "cosmos_proto/cosmos.proto"; import "cosmos_proto/cosmos.proto";
import "kava/earn/v1beta1/genesis.proto"; import "kava/earn/v1beta1/params.proto";
// Query defines the gRPC querier service for earn module // Query defines the gRPC querier service for earn module
service Query { service Query {

View File

@ -0,0 +1,18 @@
syntax = "proto3";
package kava.earn.v1beta1;
option go_package = "github.com/kava-labs/kava/x/earn/types";
import "gogoproto/gogo.proto";
import "cosmos/base/v1beta1/coin.proto";
import "cosmos_proto/cosmos.proto";
enum StrategyType {
option (gogoproto.goproto_enum_prefix) = false;
STRATEGY_TYPE_UNKNOWN = 0;
STRATEGY_TYPE_KAVA_STAKERS = 1;
// USDC / BUSD vaults use the same strategy but with the denom set in VaultRecord
STRATEGY_TYPE_STABLECOIN_STAKERS = 2;
STRATEGY_TYPE_KAVA_FOUNDATION = 3;
}

View File

@ -1,7 +1,45 @@
syntax = "proto3"; syntax = "proto3";
package kava.earn.v1beta1; package kava.earn.v1beta1;
import "gogoproto/gogo.proto";
import "cosmos_proto/cosmos.proto";
import "cosmos/base/v1beta1/coin.proto";
option go_package = "github.com/kava-labs/kava/x/earn/types"; option go_package = "github.com/kava-labs/kava/x/earn/types";
// Msg defines the earn Msg service. // Msg defines the earn Msg service.
service Msg {} service Msg {
// Deposit defines a method for depositing assets into a vault
rpc Deposit(MsgDeposit) returns (MsgDepositResponse);
// Withdraw defines a method for withdrawing assets into a vault
rpc Withdraw(MsgWithdraw) returns (MsgWithdrawResponse);
}
// MsgDeposit represents a message for depositing assedts into a vault
message MsgDeposit {
option (gogoproto.goproto_getters) = false;
// depositor represents the address to deposit funds from
string depositor = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
// Amount represents the token to deposit. The vault corresponds to the denom
// of the amount coin.
cosmos.base.v1beta1.Coin amount = 2 [(gogoproto.nullable) = false];
}
// MsgDepositResponse defines the Msg/Deposit response type.
message MsgDepositResponse {}
// MsgWithdraw represents a message for withdrawing liquidity from a vault
message MsgWithdraw {
option (gogoproto.goproto_getters) = false;
// from represents the address we are withdrawing for
string from = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
// Amount represents the token to withdraw. The vault corresponds to the denom
// of the amount coin.
cosmos.base.v1beta1.Coin amount = 2 [(gogoproto.nullable) = false];
}
// MsgWithdrawResponse defines the Msg/Withdraw response type.
message MsgWithdrawResponse {}

View File

@ -0,0 +1,42 @@
syntax = "proto3";
package kava.earn.v1beta1;
option go_package = "github.com/kava-labs/kava/x/earn/types";
import "gogoproto/gogo.proto";
import "cosmos/base/v1beta1/coin.proto";
import "cosmos_proto/cosmos.proto";
import "kava/earn/v1beta1/strategy.proto";
// AllowedVault is a vault that is allowed to be created. These can be
// modified via parameter governance.
message AllowedVault {
// Denom is the only supported denomination of the vault for deposits and withdrawals.
string denom = 1;
// VaultStrategy is the strategies to use for this vault.
StrategyType vault_strategy = 2;
}
// VaultRecord is the state of a vault and is used to store the state of a
// vault.
message VaultRecord {
// Denom is the only supported denomination of the vault for deposits and
// withdrawals.
string denom = 1;
// TotalSupply is the total supply of the vault, denominated **only** in the
// user deposit/withdrawal denom, must be the same as the Denom field.
cosmos.base.v1beta1.Coin total_supply = 2 [(gogoproto.nullable) = false];
}
// VaultShareRecord defines the shares owned by a depositor and vault.
message VaultShareRecord {
// depositor represents the owner of the shares
bytes depositor = 1 [
(cosmos_proto.scalar) = "cosmos.AddressBytes",
(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"
];
// amount_supplied represents the total amount a depositor has supplied to the
// vault. The vault is determined by the coin denom.
cosmos.base.v1beta1.Coin amount_supplied = 2 [(gogoproto.nullable) = false];
}

View File

@ -0,0 +1,60 @@
package cli
import (
"context"
"github.com/spf13/cobra"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/kava-labs/kava/x/earn/types"
)
// GetQueryCmd returns the cli query commands for the earn module
func GetQueryCmd() *cobra.Command {
earnQueryCommand := &cobra.Command{
Use: types.ModuleName,
Short: "Querying commands for the earn module",
DisableFlagParsing: true,
SuggestionsMinimumDistance: 2,
RunE: client.ValidateCmd,
}
cmds := []*cobra.Command{
queryParamsCmd(),
}
for _, cmd := range cmds {
flags.AddQueryFlagsToCmd(cmd)
}
earnQueryCommand.AddCommand(cmds...)
return earnQueryCommand
}
func queryParamsCmd() *cobra.Command {
return &cobra.Command{
Use: "params",
Short: "get the earn module parameters",
Long: "Get the current earn module parameters.",
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
req := types.NewQueryParamsRequest()
res, err := queryClient.Params(context.Background(), req)
if err != nil {
return err
}
return clientCtx.PrintProto(&res.Params)
},
}
}

101
x/earn/client/cli/tx.go Normal file
View File

@ -0,0 +1,101 @@
package cli
import (
"fmt"
"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/cosmos/cosmos-sdk/version"
"github.com/kava-labs/kava/x/earn/types"
)
// GetTxCmd returns the transaction commands for this module
func GetTxCmd() *cobra.Command {
swapTxCmd := &cobra.Command{
Use: types.ModuleName,
Short: fmt.Sprintf("%s transactions subcommands", types.ModuleName),
DisableFlagParsing: true,
SuggestionsMinimumDistance: 2,
RunE: client.ValidateCmd,
}
cmds := []*cobra.Command{
getCmdDeposit(),
getCmdWithdraw(),
}
for _, cmd := range cmds {
flags.AddTxFlagsToCmd(cmd)
}
swapTxCmd.AddCommand(cmds...)
return swapTxCmd
}
func getCmdDeposit() *cobra.Command {
return &cobra.Command{
Use: "deposit [amount]",
Short: "deposit coins to an earn vault",
Example: fmt.Sprintf(
`%s tx %s deposit 10000000ukava --from <key>`,
version.AppName, types.ModuleName,
),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}
amount, err := sdk.ParseCoinNormalized(args[0])
if err != nil {
return err
}
signer := clientCtx.GetFromAddress()
msg := types.NewMsgDeposit(signer.String(), amount)
if err := msg.ValidateBasic(); err != nil {
return err
}
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}
}
func getCmdWithdraw() *cobra.Command {
return &cobra.Command{
Use: "withdraw [amount]",
Short: "withdraw coins from an earn vault",
Example: fmt.Sprintf(
`%s tx %s withdraw 10000000ukava --from <key>`,
version.AppName, types.ModuleName,
),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}
amount, err := sdk.ParseCoinNormalized(args[0])
if err != nil {
return err
}
fromAddr := clientCtx.GetFromAddress()
msg := types.NewMsgWithdraw(fromAddr.String(), amount)
if err := msg.ValidateBasic(); err != nil {
return err
}
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}
}

76
x/earn/keeper/deposit.go Normal file
View File

@ -0,0 +1,76 @@
package keeper
import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/kava-labs/kava/x/earn/types"
)
// Deposit adds the provided amount from a depositor to a vault. The vault is
// specified by the denom in the amount.
func (k *Keeper) Deposit(ctx sdk.Context, depositor sdk.AccAddress, amount sdk.Coin) error {
// Get AllowedVault, if not found (not a valid vault), return error
allowedVault, found := k.GetAllowedVault(ctx, amount.Denom)
if !found {
return types.ErrInvalidVaultDenom
}
if amount.IsZero() {
return types.ErrInsufficientAmount
}
// Check if VaultRecord exists, create if not exist
vaultRecord, found := k.GetVaultRecord(ctx, amount.Denom)
if !found {
// Create a new VaultRecord with 0 supply
vaultRecord = types.NewVaultRecord(amount.Denom)
}
// Transfer amount to module account
if err := k.bankKeeper.SendCoinsFromAccountToModule(
ctx,
depositor,
types.ModuleName,
sdk.NewCoins(amount),
); err != nil {
return err
}
// Get VaultShareRecord for account, create if not exist
vaultShareRecord, found := k.GetVaultShareRecord(ctx, amount.Denom, depositor)
if !found {
// Create a new empty VaultShareRecord with 0 supply
vaultShareRecord = types.NewVaultShareRecord(depositor, amount.Denom)
}
// Increment VaultRecord supply
vaultRecord.TotalSupply = vaultRecord.TotalSupply.Add(amount)
// Increment VaultShareRecord supply
vaultShareRecord.AmountSupplied = vaultShareRecord.AmountSupplied.Add(amount)
// Update VaultRecord and VaultShareRecord
k.SetVaultRecord(ctx, vaultRecord)
k.SetVaultShareRecord(ctx, vaultShareRecord)
// Get the strategy for the vault
strategy, err := k.GetStrategy(allowedVault.VaultStrategy)
if err != nil {
return err
}
// Deposit to the strategy
if err := strategy.Deposit(amount); err != nil {
return err
}
ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeVaultDeposit,
sdk.NewAttribute(types.AttributeKeyVaultDenom, amount.Denom),
sdk.NewAttribute(types.AttributeKeyDepositor, depositor.String()),
sdk.NewAttribute(sdk.AttributeKeyAmount, amount.Amount.String()),
),
)
return nil
}

View File

@ -0,0 +1,132 @@
package keeper_test
import (
"os"
"testing"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/kava-labs/kava/app"
"github.com/kava-labs/kava/x/earn/testutil"
"github.com/kava-labs/kava/x/earn/types"
"github.com/stretchr/testify/suite"
)
func TestMain(m *testing.M) {
config := sdk.GetConfig()
app.SetBech32AddressPrefixes(config)
os.Exit(m.Run())
}
type depositTestSuite struct {
testutil.Suite
}
func (suite *depositTestSuite) SetupTest() {
suite.Suite.SetupTest()
suite.Keeper.SetParams(suite.Ctx, types.DefaultParams())
}
func TestDepositTestSuite(t *testing.T) {
suite.Run(t, new(depositTestSuite))
}
func (suite *depositTestSuite) TestDeposit_Balances() {
vaultDenom := "busd"
startBalance := sdk.NewInt64Coin(vaultDenom, 1000)
depositAmount := sdk.NewInt64Coin(vaultDenom, 100)
suite.CreateVault(vaultDenom, types.STRATEGY_TYPE_STABLECOIN_STAKERS)
acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount)
suite.Require().NoError(err)
suite.AccountBalanceEqual(
acc.GetAddress(),
sdk.NewCoins(startBalance.Sub(depositAmount)), // Account decreases by deposit
)
// TODO: Module account balance will be zero when strategies are implemented
suite.ModuleAccountBalanceEqual(
sdk.NewCoins(depositAmount),
)
}
func (suite *depositTestSuite) TestDeposit_Exceed() {
vaultDenom := "busd"
startBalance := sdk.NewInt64Coin(vaultDenom, 1000)
depositAmount := sdk.NewInt64Coin(vaultDenom, 1001)
suite.CreateVault(vaultDenom, types.STRATEGY_TYPE_STABLECOIN_STAKERS)
acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount)
suite.Require().Error(err)
suite.Require().ErrorIs(err, sdkerrors.ErrInsufficientFunds)
// No changes in balances
suite.AccountBalanceEqual(
acc.GetAddress(),
sdk.NewCoins(startBalance),
)
suite.ModuleAccountBalanceEqual(
sdk.NewCoins(),
)
}
func (suite *depositTestSuite) TestDeposit_Zero() {
vaultDenom := "busd"
startBalance := sdk.NewInt64Coin(vaultDenom, 1000)
depositAmount := sdk.NewInt64Coin(vaultDenom, 0)
suite.CreateVault(vaultDenom, types.STRATEGY_TYPE_STABLECOIN_STAKERS)
acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount)
suite.Require().Error(err)
suite.Require().ErrorIs(err, types.ErrInsufficientAmount)
// No changes in balances
suite.AccountBalanceEqual(
acc.GetAddress(),
sdk.NewCoins(startBalance),
)
suite.ModuleAccountBalanceEqual(
sdk.NewCoins(),
)
}
func (suite *depositTestSuite) TestDeposit_InvalidVault() {
vaultDenom := "busd"
startBalance := sdk.NewInt64Coin(vaultDenom, 1000)
depositAmount := sdk.NewInt64Coin(vaultDenom, 1001)
// Vault not created -- doesn't exist
acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount)
suite.Require().Error(err)
suite.Require().ErrorIs(err, types.ErrInvalidVaultDenom)
// No changes in balances
suite.AccountBalanceEqual(
acc.GetAddress(),
sdk.NewCoins(startBalance),
)
suite.ModuleAccountBalanceEqual(
sdk.NewCoins(),
)
}

View File

@ -0,0 +1,55 @@
package keeper_test
import (
"context"
"testing"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/kava-labs/kava/x/earn/keeper"
"github.com/kava-labs/kava/x/earn/testutil"
"github.com/kava-labs/kava/x/earn/types"
"github.com/stretchr/testify/suite"
)
type grpcQueryTestSuite struct {
testutil.Suite
queryClient types.QueryClient
}
func (suite *grpcQueryTestSuite) SetupTest() {
suite.Suite.SetupTest()
suite.Keeper.SetParams(suite.Ctx, types.DefaultParams())
queryHelper := baseapp.NewQueryServerTestHelper(suite.Ctx, suite.App.InterfaceRegistry())
types.RegisterQueryServer(queryHelper, keeper.NewQueryServerImpl(suite.Keeper))
suite.queryClient = types.NewQueryClient(queryHelper)
}
func TestGrpcQueryTestSuite(t *testing.T) {
suite.Run(t, new(grpcQueryTestSuite))
}
func (suite *grpcQueryTestSuite) TestQueryParams() {
vaultDenom := "busd"
res, err := suite.queryClient.Params(context.Background(), types.NewQueryParamsRequest())
suite.Require().NoError(err)
// ElementsMatch instead of Equal because AllowedVaults{} != AllowedVaults(nil)
suite.Require().ElementsMatch(types.DefaultParams().AllowedVaults, res.Params.AllowedVaults)
// Add vault to params
suite.CreateVault(vaultDenom, types.STRATEGY_TYPE_STABLECOIN_STAKERS)
// Query again for added vault
res, err = suite.queryClient.Params(context.Background(), types.NewQueryParamsRequest())
suite.Require().NoError(err)
suite.Require().Equal(
types.AllowedVaults{
types.NewAllowedVault(vaultDenom, types.STRATEGY_TYPE_STABLECOIN_STAKERS),
},
res.Params.AllowedVaults,
)
}

View File

@ -1,6 +1,10 @@
package keeper package keeper
import ( import (
"context"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/kava-labs/kava/x/earn/types" "github.com/kava-labs/kava/x/earn/types"
) )
@ -15,3 +19,51 @@ func NewMsgServerImpl(keeper Keeper) types.MsgServer {
} }
var _ types.MsgServer = msgServer{} var _ types.MsgServer = msgServer{}
// Deposit handles MsgDeposit messages
func (m msgServer) Deposit(goCtx context.Context, msg *types.MsgDeposit) (*types.MsgDepositResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
depositor, err := sdk.AccAddressFromBech32(msg.Depositor)
if err != nil {
return nil, err
}
if err := m.keeper.Deposit(ctx, depositor, msg.Amount); err != nil {
return nil, err
}
ctx.EventManager().EmitEvent(
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName),
sdk.NewAttribute(sdk.AttributeKeySender, depositor.String()),
),
)
return &types.MsgDepositResponse{}, nil
}
// Withdraw handles MsgWithdraw messages
func (m msgServer) Withdraw(goCtx context.Context, msg *types.MsgWithdraw) (*types.MsgWithdrawResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
from, err := sdk.AccAddressFromBech32(msg.From)
if err != nil {
return nil, err
}
if err := m.keeper.Withdraw(ctx, from, msg.Amount); err != nil {
return nil, err
}
ctx.EventManager().EmitEvent(
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName),
sdk.NewAttribute(sdk.AttributeKeySender, from.String()),
),
)
return &types.MsgWithdrawResponse{}, nil
}

View File

@ -0,0 +1,136 @@
package keeper_test
import (
"testing"
sdk "github.com/cosmos/cosmos-sdk/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/kava-labs/kava/x/earn/keeper"
"github.com/kava-labs/kava/x/earn/testutil"
"github.com/kava-labs/kava/x/earn/types"
"github.com/stretchr/testify/suite"
"github.com/tendermint/tendermint/crypto"
)
var moduleAccAddress = sdk.AccAddress(crypto.AddressHash([]byte(types.ModuleAccountName)))
type msgServerTestSuite struct {
testutil.Suite
msgServer types.MsgServer
}
func (suite *msgServerTestSuite) SetupTest() {
suite.Suite.SetupTest()
suite.Keeper.SetParams(suite.Ctx, types.DefaultParams())
suite.msgServer = keeper.NewMsgServerImpl(suite.Keeper)
}
func TestMsgServerTestSuite(t *testing.T) {
suite.Run(t, new(msgServerTestSuite))
}
func (suite *msgServerTestSuite) TestDeposit() {
vaultDenom := "usdx"
suite.CreateVault(vaultDenom, types.STRATEGY_TYPE_STABLECOIN_STAKERS)
startBalance := sdk.NewInt64Coin(vaultDenom, 1000)
depositAmount := sdk.NewInt64Coin(vaultDenom, 100)
acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
msg := types.NewMsgDeposit(acc.GetAddress().String(), depositAmount)
_, err := suite.msgServer.Deposit(sdk.WrapSDKContext(suite.Ctx), msg)
suite.Require().NoError(err)
suite.AccountBalanceEqual(
acc.GetAddress(),
sdk.NewCoins(startBalance.Sub(depositAmount)),
)
// Bank: Send deposit Account -> Module account
suite.EventsContains(
suite.GetEvents(),
sdk.NewEvent(
banktypes.EventTypeTransfer,
sdk.NewAttribute(banktypes.AttributeKeyRecipient, moduleAccAddress.String()),
sdk.NewAttribute(banktypes.AttributeKeySender, acc.GetAddress().String()),
sdk.NewAttribute(sdk.AttributeKeyAmount, depositAmount.String()),
),
)
// Keeper Deposit()
suite.EventsContains(
suite.GetEvents(),
sdk.NewEvent(
types.EventTypeVaultDeposit,
sdk.NewAttribute(types.AttributeKeyVaultDenom, depositAmount.Denom),
sdk.NewAttribute(types.AttributeKeyDepositor, acc.GetAddress().String()),
sdk.NewAttribute(sdk.AttributeKeyAmount, depositAmount.Amount.String()),
),
)
// Msg server module
suite.EventsContains(
suite.GetEvents(),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName),
sdk.NewAttribute(sdk.AttributeKeySender, acc.GetAddress().String()),
),
)
}
func (suite *msgServerTestSuite) TestWithdraw() {
vaultDenom := "usdx"
suite.CreateVault(vaultDenom, types.STRATEGY_TYPE_STABLECOIN_STAKERS)
startBalance := sdk.NewInt64Coin(vaultDenom, 1000)
depositAmount := sdk.NewInt64Coin(vaultDenom, 100)
acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
msgDeposit := types.NewMsgDeposit(acc.GetAddress().String(), depositAmount)
_, err := suite.msgServer.Deposit(sdk.WrapSDKContext(suite.Ctx), msgDeposit)
suite.Require().NoError(err)
// Withdraw all
msgWithdraw := types.NewMsgWithdraw(acc.GetAddress().String(), depositAmount)
_, err = suite.msgServer.Withdraw(sdk.WrapSDKContext(suite.Ctx), msgWithdraw)
suite.Require().NoError(err)
// Bank: Send deposit Account -> Module account
suite.EventsContains(
suite.GetEvents(),
sdk.NewEvent(
banktypes.EventTypeTransfer,
// Direction opposite from Deposit()
sdk.NewAttribute(banktypes.AttributeKeyRecipient, acc.GetAddress().String()),
sdk.NewAttribute(banktypes.AttributeKeySender, moduleAccAddress.String()),
sdk.NewAttribute(sdk.AttributeKeyAmount, depositAmount.String()),
),
)
// Keeper Withdraw()
suite.EventsContains(
suite.GetEvents(),
sdk.NewEvent(
types.EventTypeVaultWithdraw,
sdk.NewAttribute(types.AttributeKeyVaultDenom, depositAmount.Denom),
sdk.NewAttribute(types.AttributeKeyOwner, acc.GetAddress().String()),
sdk.NewAttribute(sdk.AttributeKeyAmount, depositAmount.Amount.String()),
),
)
// Msg server module
suite.EventsContains(
suite.GetEvents(),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName),
sdk.NewAttribute(sdk.AttributeKeySender, acc.GetAddress().String()),
),
)
}

View File

@ -10,6 +10,7 @@ import (
func (k Keeper) GetParams(ctx sdk.Context) types.Params { func (k Keeper) GetParams(ctx sdk.Context) types.Params {
var p types.Params var p types.Params
k.paramSubspace.GetParamSet(ctx, &p) k.paramSubspace.GetParamSet(ctx, &p)
return p return p
} }
@ -17,3 +18,20 @@ func (k Keeper) GetParams(ctx sdk.Context) types.Params {
func (k Keeper) SetParams(ctx sdk.Context, params types.Params) { func (k Keeper) SetParams(ctx sdk.Context, params types.Params) {
k.paramSubspace.SetParamSet(ctx, &params) k.paramSubspace.SetParamSet(ctx, &params)
} }
// GetAllowedVaults returns the list of allowed vaults from the module params.
func (k Keeper) GetAllowedVaults(ctx sdk.Context) types.AllowedVaults {
return k.GetParams(ctx).AllowedVaults
}
// GetAllowedVault returns a single vault from the module params specified by
// the denom.
func (k Keeper) GetAllowedVault(ctx sdk.Context, vaultDenom string) (types.AllowedVault, bool) {
for _, allowedVault := range k.GetAllowedVaults(ctx) {
if allowedVault.Denom == vaultDenom {
return allowedVault, true
}
}
return types.AllowedVault{}, false
}

55
x/earn/keeper/strategy.go Normal file
View File

@ -0,0 +1,55 @@
package keeper
import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/kava-labs/kava/x/earn/types"
)
// Strategy is the interface that must be implemented by a strategy.
type Strategy interface {
// GetName returns the name of the strategy.
GetName() string
// GetDescription returns the description of the strategy.
GetDescription() string
// GetSupportedDenoms returns a slice of supported denom for this strategy.
// For example, stablecoin stakers strategy supports both "busd" and "usdc".
GetSupportedDenoms() []string
// GetEstimatedTotalAssets returns the estimated total assets denominated in
// GetDenom() of this strategy. This is the value if the strategy were to
// liquidate all assets.
//
// **Note:** This may not reflect the true value as it may become outdated
// from market changes.
GetEstimatedTotalAssets(denom string) (sdk.Coin, error)
// Deposit the specified amount of coins into this strategy. The amount
// must be denominated in GetDenom().
Deposit(amount sdk.Coin) error
// Withdraw the specified amount of coins from this strategy. The amount
// must be denominated in GetDenom().
Withdraw(amount sdk.Coin) error
// LiquidateAll liquidates all of the entire strategy's positions, returning
// the amount of liquidated denominated in GetDenom(). This should be only
// called during use of emergency via governance.
LiquidateAll() (amount sdk.Coin, err error)
}
func (k *Keeper) GetStrategy(strategyType types.StrategyType) (Strategy, error) {
switch strategyType {
case types.STRATEGY_TYPE_STABLECOIN_STAKERS:
return (*StableCoinStrategy)(k), nil
case types.STRATEGY_TYPE_KAVA_STAKERS:
panic("unimplemented")
case types.STRATEGY_TYPE_KAVA_FOUNDATION:
panic("unimplemented")
default:
return nil, fmt.Errorf("unknown strategy type: %s", strategyType)
}
}

View File

@ -0,0 +1,42 @@
package keeper
import sdk "github.com/cosmos/cosmos-sdk/types"
// StableCoinStrategy defines the stablecoin strategy:
// 1. Supply USDX to Lend
type StableCoinStrategy Keeper
var _ Strategy = (*StableCoinStrategy)(nil)
func (s *StableCoinStrategy) GetName() string {
return "USDX"
}
func (s *StableCoinStrategy) GetDescription() string {
return "Supplies the USDX to Lend"
}
func (s *StableCoinStrategy) GetSupportedDenoms() []string {
return []string{"usdx"}
}
func (s *StableCoinStrategy) GetEstimatedTotalAssets(denom string) (sdk.Coin, error) {
// 1. Get amount of USDX in Lend
return sdk.Coin{}, nil
}
func (s *StableCoinStrategy) Deposit(amount sdk.Coin) error {
return nil
}
func (s *StableCoinStrategy) Withdraw(amount sdk.Coin) error {
return nil
}
// LiquidateAll liquidates all assets in the strategy, this should be called
// only in case of emergency or when all assets should be moved to a new
// strategy.
func (s *StableCoinStrategy) LiquidateAll() (amount sdk.Coin, err error) {
return sdk.Coin{}, nil
}

215
x/earn/keeper/vault.go Normal file
View File

@ -0,0 +1,215 @@
package keeper
import (
"github.com/cosmos/cosmos-sdk/store/prefix"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/kava-labs/kava/x/earn/types"
)
// ViewVaultKeeper defines the read-only methods used for querying vaults.
type ViewVaultKeeper interface {
// GetVaultTotalSupplied returns the total balance supplied to a vault. This
// may not necessarily be the current value of the vault, as it is the sum
// of the supplied denom.
GetVaultTotalSupplied(ctx sdk.Context, denom string) (sdk.Coin, error)
// GetVaultTotalValue returns the total **value** of all coins in a vault,
// i.e. the realizable total value denominated by GetDenom() if the vault
// were to liquidate its entire strategies.
GetVaultTotalValue(ctx sdk.Context, denom string) (sdk.Coin, error)
// GetVaultAccountSupplied returns the supplied amount for a single address
// within the vault.
GetVaultAccountSupplied(ctx sdk.Context, denom string, acc sdk.AccAddress) (sdk.Coin, error)
// GetVaultAccountValue returns the value of a single address within a vault
// if the account were to withdraw their entire balance.
GetVaultAccountValue(ctx sdk.Context, denom string, acc sdk.AccAddress) (sdk.Coin, error)
}
var _ ViewVaultKeeper = (*Keeper)(nil)
// GetVaultTotalSupplied returns the total balance supplied to the vault. This
// may not necessarily be the current value of the vault, as it is the sum
// of the supplied denom and the value may be higher due to accumulated APYs.
func (k *Keeper) GetVaultTotalSupplied(
ctx sdk.Context,
denom string,
) (sdk.Coin, error) {
vault, found := k.GetVaultRecord(ctx, denom)
if !found {
return sdk.Coin{}, types.ErrVaultRecordNotFound
}
return vault.TotalSupply, nil
}
// GetTotalValue returns the total **value** of all coins in this vault,
// i.e. the realizable total value denominated by GetDenom() if the vault
// were to liquidate its entire strategies.
func (k *Keeper) GetVaultTotalValue(
ctx sdk.Context,
denom string,
) (sdk.Coin, error) {
enabledVault, found := k.GetAllowedVault(ctx, denom)
if !found {
return sdk.Coin{}, types.ErrVaultRecordNotFound
}
strategy, err := k.GetStrategy(enabledVault.VaultStrategy)
if err != nil {
return sdk.Coin{}, types.ErrInvalidVaultStrategy
}
return strategy.GetEstimatedTotalAssets(enabledVault.Denom)
}
// GetVaultAccountSupplied returns the supplied amount for a single address
// within a vault.
func (k *Keeper) GetVaultAccountSupplied(
ctx sdk.Context,
denom string,
acc sdk.AccAddress,
) (sdk.Coin, error) {
vaultShareRecord, found := k.GetVaultShareRecord(ctx, denom, acc)
if !found {
return sdk.Coin{}, types.ErrVaultShareRecordNotFound
}
return vaultShareRecord.AmountSupplied, nil
}
// GetVaultAccountValue returns the value of a single address within a vault
// if the account were to withdraw their entire balance.
func (k *Keeper) GetVaultAccountValue(
ctx sdk.Context,
denom string,
acc sdk.AccAddress,
) (sdk.Coin, error) {
totalSupplied, err := k.GetVaultTotalSupplied(ctx, denom)
if err != nil {
return sdk.Coin{}, err
}
accSupplied, err := k.GetVaultAccountSupplied(ctx, denom, acc)
if err != nil {
return sdk.Coin{}, err
}
vaultTotalValue, err := k.GetVaultTotalValue(ctx, denom)
if err != nil {
return sdk.Coin{}, err
}
// percent of vault account ownership = accountSupply / totalSupply
// value of vault account ownership = percentOwned * totalValue
vaultShare := accSupplied.Amount.Quo(totalSupplied.Amount)
shareValue := vaultTotalValue.Amount.Mul(vaultShare)
return sdk.NewCoin(denom, shareValue), nil
}
// ----------------------------------------------------------------------------
// VaultRecord -- vault total supplies
// GetVaultRecord returns the vault record for a given denom.
func (k *Keeper) GetVaultRecord(
ctx sdk.Context,
vaultDenom string,
) (types.VaultRecord, bool) {
store := prefix.NewStore(ctx.KVStore(k.key), types.VaultRecordKeyPrefix)
bz := store.Get(types.VaultKey(vaultDenom))
if bz == nil {
return types.VaultRecord{}, false
}
var record types.VaultRecord
k.cdc.MustUnmarshal(bz, &record)
return record, true
}
// UpdateVaultRecord updates the vault record in state for a given denom. This
// deletes it if the supply is zero and updates the state if supply is non-zero.
func (k *Keeper) UpdateVaultRecord(
ctx sdk.Context,
vaultRecord types.VaultRecord,
) {
if vaultRecord.TotalSupply.IsZero() {
k.DeleteVaultRecord(ctx, vaultRecord.Denom)
} else {
k.SetVaultRecord(ctx, vaultRecord)
}
}
// DeleteVaultRecord deletes the vault record for a given denom.
func (k *Keeper) DeleteVaultRecord(ctx sdk.Context, vaultDenom string) {
store := prefix.NewStore(ctx.KVStore(k.key), types.VaultRecordKeyPrefix)
store.Delete(types.VaultKey(vaultDenom))
}
// SetVaultRecord sets the vault record for a given denom.
func (k *Keeper) SetVaultRecord(ctx sdk.Context, record types.VaultRecord) {
store := prefix.NewStore(ctx.KVStore(k.key), types.VaultRecordKeyPrefix)
bz := k.cdc.MustMarshal(&record)
store.Set(types.VaultKey(record.Denom), bz)
}
// ----------------------------------------------------------------------------
// VaultShare -- user shares per vault
// GetVaultShareRecord returns the vault share record for a given denom and
// account.
func (k *Keeper) GetVaultShareRecord(
ctx sdk.Context,
vaultDenom string,
acc sdk.AccAddress,
) (types.VaultShareRecord, bool) {
store := prefix.NewStore(ctx.KVStore(k.key), types.VaultRecordKeyPrefix)
bz := store.Get(types.DepositorVaultSharesKey(acc, vaultDenom))
if bz == nil {
return types.VaultShareRecord{}, false
}
var record types.VaultShareRecord
k.cdc.MustUnmarshal(bz, &record)
return record, true
}
// UpdateVaultShareRecord updates the vault share record in state for a given
// denom and account. This deletes it if the supply is zero and updates the
// state if supply is non-zero.
func (k *Keeper) UpdateVaultShareRecord(
ctx sdk.Context,
record types.VaultShareRecord,
) {
if record.AmountSupplied.IsZero() {
k.DeleteVaultShareRecord(ctx, record.AmountSupplied.Denom, record.Depositor)
} else {
k.SetVaultShareRecord(ctx, record)
}
}
// DeleteVaultShareRecord deletes the vault share record for a given denom and
// account.
func (k *Keeper) DeleteVaultShareRecord(
ctx sdk.Context,
vaultDenom string,
acc sdk.AccAddress,
) {
store := prefix.NewStore(ctx.KVStore(k.key), types.VaultRecordKeyPrefix)
store.Delete(types.DepositorVaultSharesKey(acc, vaultDenom))
}
// SetVaultShareRecord sets the vault share record for a given denom and account.
func (k *Keeper) SetVaultShareRecord(
ctx sdk.Context,
record types.VaultShareRecord,
) {
store := prefix.NewStore(ctx.KVStore(k.key), types.VaultRecordKeyPrefix)
bz := k.cdc.MustMarshal(&record)
store.Set(types.DepositorVaultSharesKey(record.Depositor, record.AmountSupplied.Denom), bz)
}

245
x/earn/keeper/vault_test.go Normal file
View File

@ -0,0 +1,245 @@
package keeper_test
import (
"testing"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/kava-labs/kava/x/earn/testutil"
"github.com/kava-labs/kava/x/earn/types"
"github.com/stretchr/testify/suite"
)
type vaultTestSuite struct {
testutil.Suite
}
func (suite *vaultTestSuite) SetupTest() {
suite.Suite.SetupTest()
suite.Keeper.SetParams(suite.Ctx, types.DefaultParams())
}
func TestVaultTestSuite(t *testing.T) {
suite.Run(t, new(vaultTestSuite))
}
func (suite *vaultTestSuite) TestGetVaultTotalSupplied() {
vaultDenom := "usdx"
startBalance := sdk.NewInt64Coin(vaultDenom, 1000)
depositAmount := sdk.NewInt64Coin(vaultDenom, 100)
suite.CreateVault(vaultDenom, types.STRATEGY_TYPE_STABLECOIN_STAKERS)
acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount)
suite.Require().NoError(err)
vaultTotalSupplied, err := suite.Keeper.GetVaultTotalSupplied(suite.Ctx, vaultDenom)
suite.Require().NoError(err)
suite.Equal(depositAmount, vaultTotalSupplied)
}
func (suite *vaultTestSuite) TestGetVaultTotalSupplied_NotFound() {
vaultDenom := "usdx"
_, err := suite.Keeper.GetVaultTotalSupplied(suite.Ctx, vaultDenom)
suite.Require().Error(err)
suite.Require().ErrorIs(err, types.ErrVaultRecordNotFound)
}
func (suite *vaultTestSuite) TestGetVaultTotalValue() {
// TODO: After strategy implemented GetEstimatedTotalAssets
}
func (suite *vaultTestSuite) TestGetVaultTotalValue_NotFound() {
vaultDenom := "usdx"
_, err := suite.Keeper.GetVaultTotalValue(suite.Ctx, vaultDenom)
suite.Require().Error(err)
suite.Require().ErrorIs(err, types.ErrVaultRecordNotFound)
}
func (suite *vaultTestSuite) TestGetVaultTotalValue_InvalidStrategy() {
vaultDenom := "usdx"
suite.CreateVault(vaultDenom, 99999) // not valid strategy type
_, err := suite.Keeper.GetVaultTotalValue(suite.Ctx, vaultDenom)
suite.Require().Error(err)
suite.Require().ErrorIs(err, types.ErrInvalidVaultStrategy)
}
func (suite *vaultTestSuite) TestGetVaultAccountSupplied() {
vaultDenom := "usdx"
startBalance := sdk.NewInt64Coin(vaultDenom, 1000)
deposit1Amount := sdk.NewInt64Coin(vaultDenom, 100)
deposit2Amount := sdk.NewInt64Coin(vaultDenom, 100)
suite.CreateVault(vaultDenom, types.STRATEGY_TYPE_STABLECOIN_STAKERS)
acc1 := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
acc2 := suite.CreateAccount(sdk.NewCoins(startBalance), 1)
// Before deposit, account supplied is 0
_, err := suite.Keeper.GetVaultAccountSupplied(suite.Ctx, vaultDenom, acc1.GetAddress())
suite.Require().Error(err)
suite.Require().ErrorIs(err, types.ErrVaultShareRecordNotFound)
_, err = suite.Keeper.GetVaultAccountSupplied(suite.Ctx, vaultDenom, acc2.GetAddress())
suite.Require().Error(err)
suite.Require().ErrorIs(err, types.ErrVaultShareRecordNotFound)
// Deposits from both accounts
err = suite.Keeper.Deposit(suite.Ctx, acc1.GetAddress(), deposit1Amount)
suite.Require().NoError(err)
err = suite.Keeper.Deposit(suite.Ctx, acc2.GetAddress(), deposit2Amount)
suite.Require().NoError(err)
// Check balances
vaultAcc1Supplied, err := suite.Keeper.GetVaultAccountSupplied(suite.Ctx, vaultDenom, acc1.GetAddress())
suite.Require().NoError(err)
vaultAcc2Supplied, err := suite.Keeper.GetVaultAccountSupplied(suite.Ctx, vaultDenom, acc2.GetAddress())
suite.Require().NoError(err)
// Account supply only includes the deposit from respective accounts
suite.Equal(deposit1Amount, vaultAcc1Supplied)
suite.Equal(deposit1Amount, vaultAcc2Supplied)
}
func (suite *vaultTestSuite) TestGetVaultAccountValue() {
vaultDenom := "usdx"
startBalance := sdk.NewInt64Coin(vaultDenom, 1000)
depositAmount := sdk.NewInt64Coin(vaultDenom, 100)
acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
suite.CreateVault(vaultDenom, types.STRATEGY_TYPE_STABLECOIN_STAKERS)
err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount)
suite.Require().NoError(err)
suite.T().Skip("TODO: After strategy GetEstimatedTotalAssets implemented")
_, err = suite.Keeper.GetVaultAccountValue(suite.Ctx, vaultDenom, acc.GetAddress())
suite.Require().Error(err)
suite.Require().ErrorIs(err, types.ErrVaultShareRecordNotFound)
}
func (suite *vaultTestSuite) TestGetVaultAccountValue_VaultNotFound() {
vaultDenom := "usdx"
acc := suite.CreateAccount(sdk.NewCoins(), 0)
_, err := suite.Keeper.GetVaultAccountValue(suite.Ctx, vaultDenom, acc.GetAddress())
suite.Require().Error(err)
suite.Require().ErrorIs(err, types.ErrVaultRecordNotFound)
}
func (suite *vaultTestSuite) TestGetVaultAccountValue_ShareNotFound() {
vaultDenom := "usdx"
startBalance := sdk.NewInt64Coin(vaultDenom, 1000)
depositAmount := sdk.NewInt64Coin(vaultDenom, 100)
acc1 := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
acc2 := suite.CreateAccount(sdk.NewCoins(startBalance), 1)
suite.CreateVault(vaultDenom, types.STRATEGY_TYPE_STABLECOIN_STAKERS)
// Deposit from acc1 so that vault record exists
err := suite.Keeper.Deposit(suite.Ctx, acc1.GetAddress(), depositAmount)
suite.Require().NoError(err)
// Query from acc2 with no share record
_, err = suite.Keeper.GetVaultAccountValue(suite.Ctx, vaultDenom, acc2.GetAddress())
suite.Require().Error(err)
suite.Require().ErrorIs(err, types.ErrVaultShareRecordNotFound)
}
// ----------------------------------------------------------------------------
// State methods
func (suite *vaultTestSuite) TestGetVaultRecord() {
record := types.NewVaultRecord("usdx")
_, found := suite.Keeper.GetVaultRecord(suite.Ctx, record.Denom)
suite.Require().False(found)
suite.Keeper.SetVaultRecord(suite.Ctx, record)
stateRecord, found := suite.Keeper.GetVaultRecord(suite.Ctx, record.Denom)
suite.Require().True(found)
suite.Require().Equal(record, stateRecord)
}
func (suite *vaultTestSuite) TestUpdateVaultRecord() {
record := types.NewVaultRecord("usdx")
record.TotalSupply = sdk.NewInt64Coin("usdx", 100)
// Update vault
suite.Keeper.UpdateVaultRecord(suite.Ctx, record)
stateRecord, found := suite.Keeper.GetVaultRecord(suite.Ctx, record.Denom)
suite.Require().True(found, "vault record with supply should exist")
suite.Require().Equal(record, stateRecord)
// Remove supply
record.TotalSupply = sdk.NewInt64Coin("usdx", 0)
suite.Keeper.UpdateVaultRecord(suite.Ctx, record)
_, found = suite.Keeper.GetVaultRecord(suite.Ctx, record.Denom)
suite.Require().False(found, "vault record with 0 supply should be deleted")
}
func (suite *vaultTestSuite) TestGetVaultShareRecord() {
vaultDenom := "usdx"
startBalance := sdk.NewInt64Coin(vaultDenom, 1000)
depositAmount := sdk.NewInt64Coin(vaultDenom, 100)
acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
record := types.NewVaultShareRecord(acc.GetAddress(), vaultDenom)
// Check share doesn't exist before deposit
_, found := suite.Keeper.GetVaultShareRecord(suite.Ctx, vaultDenom, acc.GetAddress())
suite.Require().False(found, "vault share record should not exist before deposit")
// Update share record
record.AmountSupplied = depositAmount
suite.Keeper.SetVaultShareRecord(suite.Ctx, record)
// Check share exists and matches set value
stateRecord, found := suite.Keeper.GetVaultShareRecord(suite.Ctx, vaultDenom, acc.GetAddress())
suite.Require().True(found)
suite.Require().Equal(record, stateRecord)
}
func (suite *vaultTestSuite) TestUpdateVaultShareRecord() {
vaultDenom := "usdx"
startBalance := sdk.NewInt64Coin(vaultDenom, 1000)
depositAmount := sdk.NewInt64Coin(vaultDenom, 100)
acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
record := types.NewVaultShareRecord(acc.GetAddress(), vaultDenom)
record.AmountSupplied = depositAmount
// Update vault
suite.Keeper.UpdateVaultShareRecord(suite.Ctx, record)
stateRecord, found := suite.Keeper.GetVaultShareRecord(suite.Ctx, vaultDenom, acc.GetAddress())
suite.Require().True(found, "vault share record with supply should exist")
suite.Require().Equal(record, stateRecord)
// Remove supply
record.AmountSupplied = sdk.NewInt64Coin("usdx", 0)
suite.Keeper.UpdateVaultShareRecord(suite.Ctx, record)
_, found = suite.Keeper.GetVaultShareRecord(suite.Ctx, vaultDenom, acc.GetAddress())
suite.Require().False(found, "vault share record with 0 supply should be deleted")
}

84
x/earn/keeper/withdraw.go Normal file
View File

@ -0,0 +1,84 @@
package keeper
import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/kava-labs/kava/x/earn/types"
)
// Withdraw removes the amount of supplied tokens from a vault and transfers it
// back to the account.
func (k *Keeper) Withdraw(ctx sdk.Context, from sdk.AccAddress, amount sdk.Coin) error {
// Get AllowedVault, if not found (not a valid vault), return error
allowedVault, found := k.GetAllowedVault(ctx, amount.Denom)
if !found {
return types.ErrInvalidVaultDenom
}
if amount.IsZero() {
return types.ErrInsufficientAmount
}
// Check if VaultRecord exists, return error if not exist as it's empty
vaultRecord, found := k.GetVaultRecord(ctx, amount.Denom)
if !found {
return types.ErrVaultRecordNotFound
}
// Get VaultShareRecord for account, create if not exist
vaultShareRecord, found := k.GetVaultShareRecord(ctx, amount.Denom, from)
if !found {
return types.ErrVaultShareRecordNotFound
}
// Check if VaultShareRecord has enough supplied to withdraw
if vaultShareRecord.AmountSupplied.Amount.LT(amount.Amount) {
return sdkerrors.Wrapf(
types.ErrInvalidShares,
"withdraw of %s shares greater than %s shares supplied",
amount,
vaultShareRecord.AmountSupplied,
)
}
// Send coins back to account
if err := k.bankKeeper.SendCoinsFromModuleToAccount(
ctx,
types.ModuleName,
from,
sdk.NewCoins(amount),
); err != nil {
return err
}
// Decrement VaultRecord and VaultShareRecord supplies
vaultRecord.TotalSupply = vaultRecord.TotalSupply.Sub(amount)
vaultShareRecord.AmountSupplied = vaultShareRecord.AmountSupplied.Sub(amount)
// Update VaultRecord and VaultShareRecord, deletes if zero supply
k.UpdateVaultRecord(ctx, vaultRecord)
k.UpdateVaultShareRecord(ctx, vaultShareRecord)
// Get the strategy for the vault
strategy, err := k.GetStrategy(allowedVault.VaultStrategy)
if err != nil {
return err
}
// Deposit to the strategy
if err := strategy.Withdraw(amount); err != nil {
return err
}
ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeVaultWithdraw,
sdk.NewAttribute(types.AttributeKeyVaultDenom, amount.Denom),
sdk.NewAttribute(types.AttributeKeyOwner, from.String()),
sdk.NewAttribute(sdk.AttributeKeyAmount, amount.Amount.String()),
),
)
return nil
}

View File

@ -0,0 +1,227 @@
package keeper_test
import (
"testing"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/kava-labs/kava/x/earn/testutil"
"github.com/kava-labs/kava/x/earn/types"
"github.com/stretchr/testify/suite"
)
type withdrawTestSuite struct {
testutil.Suite
}
func (suite *withdrawTestSuite) SetupTest() {
suite.Suite.SetupTest()
suite.Keeper.SetParams(suite.Ctx, types.DefaultParams())
}
func TestWithdrawTestSuite(t *testing.T) {
suite.Run(t, new(withdrawTestSuite))
}
func (suite *withdrawTestSuite) TestWithdraw_NoVaultRecord() {
vaultDenom := "busd"
startBalance := sdk.NewInt64Coin(vaultDenom, 1000)
withdrawAmount := sdk.NewInt64Coin(vaultDenom, 100)
suite.CreateVault(vaultDenom, types.STRATEGY_TYPE_STABLECOIN_STAKERS)
acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
// Withdraw without having any prior deposits
err := suite.Keeper.Withdraw(suite.Ctx, acc.GetAddress(), withdrawAmount)
suite.Require().Error(err)
suite.Require().ErrorIs(err, types.ErrVaultRecordNotFound)
// No balance changes
suite.AccountBalanceEqual(
acc.GetAddress(),
sdk.NewCoins(startBalance),
)
suite.ModuleAccountBalanceEqual(
sdk.NewCoins(),
)
}
func (suite *withdrawTestSuite) TestWithdraw_NoVaultShareRecord() {
vaultDenom := "busd"
startBalance := sdk.NewInt64Coin(vaultDenom, 1000)
acc1DepositAmount := sdk.NewCoin(vaultDenom, sdk.NewInt(100))
acc2WithdrawAmount := sdk.NewInt64Coin(vaultDenom, 100)
suite.CreateVault(vaultDenom, types.STRATEGY_TYPE_STABLECOIN_STAKERS)
// Create deposit from acc1 so the VaultRecord exists in state
acc1 := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
err := suite.Keeper.Deposit(suite.Ctx, acc1.GetAddress(), acc1DepositAmount)
suite.Require().NoError(err)
acc2 := suite.CreateAccount(sdk.NewCoins(startBalance), 1)
// Withdraw from acc2 without having any prior deposits
err = suite.Keeper.Withdraw(suite.Ctx, acc2.GetAddress(), acc2WithdrawAmount)
suite.Require().Error(err)
suite.Require().ErrorIs(err, types.ErrVaultShareRecordNotFound)
// No balance changes in acc2
suite.AccountBalanceEqual(
acc2.GetAddress(),
sdk.NewCoins(startBalance),
)
suite.ModuleAccountBalanceEqual(
sdk.NewCoins(acc1DepositAmount),
)
}
func (suite *withdrawTestSuite) TestWithdraw_ExceedBalance() {
vaultDenom := "busd"
startBalance := sdk.NewInt64Coin(vaultDenom, 1000)
depositAmount := sdk.NewInt64Coin(vaultDenom, 100)
withdrawAmount := sdk.NewInt64Coin(vaultDenom, 200)
suite.CreateVault(vaultDenom, types.STRATEGY_TYPE_STABLECOIN_STAKERS)
acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount)
suite.Require().NoError(err)
err = suite.Keeper.Withdraw(suite.Ctx, acc.GetAddress(), withdrawAmount)
suite.Require().Error(err)
suite.Require().ErrorIs(err, types.ErrInvalidShares)
// Balances still the same after deposit
suite.AccountBalanceEqual(
acc.GetAddress(),
sdk.NewCoins(startBalance.Sub(depositAmount)),
)
suite.ModuleAccountBalanceEqual(
sdk.NewCoins(depositAmount),
)
}
func (suite *withdrawTestSuite) TestWithdraw_Zero() {
vaultDenom := "busd"
startBalance := sdk.NewInt64Coin(vaultDenom, 1000)
withdrawAmount := sdk.NewInt64Coin(vaultDenom, 0)
suite.CreateVault(vaultDenom, types.STRATEGY_TYPE_STABLECOIN_STAKERS)
acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
err := suite.Keeper.Withdraw(suite.Ctx, acc.GetAddress(), withdrawAmount)
suite.Require().Error(err)
suite.Require().ErrorIs(err, types.ErrInsufficientAmount)
// No changes in balances
suite.AccountBalanceEqual(
acc.GetAddress(),
sdk.NewCoins(startBalance),
)
suite.ModuleAccountBalanceEqual(
sdk.NewCoins(),
)
}
func (suite *withdrawTestSuite) TestWithdraw_InvalidVault() {
vaultDenom := "busd"
startBalance := sdk.NewInt64Coin(vaultDenom, 1000)
withdrawAmount := sdk.NewInt64Coin(vaultDenom, 1001)
// Vault not created -- doesn't exist
acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
err := suite.Keeper.Withdraw(suite.Ctx, acc.GetAddress(), withdrawAmount)
suite.Require().Error(err)
suite.Require().ErrorIs(err, types.ErrInvalidVaultDenom)
// No changes in balances
suite.AccountBalanceEqual(
acc.GetAddress(),
sdk.NewCoins(startBalance),
)
suite.ModuleAccountBalanceEqual(
sdk.NewCoins(),
)
}
func (suite *withdrawTestSuite) TestWithdraw_FullBalance() {
vaultDenom := "busd"
startBalance := sdk.NewInt64Coin(vaultDenom, 1000)
depositAmount := sdk.NewInt64Coin(vaultDenom, 100)
withdrawAmount := sdk.NewInt64Coin(vaultDenom, 100)
suite.CreateVault(vaultDenom, types.STRATEGY_TYPE_STABLECOIN_STAKERS)
acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount)
suite.Require().NoError(err)
err = suite.Keeper.Withdraw(suite.Ctx, acc.GetAddress(), withdrawAmount)
suite.Require().NoError(err)
// No net changes in balances
suite.AccountBalanceEqual(
acc.GetAddress(),
sdk.NewCoins(startBalance),
)
suite.ModuleAccountBalanceEqual(
sdk.NewCoins(),
)
}
func (suite *withdrawTestSuite) TestWithdraw_Partial() {
vaultDenom := "busd"
startBalance := sdk.NewInt64Coin(vaultDenom, 1000)
depositAmount := sdk.NewInt64Coin(vaultDenom, 100)
partialWithdrawAmount := sdk.NewInt64Coin(vaultDenom, 50)
suite.CreateVault(vaultDenom, types.STRATEGY_TYPE_STABLECOIN_STAKERS)
acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount)
suite.Require().NoError(err)
err = suite.Keeper.Withdraw(suite.Ctx, acc.GetAddress(), partialWithdrawAmount)
suite.Require().NoError(err)
suite.AccountBalanceEqual(
acc.GetAddress(),
sdk.NewCoins(startBalance.Sub(depositAmount).Add(partialWithdrawAmount)),
)
// Second withdraw for remaining 50
err = suite.Keeper.Withdraw(suite.Ctx, acc.GetAddress(), partialWithdrawAmount)
suite.Require().NoError(err)
// No more balance to withdraw
err = suite.Keeper.Withdraw(suite.Ctx, acc.GetAddress(), partialWithdrawAmount)
suite.Require().Error(err)
suite.Require().ErrorIs(err, types.ErrVaultRecordNotFound, "vault record should be deleted after no more supplied")
// No net changes in balances
suite.AccountBalanceEqual(
acc.GetAddress(),
sdk.NewCoins(startBalance),
)
suite.ModuleAccountBalanceEqual(
sdk.NewCoins(),
)
}

View File

@ -17,6 +17,7 @@ import (
abci "github.com/tendermint/tendermint/abci/types" abci "github.com/tendermint/tendermint/abci/types"
"github.com/kava-labs/kava/x/earn/client/cli"
"github.com/kava-labs/kava/x/earn/keeper" "github.com/kava-labs/kava/x/earn/keeper"
"github.com/kava-labs/kava/x/earn/types" "github.com/kava-labs/kava/x/earn/types"
) )
@ -75,12 +76,12 @@ func (a AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux
// GetTxCmd returns the root tx command for the module. // GetTxCmd returns the root tx command for the module.
func (AppModuleBasic) GetTxCmd() *cobra.Command { func (AppModuleBasic) GetTxCmd() *cobra.Command {
return nil // TODO: cli.GetTxCmd() return cli.GetTxCmd()
} }
// GetQueryCmd returns no root query command for the module. // GetQueryCmd returns no root query command for the module.
func (AppModuleBasic) GetQueryCmd() *cobra.Command { func (AppModuleBasic) GetQueryCmd() *cobra.Command {
return nil // TODO: cli.GetQueryCmd() return cli.GetQueryCmd()
} }
//____________________________________________________________________________ //____________________________________________________________________________

145
x/earn/testutil/suite.go Normal file
View File

@ -0,0 +1,145 @@
package testutil
import (
"fmt"
"reflect"
"github.com/kava-labs/kava/app"
"github.com/kava-labs/kava/x/earn/keeper"
"github.com/kava-labs/kava/x/earn/types"
"github.com/cosmos/cosmos-sdk/simapp"
sdk "github.com/cosmos/cosmos-sdk/types"
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
BankKeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
"github.com/stretchr/testify/suite"
abci "github.com/tendermint/tendermint/abci/types"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
tmtime "github.com/tendermint/tendermint/types/time"
)
// Suite implements a test suite for the swap module integration tests
type Suite struct {
suite.Suite
Keeper keeper.Keeper
App app.TestApp
Ctx sdk.Context
BankKeeper BankKeeper.Keeper
AccountKeeper authkeeper.AccountKeeper
}
// SetupTest instantiates a new app, keepers, and sets suite state
func (suite *Suite) SetupTest() {
tApp := app.NewTestApp()
ctx := tApp.NewContext(true, tmproto.Header{Height: 1, Time: tmtime.Now()})
suite.Ctx = ctx
suite.App = tApp
suite.Keeper = tApp.GetEarnKeeper()
suite.BankKeeper = tApp.GetBankKeeper()
suite.AccountKeeper = tApp.GetAccountKeeper()
}
// GetEvents returns emitted events on the sdk context
func (suite *Suite) GetEvents() sdk.Events {
return suite.Ctx.EventManager().Events()
}
// AddCoinsToModule adds coins to the swap module account
func (suite *Suite) AddCoinsToModule(amount sdk.Coins) {
// Does not use suite.BankKeeper.MintCoins as module account would not have permission to mint
err := simapp.FundModuleAccount(suite.BankKeeper, suite.Ctx, types.ModuleName, amount)
suite.Require().NoError(err)
}
// RemoveCoinsFromModule removes coins to the swap module account
func (suite *Suite) RemoveCoinsFromModule(amount sdk.Coins) {
// Swap module does not have BurnCoins permission so we need to transfer to gov first to burn
err := suite.BankKeeper.SendCoinsFromModuleToModule(suite.Ctx, types.ModuleAccountName, govtypes.ModuleName, amount)
suite.Require().NoError(err)
err = suite.BankKeeper.BurnCoins(suite.Ctx, govtypes.ModuleName, amount)
suite.Require().NoError(err)
}
// CreateAccount creates a new account from the provided balance, using index
// to create different new addresses.
func (suite *Suite) CreateAccount(initialBalance sdk.Coins, index int) authtypes.AccountI {
_, addrs := app.GeneratePrivKeyAddressPairs(index + 1)
ak := suite.App.GetAccountKeeper()
acc := ak.NewAccountWithAddress(suite.Ctx, addrs[index])
ak.SetAccount(suite.Ctx, acc)
err := simapp.FundAccount(suite.BankKeeper, suite.Ctx, acc.GetAddress(), initialBalance)
suite.Require().NoError(err)
return acc
}
// NewAccountFromAddr creates a new account from the provided address with the provided balance
func (suite *Suite) NewAccountFromAddr(addr sdk.AccAddress, balance sdk.Coins) authtypes.AccountI {
ak := suite.App.GetAccountKeeper()
acc := ak.NewAccountWithAddress(suite.Ctx, addr)
ak.SetAccount(suite.Ctx, acc)
err := simapp.FundAccount(suite.BankKeeper, suite.Ctx, acc.GetAddress(), balance)
suite.Require().NoError(err)
return acc
}
// CreateVault adds a new vault to the keeper parameters
func (suite *Suite) CreateVault(vaultDenom string, vaultStrategy types.StrategyType) {
vault := types.NewAllowedVault(vaultDenom, vaultStrategy)
suite.Require().NoError(vault.Validate())
// allowedVaults := suite.Keeper.GetAllowedVaults(suite.Ctx)
// allowedVaults = append(allowedVaults, vault)
suite.Keeper.SetParams(
suite.Ctx,
types.NewParams(types.AllowedVaults{vault}),
)
}
// AccountBalanceEqual asserts that the coins match the account balance
func (suite *Suite) AccountBalanceEqual(addr sdk.AccAddress, coins sdk.Coins) {
balance := suite.BankKeeper.GetAllBalances(suite.Ctx, addr)
suite.Equal(coins, balance, fmt.Sprintf("expected account balance to equal coins %s, but got %s", coins, balance))
}
// ModuleAccountBalanceEqual asserts that the swap module account balance matches the provided coins
func (suite *Suite) ModuleAccountBalanceEqual(coins sdk.Coins) {
balance := suite.BankKeeper.GetAllBalances(
suite.Ctx,
suite.AccountKeeper.GetModuleAddress(types.ModuleAccountName),
)
suite.Equal(coins, balance, fmt.Sprintf("expected module account balance to equal coins %s, but got %s", coins, balance))
}
// EventsContains asserts that the expected event is in the provided events
func (suite *Suite) EventsContains(events sdk.Events, expectedEvent sdk.Event) {
foundMatch := false
for _, event := range events {
if event.Type == expectedEvent.Type {
if reflect.DeepEqual(attrsToMap(expectedEvent.Attributes), attrsToMap(event.Attributes)) {
foundMatch = true
}
}
}
suite.True(foundMatch, fmt.Sprintf("event of type %s not found or did not match", expectedEvent.Type))
}
func attrsToMap(attrs []abci.EventAttribute) []sdk.Attribute { // new cosmos changed the event attribute type
out := []sdk.Attribute{}
for _, attr := range attrs {
out = append(out, sdk.NewAttribute(string(attr.Key), string(attr.Value)))
}
return out
}

View File

@ -3,6 +3,7 @@ package types
import ( import (
"github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/types/msgservice"
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
@ -11,14 +12,19 @@ import (
// RegisterLegacyAminoCodec registers all the necessary types and interfaces for the // RegisterLegacyAminoCodec registers all the necessary types and interfaces for the
// earn module. // earn module.
func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {
cdc.RegisterConcrete(&MsgDeposit{}, "earn/MsgDeposit", nil)
cdc.RegisterConcrete(&MsgWithdraw{}, "earn/MsgWithdraw", nil)
} }
// RegisterInterfaces registers proto messages under their interfaces for unmarshalling, // RegisterInterfaces registers proto messages under their interfaces for unmarshalling,
// in addition to registerting the msg service for handling tx msgs // in addition to registerting the msg service for handling tx msgs
func RegisterInterfaces(registry types.InterfaceRegistry) { func RegisterInterfaces(registry types.InterfaceRegistry) {
registry.RegisterImplementations((*sdk.Msg)(nil)) registry.RegisterImplementations((*sdk.Msg)(nil),
&MsgDeposit{},
&MsgWithdraw{},
)
// msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc)
} }
var ( var (

15
x/earn/types/errors.go Normal file
View File

@ -0,0 +1,15 @@
package types
import (
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
// earn module errors
var (
ErrInvalidVaultDenom = sdkerrors.Register(ModuleName, 2, "invalid vault denom")
ErrInvalidVaultStrategy = sdkerrors.Register(ModuleName, 3, "invalid vault strategy")
ErrInsufficientAmount = sdkerrors.Register(ModuleName, 4, "insufficient amount")
ErrInvalidShares = sdkerrors.Register(ModuleName, 5, "invalid shares")
ErrVaultRecordNotFound = sdkerrors.Register(ModuleName, 6, "vault record not found")
ErrVaultShareRecordNotFound = sdkerrors.Register(ModuleName, 7, "vault share record not found")
)

12
x/earn/types/events.go Normal file
View File

@ -0,0 +1,12 @@
package types
// Event types for swap module
const (
AttributeValueCategory = ModuleName
EventTypeVaultDeposit = "vault_deposit"
EventTypeVaultWithdraw = "vault_withdraw"
AttributeKeyVaultDenom = "vault_denom"
AttributeKeyDepositor = "depositor"
AttributeKeyShares = "shares"
AttributeKeyOwner = "owner"
)

View File

@ -23,10 +23,14 @@ var _ = math.Inf
// proto package needs to be updated. // proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
// GenesisState defines the earn module's genesis state. // GenesisState defines the swap module's genesis state.
type GenesisState struct { type GenesisState struct {
// params defines all the paramaters related to earn // params defines all the paramaters related to earn
Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"`
// vault_records defines the available vaults
VaultRecords VaultRecords `protobuf:"bytes,2,rep,name=vault_records,json=vaultRecords,proto3,castrepeated=VaultRecords" json:"vault_records"`
// share_records defines the owned shares of each vault
VaultShareRecords VaultShareRecords `protobuf:"bytes,3,rep,name=vault_share_records,json=vaultShareRecords,proto3,castrepeated=VaultShareRecords" json:"vault_share_records"`
} }
func (m *GenesisState) Reset() { *m = GenesisState{} } func (m *GenesisState) Reset() { *m = GenesisState{} }
@ -69,65 +73,47 @@ func (m *GenesisState) GetParams() Params {
return Params{} return Params{}
} }
// Params defines the parameters for the earn module. func (m *GenesisState) GetVaultRecords() VaultRecords {
type Params struct { if m != nil {
return m.VaultRecords
}
return nil
} }
func (m *Params) Reset() { *m = Params{} } func (m *GenesisState) GetVaultShareRecords() VaultShareRecords {
func (m *Params) String() string { return proto.CompactTextString(m) } if m != nil {
func (*Params) ProtoMessage() {} return m.VaultShareRecords
func (*Params) Descriptor() ([]byte, []int) {
return fileDescriptor_514fe130cb964f8c, []int{1}
} }
func (m *Params) XXX_Unmarshal(b []byte) error { return nil
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 init() { func init() {
proto.RegisterType((*GenesisState)(nil), "kava.earn.v1beta1.GenesisState") proto.RegisterType((*GenesisState)(nil), "kava.earn.v1beta1.GenesisState")
proto.RegisterType((*Params)(nil), "kava.earn.v1beta1.Params")
} }
func init() { proto.RegisterFile("kava/earn/v1beta1/genesis.proto", fileDescriptor_514fe130cb964f8c) } func init() { proto.RegisterFile("kava/earn/v1beta1/genesis.proto", fileDescriptor_514fe130cb964f8c) }
var fileDescriptor_514fe130cb964f8c = []byte{ var fileDescriptor_514fe130cb964f8c = []byte{
// 195 bytes of a gzipped FileDescriptorProto // 293 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xcf, 0x4e, 0x2c, 0x4b, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xcf, 0x4e, 0x2c, 0x4b,
0xd4, 0x4f, 0x4d, 0x2c, 0xca, 0xd3, 0x2f, 0x33, 0x4c, 0x4a, 0x2d, 0x49, 0x34, 0xd4, 0x4f, 0x4f, 0xd4, 0x4f, 0x4d, 0x2c, 0xca, 0xd3, 0x2f, 0x33, 0x4c, 0x4a, 0x2d, 0x49, 0x34, 0xd4, 0x4f, 0x4f,
0xcd, 0x4b, 0x2d, 0xce, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x04, 0x29, 0xd0, 0xcd, 0x4b, 0x2d, 0xce, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x04, 0x29, 0xd0,
0x03, 0x29, 0xd0, 0x83, 0x2a, 0x90, 0x12, 0x49, 0xcf, 0x4f, 0xcf, 0x07, 0xcb, 0xea, 0x83, 0x58, 0x03, 0x29, 0xd0, 0x83, 0x2a, 0x90, 0x92, 0xc5, 0xd4, 0x53, 0x96, 0x58, 0x9a, 0x53, 0x02, 0xd1,
0x10, 0x85, 0x4a, 0xee, 0x5c, 0x3c, 0xee, 0x10, 0x9d, 0xc1, 0x25, 0x89, 0x25, 0xa9, 0x42, 0xe6, 0x21, 0x25, 0x87, 0x29, 0x5d, 0x90, 0x58, 0x94, 0x98, 0x0b, 0x35, 0x51, 0x4a, 0x24, 0x3d, 0x3f,
0x5c, 0x6c, 0x05, 0x89, 0x45, 0x89, 0xb9, 0xc5, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0xdc, 0x46, 0x92, 0x3d, 0x1f, 0xcc, 0xd4, 0x07, 0xb1, 0x20, 0xa2, 0x4a, 0x93, 0x98, 0xb8, 0x78, 0xdc, 0x21, 0x36,
0x7a, 0x18, 0x26, 0xe9, 0x05, 0x80, 0x15, 0x38, 0xb1, 0x9c, 0xb8, 0x27, 0xcf, 0x10, 0x04, 0x55, 0x07, 0x97, 0x24, 0x96, 0xa4, 0x0a, 0x99, 0x73, 0xb1, 0x41, 0xb4, 0x49, 0x30, 0x2a, 0x30, 0x6a,
0xae, 0xc4, 0xc1, 0xc5, 0x06, 0x15, 0x77, 0x38, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x70, 0x1b, 0x49, 0xea, 0x61, 0xb8, 0x44, 0x2f, 0x00, 0xac, 0xc0, 0x89, 0xe5, 0xc4, 0x3d, 0x79,
0x07, 0x8f, 0xe4, 0x18, 0x27, 0x3c, 0x96, 0x63, 0xb8, 0xf0, 0x58, 0x8e, 0xe1, 0xc6, 0x63, 0x39, 0x86, 0x20, 0xa8, 0x72, 0xa1, 0x48, 0x2e, 0x5e, 0xb0, 0x73, 0xe2, 0x8b, 0x52, 0x93, 0xf3, 0x8b,
0x86, 0x28, 0xb5, 0xf4, 0xcc, 0x92, 0x8c, 0xd2, 0x24, 0xbd, 0xe4, 0xfc, 0x5c, 0x7d, 0x90, 0xb1, 0x52, 0x8a, 0x25, 0x98, 0x14, 0x98, 0x35, 0xb8, 0x8d, 0xe4, 0xb0, 0xe8, 0x0f, 0x03, 0xa9, 0x0b,
0xba, 0x39, 0x89, 0x49, 0xc5, 0x60, 0x96, 0x7e, 0x05, 0xc4, 0x37, 0x25, 0x95, 0x05, 0xa9, 0xc5, 0x02, 0x2b, 0x73, 0x12, 0x01, 0x19, 0xb2, 0xea, 0xbe, 0x3c, 0x0f, 0x92, 0x60, 0x71, 0x10, 0x4f,
0x49, 0x6c, 0x60, 0xb7, 0x19, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0x8c, 0x51, 0x81, 0x77, 0xe7, 0x19, 0x12, 0x4f, 0x28, 0x8f, 0x4b, 0x18, 0x62, 0x74, 0x71, 0x46, 0x62, 0x51, 0x2a, 0xdc, 0x02,
0x00, 0x00, 0x00, 0x66, 0xb0, 0x05, 0xca, 0xb8, 0x2c, 0x08, 0x06, 0x29, 0x86, 0xda, 0x22, 0x09, 0xb5, 0x45, 0x10,
0x5d, 0xa6, 0x38, 0x48, 0xb0, 0x0c, 0x5d, 0xc8, 0xc9, 0xe1, 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, 0xd4, 0xd2, 0x33, 0x4b, 0x32, 0x4a, 0x93, 0xf4, 0x92, 0xf3, 0x73, 0xf5,
0x41, 0xd6, 0xea, 0xe6, 0x24, 0x26, 0x15, 0x83, 0x59, 0xfa, 0x15, 0x90, 0xb0, 0x2f, 0xa9, 0x2c,
0x48, 0x2d, 0x4e, 0x62, 0x03, 0x87, 0xae, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0x97, 0x15, 0xe4,
0xfa, 0xe8, 0x01, 0x00, 0x00,
} }
func (m *GenesisState) Marshal() (dAtA []byte, err error) { func (m *GenesisState) Marshal() (dAtA []byte, err error) {
@ -150,6 +136,34 @@ func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i _ = i
var l int var l int
_ = l _ = l
if len(m.VaultShareRecords) > 0 {
for iNdEx := len(m.VaultShareRecords) - 1; iNdEx >= 0; iNdEx-- {
{
size, err := m.VaultShareRecords[iNdEx].MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintGenesis(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x1a
}
}
if len(m.VaultRecords) > 0 {
for iNdEx := len(m.VaultRecords) - 1; iNdEx >= 0; iNdEx-- {
{
size, err := m.VaultRecords[iNdEx].MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintGenesis(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x12
}
}
{ {
size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) size, err := m.Params.MarshalToSizedBuffer(dAtA[:i])
if err != nil { if err != nil {
@ -163,29 +177,6 @@ func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) {
return len(dAtA) - i, nil 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
return len(dAtA) - i, nil
}
func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int { func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int {
offset -= sovGenesis(v) offset -= sovGenesis(v)
base := offset base := offset
@ -205,15 +196,18 @@ func (m *GenesisState) Size() (n int) {
_ = l _ = l
l = m.Params.Size() l = m.Params.Size()
n += 1 + l + sovGenesis(uint64(l)) n += 1 + l + sovGenesis(uint64(l))
return n if len(m.VaultRecords) > 0 {
for _, e := range m.VaultRecords {
l = e.Size()
n += 1 + l + sovGenesis(uint64(l))
}
}
if len(m.VaultShareRecords) > 0 {
for _, e := range m.VaultShareRecords {
l = e.Size()
n += 1 + l + sovGenesis(uint64(l))
} }
func (m *Params) Size() (n int) {
if m == nil {
return 0
} }
var l int
_ = l
return n return n
} }
@ -285,33 +279,11 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error {
return err return err
} }
iNdEx = postIndex iNdEx = postIndex
default: case 2:
iNdEx = preIndex if wireType != 2 {
skippy, err := skipGenesis(dAtA[iNdEx:]) return fmt.Errorf("proto: wrong wireType = %d for field VaultRecords", wireType)
if err != nil {
return err
} }
if (skippy < 0) || (iNdEx+skippy) < 0 { var msglen int
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 { for shift := uint(0); ; shift += 7 {
if shift >= 64 { if shift >= 64 {
return ErrIntOverflowGenesis return ErrIntOverflowGenesis
@ -321,20 +293,60 @@ func (m *Params) Unmarshal(dAtA []byte) error {
} }
b := dAtA[iNdEx] b := dAtA[iNdEx]
iNdEx++ iNdEx++
wire |= uint64(b&0x7F) << shift msglen |= int(b&0x7F) << shift
if b < 0x80 { if b < 0x80 {
break break
} }
} }
fieldNum := int32(wire >> 3) if msglen < 0 {
wireType := int(wire & 0x7) return ErrInvalidLengthGenesis
if wireType == 4 {
return fmt.Errorf("proto: Params: wiretype end group for non-group")
} }
if fieldNum <= 0 { postIndex := iNdEx + msglen
return fmt.Errorf("proto: Params: illegal tag %d (wire type %d)", fieldNum, wire) if postIndex < 0 {
return ErrInvalidLengthGenesis
} }
switch fieldNum { if postIndex > l {
return io.ErrUnexpectedEOF
}
m.VaultRecords = append(m.VaultRecords, VaultRecord{})
if err := m.VaultRecords[len(m.VaultRecords)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field VaultShareRecords", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenesis
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthGenesis
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthGenesis
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.VaultShareRecords = append(m.VaultShareRecords, VaultShareRecord{})
if err := m.VaultShareRecords[len(m.VaultShareRecords)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default: default:
iNdEx = preIndex iNdEx = preIndex
skippy, err := skipGenesis(dAtA[iNdEx:]) skippy, err := skipGenesis(dAtA[iNdEx:])

View File

@ -1,5 +1,7 @@
package types package types
import sdk "github.com/cosmos/cosmos-sdk/types"
const ( const (
// ModuleName name that will be used throughout the module // ModuleName name that will be used throughout the module
ModuleName = "earn" ModuleName = "earn"
@ -19,3 +21,28 @@ const (
// DefaultParamspace default name for parameter store // DefaultParamspace default name for parameter store
DefaultParamspace = ModuleName DefaultParamspace = ModuleName
) )
// key prefixes for store
var (
VaultRecordKeyPrefix = []byte{0x01} // denom -> vault
VaultSharePrefix = []byte{0x02}
sep = []byte("|")
)
// Vault returns a key generated from a vault denom
func VaultKey(denom string) []byte {
return []byte(denom)
}
// DepositorVaultSharesKey returns a key from a depositor and vault denom
func DepositorVaultSharesKey(depositor sdk.AccAddress, vaultDenom string) []byte {
return createKey(depositor, sep, []byte(vaultDenom))
}
func createKey(bytes ...[]byte) (r []byte) {
for _, b := range bytes {
r = append(r, b...)
}
return
}

85
x/earn/types/msg.go Normal file
View File

@ -0,0 +1,85 @@
package types
import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
var (
_ sdk.Msg = &MsgDeposit{}
_ sdk.Msg = &MsgWithdraw{}
)
// NewMsgDeposit returns a new MsgDeposit.
func NewMsgDeposit(depositor string, amount sdk.Coin) *MsgDeposit {
return &MsgDeposit{
Depositor: depositor,
Amount: amount,
}
}
// ValidateBasic does a simple validation check that doesn't require access to any other information.
func (msg MsgDeposit) ValidateBasic() error {
if msg.Depositor == "" {
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "depositor address cannot be empty")
}
if err := msg.Amount.Validate(); err != nil {
return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, err.Error())
}
return nil
}
// GetSignBytes gets the canonical byte representation of the Msg.
func (msg MsgDeposit) GetSignBytes() []byte {
bz := ModuleCdc.MustMarshalJSON(&msg)
return sdk.MustSortJSON(bz)
}
// GetSigners returns the addresses of signers that must sign.
func (msg MsgDeposit) GetSigners() []sdk.AccAddress {
depositor, err := sdk.AccAddressFromBech32(msg.Depositor)
if err != nil {
panic(err)
}
return []sdk.AccAddress{depositor}
}
// NewMsgWithdraw returns a new MsgWithdraw.
func NewMsgWithdraw(from string, amount sdk.Coin) *MsgWithdraw {
return &MsgWithdraw{
From: from,
Amount: amount,
}
}
// ValidateBasic does a simple validation check that doesn't require access to any other information.
func (msg MsgWithdraw) ValidateBasic() error {
if msg.From == "" {
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "depositor address cannot be empty")
}
if err := msg.Amount.Validate(); err != nil {
return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, err.Error())
}
return nil
}
// GetSignBytes gets the canonical byte representation of the Msg.
func (msg MsgWithdraw) GetSignBytes() []byte {
bz := ModuleCdc.MustMarshalJSON(&msg)
return sdk.MustSortJSON(bz)
}
// GetSigners returns the addresses of signers that must sign.
func (msg MsgWithdraw) GetSigners() []sdk.AccAddress {
depositor, err := sdk.AccAddressFromBech32(msg.From)
if err != nil {
panic(err)
}
return []sdk.AccAddress{depositor}
}

View File

@ -1,20 +1,27 @@
package types package types
import ( import (
fmt "fmt"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
) )
// Parameter keys and default values // Parameter keys and default values
var () var (
KeyAllowedVaults = []byte("AllowedVaults")
DefaultAllowedVaults = AllowedVaults{}
)
// NewParams returns a new params object // NewParams returns a new params object
func NewParams() Params { func NewParams(allowedVaults AllowedVaults) Params {
return Params{} return Params{
AllowedVaults: allowedVaults,
}
} }
// DefaultParams returns default params for earn module // DefaultParams returns default params for earn module
func DefaultParams() Params { func DefaultParams() Params {
return NewParams() return NewParams(DefaultAllowedVaults)
} }
// ParamKeyTable for earn module. // ParamKeyTable for earn module.
@ -25,12 +32,20 @@ func ParamKeyTable() paramtypes.KeyTable {
// ParamSetPairs implements params.ParamSet // ParamSetPairs implements params.ParamSet
func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs {
return paramtypes.ParamSetPairs{ return paramtypes.ParamSetPairs{
// paramtypes.NewParamSetPair(...), paramtypes.NewParamSetPair(KeyAllowedVaults, &p.AllowedVaults, validateAllowedVaultsParams),
} }
} }
// Validate checks that the parameters have valid values. // Validate checks that the parameters have valid values.
func (p Params) Validate() error { func (p Params) Validate() error {
// TODO: return p.AllowedVaults.Validate()
return nil }
func validateAllowedVaultsParams(i interface{}) error {
p, ok := i.(AllowedVaults)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}
return p.Validate()
} }

330
x/earn/types/params.pb.go Normal file
View File

@ -0,0 +1,330 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: kava/earn/v1beta1/params.proto
package types
import (
fmt "fmt"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
io "io"
math "math"
math_bits "math/bits"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
type Params struct {
AllowedVaults AllowedVaults `protobuf:"bytes,1,rep,name=allowed_vaults,json=allowedVaults,proto3,castrepeated=AllowedVaults" json:"allowed_vaults"`
}
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_b9b515f90f68dc5a, []int{0}
}
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) GetAllowedVaults() AllowedVaults {
if m != nil {
return m.AllowedVaults
}
return nil
}
func init() {
proto.RegisterType((*Params)(nil), "kava.earn.v1beta1.Params")
}
func init() { proto.RegisterFile("kava/earn/v1beta1/params.proto", fileDescriptor_b9b515f90f68dc5a) }
var fileDescriptor_b9b515f90f68dc5a = []byte{
// 212 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xcb, 0x4e, 0x2c, 0x4b,
0xd4, 0x4f, 0x4d, 0x2c, 0xca, 0xd3, 0x2f, 0x33, 0x4c, 0x4a, 0x2d, 0x49, 0x34, 0xd4, 0x2f, 0x48,
0x2c, 0x4a, 0xcc, 0x2d, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x04, 0xc9, 0xeb, 0x81,
0xe4, 0xf5, 0xa0, 0xf2, 0x52, 0x22, 0xe9, 0xf9, 0xe9, 0xf9, 0x60, 0x59, 0x7d, 0x10, 0x0b, 0xa2,
0x50, 0x4a, 0x16, 0xd3, 0xa0, 0xb2, 0xc4, 0xd2, 0x9c, 0x12, 0x88, 0xb4, 0x52, 0x3a, 0x17, 0x5b,
0x00, 0xd8, 0x5c, 0xa1, 0x58, 0x2e, 0xbe, 0xc4, 0x9c, 0x9c, 0xfc, 0xf2, 0xd4, 0x94, 0x78, 0xb0,
0x82, 0x62, 0x09, 0x46, 0x05, 0x66, 0x0d, 0x6e, 0x23, 0x79, 0x3d, 0x0c, 0xab, 0xf4, 0x1c, 0x21,
0x0a, 0xc3, 0x40, 0xea, 0x9c, 0x44, 0x4f, 0xdc, 0x93, 0x67, 0x58, 0x75, 0x5f, 0x9e, 0x17, 0x59,
0xb4, 0x38, 0x88, 0x37, 0x11, 0x99, 0xeb, 0xe4, 0x70, 0xe2, 0x91, 0x1c, 0xe3, 0x85, 0x47, 0x72,
0x8c, 0x0f, 0x1e, 0xc9, 0x31, 0x4e, 0x78, 0x2c, 0xc7, 0x70, 0xe1, 0xb1, 0x1c, 0xc3, 0x8d, 0xc7,
0x72, 0x0c, 0x51, 0x6a, 0xe9, 0x99, 0x25, 0x19, 0xa5, 0x49, 0x7a, 0xc9, 0xf9, 0xb9, 0xfa, 0x20,
0xab, 0x74, 0x73, 0x12, 0x93, 0x8a, 0xc1, 0x2c, 0xfd, 0x0a, 0x88, 0xc3, 0x4b, 0x2a, 0x0b, 0x52,
0x8b, 0x93, 0xd8, 0xc0, 0x2e, 0x36, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0x93, 0xe4, 0x56, 0x4c,
0x1b, 0x01, 0x00, 0x00,
}
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.AllowedVaults) > 0 {
for iNdEx := len(m.AllowedVaults) - 1; iNdEx >= 0; iNdEx-- {
{
size, err := m.AllowedVaults[iNdEx].MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintParams(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0xa
}
}
return len(dAtA) - i, nil
}
func encodeVarintParams(dAtA []byte, offset int, v uint64) int {
offset -= sovParams(v)
base := offset
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
dAtA[offset] = uint8(v)
return base
}
func (m *Params) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if len(m.AllowedVaults) > 0 {
for _, e := range m.AllowedVaults {
l = e.Size()
n += 1 + l + sovParams(uint64(l))
}
}
return n
}
func sovParams(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7
}
func sozParams(x uint64) (n int) {
return sovParams(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
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 ErrIntOverflowParams
}
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 AllowedVaults", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowParams
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthParams
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthParams
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.AllowedVaults = append(m.AllowedVaults, AllowedVault{})
if err := m.AllowedVaults[len(m.AllowedVaults)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipParams(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthParams
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipParams(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, ErrIntOverflowParams
}
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, ErrIntOverflowParams
}
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, ErrIntOverflowParams
}
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, ErrInvalidLengthParams
}
iNdEx += length
case 3:
depth++
case 4:
if depth == 0 {
return 0, ErrUnexpectedEndOfGroupParams
}
depth--
case 5:
iNdEx += 4
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
if iNdEx < 0 {
return 0, ErrInvalidLengthParams
}
if depth == 0 {
return iNdEx, nil
}
}
return 0, io.ErrUnexpectedEOF
}
var (
ErrInvalidLengthParams = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowParams = fmt.Errorf("proto: integer overflow")
ErrUnexpectedEndOfGroupParams = fmt.Errorf("proto: unexpected end of group")
)

5
x/earn/types/query.go Normal file
View File

@ -0,0 +1,5 @@
package types
func NewQueryParamsRequest() *QueryParamsRequest {
return &QueryParamsRequest{}
}

View File

@ -114,26 +114,26 @@ func init() {
func init() { proto.RegisterFile("kava/earn/v1beta1/query.proto", fileDescriptor_63f8dee2f3192a6b) } func init() { proto.RegisterFile("kava/earn/v1beta1/query.proto", fileDescriptor_63f8dee2f3192a6b) }
var fileDescriptor_63f8dee2f3192a6b = []byte{ var fileDescriptor_63f8dee2f3192a6b = []byte{
// 304 bytes of a gzipped FileDescriptorProto // 297 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xcd, 0x4e, 0x2c, 0x4b, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xcd, 0x4e, 0x2c, 0x4b,
0xd4, 0x4f, 0x4d, 0x2c, 0xca, 0xd3, 0x2f, 0x33, 0x4c, 0x4a, 0x2d, 0x49, 0x34, 0xd4, 0x2f, 0x2c, 0xd4, 0x4f, 0x4d, 0x2c, 0xca, 0xd3, 0x2f, 0x33, 0x4c, 0x4a, 0x2d, 0x49, 0x34, 0xd4, 0x2f, 0x2c,
0x4d, 0x2d, 0xaa, 0xd4, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x04, 0x49, 0xeb, 0x81, 0xa4, 0x4d, 0x2d, 0xaa, 0xd4, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x04, 0x49, 0xeb, 0x81, 0xa4,
0xf5, 0xa0, 0xd2, 0x52, 0x22, 0xe9, 0xf9, 0xe9, 0xf9, 0x60, 0x59, 0x7d, 0x10, 0x0b, 0xa2, 0x50, 0xf5, 0xa0, 0xd2, 0x52, 0x22, 0xe9, 0xf9, 0xe9, 0xf9, 0x60, 0x59, 0x7d, 0x10, 0x0b, 0xa2, 0x50,
0x4a, 0x26, 0x3d, 0x3f, 0x3f, 0x3d, 0x27, 0x55, 0x3f, 0xb1, 0x20, 0x53, 0x3f, 0x31, 0x2f, 0x2f, 0x4a, 0x26, 0x3d, 0x3f, 0x3f, 0x3d, 0x27, 0x55, 0x3f, 0xb1, 0x20, 0x53, 0x3f, 0x31, 0x2f, 0x2f,
0xbf, 0x24, 0xb1, 0x24, 0x33, 0x3f, 0xaf, 0x18, 0x2a, 0x2b, 0x99, 0x9c, 0x5f, 0x9c, 0x9b, 0x5f, 0xbf, 0x24, 0xb1, 0x24, 0x33, 0x3f, 0xaf, 0x18, 0x2a, 0x2b, 0x99, 0x9c, 0x5f, 0x9c, 0x9b, 0x5f,
0x1c, 0x0f, 0xd1, 0x06, 0xe1, 0x40, 0xa5, 0xe4, 0x31, 0x1d, 0x90, 0x9e, 0x9a, 0x97, 0x5a, 0x9c, 0x1c, 0x0f, 0xd1, 0x06, 0xe1, 0x40, 0xa5, 0xe4, 0x30, 0x1d, 0x50, 0x90, 0x58, 0x94, 0x98, 0x0b,
0x09, 0x55, 0xa0, 0x24, 0xc5, 0x25, 0x14, 0x08, 0x72, 0x51, 0x40, 0x62, 0x51, 0x62, 0x6e, 0x71, 0x95, 0x57, 0x92, 0xe2, 0x12, 0x0a, 0x04, 0x39, 0x28, 0x00, 0x2c, 0x18, 0x94, 0x5a, 0x58, 0x9a,
0x50, 0x6a, 0x61, 0x69, 0x6a, 0x71, 0x89, 0x15, 0x4b, 0xc7, 0x02, 0x79, 0x06, 0xa5, 0x10, 0x2e, 0x5a, 0x5c, 0x62, 0xc5, 0xd2, 0xb1, 0x40, 0x9e, 0x41, 0x29, 0x84, 0x4b, 0x18, 0x45, 0xae, 0xb8,
0x61, 0x14, 0xb9, 0xe2, 0x82, 0xfc, 0xbc, 0xe2, 0x54, 0x21, 0x73, 0x2e, 0xb6, 0x02, 0xb0, 0x88, 0x20, 0x3f, 0xaf, 0x38, 0x55, 0xc8, 0x9c, 0x8b, 0x0d, 0x62, 0x84, 0x04, 0xa3, 0x02, 0xa3, 0x06,
0x04, 0xa3, 0x02, 0xa3, 0x06, 0xb7, 0x91, 0xa4, 0x1e, 0x86, 0x37, 0xf4, 0x20, 0x5a, 0x9c, 0x58, 0xb7, 0x91, 0xa4, 0x1e, 0x86, 0x2f, 0xf4, 0x20, 0x5a, 0x9c, 0x58, 0x4e, 0xdc, 0x93, 0x67, 0x08,
0x4e, 0xdc, 0x93, 0x67, 0x08, 0x82, 0x2a, 0x87, 0x98, 0x6a, 0xd4, 0xcc, 0xc8, 0xc5, 0x0a, 0x36, 0x82, 0x2a, 0x87, 0x98, 0x6a, 0xd4, 0xcc, 0xc8, 0xc5, 0x0a, 0x36, 0x56, 0xa8, 0x8a, 0x8b, 0x0d,
0x56, 0xa8, 0x8a, 0x8b, 0x0d, 0xa2, 0x4e, 0x48, 0x15, 0x8b, 0x11, 0x98, 0xce, 0x92, 0x52, 0x23, 0xa2, 0x4e, 0x48, 0x15, 0x8b, 0x11, 0x98, 0xce, 0x92, 0x52, 0x23, 0xa4, 0x0c, 0xe2, 0x42, 0x25,
0xa4, 0x0c, 0xe2, 0x42, 0x25, 0xc5, 0xa6, 0xcb, 0x4f, 0x26, 0x33, 0x49, 0x0b, 0x49, 0xea, 0x63, 0xc5, 0xa6, 0xcb, 0x4f, 0x26, 0x33, 0x49, 0x0b, 0x49, 0xea, 0xe3, 0xf2, 0xbd, 0x93, 0xc3, 0x89,
0x7a, 0x1f, 0xe2, 0x16, 0x27, 0x87, 0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, 0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1, 0x1c, 0xc3,
0x48, 0x8e, 0x71, 0xc2, 0x63, 0x39, 0x86, 0x0b, 0x8f, 0xe5, 0x18, 0x6e, 0x3c, 0x96, 0x63, 0x88, 0x85, 0xc7, 0x72, 0x0c, 0x37, 0x1e, 0xcb, 0x31, 0x44, 0xa9, 0xa5, 0x67, 0x96, 0x64, 0x94, 0x26,
0x52, 0x4b, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0x05, 0x6b, 0xd7, 0xcd, 0x49, 0xe9, 0x25, 0xe7, 0xe7, 0x82, 0xb5, 0xeb, 0xe6, 0x24, 0x26, 0x15, 0x43, 0x0c, 0xaa, 0x80, 0x18,
0x4c, 0x2a, 0x86, 0x18, 0x54, 0x01, 0x31, 0xaa, 0xa4, 0xb2, 0x20, 0xb5, 0x38, 0x89, 0x0d, 0x1c, 0x55, 0x52, 0x59, 0x90, 0x5a, 0x9c, 0xc4, 0x06, 0x0e, 0x40, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff,
0x80, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x2b, 0x93, 0x51, 0x95, 0xe4, 0x01, 0x00, 0x00, 0xff, 0x84, 0xd8, 0x0f, 0xf9, 0xe3, 0x01, 0x00, 0x00,
} }
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.

View File

@ -0,0 +1,84 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: kava/earn/v1beta1/strategy.proto
package types
import (
fmt "fmt"
_ "github.com/cosmos/cosmos-proto"
_ "github.com/cosmos/cosmos-sdk/types"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
type StrategyType int32
const (
STRATEGY_TYPE_UNKNOWN StrategyType = 0
STRATEGY_TYPE_KAVA_STAKERS StrategyType = 1
// USDC / BUSD vaults use the same strategy but with the denom set in VaultRecord
STRATEGY_TYPE_STABLECOIN_STAKERS StrategyType = 2
STRATEGY_TYPE_KAVA_FOUNDATION StrategyType = 3
)
var StrategyType_name = map[int32]string{
0: "STRATEGY_TYPE_UNKNOWN",
1: "STRATEGY_TYPE_KAVA_STAKERS",
2: "STRATEGY_TYPE_STABLECOIN_STAKERS",
3: "STRATEGY_TYPE_KAVA_FOUNDATION",
}
var StrategyType_value = map[string]int32{
"STRATEGY_TYPE_UNKNOWN": 0,
"STRATEGY_TYPE_KAVA_STAKERS": 1,
"STRATEGY_TYPE_STABLECOIN_STAKERS": 2,
"STRATEGY_TYPE_KAVA_FOUNDATION": 3,
}
func (x StrategyType) String() string {
return proto.EnumName(StrategyType_name, int32(x))
}
func (StrategyType) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_257c4968dd48fa09, []int{0}
}
func init() {
proto.RegisterEnum("kava.earn.v1beta1.StrategyType", StrategyType_name, StrategyType_value)
}
func init() { proto.RegisterFile("kava/earn/v1beta1/strategy.proto", fileDescriptor_257c4968dd48fa09) }
var fileDescriptor_257c4968dd48fa09 = []byte{
// 278 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0xc8, 0x4e, 0x2c, 0x4b,
0xd4, 0x4f, 0x4d, 0x2c, 0xca, 0xd3, 0x2f, 0x33, 0x4c, 0x4a, 0x2d, 0x49, 0x34, 0xd4, 0x2f, 0x2e,
0x29, 0x4a, 0x2c, 0x49, 0x4d, 0xaf, 0xd4, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x04, 0xa9,
0xd0, 0x03, 0xa9, 0xd0, 0x83, 0xaa, 0x90, 0x12, 0x49, 0xcf, 0x4f, 0xcf, 0x07, 0xcb, 0xea, 0x83,
0x58, 0x10, 0x85, 0x52, 0x72, 0xc9, 0xf9, 0xc5, 0xb9, 0xf9, 0xc5, 0xfa, 0x49, 0x89, 0xc5, 0xa9,
0x70, 0xc3, 0x92, 0xf3, 0x33, 0xf3, 0xa0, 0xf2, 0x92, 0x10, 0xf9, 0x78, 0x88, 0x46, 0x08, 0x07,
0x22, 0xa5, 0x35, 0x83, 0x91, 0x8b, 0x27, 0x18, 0x6a, 0x6d, 0x48, 0x65, 0x41, 0xaa, 0x90, 0x24,
0x97, 0x68, 0x70, 0x48, 0x90, 0x63, 0x88, 0xab, 0x7b, 0x64, 0x7c, 0x48, 0x64, 0x80, 0x6b, 0x7c,
0xa8, 0x9f, 0xb7, 0x9f, 0x7f, 0xb8, 0x9f, 0x00, 0x83, 0x90, 0x1c, 0x97, 0x14, 0xaa, 0x94, 0xb7,
0x63, 0x98, 0x63, 0x7c, 0x70, 0x88, 0xa3, 0xb7, 0x6b, 0x50, 0xb0, 0x00, 0xa3, 0x90, 0x0a, 0x97,
0x02, 0xaa, 0x7c, 0x70, 0x88, 0xa3, 0x93, 0x8f, 0xab, 0xb3, 0xbf, 0xa7, 0x1f, 0x5c, 0x15, 0x93,
0x90, 0x22, 0x97, 0x2c, 0x16, 0x53, 0xdc, 0xfc, 0x43, 0xfd, 0x5c, 0x1c, 0x43, 0x3c, 0xfd, 0xfd,
0x04, 0x98, 0xa5, 0x58, 0x3a, 0x16, 0xcb, 0x31, 0x38, 0x39, 0x9c, 0x78, 0x24, 0xc7, 0x78, 0xe1,
0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x13, 0x1e, 0xcb, 0x31, 0x5c, 0x78, 0x2c, 0xc7, 0x70,
0xe3, 0xb1, 0x1c, 0x43, 0x94, 0x5a, 0x7a, 0x66, 0x49, 0x46, 0x69, 0x92, 0x5e, 0x72, 0x7e, 0xae,
0x3e, 0x28, 0x8c, 0x74, 0x73, 0x12, 0x93, 0x8a, 0xc1, 0x2c, 0xfd, 0x0a, 0x48, 0x88, 0x96, 0x54,
0x16, 0xa4, 0x16, 0x27, 0xb1, 0x81, 0xfd, 0x68, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0x85, 0x84,
0x93, 0x9f, 0x6b, 0x01, 0x00, 0x00,
}

View File

@ -6,10 +6,17 @@ package types
import ( import (
context "context" context "context"
fmt "fmt" fmt "fmt"
_ "github.com/cosmos/cosmos-proto"
types "github.com/cosmos/cosmos-sdk/types"
_ "github.com/gogo/protobuf/gogoproto"
grpc1 "github.com/gogo/protobuf/grpc" grpc1 "github.com/gogo/protobuf/grpc"
proto "github.com/gogo/protobuf/proto" proto "github.com/gogo/protobuf/proto"
grpc "google.golang.org/grpc" grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
io "io"
math "math" math "math"
math_bits "math/bits"
) )
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.
@ -23,19 +30,198 @@ var _ = math.Inf
// proto package needs to be updated. // proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
// MsgDeposit represents a message for depositing assedts into a vault
type MsgDeposit struct {
// depositor represents the address to deposit funds from
Depositor string `protobuf:"bytes,1,opt,name=depositor,proto3" json:"depositor,omitempty"`
// Amount represents the token to deposit. The vault corresponds to the denom
// of the amount coin.
Amount types.Coin `protobuf:"bytes,2,opt,name=amount,proto3" json:"amount"`
}
func (m *MsgDeposit) Reset() { *m = MsgDeposit{} }
func (m *MsgDeposit) String() string { return proto.CompactTextString(m) }
func (*MsgDeposit) ProtoMessage() {}
func (*MsgDeposit) Descriptor() ([]byte, []int) {
return fileDescriptor_2e9dcf48a3fa0009, []int{0}
}
func (m *MsgDeposit) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *MsgDeposit) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_MsgDeposit.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 *MsgDeposit) XXX_Merge(src proto.Message) {
xxx_messageInfo_MsgDeposit.Merge(m, src)
}
func (m *MsgDeposit) XXX_Size() int {
return m.Size()
}
func (m *MsgDeposit) XXX_DiscardUnknown() {
xxx_messageInfo_MsgDeposit.DiscardUnknown(m)
}
var xxx_messageInfo_MsgDeposit proto.InternalMessageInfo
// MsgDepositResponse defines the Msg/Deposit response type.
type MsgDepositResponse struct {
}
func (m *MsgDepositResponse) Reset() { *m = MsgDepositResponse{} }
func (m *MsgDepositResponse) String() string { return proto.CompactTextString(m) }
func (*MsgDepositResponse) ProtoMessage() {}
func (*MsgDepositResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_2e9dcf48a3fa0009, []int{1}
}
func (m *MsgDepositResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *MsgDepositResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_MsgDepositResponse.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 *MsgDepositResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_MsgDepositResponse.Merge(m, src)
}
func (m *MsgDepositResponse) XXX_Size() int {
return m.Size()
}
func (m *MsgDepositResponse) XXX_DiscardUnknown() {
xxx_messageInfo_MsgDepositResponse.DiscardUnknown(m)
}
var xxx_messageInfo_MsgDepositResponse proto.InternalMessageInfo
// MsgWithdraw represents a message for withdrawing liquidity from a vault
type MsgWithdraw struct {
// from represents the address we are withdrawing for
From string `protobuf:"bytes,1,opt,name=from,proto3" json:"from,omitempty"`
// Amount represents the token to withdraw. The vault corresponds to the denom
// of the amount coin.
Amount types.Coin `protobuf:"bytes,2,opt,name=amount,proto3" json:"amount"`
}
func (m *MsgWithdraw) Reset() { *m = MsgWithdraw{} }
func (m *MsgWithdraw) String() string { return proto.CompactTextString(m) }
func (*MsgWithdraw) ProtoMessage() {}
func (*MsgWithdraw) Descriptor() ([]byte, []int) {
return fileDescriptor_2e9dcf48a3fa0009, []int{2}
}
func (m *MsgWithdraw) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *MsgWithdraw) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_MsgWithdraw.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 *MsgWithdraw) XXX_Merge(src proto.Message) {
xxx_messageInfo_MsgWithdraw.Merge(m, src)
}
func (m *MsgWithdraw) XXX_Size() int {
return m.Size()
}
func (m *MsgWithdraw) XXX_DiscardUnknown() {
xxx_messageInfo_MsgWithdraw.DiscardUnknown(m)
}
var xxx_messageInfo_MsgWithdraw proto.InternalMessageInfo
// MsgWithdrawResponse defines the Msg/Withdraw response type.
type MsgWithdrawResponse struct {
}
func (m *MsgWithdrawResponse) Reset() { *m = MsgWithdrawResponse{} }
func (m *MsgWithdrawResponse) String() string { return proto.CompactTextString(m) }
func (*MsgWithdrawResponse) ProtoMessage() {}
func (*MsgWithdrawResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_2e9dcf48a3fa0009, []int{3}
}
func (m *MsgWithdrawResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *MsgWithdrawResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_MsgWithdrawResponse.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 *MsgWithdrawResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_MsgWithdrawResponse.Merge(m, src)
}
func (m *MsgWithdrawResponse) XXX_Size() int {
return m.Size()
}
func (m *MsgWithdrawResponse) XXX_DiscardUnknown() {
xxx_messageInfo_MsgWithdrawResponse.DiscardUnknown(m)
}
var xxx_messageInfo_MsgWithdrawResponse proto.InternalMessageInfo
func init() {
proto.RegisterType((*MsgDeposit)(nil), "kava.earn.v1beta1.MsgDeposit")
proto.RegisterType((*MsgDepositResponse)(nil), "kava.earn.v1beta1.MsgDepositResponse")
proto.RegisterType((*MsgWithdraw)(nil), "kava.earn.v1beta1.MsgWithdraw")
proto.RegisterType((*MsgWithdrawResponse)(nil), "kava.earn.v1beta1.MsgWithdrawResponse")
}
func init() { proto.RegisterFile("kava/earn/v1beta1/tx.proto", fileDescriptor_2e9dcf48a3fa0009) } func init() { proto.RegisterFile("kava/earn/v1beta1/tx.proto", fileDescriptor_2e9dcf48a3fa0009) }
var fileDescriptor_2e9dcf48a3fa0009 = []byte{ var fileDescriptor_2e9dcf48a3fa0009 = []byte{
// 132 bytes of a gzipped FileDescriptorProto // 367 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xca, 0x4e, 0x2c, 0x4b, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xca, 0x4e, 0x2c, 0x4b,
0xd4, 0x4f, 0x4d, 0x2c, 0xca, 0xd3, 0x2f, 0x33, 0x4c, 0x4a, 0x2d, 0x49, 0x34, 0xd4, 0x2f, 0xa9, 0xd4, 0x4f, 0x4d, 0x2c, 0xca, 0xd3, 0x2f, 0x33, 0x4c, 0x4a, 0x2d, 0x49, 0x34, 0xd4, 0x2f, 0xa9,
0xd0, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x04, 0xc9, 0xe9, 0x81, 0xe4, 0xf4, 0xa0, 0x72, 0xd0, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x04, 0xc9, 0xe9, 0x81, 0xe4, 0xf4, 0xa0, 0x72,
0x46, 0xac, 0x5c, 0xcc, 0xbe, 0xc5, 0xe9, 0x4e, 0x0e, 0x27, 0x1e, 0xc9, 0x31, 0x5e, 0x78, 0x24, 0x52, 0x22, 0xe9, 0xf9, 0xe9, 0xf9, 0x60, 0x59, 0x7d, 0x10, 0x0b, 0xa2, 0x50, 0x4a, 0x32, 0x39,
0xc7, 0xf8, 0xe0, 0x91, 0x1c, 0xe3, 0x84, 0xc7, 0x72, 0x0c, 0x17, 0x1e, 0xcb, 0x31, 0xdc, 0x78, 0xbf, 0x38, 0x37, 0xbf, 0x38, 0x1e, 0x22, 0x01, 0xe1, 0x40, 0xa5, 0xe4, 0x20, 0x3c, 0xfd, 0xa4,
0x2c, 0xc7, 0x10, 0xa5, 0x96, 0x9e, 0x59, 0x92, 0x51, 0x9a, 0xa4, 0x97, 0x9c, 0x9f, 0xab, 0x0f, 0xc4, 0xe2, 0x54, 0xb8, 0x0d, 0xc9, 0xf9, 0x99, 0x79, 0x10, 0x79, 0xa5, 0x66, 0x46, 0x2e, 0x2e,
0xd2, 0xae, 0x9b, 0x93, 0x98, 0x54, 0x0c, 0x66, 0xe9, 0x57, 0x40, 0xac, 0x29, 0xa9, 0x2c, 0x48, 0xdf, 0xe2, 0x74, 0x97, 0xd4, 0x82, 0xfc, 0xe2, 0xcc, 0x12, 0x21, 0x33, 0x2e, 0xce, 0x14, 0x08,
0x2d, 0x4e, 0x62, 0x03, 0x5b, 0x61, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0xc6, 0x97, 0xb1, 0x60, 0x33, 0xbf, 0x48, 0x82, 0x51, 0x81, 0x51, 0x83, 0xd3, 0x49, 0xe2, 0xd2, 0x16, 0x5d, 0x11, 0xa8,
0x80, 0x00, 0x00, 0x00, 0x99, 0x8e, 0x29, 0x29, 0x45, 0xa9, 0xc5, 0xc5, 0xc1, 0x25, 0x45, 0x99, 0x79, 0xe9, 0x41, 0x08,
0xa5, 0x42, 0xe6, 0x5c, 0x6c, 0x89, 0xb9, 0xf9, 0xa5, 0x79, 0x25, 0x12, 0x4c, 0x0a, 0x8c, 0x1a,
0xdc, 0x46, 0x92, 0x7a, 0x50, 0x1d, 0x20, 0x7b, 0x61, 0xae, 0xd7, 0x73, 0xce, 0xcf, 0xcc, 0x73,
0x62, 0x39, 0x71, 0x4f, 0x9e, 0x21, 0x08, 0xaa, 0xdc, 0x8a, 0xa5, 0x63, 0x81, 0x3c, 0x83, 0x92,
0x08, 0x97, 0x10, 0xc2, 0x11, 0x41, 0xa9, 0xc5, 0x05, 0xf9, 0x79, 0xc5, 0xa9, 0x4a, 0x55, 0x5c,
0xdc, 0xbe, 0xc5, 0xe9, 0xe1, 0x99, 0x25, 0x19, 0x29, 0x45, 0x89, 0xe5, 0x42, 0x3a, 0x5c, 0x2c,
0x69, 0x45, 0xf9, 0xb9, 0x04, 0x9d, 0x05, 0x56, 0x45, 0xa9, 0x8b, 0x44, 0xb9, 0x84, 0x91, 0xec,
0x86, 0x39, 0xc9, 0x68, 0x15, 0x23, 0x17, 0xb3, 0x6f, 0x71, 0xba, 0x90, 0x3f, 0x17, 0x3b, 0x2c,
0xc8, 0x64, 0xf5, 0x30, 0xa2, 0x49, 0x0f, 0xe1, 0x19, 0x29, 0x55, 0xbc, 0xd2, 0x30, 0x83, 0x85,
0x82, 0xb8, 0x38, 0xe0, 0x1e, 0x95, 0xc3, 0xae, 0x05, 0x26, 0x2f, 0xa5, 0x86, 0x5f, 0x1e, 0x66,
0xa6, 0x93, 0xc3, 0x89, 0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x38,
0xe1, 0xb1, 0x1c, 0xc3, 0x85, 0xc7, 0x72, 0x0c, 0x37, 0x1e, 0xcb, 0x31, 0x44, 0xa9, 0xa5, 0x67,
0x96, 0x64, 0x94, 0x26, 0xe9, 0x25, 0xe7, 0xe7, 0xea, 0x83, 0xcc, 0xd2, 0xcd, 0x49, 0x4c, 0x2a,
0x06, 0xb3, 0xf4, 0x2b, 0x20, 0x89, 0xb1, 0xa4, 0xb2, 0x20, 0xb5, 0x38, 0x89, 0x0d, 0x9c, 0x48,
0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0x0d, 0x62, 0xb1, 0xf7, 0xa6, 0x02, 0x00, 0x00,
} }
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.
@ -50,6 +236,10 @@ const _ = grpc.SupportPackageIsVersion4
// //
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. // 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 { type MsgClient interface {
// Deposit defines a method for depositing assets into a vault
Deposit(ctx context.Context, in *MsgDeposit, opts ...grpc.CallOption) (*MsgDepositResponse, error)
// Withdraw defines a method for withdrawing assets into a vault
Withdraw(ctx context.Context, in *MsgWithdraw, opts ...grpc.CallOption) (*MsgWithdrawResponse, error)
} }
type msgClient struct { type msgClient struct {
@ -60,22 +250,702 @@ func NewMsgClient(cc grpc1.ClientConn) MsgClient {
return &msgClient{cc} return &msgClient{cc}
} }
func (c *msgClient) Deposit(ctx context.Context, in *MsgDeposit, opts ...grpc.CallOption) (*MsgDepositResponse, error) {
out := new(MsgDepositResponse)
err := c.cc.Invoke(ctx, "/kava.earn.v1beta1.Msg/Deposit", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *msgClient) Withdraw(ctx context.Context, in *MsgWithdraw, opts ...grpc.CallOption) (*MsgWithdrawResponse, error) {
out := new(MsgWithdrawResponse)
err := c.cc.Invoke(ctx, "/kava.earn.v1beta1.Msg/Withdraw", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// MsgServer is the server API for Msg service. // MsgServer is the server API for Msg service.
type MsgServer interface { type MsgServer interface {
// Deposit defines a method for depositing assets into a vault
Deposit(context.Context, *MsgDeposit) (*MsgDepositResponse, error)
// Withdraw defines a method for withdrawing assets into a vault
Withdraw(context.Context, *MsgWithdraw) (*MsgWithdrawResponse, error)
} }
// UnimplementedMsgServer can be embedded to have forward compatible implementations. // UnimplementedMsgServer can be embedded to have forward compatible implementations.
type UnimplementedMsgServer struct { type UnimplementedMsgServer struct {
} }
func (*UnimplementedMsgServer) Deposit(ctx context.Context, req *MsgDeposit) (*MsgDepositResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Deposit not implemented")
}
func (*UnimplementedMsgServer) Withdraw(ctx context.Context, req *MsgWithdraw) (*MsgWithdrawResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Withdraw not implemented")
}
func RegisterMsgServer(s grpc1.Server, srv MsgServer) { func RegisterMsgServer(s grpc1.Server, srv MsgServer) {
s.RegisterService(&_Msg_serviceDesc, srv) s.RegisterService(&_Msg_serviceDesc, srv)
} }
func _Msg_Deposit_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(MsgDeposit)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(MsgServer).Deposit(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/kava.earn.v1beta1.Msg/Deposit",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(MsgServer).Deposit(ctx, req.(*MsgDeposit))
}
return interceptor(ctx, in, info, handler)
}
func _Msg_Withdraw_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(MsgWithdraw)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(MsgServer).Withdraw(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/kava.earn.v1beta1.Msg/Withdraw",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(MsgServer).Withdraw(ctx, req.(*MsgWithdraw))
}
return interceptor(ctx, in, info, handler)
}
var _Msg_serviceDesc = grpc.ServiceDesc{ var _Msg_serviceDesc = grpc.ServiceDesc{
ServiceName: "kava.earn.v1beta1.Msg", ServiceName: "kava.earn.v1beta1.Msg",
HandlerType: (*MsgServer)(nil), HandlerType: (*MsgServer)(nil),
Methods: []grpc.MethodDesc{}, Methods: []grpc.MethodDesc{
{
MethodName: "Deposit",
Handler: _Msg_Deposit_Handler,
},
{
MethodName: "Withdraw",
Handler: _Msg_Withdraw_Handler,
},
},
Streams: []grpc.StreamDesc{}, Streams: []grpc.StreamDesc{},
Metadata: "kava/earn/v1beta1/tx.proto", Metadata: "kava/earn/v1beta1/tx.proto",
} }
func (m *MsgDeposit) 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 *MsgDeposit) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *MsgDeposit) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
{
size, err := m.Amount.MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintTx(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x12
if len(m.Depositor) > 0 {
i -= len(m.Depositor)
copy(dAtA[i:], m.Depositor)
i = encodeVarintTx(dAtA, i, uint64(len(m.Depositor)))
i--
dAtA[i] = 0xa
}
return len(dAtA) - i, nil
}
func (m *MsgDepositResponse) 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 *MsgDepositResponse) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *MsgDepositResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
return len(dAtA) - i, nil
}
func (m *MsgWithdraw) 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 *MsgWithdraw) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *MsgWithdraw) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
{
size, err := m.Amount.MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintTx(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x12
if len(m.From) > 0 {
i -= len(m.From)
copy(dAtA[i:], m.From)
i = encodeVarintTx(dAtA, i, uint64(len(m.From)))
i--
dAtA[i] = 0xa
}
return len(dAtA) - i, nil
}
func (m *MsgWithdrawResponse) 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 *MsgWithdrawResponse) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *MsgWithdrawResponse) 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 *MsgDeposit) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = len(m.Depositor)
if l > 0 {
n += 1 + l + sovTx(uint64(l))
}
l = m.Amount.Size()
n += 1 + l + sovTx(uint64(l))
return n
}
func (m *MsgDepositResponse) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
return n
}
func (m *MsgWithdraw) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = len(m.From)
if l > 0 {
n += 1 + l + sovTx(uint64(l))
}
l = m.Amount.Size()
n += 1 + l + sovTx(uint64(l))
return n
}
func (m *MsgWithdrawResponse) 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 *MsgDeposit) 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: MsgDeposit: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: MsgDeposit: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Depositor", 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.Depositor = 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
}
if err := m.Amount.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 *MsgDepositResponse) 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: MsgDepositResponse: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: MsgDepositResponse: 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 *MsgWithdraw) 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: MsgWithdraw: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: MsgWithdraw: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field From", 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.From = 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
}
if err := m.Amount.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 *MsgWithdrawResponse) 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: MsgWithdrawResponse: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: MsgWithdrawResponse: 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")
)

66
x/earn/types/vault.go Normal file
View File

@ -0,0 +1,66 @@
package types
import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// NewVaultRecord returns a new VaultRecord with 0 supply.
func NewVaultRecord(vaultDenom string) VaultRecord {
return VaultRecord{
Denom: vaultDenom,
TotalSupply: sdk.NewCoin(vaultDenom, sdk.ZeroInt()),
}
}
type VaultRecords []VaultRecord
type VaultShareRecords []VaultShareRecord
// NewVaultShareRecord returns a new VaultShareRecord with 0 supply.
func NewVaultShareRecord(depositor sdk.AccAddress, vaultDenom string) VaultShareRecord {
return VaultShareRecord{
Depositor: depositor,
AmountSupplied: sdk.NewCoin(vaultDenom, sdk.ZeroInt()),
}
}
// NewAllowedVaults returns a new AllowedVaults with the given denom and strategy type.
func NewAllowedVault(denom string, strategyType StrategyType) AllowedVault {
return AllowedVault{
Denom: denom,
VaultStrategy: strategyType,
}
}
type AllowedVaults []AllowedVault
func (a AllowedVaults) Validate() error {
denoms := make(map[string]bool)
for _, v := range a {
if err := v.Validate(); err != nil {
return err
}
if denoms[v.Denom] {
return fmt.Errorf("duplicate vault denom %s", v.Denom)
}
denoms[v.Denom] = true
}
return nil
}
func (a *AllowedVault) Validate() error {
if a.Denom == "" {
return ErrInvalidVaultDenom
}
if a.VaultStrategy == STRATEGY_TYPE_UNKNOWN {
return ErrInvalidVaultStrategy
}
return nil
}

830
x/earn/types/vault.pb.go Normal file
View File

@ -0,0 +1,830 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: kava/earn/v1beta1/vault.proto
package types
import (
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/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
io "io"
math "math"
math_bits "math/bits"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
// AllowedVault is a vault that is allowed to be created. These can be
// modified via parameter governance.
type AllowedVault struct {
// Denom is the only supported denomination of the vault for deposits and withdrawals.
Denom string `protobuf:"bytes,1,opt,name=denom,proto3" json:"denom,omitempty"`
// VaultStrategy is the strategies to use for this vault.
VaultStrategy StrategyType `protobuf:"varint,2,opt,name=vault_strategy,json=vaultStrategy,proto3,enum=kava.earn.v1beta1.StrategyType" json:"vault_strategy,omitempty"`
}
func (m *AllowedVault) Reset() { *m = AllowedVault{} }
func (m *AllowedVault) String() string { return proto.CompactTextString(m) }
func (*AllowedVault) ProtoMessage() {}
func (*AllowedVault) Descriptor() ([]byte, []int) {
return fileDescriptor_884eb89509fbdc04, []int{0}
}
func (m *AllowedVault) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *AllowedVault) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_AllowedVault.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 *AllowedVault) XXX_Merge(src proto.Message) {
xxx_messageInfo_AllowedVault.Merge(m, src)
}
func (m *AllowedVault) XXX_Size() int {
return m.Size()
}
func (m *AllowedVault) XXX_DiscardUnknown() {
xxx_messageInfo_AllowedVault.DiscardUnknown(m)
}
var xxx_messageInfo_AllowedVault proto.InternalMessageInfo
func (m *AllowedVault) GetDenom() string {
if m != nil {
return m.Denom
}
return ""
}
func (m *AllowedVault) GetVaultStrategy() StrategyType {
if m != nil {
return m.VaultStrategy
}
return STRATEGY_TYPE_UNKNOWN
}
// VaultRecord is the state of a vault and is used to store the state of a
// vault.
type VaultRecord struct {
// Denom is the only supported denomination of the vault for deposits and
// withdrawals.
Denom string `protobuf:"bytes,1,opt,name=denom,proto3" json:"denom,omitempty"`
// TotalSupply is the total supply of the vault, denominated **only** in the
// user deposit/withdrawal denom, must be the same as the Denom field.
TotalSupply types.Coin `protobuf:"bytes,2,opt,name=total_supply,json=totalSupply,proto3" json:"total_supply"`
}
func (m *VaultRecord) Reset() { *m = VaultRecord{} }
func (m *VaultRecord) String() string { return proto.CompactTextString(m) }
func (*VaultRecord) ProtoMessage() {}
func (*VaultRecord) Descriptor() ([]byte, []int) {
return fileDescriptor_884eb89509fbdc04, []int{1}
}
func (m *VaultRecord) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *VaultRecord) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_VaultRecord.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 *VaultRecord) XXX_Merge(src proto.Message) {
xxx_messageInfo_VaultRecord.Merge(m, src)
}
func (m *VaultRecord) XXX_Size() int {
return m.Size()
}
func (m *VaultRecord) XXX_DiscardUnknown() {
xxx_messageInfo_VaultRecord.DiscardUnknown(m)
}
var xxx_messageInfo_VaultRecord proto.InternalMessageInfo
func (m *VaultRecord) GetDenom() string {
if m != nil {
return m.Denom
}
return ""
}
func (m *VaultRecord) GetTotalSupply() types.Coin {
if m != nil {
return m.TotalSupply
}
return types.Coin{}
}
// VaultShareRecord defines the shares owned by a depositor and vault.
type VaultShareRecord struct {
// depositor represents the owner of the shares
Depositor github_com_cosmos_cosmos_sdk_types.AccAddress `protobuf:"bytes,1,opt,name=depositor,proto3,casttype=github.com/cosmos/cosmos-sdk/types.AccAddress" json:"depositor,omitempty"`
// amount_supplied represents the total amount a depositor has supplied to the
// vault. The vault is determined by the coin denom.
AmountSupplied types.Coin `protobuf:"bytes,2,opt,name=amount_supplied,json=amountSupplied,proto3" json:"amount_supplied"`
}
func (m *VaultShareRecord) Reset() { *m = VaultShareRecord{} }
func (m *VaultShareRecord) String() string { return proto.CompactTextString(m) }
func (*VaultShareRecord) ProtoMessage() {}
func (*VaultShareRecord) Descriptor() ([]byte, []int) {
return fileDescriptor_884eb89509fbdc04, []int{2}
}
func (m *VaultShareRecord) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *VaultShareRecord) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_VaultShareRecord.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 *VaultShareRecord) XXX_Merge(src proto.Message) {
xxx_messageInfo_VaultShareRecord.Merge(m, src)
}
func (m *VaultShareRecord) XXX_Size() int {
return m.Size()
}
func (m *VaultShareRecord) XXX_DiscardUnknown() {
xxx_messageInfo_VaultShareRecord.DiscardUnknown(m)
}
var xxx_messageInfo_VaultShareRecord proto.InternalMessageInfo
func (m *VaultShareRecord) GetDepositor() github_com_cosmos_cosmos_sdk_types.AccAddress {
if m != nil {
return m.Depositor
}
return nil
}
func (m *VaultShareRecord) GetAmountSupplied() types.Coin {
if m != nil {
return m.AmountSupplied
}
return types.Coin{}
}
func init() {
proto.RegisterType((*AllowedVault)(nil), "kava.earn.v1beta1.AllowedVault")
proto.RegisterType((*VaultRecord)(nil), "kava.earn.v1beta1.VaultRecord")
proto.RegisterType((*VaultShareRecord)(nil), "kava.earn.v1beta1.VaultShareRecord")
}
func init() { proto.RegisterFile("kava/earn/v1beta1/vault.proto", fileDescriptor_884eb89509fbdc04) }
var fileDescriptor_884eb89509fbdc04 = []byte{
// 398 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x51, 0xcd, 0xae, 0xd2, 0x40,
0x14, 0x6e, 0x8d, 0x9a, 0x30, 0x20, 0x6a, 0x65, 0x01, 0x24, 0x16, 0xc2, 0xc2, 0xb0, 0xe9, 0x34,
0xe0, 0x0b, 0x48, 0x4d, 0x0c, 0xeb, 0xd6, 0xb8, 0x70, 0x43, 0xa6, 0x9d, 0xb1, 0x34, 0xb4, 0x3d,
0x4d, 0x67, 0x8a, 0xf6, 0x2d, 0x7c, 0x18, 0x1f, 0xc1, 0x05, 0x4b, 0xe2, 0xca, 0x15, 0xb9, 0x81,
0xb7, 0xb8, 0xab, 0x9b, 0xce, 0x0c, 0xdc, 0x9b, 0x90, 0x9b, 0xdc, 0xd5, 0xfc, 0x7c, 0xe7, 0x3b,
0xdf, 0xf7, 0x9d, 0x83, 0xde, 0x6f, 0xc8, 0x96, 0xb8, 0x8c, 0x94, 0xb9, 0xbb, 0x9d, 0x85, 0x4c,
0x90, 0x99, 0xbb, 0x25, 0x55, 0x2a, 0x70, 0x51, 0x82, 0x00, 0xeb, 0x6d, 0x03, 0xe3, 0x06, 0xc6,
0x1a, 0x1e, 0xf6, 0x62, 0x88, 0x41, 0xa2, 0x6e, 0x73, 0x53, 0x85, 0x43, 0x3b, 0x02, 0x9e, 0x01,
0x77, 0x43, 0xc2, 0xd9, 0xa5, 0x53, 0x04, 0x49, 0xae, 0xf1, 0x81, 0xc2, 0x57, 0x8a, 0xa8, 0x1e,
0x1a, 0x1a, 0x5f, 0x5b, 0xe0, 0xa2, 0x24, 0x82, 0xc5, 0xb5, 0xaa, 0x98, 0xa4, 0xa8, 0xb3, 0x48,
0x53, 0xf8, 0xc9, 0xe8, 0xb7, 0xc6, 0x9b, 0xd5, 0x43, 0x2f, 0x28, 0xcb, 0x21, 0xeb, 0x9b, 0x63,
0x73, 0xda, 0xf2, 0xd5, 0xc3, 0xfa, 0x82, 0xba, 0xd2, 0xfa, 0xea, 0xcc, 0xee, 0x3f, 0x1b, 0x9b,
0xd3, 0xee, 0x7c, 0x84, 0xaf, 0x42, 0xe0, 0x40, 0x97, 0x7c, 0xad, 0x0b, 0xe6, 0xbf, 0x92, 0xb4,
0xf3, 0xd7, 0x24, 0x46, 0x6d, 0x29, 0xe3, 0xb3, 0x08, 0x4a, 0xfa, 0x88, 0x98, 0x87, 0x3a, 0x02,
0x04, 0x49, 0x57, 0xbc, 0x2a, 0x8a, 0x54, 0x49, 0xb5, 0xe7, 0x03, 0xac, 0x93, 0x35, 0x63, 0xb8,
0x88, 0x7d, 0x86, 0x24, 0xf7, 0x9e, 0xef, 0x0e, 0x23, 0xc3, 0x6f, 0x4b, 0x52, 0x20, 0x39, 0x93,
0xbf, 0x26, 0x7a, 0x23, 0x95, 0x82, 0x35, 0x29, 0x99, 0x96, 0xfb, 0x81, 0x5a, 0x94, 0x15, 0xc0,
0x13, 0x01, 0xa5, 0x94, 0xec, 0x78, 0xcb, 0xdb, 0xc3, 0xc8, 0x89, 0x13, 0xb1, 0xae, 0x42, 0x1c,
0x41, 0xa6, 0xa7, 0xa7, 0x0f, 0x87, 0xd3, 0x8d, 0x2b, 0xea, 0x82, 0x71, 0xbc, 0x88, 0xa2, 0x05,
0xa5, 0x25, 0xe3, 0xfc, 0xdf, 0x1f, 0xe7, 0x9d, 0x76, 0xa2, 0x7f, 0xbc, 0x5a, 0x30, 0xee, 0xdf,
0xb7, 0xb6, 0x96, 0xe8, 0x35, 0xc9, 0xa0, 0xca, 0x85, 0x4a, 0x90, 0x30, 0xfa, 0xd4, 0x0c, 0x5d,
0xc5, 0x0b, 0x34, 0xcd, 0xfb, 0xb4, 0x3b, 0xda, 0xe6, 0xfe, 0x68, 0x9b, 0x37, 0x47, 0xdb, 0xfc,
0x7d, 0xb2, 0x8d, 0xfd, 0xc9, 0x36, 0xfe, 0x9f, 0x6c, 0xe3, 0xfb, 0x87, 0x07, 0xa6, 0x9b, 0x1d,
0x38, 0x29, 0x09, 0xb9, 0xbc, 0xb9, 0xbf, 0xd4, 0xc2, 0xa5, 0xf1, 0xf0, 0xa5, 0x5c, 0xf3, 0xc7,
0xbb, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc6, 0x8b, 0xa9, 0xd7, 0x8d, 0x02, 0x00, 0x00,
}
func (m *AllowedVault) 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 *AllowedVault) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *AllowedVault) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if m.VaultStrategy != 0 {
i = encodeVarintVault(dAtA, i, uint64(m.VaultStrategy))
i--
dAtA[i] = 0x10
}
if len(m.Denom) > 0 {
i -= len(m.Denom)
copy(dAtA[i:], m.Denom)
i = encodeVarintVault(dAtA, i, uint64(len(m.Denom)))
i--
dAtA[i] = 0xa
}
return len(dAtA) - i, nil
}
func (m *VaultRecord) 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 *VaultRecord) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *VaultRecord) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
{
size, err := m.TotalSupply.MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintVault(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x12
if len(m.Denom) > 0 {
i -= len(m.Denom)
copy(dAtA[i:], m.Denom)
i = encodeVarintVault(dAtA, i, uint64(len(m.Denom)))
i--
dAtA[i] = 0xa
}
return len(dAtA) - i, nil
}
func (m *VaultShareRecord) 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 *VaultShareRecord) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *VaultShareRecord) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
{
size, err := m.AmountSupplied.MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintVault(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x12
if len(m.Depositor) > 0 {
i -= len(m.Depositor)
copy(dAtA[i:], m.Depositor)
i = encodeVarintVault(dAtA, i, uint64(len(m.Depositor)))
i--
dAtA[i] = 0xa
}
return len(dAtA) - i, nil
}
func encodeVarintVault(dAtA []byte, offset int, v uint64) int {
offset -= sovVault(v)
base := offset
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
dAtA[offset] = uint8(v)
return base
}
func (m *AllowedVault) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = len(m.Denom)
if l > 0 {
n += 1 + l + sovVault(uint64(l))
}
if m.VaultStrategy != 0 {
n += 1 + sovVault(uint64(m.VaultStrategy))
}
return n
}
func (m *VaultRecord) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = len(m.Denom)
if l > 0 {
n += 1 + l + sovVault(uint64(l))
}
l = m.TotalSupply.Size()
n += 1 + l + sovVault(uint64(l))
return n
}
func (m *VaultShareRecord) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = len(m.Depositor)
if l > 0 {
n += 1 + l + sovVault(uint64(l))
}
l = m.AmountSupplied.Size()
n += 1 + l + sovVault(uint64(l))
return n
}
func sovVault(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7
}
func sozVault(x uint64) (n int) {
return sovVault(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (m *AllowedVault) 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 ErrIntOverflowVault
}
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: AllowedVault: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: AllowedVault: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Denom", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowVault
}
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 ErrInvalidLengthVault
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthVault
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Denom = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 2:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field VaultStrategy", wireType)
}
m.VaultStrategy = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowVault
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.VaultStrategy |= StrategyType(b&0x7F) << shift
if b < 0x80 {
break
}
}
default:
iNdEx = preIndex
skippy, err := skipVault(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthVault
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *VaultRecord) 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 ErrIntOverflowVault
}
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: VaultRecord: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: VaultRecord: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Denom", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowVault
}
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 ErrInvalidLengthVault
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthVault
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Denom = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field TotalSupply", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowVault
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthVault
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthVault
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if err := m.TotalSupply.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipVault(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthVault
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *VaultShareRecord) 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 ErrIntOverflowVault
}
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: VaultShareRecord: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: VaultShareRecord: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Depositor", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowVault
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthVault
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthVault
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Depositor = append(m.Depositor[:0], dAtA[iNdEx:postIndex]...)
if m.Depositor == nil {
m.Depositor = []byte{}
}
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field AmountSupplied", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowVault
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthVault
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthVault
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if err := m.AmountSupplied.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipVault(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthVault
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipVault(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, ErrIntOverflowVault
}
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, ErrIntOverflowVault
}
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, ErrIntOverflowVault
}
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, ErrInvalidLengthVault
}
iNdEx += length
case 3:
depth++
case 4:
if depth == 0 {
return 0, ErrUnexpectedEndOfGroupVault
}
depth--
case 5:
iNdEx += 4
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
if iNdEx < 0 {
return 0, ErrInvalidLengthVault
}
if depth == 0 {
return iNdEx, nil
}
}
return 0, io.ErrUnexpectedEOF
}
var (
ErrInvalidLengthVault = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowVault = fmt.Errorf("proto: integer overflow")
ErrUnexpectedEndOfGroupVault = fmt.Errorf("proto: unexpected end of group")
)