Update Earn requests and responses to use multiple strategies (#1284)

* Add multiple strategies to params, queries, txs

* Check deposit/withdraw strategy if supported by vault

* Add note for deposit strategy

* Add strategy type to messages

* Update swagger docs, ignore ethermint proto linting errors

* Update strategy test, move single strategy support to strategytype

* Simplify NewStrategyTypeFromString
This commit is contained in:
Derrick Lee 2022-09-12 09:43:59 -07:00 committed by GitHub
parent b5e162a930
commit b38cd850df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 999 additions and 459 deletions

View File

@ -6978,22 +6978,48 @@ paths:
depositor: depositor:
type: string type: string
description: depositor represents the owner of the deposit. description: depositor represents the owner of the deposit.
denom: shares:
type: string type: array
description: denom represents the vault denom the deposit is for. items:
account_supplied: type: object
type: string properties:
denom:
type: string
amount:
type: string
description: >-
VaultShare defines shares of a vault owned by a
depositor.
description: >- description: >-
AccountSupplied represents the amount of denom supplied Shares represent the issued shares from their
to the vault. corresponding vaults.
account_value: value:
type: string type: array
items:
type: object
properties:
denom:
type: string
amount:
type: string
description: >-
Coin defines a token with a denomination and an
amount.
NOTE: The amount field is an Int which implements the
custom method
signatures required by gogoproto.
description: >- description: >-
AccountValue represents the coin value of the Value represents the total accumulated value of denom
depositor's share of the vault. coins supplied to
description: >-
DepositResponse defines a single deposit query response vaults. This may be greater than or equal to
type. amount_supplied depending on
the strategy.
description: DepositResponse defines a deposit query response type.
title: >- title: >-
deposits returns the deposits matching the requested deposits returns the deposits matching the requested
parameters parameters
@ -7135,14 +7161,25 @@ paths:
description: >- description: >-
Denom is the only supported denomination of the Denom is the only supported denomination of the
vault for deposits and withdrawals. vault for deposits and withdrawals.
vault_strategy: strategies:
type: array
items:
type: string
enum:
- STRATEGY_TYPE_UNSPECIFIED
- STRATEGY_TYPE_HARD
- STRATEGY_TYPE_SAVINGS
default: STRATEGY_TYPE_UNSPECIFIED
description: >-
StrategyType is the type of strategy that a vault
uses to optimize yields.
- STRATEGY_TYPE_UNSPECIFIED: STRATEGY_TYPE_UNSPECIFIED represents an unspecified or invalid strategy type.
- STRATEGY_TYPE_HARD: STRATEGY_TYPE_HARD represents the strategy that deposits assets in the Hard
module.
- STRATEGY_TYPE_SAVINGS: STRATEGY_TYPE_SAVINGS represents the strategy that deposits assets in the
Savings module.
description: VaultStrategy is the strategy used for this vault. description: VaultStrategy is the strategy used for this vault.
type: string
enum:
- STRATEGY_TYPE_UNSPECIFIED
- STRATEGY_TYPE_HARD
- STRATEGY_TYPE_SAVINGS
default: STRATEGY_TYPE_UNSPECIFIED
description: >- description: >-
AllowedVault is a vault that is allowed to be created. AllowedVault is a vault that is allowed to be created.
These can be These can be
@ -7176,69 +7213,7 @@ paths:
format: byte format: byte
tags: tags:
- Earn - Earn
/kava/earn/v1beta1/total-deposited/{denom}: /kava/earn/v1beta1/vaults/{denom}:
get:
summary: TotalDeposited queries total deposited amount for each vault.
operationId: EarnTotalDeposited
responses:
'200':
description: A successful response.
schema:
type: object
properties:
supplied_coins:
type: array
items:
type: object
properties:
denom:
type: string
amount:
type: string
description: >-
Coin defines a token with a denomination and an amount.
NOTE: The amount field is an Int which implements the custom
method
signatures required by gogoproto.
description: >-
QueryTotalDepositedResponse is the response type for the
Query/TotalDeposited RPC method.
default:
description: An unexpected error response
schema:
type: object
properties:
error:
type: string
code:
type: integer
format: int32
message:
type: string
details:
type: array
items:
type: object
properties:
type_url:
type: string
value:
type: string
format: byte
parameters:
- name: denom
description: >-
denom represents the vault denom to query total deposited amount
for.
in: path
required: true
type: string
tags:
- Earn
/kava/earn/v1beta1/vaults:
get: get:
summary: Vaults queries vaults based on vault denom summary: Vaults queries vaults based on vault denom
operationId: EarnVaults operationId: EarnVaults
@ -7256,19 +7231,30 @@ paths:
denom: denom:
type: string type: string
title: denom represents the denom of the vault title: denom represents the denom of the vault
vault_strategy: strategies:
type: array
items:
type: string
enum:
- STRATEGY_TYPE_UNSPECIFIED
- STRATEGY_TYPE_HARD
- STRATEGY_TYPE_SAVINGS
default: STRATEGY_TYPE_UNSPECIFIED
description: >-
StrategyType is the type of strategy that a vault uses
to optimize yields.
- STRATEGY_TYPE_UNSPECIFIED: STRATEGY_TYPE_UNSPECIFIED represents an unspecified or invalid strategy type.
- STRATEGY_TYPE_HARD: STRATEGY_TYPE_HARD represents the strategy that deposits assets in the Hard
module.
- STRATEGY_TYPE_SAVINGS: STRATEGY_TYPE_SAVINGS represents the strategy that deposits assets in the
Savings module.
description: VaultStrategy is the strategy used for this vault. description: VaultStrategy is the strategy used for this vault.
type: string total_shares:
enum:
- STRATEGY_TYPE_UNSPECIFIED
- STRATEGY_TYPE_HARD
- STRATEGY_TYPE_SAVINGS
default: STRATEGY_TYPE_UNSPECIFIED
total_supplied:
type: string type: string
description: >- description: >-
TotalSupplied is the total amount of denom coins TotalShares is the total amount of shares issued to
supplied to the vault. depositors.
total_value: total_value:
type: string type: string
description: >- description: >-
@ -7305,9 +7291,9 @@ paths:
format: byte format: byte
parameters: parameters:
- name: denom - name: denom
description: vault filters vault by denom. description: vault filters vault by denom
in: query in: path
required: false required: true
type: string type: string
tags: tags:
- Earn - Earn
@ -54207,14 +54193,25 @@ definitions:
description: >- description: >-
Denom is the only supported denomination of the vault for deposits and Denom is the only supported denomination of the vault for deposits and
withdrawals. withdrawals.
vault_strategy: strategies:
type: array
items:
type: string
enum:
- STRATEGY_TYPE_UNSPECIFIED
- STRATEGY_TYPE_HARD
- STRATEGY_TYPE_SAVINGS
default: STRATEGY_TYPE_UNSPECIFIED
description: >-
StrategyType is the type of strategy that a vault uses to optimize
yields.
- STRATEGY_TYPE_UNSPECIFIED: STRATEGY_TYPE_UNSPECIFIED represents an unspecified or invalid strategy type.
- STRATEGY_TYPE_HARD: STRATEGY_TYPE_HARD represents the strategy that deposits assets in the Hard
module.
- STRATEGY_TYPE_SAVINGS: STRATEGY_TYPE_SAVINGS represents the strategy that deposits assets in the
Savings module.
description: VaultStrategy is the strategy used for this vault. description: VaultStrategy is the strategy used for this vault.
type: string
enum:
- STRATEGY_TYPE_UNSPECIFIED
- STRATEGY_TYPE_HARD
- STRATEGY_TYPE_SAVINGS
default: STRATEGY_TYPE_UNSPECIFIED
description: |- description: |-
AllowedVault is a vault that is allowed to be created. These can be AllowedVault is a vault that is allowed to be created. These can be
modified via parameter governance. modified via parameter governance.
@ -54224,18 +54221,40 @@ definitions:
depositor: depositor:
type: string type: string
description: depositor represents the owner of the deposit. description: depositor represents the owner of the deposit.
denom: shares:
type: string type: array
description: denom represents the vault denom the deposit is for. items:
account_supplied: type: object
type: string properties:
description: AccountSupplied represents the amount of denom supplied to the vault. denom:
account_value: type: string
type: string amount:
type: string
description: VaultShare defines shares of a vault owned by a depositor.
description: Shares represent the issued shares from their corresponding vaults.
value:
type: array
items:
type: object
properties:
denom:
type: string
amount:
type: string
description: |-
Coin defines a token with a denomination and an amount.
NOTE: The amount field is an Int which implements the custom method
signatures required by gogoproto.
description: >- description: >-
AccountValue represents the coin value of the depositor's share of the Value represents the total accumulated value of denom coins supplied
vault. to
description: DepositResponse defines a single deposit query response type.
vaults. This may be greater than or equal to amount_supplied depending
on
the strategy.
description: DepositResponse defines a deposit query response type.
kava.earn.v1beta1.Params: kava.earn.v1beta1.Params:
type: object type: object
properties: properties:
@ -54249,14 +54268,25 @@ definitions:
description: >- description: >-
Denom is the only supported denomination of the vault for Denom is the only supported denomination of the vault for
deposits and withdrawals. deposits and withdrawals.
vault_strategy: strategies:
type: array
items:
type: string
enum:
- STRATEGY_TYPE_UNSPECIFIED
- STRATEGY_TYPE_HARD
- STRATEGY_TYPE_SAVINGS
default: STRATEGY_TYPE_UNSPECIFIED
description: >-
StrategyType is the type of strategy that a vault uses to
optimize yields.
- STRATEGY_TYPE_UNSPECIFIED: STRATEGY_TYPE_UNSPECIFIED represents an unspecified or invalid strategy type.
- STRATEGY_TYPE_HARD: STRATEGY_TYPE_HARD represents the strategy that deposits assets in the Hard
module.
- STRATEGY_TYPE_SAVINGS: STRATEGY_TYPE_SAVINGS represents the strategy that deposits assets in the
Savings module.
description: VaultStrategy is the strategy used for this vault. description: VaultStrategy is the strategy used for this vault.
type: string
enum:
- STRATEGY_TYPE_UNSPECIFIED
- STRATEGY_TYPE_HARD
- STRATEGY_TYPE_SAVINGS
default: STRATEGY_TYPE_UNSPECIFIED
description: |- description: |-
AllowedVault is a vault that is allowed to be created. These can be AllowedVault is a vault that is allowed to be created. These can be
modified via parameter governance. modified via parameter governance.
@ -54272,20 +54302,45 @@ definitions:
depositor: depositor:
type: string type: string
description: depositor represents the owner of the deposit. description: depositor represents the owner of the deposit.
denom: shares:
type: string type: array
description: denom represents the vault denom the deposit is for. items:
account_supplied: type: object
type: string properties:
denom:
type: string
amount:
type: string
description: VaultShare defines shares of a vault owned by a depositor.
description: >- description: >-
AccountSupplied represents the amount of denom supplied to the Shares represent the issued shares from their corresponding
vault. vaults.
account_value: value:
type: string type: array
items:
type: object
properties:
denom:
type: string
amount:
type: string
description: >-
Coin defines a token with a denomination and an amount.
NOTE: The amount field is an Int which implements the custom
method
signatures required by gogoproto.
description: >- description: >-
AccountValue represents the coin value of the depositor's share Value represents the total accumulated value of denom coins
of the vault. supplied to
description: DepositResponse defines a single deposit query response type.
vaults. This may be greater than or equal to amount_supplied
depending on
the strategy.
description: DepositResponse defines a deposit query response type.
title: deposits returns the deposits matching the requested parameters title: deposits returns the deposits matching the requested parameters
pagination: pagination:
description: pagination defines the pagination in the response. description: pagination defines the pagination in the response.
@ -54325,14 +54380,25 @@ definitions:
description: >- description: >-
Denom is the only supported denomination of the vault for Denom is the only supported denomination of the vault for
deposits and withdrawals. deposits and withdrawals.
vault_strategy: strategies:
type: array
items:
type: string
enum:
- STRATEGY_TYPE_UNSPECIFIED
- STRATEGY_TYPE_HARD
- STRATEGY_TYPE_SAVINGS
default: STRATEGY_TYPE_UNSPECIFIED
description: >-
StrategyType is the type of strategy that a vault uses to
optimize yields.
- STRATEGY_TYPE_UNSPECIFIED: STRATEGY_TYPE_UNSPECIFIED represents an unspecified or invalid strategy type.
- STRATEGY_TYPE_HARD: STRATEGY_TYPE_HARD represents the strategy that deposits assets in the Hard
module.
- STRATEGY_TYPE_SAVINGS: STRATEGY_TYPE_SAVINGS represents the strategy that deposits assets in the
Savings module.
description: VaultStrategy is the strategy used for this vault. description: VaultStrategy is the strategy used for this vault.
type: string
enum:
- STRATEGY_TYPE_UNSPECIFIED
- STRATEGY_TYPE_HARD
- STRATEGY_TYPE_SAVINGS
default: STRATEGY_TYPE_UNSPECIFIED
description: >- description: >-
AllowedVault is a vault that is allowed to be created. These can AllowedVault is a vault that is allowed to be created. These can
be be
@ -54342,26 +54408,6 @@ definitions:
description: >- description: >-
QueryParamsResponse defines the response type for querying x/earn QueryParamsResponse defines the response type for querying x/earn
parameters. parameters.
kava.earn.v1beta1.QueryTotalDepositedResponse:
type: object
properties:
supplied_coins:
type: array
items:
type: object
properties:
denom:
type: string
amount:
type: string
description: |-
Coin defines a token with a denomination and an amount.
NOTE: The amount field is an Int which implements the custom method
signatures required by gogoproto.
description: >-
QueryTotalDepositedResponse is the response type for the
Query/TotalDeposited RPC method.
kava.earn.v1beta1.QueryVaultsResponse: kava.earn.v1beta1.QueryVaultsResponse:
type: object type: object
properties: properties:
@ -54373,19 +54419,28 @@ definitions:
denom: denom:
type: string type: string
title: denom represents the denom of the vault title: denom represents the denom of the vault
vault_strategy: strategies:
type: array
items:
type: string
enum:
- STRATEGY_TYPE_UNSPECIFIED
- STRATEGY_TYPE_HARD
- STRATEGY_TYPE_SAVINGS
default: STRATEGY_TYPE_UNSPECIFIED
description: >-
StrategyType is the type of strategy that a vault uses to
optimize yields.
- STRATEGY_TYPE_UNSPECIFIED: STRATEGY_TYPE_UNSPECIFIED represents an unspecified or invalid strategy type.
- STRATEGY_TYPE_HARD: STRATEGY_TYPE_HARD represents the strategy that deposits assets in the Hard
module.
- STRATEGY_TYPE_SAVINGS: STRATEGY_TYPE_SAVINGS represents the strategy that deposits assets in the
Savings module.
description: VaultStrategy is the strategy used for this vault. description: VaultStrategy is the strategy used for this vault.
total_shares:
type: string type: string
enum: description: TotalShares is the total amount of shares issued to depositors.
- STRATEGY_TYPE_UNSPECIFIED
- STRATEGY_TYPE_HARD
- STRATEGY_TYPE_SAVINGS
default: STRATEGY_TYPE_UNSPECIFIED
total_supplied:
type: string
description: >-
TotalSupplied is the total amount of denom coins supplied to the
vault.
total_value: total_value:
type: string type: string
description: >- description: >-
@ -54417,19 +54472,28 @@ definitions:
denom: denom:
type: string type: string
title: denom represents the denom of the vault title: denom represents the denom of the vault
vault_strategy: strategies:
type: array
items:
type: string
enum:
- STRATEGY_TYPE_UNSPECIFIED
- STRATEGY_TYPE_HARD
- STRATEGY_TYPE_SAVINGS
default: STRATEGY_TYPE_UNSPECIFIED
description: >-
StrategyType is the type of strategy that a vault uses to optimize
yields.
- STRATEGY_TYPE_UNSPECIFIED: STRATEGY_TYPE_UNSPECIFIED represents an unspecified or invalid strategy type.
- STRATEGY_TYPE_HARD: STRATEGY_TYPE_HARD represents the strategy that deposits assets in the Hard
module.
- STRATEGY_TYPE_SAVINGS: STRATEGY_TYPE_SAVINGS represents the strategy that deposits assets in the
Savings module.
description: VaultStrategy is the strategy used for this vault. description: VaultStrategy is the strategy used for this vault.
total_shares:
type: string type: string
enum: description: TotalShares is the total amount of shares issued to depositors.
- STRATEGY_TYPE_UNSPECIFIED
- STRATEGY_TYPE_HARD
- STRATEGY_TYPE_SAVINGS
default: STRATEGY_TYPE_UNSPECIFIED
total_supplied:
type: string
description: >-
TotalSupplied is the total amount of denom coins supplied to the
vault.
total_value: total_value:
type: string type: string
description: >- description: >-
@ -54438,6 +54502,14 @@ definitions:
vault were to be liquidated. vault were to be liquidated.
description: VaultResponse is the response type for a vault. description: VaultResponse is the response type for a vault.
kava.earn.v1beta1.VaultShare:
type: object
properties:
denom:
type: string
amount:
type: string
description: VaultShare defines shares of a vault owned by a depositor.
kava.hard.v1beta1.BorrowInterestFactorResponse: kava.hard.v1beta1.BorrowInterestFactorResponse:
type: object type: object
properties: properties:

View File

@ -2806,7 +2806,7 @@ modified via parameter governance.
| Field | Type | Label | Description | | Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- | | ----- | ---- | ----- | ----------- |
| `denom` | [string](#string) | | Denom is the only supported denomination of the vault for deposits and withdrawals. | | `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 strategy used for this vault. | | `strategies` | [StrategyType](#kava.earn.v1beta1.StrategyType) | repeated | VaultStrategy is the strategy used for this vault. |
@ -3054,7 +3054,7 @@ VaultResponse is the response type for a vault.
| Field | Type | Label | Description | | Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- | | ----- | ---- | ----- | ----------- |
| `denom` | [string](#string) | | denom represents the denom of the vault | | `denom` | [string](#string) | | denom represents the denom of the vault |
| `vault_strategy` | [StrategyType](#kava.earn.v1beta1.StrategyType) | | VaultStrategy is the strategy used for this vault. | | `strategies` | [StrategyType](#kava.earn.v1beta1.StrategyType) | repeated | VaultStrategy is the strategy used for this vault. |
| `total_shares` | [string](#string) | | TotalShares is the total amount of shares issued to depositors. | | `total_shares` | [string](#string) | | TotalShares is the total amount of shares issued to depositors. |
| `total_value` | [string](#string) | | TotalValue is the total value of denom coins supplied to the vault if the vault were to be liquidated. | | `total_value` | [string](#string) | | TotalValue is the total value of denom coins supplied to the vault if the vault were to be liquidated. |
@ -3101,6 +3101,7 @@ MsgDeposit represents a message for depositing assedts into a vault
| ----- | ---- | ----- | ----------- | | ----- | ---- | ----- | ----------- |
| `depositor` | [string](#string) | | depositor represents the address to deposit funds from | | `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. | | `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. |
| `strategy` | [StrategyType](#kava.earn.v1beta1.StrategyType) | | Strategy is the vault strategy to use. |
@ -3132,6 +3133,7 @@ MsgWithdraw represents a message for withdrawing liquidity from a vault
| ----- | ---- | ----- | ----------- | | ----- | ---- | ----- | ----------- |
| `from` | [string](#string) | | from represents the address we are withdrawing for | | `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. | | `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. |
| `strategy` | [StrategyType](#kava.earn.v1beta1.StrategyType) | | Strategy is the vault strategy to use. |

View File

@ -58,7 +58,7 @@ message VaultResponse {
string denom = 1; string denom = 1;
// VaultStrategy is the strategy used for this vault. // VaultStrategy is the strategy used for this vault.
StrategyType vault_strategy = 2; repeated StrategyType strategies = 2 [(gogoproto.castrepeated) = "StrategyTypes"];
// TotalShares is the total amount of shares issued to depositors. // TotalShares is the total amount of shares issued to depositors.
string total_shares = 3; string total_shares = 3;

View File

@ -4,6 +4,7 @@ package kava.earn.v1beta1;
import "cosmos_proto/cosmos.proto"; import "cosmos_proto/cosmos.proto";
import "cosmos/base/v1beta1/coin.proto"; import "cosmos/base/v1beta1/coin.proto";
import "gogoproto/gogo.proto"; import "gogoproto/gogo.proto";
import "kava/earn/v1beta1/strategy.proto";
import "kava/earn/v1beta1/vault.proto"; import "kava/earn/v1beta1/vault.proto";
option go_package = "github.com/kava-labs/kava/x/earn/types"; option go_package = "github.com/kava-labs/kava/x/earn/types";
@ -25,6 +26,9 @@ message MsgDeposit {
// Amount represents the token to deposit. The vault corresponds to the denom // Amount represents the token to deposit. The vault corresponds to the denom
// of the amount coin. // of the amount coin.
cosmos.base.v1beta1.Coin amount = 2 [(gogoproto.nullable) = false]; cosmos.base.v1beta1.Coin amount = 2 [(gogoproto.nullable) = false];
// Strategy is the vault strategy to use.
StrategyType strategy = 3;
} }
// MsgDepositResponse defines the Msg/Deposit response type. // MsgDepositResponse defines the Msg/Deposit response type.
@ -42,6 +46,9 @@ message MsgWithdraw {
// Amount represents the token to withdraw. The vault corresponds to the denom // Amount represents the token to withdraw. The vault corresponds to the denom
// of the amount coin. // of the amount coin.
cosmos.base.v1beta1.Coin amount = 2 [(gogoproto.nullable) = false]; cosmos.base.v1beta1.Coin amount = 2 [(gogoproto.nullable) = false];
// Strategy is the vault strategy to use.
StrategyType strategy = 3;
} }
// MsgWithdrawResponse defines the Msg/Withdraw response type. // MsgWithdrawResponse defines the Msg/Withdraw response type.

View File

@ -4,7 +4,6 @@ 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 "cosmos_proto/cosmos.proto"; import "cosmos_proto/cosmos.proto";
import "cosmos/base/v1beta1/coin.proto";
import "gogoproto/gogo.proto"; import "gogoproto/gogo.proto";
import "kava/earn/v1beta1/strategy.proto"; import "kava/earn/v1beta1/strategy.proto";
@ -15,7 +14,7 @@ message AllowedVault {
string denom = 1; string denom = 1;
// VaultStrategy is the strategy used for this vault. // VaultStrategy is the strategy used for this vault.
StrategyType vault_strategy = 2; repeated StrategyType strategies = 2 [(gogoproto.castrepeated) = "StrategyTypes"];
} }
// VaultRecord is the state of a vault. // VaultRecord is the state of a vault.

View File

@ -4,6 +4,7 @@ lint:
ignore: ignore:
- cosmos - cosmos
- cosmos_proto - cosmos_proto
- ethermint
- gogoproto - gogoproto
- google - google
- ibc - ibc

View File

@ -40,13 +40,13 @@ func GetTxCmd() *cobra.Command {
func getCmdDeposit() *cobra.Command { func getCmdDeposit() *cobra.Command {
return &cobra.Command{ return &cobra.Command{
Use: "deposit [amount]", Use: "deposit [amount] [strategy]",
Short: "deposit coins to an earn vault", Short: "deposit coins to an earn vault",
Example: fmt.Sprintf( Example: fmt.Sprintf(
`%s tx %s deposit 10000000ukava --from <key>`, `%s tx %s deposit 10000000ukava hard --from <key>`,
version.AppName, types.ModuleName, version.AppName, types.ModuleName,
), ),
Args: cobra.ExactArgs(1), Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd) clientCtx, err := client.GetClientTxContext(cmd)
if err != nil { if err != nil {
@ -58,8 +58,13 @@ func getCmdDeposit() *cobra.Command {
return err return err
} }
strategy := types.NewStrategyTypeFromString(args[1])
if !strategy.IsValid() {
return fmt.Errorf("invalid strategy type: %s", args[1])
}
signer := clientCtx.GetFromAddress() signer := clientCtx.GetFromAddress()
msg := types.NewMsgDeposit(signer.String(), amount) msg := types.NewMsgDeposit(signer.String(), amount, strategy)
if err := msg.ValidateBasic(); err != nil { if err := msg.ValidateBasic(); err != nil {
return err return err
} }
@ -71,13 +76,13 @@ func getCmdDeposit() *cobra.Command {
func getCmdWithdraw() *cobra.Command { func getCmdWithdraw() *cobra.Command {
return &cobra.Command{ return &cobra.Command{
Use: "withdraw [amount]", Use: "withdraw [amount] [strategy]",
Short: "withdraw coins from an earn vault", Short: "withdraw coins from an earn vault",
Example: fmt.Sprintf( Example: fmt.Sprintf(
`%s tx %s withdraw 10000000ukava --from <key>`, `%s tx %s withdraw 10000000ukava hard --from <key>`,
version.AppName, types.ModuleName, version.AppName, types.ModuleName,
), ),
Args: cobra.ExactArgs(1), Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd) clientCtx, err := client.GetClientTxContext(cmd)
if err != nil { if err != nil {
@ -89,8 +94,13 @@ func getCmdWithdraw() *cobra.Command {
return err return err
} }
strategy := types.NewStrategyTypeFromString(args[1])
if !strategy.IsValid() {
return fmt.Errorf("invalid strategy type: %s", args[1])
}
fromAddr := clientCtx.GetFromAddress() fromAddr := clientCtx.GetFromAddress()
msg := types.NewMsgWithdraw(fromAddr.String(), amount) msg := types.NewMsgWithdraw(fromAddr.String(), amount, strategy)
if err := msg.ValidateBasic(); err != nil { if err := msg.ValidateBasic(); err != nil {
return err return err
} }

View File

@ -9,7 +9,12 @@ import (
// Deposit adds the provided amount from a depositor to a vault. The vault is // Deposit adds the provided amount from a depositor to a vault. The vault is
// specified by the denom in the amount. // specified by the denom in the amount.
func (k *Keeper) Deposit(ctx sdk.Context, depositor sdk.AccAddress, amount sdk.Coin) error { func (k *Keeper) Deposit(
ctx sdk.Context,
depositor sdk.AccAddress,
amount sdk.Coin,
depositStrategy types.StrategyType,
) error {
// Get AllowedVault, if not found (not a valid vault), return error // Get AllowedVault, if not found (not a valid vault), return error
allowedVault, found := k.GetAllowedVault(ctx, amount.Denom) allowedVault, found := k.GetAllowedVault(ctx, amount.Denom)
if !found { if !found {
@ -20,6 +25,11 @@ func (k *Keeper) Deposit(ctx sdk.Context, depositor sdk.AccAddress, amount sdk.C
return types.ErrInsufficientAmount return types.ErrInsufficientAmount
} }
// Check if deposit strategy is supported by vault
if !allowedVault.IsStrategyAllowed(depositStrategy) {
return types.ErrInvalidVaultStrategy
}
// Check if VaultRecord exists, create if not exist // Check if VaultRecord exists, create if not exist
vaultRecord, found := k.GetVaultRecord(ctx, amount.Denom) vaultRecord, found := k.GetVaultRecord(ctx, amount.Denom)
if !found { if !found {
@ -28,7 +38,11 @@ func (k *Keeper) Deposit(ctx sdk.Context, depositor sdk.AccAddress, amount sdk.C
} }
// Get the strategy for the vault // Get the strategy for the vault
strategy, err := k.GetStrategy(allowedVault.VaultStrategy) // NOTE: Currently always uses the first one, AllowedVaults are currently
// only valid with 1 and only 1 strategy so this is safe.
// If/When multiple strategies are supported and users can specify specific
// strategies, shares should be issued per-strategy instead of per-vault.
strategy, err := k.GetStrategy(allowedVault.Strategies[0])
if err != nil { if err != nil {
return err return err
} }

View File

@ -42,7 +42,7 @@ func (suite *depositTestSuite) TestDeposit_Balances() {
acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0) acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount) err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount, types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
suite.AccountBalanceEqual( suite.AccountBalanceEqual(
@ -65,7 +65,7 @@ func (suite *depositTestSuite) TestDeposit_Exceed() {
acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0) acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount) err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount, types.STRATEGY_TYPE_HARD)
suite.Require().Error(err) suite.Require().Error(err)
suite.Require().ErrorIs(err, sdkerrors.ErrInsufficientFunds) suite.Require().ErrorIs(err, sdkerrors.ErrInsufficientFunds)
@ -90,7 +90,7 @@ func (suite *depositTestSuite) TestDeposit_Zero() {
acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0) acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount) err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount, types.STRATEGY_TYPE_HARD)
suite.Require().Error(err) suite.Require().Error(err)
suite.Require().ErrorIs(err, types.ErrInsufficientAmount) suite.Require().ErrorIs(err, types.ErrInsufficientAmount)
@ -115,7 +115,7 @@ func (suite *depositTestSuite) TestDeposit_InvalidVault() {
acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0) acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount) err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount, types.STRATEGY_TYPE_HARD)
suite.Require().Error(err) suite.Require().Error(err)
suite.Require().ErrorIs(err, types.ErrInvalidVaultDenom) suite.Require().ErrorIs(err, types.ErrInvalidVaultDenom)
@ -130,3 +130,17 @@ func (suite *depositTestSuite) TestDeposit_InvalidVault() {
sdk.NewCoins(), sdk.NewCoins(),
) )
} }
func (suite *depositTestSuite) TestDeposit_InvalidStrategy() {
vaultDenom := "usdx"
startBalance := sdk.NewInt64Coin(vaultDenom, 1000)
depositAmount := sdk.NewInt64Coin(vaultDenom, 1001)
suite.CreateVault(vaultDenom, types.STRATEGY_TYPE_HARD)
acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount, types.STRATEGY_TYPE_SAVINGS)
suite.Require().Error(err)
suite.Require().ErrorIs(err, types.ErrInvalidVaultStrategy)
}

View File

@ -81,10 +81,10 @@ func (s queryServer) Vaults(
} }
vaults = append(vaults, types.VaultResponse{ vaults = append(vaults, types.VaultResponse{
Denom: allowedVault.Denom, Denom: allowedVault.Denom,
VaultStrategy: allowedVault.VaultStrategy, Strategies: allowedVault.Strategies,
TotalShares: vaultTotalShares.Amount.String(), TotalShares: vaultTotalShares.Amount.String(),
TotalValue: totalValue.Amount, TotalValue: totalValue.Amount,
}) })
} }

View File

@ -68,10 +68,10 @@ func (suite *grpcQueryTestSuite) TestVaults_ZeroSupply() {
suite.Require().Len(res.Vaults, 1) suite.Require().Len(res.Vaults, 1)
suite.Require().Equal( suite.Require().Equal(
types.VaultResponse{ types.VaultResponse{
Denom: "usdx", Denom: "usdx",
VaultStrategy: types.STRATEGY_TYPE_HARD, Strategies: []types.StrategyType{types.STRATEGY_TYPE_HARD},
TotalShares: sdk.NewDec(0).String(), TotalShares: sdk.NewDec(0).String(),
TotalValue: sdk.NewInt(0), TotalValue: sdk.NewInt(0),
}, },
res.Vaults[0], res.Vaults[0],
) )
@ -84,16 +84,16 @@ func (suite *grpcQueryTestSuite) TestVaults_ZeroSupply() {
suite.Require().ElementsMatch( suite.Require().ElementsMatch(
[]types.VaultResponse{ []types.VaultResponse{
{ {
Denom: "usdx", Denom: "usdx",
VaultStrategy: types.STRATEGY_TYPE_HARD, Strategies: []types.StrategyType{types.STRATEGY_TYPE_HARD},
TotalShares: sdk.NewDec(0).String(), TotalShares: sdk.NewDec(0).String(),
TotalValue: sdk.NewInt(0), TotalValue: sdk.NewInt(0),
}, },
{ {
Denom: "busd", Denom: "busd",
VaultStrategy: types.STRATEGY_TYPE_HARD, Strategies: []types.StrategyType{types.STRATEGY_TYPE_HARD},
TotalShares: sdk.NewDec(0).String(), TotalShares: sdk.NewDec(0).String(),
TotalValue: sdk.NewInt(0), TotalValue: sdk.NewInt(0),
}, },
}, },
res.Vaults, res.Vaults,
@ -111,7 +111,7 @@ func (suite *grpcQueryTestSuite) TestVaults_WithSupply() {
acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0) acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount) err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount, types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
res, err := suite.queryClient.Vaults(context.Background(), types.NewQueryVaultsRequest("usdx")) res, err := suite.queryClient.Vaults(context.Background(), types.NewQueryVaultsRequest("usdx"))
@ -119,10 +119,10 @@ func (suite *grpcQueryTestSuite) TestVaults_WithSupply() {
suite.Require().Len(res.Vaults, 1) suite.Require().Len(res.Vaults, 1)
suite.Require().Equal( suite.Require().Equal(
types.VaultResponse{ types.VaultResponse{
Denom: "usdx", Denom: "usdx",
VaultStrategy: types.STRATEGY_TYPE_HARD, Strategies: []types.StrategyType{types.STRATEGY_TYPE_HARD},
TotalShares: depositAmount.Amount.ToDec().String(), TotalShares: depositAmount.Amount.ToDec().String(),
TotalValue: depositAmount.Amount, TotalValue: depositAmount.Amount,
}, },
res.Vaults[0], res.Vaults[0],
) )
@ -160,14 +160,14 @@ func (suite *grpcQueryTestSuite) TestDeposits() {
// Deposit into each vault from each account - 4 total deposits // Deposit into each vault from each account - 4 total deposits
// Acc 1: usdx + busd // Acc 1: usdx + busd
// Acc 2: usdx + usdc // Acc 2: usdx + usdc
err := suite.Keeper.Deposit(suite.Ctx, acc1, deposit1Amount) err := suite.Keeper.Deposit(suite.Ctx, acc1, deposit1Amount, types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
err = suite.Keeper.Deposit(suite.Ctx, acc1, deposit2Amount) err = suite.Keeper.Deposit(suite.Ctx, acc1, deposit2Amount, types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
err = suite.Keeper.Deposit(suite.Ctx, acc2, deposit1Amount) err = suite.Keeper.Deposit(suite.Ctx, acc2, deposit1Amount, types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
err = suite.Keeper.Deposit(suite.Ctx, acc2, deposit3Amount) err = suite.Keeper.Deposit(suite.Ctx, acc2, deposit3Amount, types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
suite.Run("1) 1 vault for 1 account", func() { suite.Run("1) 1 vault for 1 account", func() {

View File

@ -29,7 +29,7 @@ func (m msgServer) Deposit(goCtx context.Context, msg *types.MsgDeposit) (*types
return nil, err return nil, err
} }
if err := m.keeper.Deposit(ctx, depositor, msg.Amount); err != nil { if err := m.keeper.Deposit(ctx, depositor, msg.Amount, msg.Strategy); err != nil {
return nil, err return nil, err
} }
@ -53,7 +53,7 @@ func (m msgServer) Withdraw(goCtx context.Context, msg *types.MsgWithdraw) (*typ
return nil, err return nil, err
} }
if err := m.keeper.Withdraw(ctx, from, msg.Amount); err != nil { if err := m.keeper.Withdraw(ctx, from, msg.Amount, msg.Strategy); err != nil {
return nil, err return nil, err
} }

View File

@ -41,7 +41,7 @@ func (suite *msgServerTestSuite) TestDeposit() {
acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0) acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
msg := types.NewMsgDeposit(acc.GetAddress().String(), depositAmount) msg := types.NewMsgDeposit(acc.GetAddress().String(), depositAmount, types.STRATEGY_TYPE_HARD)
_, err := suite.msgServer.Deposit(sdk.WrapSDKContext(suite.Ctx), msg) _, err := suite.msgServer.Deposit(sdk.WrapSDKContext(suite.Ctx), msg)
suite.Require().NoError(err) suite.Require().NoError(err)
@ -94,12 +94,12 @@ func (suite *msgServerTestSuite) TestWithdraw() {
acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0) acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
msgDeposit := types.NewMsgDeposit(acc.GetAddress().String(), depositAmount) msgDeposit := types.NewMsgDeposit(acc.GetAddress().String(), depositAmount, types.STRATEGY_TYPE_HARD)
_, err := suite.msgServer.Deposit(sdk.WrapSDKContext(suite.Ctx), msgDeposit) _, err := suite.msgServer.Deposit(sdk.WrapSDKContext(suite.Ctx), msgDeposit)
suite.Require().NoError(err) suite.Require().NoError(err)
// Withdraw all // Withdraw all
msgWithdraw := types.NewMsgWithdraw(acc.GetAddress().String(), depositAmount) msgWithdraw := types.NewMsgWithdraw(acc.GetAddress().String(), depositAmount, types.STRATEGY_TYPE_HARD)
_, err = suite.msgServer.Withdraw(sdk.WrapSDKContext(suite.Ctx), msgWithdraw) _, err = suite.msgServer.Withdraw(sdk.WrapSDKContext(suite.Ctx), msgWithdraw)
suite.Require().NoError(err) suite.Require().NoError(err)

View File

@ -40,7 +40,7 @@ func (suite *strategyHardTestSuite) TestDeposit_SingleAcc() {
acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0) acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount) err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount, types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
suite.HardDepositAmountEqual(sdk.NewCoins(depositAmount)) suite.HardDepositAmountEqual(sdk.NewCoins(depositAmount))
@ -65,11 +65,11 @@ func (suite *strategyHardTestSuite) TestDeposit_SingleAcc_MultipleDeposits() {
acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0) acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount) err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount, types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
// Second deposit // Second deposit
err = suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount) err = suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount, types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
expectedVaultBalance := depositAmount.Add(depositAmount) expectedVaultBalance := depositAmount.Add(depositAmount)
@ -101,11 +101,11 @@ func (suite *strategyHardTestSuite) TestDeposit_MultipleAcc_MultipleDeposits() {
// 2 deposits each account // 2 deposits each account
for i := 0; i < 2; i++ { for i := 0; i < 2; i++ {
// Deposit from acc1 // Deposit from acc1
err := suite.Keeper.Deposit(suite.Ctx, acc1.GetAddress(), depositAmount) err := suite.Keeper.Deposit(suite.Ctx, acc1.GetAddress(), depositAmount, types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
// Deposit from acc2 // Deposit from acc2
err = suite.Keeper.Deposit(suite.Ctx, acc2.GetAddress(), depositAmount) err = suite.Keeper.Deposit(suite.Ctx, acc2.GetAddress(), depositAmount, types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
} }
@ -150,7 +150,7 @@ func (suite *strategyHardTestSuite) TestGetVaultTotalValue_NoDenomDeposit() {
acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0) acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
// Deposit vault1 // Deposit vault1
err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount) err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount, types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
// Query vault total, hard deposit exists for account, but amount in busd does not // Query vault total, hard deposit exists for account, but amount in busd does not
@ -173,7 +173,7 @@ func (suite *strategyHardTestSuite) TestWithdraw() {
suite.CreateVault(vaultDenom, types.STRATEGY_TYPE_HARD) suite.CreateVault(vaultDenom, types.STRATEGY_TYPE_HARD)
acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0) acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount) err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount, types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
suite.HardDepositAmountEqual(sdk.NewCoins(depositAmount)) suite.HardDepositAmountEqual(sdk.NewCoins(depositAmount))
@ -184,7 +184,7 @@ func (suite *strategyHardTestSuite) TestWithdraw() {
suite.Equal(depositAmount, totalValue) suite.Equal(depositAmount, totalValue)
// Withdraw // Withdraw
err = suite.Keeper.Withdraw(suite.Ctx, acc.GetAddress(), depositAmount) err = suite.Keeper.Withdraw(suite.Ctx, acc.GetAddress(), depositAmount, types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
suite.HardDepositAmountEqual(sdk.NewCoins()) suite.HardDepositAmountEqual(sdk.NewCoins())
@ -196,7 +196,7 @@ func (suite *strategyHardTestSuite) TestWithdraw() {
suite.Equal(sdk.NewInt64Coin(vaultDenom, 0), totalValue) suite.Equal(sdk.NewInt64Coin(vaultDenom, 0), totalValue)
// Withdraw again // Withdraw again
err = suite.Keeper.Withdraw(suite.Ctx, acc.GetAddress(), depositAmount) err = suite.Keeper.Withdraw(suite.Ctx, acc.GetAddress(), depositAmount, types.STRATEGY_TYPE_HARD)
suite.Require().Error(err) suite.Require().Error(err)
suite.Require().ErrorIs(err, types.ErrVaultRecordNotFound, "vault should be deleted when no more supply") suite.Require().ErrorIs(err, types.ErrVaultRecordNotFound, "vault should be deleted when no more supply")
} }
@ -211,18 +211,18 @@ func (suite *strategyHardTestSuite) TestWithdraw_OnlyWithdrawOwnSupply() {
// Deposits from 2 accounts // Deposits from 2 accounts
acc1 := suite.CreateAccount(sdk.NewCoins(startBalance), 0).GetAddress() acc1 := suite.CreateAccount(sdk.NewCoins(startBalance), 0).GetAddress()
acc2 := suite.CreateAccount(sdk.NewCoins(startBalance), 1).GetAddress() acc2 := suite.CreateAccount(sdk.NewCoins(startBalance), 1).GetAddress()
err := suite.Keeper.Deposit(suite.Ctx, acc1, depositAmount) err := suite.Keeper.Deposit(suite.Ctx, acc1, depositAmount, types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
err = suite.Keeper.Deposit(suite.Ctx, acc2, depositAmount) err = suite.Keeper.Deposit(suite.Ctx, acc2, depositAmount, types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
// Withdraw // Withdraw
err = suite.Keeper.Withdraw(suite.Ctx, acc1, depositAmount) err = suite.Keeper.Withdraw(suite.Ctx, acc1, depositAmount, types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
// Withdraw again // Withdraw again
err = suite.Keeper.Withdraw(suite.Ctx, acc1, depositAmount) err = suite.Keeper.Withdraw(suite.Ctx, acc1, depositAmount, types.STRATEGY_TYPE_HARD)
suite.Require().Error(err) suite.Require().Error(err)
suite.Require().ErrorIs( suite.Require().ErrorIs(
err, err,
@ -242,11 +242,11 @@ func (suite *strategyHardTestSuite) TestWithdraw_WithAccumulatedHard() {
acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0).GetAddress() acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0).GetAddress()
acc2 := suite.CreateAccount(sdk.NewCoins(startBalance), 1).GetAddress() acc2 := suite.CreateAccount(sdk.NewCoins(startBalance), 1).GetAddress()
err := suite.Keeper.Deposit(suite.Ctx, acc, depositAmount) err := suite.Keeper.Deposit(suite.Ctx, acc, depositAmount, types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
// Deposit from acc2 so the vault doesn't get deleted when withdrawing // Deposit from acc2 so the vault doesn't get deleted when withdrawing
err = suite.Keeper.Deposit(suite.Ctx, acc2, depositAmount) err = suite.Keeper.Deposit(suite.Ctx, acc2, depositAmount, types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
// Direct hard deposit from module account to increase vault value // Direct hard deposit from module account to increase vault value
@ -260,11 +260,11 @@ func (suite *strategyHardTestSuite) TestWithdraw_WithAccumulatedHard() {
suite.Equal(depositAmount.AddAmount(sdk.NewInt(10)), accValue) suite.Equal(depositAmount.AddAmount(sdk.NewInt(10)), accValue)
// Withdraw 100, 10 remaining // Withdraw 100, 10 remaining
err = suite.Keeper.Withdraw(suite.Ctx, acc, depositAmount) err = suite.Keeper.Withdraw(suite.Ctx, acc, depositAmount, types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
// Withdraw 100 again -- too much // Withdraw 100 again -- too much
err = suite.Keeper.Withdraw(suite.Ctx, acc, depositAmount) err = suite.Keeper.Withdraw(suite.Ctx, acc, depositAmount, types.STRATEGY_TYPE_HARD)
suite.Require().Error(err) suite.Require().Error(err)
suite.Require().ErrorIs( suite.Require().ErrorIs(
err, err,
@ -273,11 +273,11 @@ func (suite *strategyHardTestSuite) TestWithdraw_WithAccumulatedHard() {
) )
// Half of remaining 10, 5 remaining // Half of remaining 10, 5 remaining
err = suite.Keeper.Withdraw(suite.Ctx, acc, sdk.NewCoin(vaultDenom, sdk.NewInt(5))) err = suite.Keeper.Withdraw(suite.Ctx, acc, sdk.NewCoin(vaultDenom, sdk.NewInt(5)), types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
// Withdraw all // Withdraw all
err = suite.Keeper.Withdraw(suite.Ctx, acc, sdk.NewCoin(vaultDenom, sdk.NewInt(5))) err = suite.Keeper.Withdraw(suite.Ctx, acc, sdk.NewCoin(vaultDenom, sdk.NewInt(5)), types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
accValue, err = suite.Keeper.GetVaultAccountValue(suite.Ctx, vaultDenom, acc) accValue, err = suite.Keeper.GetVaultAccountValue(suite.Ctx, vaultDenom, acc)
@ -302,7 +302,7 @@ func (suite *strategyHardTestSuite) TestAccountShares() {
acc2 := suite.CreateAccount(sdk.NewCoins(startBalance), 1).GetAddress() acc2 := suite.CreateAccount(sdk.NewCoins(startBalance), 1).GetAddress()
// 1. acc1 deposit 100 // 1. acc1 deposit 100
err := suite.Keeper.Deposit(suite.Ctx, acc1, depositAmount) err := suite.Keeper.Deposit(suite.Ctx, acc1, depositAmount, types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
acc1Shares, found := suite.Keeper.GetVaultAccountShares(suite.Ctx, acc1) acc1Shares, found := suite.Keeper.GetVaultAccountShares(suite.Ctx, acc1)
@ -318,7 +318,7 @@ func (suite *strategyHardTestSuite) TestAccountShares() {
// 2. acc2 deposit 100 // 2. acc2 deposit 100
// share price is 10% more expensive now // share price is 10% more expensive now
// hard 110 -> 210 // hard 110 -> 210
err = suite.Keeper.Deposit(suite.Ctx, acc2, depositAmount) err = suite.Keeper.Deposit(suite.Ctx, acc2, depositAmount, types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
// 100 * 100 / 210 = 47.619047619 shares // 100 * 100 / 210 = 47.619047619 shares
@ -347,7 +347,7 @@ func (suite *strategyHardTestSuite) TestAccountShares() {
suite.HardKeeper.Deposit(suite.Ctx, macc.GetAddress(), sdk.NewCoins(sdk.NewInt64Coin(vaultDenom, 90))) suite.HardKeeper.Deposit(suite.Ctx, macc.GetAddress(), sdk.NewCoins(sdk.NewInt64Coin(vaultDenom, 90)))
// Deposit again from acc1 // Deposit again from acc1
err = suite.Keeper.Deposit(suite.Ctx, acc1, depositAmount) err = suite.Keeper.Deposit(suite.Ctx, acc1, depositAmount, types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
acc1Shares, found = suite.Keeper.GetVaultAccountShares(suite.Ctx, acc1) acc1Shares, found = suite.Keeper.GetVaultAccountShares(suite.Ctx, acc1)
@ -377,11 +377,11 @@ func (suite *strategyHardTestSuite) TestWithdraw_AccumulatedAmount() {
acc2 := suite.CreateAccount(sdk.NewCoins(startBalance), 1).GetAddress() acc2 := suite.CreateAccount(sdk.NewCoins(startBalance), 1).GetAddress()
// 1. acc1 deposit 100 // 1. acc1 deposit 100
err := suite.Keeper.Deposit(suite.Ctx, acc1, depositAmount) err := suite.Keeper.Deposit(suite.Ctx, acc1, depositAmount, types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
// acc2 deposit 100, just to make sure other deposits do not affect acc1 // acc2 deposit 100, just to make sure other deposits do not affect acc1
err = suite.Keeper.Deposit(suite.Ctx, acc2, depositAmount) err = suite.Keeper.Deposit(suite.Ctx, acc2, depositAmount, types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
acc1Shares, found := suite.Keeper.GetVaultAccountShares(suite.Ctx, acc1) acc1Shares, found := suite.Keeper.GetVaultAccountShares(suite.Ctx, acc1)
@ -395,7 +395,7 @@ func (suite *strategyHardTestSuite) TestWithdraw_AccumulatedAmount() {
suite.Require().NoError(err) suite.Require().NoError(err)
// 3. Withdraw all from acc1 - including accumulated amount // 3. Withdraw all from acc1 - including accumulated amount
err = suite.Keeper.Withdraw(suite.Ctx, acc1, depositAmount.AddAmount(sdk.NewInt(10))) err = suite.Keeper.Withdraw(suite.Ctx, acc1, depositAmount.AddAmount(sdk.NewInt(10)), types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
_, found = suite.Keeper.GetVaultAccountShares(suite.Ctx, acc1) _, found = suite.Keeper.GetVaultAccountShares(suite.Ctx, acc1)
@ -415,11 +415,11 @@ func (suite *strategyHardTestSuite) TestWithdraw_AccumulatedTruncated() {
acc2 := suite.CreateAccount(sdk.NewCoins(startBalance), 1).GetAddress() acc2 := suite.CreateAccount(sdk.NewCoins(startBalance), 1).GetAddress()
// 1. acc1 deposit 100 // 1. acc1 deposit 100
err := suite.Keeper.Deposit(suite.Ctx, acc1, depositAmount) err := suite.Keeper.Deposit(suite.Ctx, acc1, depositAmount, types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
// acc2 deposit 100, just to make sure other deposits do not affect acc1 // acc2 deposit 100, just to make sure other deposits do not affect acc1
err = suite.Keeper.Deposit(suite.Ctx, acc2, depositAmount) err = suite.Keeper.Deposit(suite.Ctx, acc2, depositAmount, types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
acc1Shares, found := suite.Keeper.GetVaultAccountShares(suite.Ctx, acc1) acc1Shares, found := suite.Keeper.GetVaultAccountShares(suite.Ctx, acc1)
@ -437,7 +437,7 @@ func (suite *strategyHardTestSuite) TestWithdraw_AccumulatedTruncated() {
suite.Equal(depositAmount.AddAmount(sdk.NewInt(5)), accBal, "acc1 should have 105 usdx") suite.Equal(depositAmount.AddAmount(sdk.NewInt(5)), accBal, "acc1 should have 105 usdx")
// 3. Withdraw all from acc1 - including accumulated amount // 3. Withdraw all from acc1 - including accumulated amount
err = suite.Keeper.Withdraw(suite.Ctx, acc1, depositAmount.AddAmount(sdk.NewInt(5))) err = suite.Keeper.Withdraw(suite.Ctx, acc1, depositAmount.AddAmount(sdk.NewInt(5)), types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
acc1Shares, found = suite.Keeper.GetVaultAccountShares(suite.Ctx, acc1) acc1Shares, found = suite.Keeper.GetVaultAccountShares(suite.Ctx, acc1)
@ -459,7 +459,7 @@ func (suite *strategyHardTestSuite) TestWithdraw_ExpensiveShares() {
acc1 := suite.CreateAccount(sdk.NewCoins(startBalance), 0).GetAddress() acc1 := suite.CreateAccount(sdk.NewCoins(startBalance), 0).GetAddress()
// 1. acc1 deposit 100 // 1. acc1 deposit 100
err := suite.Keeper.Deposit(suite.Ctx, acc1, depositAmount) err := suite.Keeper.Deposit(suite.Ctx, acc1, depositAmount, types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
acc1Shares, found := suite.Keeper.GetVaultAccountShares(suite.Ctx, acc1) acc1Shares, found := suite.Keeper.GetVaultAccountShares(suite.Ctx, acc1)
@ -477,7 +477,7 @@ func (suite *strategyHardTestSuite) TestWithdraw_ExpensiveShares() {
suite.Equal(sdk.NewInt(2000), accBal.Amount, "acc1 should have 2000 usdx") suite.Equal(sdk.NewInt(2000), accBal.Amount, "acc1 should have 2000 usdx")
// 3. Withdraw all from acc1 - including accumulated amount // 3. Withdraw all from acc1 - including accumulated amount
err = suite.Keeper.Withdraw(suite.Ctx, acc1, sdk.NewInt64Coin(vaultDenom, 2000)) err = suite.Keeper.Withdraw(suite.Ctx, acc1, sdk.NewInt64Coin(vaultDenom, 2000), types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
acc1Shares, found = suite.Keeper.GetVaultAccountShares(suite.Ctx, acc1) acc1Shares, found = suite.Keeper.GetVaultAccountShares(suite.Ctx, acc1)

View File

@ -38,7 +38,7 @@ func (k *Keeper) GetVaultTotalValue(
return sdk.Coin{}, types.ErrVaultRecordNotFound return sdk.Coin{}, types.ErrVaultRecordNotFound
} }
strategy, err := k.GetStrategy(enabledVault.VaultStrategy) strategy, err := k.GetStrategy(enabledVault.Strategies[0])
if err != nil { if err != nil {
return sdk.Coin{}, types.ErrInvalidVaultStrategy return sdk.Coin{}, types.ErrInvalidVaultStrategy
} }

View File

@ -32,7 +32,7 @@ func (suite *vaultTestSuite) TestGetVaultTotalShares() {
acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0) acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount) err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount, types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
vaultTotalShares, found := suite.Keeper.GetVaultTotalShares(suite.Ctx, vaultDenom) vaultTotalShares, found := suite.Keeper.GetVaultTotalShares(suite.Ctx, vaultDenom)
@ -66,13 +66,12 @@ func (suite *vaultTestSuite) TestGetVaultTotalValue_NotFound() {
suite.Require().ErrorIs(err, types.ErrVaultRecordNotFound) suite.Require().ErrorIs(err, types.ErrVaultRecordNotFound)
} }
func (suite *vaultTestSuite) TestGetVaultTotalValue_InvalidStrategy() { func (suite *vaultTestSuite) TestInvalidVaultStrategy() {
vaultDenom := "usdx" vaultDenom := "usdx"
suite.CreateVault(vaultDenom, 99999) // not valid strategy type
_, err := suite.Keeper.GetVaultTotalValue(suite.Ctx, vaultDenom) suite.PanicsWithValue("value from ParamSetPair is invalid: invalid strategy 99999", func() {
suite.Require().Error(err) suite.CreateVault(vaultDenom, 99999) // not valid strategy type
suite.Require().ErrorIs(err, types.ErrInvalidVaultStrategy) })
} }
func (suite *vaultTestSuite) TestGetVaultAccountSupplied() { func (suite *vaultTestSuite) TestGetVaultAccountSupplied() {
@ -95,10 +94,10 @@ func (suite *vaultTestSuite) TestGetVaultAccountSupplied() {
suite.Require().False(found) suite.Require().False(found)
// Deposits from both accounts // Deposits from both accounts
err := suite.Keeper.Deposit(suite.Ctx, acc1.GetAddress(), deposit1Amount) err := suite.Keeper.Deposit(suite.Ctx, acc1.GetAddress(), deposit1Amount, types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
err = suite.Keeper.Deposit(suite.Ctx, acc2.GetAddress(), deposit2Amount) err = suite.Keeper.Deposit(suite.Ctx, acc2.GetAddress(), deposit2Amount, types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
// Check balances // Check balances
@ -123,7 +122,7 @@ func (suite *vaultTestSuite) TestGetVaultAccountValue() {
suite.CreateVault(vaultDenom, types.STRATEGY_TYPE_HARD) suite.CreateVault(vaultDenom, types.STRATEGY_TYPE_HARD)
err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount) err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount, types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
accValue, err := suite.Keeper.GetVaultAccountValue(suite.Ctx, vaultDenom, acc.GetAddress()) accValue, err := suite.Keeper.GetVaultAccountValue(suite.Ctx, vaultDenom, acc.GetAddress())
@ -151,7 +150,7 @@ func (suite *vaultTestSuite) TestGetVaultAccountValue_ShareNotFound() {
suite.CreateVault(vaultDenom, types.STRATEGY_TYPE_HARD) suite.CreateVault(vaultDenom, types.STRATEGY_TYPE_HARD)
// Deposit from acc1 so that vault record exists // Deposit from acc1 so that vault record exists
err := suite.Keeper.Deposit(suite.Ctx, acc1.GetAddress(), depositAmount) err := suite.Keeper.Deposit(suite.Ctx, acc1.GetAddress(), depositAmount, types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
// Query from acc2 with no share record // Query from acc2 with no share record

View File

@ -11,7 +11,12 @@ import (
// Withdraw removes the amount of supplied tokens from a vault and transfers it // Withdraw removes the amount of supplied tokens from a vault and transfers it
// back to the account. // back to the account.
func (k *Keeper) Withdraw(ctx sdk.Context, from sdk.AccAddress, wantAmount sdk.Coin) error { func (k *Keeper) Withdraw(
ctx sdk.Context,
from sdk.AccAddress,
wantAmount sdk.Coin,
withdrawStrategy types.StrategyType,
) error {
// Get AllowedVault, if not found (not a valid vault), return error // Get AllowedVault, if not found (not a valid vault), return error
allowedVault, found := k.GetAllowedVault(ctx, wantAmount.Denom) allowedVault, found := k.GetAllowedVault(ctx, wantAmount.Denom)
if !found { if !found {
@ -22,6 +27,11 @@ func (k *Keeper) Withdraw(ctx sdk.Context, from sdk.AccAddress, wantAmount sdk.C
return types.ErrInsufficientAmount return types.ErrInsufficientAmount
} }
// Check if withdraw strategy is supported by vault
if !allowedVault.IsStrategyAllowed(withdrawStrategy) {
return types.ErrInvalidVaultStrategy
}
// Check if VaultRecord exists // Check if VaultRecord exists
vaultRecord, found := k.GetVaultRecord(ctx, wantAmount.Denom) vaultRecord, found := k.GetVaultRecord(ctx, wantAmount.Denom)
if !found { if !found {
@ -74,7 +84,7 @@ func (k *Keeper) Withdraw(ctx sdk.Context, from sdk.AccAddress, wantAmount sdk.C
} }
// Get the strategy for the vault // Get the strategy for the vault
strategy, err := k.GetStrategy(allowedVault.VaultStrategy) strategy, err := k.GetStrategy(allowedVault.Strategies[0])
if err != nil { if err != nil {
return err return err
} }

View File

@ -33,7 +33,7 @@ func (suite *withdrawTestSuite) TestWithdraw_NoVaultRecord() {
acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0) acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
// Withdraw without having any prior deposits // Withdraw without having any prior deposits
err := suite.Keeper.Withdraw(suite.Ctx, acc.GetAddress(), withdrawAmount) err := suite.Keeper.Withdraw(suite.Ctx, acc.GetAddress(), withdrawAmount, types.STRATEGY_TYPE_HARD)
suite.Require().Error(err) suite.Require().Error(err)
suite.Require().ErrorIs(err, types.ErrVaultRecordNotFound) suite.Require().ErrorIs(err, types.ErrVaultRecordNotFound)
@ -59,13 +59,13 @@ func (suite *withdrawTestSuite) TestWithdraw_NoVaultShareRecord() {
// Create deposit from acc1 so the VaultRecord exists in state // Create deposit from acc1 so the VaultRecord exists in state
acc1 := suite.CreateAccount(sdk.NewCoins(startBalance), 0) acc1 := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
err := suite.Keeper.Deposit(suite.Ctx, acc1.GetAddress(), acc1DepositAmount) err := suite.Keeper.Deposit(suite.Ctx, acc1.GetAddress(), acc1DepositAmount, types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
acc2 := suite.CreateAccount(sdk.NewCoins(startBalance), 1) acc2 := suite.CreateAccount(sdk.NewCoins(startBalance), 1)
// Withdraw from acc2 without having any prior deposits // Withdraw from acc2 without having any prior deposits
err = suite.Keeper.Withdraw(suite.Ctx, acc2.GetAddress(), acc2WithdrawAmount) err = suite.Keeper.Withdraw(suite.Ctx, acc2.GetAddress(), acc2WithdrawAmount, types.STRATEGY_TYPE_HARD)
suite.Require().Error(err) suite.Require().Error(err)
suite.Require().ErrorIs(err, types.ErrVaultShareRecordNotFound) suite.Require().ErrorIs(err, types.ErrVaultShareRecordNotFound)
@ -91,10 +91,10 @@ func (suite *withdrawTestSuite) TestWithdraw_ExceedBalance() {
acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0) acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount) err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount, types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
err = suite.Keeper.Withdraw(suite.Ctx, acc.GetAddress(), withdrawAmount) err = suite.Keeper.Withdraw(suite.Ctx, acc.GetAddress(), withdrawAmount, types.STRATEGY_TYPE_HARD)
suite.Require().Error(err) suite.Require().Error(err)
suite.Require().ErrorIs(err, types.ErrInsufficientValue) suite.Require().ErrorIs(err, types.ErrInsufficientValue)
@ -119,7 +119,7 @@ func (suite *withdrawTestSuite) TestWithdraw_Zero() {
acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0) acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
err := suite.Keeper.Withdraw(suite.Ctx, acc.GetAddress(), withdrawAmount) err := suite.Keeper.Withdraw(suite.Ctx, acc.GetAddress(), withdrawAmount, types.STRATEGY_TYPE_HARD)
suite.Require().Error(err) suite.Require().Error(err)
suite.Require().ErrorIs(err, types.ErrInsufficientAmount) suite.Require().ErrorIs(err, types.ErrInsufficientAmount)
@ -144,7 +144,7 @@ func (suite *withdrawTestSuite) TestWithdraw_InvalidVault() {
acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0) acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
err := suite.Keeper.Withdraw(suite.Ctx, acc.GetAddress(), withdrawAmount) err := suite.Keeper.Withdraw(suite.Ctx, acc.GetAddress(), withdrawAmount, types.STRATEGY_TYPE_HARD)
suite.Require().Error(err) suite.Require().Error(err)
suite.Require().ErrorIs(err, types.ErrInvalidVaultDenom) suite.Require().ErrorIs(err, types.ErrInvalidVaultDenom)
@ -160,6 +160,20 @@ func (suite *withdrawTestSuite) TestWithdraw_InvalidVault() {
) )
} }
func (suite *withdrawTestSuite) TestWithdraw_InvalidStrategy() {
vaultDenom := "usdx"
startBalance := sdk.NewInt64Coin(vaultDenom, 1000)
withdrawAmount := sdk.NewInt64Coin(vaultDenom, 1001)
suite.CreateVault(vaultDenom, types.STRATEGY_TYPE_HARD)
acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
err := suite.Keeper.Withdraw(suite.Ctx, acc.GetAddress(), withdrawAmount, types.STRATEGY_TYPE_SAVINGS)
suite.Require().Error(err)
suite.Require().ErrorIs(err, types.ErrInvalidVaultStrategy)
}
func (suite *withdrawTestSuite) TestWithdraw_FullBalance() { func (suite *withdrawTestSuite) TestWithdraw_FullBalance() {
vaultDenom := "usdx" vaultDenom := "usdx"
startBalance := sdk.NewInt64Coin(vaultDenom, 1000) startBalance := sdk.NewInt64Coin(vaultDenom, 1000)
@ -170,10 +184,10 @@ func (suite *withdrawTestSuite) TestWithdraw_FullBalance() {
acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0) acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount) err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount, types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
err = suite.Keeper.Withdraw(suite.Ctx, acc.GetAddress(), withdrawAmount) err = suite.Keeper.Withdraw(suite.Ctx, acc.GetAddress(), withdrawAmount, types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
// No net changes in balances // No net changes in balances
@ -197,10 +211,10 @@ func (suite *withdrawTestSuite) TestWithdraw_Partial() {
acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0) acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount) err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount, types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
err = suite.Keeper.Withdraw(suite.Ctx, acc.GetAddress(), partialWithdrawAmount) err = suite.Keeper.Withdraw(suite.Ctx, acc.GetAddress(), partialWithdrawAmount, types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
suite.AccountBalanceEqual( suite.AccountBalanceEqual(
@ -209,11 +223,11 @@ func (suite *withdrawTestSuite) TestWithdraw_Partial() {
) )
// Second withdraw for remaining 50 // Second withdraw for remaining 50
err = suite.Keeper.Withdraw(suite.Ctx, acc.GetAddress(), partialWithdrawAmount) err = suite.Keeper.Withdraw(suite.Ctx, acc.GetAddress(), partialWithdrawAmount, types.STRATEGY_TYPE_HARD)
suite.Require().NoError(err) suite.Require().NoError(err)
// No more balance to withdraw // No more balance to withdraw
err = suite.Keeper.Withdraw(suite.Ctx, acc.GetAddress(), partialWithdrawAmount) err = suite.Keeper.Withdraw(suite.Ctx, acc.GetAddress(), partialWithdrawAmount, types.STRATEGY_TYPE_HARD)
suite.Require().Error(err) suite.Require().Error(err)
suite.Require().ErrorIs(err, types.ErrVaultRecordNotFound, "vault record should be deleted after no more supplied") suite.Require().ErrorIs(err, types.ErrVaultRecordNotFound, "vault record should be deleted after no more supplied")

View File

@ -216,13 +216,11 @@ func (suite *Suite) NewAccountFromAddr(addr sdk.AccAddress, balance sdk.Coins) a
// CreateVault adds a new vault to the keeper parameters // CreateVault adds a new vault to the keeper parameters
func (suite *Suite) CreateVault(vaultDenom string, vaultStrategy types.StrategyType) { func (suite *Suite) CreateVault(vaultDenom string, vaultStrategy types.StrategyType) {
vault := types.NewAllowedVault(vaultDenom, vaultStrategy) vault := types.NewAllowedVault(vaultDenom, vaultStrategy)
suite.Require().NoError(vault.Validate())
allowedVaults := suite.Keeper.GetAllowedVaults(suite.Ctx) allowedVaults := suite.Keeper.GetAllowedVaults(suite.Ctx)
allowedVaults = append(allowedVaults, vault) allowedVaults = append(allowedVaults, vault)
params := types.NewParams(allowedVaults) params := types.NewParams(allowedVaults)
suite.Require().NoError(params.Validate())
suite.Keeper.SetParams( suite.Keeper.SetParams(
suite.Ctx, suite.Ctx,

View File

@ -20,10 +20,11 @@ const (
) )
// NewMsgDeposit returns a new MsgDeposit. // NewMsgDeposit returns a new MsgDeposit.
func NewMsgDeposit(depositor string, amount sdk.Coin) *MsgDeposit { func NewMsgDeposit(depositor string, amount sdk.Coin, strategy StrategyType) *MsgDeposit {
return &MsgDeposit{ return &MsgDeposit{
Depositor: depositor, Depositor: depositor,
Amount: amount, Amount: amount,
Strategy: strategy,
} }
} }
@ -37,6 +38,10 @@ func (msg MsgDeposit) ValidateBasic() error {
return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, err.Error()) return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, err.Error())
} }
if err := msg.Strategy.Validate(); err != nil {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error())
}
return nil return nil
} }
@ -67,10 +72,11 @@ func (msg MsgDeposit) Type() string {
} }
// NewMsgWithdraw returns a new MsgWithdraw. // NewMsgWithdraw returns a new MsgWithdraw.
func NewMsgWithdraw(from string, amount sdk.Coin) *MsgWithdraw { func NewMsgWithdraw(from string, amount sdk.Coin, strategy StrategyType) *MsgWithdraw {
return &MsgWithdraw{ return &MsgWithdraw{
From: from, From: from,
Amount: amount, Amount: amount,
Strategy: strategy,
} }
} }
@ -84,6 +90,10 @@ func (msg MsgWithdraw) ValidateBasic() error {
return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, err.Error()) return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, err.Error())
} }
if err := msg.Strategy.Validate(); err != nil {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error())
}
return nil return nil
} }

View File

@ -192,7 +192,7 @@ type VaultResponse struct {
// denom represents the denom of the vault // denom represents the denom of the vault
Denom string `protobuf:"bytes,1,opt,name=denom,proto3" json:"denom,omitempty"` Denom string `protobuf:"bytes,1,opt,name=denom,proto3" json:"denom,omitempty"`
// VaultStrategy is the strategy used for this vault. // VaultStrategy is the strategy used for this vault.
VaultStrategy StrategyType `protobuf:"varint,2,opt,name=vault_strategy,json=vaultStrategy,proto3,enum=kava.earn.v1beta1.StrategyType" json:"vault_strategy,omitempty"` Strategies StrategyTypes `protobuf:"varint,2,rep,packed,name=strategies,proto3,enum=kava.earn.v1beta1.StrategyType,castrepeated=StrategyTypes" json:"strategies,omitempty"`
// TotalShares is the total amount of shares issued to depositors. // TotalShares is the total amount of shares issued to depositors.
TotalShares string `protobuf:"bytes,3,opt,name=total_shares,json=totalShares,proto3" json:"total_shares,omitempty"` TotalShares string `protobuf:"bytes,3,opt,name=total_shares,json=totalShares,proto3" json:"total_shares,omitempty"`
// TotalValue is the total value of denom coins supplied to the vault if the // TotalValue is the total value of denom coins supplied to the vault if the
@ -376,55 +376,56 @@ 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{
// 762 bytes of a gzipped FileDescriptorProto // 771 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x55, 0xcf, 0x4f, 0x13, 0x4f, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x55, 0x4f, 0x4f, 0x13, 0x4d,
0x14, 0xef, 0xb6, 0xb4, 0x81, 0xe9, 0x17, 0xbe, 0x71, 0xa8, 0x49, 0x5b, 0x64, 0x5b, 0x96, 0x08, 0x18, 0xef, 0xb6, 0xb4, 0x81, 0xe9, 0xcb, 0xfb, 0x86, 0xa1, 0x6f, 0xd2, 0x96, 0x97, 0x6d, 0x59,
0x95, 0xa4, 0xbb, 0x52, 0x13, 0xbd, 0x18, 0x13, 0x2b, 0xd1, 0xe0, 0xc1, 0xe8, 0xa2, 0x1c, 0x4c, 0xf2, 0x42, 0x25, 0xe9, 0xae, 0xd4, 0x44, 0x2f, 0xc6, 0xc4, 0x4a, 0x34, 0x78, 0x30, 0xba, 0x28,
0x4c, 0x33, 0xa5, 0x93, 0x65, 0x43, 0xbb, 0xb3, 0xec, 0x4c, 0xab, 0x68, 0xbc, 0x70, 0x37, 0x31, 0x07, 0x13, 0x43, 0xa6, 0x74, 0xb2, 0x6c, 0x68, 0x77, 0x96, 0x9d, 0x69, 0x15, 0x8d, 0x17, 0xee,
0xf1, 0x5f, 0x30, 0x1e, 0x3c, 0xf3, 0x47, 0x70, 0x24, 0x78, 0x31, 0x1e, 0x50, 0xc1, 0xbb, 0x57, 0x26, 0x26, 0x7e, 0x05, 0xe3, 0x81, 0x33, 0x1f, 0x82, 0x23, 0xc1, 0x8b, 0xf1, 0x00, 0x0a, 0x7e,
0x8f, 0x66, 0x7e, 0x2c, 0x65, 0xdb, 0x6d, 0xea, 0xa9, 0x9d, 0xf7, 0xe3, 0xf3, 0xf9, 0xbc, 0x37, 0x08, 0x13, 0x2f, 0x66, 0xfe, 0x2c, 0xed, 0xb6, 0xdb, 0xd4, 0x53, 0x3b, 0xcf, 0x9f, 0xdf, 0xef,
0x6f, 0xde, 0x82, 0xf9, 0x1d, 0xd4, 0x43, 0x16, 0x46, 0x81, 0x67, 0xf5, 0x56, 0x9b, 0x98, 0xa1, 0x79, 0x9e, 0xf9, 0xcd, 0xb3, 0x60, 0x7e, 0x17, 0x75, 0x91, 0x85, 0x51, 0xe0, 0x59, 0xdd, 0xd5,
0x55, 0x6b, 0xb7, 0x8b, 0x83, 0x3d, 0xd3, 0x0f, 0x08, 0x23, 0xf0, 0x12, 0x77, 0x9b, 0xdc, 0x6d, 0x06, 0x66, 0x68, 0xd5, 0xda, 0xeb, 0xe0, 0x60, 0xdf, 0xf4, 0x03, 0xc2, 0x08, 0x9c, 0xe1, 0x6e,
0x2a, 0x77, 0xb1, 0xb0, 0x45, 0x68, 0x87, 0xd0, 0x86, 0x08, 0xb0, 0xe4, 0x41, 0x46, 0x17, 0x57, 0x93, 0xbb, 0x4d, 0xe5, 0x2e, 0x16, 0xb6, 0x09, 0x6d, 0x13, 0xba, 0x25, 0x02, 0x2c, 0x79, 0x90,
0xe4, 0xc9, 0x6a, 0x22, 0x8a, 0x25, 0xcc, 0x39, 0xa8, 0x8f, 0x1c, 0xd7, 0x43, 0xcc, 0x25, 0x9e, 0xd1, 0xc5, 0x15, 0x79, 0xb2, 0x1a, 0x88, 0x62, 0x09, 0x73, 0x05, 0xea, 0x23, 0xc7, 0xf5, 0x10,
0x8a, 0xd5, 0x2f, 0xc6, 0x86, 0x51, 0x5b, 0xc4, 0x0d, 0xfd, 0x39, 0x87, 0x38, 0x44, 0x72, 0xf0, 0x73, 0x89, 0xa7, 0x62, 0xf5, 0xfe, 0xd8, 0x30, 0x6a, 0x9b, 0xb8, 0xa1, 0x3f, 0xe7, 0x10, 0x87,
0x7f, 0xca, 0x7a, 0xc5, 0x21, 0xc4, 0x69, 0x63, 0x0b, 0xf9, 0xae, 0x85, 0x3c, 0x8f, 0x30, 0x01, 0x48, 0x0e, 0xfe, 0x4f, 0x59, 0xff, 0x73, 0x08, 0x71, 0x5a, 0xd8, 0x42, 0xbe, 0x6b, 0x21, 0xcf,
0x19, 0xf2, 0xeb, 0xc3, 0xc5, 0xf8, 0x28, 0x40, 0x9d, 0xd0, 0x5f, 0x1e, 0xf6, 0x53, 0x16, 0x20, 0x23, 0x4c, 0x40, 0x86, 0xfc, 0xfa, 0x70, 0x33, 0x3e, 0x0a, 0x50, 0x3b, 0xf4, 0x97, 0x87, 0xfd,
0x86, 0x1d, 0x55, 0x6f, 0x31, 0xa6, 0x1d, 0x3d, 0xd4, 0x6d, 0x33, 0xe9, 0x36, 0x72, 0x00, 0x3e, 0x94, 0x05, 0x88, 0x61, 0x47, 0xf5, 0x5b, 0x8c, 0x19, 0x47, 0x17, 0x75, 0x5a, 0x4c, 0xba, 0x8d,
0xe1, 0x65, 0x3d, 0x16, 0xa8, 0x36, 0xde, 0xed, 0x62, 0xca, 0x8c, 0x47, 0x60, 0x36, 0x62, 0xa5, 0x1c, 0x80, 0x4f, 0x78, 0x5b, 0x8f, 0x05, 0xaa, 0x8d, 0xf7, 0x3a, 0x98, 0x32, 0xe3, 0x11, 0x98,
0x3e, 0xf1, 0x28, 0x86, 0xb7, 0x40, 0x46, 0xb2, 0xe7, 0xb5, 0xb2, 0x56, 0xc9, 0xd6, 0x0a, 0xe6, 0x8d, 0x58, 0xa9, 0x4f, 0x3c, 0x8a, 0xe1, 0x2d, 0x90, 0x91, 0xec, 0x79, 0xad, 0xac, 0x55, 0xb2,
0x50, 0x33, 0x4d, 0x99, 0x52, 0x9f, 0x38, 0x3c, 0x29, 0x25, 0x6c, 0x15, 0x6e, 0xac, 0x28, 0x96, 0xb5, 0x82, 0x39, 0x34, 0x4c, 0x53, 0xa6, 0xd4, 0x27, 0x8e, 0xcf, 0x4a, 0x09, 0x5b, 0x85, 0x1b,
0x4d, 0xce, 0x1c, 0xb2, 0xc0, 0x1c, 0x48, 0xb7, 0xb0, 0x47, 0x3a, 0x02, 0x6d, 0xca, 0x96, 0x07, 0x2b, 0x8a, 0x65, 0x93, 0x33, 0x87, 0x2c, 0x30, 0x07, 0xd2, 0x4d, 0xec, 0x91, 0xb6, 0x40, 0x9b,
0xe3, 0x99, 0xe2, 0x0e, 0x63, 0x15, 0xf7, 0x1d, 0x90, 0x11, 0xba, 0x39, 0x77, 0xaa, 0x92, 0xad, 0xb2, 0xe5, 0xc1, 0x78, 0xa6, 0xb8, 0xc3, 0x58, 0xc5, 0x7d, 0x07, 0x64, 0x44, 0xdd, 0x9c, 0x3b,
0x95, 0x63, 0xb8, 0x45, 0x4a, 0x98, 0x11, 0x4a, 0x90, 0x59, 0xc6, 0x6f, 0x0d, 0x4c, 0x47, 0xfc, 0x55, 0xc9, 0xd6, 0xca, 0x31, 0xdc, 0x22, 0x25, 0xcc, 0x08, 0x4b, 0x90, 0x59, 0xc6, 0x2f, 0x0d,
0xf1, 0xf4, 0xf0, 0x3e, 0x98, 0x11, 0x19, 0x8d, 0xb0, 0x8f, 0xf9, 0x64, 0x59, 0xab, 0xcc, 0xd4, 0x4c, 0x47, 0xfc, 0xf1, 0xf4, 0xd0, 0x06, 0x40, 0x4d, 0xd0, 0xc5, 0x34, 0x9f, 0x2c, 0xa7, 0x2a,
0x4a, 0x31, 0x7c, 0x1b, 0x2a, 0xe4, 0xe9, 0x9e, 0x8f, 0xed, 0x69, 0x91, 0x16, 0x9a, 0xe0, 0x02, 0x7f, 0xd7, 0x4a, 0x31, 0x5c, 0x1b, 0x6a, 0xcc, 0x4f, 0xf7, 0x7d, 0x5c, 0x9f, 0x39, 0x3c, 0x2f,
0xf8, 0x8f, 0x11, 0x86, 0xda, 0x0d, 0xba, 0x8d, 0x02, 0x4c, 0xf3, 0x29, 0x41, 0x92, 0x15, 0xb6, 0x4d, 0xf7, 0x5b, 0xa8, 0xdd, 0x87, 0x02, 0x17, 0xc0, 0x5f, 0x8c, 0x30, 0xd4, 0xda, 0xa2, 0x3b,
0x0d, 0x61, 0x82, 0x2f, 0x80, 0x3c, 0x36, 0x7a, 0xa8, 0xdd, 0xc5, 0xf9, 0x09, 0x1e, 0x51, 0xbf, 0x28, 0xc0, 0x34, 0x9f, 0x12, 0x84, 0x59, 0x61, 0xdb, 0x10, 0x26, 0xf8, 0x02, 0xc8, 0xe3, 0x56,
0xcd, 0x55, 0x7f, 0x3b, 0x29, 0x2d, 0x39, 0x2e, 0xdb, 0xee, 0x36, 0xcd, 0x2d, 0xd2, 0x51, 0x23, 0x17, 0xb5, 0x3a, 0x38, 0x3f, 0xc1, 0x23, 0xea, 0xb7, 0x79, 0x07, 0x5f, 0xcf, 0x4a, 0x4b, 0x8e,
0xa9, 0x7e, 0xaa, 0xb4, 0xb5, 0x63, 0xb1, 0x3d, 0x1f, 0x53, 0x73, 0xdd, 0x63, 0xc7, 0x07, 0x55, 0xcb, 0x76, 0x3a, 0x0d, 0x73, 0x9b, 0xb4, 0x95, 0x3c, 0xd5, 0x4f, 0x95, 0x36, 0x77, 0x2d, 0xc6,
0xa0, 0x26, 0x76, 0xdd, 0x63, 0x36, 0x10, 0x80, 0x9b, 0x1c, 0xcf, 0xf8, 0xa8, 0x81, 0x9c, 0xe8, 0xf9, 0xcc, 0x75, 0x8f, 0x9d, 0x1e, 0x55, 0x81, 0x52, 0xef, 0xba, 0xc7, 0x6c, 0x20, 0x00, 0x37,
0xe4, 0x1a, 0xf6, 0x09, 0x75, 0xfb, 0x7d, 0x37, 0x41, 0x9a, 0xbc, 0xf4, 0x70, 0x20, 0x0b, 0xaf, 0x39, 0x9e, 0xf1, 0x51, 0x03, 0x39, 0x31, 0xd5, 0x35, 0xec, 0x13, 0xea, 0xf6, 0xee, 0xc0, 0x04,
0xe7, 0x8f, 0x0f, 0xaa, 0x39, 0x85, 0x71, 0xb7, 0xd5, 0x0a, 0x30, 0xa5, 0x1b, 0x2c, 0x70, 0x3d, 0x69, 0xf2, 0xd2, 0xc3, 0x81, 0x1c, 0x42, 0x3d, 0x7f, 0x7a, 0x54, 0xcd, 0x29, 0x8c, 0xbb, 0xcd,
0xc7, 0x96, 0x61, 0xfd, 0x46, 0x25, 0xa3, 0x8d, 0x02, 0xfd, 0x27, 0x20, 0xca, 0xcb, 0xd6, 0x96, 0x66, 0x80, 0x29, 0xdd, 0x60, 0x81, 0xeb, 0x39, 0xb6, 0x0c, 0xeb, 0x0d, 0x2d, 0xd9, 0x3f, 0xb4,
0x4c, 0x85, 0xc3, 0xdf, 0x80, 0x29, 0x9f, 0x5d, 0x7f, 0x30, 0x1c, 0xac, 0x14, 0xd8, 0x17, 0x32, 0xfb, 0x00, 0xf4, 0x9e, 0x83, 0x68, 0x2f, 0x5b, 0x5b, 0x32, 0x15, 0x0e, 0x7f, 0x0f, 0xa6, 0x7c,
0x8d, 0x4f, 0x1a, 0xb8, 0x3c, 0x20, 0x53, 0x5d, 0xd0, 0x1a, 0x98, 0x6c, 0x29, 0x9b, 0xba, 0x74, 0x82, 0x3d, 0x91, 0x38, 0x58, 0x55, 0x60, 0xf7, 0x65, 0x1a, 0x9f, 0x34, 0xf0, 0xef, 0x40, 0x99,
0x23, 0xe6, 0x12, 0x54, 0xda, 0xc0, 0xb5, 0x9f, 0x67, 0xc2, 0x07, 0x11, 0x9d, 0x49, 0xa1, 0x73, 0xea, 0xb2, 0xd6, 0xc0, 0x64, 0x53, 0xd9, 0x94, 0x00, 0x8c, 0x98, 0x4b, 0x51, 0x69, 0x03, 0x12,
0x79, 0xac, 0x4e, 0x09, 0x16, 0x11, 0xfa, 0x47, 0x03, 0xff, 0x0f, 0x90, 0xc1, 0x9b, 0x60, 0x4a, 0xb8, 0xca, 0x84, 0x0f, 0x22, 0x75, 0x26, 0x45, 0x9d, 0xcb, 0x63, 0xeb, 0x94, 0x60, 0x91, 0x42,
0x11, 0x91, 0xf1, 0xed, 0xec, 0x87, 0xc2, 0x87, 0x20, 0xa3, 0xe6, 0x22, 0x29, 0x0a, 0x9b, 0x1f, 0x7f, 0x6a, 0xe0, 0x9f, 0x01, 0x32, 0x78, 0x13, 0x4c, 0x29, 0x22, 0x32, 0x7e, 0x9c, 0xbd, 0x50,
0x35, 0xcd, 0x62, 0x54, 0xea, 0xb3, 0xbc, 0xa6, 0xcf, 0xdf, 0x4b, 0xd9, 0xbe, 0x8d, 0xda, 0x0a, 0xf8, 0x10, 0x64, 0x94, 0x2e, 0x92, 0xa2, 0xb1, 0xf9, 0x51, 0xca, 0x16, 0x52, 0xa9, 0xcf, 0xf2,
0x01, 0x22, 0x90, 0x96, 0x03, 0x94, 0x12, 0x50, 0x85, 0x48, 0x6d, 0x21, 0xd8, 0x3d, 0xe2, 0x7a, 0x9e, 0x0e, 0xcf, 0x4b, 0xd9, 0x9e, 0x8d, 0xda, 0x0a, 0x01, 0x22, 0x90, 0x96, 0x02, 0x4a, 0x09,
0xf5, 0xeb, 0x0a, 0xa6, 0xf2, 0x0f, 0xb3, 0xc5, 0x13, 0xa8, 0x2d, 0x91, 0x6b, 0xef, 0x52, 0x20, 0xa8, 0x42, 0xa4, 0xb7, 0x10, 0xec, 0x1e, 0x71, 0xbd, 0xfa, 0x75, 0x05, 0x53, 0xf9, 0x03, 0x6d,
0x2d, 0xee, 0x08, 0xbe, 0x06, 0x19, 0xf9, 0xc2, 0xe1, 0xd5, 0x18, 0xc9, 0xc3, 0xab, 0xa4, 0xb8, 0xf1, 0x04, 0x6a, 0x4b, 0xe4, 0xda, 0xbb, 0x14, 0x48, 0x8b, 0x3b, 0x82, 0xaf, 0x41, 0x46, 0xbe,
0x34, 0x2e, 0x4c, 0x76, 0xd2, 0x58, 0xd8, 0xff, 0xf2, 0xeb, 0x43, 0x72, 0x0e, 0x16, 0xac, 0x51, 0x76, 0xf8, 0x7f, 0x4c, 0xc9, 0xc3, 0x6b, 0xa5, 0xb8, 0x34, 0x2e, 0x4c, 0x4e, 0xd2, 0x58, 0x38,
0x2b, 0x0f, 0xee, 0x6b, 0x20, 0x23, 0xb7, 0xc2, 0x68, 0xf2, 0xc8, 0x86, 0x19, 0x4d, 0x1e, 0x5d, 0xf8, 0xfc, 0xe3, 0x43, 0x72, 0x0e, 0x16, 0xac, 0x51, 0xeb, 0x0f, 0x1e, 0x68, 0x20, 0x23, 0x37,
0x2e, 0xc6, 0x35, 0x41, 0xbe, 0x08, 0x17, 0xac, 0x11, 0xdb, 0x92, 0x5a, 0x6f, 0xc4, 0xd4, 0xbf, 0xc4, 0x68, 0xf2, 0xc8, 0xb6, 0x19, 0x4d, 0x1e, 0x5d, 0x34, 0xc6, 0x35, 0x41, 0xbe, 0x08, 0x17,
0xe5, 0x22, 0x26, 0xc3, 0x49, 0x85, 0xcb, 0xa3, 0xf0, 0x07, 0x9e, 0x5c, 0xb1, 0x32, 0x3e, 0x50, 0xac, 0x11, 0x9b, 0x93, 0x5a, 0x6f, 0x84, 0xea, 0xdf, 0xf2, 0x22, 0x26, 0x43, 0xa5, 0xc2, 0xe5,
0x49, 0x59, 0x14, 0x52, 0xe6, 0xe1, 0x5c, 0x8c, 0x94, 0x70, 0xa6, 0xeb, 0x6b, 0x87, 0x3f, 0xf5, 0x51, 0xf8, 0x03, 0x4f, 0xae, 0x58, 0x19, 0x1f, 0xa8, 0x4a, 0x59, 0x14, 0xa5, 0xcc, 0xc3, 0xb9,
0xc4, 0xe1, 0xa9, 0xae, 0x1d, 0x9d, 0xea, 0xda, 0x8f, 0x53, 0x5d, 0x7b, 0x7f, 0xa6, 0x27, 0x8e, 0x98, 0x52, 0x42, 0x4d, 0xd7, 0xd7, 0x8e, 0xbf, 0xeb, 0x89, 0xe3, 0x0b, 0x5d, 0x3b, 0xb9, 0xd0,
0xce, 0xf4, 0xc4, 0xd7, 0x33, 0x3d, 0xf1, 0xfc, 0xe2, 0xea, 0xe0, 0x20, 0xd5, 0x36, 0x6a, 0x52, 0xb5, 0x6f, 0x17, 0xba, 0xf6, 0xfe, 0x52, 0x4f, 0x9c, 0x5c, 0xea, 0x89, 0x2f, 0x97, 0x7a, 0xe2,
0x09, 0xf7, 0x4a, 0x02, 0x8a, 0x2b, 0x6e, 0x66, 0xc4, 0x27, 0xe0, 0xc6, 0xdf, 0x00, 0x00, 0x00, 0x79, 0xff, 0xea, 0xe0, 0x20, 0xd5, 0x16, 0x6a, 0x50, 0x09, 0xf7, 0x4a, 0x02, 0x8a, 0x2b, 0x6e,
0xff, 0xff, 0x27, 0x75, 0x39, 0xf4, 0x32, 0x07, 0x00, 0x00, 0x64, 0xc4, 0xe7, 0xe0, 0xc6, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0x53, 0xed, 0x53, 0xe2, 0x3e,
0x07, 0x00, 0x00,
} }
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.
@ -745,10 +746,23 @@ func (m *VaultResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i-- i--
dAtA[i] = 0x1a dAtA[i] = 0x1a
} }
if m.VaultStrategy != 0 { if len(m.Strategies) > 0 {
i = encodeVarintQuery(dAtA, i, uint64(m.VaultStrategy)) dAtA3 := make([]byte, len(m.Strategies)*10)
var j2 int
for _, num := range m.Strategies {
for num >= 1<<7 {
dAtA3[j2] = uint8(uint64(num)&0x7f | 0x80)
num >>= 7
j2++
}
dAtA3[j2] = uint8(num)
j2++
}
i -= j2
copy(dAtA[i:], dAtA3[:j2])
i = encodeVarintQuery(dAtA, i, uint64(j2))
i-- i--
dAtA[i] = 0x10 dAtA[i] = 0x12
} }
if len(m.Denom) > 0 { if len(m.Denom) > 0 {
i -= len(m.Denom) i -= len(m.Denom)
@ -985,8 +999,12 @@ func (m *VaultResponse) Size() (n int) {
if l > 0 { if l > 0 {
n += 1 + l + sovQuery(uint64(l)) n += 1 + l + sovQuery(uint64(l))
} }
if m.VaultStrategy != 0 { if len(m.Strategies) > 0 {
n += 1 + sovQuery(uint64(m.VaultStrategy)) l = 0
for _, e := range m.Strategies {
l += sovQuery(uint64(e))
}
n += 1 + sovQuery(uint64(l)) + l
} }
l = len(m.TotalShares) l = len(m.TotalShares)
if l > 0 { if l > 0 {
@ -1429,23 +1447,73 @@ func (m *VaultResponse) Unmarshal(dAtA []byte) error {
m.Denom = string(dAtA[iNdEx:postIndex]) m.Denom = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex iNdEx = postIndex
case 2: case 2:
if wireType != 0 { if wireType == 0 {
return fmt.Errorf("proto: wrong wireType = %d for field VaultStrategy", wireType) var v StrategyType
} for shift := uint(0); ; shift += 7 {
m.VaultStrategy = 0 if shift >= 64 {
for shift := uint(0); ; shift += 7 { return ErrIntOverflowQuery
if shift >= 64 { }
return ErrIntOverflowQuery if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= StrategyType(b&0x7F) << shift
if b < 0x80 {
break
}
} }
if iNdEx >= l { m.Strategies = append(m.Strategies, v)
} else if wireType == 2 {
var packedLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowQuery
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
packedLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if packedLen < 0 {
return ErrInvalidLengthQuery
}
postIndex := iNdEx + packedLen
if postIndex < 0 {
return ErrInvalidLengthQuery
}
if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
b := dAtA[iNdEx] var elementCount int
iNdEx++ if elementCount != 0 && len(m.Strategies) == 0 {
m.VaultStrategy |= StrategyType(b&0x7F) << shift m.Strategies = make([]StrategyType, 0, elementCount)
if b < 0x80 {
break
} }
for iNdEx < postIndex {
var v StrategyType
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowQuery
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= StrategyType(b&0x7F) << shift
if b < 0x80 {
break
}
}
m.Strategies = append(m.Strategies, v)
}
} else {
return fmt.Errorf("proto: wrong wireType = %d for field Strategies", wireType)
} }
case 3: case 3:
if wireType != 2 { if wireType != 2 {

62
x/earn/types/strategy.go Normal file
View File

@ -0,0 +1,62 @@
package types
import (
"fmt"
"strings"
)
// IsValid returns true if the StrategyType status is valid and false otherwise.
func (s StrategyType) IsValid() bool {
return s == STRATEGY_TYPE_HARD || s == STRATEGY_TYPE_SAVINGS
}
// Validate returns an error if the StrategyType is invalid.
func (s StrategyType) Validate() error {
if !s.IsValid() {
return fmt.Errorf("invalid strategy %s", s)
}
return nil
}
// NewStrategyTypeFromString converts string to StrategyType type
func NewStrategyTypeFromString(str string) StrategyType {
switch strings.ToLower(str) {
case "hard":
return STRATEGY_TYPE_HARD
case "savings":
return STRATEGY_TYPE_SAVINGS
default:
return STRATEGY_TYPE_UNSPECIFIED
}
}
// StrategyTypes defines a slice of StrategyType
type StrategyTypes []StrategyType
// Validate returns an error if StrategyTypes are invalid.
func (strategies StrategyTypes) Validate() error {
if len(strategies) == 0 {
return fmt.Errorf("empty StrategyTypes")
}
if len(strategies) != 1 {
return fmt.Errorf("must have exactly one strategy type, multiple strategies are not supported")
}
uniqueStrategies := make(map[StrategyType]bool)
for _, strategy := range strategies {
if err := strategy.Validate(); err != nil {
return err
}
if _, found := uniqueStrategies[strategy]; found {
return fmt.Errorf("duplicate strategy %s", strategy)
}
uniqueStrategies[strategy] = true
}
return nil
}

View File

@ -0,0 +1,120 @@
package types_test
import (
"testing"
"github.com/kava-labs/kava/x/earn/types"
"github.com/stretchr/testify/require"
)
func TestNewStrategyTypeFromString(t *testing.T) {
tests := []struct {
name string
strategy string
expected types.StrategyType
}{
{
name: "hard",
strategy: "hard",
expected: types.STRATEGY_TYPE_HARD,
},
{
name: "savings",
strategy: "savings",
expected: types.STRATEGY_TYPE_SAVINGS,
},
{
name: "unspecified",
strategy: "not a valid strategy name",
expected: types.STRATEGY_TYPE_UNSPECIFIED,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
actual := types.NewStrategyTypeFromString(tc.strategy)
if actual != tc.expected {
t.Errorf("expected %s, got %s", tc.expected, actual)
}
})
}
}
func TestValidateStrategyTypes(t *testing.T) {
type errArgs struct {
expectPass bool
contains string
}
tests := []struct {
name string
strategies types.StrategyTypes
errArgs errArgs
}{
{
name: "valid - hard",
strategies: types.StrategyTypes{types.STRATEGY_TYPE_HARD},
errArgs: errArgs{
expectPass: true,
},
},
{
name: "valid - savings",
strategies: types.StrategyTypes{types.STRATEGY_TYPE_SAVINGS},
errArgs: errArgs{
expectPass: true,
},
},
{
name: "invalid - duplicate",
strategies: types.StrategyTypes{
types.STRATEGY_TYPE_SAVINGS,
types.STRATEGY_TYPE_SAVINGS,
},
errArgs: errArgs{
expectPass: false,
// This will change to duplicate error if multiple strategies are supported
contains: "must have exactly one strategy type, multiple strategies are not supported",
},
},
{
name: "invalid - unspecified",
strategies: types.StrategyTypes{types.STRATEGY_TYPE_UNSPECIFIED},
errArgs: errArgs{
expectPass: false,
contains: "invalid strategy",
},
},
{
name: "invalid - zero",
strategies: types.StrategyTypes{},
errArgs: errArgs{
expectPass: false,
contains: "empty StrategyTypes",
},
},
{
name: "invalid - more than 1",
strategies: types.StrategyTypes{
types.STRATEGY_TYPE_HARD,
types.STRATEGY_TYPE_SAVINGS,
},
errArgs: errArgs{
expectPass: false,
contains: "must have exactly one strategy type, multiple strategies are not supported",
},
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
err := tc.strategies.Validate()
if tc.errArgs.expectPass {
require.NoError(t, err)
} else {
require.Error(t, err)
require.Contains(t, err.Error(), tc.errArgs.contains)
}
})
}
}

View File

@ -37,6 +37,8 @@ type MsgDeposit struct {
// Amount represents the token to deposit. The vault corresponds to the denom // Amount represents the token to deposit. The vault corresponds to the denom
// of the amount coin. // of the amount coin.
Amount types.Coin `protobuf:"bytes,2,opt,name=amount,proto3" json:"amount"` Amount types.Coin `protobuf:"bytes,2,opt,name=amount,proto3" json:"amount"`
// Strategy is the vault strategy to use.
Strategy StrategyType `protobuf:"varint,3,opt,name=strategy,proto3,enum=kava.earn.v1beta1.StrategyType" json:"strategy,omitempty"`
} }
func (m *MsgDeposit) Reset() { *m = MsgDeposit{} } func (m *MsgDeposit) Reset() { *m = MsgDeposit{} }
@ -124,6 +126,8 @@ type MsgWithdraw struct {
// Amount represents the token to withdraw. The vault corresponds to the denom // Amount represents the token to withdraw. The vault corresponds to the denom
// of the amount coin. // of the amount coin.
Amount types.Coin `protobuf:"bytes,2,opt,name=amount,proto3" json:"amount"` Amount types.Coin `protobuf:"bytes,2,opt,name=amount,proto3" json:"amount"`
// Strategy is the vault strategy to use.
Strategy StrategyType `protobuf:"varint,3,opt,name=strategy,proto3,enum=kava.earn.v1beta1.StrategyType" json:"strategy,omitempty"`
} }
func (m *MsgWithdraw) Reset() { *m = MsgWithdraw{} } func (m *MsgWithdraw) Reset() { *m = MsgWithdraw{} }
@ -214,33 +218,35 @@ func init() {
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{
// 404 bytes of a gzipped FileDescriptorProto // 443 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, 0xc4, 0x93, 0x41, 0x8b, 0xd3, 0x40,
0xd4, 0x4f, 0x4d, 0x2c, 0xca, 0xd3, 0x2f, 0x33, 0x4c, 0x4a, 0x2d, 0x49, 0x34, 0xd4, 0x2f, 0xa9, 0x14, 0xc7, 0x33, 0x6e, 0xa9, 0xbb, 0x53, 0x10, 0x1c, 0xf7, 0xd0, 0x0d, 0xec, 0xb4, 0x14, 0x5c,
0xd0, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x04, 0xc9, 0xe9, 0x81, 0xe4, 0xf4, 0xa0, 0x72, 0x7a, 0x70, 0x27, 0x6c, 0x05, 0x05, 0xf7, 0xa2, 0xd5, 0x6b, 0x11, 0x53, 0x51, 0xf0, 0x22, 0x93,
0x52, 0x92, 0xc9, 0xf9, 0xc5, 0xb9, 0xf9, 0xc5, 0xf1, 0x60, 0x05, 0xfa, 0x10, 0x0e, 0x44, 0xb5, 0x66, 0x9c, 0x06, 0x37, 0x99, 0x30, 0x6f, 0x5a, 0xb7, 0xdf, 0xc0, 0xa3, 0x1f, 0xc1, 0xb3, 0x67,
0x94, 0x1c, 0x84, 0xa7, 0x9f, 0x94, 0x58, 0x9c, 0x0a, 0x37, 0x2b, 0x39, 0x3f, 0x33, 0x0f, 0x2a, 0xc1, 0xab, 0xc7, 0x3d, 0x2e, 0x9e, 0x3c, 0x89, 0xb4, 0x5f, 0x44, 0x92, 0x99, 0xa4, 0x42, 0xcb,
0x2f, 0x92, 0x9e, 0x9f, 0x9e, 0x0f, 0xd1, 0x07, 0x62, 0x41, 0x45, 0x65, 0x31, 0xed, 0x2f, 0x4b, 0x7a, 0x11, 0xf6, 0xf6, 0x26, 0xff, 0xdf, 0xff, 0xe5, 0xbd, 0x7f, 0x32, 0xd8, 0x7f, 0xcf, 0xe7,
0x2c, 0xcd, 0x29, 0x81, 0x48, 0x2b, 0x35, 0x33, 0x72, 0x71, 0xf9, 0x16, 0xa7, 0xbb, 0xa4, 0x16, 0x3c, 0x10, 0x5c, 0x67, 0xc1, 0xfc, 0x24, 0x12, 0x86, 0x9f, 0x04, 0xe6, 0x9c, 0xe5, 0x5a, 0x19,
0xe4, 0x17, 0x67, 0x96, 0x08, 0x99, 0x71, 0x71, 0xa6, 0x40, 0x98, 0xf9, 0x45, 0x12, 0x8c, 0x0a, 0x45, 0x6e, 0x17, 0x1a, 0x2b, 0x34, 0xe6, 0x34, 0xff, 0x60, 0xa2, 0x20, 0x55, 0xf0, 0xb6, 0x04,
0x8c, 0x1a, 0x9c, 0x4e, 0x12, 0x97, 0xb6, 0xe8, 0x8a, 0x40, 0x1d, 0xe2, 0x98, 0x92, 0x52, 0x94, 0x02, 0x7b, 0xb0, 0xb4, 0x4f, 0xed, 0x29, 0x88, 0x38, 0x88, 0xba, 0xd7, 0x44, 0x25, 0x99, 0xd3,
0x5a, 0x5c, 0x1c, 0x5c, 0x52, 0x94, 0x99, 0x97, 0x1e, 0x84, 0x50, 0x2a, 0x64, 0xce, 0xc5, 0x96, 0xf7, 0xa5, 0x92, 0xca, 0xfa, 0x8a, 0xca, 0x3d, 0xed, 0x6e, 0xbe, 0x1f, 0x8c, 0xe6, 0x46, 0xc8,
0x98, 0x9b, 0x5f, 0x9a, 0x57, 0x22, 0xc1, 0xa4, 0xc0, 0xa8, 0xc1, 0x6d, 0x24, 0xa9, 0x07, 0xd5, 0x85, 0x23, 0x0e, 0x37, 0x89, 0x39, 0x9f, 0x9d, 0x19, 0x2b, 0xf7, 0xbe, 0x23, 0x8c, 0x47, 0x20,
0x01, 0x72, 0x2c, 0xcc, 0x73, 0x7a, 0xce, 0xf9, 0x99, 0x79, 0x4e, 0x2c, 0x27, 0xee, 0xc9, 0x33, 0x9f, 0x89, 0x5c, 0x41, 0x62, 0xc8, 0x03, 0xbc, 0x17, 0xdb, 0x52, 0xe9, 0x36, 0xea, 0xa2, 0xfe,
0x04, 0x41, 0x95, 0x5b, 0xb1, 0x74, 0x2c, 0x90, 0x67, 0x50, 0x0a, 0xe4, 0x12, 0x42, 0x38, 0x22, 0xde, 0xb0, 0xfd, 0xe3, 0xeb, 0xf1, 0xbe, 0x1b, 0xf5, 0x49, 0x1c, 0x6b, 0x01, 0x30, 0x36, 0x3a,
0x28, 0xb5, 0xb8, 0x20, 0x3f, 0xaf, 0x38, 0x55, 0xc8, 0x9a, 0x8b, 0xad, 0x38, 0x23, 0xb1, 0x28, 0xc9, 0x64, 0xb8, 0x46, 0xc9, 0x43, 0xdc, 0xe4, 0xa9, 0x9a, 0x65, 0xa6, 0x7d, 0xa3, 0x8b, 0xfa,
0xb5, 0x18, 0xec, 0x12, 0x6e, 0x23, 0x59, 0x3d, 0x8c, 0xf0, 0xd2, 0x0b, 0x03, 0xf9, 0x25, 0x18, 0xad, 0xc1, 0x01, 0x73, 0x8e, 0x62, 0x9d, 0x6a, 0x7d, 0xf6, 0x54, 0x25, 0xd9, 0xb0, 0x71, 0xf1,
0xa4, 0x0a, 0x66, 0x30, 0x44, 0x8b, 0x52, 0x15, 0x17, 0xb7, 0x6f, 0x71, 0x7a, 0x78, 0x66, 0x49, 0xab, 0xe3, 0x85, 0x0e, 0x27, 0xa7, 0x78, 0xb7, 0x1a, 0xb8, 0xbd, 0xd3, 0x45, 0xfd, 0x5b, 0x83,
0x46, 0x4a, 0x51, 0x62, 0xb9, 0x90, 0x0e, 0x17, 0x4b, 0x5a, 0x51, 0x7e, 0x2e, 0x41, 0x3f, 0x81, 0x0e, 0xdb, 0xc8, 0x8d, 0x8d, 0x1d, 0xf2, 0x72, 0x91, 0x8b, 0xb0, 0x36, 0x3c, 0x6a, 0x7c, 0xfc,
0x55, 0x51, 0xea, 0x9d, 0x20, 0x2e, 0x61, 0x24, 0xbb, 0xa9, 0xe2, 0x1f, 0xa3, 0x55, 0x8c, 0x5c, 0xdc, 0xf1, 0x7a, 0x2f, 0x30, 0x59, 0x6f, 0x10, 0x0a, 0xc8, 0x55, 0x06, 0x82, 0x9c, 0xe2, 0x26,
0xcc, 0xbe, 0xc5, 0xe9, 0x42, 0xfe, 0x5c, 0xec, 0xb0, 0xc8, 0xc2, 0xa6, 0x1f, 0x11, 0x8c, 0x52, 0x4c, 0xb9, 0x16, 0x50, 0xae, 0xd1, 0x1a, 0x1c, 0x6e, 0x69, 0xfb, 0xaa, 0x08, 0x62, 0x5c, 0x50,
0xaa, 0x78, 0xa5, 0xe1, 0xae, 0x0a, 0xe2, 0xe2, 0x80, 0x87, 0x92, 0x1c, 0x76, 0x2d, 0x30, 0x79, 0xd5, 0x54, 0xd6, 0xd2, 0xfb, 0x86, 0x70, 0x6b, 0x04, 0xf2, 0x75, 0x62, 0xa6, 0xb1, 0xe6, 0x1f,
0x29, 0x35, 0xfc, 0xf2, 0x30, 0x33, 0x9d, 0x1c, 0x4e, 0x3c, 0x92, 0x63, 0xbc, 0xf0, 0x48, 0x8e, 0xc8, 0x3d, 0xdc, 0x78, 0xa7, 0x55, 0xfa, 0xcf, 0x44, 0x4a, 0xea, 0x5a, 0xc3, 0x08, 0xf1, 0x9d,
0xf1, 0xc1, 0x23, 0x39, 0xc6, 0x09, 0x8f, 0xe5, 0x18, 0x2e, 0x3c, 0x96, 0x63, 0xb8, 0xf1, 0x58, 0xbf, 0x06, 0xff, 0x2f, 0x69, 0x0c, 0xbe, 0x20, 0xbc, 0x33, 0x02, 0x49, 0x9e, 0xe3, 0x9b, 0xd5,
0x8e, 0x21, 0x4a, 0x2d, 0x3d, 0xb3, 0x24, 0xa3, 0x34, 0x49, 0x2f, 0x39, 0x3f, 0x57, 0x1f, 0x64, 0x7f, 0xb2, 0xcd, 0xbf, 0xfe, 0x08, 0xfe, 0xdd, 0x2b, 0xe5, 0x7a, 0xaa, 0x10, 0xef, 0xd6, 0x11,
0x96, 0x6e, 0x4e, 0x62, 0x52, 0x31, 0x98, 0xa5, 0x5f, 0x01, 0x49, 0xa5, 0x25, 0x95, 0x05, 0xa9, 0xd3, 0xed, 0x96, 0x4a, 0xf7, 0x8f, 0xae, 0xd6, 0xab, 0x9e, 0xc3, 0xc7, 0x17, 0x4b, 0x8a, 0x2e,
0xc5, 0x49, 0x6c, 0xe0, 0xe4, 0x69, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0xb4, 0xb0, 0x19, 0x18, 0x97, 0x14, 0xfd, 0x5e, 0x52, 0xf4, 0x69, 0x45, 0xbd, 0xcb, 0x15, 0xf5, 0x7e, 0xae, 0xa8, 0xf7,
0x3f, 0x03, 0x00, 0x00, 0xe6, 0x48, 0x26, 0x66, 0x3a, 0x8b, 0xd8, 0x44, 0xa5, 0x41, 0xd1, 0xeb, 0xf8, 0x8c, 0x47, 0x50,
0x56, 0xc1, 0xb9, 0xbd, 0x20, 0x66, 0x91, 0x0b, 0x88, 0x9a, 0xe5, 0xcd, 0xb8, 0xff, 0x27, 0x00,
0x00, 0xff, 0xff, 0x23, 0xf1, 0x3e, 0x54, 0xdc, 0x03, 0x00, 0x00,
} }
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.
@ -383,6 +389,11 @@ func (m *MsgDeposit) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i _ = i
var l int var l int
_ = l _ = l
if m.Strategy != 0 {
i = encodeVarintTx(dAtA, i, uint64(m.Strategy))
i--
dAtA[i] = 0x18
}
{ {
size, err := m.Amount.MarshalToSizedBuffer(dAtA[:i]) size, err := m.Amount.MarshalToSizedBuffer(dAtA[:i])
if err != nil { if err != nil {
@ -456,6 +467,11 @@ func (m *MsgWithdraw) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i _ = i
var l int var l int
_ = l _ = l
if m.Strategy != 0 {
i = encodeVarintTx(dAtA, i, uint64(m.Strategy))
i--
dAtA[i] = 0x18
}
{ {
size, err := m.Amount.MarshalToSizedBuffer(dAtA[:i]) size, err := m.Amount.MarshalToSizedBuffer(dAtA[:i])
if err != nil { if err != nil {
@ -532,6 +548,9 @@ func (m *MsgDeposit) Size() (n int) {
} }
l = m.Amount.Size() l = m.Amount.Size()
n += 1 + l + sovTx(uint64(l)) n += 1 + l + sovTx(uint64(l))
if m.Strategy != 0 {
n += 1 + sovTx(uint64(m.Strategy))
}
return n return n
} }
@ -558,6 +577,9 @@ func (m *MsgWithdraw) Size() (n int) {
} }
l = m.Amount.Size() l = m.Amount.Size()
n += 1 + l + sovTx(uint64(l)) n += 1 + l + sovTx(uint64(l))
if m.Strategy != 0 {
n += 1 + sovTx(uint64(m.Strategy))
}
return n return n
} }
@ -672,6 +694,25 @@ func (m *MsgDeposit) Unmarshal(dAtA []byte) error {
return err return err
} }
iNdEx = postIndex iNdEx = postIndex
case 3:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Strategy", wireType)
}
m.Strategy = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTx
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Strategy |= StrategyType(b&0x7F) << shift
if b < 0x80 {
break
}
}
default: default:
iNdEx = preIndex iNdEx = preIndex
skippy, err := skipTx(dAtA[iNdEx:]) skippy, err := skipTx(dAtA[iNdEx:])
@ -870,6 +911,25 @@ func (m *MsgWithdraw) Unmarshal(dAtA []byte) error {
return err return err
} }
iNdEx = postIndex iNdEx = postIndex
case 3:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Strategy", wireType)
}
m.Strategy = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTx
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Strategy |= StrategyType(b&0x7F) << shift
if b < 0x80 {
break
}
}
default: default:
iNdEx = preIndex iNdEx = preIndex
skippy, err := skipTx(dAtA[iNdEx:]) skippy, err := skipTx(dAtA[iNdEx:])

View File

@ -86,15 +86,17 @@ func (vsrs VaultShareRecords) Validate() error {
} }
// NewAllowedVaults returns a new AllowedVaults with the given denom and strategy type. // NewAllowedVaults returns a new AllowedVaults with the given denom and strategy type.
func NewAllowedVault(denom string, strategyType StrategyType) AllowedVault { func NewAllowedVault(denom string, strategyTypes ...StrategyType) AllowedVault {
return AllowedVault{ return AllowedVault{
Denom: denom, Denom: denom,
VaultStrategy: strategyType, Strategies: strategyTypes,
} }
} }
// AllowedVaults is a slice of AllowedVault.
type AllowedVaults []AllowedVault type AllowedVaults []AllowedVault
// Validate returns an error if the AllowedVaults is invalid.
func (a AllowedVaults) Validate() error { func (a AllowedVaults) Validate() error {
denoms := make(map[string]bool) denoms := make(map[string]bool)
@ -109,17 +111,27 @@ func (a AllowedVaults) Validate() error {
denoms[v.Denom] = true denoms[v.Denom] = true
} }
return nil return nil
} }
// Validate returns an error if the AllowedVault is invalid
func (a *AllowedVault) Validate() error { func (a *AllowedVault) Validate() error {
if err := sdk.ValidateDenom(a.Denom); err != nil { if err := sdk.ValidateDenom(a.Denom); err != nil {
return sdkerrors.Wrap(ErrInvalidVaultDenom, err.Error()) return sdkerrors.Wrap(ErrInvalidVaultDenom, err.Error())
} }
if a.VaultStrategy == STRATEGY_TYPE_UNSPECIFIED { return a.Strategies.Validate()
return ErrInvalidVaultStrategy }
// IsStrategyAllowed returns true if the given strategy type is allowed for the
// vault.
func (a *AllowedVault) IsStrategyAllowed(strategy StrategyType) bool {
for _, s := range a.Strategies {
if s == strategy {
return true
}
} }
return nil return false
} }

View File

@ -32,7 +32,7 @@ type AllowedVault struct {
// Denom is the only supported denomination of the vault for deposits and withdrawals. // 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"` Denom string `protobuf:"bytes,1,opt,name=denom,proto3" json:"denom,omitempty"`
// VaultStrategy is the strategy used for this vault. // VaultStrategy is the strategy used for this vault.
VaultStrategy StrategyType `protobuf:"varint,2,opt,name=vault_strategy,json=vaultStrategy,proto3,enum=kava.earn.v1beta1.StrategyType" json:"vault_strategy,omitempty"` Strategies StrategyTypes `protobuf:"varint,2,rep,packed,name=strategies,proto3,enum=kava.earn.v1beta1.StrategyType,castrepeated=StrategyTypes" json:"strategies,omitempty"`
} }
func (m *AllowedVault) Reset() { *m = AllowedVault{} } func (m *AllowedVault) Reset() { *m = AllowedVault{} }
@ -75,11 +75,11 @@ func (m *AllowedVault) GetDenom() string {
return "" return ""
} }
func (m *AllowedVault) GetVaultStrategy() StrategyType { func (m *AllowedVault) GetStrategies() StrategyTypes {
if m != nil { if m != nil {
return m.VaultStrategy return m.Strategies
} }
return STRATEGY_TYPE_UNSPECIFIED return nil
} }
// VaultRecord is the state of a vault. // VaultRecord is the state of a vault.
@ -238,35 +238,36 @@ func init() {
func init() { proto.RegisterFile("kava/earn/v1beta1/vault.proto", fileDescriptor_884eb89509fbdc04) } func init() { proto.RegisterFile("kava/earn/v1beta1/vault.proto", fileDescriptor_884eb89509fbdc04) }
var fileDescriptor_884eb89509fbdc04 = []byte{ var fileDescriptor_884eb89509fbdc04 = []byte{
// 445 bytes of a gzipped FileDescriptorProto // 450 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x52, 0x31, 0x8f, 0xd3, 0x30, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0x31, 0x6f, 0xd3, 0x40,
0x18, 0x4d, 0x8e, 0xa3, 0x52, 0x9d, 0x72, 0x82, 0xdc, 0x0d, 0xc7, 0x49, 0x4d, 0xa2, 0x0c, 0xa8, 0x14, 0xc7, 0xed, 0x52, 0x22, 0xf5, 0x1c, 0x10, 0x75, 0x3b, 0x84, 0x4a, 0xb5, 0x23, 0x0f, 0xa8,
0x4b, 0x12, 0xb5, 0x6c, 0x88, 0x81, 0x46, 0x55, 0x85, 0x18, 0xd3, 0xc2, 0xc0, 0x52, 0x39, 0x8e, 0x8b, 0x6d, 0xb5, 0x6c, 0x88, 0x81, 0x58, 0x15, 0x42, 0x8c, 0xd7, 0xc2, 0xc0, 0x52, 0x9d, 0xcf,
0x49, 0xab, 0x26, 0x71, 0x14, 0xbb, 0x85, 0x2c, 0xfc, 0x06, 0x46, 0x46, 0x66, 0xe6, 0xfe, 0x06, 0x87, 0x6b, 0xd5, 0xf6, 0x45, 0x7e, 0x97, 0x90, 0x2c, 0x7c, 0x06, 0x46, 0x46, 0xe6, 0xcc, 0xf9,
0xd4, 0xb1, 0xea, 0x84, 0x18, 0x0a, 0x6a, 0xff, 0x05, 0x13, 0xb2, 0xe3, 0x12, 0xa4, 0x82, 0xb8, 0x0c, 0x28, 0x63, 0x94, 0x09, 0x31, 0x24, 0x28, 0xf9, 0x16, 0x4c, 0xe8, 0xce, 0x27, 0x1c, 0x29,
0x29, 0xf6, 0xfb, 0xde, 0x7b, 0xdf, 0xfb, 0xf2, 0x19, 0xb4, 0xe7, 0x70, 0x09, 0x3d, 0x0c, 0x8b, 0x20, 0x98, 0xec, 0xf7, 0x7f, 0xef, 0xfd, 0xde, 0xff, 0xdd, 0x1d, 0x3a, 0xbd, 0x23, 0x43, 0x12,
0xcc, 0x5b, 0x76, 0x43, 0xcc, 0x60, 0xd7, 0x5b, 0xc2, 0x45, 0xc2, 0xdc, 0xbc, 0x20, 0x8c, 0xe8, 0x32, 0x52, 0x95, 0xe1, 0xf0, 0x3c, 0x66, 0x82, 0x9c, 0x87, 0x43, 0x32, 0xc8, 0x45, 0xd0, 0xaf,
0x0f, 0x78, 0xd9, 0xe5, 0x65, 0x57, 0x96, 0x6f, 0x1e, 0x22, 0x42, 0x53, 0x42, 0x27, 0x82, 0xe0, 0xb8, 0xe0, 0xf6, 0xa1, 0x4c, 0x07, 0x32, 0x1d, 0xe8, 0xf4, 0xc9, 0x63, 0xca, 0xa1, 0xe0, 0x70,
0x55, 0x97, 0x8a, 0x7d, 0x63, 0x54, 0x37, 0x2f, 0x84, 0x14, 0xff, 0xb6, 0x43, 0x64, 0x96, 0xc9, 0xa3, 0x0a, 0xc2, 0x3a, 0xa8, 0xab, 0x4f, 0x9c, 0x3a, 0x0a, 0x63, 0x02, 0xec, 0x37, 0x8e, 0xf2,
0xfa, 0x55, 0x4c, 0x62, 0x52, 0xe9, 0xf8, 0x49, 0xa2, 0xd6, 0x69, 0x04, 0xca, 0x0a, 0xc8, 0x70, 0xac, 0xd4, 0xf9, 0xe3, 0x94, 0xa7, 0xbc, 0xee, 0x93, 0x7f, 0x5a, 0xed, 0xee, 0x5a, 0x00, 0x51,
0x5c, 0x56, 0x0c, 0x3b, 0x01, 0xad, 0x7e, 0x92, 0x90, 0xb7, 0x38, 0x7a, 0xc5, 0xb3, 0xe9, 0x57, 0x11, 0xc1, 0xd2, 0x71, 0x5d, 0xe1, 0x8d, 0x50, 0xbb, 0x97, 0xe7, 0xfc, 0x03, 0x4b, 0xde, 0x4a,
0xe0, 0x6e, 0x84, 0x33, 0x92, 0x5e, 0xab, 0x96, 0xda, 0x69, 0x06, 0xd5, 0x45, 0x1f, 0x82, 0x0b, 0x6f, 0xf6, 0x31, 0xba, 0x9f, 0xb0, 0x92, 0x17, 0x1d, 0xb3, 0x6b, 0x9e, 0x1d, 0xe0, 0x3a, 0xb0,
0x11, 0x7d, 0x72, 0x54, 0x5f, 0x9f, 0x59, 0x6a, 0xe7, 0xa2, 0x67, 0xba, 0x27, 0x43, 0xb8, 0x23, 0x31, 0x42, 0xba, 0x2f, 0x63, 0xd0, 0xd9, 0xeb, 0xde, 0x3b, 0x7b, 0x78, 0xe1, 0x06, 0x3b, 0x0b,
0x49, 0x19, 0x97, 0x39, 0x0e, 0xee, 0x09, 0xd9, 0x11, 0xb2, 0x5f, 0x02, 0x4d, 0xb4, 0x09, 0x30, 0x04, 0x57, 0x1a, 0x7e, 0x3d, 0xee, 0xb3, 0xe8, 0x70, 0xb2, 0x72, 0x1f, 0x6c, 0x2b, 0x80, 0xb7,
0x22, 0x45, 0xa4, 0x0f, 0x41, 0x8b, 0x11, 0x06, 0x93, 0x09, 0x9d, 0xc2, 0x02, 0x53, 0xd1, 0x53, 0x28, 0xde, 0x1b, 0x64, 0xa9, 0x91, 0x98, 0x51, 0x5e, 0x25, 0xf6, 0x4b, 0xd4, 0x16, 0x5c, 0x90,
0xeb, 0xb5, 0xff, 0x62, 0x2a, 0x54, 0x23, 0xce, 0xf2, 0xcf, 0xd7, 0x3b, 0x53, 0x09, 0x34, 0x21, 0xfc, 0x06, 0x6e, 0x49, 0xc5, 0x40, 0xcd, 0xb7, 0x2e, 0x4e, 0xff, 0x30, 0x44, 0x75, 0x5d, 0xc9,
0x14, 0x08, 0xb5, 0xbf, 0xa8, 0xe0, 0x7e, 0xcd, 0x90, 0xe6, 0x6f, 0x40, 0x33, 0xc2, 0x39, 0xa1, 0xaa, 0x68, 0x7f, 0xb6, 0x74, 0x0d, 0x6c, 0xa9, 0x46, 0xa5, 0x80, 0xf7, 0xd5, 0x44, 0x8f, 0x9a,
0x33, 0x46, 0x0a, 0xe1, 0xdc, 0xf2, 0x9f, 0xff, 0xdc, 0x99, 0x4e, 0x3c, 0x63, 0xd3, 0x45, 0xe8, 0x0a, 0x0d, 0x7f, 0x8f, 0x0e, 0x12, 0xd6, 0xe7, 0x90, 0x09, 0x5e, 0x29, 0x72, 0x3b, 0x7a, 0xf5,
0x22, 0x92, 0xca, 0x3f, 0x2c, 0x3f, 0x0e, 0x8d, 0xe6, 0x1e, 0x2b, 0x73, 0x4c, 0xdd, 0x3e, 0x42, 0x73, 0xe9, 0xfa, 0x69, 0x26, 0x6e, 0x07, 0x71, 0x40, 0x79, 0xa1, 0x4f, 0x5b, 0x7f, 0x7c, 0x48,
0xfd, 0x28, 0x2a, 0x30, 0xa5, 0xdb, 0x95, 0x73, 0x29, 0xf7, 0x20, 0x11, 0xbf, 0x64, 0x98, 0x06, 0xee, 0x42, 0x21, 0x2d, 0x07, 0x3d, 0x4a, 0x7b, 0x49, 0x52, 0x31, 0x80, 0xc5, 0xd4, 0x3f, 0xd2,
0xb5, 0xb5, 0xfe, 0x02, 0x34, 0x64, 0xfc, 0x33, 0xeb, 0xce, 0xff, 0xe3, 0x5f, 0xf2, 0xf8, 0x9f, 0x77, 0xa2, 0x95, 0x68, 0x2c, 0x18, 0xe0, 0x06, 0x6d, 0xbf, 0x46, 0x2d, 0x6d, 0x5f, 0x9e, 0xd1,
0xbf, 0x9b, 0x5a, 0x8d, 0xd1, 0x40, 0x3a, 0xd8, 0xef, 0x01, 0xa8, 0xe1, 0x7f, 0xec, 0x62, 0x0c, 0x3f, 0xed, 0x1f, 0x49, 0xfb, 0x93, 0x95, 0x6b, 0x35, 0x1a, 0x60, 0x4d, 0xf0, 0x3e, 0x22, 0xd4,
0x1a, 0x30, 0x25, 0x8b, 0x8c, 0x89, 0x1d, 0x34, 0xfd, 0xa7, 0xdc, 0xf0, 0xdb, 0xce, 0x7c, 0x74, 0xc8, 0x7f, 0xb9, 0x97, 0x6b, 0xd4, 0x22, 0x05, 0x1f, 0x94, 0xa2, 0xb3, 0x27, 0xe5, 0xe8, 0xb9,
0x8b, 0xc1, 0x06, 0x18, 0x6d, 0x57, 0x0e, 0x90, 0x13, 0x0d, 0x30, 0x0a, 0xa4, 0xd7, 0x93, 0xf3, 0x04, 0x7e, 0x5f, 0xba, 0x4f, 0xfe, 0x63, 0xb1, 0x4b, 0x46, 0x17, 0x53, 0x1f, 0xe9, 0x8d, 0x2e,
0x8f, 0x9f, 0x4c, 0xc5, 0x7f, 0xb6, 0xde, 0x1b, 0xea, 0x66, 0x6f, 0xa8, 0x3f, 0xf6, 0x86, 0xfa, 0x19, 0xc5, 0x9a, 0xf5, 0x6c, 0xff, 0xf3, 0x17, 0xd7, 0x88, 0x5e, 0xcc, 0xd6, 0x8e, 0x39, 0x5f,
0xe1, 0x60, 0x28, 0x9b, 0x83, 0xa1, 0x7c, 0x3d, 0x18, 0xca, 0xeb, 0x3f, 0xdd, 0xf9, 0x7c, 0x4e, 0x3b, 0xe6, 0x8f, 0xb5, 0x63, 0x7e, 0xda, 0x38, 0xc6, 0x7c, 0xe3, 0x18, 0xdf, 0x36, 0x8e, 0xf1,
0x02, 0x43, 0x2a, 0x4e, 0xde, 0xbb, 0xea, 0x81, 0x89, 0x0e, 0x61, 0x43, 0x3c, 0xab, 0xc7, 0xbf, 0x6e, 0x9b, 0x2e, 0xf7, 0xf3, 0x73, 0x12, 0x83, 0xfa, 0x0b, 0x47, 0xf5, 0x63, 0x53, 0x13, 0xe2,
0x02, 0x00, 0x00, 0xff, 0xff, 0x19, 0x75, 0x6f, 0x0e, 0xfd, 0x02, 0x00, 0x00, 0x96, 0x7a, 0x62, 0x4f, 0x7f, 0x05, 0x00, 0x00, 0xff, 0xff, 0xae, 0x23, 0x43, 0xb6, 0x09, 0x03,
0x00, 0x00,
} }
func (m *AllowedVault) Marshal() (dAtA []byte, err error) { func (m *AllowedVault) Marshal() (dAtA []byte, err error) {
@ -289,10 +290,23 @@ func (m *AllowedVault) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i _ = i
var l int var l int
_ = l _ = l
if m.VaultStrategy != 0 { if len(m.Strategies) > 0 {
i = encodeVarintVault(dAtA, i, uint64(m.VaultStrategy)) dAtA2 := make([]byte, len(m.Strategies)*10)
var j1 int
for _, num := range m.Strategies {
for num >= 1<<7 {
dAtA2[j1] = uint8(uint64(num)&0x7f | 0x80)
num >>= 7
j1++
}
dAtA2[j1] = uint8(num)
j1++
}
i -= j1
copy(dAtA[i:], dAtA2[:j1])
i = encodeVarintVault(dAtA, i, uint64(j1))
i-- i--
dAtA[i] = 0x10 dAtA[i] = 0x12
} }
if len(m.Denom) > 0 { if len(m.Denom) > 0 {
i -= len(m.Denom) i -= len(m.Denom)
@ -442,8 +456,12 @@ func (m *AllowedVault) Size() (n int) {
if l > 0 { if l > 0 {
n += 1 + l + sovVault(uint64(l)) n += 1 + l + sovVault(uint64(l))
} }
if m.VaultStrategy != 0 { if len(m.Strategies) > 0 {
n += 1 + sovVault(uint64(m.VaultStrategy)) l = 0
for _, e := range m.Strategies {
l += sovVault(uint64(e))
}
n += 1 + sovVault(uint64(l)) + l
} }
return n return n
} }
@ -561,23 +579,73 @@ func (m *AllowedVault) Unmarshal(dAtA []byte) error {
m.Denom = string(dAtA[iNdEx:postIndex]) m.Denom = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex iNdEx = postIndex
case 2: case 2:
if wireType != 0 { if wireType == 0 {
return fmt.Errorf("proto: wrong wireType = %d for field VaultStrategy", wireType) var v StrategyType
} for shift := uint(0); ; shift += 7 {
m.VaultStrategy = 0 if shift >= 64 {
for shift := uint(0); ; shift += 7 { return ErrIntOverflowVault
if shift >= 64 { }
return ErrIntOverflowVault if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= StrategyType(b&0x7F) << shift
if b < 0x80 {
break
}
} }
if iNdEx >= l { m.Strategies = append(m.Strategies, v)
} else if wireType == 2 {
var packedLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowVault
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
packedLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if packedLen < 0 {
return ErrInvalidLengthVault
}
postIndex := iNdEx + packedLen
if postIndex < 0 {
return ErrInvalidLengthVault
}
if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
b := dAtA[iNdEx] var elementCount int
iNdEx++ if elementCount != 0 && len(m.Strategies) == 0 {
m.VaultStrategy |= StrategyType(b&0x7F) << shift m.Strategies = make([]StrategyType, 0, elementCount)
if b < 0x80 {
break
} }
for iNdEx < postIndex {
var v StrategyType
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowVault
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= StrategyType(b&0x7F) << shift
if b < 0x80 {
break
}
}
m.Strategies = append(m.Strategies, v)
}
} else {
return fmt.Errorf("proto: wrong wireType = %d for field Strategies", wireType)
} }
default: default:
iNdEx = preIndex iNdEx = preIndex

View File

@ -208,12 +208,12 @@ func TestAllowedVaultsValidate(t *testing.T) {
name: "valid vault share records", name: "valid vault share records",
vaultRecords: types.AllowedVaults{ vaultRecords: types.AllowedVaults{
{ {
Denom: "usdx", Denom: "usdx",
VaultStrategy: types.STRATEGY_TYPE_HARD, Strategies: []types.StrategyType{types.STRATEGY_TYPE_HARD},
}, },
{ {
Denom: "busd", Denom: "busd",
VaultStrategy: types.STRATEGY_TYPE_HARD, Strategies: []types.StrategyType{types.STRATEGY_TYPE_HARD},
}, },
}, },
errArgs: errArgs{ errArgs: errArgs{
@ -224,12 +224,12 @@ func TestAllowedVaultsValidate(t *testing.T) {
name: "invalid - duplicate denom", name: "invalid - duplicate denom",
vaultRecords: types.AllowedVaults{ vaultRecords: types.AllowedVaults{
{ {
Denom: "usdx", Denom: "usdx",
VaultStrategy: types.STRATEGY_TYPE_HARD, Strategies: []types.StrategyType{types.STRATEGY_TYPE_HARD},
}, },
{ {
Denom: "usdx", Denom: "usdx",
VaultStrategy: types.STRATEGY_TYPE_HARD, Strategies: []types.StrategyType{types.STRATEGY_TYPE_HARD},
}, },
}, },
errArgs: errArgs{ errArgs: errArgs{
@ -241,8 +241,8 @@ func TestAllowedVaultsValidate(t *testing.T) {
name: "invalid - invalid denom", name: "invalid - invalid denom",
vaultRecords: types.AllowedVaults{ vaultRecords: types.AllowedVaults{
{ {
Denom: "", Denom: "",
VaultStrategy: types.STRATEGY_TYPE_HARD, Strategies: []types.StrategyType{types.STRATEGY_TYPE_HARD},
}, },
}, },
errArgs: errArgs{ errArgs: errArgs{
@ -254,13 +254,13 @@ func TestAllowedVaultsValidate(t *testing.T) {
name: "invalid - invalid strategy", name: "invalid - invalid strategy",
vaultRecords: types.AllowedVaults{ vaultRecords: types.AllowedVaults{
{ {
Denom: "usdx", Denom: "usdx",
VaultStrategy: types.STRATEGY_TYPE_UNSPECIFIED, Strategies: []types.StrategyType{types.STRATEGY_TYPE_UNSPECIFIED},
}, },
}, },
errArgs: errArgs{ errArgs: errArgs{
expectPass: false, expectPass: false,
contains: "invalid vault strategy", contains: "invalid strategy STRATEGY_TYPE_UNSPECIFIED",
}, },
}, },
} }