mirror of
				https://github.com/0glabs/0g-chain.git
				synced 2025-11-04 04:57:27 +00:00 
			
		
		
		
	Update Earn vaults to use sdk.Dec shares (#1283)
* Change vault supply to shares * Update deposit shares * Use shares instead of supplied * Update tests, fix share calculation * Pass hard and savings keeper as pointer to earn keeper * Update remaining failing test * Add different share price test, fix comment for share price * Add shares amount to events * Additional share tests, use share to asset conversion for withdraw amount * Update VaultTotalValue test * Use sdk.Dec for vault shares instead of sdk.Int * Add test for expensive 20:1 shares * Update ConvertToShares comment for division, remove redundant test * Add vault share tests
This commit is contained in:
		
							parent
							
								
									fe89ba938d
								
							
						
					
					
						commit
						b5e162a930
					
				@ -604,8 +604,8 @@ func NewApp(
 | 
			
		||||
		earnSubspace,
 | 
			
		||||
		app.accountKeeper,
 | 
			
		||||
		app.bankKeeper,
 | 
			
		||||
		hardKeeper,
 | 
			
		||||
		savingsKeeper,
 | 
			
		||||
		&hardKeeper,
 | 
			
		||||
		&savingsKeeper,
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	// create committee keeper with router
 | 
			
		||||
 | 
			
		||||
@ -184,6 +184,7 @@
 | 
			
		||||
- [kava/earn/v1beta1/vault.proto](#kava/earn/v1beta1/vault.proto)
 | 
			
		||||
    - [AllowedVault](#kava.earn.v1beta1.AllowedVault)
 | 
			
		||||
    - [VaultRecord](#kava.earn.v1beta1.VaultRecord)
 | 
			
		||||
    - [VaultShare](#kava.earn.v1beta1.VaultShare)
 | 
			
		||||
    - [VaultShareRecord](#kava.earn.v1beta1.VaultShareRecord)
 | 
			
		||||
  
 | 
			
		||||
- [kava/earn/v1beta1/params.proto](#kava/earn/v1beta1/params.proto)
 | 
			
		||||
@ -198,8 +199,6 @@
 | 
			
		||||
    - [QueryDepositsResponse](#kava.earn.v1beta1.QueryDepositsResponse)
 | 
			
		||||
    - [QueryParamsRequest](#kava.earn.v1beta1.QueryParamsRequest)
 | 
			
		||||
    - [QueryParamsResponse](#kava.earn.v1beta1.QueryParamsResponse)
 | 
			
		||||
    - [QueryTotalDepositedRequest](#kava.earn.v1beta1.QueryTotalDepositedRequest)
 | 
			
		||||
    - [QueryTotalDepositedResponse](#kava.earn.v1beta1.QueryTotalDepositedResponse)
 | 
			
		||||
    - [QueryVaultsRequest](#kava.earn.v1beta1.QueryVaultsRequest)
 | 
			
		||||
    - [QueryVaultsResponse](#kava.earn.v1beta1.QueryVaultsResponse)
 | 
			
		||||
    - [VaultResponse](#kava.earn.v1beta1.VaultResponse)
 | 
			
		||||
@ -2817,14 +2816,28 @@ modified via parameter governance.
 | 
			
		||||
<a name="kava.earn.v1beta1.VaultRecord"></a>
 | 
			
		||||
 | 
			
		||||
### VaultRecord
 | 
			
		||||
VaultRecord is the state of a vault and is used to store the state of a
 | 
			
		||||
vault.
 | 
			
		||||
VaultRecord is the state of a vault.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| Field | Type | Label | Description |
 | 
			
		||||
| ----- | ---- | ----- | ----------- |
 | 
			
		||||
| `denom` | [string](#string) |  | Denom is the only supported denomination of the vault for deposits and withdrawals. |
 | 
			
		||||
| `total_supply` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) |  | TotalSupply is the total supply of the vault, denominated **only** in the user deposit/withdrawal denom, must be the same as the Denom field. |
 | 
			
		||||
| `total_shares` | [VaultShare](#kava.earn.v1beta1.VaultShare) |  | TotalShares is the total distributed number of shares in the vault. |
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<a name="kava.earn.v1beta1.VaultShare"></a>
 | 
			
		||||
 | 
			
		||||
### VaultShare
 | 
			
		||||
VaultShare defines shares of a vault owned by a depositor.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| Field | Type | Label | Description |
 | 
			
		||||
| ----- | ---- | ----- | ----------- |
 | 
			
		||||
| `denom` | [string](#string) |  |  |
 | 
			
		||||
| `amount` | [string](#string) |  |  |
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -2840,7 +2853,7 @@ VaultShareRecord defines the vault shares owned by a depositor.
 | 
			
		||||
| Field | Type | Label | Description |
 | 
			
		||||
| ----- | ---- | ----- | ----------- |
 | 
			
		||||
| `depositor` | [bytes](#bytes) |  | Depositor represents the owner of the shares |
 | 
			
		||||
| `amount_supplied` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | AmountSupplied represents the total amount a depositor has supplied to the vault. The vault is determined by the coin denom. |
 | 
			
		||||
| `shares` | [VaultShare](#kava.earn.v1beta1.VaultShare) | repeated | Shares represent the vault shares owned by the depositor. |
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -2936,7 +2949,7 @@ DepositResponse defines a deposit query response type.
 | 
			
		||||
| Field | Type | Label | Description |
 | 
			
		||||
| ----- | ---- | ----- | ----------- |
 | 
			
		||||
| `depositor` | [string](#string) |  | depositor represents the owner of the deposit. |
 | 
			
		||||
| `amount_supplied` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | Amount represents the amount supplied to vaults. |
 | 
			
		||||
| `shares` | [VaultShare](#kava.earn.v1beta1.VaultShare) | repeated | Shares represent the issued shares from their corresponding vaults. |
 | 
			
		||||
| `value` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | Value represents the total accumulated value of denom coins supplied to vaults. This may be greater than or equal to amount_supplied depending on the strategy. |
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -3002,36 +3015,6 @@ QueryParamsResponse defines the response type for querying x/earn parameters.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<a name="kava.earn.v1beta1.QueryTotalDepositedRequest"></a>
 | 
			
		||||
 | 
			
		||||
### QueryTotalDepositedRequest
 | 
			
		||||
QueryTotalDepositedRequest is the request type for the Query/TotalDeposited RPC method.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| Field | Type | Label | Description |
 | 
			
		||||
| ----- | ---- | ----- | ----------- |
 | 
			
		||||
| `denom` | [string](#string) |  | denom represents the vault denom to query total deposited amount for. |
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<a name="kava.earn.v1beta1.QueryTotalDepositedResponse"></a>
 | 
			
		||||
 | 
			
		||||
### QueryTotalDepositedResponse
 | 
			
		||||
QueryTotalDepositedResponse is the response type for the Query/TotalDeposited RPC method.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| Field | Type | Label | Description |
 | 
			
		||||
| ----- | ---- | ----- | ----------- |
 | 
			
		||||
| `supplied_coins` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated |  |
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<a name="kava.earn.v1beta1.QueryVaultsRequest"></a>
 | 
			
		||||
 | 
			
		||||
### QueryVaultsRequest
 | 
			
		||||
@ -3072,7 +3055,7 @@ VaultResponse is the response type for a 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. |
 | 
			
		||||
| `total_supplied` | [string](#string) |  | TotalSupplied is the total amount of denom coins supplied to the vault. |
 | 
			
		||||
| `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. |
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -3096,7 +3079,6 @@ Query defines the gRPC querier service for earn module
 | 
			
		||||
| `Params` | [QueryParamsRequest](#kava.earn.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#kava.earn.v1beta1.QueryParamsResponse) | Params queries all parameters of the earn module. | GET|/kava/earn/v1beta1/params|
 | 
			
		||||
| `Vaults` | [QueryVaultsRequest](#kava.earn.v1beta1.QueryVaultsRequest) | [QueryVaultsResponse](#kava.earn.v1beta1.QueryVaultsResponse) | Vaults queries vaults based on vault denom | GET|/kava/earn/v1beta1/vaults/{denom}|
 | 
			
		||||
| `Deposits` | [QueryDepositsRequest](#kava.earn.v1beta1.QueryDepositsRequest) | [QueryDepositsResponse](#kava.earn.v1beta1.QueryDepositsResponse) | Deposits queries deposit details based on owner address and vault | GET|/kava/earn/v1beta1/deposits|
 | 
			
		||||
| `TotalDeposited` | [QueryTotalDepositedRequest](#kava.earn.v1beta1.QueryTotalDepositedRequest) | [QueryTotalDepositedResponse](#kava.earn.v1beta1.QueryTotalDepositedResponse) | TotalDeposited queries total deposited amount for each vault. | GET|/kava/earn/v1beta1/total-deposited/{denom}|
 | 
			
		||||
 | 
			
		||||
 <!-- end services -->
 | 
			
		||||
 | 
			
		||||
@ -3131,6 +3113,11 @@ MsgDeposit represents a message for depositing assedts into a vault
 | 
			
		||||
MsgDepositResponse defines the Msg/Deposit response type.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| Field | Type | Label | Description |
 | 
			
		||||
| ----- | ---- | ----- | ----------- |
 | 
			
		||||
| `shares` | [VaultShare](#kava.earn.v1beta1.VaultShare) |  |  |
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -3157,6 +3144,11 @@ MsgWithdraw represents a message for withdrawing liquidity from a vault
 | 
			
		||||
MsgWithdrawResponse defines the Msg/Withdraw response type.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| Field | Type | Label | Description |
 | 
			
		||||
| ----- | ---- | ----- | ----------- |
 | 
			
		||||
| `shares` | [VaultShare](#kava.earn.v1beta1.VaultShare) |  |  |
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -11,6 +11,7 @@ import "gogoproto/gogo.proto";
 | 
			
		||||
import "google/api/annotations.proto";
 | 
			
		||||
import "kava/earn/v1beta1/params.proto";
 | 
			
		||||
import "kava/earn/v1beta1/strategy.proto";
 | 
			
		||||
import "kava/earn/v1beta1/vault.proto";
 | 
			
		||||
 | 
			
		||||
// Query defines the gRPC querier service for earn module
 | 
			
		||||
service Query {
 | 
			
		||||
@ -28,11 +29,6 @@ service Query {
 | 
			
		||||
  rpc Deposits(QueryDepositsRequest) returns (QueryDepositsResponse) {
 | 
			
		||||
    option (google.api.http).get = "/kava/earn/v1beta1/deposits";
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // TotalDeposited queries total deposited amount for each vault.
 | 
			
		||||
  rpc TotalDeposited(QueryTotalDepositedRequest) returns (QueryTotalDepositedResponse) {
 | 
			
		||||
    option (google.api.http).get = "/kava/earn/v1beta1/total-deposited/{denom}";
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// QueryParamsRequest defines the request type for querying x/earn parameters.
 | 
			
		||||
@ -40,7 +36,6 @@ message QueryParamsRequest {}
 | 
			
		||||
 | 
			
		||||
// QueryParamsResponse defines the response type for querying x/earn parameters.
 | 
			
		||||
message QueryParamsResponse {
 | 
			
		||||
 | 
			
		||||
  // params represents the earn module parameters
 | 
			
		||||
  Params params = 1 [(gogoproto.nullable) = false];
 | 
			
		||||
}
 | 
			
		||||
@ -65,12 +60,8 @@ message VaultResponse {
 | 
			
		||||
  // VaultStrategy is the strategy used for this vault.
 | 
			
		||||
  StrategyType vault_strategy = 2;
 | 
			
		||||
 | 
			
		||||
  // TotalSupplied is the total amount of denom coins supplied to the vault.
 | 
			
		||||
  string total_supplied = 3 [
 | 
			
		||||
    (cosmos_proto.scalar)  = "cosmos.Int",
 | 
			
		||||
    (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
 | 
			
		||||
    (gogoproto.nullable)   = false
 | 
			
		||||
  ];
 | 
			
		||||
  // TotalShares is the total amount of shares issued to depositors.
 | 
			
		||||
  string total_shares = 3;
 | 
			
		||||
 | 
			
		||||
  // TotalValue is the total value of denom coins supplied to the vault if the
 | 
			
		||||
  // vault were to be liquidated.
 | 
			
		||||
@ -107,9 +98,8 @@ message DepositResponse {
 | 
			
		||||
  // depositor represents the owner of the deposit.
 | 
			
		||||
  string depositor = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
 | 
			
		||||
 | 
			
		||||
  // Amount represents the amount supplied to vaults.
 | 
			
		||||
  repeated cosmos.base.v1beta1.Coin amount_supplied = 2
 | 
			
		||||
      [(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins", (gogoproto.nullable) = false];
 | 
			
		||||
  // Shares represent the issued shares from their corresponding vaults.
 | 
			
		||||
  repeated VaultShare shares = 2 [(gogoproto.castrepeated) = "VaultShares", (gogoproto.nullable) = false];
 | 
			
		||||
 | 
			
		||||
  // Value represents the total accumulated value of denom coins supplied to
 | 
			
		||||
  // vaults. This may be greater than or equal to amount_supplied depending on
 | 
			
		||||
@ -117,15 +107,3 @@ message DepositResponse {
 | 
			
		||||
  repeated cosmos.base.v1beta1.Coin value = 3
 | 
			
		||||
      [(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins", (gogoproto.nullable) = false];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// QueryTotalDepositedRequest is the request type for the Query/TotalDeposited RPC method.
 | 
			
		||||
message QueryTotalDepositedRequest {
 | 
			
		||||
  // denom represents the vault denom to query total deposited amount for.
 | 
			
		||||
  string denom = 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// QueryTotalDepositedResponse is the response type for the Query/TotalDeposited RPC method.
 | 
			
		||||
message QueryTotalDepositedResponse {
 | 
			
		||||
  repeated cosmos.base.v1beta1.Coin supplied_coins = 1
 | 
			
		||||
      [(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins", (gogoproto.nullable) = false];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -4,6 +4,7 @@ package kava.earn.v1beta1;
 | 
			
		||||
import "cosmos_proto/cosmos.proto";
 | 
			
		||||
import "cosmos/base/v1beta1/coin.proto";
 | 
			
		||||
import "gogoproto/gogo.proto";
 | 
			
		||||
import "kava/earn/v1beta1/vault.proto";
 | 
			
		||||
 | 
			
		||||
option go_package = "github.com/kava-labs/kava/x/earn/types";
 | 
			
		||||
 | 
			
		||||
@ -27,7 +28,9 @@ message MsgDeposit {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MsgDepositResponse defines the Msg/Deposit response type.
 | 
			
		||||
message MsgDepositResponse {}
 | 
			
		||||
message MsgDepositResponse {
 | 
			
		||||
  VaultShare shares = 1 [(gogoproto.nullable) = false];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MsgWithdraw represents a message for withdrawing liquidity from a vault
 | 
			
		||||
message MsgWithdraw {
 | 
			
		||||
@ -42,4 +45,6 @@ message MsgWithdraw {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MsgWithdrawResponse defines the Msg/Withdraw response type.
 | 
			
		||||
message MsgWithdrawResponse {}
 | 
			
		||||
message MsgWithdrawResponse {
 | 
			
		||||
  VaultShare shares = 1 [(gogoproto.nullable) = false];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -18,15 +18,10 @@ message AllowedVault {
 | 
			
		||||
  StrategyType vault_strategy = 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// VaultRecord is the state of a vault and is used to store the state of a
 | 
			
		||||
// vault.
 | 
			
		||||
// VaultRecord is the state of a vault.
 | 
			
		||||
message VaultRecord {
 | 
			
		||||
  // Denom is the only supported denomination of the vault for deposits and
 | 
			
		||||
  // withdrawals.
 | 
			
		||||
  string denom = 1;
 | 
			
		||||
  // TotalSupply is the total supply of the vault, denominated **only** in the
 | 
			
		||||
  // user deposit/withdrawal denom, must be the same as the Denom field.
 | 
			
		||||
  cosmos.base.v1beta1.Coin total_supply = 2 [(gogoproto.nullable) = false];
 | 
			
		||||
  // TotalShares is the total distributed number of shares in the vault.
 | 
			
		||||
  VaultShare total_shares = 1 [(gogoproto.nullable) = false];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// VaultShareRecord defines the vault shares owned by a depositor.
 | 
			
		||||
@ -36,8 +31,18 @@ message VaultShareRecord {
 | 
			
		||||
    (cosmos_proto.scalar) = "cosmos.AddressBytes",
 | 
			
		||||
    (gogoproto.casttype)  = "github.com/cosmos/cosmos-sdk/types.AccAddress"
 | 
			
		||||
  ];
 | 
			
		||||
  // AmountSupplied represents the total amount a depositor has supplied to the
 | 
			
		||||
  // vault. The vault is determined by the coin denom.
 | 
			
		||||
  repeated cosmos.base.v1beta1.Coin amount_supplied = 2
 | 
			
		||||
      [(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins", (gogoproto.nullable) = false];
 | 
			
		||||
  // Shares represent the vault shares owned by the depositor.
 | 
			
		||||
  repeated VaultShare shares = 2 [(gogoproto.castrepeated) = "VaultShares", (gogoproto.nullable) = false];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// VaultShare defines shares of a vault owned by a depositor.
 | 
			
		||||
message VaultShare {
 | 
			
		||||
  option (gogoproto.goproto_stringer) = false;
 | 
			
		||||
 | 
			
		||||
  string denom  = 1;
 | 
			
		||||
  string amount = 2 [
 | 
			
		||||
    (cosmos_proto.scalar)  = "cosmos.Dec",
 | 
			
		||||
    (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
 | 
			
		||||
    (gogoproto.nullable)   = false
 | 
			
		||||
  ];
 | 
			
		||||
}
 | 
			
		||||
@ -33,7 +33,6 @@ func GetQueryCmd() *cobra.Command {
 | 
			
		||||
		queryParamsCmd(),
 | 
			
		||||
		queryVaultsCmd(),
 | 
			
		||||
		queryDepositsCmd(),
 | 
			
		||||
		queryTotalDepositedCmd(),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, cmd := range cmds {
 | 
			
		||||
@ -155,35 +154,3 @@ func queryDepositsCmd() *cobra.Command {
 | 
			
		||||
 | 
			
		||||
	return cmd
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func queryTotalDepositedCmd() *cobra.Command {
 | 
			
		||||
	return &cobra.Command{
 | 
			
		||||
		Use:   "total-deposited",
 | 
			
		||||
		Short: "get the current total deposited amount",
 | 
			
		||||
		Long:  "Get the current total deposited amount in the earn module vaults.",
 | 
			
		||||
		Args:  cobra.MaximumNArgs(1),
 | 
			
		||||
		Example: fmt.Sprintf(`%[1]s q %[2]s total-deposited
 | 
			
		||||
%[1]s q %[2]s total-deposited usdx`, version.AppName, types.ModuleName),
 | 
			
		||||
		RunE: func(cmd *cobra.Command, args []string) error {
 | 
			
		||||
			clientCtx, err := client.GetClientQueryContext(cmd)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			queryClient := types.NewQueryClient(clientCtx)
 | 
			
		||||
 | 
			
		||||
			vaultDenom := ""
 | 
			
		||||
			if len(args) > 1 {
 | 
			
		||||
				vaultDenom = args[0]
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			req := types.NewQueryTotalDepositedRequest(vaultDenom)
 | 
			
		||||
			res, err := queryClient.TotalDeposited(context.Background(), req)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return clientCtx.PrintProto(res)
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -21,14 +21,14 @@ func InitGenesis(
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Total of all vault share records, vault record total supply should equal this
 | 
			
		||||
	vaultTotalSupplies := sdk.NewCoins()
 | 
			
		||||
	vaultTotalShares := types.NewVaultShares()
 | 
			
		||||
 | 
			
		||||
	for _, vaultShareRecord := range gs.VaultShareRecords {
 | 
			
		||||
		if err := vaultShareRecord.Validate(); err != nil {
 | 
			
		||||
			panic(fmt.Sprintf("invalid vault share: %s", err))
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		vaultTotalSupplies = vaultTotalSupplies.Add(vaultShareRecord.AmountSupplied...)
 | 
			
		||||
		vaultTotalShares = vaultTotalShares.Add(vaultShareRecord.Shares...)
 | 
			
		||||
 | 
			
		||||
		k.SetVaultShareRecord(ctx, vaultShareRecord)
 | 
			
		||||
	}
 | 
			
		||||
@ -38,12 +38,12 @@ func InitGenesis(
 | 
			
		||||
			panic(fmt.Sprintf("invalid vault record: %s", err))
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if !vaultRecord.TotalSupply.Amount.Equal(vaultTotalSupplies.AmountOf(vaultRecord.Denom)) {
 | 
			
		||||
		if !vaultRecord.TotalShares.Amount.Equal(vaultTotalShares.AmountOf(vaultRecord.TotalShares.Denom)) {
 | 
			
		||||
			panic(fmt.Sprintf(
 | 
			
		||||
				"invalid vault record total supply for %s, got %s but sum of vault shares is %s",
 | 
			
		||||
				vaultRecord.Denom,
 | 
			
		||||
				vaultRecord.TotalSupply.Amount,
 | 
			
		||||
				vaultTotalSupplies.AmountOf(vaultRecord.Denom),
 | 
			
		||||
				vaultRecord.TotalShares.Denom,
 | 
			
		||||
				vaultRecord.TotalShares.Amount,
 | 
			
		||||
				vaultTotalShares.AmountOf(vaultRecord.TotalShares.Denom),
 | 
			
		||||
			))
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -25,8 +25,9 @@ func (suite *genesisTestSuite) Test_InitGenesis_ValidationPanic() {
 | 
			
		||||
		},
 | 
			
		||||
		types.VaultRecords{
 | 
			
		||||
			{
 | 
			
		||||
				Denom:       "",
 | 
			
		||||
				TotalSupply: sdk.NewInt64Coin("usdx", 0),
 | 
			
		||||
				TotalShares: types.VaultShare{
 | 
			
		||||
					Denom: "", Amount: sdk.NewDec(1),
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		types.VaultShareRecords{},
 | 
			
		||||
@ -53,22 +54,26 @@ func (suite *genesisTestSuite) Test_InitAndExportGenesis() {
 | 
			
		||||
		},
 | 
			
		||||
		types.VaultRecords{
 | 
			
		||||
			types.VaultRecord{
 | 
			
		||||
				Denom:       "ukava",
 | 
			
		||||
				TotalSupply: sdk.NewInt64Coin("ukava", 2000000),
 | 
			
		||||
				TotalShares: types.NewVaultShare("ukava", sdk.NewDec(3800000)),
 | 
			
		||||
			},
 | 
			
		||||
			types.VaultRecord{
 | 
			
		||||
				Denom:       "usdx",
 | 
			
		||||
				TotalSupply: sdk.NewInt64Coin("usdx", 1000000),
 | 
			
		||||
				TotalShares: types.NewVaultShare("usdx", sdk.NewDec(1000000)),
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		types.VaultShareRecords{
 | 
			
		||||
			types.VaultShareRecord{
 | 
			
		||||
				Depositor: depositor_1,
 | 
			
		||||
				AmountSupplied: sdk.NewCoins(sdk.NewInt64Coin("usdx", 500000), sdk.NewInt64Coin("ukava", 1900000)),
 | 
			
		||||
				Shares: types.NewVaultShares(
 | 
			
		||||
					types.NewVaultShare("usdx", sdk.NewDec(500000)),
 | 
			
		||||
					types.NewVaultShare("ukava", sdk.NewDec(1900000)),
 | 
			
		||||
				),
 | 
			
		||||
			},
 | 
			
		||||
			types.VaultShareRecord{
 | 
			
		||||
				Depositor: depositor_2,
 | 
			
		||||
				AmountSupplied: sdk.NewCoins(sdk.NewInt64Coin("usdx", 500000), sdk.NewInt64Coin("ukava", 100000)),
 | 
			
		||||
				Shares: types.NewVaultShares(
 | 
			
		||||
					types.NewVaultShare("usdx", sdk.NewDec(500000)),
 | 
			
		||||
					types.NewVaultShare("ukava", sdk.NewDec(1900000)),
 | 
			
		||||
				),
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	)
 | 
			
		||||
@ -107,22 +112,26 @@ func (suite *genesisTestSuite) Test_Marshall() {
 | 
			
		||||
		},
 | 
			
		||||
		types.VaultRecords{
 | 
			
		||||
			types.VaultRecord{
 | 
			
		||||
				Denom:       "ukava",
 | 
			
		||||
				TotalSupply: sdk.NewInt64Coin("ukava", 2000000),
 | 
			
		||||
				TotalShares: types.NewVaultShare("ukava", sdk.NewDec(3800000)),
 | 
			
		||||
			},
 | 
			
		||||
			types.VaultRecord{
 | 
			
		||||
				Denom:       "usdx",
 | 
			
		||||
				TotalSupply: sdk.NewInt64Coin("usdx", 1000000),
 | 
			
		||||
				TotalShares: types.NewVaultShare("usdx", sdk.NewDec(1000000)),
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		types.VaultShareRecords{
 | 
			
		||||
			types.VaultShareRecord{
 | 
			
		||||
				Depositor: depositor_1,
 | 
			
		||||
				AmountSupplied: sdk.NewCoins(sdk.NewInt64Coin("usdx", 500000), sdk.NewInt64Coin("ukava", 1900000)),
 | 
			
		||||
				Shares: types.NewVaultShares(
 | 
			
		||||
					types.NewVaultShare("usdx", sdk.NewDec(500000)),
 | 
			
		||||
					types.NewVaultShare("ukava", sdk.NewDec(1900000)),
 | 
			
		||||
				),
 | 
			
		||||
			},
 | 
			
		||||
			types.VaultShareRecord{
 | 
			
		||||
				Depositor: depositor_2,
 | 
			
		||||
				AmountSupplied: sdk.NewCoins(sdk.NewInt64Coin("usdx", 500000), sdk.NewInt64Coin("ukava", 100000)),
 | 
			
		||||
				Shares: types.NewVaultShares(
 | 
			
		||||
					types.NewVaultShare("usdx", sdk.NewDec(500000)),
 | 
			
		||||
					types.NewVaultShare("ukava", sdk.NewDec(1900000)),
 | 
			
		||||
				),
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,8 @@
 | 
			
		||||
package keeper
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
			
		||||
	"github.com/kava-labs/kava/x/earn/types"
 | 
			
		||||
)
 | 
			
		||||
@ -22,7 +24,7 @@ func (k *Keeper) Deposit(ctx sdk.Context, depositor sdk.AccAddress, amount sdk.C
 | 
			
		||||
	vaultRecord, found := k.GetVaultRecord(ctx, amount.Denom)
 | 
			
		||||
	if !found {
 | 
			
		||||
		// Create a new VaultRecord with 0 supply
 | 
			
		||||
		vaultRecord = types.NewVaultRecord(amount.Denom)
 | 
			
		||||
		vaultRecord = types.NewVaultRecord(amount.Denom, sdk.ZeroDec())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Get the strategy for the vault
 | 
			
		||||
@ -45,14 +47,17 @@ func (k *Keeper) Deposit(ctx sdk.Context, depositor sdk.AccAddress, amount sdk.C
 | 
			
		||||
	vaultShareRecord, found := k.GetVaultShareRecord(ctx, depositor)
 | 
			
		||||
	if !found {
 | 
			
		||||
		// Create a new empty VaultShareRecord with 0 supply
 | 
			
		||||
		vaultShareRecord = types.NewVaultShareRecord(depositor)
 | 
			
		||||
		vaultShareRecord = types.NewVaultShareRecord(depositor, types.NewVaultShares())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Increment VaultRecord supply
 | 
			
		||||
	vaultRecord.TotalSupply = vaultRecord.TotalSupply.Add(amount)
 | 
			
		||||
	shares, err := k.ConvertToShares(ctx, amount)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("failed to convert assets to shares: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Increment VaultShareRecord supply
 | 
			
		||||
	vaultShareRecord.AmountSupplied = vaultShareRecord.AmountSupplied.Add(amount)
 | 
			
		||||
	// Increment VaultRecord total shares and account shares
 | 
			
		||||
	vaultRecord.TotalShares = vaultRecord.TotalShares.Add(shares)
 | 
			
		||||
	vaultShareRecord.Shares = vaultShareRecord.Shares.Add(shares)
 | 
			
		||||
 | 
			
		||||
	// Update VaultRecord and VaultShareRecord
 | 
			
		||||
	k.SetVaultRecord(ctx, vaultRecord)
 | 
			
		||||
@ -68,6 +73,7 @@ func (k *Keeper) Deposit(ctx sdk.Context, depositor sdk.AccAddress, amount sdk.C
 | 
			
		||||
			types.EventTypeVaultDeposit,
 | 
			
		||||
			sdk.NewAttribute(types.AttributeKeyVaultDenom, amount.Denom),
 | 
			
		||||
			sdk.NewAttribute(types.AttributeKeyDepositor, depositor.String()),
 | 
			
		||||
			sdk.NewAttribute(types.AttributeKeyShares, shares.Amount.String()),
 | 
			
		||||
			sdk.NewAttribute(sdk.AttributeKeyAmount, amount.Amount.String()),
 | 
			
		||||
		),
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
@ -51,7 +51,9 @@ func (suite *depositTestSuite) TestDeposit_Balances() {
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	suite.VaultTotalValuesEqual(sdk.NewCoins(depositAmount))
 | 
			
		||||
	suite.VaultTotalSuppliedEqual(sdk.NewCoins(depositAmount))
 | 
			
		||||
	suite.VaultTotalSharesEqual(types.NewVaultShares(
 | 
			
		||||
		types.NewVaultShare(depositAmount.Denom, depositAmount.Amount.ToDec()),
 | 
			
		||||
	))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *depositTestSuite) TestDeposit_Exceed() {
 | 
			
		||||
 | 
			
		||||
@ -69,10 +69,10 @@ func (s queryServer) Vaults(
 | 
			
		||||
	vaults := []types.VaultResponse{}
 | 
			
		||||
 | 
			
		||||
	for _, allowedVault := range queriedAllowedVaults {
 | 
			
		||||
		totalSupplied, err := s.keeper.GetVaultTotalSupplied(sdkCtx, allowedVault.Denom)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
		vaultTotalShares, found := s.keeper.GetVaultTotalShares(sdkCtx, allowedVault.Denom)
 | 
			
		||||
		if !found {
 | 
			
		||||
			// No supply yet, no error just zero
 | 
			
		||||
			totalSupplied = sdk.NewCoin(allowedVault.Denom, sdk.ZeroInt())
 | 
			
		||||
			vaultTotalShares = types.NewVaultShare(allowedVault.Denom, sdk.ZeroDec())
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		totalValue, err := s.keeper.GetVaultTotalValue(sdkCtx, allowedVault.Denom)
 | 
			
		||||
@ -83,7 +83,7 @@ func (s queryServer) Vaults(
 | 
			
		||||
		vaults = append(vaults, types.VaultResponse{
 | 
			
		||||
			Denom:         allowedVault.Denom,
 | 
			
		||||
			VaultStrategy: allowedVault.VaultStrategy,
 | 
			
		||||
			TotalSupplied: totalSupplied.Amount,
 | 
			
		||||
			TotalShares:   vaultTotalShares.Amount.String(),
 | 
			
		||||
			TotalValue:    totalValue.Amount,
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
@ -106,21 +106,44 @@ func (s queryServer) Deposits(
 | 
			
		||||
 | 
			
		||||
	// 1. Specific account and specific vault
 | 
			
		||||
	if req.Owner != "" && req.Denom != "" {
 | 
			
		||||
		return s.getAccountVaultDeposit(sdkCtx, req)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 2. All accounts, specific vault
 | 
			
		||||
	if req.Owner == "" && req.Denom != "" {
 | 
			
		||||
		return s.getVaultAllDeposits(sdkCtx, req)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 3. Specific account, all vaults
 | 
			
		||||
	if req.Owner != "" && req.Denom == "" {
 | 
			
		||||
		return s.getAccountAllDeposits(sdkCtx, req)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 4. All accounts, all vaults
 | 
			
		||||
	return s.getAllDeposits(sdkCtx, req)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getAccountVaultDeposit returns deposits for a specific vault and a specific
 | 
			
		||||
// account
 | 
			
		||||
func (s queryServer) getAccountVaultDeposit(
 | 
			
		||||
	ctx sdk.Context,
 | 
			
		||||
	req *types.QueryDepositsRequest,
 | 
			
		||||
) (*types.QueryDepositsResponse, error) {
 | 
			
		||||
	owner, err := sdk.AccAddressFromBech32(req.Owner)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, status.Error(codes.InvalidArgument, "Invalid address")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
		shareRecord, found := s.keeper.GetVaultShareRecord(sdkCtx, owner)
 | 
			
		||||
	shareRecord, found := s.keeper.GetVaultShareRecord(ctx, owner)
 | 
			
		||||
	if !found {
 | 
			
		||||
		return nil, status.Error(codes.NotFound, "No deposit found for owner")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
		if shareRecord.AmountSupplied.AmountOf(req.Denom).IsZero() {
 | 
			
		||||
	if shareRecord.Shares.AmountOf(req.Denom).IsZero() {
 | 
			
		||||
		return nil, status.Error(codes.NotFound, fmt.Sprintf("No deposit for denom %s found for owner", req.Denom))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
		value, err := getAccountValue(sdkCtx, s.keeper, owner, shareRecord.AmountSupplied)
 | 
			
		||||
	value, err := getAccountValue(ctx, s.keeper, owner, shareRecord.Shares)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, status.Error(codes.InvalidArgument, err.Error())
 | 
			
		||||
	}
 | 
			
		||||
@ -129,7 +152,7 @@ func (s queryServer) Deposits(
 | 
			
		||||
		Deposits: []types.DepositResponse{
 | 
			
		||||
			{
 | 
			
		||||
				Depositor: owner.String(),
 | 
			
		||||
					AmountSupplied: shareRecord.AmountSupplied,
 | 
			
		||||
				Shares:    shareRecord.Shares,
 | 
			
		||||
				Value:     value,
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
@ -137,15 +160,18 @@ func (s queryServer) Deposits(
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	// 2. All accounts, specific vault
 | 
			
		||||
	if req.Owner == "" && req.Denom != "" {
 | 
			
		||||
		_, found := s.keeper.GetVaultRecord(sdkCtx, req.Denom)
 | 
			
		||||
// getVaultAllDeposits returns all deposits for a specific vault
 | 
			
		||||
func (s queryServer) getVaultAllDeposits(
 | 
			
		||||
	ctx sdk.Context,
 | 
			
		||||
	req *types.QueryDepositsRequest,
 | 
			
		||||
) (*types.QueryDepositsResponse, error) {
 | 
			
		||||
	_, found := s.keeper.GetVaultRecord(ctx, req.Denom)
 | 
			
		||||
	if !found {
 | 
			
		||||
		return nil, status.Error(codes.NotFound, "Vault record for denom not found")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	deposits := []types.DepositResponse{}
 | 
			
		||||
		store := prefix.NewStore(sdkCtx.KVStore(s.keeper.key), types.VaultShareRecordKeyPrefix)
 | 
			
		||||
	store := prefix.NewStore(ctx.KVStore(s.keeper.key), types.VaultShareRecordKeyPrefix)
 | 
			
		||||
 | 
			
		||||
	pageRes, err := query.FilteredPaginate(
 | 
			
		||||
		store,
 | 
			
		||||
@ -158,13 +184,13 @@ func (s queryServer) Deposits(
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Only those that have amount of requested denom
 | 
			
		||||
				if record.AmountSupplied.AmountOf(req.Denom).IsZero() {
 | 
			
		||||
			if record.Shares.AmountOf(req.Denom).IsZero() {
 | 
			
		||||
				// inform paginate that there was no match on this key
 | 
			
		||||
				return false, nil
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if accumulate {
 | 
			
		||||
					accValue, err := getAccountValue(sdkCtx, s.keeper, record.Depositor, record.AmountSupplied)
 | 
			
		||||
				accValue, err := getAccountValue(ctx, s.keeper, record.Depositor, record.Shares)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return false, err
 | 
			
		||||
				}
 | 
			
		||||
@ -172,7 +198,7 @@ func (s queryServer) Deposits(
 | 
			
		||||
				// only add to results if paginate tells us to
 | 
			
		||||
				deposits = append(deposits, types.DepositResponse{
 | 
			
		||||
					Depositor: record.Depositor.String(),
 | 
			
		||||
						AmountSupplied: record.AmountSupplied,
 | 
			
		||||
					Shares:    record.Shares,
 | 
			
		||||
					Value:     accValue,
 | 
			
		||||
				})
 | 
			
		||||
			}
 | 
			
		||||
@ -192,8 +218,11 @@ func (s queryServer) Deposits(
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	// 3. Specific account, all vaults
 | 
			
		||||
	if req.Owner != "" && req.Denom == "" {
 | 
			
		||||
// getAccountAllDeposits returns deposits for all vaults for a specific account
 | 
			
		||||
func (s queryServer) getAccountAllDeposits(
 | 
			
		||||
	ctx sdk.Context,
 | 
			
		||||
	req *types.QueryDepositsRequest,
 | 
			
		||||
) (*types.QueryDepositsResponse, error) {
 | 
			
		||||
	owner, err := sdk.AccAddressFromBech32(req.Owner)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, status.Error(codes.InvalidArgument, "Invalid address")
 | 
			
		||||
@ -201,19 +230,19 @@ func (s queryServer) Deposits(
 | 
			
		||||
 | 
			
		||||
	deposits := []types.DepositResponse{}
 | 
			
		||||
 | 
			
		||||
		accountShare, found := s.keeper.GetVaultShareRecord(sdkCtx, owner)
 | 
			
		||||
	accountShare, found := s.keeper.GetVaultShareRecord(ctx, owner)
 | 
			
		||||
	if !found {
 | 
			
		||||
		return nil, status.Error(codes.NotFound, "No deposit found for owner")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
		value, err := getAccountValue(sdkCtx, s.keeper, owner, accountShare.AmountSupplied)
 | 
			
		||||
	value, err := getAccountValue(ctx, s.keeper, owner, accountShare.Shares)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, status.Error(codes.InvalidArgument, err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	deposits = append(deposits, types.DepositResponse{
 | 
			
		||||
		Depositor: owner.String(),
 | 
			
		||||
			AmountSupplied: accountShare.AmountSupplied,
 | 
			
		||||
		Shares:    accountShare.Shares,
 | 
			
		||||
		Value:     value,
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
@ -223,9 +252,13 @@ func (s queryServer) Deposits(
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	// 4. All accounts, all vaults
 | 
			
		||||
// getAllDeposits returns all deposits for all vaults
 | 
			
		||||
func (s queryServer) getAllDeposits(
 | 
			
		||||
	ctx sdk.Context,
 | 
			
		||||
	req *types.QueryDepositsRequest,
 | 
			
		||||
) (*types.QueryDepositsResponse, error) {
 | 
			
		||||
	deposits := []types.DepositResponse{}
 | 
			
		||||
	store := prefix.NewStore(sdkCtx.KVStore(s.keeper.key), types.VaultShareRecordKeyPrefix)
 | 
			
		||||
	store := prefix.NewStore(ctx.KVStore(s.keeper.key), types.VaultShareRecordKeyPrefix)
 | 
			
		||||
 | 
			
		||||
	pageRes, err := query.Paginate(
 | 
			
		||||
		store,
 | 
			
		||||
@ -237,7 +270,7 @@ func (s queryServer) Deposits(
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			accValue, err := getAccountValue(sdkCtx, s.keeper, record.Depositor, record.AmountSupplied)
 | 
			
		||||
			accValue, err := getAccountValue(ctx, s.keeper, record.Depositor, record.Shares)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
@ -245,7 +278,7 @@ func (s queryServer) Deposits(
 | 
			
		||||
			// only add to results if paginate tells us to
 | 
			
		||||
			deposits = append(deposits, types.DepositResponse{
 | 
			
		||||
				Depositor: record.Depositor.String(),
 | 
			
		||||
				AmountSupplied: record.AmountSupplied,
 | 
			
		||||
				Shares:    record.Shares,
 | 
			
		||||
				Value:     accValue,
 | 
			
		||||
			})
 | 
			
		||||
 | 
			
		||||
@ -263,56 +296,21 @@ func (s queryServer) Deposits(
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Deposits implements the gRPC service handler for querying x/earn deposits.
 | 
			
		||||
func (s queryServer) TotalDeposited(
 | 
			
		||||
	ctx context.Context,
 | 
			
		||||
	req *types.QueryTotalDepositedRequest,
 | 
			
		||||
) (*types.QueryTotalDepositedResponse, error) {
 | 
			
		||||
	if req == nil {
 | 
			
		||||
		return nil, status.Errorf(codes.InvalidArgument, "empty request")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sdkCtx := sdk.UnwrapSDKContext(ctx)
 | 
			
		||||
 | 
			
		||||
	// Single vault
 | 
			
		||||
	if req.Denom != "" {
 | 
			
		||||
		totalSupplied, err := s.keeper.GetVaultTotalSupplied(sdkCtx, req.Denom)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return &types.QueryTotalDepositedResponse{
 | 
			
		||||
			SuppliedCoins: sdk.NewCoins(totalSupplied),
 | 
			
		||||
		}, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	coins := sdk.NewCoins()
 | 
			
		||||
	vaults := s.keeper.GetAllVaultRecords(sdkCtx)
 | 
			
		||||
 | 
			
		||||
	for _, vault := range vaults {
 | 
			
		||||
		coins = coins.Add(vault.TotalSupply)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &types.QueryTotalDepositedResponse{
 | 
			
		||||
		SuppliedCoins: coins,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getAccountValue(
 | 
			
		||||
	ctx sdk.Context,
 | 
			
		||||
	keeper Keeper,
 | 
			
		||||
	account sdk.AccAddress,
 | 
			
		||||
	supplied sdk.Coins,
 | 
			
		||||
	shares types.VaultShares,
 | 
			
		||||
) (sdk.Coins, error) {
 | 
			
		||||
	value := sdk.NewCoins()
 | 
			
		||||
 | 
			
		||||
	for _, coin := range supplied {
 | 
			
		||||
		accValue, err := keeper.GetVaultAccountValue(ctx, coin.Denom, account)
 | 
			
		||||
	for _, share := range shares {
 | 
			
		||||
		accValue, err := keeper.GetVaultAccountValue(ctx, share.Denom, account)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		value = value.Add(sdk.NewCoin(coin.Denom, accValue.Amount))
 | 
			
		||||
		value = value.Add(sdk.NewCoin(share.Denom, accValue.Amount))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return value, nil
 | 
			
		||||
 | 
			
		||||
@ -70,7 +70,7 @@ func (suite *grpcQueryTestSuite) TestVaults_ZeroSupply() {
 | 
			
		||||
			types.VaultResponse{
 | 
			
		||||
				Denom:         "usdx",
 | 
			
		||||
				VaultStrategy: types.STRATEGY_TYPE_HARD,
 | 
			
		||||
				TotalSupplied: sdk.NewInt(0),
 | 
			
		||||
				TotalShares:   sdk.NewDec(0).String(),
 | 
			
		||||
				TotalValue:    sdk.NewInt(0),
 | 
			
		||||
			},
 | 
			
		||||
			res.Vaults[0],
 | 
			
		||||
@ -86,13 +86,13 @@ func (suite *grpcQueryTestSuite) TestVaults_ZeroSupply() {
 | 
			
		||||
				{
 | 
			
		||||
					Denom:         "usdx",
 | 
			
		||||
					VaultStrategy: types.STRATEGY_TYPE_HARD,
 | 
			
		||||
					TotalSupplied: sdk.NewInt(0),
 | 
			
		||||
					TotalShares:   sdk.NewDec(0).String(),
 | 
			
		||||
					TotalValue:    sdk.NewInt(0),
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Denom:         "busd",
 | 
			
		||||
					VaultStrategy: types.STRATEGY_TYPE_HARD,
 | 
			
		||||
					TotalSupplied: sdk.NewInt(0),
 | 
			
		||||
					TotalShares:   sdk.NewDec(0).String(),
 | 
			
		||||
					TotalValue:    sdk.NewInt(0),
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
@ -121,7 +121,7 @@ func (suite *grpcQueryTestSuite) TestVaults_WithSupply() {
 | 
			
		||||
		types.VaultResponse{
 | 
			
		||||
			Denom:         "usdx",
 | 
			
		||||
			VaultStrategy: types.STRATEGY_TYPE_HARD,
 | 
			
		||||
			TotalSupplied: depositAmount.Amount,
 | 
			
		||||
			TotalShares:   depositAmount.Amount.ToDec().String(),
 | 
			
		||||
			TotalValue:    depositAmount.Amount,
 | 
			
		||||
		},
 | 
			
		||||
		res.Vaults[0],
 | 
			
		||||
@ -183,7 +183,10 @@ func (suite *grpcQueryTestSuite) TestDeposits() {
 | 
			
		||||
				{
 | 
			
		||||
					Depositor: acc1.String(),
 | 
			
		||||
					// Still includes all deposits
 | 
			
		||||
					AmountSupplied: sdk.NewCoins(deposit1Amount, deposit2Amount),
 | 
			
		||||
					Shares: types.NewVaultShares(
 | 
			
		||||
						types.NewVaultShare(deposit1Amount.Denom, deposit1Amount.Amount.ToDec()),
 | 
			
		||||
						types.NewVaultShare(deposit2Amount.Denom, deposit2Amount.Amount.ToDec()),
 | 
			
		||||
					),
 | 
			
		||||
					Value: sdk.NewCoins(deposit1Amount, deposit2Amount),
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
@ -214,7 +217,10 @@ func (suite *grpcQueryTestSuite) TestDeposits() {
 | 
			
		||||
			[]types.DepositResponse{
 | 
			
		||||
				{
 | 
			
		||||
					Depositor: acc1.String(),
 | 
			
		||||
					AmountSupplied: sdk.NewCoins(deposit1Amount, deposit2Amount),
 | 
			
		||||
					Shares: types.NewVaultShares(
 | 
			
		||||
						types.NewVaultShare(deposit1Amount.Denom, deposit1Amount.Amount.ToDec()),
 | 
			
		||||
						types.NewVaultShare(deposit2Amount.Denom, deposit2Amount.Amount.ToDec()),
 | 
			
		||||
					),
 | 
			
		||||
					Value: sdk.NewCoins(deposit1Amount, deposit2Amount),
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
@ -234,7 +240,10 @@ func (suite *grpcQueryTestSuite) TestDeposits() {
 | 
			
		||||
			[]types.DepositResponse{
 | 
			
		||||
				{
 | 
			
		||||
					Depositor: acc2.String(),
 | 
			
		||||
					AmountSupplied: sdk.NewCoins(deposit1Amount, deposit3Amount),
 | 
			
		||||
					Shares: types.NewVaultShares(
 | 
			
		||||
						types.NewVaultShare(deposit1Amount.Denom, deposit1Amount.Amount.ToDec()),
 | 
			
		||||
						types.NewVaultShare(deposit3Amount.Denom, deposit3Amount.Amount.ToDec()),
 | 
			
		||||
					),
 | 
			
		||||
					Value: sdk.NewCoins(deposit1Amount, deposit3Amount),
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
@ -254,12 +263,18 @@ func (suite *grpcQueryTestSuite) TestDeposits() {
 | 
			
		||||
			[]types.DepositResponse{
 | 
			
		||||
				{
 | 
			
		||||
					Depositor: acc1.String(),
 | 
			
		||||
					AmountSupplied: sdk.NewCoins(deposit1Amount, deposit2Amount),
 | 
			
		||||
					Shares: types.NewVaultShares(
 | 
			
		||||
						types.NewVaultShare(deposit1Amount.Denom, deposit1Amount.Amount.ToDec()),
 | 
			
		||||
						types.NewVaultShare(deposit2Amount.Denom, deposit2Amount.Amount.ToDec()),
 | 
			
		||||
					),
 | 
			
		||||
					Value: sdk.NewCoins(deposit1Amount, deposit2Amount),
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Depositor: acc2.String(),
 | 
			
		||||
					AmountSupplied: sdk.NewCoins(deposit1Amount, deposit3Amount),
 | 
			
		||||
					Shares: types.NewVaultShares(
 | 
			
		||||
						types.NewVaultShare(deposit1Amount.Denom, deposit1Amount.Amount.ToDec()),
 | 
			
		||||
						types.NewVaultShare(deposit3Amount.Denom, deposit3Amount.Amount.ToDec()),
 | 
			
		||||
					),
 | 
			
		||||
					Value: sdk.NewCoins(deposit1Amount, deposit3Amount),
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
@ -294,103 +309,3 @@ func (suite *grpcQueryTestSuite) TestDeposits_InvalidAddress() {
 | 
			
		||||
	suite.Require().Error(err)
 | 
			
		||||
	suite.Require().ErrorIs(err, status.Error(codes.InvalidArgument, "Invalid address"))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *grpcQueryTestSuite) TestTotalDeposited_NoSupply() {
 | 
			
		||||
	// Add vaults
 | 
			
		||||
	suite.CreateVault("usdx", types.STRATEGY_TYPE_HARD)
 | 
			
		||||
	suite.CreateVault("cats", types.STRATEGY_TYPE_HARD)
 | 
			
		||||
 | 
			
		||||
	res, err := suite.queryClient.TotalDeposited(context.Background(), types.NewQueryTotalDepositedRequest(""))
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
	suite.Require().True(res.SuppliedCoins.Empty(), "supplied coins should be empty")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *grpcQueryTestSuite) TestTotalDeposited_All() {
 | 
			
		||||
	vault1Denom := "usdx"
 | 
			
		||||
	vault2Denom := "busd"
 | 
			
		||||
 | 
			
		||||
	// Add vaults
 | 
			
		||||
	suite.CreateVault(vault1Denom, types.STRATEGY_TYPE_HARD)
 | 
			
		||||
	suite.CreateVault(vault2Denom, types.STRATEGY_TYPE_HARD)
 | 
			
		||||
 | 
			
		||||
	startBalance := sdk.NewCoins(
 | 
			
		||||
		sdk.NewInt64Coin(vault1Denom, 1000),
 | 
			
		||||
		sdk.NewInt64Coin(vault2Denom, 1000),
 | 
			
		||||
	)
 | 
			
		||||
	deposit1Amount := sdk.NewInt64Coin(vault1Denom, 100)
 | 
			
		||||
	deposit2Amount := sdk.NewInt64Coin(vault2Denom, 100)
 | 
			
		||||
 | 
			
		||||
	acc := suite.CreateAccount(startBalance, 0).GetAddress()
 | 
			
		||||
	err := suite.Keeper.Deposit(suite.Ctx, acc, deposit1Amount)
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
 | 
			
		||||
	res, err := suite.queryClient.TotalDeposited(
 | 
			
		||||
		context.Background(),
 | 
			
		||||
		types.NewQueryTotalDepositedRequest(""), // query all
 | 
			
		||||
	)
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
	suite.Require().Equal(
 | 
			
		||||
		sdk.NewCoins(deposit1Amount),
 | 
			
		||||
		res.SuppliedCoins,
 | 
			
		||||
		"supplied coins should be sum of all supplied coins",
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	err = suite.Keeper.Deposit(suite.Ctx, acc, deposit2Amount)
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
 | 
			
		||||
	res, err = suite.queryClient.TotalDeposited(
 | 
			
		||||
		context.Background(),
 | 
			
		||||
		types.NewQueryTotalDepositedRequest(""), // query all
 | 
			
		||||
	)
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
	suite.Require().Equal(
 | 
			
		||||
		sdk.NewCoins(deposit1Amount, deposit2Amount),
 | 
			
		||||
		res.SuppliedCoins,
 | 
			
		||||
		"supplied coins should be sum of all supplied coins for multiple coins",
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *grpcQueryTestSuite) TestTotalDeposited_Single() {
 | 
			
		||||
	vault1Denom := "usdx"
 | 
			
		||||
	vault2Denom := "busd"
 | 
			
		||||
 | 
			
		||||
	// Add vaults
 | 
			
		||||
	suite.CreateVault(vault1Denom, types.STRATEGY_TYPE_HARD)
 | 
			
		||||
	suite.CreateVault(vault2Denom, types.STRATEGY_TYPE_HARD)
 | 
			
		||||
 | 
			
		||||
	startBalance := sdk.NewCoins(
 | 
			
		||||
		sdk.NewInt64Coin(vault1Denom, 1000),
 | 
			
		||||
		sdk.NewInt64Coin(vault2Denom, 1000),
 | 
			
		||||
	)
 | 
			
		||||
	deposit1Amount := sdk.NewInt64Coin(vault1Denom, 100)
 | 
			
		||||
	deposit2Amount := sdk.NewInt64Coin(vault2Denom, 100)
 | 
			
		||||
 | 
			
		||||
	acc := suite.CreateAccount(startBalance, 0).GetAddress()
 | 
			
		||||
	err := suite.Keeper.Deposit(suite.Ctx, acc, deposit1Amount)
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
 | 
			
		||||
	err = suite.Keeper.Deposit(suite.Ctx, acc, deposit2Amount)
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
 | 
			
		||||
	res, err := suite.queryClient.TotalDeposited(
 | 
			
		||||
		context.Background(),
 | 
			
		||||
		types.NewQueryTotalDepositedRequest(vault1Denom),
 | 
			
		||||
	)
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
	suite.Require().Equal(
 | 
			
		||||
		sdk.NewCoins(deposit1Amount),
 | 
			
		||||
		res.SuppliedCoins,
 | 
			
		||||
		"should only contain queried denom",
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	res, err = suite.queryClient.TotalDeposited(
 | 
			
		||||
		context.Background(),
 | 
			
		||||
		types.NewQueryTotalDepositedRequest(vault2Denom),
 | 
			
		||||
	)
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
	suite.Require().Equal(
 | 
			
		||||
		sdk.NewCoins(deposit2Amount),
 | 
			
		||||
		res.SuppliedCoins,
 | 
			
		||||
		"should only contain queried denom",
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -68,6 +68,8 @@ func (suite *msgServerTestSuite) TestDeposit() {
 | 
			
		||||
			types.EventTypeVaultDeposit,
 | 
			
		||||
			sdk.NewAttribute(types.AttributeKeyVaultDenom, depositAmount.Denom),
 | 
			
		||||
			sdk.NewAttribute(types.AttributeKeyDepositor, acc.GetAddress().String()),
 | 
			
		||||
			// Shares 1:1 to amount
 | 
			
		||||
			sdk.NewAttribute(types.AttributeKeyShares, depositAmount.Amount.ToDec().String()),
 | 
			
		||||
			sdk.NewAttribute(sdk.AttributeKeyAmount, depositAmount.Amount.String()),
 | 
			
		||||
		),
 | 
			
		||||
	)
 | 
			
		||||
@ -120,6 +122,7 @@ func (suite *msgServerTestSuite) TestWithdraw() {
 | 
			
		||||
			types.EventTypeVaultWithdraw,
 | 
			
		||||
			sdk.NewAttribute(types.AttributeKeyVaultDenom, depositAmount.Denom),
 | 
			
		||||
			sdk.NewAttribute(types.AttributeKeyOwner, acc.GetAddress().String()),
 | 
			
		||||
			sdk.NewAttribute(types.AttributeKeyShares, depositAmount.Amount.ToDec().String()),
 | 
			
		||||
			sdk.NewAttribute(sdk.AttributeKeyAmount, depositAmount.Amount.String()),
 | 
			
		||||
		),
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
@ -45,7 +45,9 @@ func (suite *strategyHardTestSuite) TestDeposit_SingleAcc() {
 | 
			
		||||
 | 
			
		||||
	suite.HardDepositAmountEqual(sdk.NewCoins(depositAmount))
 | 
			
		||||
	suite.VaultTotalValuesEqual(sdk.NewCoins(depositAmount))
 | 
			
		||||
	suite.VaultTotalSuppliedEqual(sdk.NewCoins(depositAmount))
 | 
			
		||||
	suite.VaultTotalSharesEqual(types.NewVaultShares(
 | 
			
		||||
		types.NewVaultShare(depositAmount.Denom, depositAmount.Amount.ToDec()),
 | 
			
		||||
	))
 | 
			
		||||
 | 
			
		||||
	// Query vault total
 | 
			
		||||
	totalValue, err := suite.Keeper.GetVaultTotalValue(suite.Ctx, vaultDenom)
 | 
			
		||||
@ -70,10 +72,12 @@ func (suite *strategyHardTestSuite) TestDeposit_SingleAcc_MultipleDeposits() {
 | 
			
		||||
	err = suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount)
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
 | 
			
		||||
	expectedVaultBalance := sdk.NewCoins(depositAmount.Add(depositAmount))
 | 
			
		||||
	suite.HardDepositAmountEqual(expectedVaultBalance)
 | 
			
		||||
	suite.VaultTotalValuesEqual(expectedVaultBalance)
 | 
			
		||||
	suite.VaultTotalSuppliedEqual(expectedVaultBalance)
 | 
			
		||||
	expectedVaultBalance := depositAmount.Add(depositAmount)
 | 
			
		||||
	suite.HardDepositAmountEqual(sdk.NewCoins(expectedVaultBalance))
 | 
			
		||||
	suite.VaultTotalValuesEqual(sdk.NewCoins(expectedVaultBalance))
 | 
			
		||||
	suite.VaultTotalSharesEqual(types.NewVaultShares(
 | 
			
		||||
		types.NewVaultShare(expectedVaultBalance.Denom, expectedVaultBalance.Amount.ToDec()),
 | 
			
		||||
	))
 | 
			
		||||
 | 
			
		||||
	// Query vault total
 | 
			
		||||
	totalValue, err := suite.Keeper.GetVaultTotalValue(suite.Ctx, vaultDenom)
 | 
			
		||||
@ -107,7 +111,9 @@ func (suite *strategyHardTestSuite) TestDeposit_MultipleAcc_MultipleDeposits() {
 | 
			
		||||
 | 
			
		||||
	suite.HardDepositAmountEqual(sdk.NewCoins(expectedTotalValue))
 | 
			
		||||
	suite.VaultTotalValuesEqual(sdk.NewCoins(expectedTotalValue))
 | 
			
		||||
	suite.VaultTotalSuppliedEqual(sdk.NewCoins(expectedTotalValue))
 | 
			
		||||
	suite.VaultTotalSharesEqual(types.NewVaultShares(
 | 
			
		||||
		types.NewVaultShare(expectedTotalValue.Denom, expectedTotalValue.Amount.ToDec()),
 | 
			
		||||
	))
 | 
			
		||||
 | 
			
		||||
	// Query vault total
 | 
			
		||||
	totalValue, err := suite.Keeper.GetVaultTotalValue(suite.Ctx, vaultDenom)
 | 
			
		||||
@ -183,7 +189,7 @@ func (suite *strategyHardTestSuite) TestWithdraw() {
 | 
			
		||||
 | 
			
		||||
	suite.HardDepositAmountEqual(sdk.NewCoins())
 | 
			
		||||
	suite.VaultTotalValuesEqual(sdk.NewCoins())
 | 
			
		||||
	suite.VaultTotalSuppliedEqual(sdk.NewCoins())
 | 
			
		||||
	suite.VaultTotalSharesEqual(types.NewVaultShares())
 | 
			
		||||
 | 
			
		||||
	totalValue, err = suite.Keeper.GetVaultTotalValue(suite.Ctx, vaultDenom)
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
@ -232,26 +238,32 @@ func (suite *strategyHardTestSuite) TestWithdraw_WithAccumulatedHard() {
 | 
			
		||||
 | 
			
		||||
	suite.CreateVault(vaultDenom, types.STRATEGY_TYPE_HARD)
 | 
			
		||||
 | 
			
		||||
	// Deposits from 2 accounts
 | 
			
		||||
	// Deposits accounts
 | 
			
		||||
	acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0).GetAddress()
 | 
			
		||||
	acc2 := suite.CreateAccount(sdk.NewCoins(startBalance), 1).GetAddress()
 | 
			
		||||
 | 
			
		||||
	err := suite.Keeper.Deposit(suite.Ctx, acc, depositAmount)
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
 | 
			
		||||
	// Deposit from acc2 so the vault doesn't get deleted when withdrawing
 | 
			
		||||
	err = suite.Keeper.Deposit(suite.Ctx, acc2, depositAmount)
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
 | 
			
		||||
	// Direct hard deposit from module account to increase vault value
 | 
			
		||||
	suite.App.FundModuleAccount(suite.Ctx, types.ModuleName, sdk.NewCoins(sdk.NewInt64Coin(vaultDenom, 10)))
 | 
			
		||||
	suite.App.FundModuleAccount(suite.Ctx, types.ModuleName, sdk.NewCoins(sdk.NewInt64Coin(vaultDenom, 20)))
 | 
			
		||||
	macc := suite.AccountKeeper.GetModuleAccount(suite.Ctx, types.ModuleName)
 | 
			
		||||
	suite.HardKeeper.Deposit(suite.Ctx, macc.GetAddress(), sdk.NewCoins(sdk.NewInt64Coin(vaultDenom, 10)))
 | 
			
		||||
	suite.HardKeeper.Deposit(suite.Ctx, macc.GetAddress(), sdk.NewCoins(sdk.NewInt64Coin(vaultDenom, 20)))
 | 
			
		||||
 | 
			
		||||
	// Query account value
 | 
			
		||||
	accValue, err := suite.Keeper.GetVaultAccountValue(suite.Ctx, vaultDenom, acc)
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
	suite.Equal(depositAmount.AddAmount(sdk.NewInt(10)), accValue)
 | 
			
		||||
 | 
			
		||||
	// Withdraw 10, 10 remaining
 | 
			
		||||
	// Withdraw 100, 10 remaining
 | 
			
		||||
	err = suite.Keeper.Withdraw(suite.Ctx, acc, depositAmount)
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
 | 
			
		||||
	// Withdraw again -- too much
 | 
			
		||||
	// Withdraw 100 again -- too much
 | 
			
		||||
	err = suite.Keeper.Withdraw(suite.Ctx, acc, depositAmount)
 | 
			
		||||
	suite.Require().Error(err)
 | 
			
		||||
	suite.Require().ErrorIs(
 | 
			
		||||
@ -268,7 +280,209 @@ func (suite *strategyHardTestSuite) TestWithdraw_WithAccumulatedHard() {
 | 
			
		||||
	err = suite.Keeper.Withdraw(suite.Ctx, acc, sdk.NewCoin(vaultDenom, sdk.NewInt(5)))
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
 | 
			
		||||
	_, err = suite.Keeper.GetVaultAccountValue(suite.Ctx, vaultDenom, acc)
 | 
			
		||||
	suite.Require().Error(err)
 | 
			
		||||
	suite.Require().ErrorIs(err, types.ErrVaultRecordNotFound)
 | 
			
		||||
	accValue, err = suite.Keeper.GetVaultAccountValue(suite.Ctx, vaultDenom, acc)
 | 
			
		||||
	suite.Require().Errorf(
 | 
			
		||||
		err,
 | 
			
		||||
		"account should be deleted when all shares withdrawn but has %s value still",
 | 
			
		||||
		accValue,
 | 
			
		||||
	)
 | 
			
		||||
	suite.Require().Equal("account vault share record for usdx not found", err.Error())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *strategyHardTestSuite) TestAccountShares() {
 | 
			
		||||
	vaultDenom := "usdx"
 | 
			
		||||
	startBalance := sdk.NewInt64Coin(vaultDenom, 1000)
 | 
			
		||||
	depositAmount := sdk.NewInt64Coin(vaultDenom, 100)
 | 
			
		||||
	suite.App.FundModuleAccount(suite.Ctx, types.ModuleName, sdk.NewCoins(sdk.NewInt64Coin(vaultDenom, 1000)))
 | 
			
		||||
 | 
			
		||||
	suite.CreateVault(vaultDenom, types.STRATEGY_TYPE_HARD)
 | 
			
		||||
 | 
			
		||||
	// Deposit from account1
 | 
			
		||||
	acc1 := suite.CreateAccount(sdk.NewCoins(startBalance), 0).GetAddress()
 | 
			
		||||
	acc2 := suite.CreateAccount(sdk.NewCoins(startBalance), 1).GetAddress()
 | 
			
		||||
 | 
			
		||||
	// 1. acc1 deposit 100
 | 
			
		||||
	err := suite.Keeper.Deposit(suite.Ctx, acc1, depositAmount)
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
 | 
			
		||||
	acc1Shares, found := suite.Keeper.GetVaultAccountShares(suite.Ctx, acc1)
 | 
			
		||||
	suite.Require().True(found)
 | 
			
		||||
	suite.Equal(sdk.NewDec(100), acc1Shares.AmountOf(vaultDenom), "initial deposit 1:1 shares")
 | 
			
		||||
 | 
			
		||||
	// 2. Direct hard deposit from module account to increase vault value
 | 
			
		||||
	// Total value: 100 -> 110
 | 
			
		||||
	macc := suite.AccountKeeper.GetModuleAccount(suite.Ctx, types.ModuleName)
 | 
			
		||||
	err = suite.HardKeeper.Deposit(suite.Ctx, macc.GetAddress(), sdk.NewCoins(sdk.NewInt64Coin(vaultDenom, 10)))
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
 | 
			
		||||
	// 2. acc2 deposit 100
 | 
			
		||||
	// share price is 10% more expensive now
 | 
			
		||||
	// hard 110 -> 210
 | 
			
		||||
	err = suite.Keeper.Deposit(suite.Ctx, acc2, depositAmount)
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
 | 
			
		||||
	// 100 * 100 / 210 = 47.619047619 shares
 | 
			
		||||
	// 2.1 price * 47.619047619 = 99.9999999999
 | 
			
		||||
	acc2Value, err := suite.Keeper.GetVaultAccountValue(suite.Ctx, vaultDenom, acc2)
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
	suite.Equal(
 | 
			
		||||
		sdk.NewInt(99),
 | 
			
		||||
		acc2Value.Amount,
 | 
			
		||||
		"value 1 less than deposit amount with different share price, decimals truncated",
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	acc2Shares, found := suite.Keeper.GetVaultAccountShares(suite.Ctx, acc2)
 | 
			
		||||
	suite.Require().True(found)
 | 
			
		||||
	// 100 * 100 / 110 = 190.909090909090909091
 | 
			
		||||
	// QuoInt64() truncates
 | 
			
		||||
	expectedAcc2Shares := sdk.NewDec(100).MulInt64(100).QuoInt64(110)
 | 
			
		||||
	suite.Equal(expectedAcc2Shares, acc2Shares.AmountOf(vaultDenom))
 | 
			
		||||
 | 
			
		||||
	vaultTotalShares, found := suite.Keeper.GetVaultTotalShares(suite.Ctx, vaultDenom)
 | 
			
		||||
	suite.Require().True(found)
 | 
			
		||||
	suite.Equal(sdk.NewDec(100).Add(expectedAcc2Shares), vaultTotalShares.Amount)
 | 
			
		||||
 | 
			
		||||
	// Hard deposit again from module account to triple original value
 | 
			
		||||
	// 210 -> 300
 | 
			
		||||
	suite.HardKeeper.Deposit(suite.Ctx, macc.GetAddress(), sdk.NewCoins(sdk.NewInt64Coin(vaultDenom, 90)))
 | 
			
		||||
 | 
			
		||||
	// Deposit again from acc1
 | 
			
		||||
	err = suite.Keeper.Deposit(suite.Ctx, acc1, depositAmount)
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
 | 
			
		||||
	acc1Shares, found = suite.Keeper.GetVaultAccountShares(suite.Ctx, acc1)
 | 
			
		||||
	suite.Require().True(found)
 | 
			
		||||
	// totalShares = 100 + 90            = 190
 | 
			
		||||
	// totalValue  = 100 + 10 + 100 + 90 = 300
 | 
			
		||||
	// sharesIssued = assetAmount * (shareCount / totalTokens)
 | 
			
		||||
	// sharedIssued = 100 * 190 / 300 = 63.3 = 63
 | 
			
		||||
	// total shares = 100 + 63 = 163
 | 
			
		||||
	suite.Equal(
 | 
			
		||||
		sdk.NewDec(100).Add(sdk.NewDec(100).Mul(vaultTotalShares.Amount).Quo(sdk.NewDec(300))),
 | 
			
		||||
		acc1Shares.AmountOf(vaultDenom),
 | 
			
		||||
		"shares should consist of 100 of 1x share price and 63 of 3x share price",
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *strategyHardTestSuite) TestWithdraw_AccumulatedAmount() {
 | 
			
		||||
	vaultDenom := "usdx"
 | 
			
		||||
	startBalance := sdk.NewInt64Coin(vaultDenom, 1000)
 | 
			
		||||
	depositAmount := sdk.NewInt64Coin(vaultDenom, 100)
 | 
			
		||||
	suite.App.FundModuleAccount(suite.Ctx, types.ModuleName, sdk.NewCoins(sdk.NewInt64Coin(vaultDenom, 1000)))
 | 
			
		||||
 | 
			
		||||
	suite.CreateVault(vaultDenom, types.STRATEGY_TYPE_HARD)
 | 
			
		||||
 | 
			
		||||
	// Deposit from account1
 | 
			
		||||
	acc1 := suite.CreateAccount(sdk.NewCoins(startBalance), 0).GetAddress()
 | 
			
		||||
	acc2 := suite.CreateAccount(sdk.NewCoins(startBalance), 1).GetAddress()
 | 
			
		||||
 | 
			
		||||
	// 1. acc1 deposit 100
 | 
			
		||||
	err := suite.Keeper.Deposit(suite.Ctx, acc1, depositAmount)
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
 | 
			
		||||
	// acc2 deposit 100, just to make sure other deposits do not affect acc1
 | 
			
		||||
	err = suite.Keeper.Deposit(suite.Ctx, acc2, depositAmount)
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
 | 
			
		||||
	acc1Shares, found := suite.Keeper.GetVaultAccountShares(suite.Ctx, acc1)
 | 
			
		||||
	suite.Require().True(found)
 | 
			
		||||
	suite.Equal(sdk.NewDec(100), acc1Shares.AmountOf(vaultDenom), "initial deposit 1:1 shares")
 | 
			
		||||
 | 
			
		||||
	// 2. Direct hard deposit from module account to increase vault value
 | 
			
		||||
	// Total value: 200 -> 220, 110 each account
 | 
			
		||||
	macc := suite.AccountKeeper.GetModuleAccount(suite.Ctx, types.ModuleName)
 | 
			
		||||
	err = suite.HardKeeper.Deposit(suite.Ctx, macc.GetAddress(), sdk.NewCoins(sdk.NewInt64Coin(vaultDenom, 20)))
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
 | 
			
		||||
	// 3. Withdraw all from acc1 - including accumulated amount
 | 
			
		||||
	err = suite.Keeper.Withdraw(suite.Ctx, acc1, depositAmount.AddAmount(sdk.NewInt(10)))
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
 | 
			
		||||
	_, found = suite.Keeper.GetVaultAccountShares(suite.Ctx, acc1)
 | 
			
		||||
	suite.Require().False(found, "should have withdrawn entire shares")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *strategyHardTestSuite) TestWithdraw_AccumulatedTruncated() {
 | 
			
		||||
	vaultDenom := "usdx"
 | 
			
		||||
	startBalance := sdk.NewInt64Coin(vaultDenom, 1000)
 | 
			
		||||
	depositAmount := sdk.NewInt64Coin(vaultDenom, 100)
 | 
			
		||||
	suite.App.FundModuleAccount(suite.Ctx, types.ModuleName, sdk.NewCoins(sdk.NewInt64Coin(vaultDenom, 1000)))
 | 
			
		||||
 | 
			
		||||
	suite.CreateVault(vaultDenom, types.STRATEGY_TYPE_HARD)
 | 
			
		||||
 | 
			
		||||
	// Deposit from account1
 | 
			
		||||
	acc1 := suite.CreateAccount(sdk.NewCoins(startBalance), 0).GetAddress()
 | 
			
		||||
	acc2 := suite.CreateAccount(sdk.NewCoins(startBalance), 1).GetAddress()
 | 
			
		||||
 | 
			
		||||
	// 1. acc1 deposit 100
 | 
			
		||||
	err := suite.Keeper.Deposit(suite.Ctx, acc1, depositAmount)
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
 | 
			
		||||
	// acc2 deposit 100, just to make sure other deposits do not affect acc1
 | 
			
		||||
	err = suite.Keeper.Deposit(suite.Ctx, acc2, depositAmount)
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
 | 
			
		||||
	acc1Shares, found := suite.Keeper.GetVaultAccountShares(suite.Ctx, acc1)
 | 
			
		||||
	suite.Require().True(found)
 | 
			
		||||
	suite.Equal(sdk.NewDec(100), acc1Shares.AmountOf(vaultDenom), "initial deposit 1:1 shares")
 | 
			
		||||
 | 
			
		||||
	// 2. Direct hard deposit from module account to increase vault value
 | 
			
		||||
	// Total value: 200 -> 211, 105.5 each account
 | 
			
		||||
	macc := suite.AccountKeeper.GetModuleAccount(suite.Ctx, types.ModuleName)
 | 
			
		||||
	err = suite.HardKeeper.Deposit(suite.Ctx, macc.GetAddress(), sdk.NewCoins(sdk.NewInt64Coin(vaultDenom, 11)))
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
 | 
			
		||||
	accBal, err := suite.Keeper.GetVaultAccountValue(suite.Ctx, vaultDenom, acc1)
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
	suite.Equal(depositAmount.AddAmount(sdk.NewInt(5)), accBal, "acc1 should have 105 usdx")
 | 
			
		||||
 | 
			
		||||
	// 3. Withdraw all from acc1 - including accumulated amount
 | 
			
		||||
	err = suite.Keeper.Withdraw(suite.Ctx, acc1, depositAmount.AddAmount(sdk.NewInt(5)))
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
 | 
			
		||||
	acc1Shares, found = suite.Keeper.GetVaultAccountShares(suite.Ctx, acc1)
 | 
			
		||||
	suite.Require().Falsef(found, "should have withdrawn entire shares but has %s", acc1Shares)
 | 
			
		||||
 | 
			
		||||
	_, err = suite.Keeper.GetVaultAccountValue(suite.Ctx, vaultDenom, acc1)
 | 
			
		||||
	suite.Require().Error(err)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *strategyHardTestSuite) TestWithdraw_ExpensiveShares() {
 | 
			
		||||
	vaultDenom := "usdx"
 | 
			
		||||
	startBalance := sdk.NewInt64Coin(vaultDenom, 1000)
 | 
			
		||||
	depositAmount := sdk.NewInt64Coin(vaultDenom, 100)
 | 
			
		||||
	suite.App.FundModuleAccount(suite.Ctx, types.ModuleName, sdk.NewCoins(sdk.NewInt64Coin(vaultDenom, 2000)))
 | 
			
		||||
 | 
			
		||||
	suite.CreateVault(vaultDenom, types.STRATEGY_TYPE_HARD)
 | 
			
		||||
 | 
			
		||||
	// Deposit from account1
 | 
			
		||||
	acc1 := suite.CreateAccount(sdk.NewCoins(startBalance), 0).GetAddress()
 | 
			
		||||
 | 
			
		||||
	// 1. acc1 deposit 100
 | 
			
		||||
	err := suite.Keeper.Deposit(suite.Ctx, acc1, depositAmount)
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
 | 
			
		||||
	acc1Shares, found := suite.Keeper.GetVaultAccountShares(suite.Ctx, acc1)
 | 
			
		||||
	suite.Require().True(found)
 | 
			
		||||
	suite.Equal(sdk.NewDec(100), acc1Shares.AmountOf(vaultDenom), "initial deposit 1:1 shares")
 | 
			
		||||
 | 
			
		||||
	// 2. Direct hard deposit from module account to increase vault value
 | 
			
		||||
	// Total value: 100 -> 2000, shares now 10usdx each
 | 
			
		||||
	macc := suite.AccountKeeper.GetModuleAccount(suite.Ctx, types.ModuleName)
 | 
			
		||||
	err = suite.HardKeeper.Deposit(suite.Ctx, macc.GetAddress(), sdk.NewCoins(sdk.NewInt64Coin(vaultDenom, 1900)))
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
 | 
			
		||||
	accBal, err := suite.Keeper.GetVaultAccountValue(suite.Ctx, vaultDenom, acc1)
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
	suite.Equal(sdk.NewInt(2000), accBal.Amount, "acc1 should have 2000 usdx")
 | 
			
		||||
 | 
			
		||||
	// 3. Withdraw all from acc1 - including accumulated amount
 | 
			
		||||
	err = suite.Keeper.Withdraw(suite.Ctx, acc1, sdk.NewInt64Coin(vaultDenom, 2000))
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
 | 
			
		||||
	acc1Shares, found = suite.Keeper.GetVaultAccountShares(suite.Ctx, acc1)
 | 
			
		||||
	suite.Require().Falsef(found, "should have withdrawn entire shares but has %s", acc1Shares)
 | 
			
		||||
 | 
			
		||||
	_, err = suite.Keeper.GetVaultAccountValue(suite.Ctx, vaultDenom, acc1)
 | 
			
		||||
	suite.Require().Error(err)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,24 +1,25 @@
 | 
			
		||||
package keeper
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/store/prefix"
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
			
		||||
	"github.com/kava-labs/kava/x/earn/types"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// GetVaultTotalSupplied returns the total balance supplied to the vault. This
 | 
			
		||||
// GetVaultTotalShares returns the total balance supplied to the vault. This
 | 
			
		||||
// may not necessarily be the current value of the vault, as it is the sum
 | 
			
		||||
// of the supplied denom and the value may be higher due to accumulated APYs.
 | 
			
		||||
func (k *Keeper) GetVaultTotalSupplied(
 | 
			
		||||
func (k *Keeper) GetVaultTotalShares(
 | 
			
		||||
	ctx sdk.Context,
 | 
			
		||||
	denom string,
 | 
			
		||||
) (sdk.Coin, error) {
 | 
			
		||||
) (types.VaultShare, bool) {
 | 
			
		||||
	vault, found := k.GetVaultRecord(ctx, denom)
 | 
			
		||||
	if !found {
 | 
			
		||||
		return sdk.Coin{}, types.ErrVaultRecordNotFound
 | 
			
		||||
		return types.VaultShare{}, false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return vault.TotalSupply, nil
 | 
			
		||||
	return vault.TotalShares, true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetTotalValue returns the total **value** of all coins in this vault,
 | 
			
		||||
@ -47,16 +48,16 @@ func (k *Keeper) GetVaultTotalValue(
 | 
			
		||||
 | 
			
		||||
// GetVaultAccountSupplied returns the supplied amount for a single address
 | 
			
		||||
// within a vault.
 | 
			
		||||
func (k *Keeper) GetVaultAccountSupplied(
 | 
			
		||||
func (k *Keeper) GetVaultAccountShares(
 | 
			
		||||
	ctx sdk.Context,
 | 
			
		||||
	acc sdk.AccAddress,
 | 
			
		||||
) (sdk.Coins, error) {
 | 
			
		||||
) (types.VaultShares, bool) {
 | 
			
		||||
	vaultShareRecord, found := k.GetVaultShareRecord(ctx, acc)
 | 
			
		||||
	if !found {
 | 
			
		||||
		return sdk.Coins{}, types.ErrVaultShareRecordNotFound
 | 
			
		||||
		return nil, false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return vaultShareRecord.AmountSupplied, nil
 | 
			
		||||
	return vaultShareRecord.Shares, true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetVaultAccountValue returns the value of a single address within a vault
 | 
			
		||||
@ -66,190 +67,10 @@ func (k *Keeper) GetVaultAccountValue(
 | 
			
		||||
	denom string,
 | 
			
		||||
	acc sdk.AccAddress,
 | 
			
		||||
) (sdk.Coin, error) {
 | 
			
		||||
	totalSupplied, err := k.GetVaultTotalSupplied(ctx, denom)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return sdk.Coin{}, err
 | 
			
		||||
	accShares, found := k.GetVaultAccountShares(ctx, acc)
 | 
			
		||||
	if !found {
 | 
			
		||||
		return sdk.Coin{}, fmt.Errorf("account vault share record for %s not found", denom)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	accSupplied, err := k.GetVaultAccountSupplied(ctx, acc)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return sdk.Coin{}, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	vaultTotalValue, err := k.GetVaultTotalValue(ctx, denom)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return sdk.Coin{}, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Percent of vault account ownership = accountSupply / totalSupply
 | 
			
		||||
	// Value of vault account ownership = percentOwned * totalValue
 | 
			
		||||
	vaultShare := accSupplied.AmountOf(denom).ToDec().Quo(totalSupplied.Amount.ToDec())
 | 
			
		||||
	shareValueDec := vaultTotalValue.Amount.ToDec().Mul(vaultShare)
 | 
			
		||||
 | 
			
		||||
	return sdk.NewCoin(denom, shareValueDec.TruncateInt()), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ----------------------------------------------------------------------------
 | 
			
		||||
// VaultRecord -- vault total supplies
 | 
			
		||||
 | 
			
		||||
// GetVaultRecord returns the vault record for a given denom.
 | 
			
		||||
func (k *Keeper) GetVaultRecord(
 | 
			
		||||
	ctx sdk.Context,
 | 
			
		||||
	vaultDenom string,
 | 
			
		||||
) (types.VaultRecord, bool) {
 | 
			
		||||
	store := prefix.NewStore(ctx.KVStore(k.key), types.VaultRecordKeyPrefix)
 | 
			
		||||
 | 
			
		||||
	bz := store.Get(types.VaultKey(vaultDenom))
 | 
			
		||||
	if bz == nil {
 | 
			
		||||
		return types.VaultRecord{}, false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var record types.VaultRecord
 | 
			
		||||
	k.cdc.MustUnmarshal(bz, &record)
 | 
			
		||||
 | 
			
		||||
	return record, true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateVaultRecord updates the vault record in state for a given denom. This
 | 
			
		||||
// deletes it if the supply is zero and updates the state if supply is non-zero.
 | 
			
		||||
func (k *Keeper) UpdateVaultRecord(
 | 
			
		||||
	ctx sdk.Context,
 | 
			
		||||
	vaultRecord types.VaultRecord,
 | 
			
		||||
) {
 | 
			
		||||
	if vaultRecord.TotalSupply.IsZero() {
 | 
			
		||||
		k.DeleteVaultRecord(ctx, vaultRecord.Denom)
 | 
			
		||||
	} else {
 | 
			
		||||
		k.SetVaultRecord(ctx, vaultRecord)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteVaultRecord deletes the vault record for a given denom.
 | 
			
		||||
func (k *Keeper) DeleteVaultRecord(ctx sdk.Context, vaultDenom string) {
 | 
			
		||||
	store := prefix.NewStore(ctx.KVStore(k.key), types.VaultRecordKeyPrefix)
 | 
			
		||||
	store.Delete(types.VaultKey(vaultDenom))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetVaultRecord sets the vault record for a given denom.
 | 
			
		||||
func (k *Keeper) SetVaultRecord(ctx sdk.Context, record types.VaultRecord) {
 | 
			
		||||
	store := prefix.NewStore(ctx.KVStore(k.key), types.VaultRecordKeyPrefix)
 | 
			
		||||
	bz := k.cdc.MustMarshal(&record)
 | 
			
		||||
	store.Set(types.VaultKey(record.Denom), bz)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IterateVaultRecords iterates over all vault objects in the store and performs
 | 
			
		||||
// a callback function.
 | 
			
		||||
func (k Keeper) IterateVaultRecords(
 | 
			
		||||
	ctx sdk.Context,
 | 
			
		||||
	cb func(record types.VaultRecord) (stop bool),
 | 
			
		||||
) {
 | 
			
		||||
	store := prefix.NewStore(ctx.KVStore(k.key), types.VaultRecordKeyPrefix)
 | 
			
		||||
	iterator := sdk.KVStorePrefixIterator(store, []byte{})
 | 
			
		||||
	defer iterator.Close()
 | 
			
		||||
 | 
			
		||||
	for ; iterator.Valid(); iterator.Next() {
 | 
			
		||||
		var record types.VaultRecord
 | 
			
		||||
		k.cdc.MustUnmarshal(iterator.Value(), &record)
 | 
			
		||||
		if cb(record) {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetAllVaultRecords returns all vault records from the store.
 | 
			
		||||
func (k Keeper) GetAllVaultRecords(ctx sdk.Context) types.VaultRecords {
 | 
			
		||||
	var records types.VaultRecords
 | 
			
		||||
 | 
			
		||||
	k.IterateVaultRecords(ctx, func(record types.VaultRecord) bool {
 | 
			
		||||
		records = append(records, record)
 | 
			
		||||
		return false
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	return records
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ----------------------------------------------------------------------------
 | 
			
		||||
// VaultShare -- user shares per vault
 | 
			
		||||
 | 
			
		||||
// GetVaultShareRecord returns the vault share record for a given denom and
 | 
			
		||||
// account.
 | 
			
		||||
func (k *Keeper) GetVaultShareRecord(
 | 
			
		||||
	ctx sdk.Context,
 | 
			
		||||
	acc sdk.AccAddress,
 | 
			
		||||
) (types.VaultShareRecord, bool) {
 | 
			
		||||
	store := prefix.NewStore(ctx.KVStore(k.key), types.VaultShareRecordKeyPrefix)
 | 
			
		||||
 | 
			
		||||
	bz := store.Get(types.DepositorVaultSharesKey(acc))
 | 
			
		||||
	if bz == nil {
 | 
			
		||||
		return types.VaultShareRecord{}, false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var record types.VaultShareRecord
 | 
			
		||||
	k.cdc.MustUnmarshal(bz, &record)
 | 
			
		||||
 | 
			
		||||
	return record, true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateVaultShareRecord updates the vault share record in state for a given
 | 
			
		||||
// denom and account. This deletes it if the supply is zero and updates the
 | 
			
		||||
// state if supply is non-zero.
 | 
			
		||||
func (k *Keeper) UpdateVaultShareRecord(
 | 
			
		||||
	ctx sdk.Context,
 | 
			
		||||
	record types.VaultShareRecord,
 | 
			
		||||
) {
 | 
			
		||||
	if record.AmountSupplied.IsZero() {
 | 
			
		||||
		k.DeleteVaultShareRecord(ctx, record.Depositor)
 | 
			
		||||
	} else {
 | 
			
		||||
		k.SetVaultShareRecord(ctx, record)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteVaultShareRecord deletes the vault share record for a given denom and
 | 
			
		||||
// account.
 | 
			
		||||
func (k *Keeper) DeleteVaultShareRecord(
 | 
			
		||||
	ctx sdk.Context,
 | 
			
		||||
	acc sdk.AccAddress,
 | 
			
		||||
) {
 | 
			
		||||
	store := prefix.NewStore(ctx.KVStore(k.key), types.VaultShareRecordKeyPrefix)
 | 
			
		||||
	store.Delete(types.DepositorVaultSharesKey(acc))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetVaultShareRecord sets the vault share record for a given denom and account.
 | 
			
		||||
func (k *Keeper) SetVaultShareRecord(
 | 
			
		||||
	ctx sdk.Context,
 | 
			
		||||
	record types.VaultShareRecord,
 | 
			
		||||
) {
 | 
			
		||||
	store := prefix.NewStore(ctx.KVStore(k.key), types.VaultShareRecordKeyPrefix)
 | 
			
		||||
	bz := k.cdc.MustMarshal(&record)
 | 
			
		||||
	store.Set(types.DepositorVaultSharesKey(record.Depositor), bz)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IterateVaultShareRecords iterates over all vault share objects in the store
 | 
			
		||||
// and performs a callback function.
 | 
			
		||||
func (k Keeper) IterateVaultShareRecords(
 | 
			
		||||
	ctx sdk.Context,
 | 
			
		||||
	cb func(record types.VaultShareRecord) (stop bool),
 | 
			
		||||
) {
 | 
			
		||||
	store := prefix.NewStore(ctx.KVStore(k.key), types.VaultShareRecordKeyPrefix)
 | 
			
		||||
	iterator := sdk.KVStorePrefixIterator(store, []byte{})
 | 
			
		||||
	defer iterator.Close()
 | 
			
		||||
 | 
			
		||||
	for ; iterator.Valid(); iterator.Next() {
 | 
			
		||||
		var record types.VaultShareRecord
 | 
			
		||||
		k.cdc.MustUnmarshal(iterator.Value(), &record)
 | 
			
		||||
		if cb(record) {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetAllVaultShareRecords returns all vault share records from the store.
 | 
			
		||||
func (k Keeper) GetAllVaultShareRecords(ctx sdk.Context) types.VaultShareRecords {
 | 
			
		||||
	var records types.VaultShareRecords
 | 
			
		||||
 | 
			
		||||
	k.IterateVaultShareRecords(ctx, func(record types.VaultShareRecord) bool {
 | 
			
		||||
		records = append(records, record)
 | 
			
		||||
		return false
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	return records
 | 
			
		||||
	return k.ConvertToAssets(ctx, accShares.GetShare(denom))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										85
									
								
								x/earn/keeper/vault_record.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								x/earn/keeper/vault_record.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,85 @@
 | 
			
		||||
package keeper
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/store/prefix"
 | 
			
		||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
			
		||||
	"github.com/kava-labs/kava/x/earn/types"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ----------------------------------------------------------------------------
 | 
			
		||||
// VaultRecord -- vault total shares
 | 
			
		||||
 | 
			
		||||
// GetVaultRecord returns the vault record for a given denom.
 | 
			
		||||
func (k *Keeper) GetVaultRecord(
 | 
			
		||||
	ctx sdk.Context,
 | 
			
		||||
	vaultDenom string,
 | 
			
		||||
) (types.VaultRecord, bool) {
 | 
			
		||||
	store := prefix.NewStore(ctx.KVStore(k.key), types.VaultRecordKeyPrefix)
 | 
			
		||||
 | 
			
		||||
	bz := store.Get(types.VaultKey(vaultDenom))
 | 
			
		||||
	if bz == nil {
 | 
			
		||||
		return types.VaultRecord{}, false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var record types.VaultRecord
 | 
			
		||||
	k.cdc.MustUnmarshal(bz, &record)
 | 
			
		||||
 | 
			
		||||
	return record, true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateVaultRecord updates the vault record in state for a given denom. This
 | 
			
		||||
// deletes it if the supply is zero and updates the state if supply is non-zero.
 | 
			
		||||
func (k *Keeper) UpdateVaultRecord(
 | 
			
		||||
	ctx sdk.Context,
 | 
			
		||||
	vaultRecord types.VaultRecord,
 | 
			
		||||
) {
 | 
			
		||||
	if vaultRecord.TotalShares.Amount.IsZero() {
 | 
			
		||||
		k.DeleteVaultRecord(ctx, vaultRecord.TotalShares.Denom)
 | 
			
		||||
	} else {
 | 
			
		||||
		k.SetVaultRecord(ctx, vaultRecord)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteVaultRecord deletes the vault record for a given denom.
 | 
			
		||||
func (k *Keeper) DeleteVaultRecord(ctx sdk.Context, vaultDenom string) {
 | 
			
		||||
	store := prefix.NewStore(ctx.KVStore(k.key), types.VaultRecordKeyPrefix)
 | 
			
		||||
	store.Delete(types.VaultKey(vaultDenom))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetVaultRecord sets the vault record for a given denom.
 | 
			
		||||
func (k *Keeper) SetVaultRecord(ctx sdk.Context, record types.VaultRecord) {
 | 
			
		||||
	store := prefix.NewStore(ctx.KVStore(k.key), types.VaultRecordKeyPrefix)
 | 
			
		||||
	bz := k.cdc.MustMarshal(&record)
 | 
			
		||||
	store.Set(types.VaultKey(record.TotalShares.Denom), bz)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IterateVaultRecords iterates over all vault objects in the store and performs
 | 
			
		||||
// a callback function.
 | 
			
		||||
func (k Keeper) IterateVaultRecords(
 | 
			
		||||
	ctx sdk.Context,
 | 
			
		||||
	cb func(record types.VaultRecord) (stop bool),
 | 
			
		||||
) {
 | 
			
		||||
	store := prefix.NewStore(ctx.KVStore(k.key), types.VaultRecordKeyPrefix)
 | 
			
		||||
	iterator := sdk.KVStorePrefixIterator(store, []byte{})
 | 
			
		||||
	defer iterator.Close()
 | 
			
		||||
 | 
			
		||||
	for ; iterator.Valid(); iterator.Next() {
 | 
			
		||||
		var record types.VaultRecord
 | 
			
		||||
		k.cdc.MustUnmarshal(iterator.Value(), &record)
 | 
			
		||||
		if cb(record) {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetAllVaultRecords returns all vault records from the store.
 | 
			
		||||
func (k Keeper) GetAllVaultRecords(ctx sdk.Context) types.VaultRecords {
 | 
			
		||||
	var records types.VaultRecords
 | 
			
		||||
 | 
			
		||||
	k.IterateVaultRecords(ctx, func(record types.VaultRecord) bool {
 | 
			
		||||
		records = append(records, record)
 | 
			
		||||
		return false
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	return records
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										82
									
								
								x/earn/keeper/vault_share.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								x/earn/keeper/vault_share.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,82 @@
 | 
			
		||||
package keeper
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
			
		||||
	"github.com/kava-labs/kava/x/earn/types"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ConvertToShares converts a given amount of tokens to shares.
 | 
			
		||||
func (k *Keeper) ConvertToShares(ctx sdk.Context, assets sdk.Coin) (types.VaultShare, error) {
 | 
			
		||||
	totalShares, found := k.GetVaultTotalShares(ctx, assets.Denom)
 | 
			
		||||
	if !found {
 | 
			
		||||
		// No shares issued yet, so shares are issued 1:1
 | 
			
		||||
		return types.NewVaultShare(assets.Denom, assets.Amount.ToDec()), nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	totalValue, err := k.GetVaultTotalValue(ctx, assets.Denom)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return types.VaultShare{}, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if totalValue.Amount.IsZero() {
 | 
			
		||||
		return types.VaultShare{}, fmt.Errorf("total value of vault is zero")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// sharePrice   = totalValue / totalShares
 | 
			
		||||
	// issuedShares = assets / sharePrice
 | 
			
		||||
	// issuedShares = assets / (totalValue / totalShares)
 | 
			
		||||
	//              = assets * (totalShares / totalValue)
 | 
			
		||||
	//              = (assets * totalShares) / totalValue
 | 
			
		||||
	//
 | 
			
		||||
	// Multiply by reciprocal of sharePrice to avoid two divisions and limit
 | 
			
		||||
	// rounding to one time. Per-share price is also not used as there is a loss
 | 
			
		||||
	// of precision.
 | 
			
		||||
 | 
			
		||||
	// Division is done at the last step as there is a slight amount that is
 | 
			
		||||
	// rounded down.
 | 
			
		||||
	// For example:
 | 
			
		||||
	// 100 * 100 / 105   == 10000 / 105                == 95.238095238095238095
 | 
			
		||||
	// 100 * (100 / 105) == 100 * 0.952380952380952380 == 95.238095238095238000
 | 
			
		||||
	//                    rounded down and truncated ^    loss of precision ^
 | 
			
		||||
	issuedShares := assets.Amount.ToDec().Mul(totalShares.Amount).QuoTruncate(totalValue.Amount.ToDec())
 | 
			
		||||
 | 
			
		||||
	if issuedShares.IsZero() {
 | 
			
		||||
		return types.VaultShare{}, fmt.Errorf("share count is zero")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return types.NewVaultShare(assets.Denom, issuedShares), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ConvertToAssets converts a given amount of shares to tokens.
 | 
			
		||||
func (k *Keeper) ConvertToAssets(ctx sdk.Context, share types.VaultShare) (sdk.Coin, error) {
 | 
			
		||||
	totalVaultShares, found := k.GetVaultTotalShares(ctx, share.Denom)
 | 
			
		||||
	if !found {
 | 
			
		||||
		return sdk.Coin{}, fmt.Errorf("vault for %s not found", share.Denom)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	totalValue, err := k.GetVaultTotalValue(ctx, share.Denom)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return sdk.Coin{}, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// percentOwnership := accShares / totalVaultShares
 | 
			
		||||
	// accValue := totalValue * percentOwnership
 | 
			
		||||
	// accValue := totalValue * accShares / totalVaultShares
 | 
			
		||||
	// Division must be last to avoid rounding errors and properly truncate.
 | 
			
		||||
	value := totalValue.Amount.ToDec().Mul(share.Amount).QuoTruncate(totalVaultShares.Amount)
 | 
			
		||||
 | 
			
		||||
	return sdk.NewCoin(share.Denom, value.TruncateInt()), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ShareIsDust returns true if the share value is less than 1 coin
 | 
			
		||||
func (k *Keeper) ShareIsDust(ctx sdk.Context, share types.VaultShare) (bool, error) {
 | 
			
		||||
	coin, err := k.ConvertToAssets(ctx, share)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Truncated int, becomes zero if < 1
 | 
			
		||||
	return coin.IsZero(), nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										94
									
								
								x/earn/keeper/vault_share_record.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								x/earn/keeper/vault_share_record.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,94 @@
 | 
			
		||||
package keeper
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/store/prefix"
 | 
			
		||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
			
		||||
	"github.com/kava-labs/kava/x/earn/types"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ----------------------------------------------------------------------------
 | 
			
		||||
// VaultShareRecords -- user shares per vault
 | 
			
		||||
 | 
			
		||||
// GetVaultShareRecord returns the vault share record for a given denom and
 | 
			
		||||
// account.
 | 
			
		||||
func (k *Keeper) GetVaultShareRecord(
 | 
			
		||||
	ctx sdk.Context,
 | 
			
		||||
	acc sdk.AccAddress,
 | 
			
		||||
) (types.VaultShareRecord, bool) {
 | 
			
		||||
	store := prefix.NewStore(ctx.KVStore(k.key), types.VaultShareRecordKeyPrefix)
 | 
			
		||||
 | 
			
		||||
	bz := store.Get(types.DepositorVaultSharesKey(acc))
 | 
			
		||||
	if bz == nil {
 | 
			
		||||
		return types.VaultShareRecord{}, false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var record types.VaultShareRecord
 | 
			
		||||
	k.cdc.MustUnmarshal(bz, &record)
 | 
			
		||||
 | 
			
		||||
	return record, true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateVaultShareRecord updates the vault share record in state for a given
 | 
			
		||||
// denom and account. This deletes it if the supply is zero and updates the
 | 
			
		||||
// state if supply is non-zero.
 | 
			
		||||
func (k *Keeper) UpdateVaultShareRecord(
 | 
			
		||||
	ctx sdk.Context,
 | 
			
		||||
	record types.VaultShareRecord,
 | 
			
		||||
) {
 | 
			
		||||
	if record.Shares.IsZero() {
 | 
			
		||||
		k.DeleteVaultShareRecord(ctx, record.Depositor)
 | 
			
		||||
	} else {
 | 
			
		||||
		k.SetVaultShareRecord(ctx, record)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteVaultShareRecord deletes the vault share record for a given denom and
 | 
			
		||||
// account.
 | 
			
		||||
func (k *Keeper) DeleteVaultShareRecord(
 | 
			
		||||
	ctx sdk.Context,
 | 
			
		||||
	acc sdk.AccAddress,
 | 
			
		||||
) {
 | 
			
		||||
	store := prefix.NewStore(ctx.KVStore(k.key), types.VaultShareRecordKeyPrefix)
 | 
			
		||||
	store.Delete(types.DepositorVaultSharesKey(acc))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetVaultShareRecord sets the vault share record for a given denom and account.
 | 
			
		||||
func (k *Keeper) SetVaultShareRecord(
 | 
			
		||||
	ctx sdk.Context,
 | 
			
		||||
	record types.VaultShareRecord,
 | 
			
		||||
) {
 | 
			
		||||
	store := prefix.NewStore(ctx.KVStore(k.key), types.VaultShareRecordKeyPrefix)
 | 
			
		||||
	bz := k.cdc.MustMarshal(&record)
 | 
			
		||||
	store.Set(types.DepositorVaultSharesKey(record.Depositor), bz)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IterateVaultShareRecords iterates over all vault share objects in the store
 | 
			
		||||
// and performs a callback function.
 | 
			
		||||
func (k Keeper) IterateVaultShareRecords(
 | 
			
		||||
	ctx sdk.Context,
 | 
			
		||||
	cb func(record types.VaultShareRecord) (stop bool),
 | 
			
		||||
) {
 | 
			
		||||
	store := prefix.NewStore(ctx.KVStore(k.key), types.VaultShareRecordKeyPrefix)
 | 
			
		||||
	iterator := sdk.KVStorePrefixIterator(store, []byte{})
 | 
			
		||||
	defer iterator.Close()
 | 
			
		||||
 | 
			
		||||
	for ; iterator.Valid(); iterator.Next() {
 | 
			
		||||
		var record types.VaultShareRecord
 | 
			
		||||
		k.cdc.MustUnmarshal(iterator.Value(), &record)
 | 
			
		||||
		if cb(record) {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetAllVaultShareRecords returns all vault share records from the store.
 | 
			
		||||
func (k Keeper) GetAllVaultShareRecords(ctx sdk.Context) types.VaultShareRecords {
 | 
			
		||||
	var records types.VaultShareRecords
 | 
			
		||||
 | 
			
		||||
	k.IterateVaultShareRecords(ctx, func(record types.VaultShareRecord) bool {
 | 
			
		||||
		records = append(records, record)
 | 
			
		||||
		return false
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	return records
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										90
									
								
								x/earn/keeper/vault_share_record_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								x/earn/keeper/vault_share_record_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,90 @@
 | 
			
		||||
package keeper_test
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
			
		||||
	"github.com/kava-labs/kava/x/earn/types"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ----------------------------------------------------------------------------
 | 
			
		||||
// State methods
 | 
			
		||||
 | 
			
		||||
func (suite *vaultTestSuite) TestGetVaultRecord() {
 | 
			
		||||
	record := types.NewVaultRecord("usdx", sdk.ZeroDec())
 | 
			
		||||
 | 
			
		||||
	_, found := suite.Keeper.GetVaultRecord(suite.Ctx, record.TotalShares.Denom)
 | 
			
		||||
	suite.Require().False(found)
 | 
			
		||||
 | 
			
		||||
	suite.Keeper.SetVaultRecord(suite.Ctx, record)
 | 
			
		||||
 | 
			
		||||
	stateRecord, found := suite.Keeper.GetVaultRecord(suite.Ctx, record.TotalShares.Denom)
 | 
			
		||||
	suite.Require().True(found)
 | 
			
		||||
	suite.Require().Equal(record, stateRecord)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *vaultTestSuite) TestUpdateVaultRecord() {
 | 
			
		||||
	record := types.NewVaultRecord("usdx", sdk.ZeroDec())
 | 
			
		||||
 | 
			
		||||
	record.TotalShares = types.NewVaultShare("usdx", sdk.NewDec(100))
 | 
			
		||||
 | 
			
		||||
	// Update vault
 | 
			
		||||
	suite.Keeper.UpdateVaultRecord(suite.Ctx, record)
 | 
			
		||||
 | 
			
		||||
	stateRecord, found := suite.Keeper.GetVaultRecord(suite.Ctx, record.TotalShares.Denom)
 | 
			
		||||
	suite.Require().True(found, "vault record with supply should exist")
 | 
			
		||||
	suite.Require().Equal(record, stateRecord)
 | 
			
		||||
 | 
			
		||||
	// Remove supply
 | 
			
		||||
	record.TotalShares = types.NewVaultShare("usdx", sdk.NewDec(0))
 | 
			
		||||
	suite.Keeper.UpdateVaultRecord(suite.Ctx, record)
 | 
			
		||||
 | 
			
		||||
	_, found = suite.Keeper.GetVaultRecord(suite.Ctx, record.TotalShares.Denom)
 | 
			
		||||
	suite.Require().False(found, "vault record with 0 supply should be deleted")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *vaultTestSuite) TestGetVaultShareRecord() {
 | 
			
		||||
	vaultDenom := "usdx"
 | 
			
		||||
	startBalance := sdk.NewInt64Coin(vaultDenom, 1000)
 | 
			
		||||
	acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
 | 
			
		||||
 | 
			
		||||
	record := types.NewVaultShareRecord(acc.GetAddress(), types.NewVaultShares())
 | 
			
		||||
 | 
			
		||||
	// Check share doesn't exist before deposit
 | 
			
		||||
 | 
			
		||||
	_, found := suite.Keeper.GetVaultShareRecord(suite.Ctx, acc.GetAddress())
 | 
			
		||||
	suite.Require().False(found, "vault share record should not exist before deposit")
 | 
			
		||||
 | 
			
		||||
	// Update share record
 | 
			
		||||
	record.Shares = types.NewVaultShares(
 | 
			
		||||
		types.NewVaultShare(vaultDenom, sdk.NewDec(100)),
 | 
			
		||||
	)
 | 
			
		||||
	suite.Keeper.SetVaultShareRecord(suite.Ctx, record)
 | 
			
		||||
 | 
			
		||||
	// Check share exists and matches set value
 | 
			
		||||
	stateRecord, found := suite.Keeper.GetVaultShareRecord(suite.Ctx, acc.GetAddress())
 | 
			
		||||
	suite.Require().True(found)
 | 
			
		||||
	suite.Require().Equal(record, stateRecord)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *vaultTestSuite) TestUpdateVaultShareRecord() {
 | 
			
		||||
	vaultDenom := "usdx"
 | 
			
		||||
	startBalance := sdk.NewInt64Coin(vaultDenom, 1000)
 | 
			
		||||
	acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
 | 
			
		||||
 | 
			
		||||
	record := types.NewVaultShareRecord(acc.GetAddress(), types.NewVaultShares(
 | 
			
		||||
		types.NewVaultShare(vaultDenom, sdk.NewDec(100)),
 | 
			
		||||
	))
 | 
			
		||||
 | 
			
		||||
	// Update vault
 | 
			
		||||
	suite.Keeper.UpdateVaultShareRecord(suite.Ctx, record)
 | 
			
		||||
 | 
			
		||||
	stateRecord, found := suite.Keeper.GetVaultShareRecord(suite.Ctx, acc.GetAddress())
 | 
			
		||||
	suite.Require().True(found, "vault share record with supply should exist")
 | 
			
		||||
	suite.Require().Equal(record, stateRecord)
 | 
			
		||||
 | 
			
		||||
	// Remove supply
 | 
			
		||||
	record.Shares = types.NewVaultShares()
 | 
			
		||||
	suite.Keeper.UpdateVaultShareRecord(suite.Ctx, record)
 | 
			
		||||
 | 
			
		||||
	_, found = suite.Keeper.GetVaultShareRecord(suite.Ctx, acc.GetAddress())
 | 
			
		||||
	suite.Require().False(found, "vault share record with 0 supply should be deleted")
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										132
									
								
								x/earn/keeper/vault_share_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								x/earn/keeper/vault_share_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,132 @@
 | 
			
		||||
package keeper_test
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
			
		||||
	"github.com/stretchr/testify/assert"
 | 
			
		||||
	"github.com/stretchr/testify/suite"
 | 
			
		||||
 | 
			
		||||
	"github.com/kava-labs/kava/x/earn/testutil"
 | 
			
		||||
	"github.com/kava-labs/kava/x/earn/types"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type vaultShareTestSuite struct {
 | 
			
		||||
	testutil.Suite
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *vaultShareTestSuite) SetupTest() {
 | 
			
		||||
	suite.Suite.SetupTest()
 | 
			
		||||
	suite.Keeper.SetParams(suite.Ctx, types.DefaultParams())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestVaultShareTestSuite(t *testing.T) {
 | 
			
		||||
	suite.Run(t, new(vaultShareTestSuite))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *vaultShareTestSuite) TestConvertToShares() {
 | 
			
		||||
	vaultDenom := "usdx"
 | 
			
		||||
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		name          string
 | 
			
		||||
		beforeConvert func()
 | 
			
		||||
		giveAmount    sdk.Coin
 | 
			
		||||
		wantShares    types.VaultShare
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name:          "initial 1:1",
 | 
			
		||||
			beforeConvert: func() {},
 | 
			
		||||
			giveAmount:    sdk.NewCoin(vaultDenom, sdk.NewInt(100)),
 | 
			
		||||
			wantShares:    types.NewVaultShare(vaultDenom, sdk.NewDec(100)),
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "value doubled",
 | 
			
		||||
 | 
			
		||||
			beforeConvert: func() {
 | 
			
		||||
				// set total shares set total value for hard
 | 
			
		||||
				// value is double than shares
 | 
			
		||||
				// shares is 2x price now
 | 
			
		||||
				suite.addTotalShareAndValue(vaultDenom, sdk.NewDec(100), sdk.NewInt(200))
 | 
			
		||||
			},
 | 
			
		||||
			giveAmount: sdk.NewCoin(vaultDenom, sdk.NewInt(100)),
 | 
			
		||||
			wantShares: types.NewVaultShare(vaultDenom, sdk.NewDec(50)),
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "truncate",
 | 
			
		||||
 | 
			
		||||
			beforeConvert: func() {
 | 
			
		||||
				suite.addTotalShareAndValue(vaultDenom, sdk.NewDec(1000), sdk.NewInt(1001))
 | 
			
		||||
			},
 | 
			
		||||
			giveAmount: sdk.NewCoin(vaultDenom, sdk.NewInt(100)),
 | 
			
		||||
			// 100 * 100 / 101 = 99.0099something
 | 
			
		||||
			wantShares: types.NewVaultShare(vaultDenom, sdk.NewDec(100).MulInt64(1000).QuoInt64(1001)),
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, tt := range tests {
 | 
			
		||||
		suite.Run(tt.name, func() {
 | 
			
		||||
			// Reset state
 | 
			
		||||
			suite.Suite.SetupTest()
 | 
			
		||||
			suite.CreateVault(vaultDenom, types.STRATEGY_TYPE_HARD)
 | 
			
		||||
			err := suite.App.FundModuleAccount(
 | 
			
		||||
				suite.Ctx,
 | 
			
		||||
				types.ModuleName,
 | 
			
		||||
				sdk.NewCoins(sdk.NewInt64Coin(vaultDenom, 10000)),
 | 
			
		||||
			)
 | 
			
		||||
			suite.Require().NoError(err)
 | 
			
		||||
 | 
			
		||||
			// Run any deposits or any other setup
 | 
			
		||||
			tt.beforeConvert()
 | 
			
		||||
 | 
			
		||||
			issuedShares, err := suite.Keeper.ConvertToShares(suite.Ctx, tt.giveAmount)
 | 
			
		||||
			suite.Require().NoError(err)
 | 
			
		||||
 | 
			
		||||
			suite.Equal(tt.wantShares, issuedShares)
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *vaultShareTestSuite) addTotalShareAndValue(
 | 
			
		||||
	vaultDenom string,
 | 
			
		||||
	vaultShares sdk.Dec,
 | 
			
		||||
	hardDeposit sdk.Int,
 | 
			
		||||
) {
 | 
			
		||||
	macc := suite.AccountKeeper.GetModuleAccount(suite.Ctx, types.ModuleName)
 | 
			
		||||
 | 
			
		||||
	vaultRecord, found := suite.Keeper.GetVaultRecord(suite.Ctx, vaultDenom)
 | 
			
		||||
	if !found {
 | 
			
		||||
		vaultRecord = types.NewVaultRecord(vaultDenom, sdk.ZeroDec())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Add to vault record
 | 
			
		||||
	vaultRecord.TotalShares.Amount = vaultRecord.TotalShares.Amount.Add(vaultShares)
 | 
			
		||||
 | 
			
		||||
	// set total shares
 | 
			
		||||
	suite.Keeper.UpdateVaultRecord(
 | 
			
		||||
		suite.Ctx,
 | 
			
		||||
		vaultRecord,
 | 
			
		||||
	)
 | 
			
		||||
	// add value for hard -- this does not set
 | 
			
		||||
	err := suite.HardKeeper.Deposit(
 | 
			
		||||
		suite.Ctx,
 | 
			
		||||
		macc.GetAddress(),
 | 
			
		||||
		sdk.NewCoins(sdk.NewCoin(vaultDenom, hardDeposit)),
 | 
			
		||||
	)
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestPrecisionMulQuoOrder(t *testing.T) {
 | 
			
		||||
	assetAmount := sdk.NewDec(100)
 | 
			
		||||
	totalShares := sdk.NewDec(100)
 | 
			
		||||
	totalValue := sdk.NewDec(105)
 | 
			
		||||
 | 
			
		||||
	// issuedShares =  assetAmount * (totalValue / totalShares)
 | 
			
		||||
	//              = (assetAmount * totalShares) / totalValue
 | 
			
		||||
	mulFirst := assetAmount.Mul(totalShares).QuoTruncate(totalValue)
 | 
			
		||||
	quoFirst := assetAmount.Mul(totalShares.QuoTruncate(totalValue))
 | 
			
		||||
 | 
			
		||||
	assert.Equal(t, sdk.MustNewDecFromStr("95.238095238095238095"), mulFirst)
 | 
			
		||||
	assert.Equal(t, sdk.MustNewDecFromStr("95.238095238095238000"), quoFirst)
 | 
			
		||||
 | 
			
		||||
	assert.NotEqual(t, mulFirst, quoFirst)
 | 
			
		||||
}
 | 
			
		||||
@ -23,7 +23,7 @@ func TestVaultTestSuite(t *testing.T) {
 | 
			
		||||
	suite.Run(t, new(vaultTestSuite))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *vaultTestSuite) TestGetVaultTotalSupplied() {
 | 
			
		||||
func (suite *vaultTestSuite) TestGetVaultTotalShares() {
 | 
			
		||||
	vaultDenom := "usdx"
 | 
			
		||||
	startBalance := sdk.NewInt64Coin(vaultDenom, 1000)
 | 
			
		||||
	depositAmount := sdk.NewInt64Coin(vaultDenom, 100)
 | 
			
		||||
@ -35,22 +35,27 @@ func (suite *vaultTestSuite) TestGetVaultTotalSupplied() {
 | 
			
		||||
	err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount)
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
 | 
			
		||||
	vaultTotalSupplied, err := suite.Keeper.GetVaultTotalSupplied(suite.Ctx, vaultDenom)
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
	vaultTotalShares, found := suite.Keeper.GetVaultTotalShares(suite.Ctx, vaultDenom)
 | 
			
		||||
	suite.Require().True(found)
 | 
			
		||||
 | 
			
		||||
	suite.Equal(depositAmount, vaultTotalSupplied)
 | 
			
		||||
	suite.Equal(depositAmount.Amount.ToDec(), vaultTotalShares.Amount)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *vaultTestSuite) TestGetVaultTotalSupplied_NotFound() {
 | 
			
		||||
func (suite *vaultTestSuite) TestGetVaultTotalShares_NotFound() {
 | 
			
		||||
	vaultDenom := "usdx"
 | 
			
		||||
 | 
			
		||||
	_, err := suite.Keeper.GetVaultTotalSupplied(suite.Ctx, vaultDenom)
 | 
			
		||||
	suite.Require().Error(err)
 | 
			
		||||
	suite.Require().ErrorIs(err, types.ErrVaultRecordNotFound)
 | 
			
		||||
	_, found := suite.Keeper.GetVaultTotalShares(suite.Ctx, vaultDenom)
 | 
			
		||||
	suite.Require().False(found)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *vaultTestSuite) TestGetVaultTotalValue() {
 | 
			
		||||
	// TODO: After strategy implemented GetEstimatedTotalAssets
 | 
			
		||||
	vaultDenom := "usdx"
 | 
			
		||||
 | 
			
		||||
	suite.CreateVault(vaultDenom, types.STRATEGY_TYPE_HARD)
 | 
			
		||||
 | 
			
		||||
	totalValue, err := suite.Keeper.GetVaultTotalValue(suite.Ctx, vaultDenom)
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
	suite.Equal(sdk.NewInt(0), totalValue.Amount)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *vaultTestSuite) TestGetVaultTotalValue_NotFound() {
 | 
			
		||||
@ -83,17 +88,14 @@ func (suite *vaultTestSuite) TestGetVaultAccountSupplied() {
 | 
			
		||||
 | 
			
		||||
	// Before deposit, account supplied is 0
 | 
			
		||||
 | 
			
		||||
	_, err := suite.Keeper.GetVaultAccountSupplied(suite.Ctx, acc1.GetAddress())
 | 
			
		||||
	suite.Require().Error(err)
 | 
			
		||||
	suite.Require().ErrorIs(err, types.ErrVaultShareRecordNotFound)
 | 
			
		||||
	_, found := suite.Keeper.GetVaultShareRecord(suite.Ctx, acc1.GetAddress())
 | 
			
		||||
	suite.Require().False(found)
 | 
			
		||||
 | 
			
		||||
	_, err = suite.Keeper.GetVaultAccountSupplied(suite.Ctx, acc2.GetAddress())
 | 
			
		||||
	suite.Require().Error(err)
 | 
			
		||||
	suite.Require().ErrorIs(err, types.ErrVaultShareRecordNotFound)
 | 
			
		||||
	_, found = suite.Keeper.GetVaultShareRecord(suite.Ctx, acc2.GetAddress())
 | 
			
		||||
	suite.Require().False(found)
 | 
			
		||||
 | 
			
		||||
	// Deposits from both accounts
 | 
			
		||||
 | 
			
		||||
	err = suite.Keeper.Deposit(suite.Ctx, acc1.GetAddress(), deposit1Amount)
 | 
			
		||||
	err := suite.Keeper.Deposit(suite.Ctx, acc1.GetAddress(), deposit1Amount)
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
 | 
			
		||||
	err = suite.Keeper.Deposit(suite.Ctx, acc2.GetAddress(), deposit2Amount)
 | 
			
		||||
@ -101,15 +103,15 @@ func (suite *vaultTestSuite) TestGetVaultAccountSupplied() {
 | 
			
		||||
 | 
			
		||||
	// Check balances
 | 
			
		||||
 | 
			
		||||
	vaultAcc1Supplied, err := suite.Keeper.GetVaultAccountSupplied(suite.Ctx, acc1.GetAddress())
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
	vaultAcc1Supplied, found := suite.Keeper.GetVaultShareRecord(suite.Ctx, acc1.GetAddress())
 | 
			
		||||
	suite.Require().True(found)
 | 
			
		||||
 | 
			
		||||
	vaultAcc2Supplied, err := suite.Keeper.GetVaultAccountSupplied(suite.Ctx, acc2.GetAddress())
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
	vaultAcc2Supplied, found := suite.Keeper.GetVaultShareRecord(suite.Ctx, acc2.GetAddress())
 | 
			
		||||
	suite.Require().True(found)
 | 
			
		||||
 | 
			
		||||
	// Account supply only includes the deposit from respective accounts
 | 
			
		||||
	suite.Equal(sdk.NewCoins(deposit1Amount), vaultAcc1Supplied)
 | 
			
		||||
	suite.Equal(sdk.NewCoins(deposit1Amount), vaultAcc2Supplied)
 | 
			
		||||
	suite.Equal(deposit1Amount.Amount.ToDec(), vaultAcc1Supplied.Shares.AmountOf(vaultDenom))
 | 
			
		||||
	suite.Equal(deposit1Amount.Amount.ToDec(), vaultAcc2Supplied.Shares.AmountOf(vaultDenom))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *vaultTestSuite) TestGetVaultAccountValue() {
 | 
			
		||||
@ -135,7 +137,7 @@ func (suite *vaultTestSuite) TestGetVaultAccountValue_VaultNotFound() {
 | 
			
		||||
 | 
			
		||||
	_, err := suite.Keeper.GetVaultAccountValue(suite.Ctx, vaultDenom, acc.GetAddress())
 | 
			
		||||
	suite.Require().Error(err)
 | 
			
		||||
	suite.Require().ErrorIs(err, types.ErrVaultRecordNotFound)
 | 
			
		||||
	suite.Require().Equal("account vault share record for usdx not found", err.Error())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *vaultTestSuite) TestGetVaultAccountValue_ShareNotFound() {
 | 
			
		||||
@ -155,87 +157,5 @@ func (suite *vaultTestSuite) TestGetVaultAccountValue_ShareNotFound() {
 | 
			
		||||
	// Query from acc2 with no share record
 | 
			
		||||
	_, err = suite.Keeper.GetVaultAccountValue(suite.Ctx, vaultDenom, acc2.GetAddress())
 | 
			
		||||
	suite.Require().Error(err)
 | 
			
		||||
	suite.Require().ErrorIs(err, types.ErrVaultShareRecordNotFound)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ----------------------------------------------------------------------------
 | 
			
		||||
// State methods
 | 
			
		||||
 | 
			
		||||
func (suite *vaultTestSuite) TestGetVaultRecord() {
 | 
			
		||||
	record := types.NewVaultRecord("usdx")
 | 
			
		||||
 | 
			
		||||
	_, found := suite.Keeper.GetVaultRecord(suite.Ctx, record.Denom)
 | 
			
		||||
	suite.Require().False(found)
 | 
			
		||||
 | 
			
		||||
	suite.Keeper.SetVaultRecord(suite.Ctx, record)
 | 
			
		||||
 | 
			
		||||
	stateRecord, found := suite.Keeper.GetVaultRecord(suite.Ctx, record.Denom)
 | 
			
		||||
	suite.Require().True(found)
 | 
			
		||||
	suite.Require().Equal(record, stateRecord)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *vaultTestSuite) TestUpdateVaultRecord() {
 | 
			
		||||
	record := types.NewVaultRecord("usdx")
 | 
			
		||||
 | 
			
		||||
	record.TotalSupply = sdk.NewInt64Coin("usdx", 100)
 | 
			
		||||
 | 
			
		||||
	// Update vault
 | 
			
		||||
	suite.Keeper.UpdateVaultRecord(suite.Ctx, record)
 | 
			
		||||
 | 
			
		||||
	stateRecord, found := suite.Keeper.GetVaultRecord(suite.Ctx, record.Denom)
 | 
			
		||||
	suite.Require().True(found, "vault record with supply should exist")
 | 
			
		||||
	suite.Require().Equal(record, stateRecord)
 | 
			
		||||
 | 
			
		||||
	// Remove supply
 | 
			
		||||
	record.TotalSupply = sdk.NewInt64Coin("usdx", 0)
 | 
			
		||||
	suite.Keeper.UpdateVaultRecord(suite.Ctx, record)
 | 
			
		||||
 | 
			
		||||
	_, found = suite.Keeper.GetVaultRecord(suite.Ctx, record.Denom)
 | 
			
		||||
	suite.Require().False(found, "vault record with 0 supply should be deleted")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *vaultTestSuite) TestGetVaultShareRecord() {
 | 
			
		||||
	vaultDenom := "usdx"
 | 
			
		||||
	startBalance := sdk.NewInt64Coin(vaultDenom, 1000)
 | 
			
		||||
	depositAmount := sdk.NewInt64Coin(vaultDenom, 100)
 | 
			
		||||
	acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
 | 
			
		||||
 | 
			
		||||
	record := types.NewVaultShareRecord(acc.GetAddress())
 | 
			
		||||
 | 
			
		||||
	// Check share doesn't exist before deposit
 | 
			
		||||
 | 
			
		||||
	_, found := suite.Keeper.GetVaultShareRecord(suite.Ctx, acc.GetAddress())
 | 
			
		||||
	suite.Require().False(found, "vault share record should not exist before deposit")
 | 
			
		||||
 | 
			
		||||
	// Update share record
 | 
			
		||||
	record.AmountSupplied = sdk.NewCoins(depositAmount)
 | 
			
		||||
	suite.Keeper.SetVaultShareRecord(suite.Ctx, record)
 | 
			
		||||
 | 
			
		||||
	// Check share exists and matches set value
 | 
			
		||||
	stateRecord, found := suite.Keeper.GetVaultShareRecord(suite.Ctx, acc.GetAddress())
 | 
			
		||||
	suite.Require().True(found)
 | 
			
		||||
	suite.Require().Equal(record, stateRecord)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *vaultTestSuite) TestUpdateVaultShareRecord() {
 | 
			
		||||
	vaultDenom := "usdx"
 | 
			
		||||
	startBalance := sdk.NewInt64Coin(vaultDenom, 1000)
 | 
			
		||||
	depositAmount := sdk.NewInt64Coin(vaultDenom, 100)
 | 
			
		||||
	acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0)
 | 
			
		||||
 | 
			
		||||
	record := types.NewVaultShareRecord(acc.GetAddress(), depositAmount)
 | 
			
		||||
 | 
			
		||||
	// Update vault
 | 
			
		||||
	suite.Keeper.UpdateVaultShareRecord(suite.Ctx, record)
 | 
			
		||||
 | 
			
		||||
	stateRecord, found := suite.Keeper.GetVaultShareRecord(suite.Ctx, acc.GetAddress())
 | 
			
		||||
	suite.Require().True(found, "vault share record with supply should exist")
 | 
			
		||||
	suite.Require().Equal(record, stateRecord)
 | 
			
		||||
 | 
			
		||||
	// Remove supply
 | 
			
		||||
	record.AmountSupplied = sdk.NewCoins()
 | 
			
		||||
	suite.Keeper.UpdateVaultShareRecord(suite.Ctx, record)
 | 
			
		||||
 | 
			
		||||
	_, found = suite.Keeper.GetVaultShareRecord(suite.Ctx, acc.GetAddress())
 | 
			
		||||
	suite.Require().False(found, "vault share record with 0 supply should be deleted")
 | 
			
		||||
	suite.Require().Equal("account vault share record for usdx not found", err.Error())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -28,34 +28,48 @@ func (k *Keeper) Withdraw(ctx sdk.Context, from sdk.AccAddress, wantAmount sdk.C
 | 
			
		||||
		return types.ErrVaultRecordNotFound
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Get account value for vault
 | 
			
		||||
	vaultAccValue, err := k.GetVaultAccountValue(ctx, wantAmount.Denom, from)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if vaultAccValue.IsZero() {
 | 
			
		||||
		panic("vault account value is zero")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Get account share record for the vault
 | 
			
		||||
	vaultShareRecord, found := k.GetVaultShareRecord(ctx, from)
 | 
			
		||||
	if !found {
 | 
			
		||||
		return types.ErrVaultShareRecordNotFound
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Percent of vault account value the account is withdrawing
 | 
			
		||||
	// This is the total account value, not just the supplied amount.
 | 
			
		||||
	withdrawAmountPercent := wantAmount.Amount.ToDec().Quo(vaultAccValue.Amount.ToDec())
 | 
			
		||||
	withdrawShares, err := k.ConvertToShares(ctx, wantAmount)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("failed to convert assets to shares: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Check if account is not withdrawing more than they have
 | 
			
		||||
	// account value < want withdraw amount
 | 
			
		||||
	if vaultAccValue.Amount.LT(wantAmount.Amount) {
 | 
			
		||||
	accCurrentShares := vaultShareRecord.Shares.AmountOf(wantAmount.Denom)
 | 
			
		||||
	// Check if account is not withdrawing more shares than they have
 | 
			
		||||
	if accCurrentShares.LT(withdrawShares.Amount) {
 | 
			
		||||
		return sdkerrors.Wrapf(
 | 
			
		||||
			types.ErrInsufficientValue,
 | 
			
		||||
			"account vault value of %s is less than %s desired withdraw amount",
 | 
			
		||||
			vaultAccValue,
 | 
			
		||||
			wantAmount,
 | 
			
		||||
			"account has less %s vault shares than withdraw shares, %s < %s",
 | 
			
		||||
			wantAmount.Denom,
 | 
			
		||||
			accCurrentShares,
 | 
			
		||||
			withdrawShares.Amount,
 | 
			
		||||
		)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Convert shares to amount to get truncated true share value
 | 
			
		||||
	withdrawAmount, err := k.ConvertToAssets(ctx, withdrawShares)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("failed to convert shares to assets: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	accountValue, err := k.GetVaultAccountValue(ctx, wantAmount.Denom, from)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("failed to get account value: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Check if withdrawAmount > account value
 | 
			
		||||
	if withdrawAmount.Amount.GT(accountValue.Amount) {
 | 
			
		||||
		return sdkerrors.Wrapf(
 | 
			
		||||
			types.ErrInsufficientValue,
 | 
			
		||||
			"account has less %s vault value than withdraw amount, %s < %s",
 | 
			
		||||
			withdrawAmount.Denom,
 | 
			
		||||
			accountValue.Amount,
 | 
			
		||||
			withdrawAmount.Amount,
 | 
			
		||||
		)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -68,8 +82,8 @@ func (k *Keeper) Withdraw(ctx sdk.Context, from sdk.AccAddress, wantAmount sdk.C
 | 
			
		||||
	// Not necessary to check if amount denom is allowed for the strategy, as
 | 
			
		||||
	// there would be no vault record if it weren't allowed.
 | 
			
		||||
 | 
			
		||||
	// Withdraw the wantAmount from the strategy
 | 
			
		||||
	if err := strategy.Withdraw(ctx, wantAmount); err != nil {
 | 
			
		||||
	// Withdraw the withdrawAmount from the strategy
 | 
			
		||||
	if err := strategy.Withdraw(ctx, withdrawAmount); err != nil {
 | 
			
		||||
		return fmt.Errorf("failed to withdraw from strategy: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -79,27 +93,33 @@ func (k *Keeper) Withdraw(ctx sdk.Context, from sdk.AccAddress, wantAmount sdk.C
 | 
			
		||||
		ctx,
 | 
			
		||||
		types.ModuleName,
 | 
			
		||||
		from,
 | 
			
		||||
		sdk.NewCoins(wantAmount),
 | 
			
		||||
		sdk.NewCoins(withdrawAmount),
 | 
			
		||||
	); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Shares withdrawn from vault
 | 
			
		||||
	// For example:
 | 
			
		||||
	// account supplied = 10hard
 | 
			
		||||
	// account value    = 20hard
 | 
			
		||||
	// wantAmount       = 10hard
 | 
			
		||||
	// withdrawAmountPercent = 10hard / 20hard = 0.5
 | 
			
		||||
	// sharesWithdrawn = 0.5 * 10hard = 5hard
 | 
			
		||||
	vaultShareAmount := vaultShareRecord.AmountSupplied.AmountOf(wantAmount.Denom)
 | 
			
		||||
	sharesWithdrawn := sdk.NewCoin(wantAmount.Denom, vaultShareAmount.
 | 
			
		||||
		ToDec().
 | 
			
		||||
		Mul(withdrawAmountPercent).
 | 
			
		||||
		TruncateInt())
 | 
			
		||||
	// Check if new account balance of shares results in account share value
 | 
			
		||||
	// of < 1 of a sdk.Coin. This share value is not able to be withdrawn and
 | 
			
		||||
	// should just be removed.
 | 
			
		||||
	isDust, err := k.ShareIsDust(
 | 
			
		||||
		ctx,
 | 
			
		||||
		vaultShareRecord.Shares.GetShare(withdrawAmount.Denom).Sub(withdrawShares),
 | 
			
		||||
	)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Decrement VaultRecord and VaultShareRecord supplies
 | 
			
		||||
	vaultRecord.TotalSupply = vaultRecord.TotalSupply.Sub(sharesWithdrawn)
 | 
			
		||||
	vaultShareRecord.AmountSupplied = vaultShareRecord.AmountSupplied.Sub(sdk.NewCoins(sharesWithdrawn))
 | 
			
		||||
	if isDust {
 | 
			
		||||
		// Modify withdrawShares to subtract entire share balance for denom
 | 
			
		||||
		// This does not modify the actual withdraw coin amount as the
 | 
			
		||||
		// difference is < 1coin.
 | 
			
		||||
		withdrawShares = vaultShareRecord.Shares.GetShare(withdrawAmount.Denom)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Decrement VaultRecord and VaultShareRecord supplies - must delete same
 | 
			
		||||
	// amounts
 | 
			
		||||
	vaultShareRecord.Shares = vaultShareRecord.Shares.Sub(withdrawShares)
 | 
			
		||||
	vaultRecord.TotalShares = vaultRecord.TotalShares.Sub(withdrawShares)
 | 
			
		||||
 | 
			
		||||
	// Update VaultRecord and VaultShareRecord, deletes if zero supply
 | 
			
		||||
	k.UpdateVaultRecord(ctx, vaultRecord)
 | 
			
		||||
@ -108,9 +128,10 @@ func (k *Keeper) Withdraw(ctx sdk.Context, from sdk.AccAddress, wantAmount sdk.C
 | 
			
		||||
	ctx.EventManager().EmitEvent(
 | 
			
		||||
		sdk.NewEvent(
 | 
			
		||||
			types.EventTypeVaultWithdraw,
 | 
			
		||||
			sdk.NewAttribute(types.AttributeKeyVaultDenom, wantAmount.Denom),
 | 
			
		||||
			sdk.NewAttribute(types.AttributeKeyVaultDenom, withdrawAmount.Denom),
 | 
			
		||||
			sdk.NewAttribute(types.AttributeKeyOwner, from.String()),
 | 
			
		||||
			sdk.NewAttribute(sdk.AttributeKeyAmount, wantAmount.Amount.String()),
 | 
			
		||||
			sdk.NewAttribute(types.AttributeKeyShares, withdrawShares.Amount.String()),
 | 
			
		||||
			sdk.NewAttribute(sdk.AttributeKeyAmount, withdrawAmount.Amount.String()),
 | 
			
		||||
		),
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -76,7 +76,9 @@ func (suite *withdrawTestSuite) TestWithdraw_NoVaultShareRecord() {
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	suite.VaultTotalValuesEqual(sdk.NewCoins(acc1DepositAmount))
 | 
			
		||||
	suite.VaultTotalSuppliedEqual(sdk.NewCoins(acc1DepositAmount))
 | 
			
		||||
	suite.VaultTotalSharesEqual(types.NewVaultShares(
 | 
			
		||||
		types.NewVaultShare(acc1DepositAmount.Denom, acc1DepositAmount.Amount.ToDec()),
 | 
			
		||||
	))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *withdrawTestSuite) TestWithdraw_ExceedBalance() {
 | 
			
		||||
@ -103,7 +105,9 @@ func (suite *withdrawTestSuite) TestWithdraw_ExceedBalance() {
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	suite.VaultTotalValuesEqual(sdk.NewCoins(depositAmount))
 | 
			
		||||
	suite.VaultTotalSuppliedEqual(sdk.NewCoins(depositAmount))
 | 
			
		||||
	suite.VaultTotalSharesEqual(types.NewVaultShares(
 | 
			
		||||
		types.NewVaultShare(depositAmount.Denom, depositAmount.Amount.ToDec()),
 | 
			
		||||
	))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *withdrawTestSuite) TestWithdraw_Zero() {
 | 
			
		||||
 | 
			
		||||
@ -256,21 +256,29 @@ func (suite *Suite) VaultTotalValuesEqual(expected sdk.Coins) {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *Suite) VaultTotalSuppliedEqual(expected sdk.Coins) {
 | 
			
		||||
	for _, coin := range expected {
 | 
			
		||||
		vaultBal, err := suite.Keeper.GetVaultTotalSupplied(suite.Ctx, coin.Denom)
 | 
			
		||||
		suite.Require().NoError(err, "failed to get vault balance")
 | 
			
		||||
		suite.Require().Equal(coin, vaultBal)
 | 
			
		||||
func (suite *Suite) VaultTotalSharesEqual(expected types.VaultShares) {
 | 
			
		||||
	for _, share := range expected {
 | 
			
		||||
		vaultBal, found := suite.Keeper.GetVaultTotalShares(suite.Ctx, share.Denom)
 | 
			
		||||
		suite.Require().Truef(found, "%s vault does not exist", share.Denom)
 | 
			
		||||
		suite.Require().Equal(share.Amount, vaultBal.Amount)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *Suite) AccountTotalSuppliedEqual(accs []sdk.AccAddress, supplies []sdk.Coins) {
 | 
			
		||||
func (suite *Suite) VaultAccountSharesEqual(accs []sdk.AccAddress, supplies []sdk.Coins) {
 | 
			
		||||
	for i, acc := range accs {
 | 
			
		||||
		coins := supplies[i]
 | 
			
		||||
 | 
			
		||||
		accVaultBal, err := suite.Keeper.GetVaultAccountSupplied(suite.Ctx, acc)
 | 
			
		||||
		suite.Require().NoError(err)
 | 
			
		||||
		suite.Require().True(coins.IsEqual(accVaultBal), "expected account vault balance to equal coins %s, but got %s", coins, accVaultBal)
 | 
			
		||||
		accVaultBal, found := suite.Keeper.GetVaultAccountShares(suite.Ctx, acc)
 | 
			
		||||
		suite.Require().True(found)
 | 
			
		||||
 | 
			
		||||
		for _, coin := range coins {
 | 
			
		||||
			suite.Require().Equal(
 | 
			
		||||
				coin.Amount,
 | 
			
		||||
				accVaultBal.AmountOf(coin.Denom),
 | 
			
		||||
				"expected account vault balance to equal coins %s, but got %s",
 | 
			
		||||
				coins, accVaultBal,
 | 
			
		||||
			)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -26,10 +26,3 @@ func NewQueryDepositsRequest(
 | 
			
		||||
		Pagination: pagination,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewQueryTotalDepositedRequest returns a new QueryTotalDepositedRequest
 | 
			
		||||
func NewQueryTotalDepositedRequest(denom string) *QueryTotalDepositedRequest {
 | 
			
		||||
	return &QueryTotalDepositedRequest{
 | 
			
		||||
		Denom: denom,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -193,8 +193,8 @@ type VaultResponse struct {
 | 
			
		||||
	Denom string `protobuf:"bytes,1,opt,name=denom,proto3" json:"denom,omitempty"`
 | 
			
		||||
	// 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"`
 | 
			
		||||
	// TotalSupplied is the total amount of denom coins supplied to the vault.
 | 
			
		||||
	TotalSupplied github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,3,opt,name=total_supplied,json=totalSupplied,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"total_supplied"`
 | 
			
		||||
	// 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"`
 | 
			
		||||
	// TotalValue is the total value of denom coins supplied to the vault if the
 | 
			
		||||
	// vault were to be liquidated.
 | 
			
		||||
	TotalValue github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,4,opt,name=total_value,json=totalValue,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"total_value"`
 | 
			
		||||
@ -321,8 +321,8 @@ var xxx_messageInfo_QueryDepositsResponse proto.InternalMessageInfo
 | 
			
		||||
type DepositResponse struct {
 | 
			
		||||
	// depositor represents the owner of the deposit.
 | 
			
		||||
	Depositor string `protobuf:"bytes,1,opt,name=depositor,proto3" json:"depositor,omitempty"`
 | 
			
		||||
	// Amount represents the amount supplied to vaults.
 | 
			
		||||
	AmountSupplied github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,2,rep,name=amount_supplied,json=amountSupplied,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"amount_supplied"`
 | 
			
		||||
	// Shares represent the issued shares from their corresponding vaults.
 | 
			
		||||
	Shares VaultShares `protobuf:"bytes,2,rep,name=shares,proto3,castrepeated=VaultShares" json:"shares"`
 | 
			
		||||
	// Value represents the total accumulated value of denom coins supplied to
 | 
			
		||||
	// vaults. This may be greater than or equal to amount_supplied depending on
 | 
			
		||||
	// the strategy.
 | 
			
		||||
@ -362,83 +362,6 @@ func (m *DepositResponse) XXX_DiscardUnknown() {
 | 
			
		||||
 | 
			
		||||
var xxx_messageInfo_DepositResponse proto.InternalMessageInfo
 | 
			
		||||
 | 
			
		||||
// QueryTotalDepositedRequest is the request type for the Query/TotalDeposited RPC method.
 | 
			
		||||
type QueryTotalDepositedRequest struct {
 | 
			
		||||
	// denom represents the vault denom to query total deposited amount for.
 | 
			
		||||
	Denom string `protobuf:"bytes,1,opt,name=denom,proto3" json:"denom,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *QueryTotalDepositedRequest) Reset()         { *m = QueryTotalDepositedRequest{} }
 | 
			
		||||
func (m *QueryTotalDepositedRequest) String() string { return proto.CompactTextString(m) }
 | 
			
		||||
func (*QueryTotalDepositedRequest) ProtoMessage()    {}
 | 
			
		||||
func (*QueryTotalDepositedRequest) Descriptor() ([]byte, []int) {
 | 
			
		||||
	return fileDescriptor_63f8dee2f3192a6b, []int{8}
 | 
			
		||||
}
 | 
			
		||||
func (m *QueryTotalDepositedRequest) XXX_Unmarshal(b []byte) error {
 | 
			
		||||
	return m.Unmarshal(b)
 | 
			
		||||
}
 | 
			
		||||
func (m *QueryTotalDepositedRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 | 
			
		||||
	if deterministic {
 | 
			
		||||
		return xxx_messageInfo_QueryTotalDepositedRequest.Marshal(b, m, deterministic)
 | 
			
		||||
	} else {
 | 
			
		||||
		b = b[:cap(b)]
 | 
			
		||||
		n, err := m.MarshalToSizedBuffer(b)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		return b[:n], nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
func (m *QueryTotalDepositedRequest) XXX_Merge(src proto.Message) {
 | 
			
		||||
	xxx_messageInfo_QueryTotalDepositedRequest.Merge(m, src)
 | 
			
		||||
}
 | 
			
		||||
func (m *QueryTotalDepositedRequest) XXX_Size() int {
 | 
			
		||||
	return m.Size()
 | 
			
		||||
}
 | 
			
		||||
func (m *QueryTotalDepositedRequest) XXX_DiscardUnknown() {
 | 
			
		||||
	xxx_messageInfo_QueryTotalDepositedRequest.DiscardUnknown(m)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var xxx_messageInfo_QueryTotalDepositedRequest proto.InternalMessageInfo
 | 
			
		||||
 | 
			
		||||
// QueryTotalDepositedResponse is the response type for the Query/TotalDeposited RPC method.
 | 
			
		||||
type QueryTotalDepositedResponse struct {
 | 
			
		||||
	SuppliedCoins github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,1,rep,name=supplied_coins,json=suppliedCoins,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"supplied_coins"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *QueryTotalDepositedResponse) Reset()         { *m = QueryTotalDepositedResponse{} }
 | 
			
		||||
func (m *QueryTotalDepositedResponse) String() string { return proto.CompactTextString(m) }
 | 
			
		||||
func (*QueryTotalDepositedResponse) ProtoMessage()    {}
 | 
			
		||||
func (*QueryTotalDepositedResponse) Descriptor() ([]byte, []int) {
 | 
			
		||||
	return fileDescriptor_63f8dee2f3192a6b, []int{9}
 | 
			
		||||
}
 | 
			
		||||
func (m *QueryTotalDepositedResponse) XXX_Unmarshal(b []byte) error {
 | 
			
		||||
	return m.Unmarshal(b)
 | 
			
		||||
}
 | 
			
		||||
func (m *QueryTotalDepositedResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 | 
			
		||||
	if deterministic {
 | 
			
		||||
		return xxx_messageInfo_QueryTotalDepositedResponse.Marshal(b, m, deterministic)
 | 
			
		||||
	} else {
 | 
			
		||||
		b = b[:cap(b)]
 | 
			
		||||
		n, err := m.MarshalToSizedBuffer(b)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		return b[:n], nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
func (m *QueryTotalDepositedResponse) XXX_Merge(src proto.Message) {
 | 
			
		||||
	xxx_messageInfo_QueryTotalDepositedResponse.Merge(m, src)
 | 
			
		||||
}
 | 
			
		||||
func (m *QueryTotalDepositedResponse) XXX_Size() int {
 | 
			
		||||
	return m.Size()
 | 
			
		||||
}
 | 
			
		||||
func (m *QueryTotalDepositedResponse) XXX_DiscardUnknown() {
 | 
			
		||||
	xxx_messageInfo_QueryTotalDepositedResponse.DiscardUnknown(m)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var xxx_messageInfo_QueryTotalDepositedResponse proto.InternalMessageInfo
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	proto.RegisterType((*QueryParamsRequest)(nil), "kava.earn.v1beta1.QueryParamsRequest")
 | 
			
		||||
	proto.RegisterType((*QueryParamsResponse)(nil), "kava.earn.v1beta1.QueryParamsResponse")
 | 
			
		||||
@ -448,67 +371,60 @@ func init() {
 | 
			
		||||
	proto.RegisterType((*QueryDepositsRequest)(nil), "kava.earn.v1beta1.QueryDepositsRequest")
 | 
			
		||||
	proto.RegisterType((*QueryDepositsResponse)(nil), "kava.earn.v1beta1.QueryDepositsResponse")
 | 
			
		||||
	proto.RegisterType((*DepositResponse)(nil), "kava.earn.v1beta1.DepositResponse")
 | 
			
		||||
	proto.RegisterType((*QueryTotalDepositedRequest)(nil), "kava.earn.v1beta1.QueryTotalDepositedRequest")
 | 
			
		||||
	proto.RegisterType((*QueryTotalDepositedResponse)(nil), "kava.earn.v1beta1.QueryTotalDepositedResponse")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func init() { proto.RegisterFile("kava/earn/v1beta1/query.proto", fileDescriptor_63f8dee2f3192a6b) }
 | 
			
		||||
 | 
			
		||||
var fileDescriptor_63f8dee2f3192a6b = []byte{
 | 
			
		||||
	// 833 bytes of a gzipped FileDescriptorProto
 | 
			
		||||
	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x55, 0x4f, 0x6f, 0xd3, 0x48,
 | 
			
		||||
	0x14, 0x8f, 0xd3, 0x26, 0x6a, 0x27, 0x4a, 0xaa, 0x9d, 0xcd, 0x4a, 0x49, 0xba, 0x75, 0x52, 0x57,
 | 
			
		||||
	0xdb, 0x66, 0xab, 0x8d, 0xbd, 0xcd, 0x4a, 0xbb, 0x97, 0xd5, 0x4a, 0x9b, 0xad, 0x16, 0xf5, 0x82,
 | 
			
		||||
	0xc0, 0x2d, 0x3d, 0x20, 0xa1, 0x68, 0x12, 0x8f, 0x8c, 0xd5, 0xc4, 0xe3, 0xda, 0x93, 0x40, 0x41,
 | 
			
		||||
	0x5c, 0xfa, 0x09, 0x40, 0x7c, 0x03, 0x40, 0x1c, 0xb8, 0x21, 0xfa, 0x21, 0x7a, 0xac, 0xca, 0x05,
 | 
			
		||||
	0x71, 0x28, 0xd0, 0xf2, 0x41, 0x90, 0xe7, 0x4f, 0x52, 0x27, 0x0e, 0xe9, 0xa1, 0xa7, 0x64, 0xe6,
 | 
			
		||||
	0xbd, 0xf7, 0xfb, 0xfd, 0xe6, 0xcd, 0x6f, 0x9e, 0xc1, 0xd2, 0x1e, 0xea, 0x23, 0x03, 0x23, 0xdf,
 | 
			
		||||
	0x35, 0xfa, 0x1b, 0x2d, 0x4c, 0xd1, 0x86, 0xb1, 0xdf, 0xc3, 0xfe, 0x81, 0xee, 0xf9, 0x84, 0x12,
 | 
			
		||||
	0xf8, 0x43, 0x18, 0xd6, 0xc3, 0xb0, 0x2e, 0xc2, 0xa5, 0x62, 0x9b, 0x04, 0x5d, 0x12, 0x34, 0x59,
 | 
			
		||||
	0x82, 0xc1, 0x17, 0x3c, 0xbb, 0xb4, 0xce, 0x57, 0x46, 0x0b, 0x05, 0x98, 0xc3, 0x0c, 0x40, 0x3d,
 | 
			
		||||
	0x64, 0x3b, 0x2e, 0xa2, 0x0e, 0x71, 0x45, 0xae, 0x7a, 0x39, 0x57, 0x66, 0xb5, 0x89, 0x23, 0xe3,
 | 
			
		||||
	0x79, 0x9b, 0xd8, 0x84, 0x73, 0x84, 0xff, 0xc4, 0xee, 0xcf, 0x36, 0x21, 0x76, 0x07, 0x1b, 0xc8,
 | 
			
		||||
	0x73, 0x0c, 0xe4, 0xba, 0x84, 0x32, 0x48, 0xc9, 0xaf, 0x8e, 0x1f, 0xc6, 0x43, 0x3e, 0xea, 0xca,
 | 
			
		||||
	0x78, 0x65, 0x3c, 0x1e, 0x50, 0x1f, 0x51, 0x6c, 0x8b, 0xf3, 0x6a, 0x79, 0x00, 0x6f, 0x87, 0xba,
 | 
			
		||||
	0x6f, 0xb1, 0x32, 0x13, 0xef, 0xf7, 0x70, 0x40, 0xb5, 0x9b, 0xe0, 0xc7, 0xc8, 0x6e, 0xe0, 0x11,
 | 
			
		||||
	0x37, 0xc0, 0xf0, 0x2f, 0x90, 0xe6, 0xf0, 0x05, 0xa5, 0xa2, 0x54, 0x33, 0xf5, 0xa2, 0x3e, 0xd6,
 | 
			
		||||
	0x2d, 0x9d, 0x97, 0x34, 0x66, 0x8f, 0xcf, 0xca, 0x09, 0x53, 0xa4, 0x6b, 0xeb, 0x82, 0x65, 0x17,
 | 
			
		||||
	0xf5, 0x3a, 0x54, 0xb2, 0xc0, 0x3c, 0x48, 0x59, 0xd8, 0x25, 0x5d, 0x86, 0x36, 0x6f, 0xf2, 0x85,
 | 
			
		||||
	0x76, 0x47, 0x70, 0xcb, 0x5c, 0xc1, 0xfd, 0x0f, 0x48, 0xf7, 0xd9, 0x4e, 0x41, 0xa9, 0xcc, 0x54,
 | 
			
		||||
	0x33, 0xf5, 0x4a, 0x0c, 0x37, 0x2b, 0x91, 0x15, 0x52, 0x02, 0xaf, 0xd2, 0xde, 0x26, 0x41, 0x36,
 | 
			
		||||
	0x12, 0x8f, 0xa7, 0x87, 0xff, 0x83, 0x1c, 0xab, 0x68, 0xca, 0x46, 0x15, 0x92, 0x15, 0xa5, 0x9a,
 | 
			
		||||
	0xab, 0x97, 0x63, 0xf8, 0xb6, 0x45, 0xca, 0xce, 0x81, 0x87, 0xcd, 0x2c, 0x2b, 0x93, 0x5b, 0xb0,
 | 
			
		||||
	0x0d, 0x72, 0x94, 0x50, 0xd4, 0x69, 0x06, 0x3d, 0xcf, 0xeb, 0x38, 0xd8, 0x2a, 0xcc, 0x84, 0x34,
 | 
			
		||||
	0x8d, 0xbf, 0x43, 0x55, 0x1f, 0xcf, 0xca, 0xab, 0xb6, 0x43, 0xef, 0xf7, 0x5a, 0x7a, 0x9b, 0x74,
 | 
			
		||||
	0x85, 0xa7, 0xc4, 0x4f, 0x2d, 0xb0, 0xf6, 0x0c, 0x7a, 0xe0, 0xe1, 0x40, 0xdf, 0x72, 0xe9, 0xe9,
 | 
			
		||||
	0x51, 0x0d, 0x08, 0xcb, 0x6d, 0xb9, 0xd4, 0xcc, 0x32, 0xcc, 0x6d, 0x01, 0x09, 0xef, 0x81, 0x0c,
 | 
			
		||||
	0x27, 0xe9, 0xa3, 0x4e, 0x0f, 0x17, 0x66, 0xaf, 0x81, 0x01, 0x30, 0xc0, 0xdd, 0x10, 0x4f, 0x7b,
 | 
			
		||||
	0xa5, 0x80, 0x3c, 0xbb, 0x8b, 0x4d, 0xec, 0x91, 0xc0, 0x19, 0xde, 0x9c, 0x0e, 0x52, 0xe4, 0x81,
 | 
			
		||||
	0x8b, 0x7d, 0xde, 0xba, 0x46, 0xe1, 0xf4, 0xa8, 0x96, 0x17, 0x18, 0xff, 0x5a, 0x96, 0x8f, 0x83,
 | 
			
		||||
	0x60, 0x9b, 0xfa, 0x8e, 0x6b, 0x9b, 0x3c, 0x6d, 0xd8, 0xea, 0x64, 0xb4, 0xd5, 0x60, 0xf8, 0x4a,
 | 
			
		||||
	0x58, 0x7b, 0x32, 0xf5, 0x55, 0x5d, 0xe0, 0x84, 0xcf, 0x44, 0xe7, 0x2f, 0x73, 0x68, 0x2d, 0x1b,
 | 
			
		||||
	0x0b, 0x05, 0xe6, 0xa5, 0x4a, 0xed, 0xb5, 0x02, 0x7e, 0x1a, 0x91, 0x29, 0xae, 0x78, 0x13, 0xcc,
 | 
			
		||||
	0x59, 0x62, 0x4f, 0xd8, 0x46, 0x8b, 0xb9, 0x46, 0x51, 0x36, 0x62, 0x9c, 0x41, 0x25, 0xbc, 0x11,
 | 
			
		||||
	0xd1, 0x99, 0x64, 0x3a, 0xd7, 0xa6, 0xea, 0xe4, 0x60, 0x11, 0xa1, 0x2f, 0x92, 0x60, 0x61, 0x84,
 | 
			
		||||
	0x0c, 0xfe, 0x09, 0xe6, 0x05, 0x11, 0x99, 0xde, 0xce, 0x61, 0x2a, 0xa4, 0x60, 0x01, 0x75, 0x49,
 | 
			
		||||
	0xcf, 0xa5, 0x43, 0x83, 0x25, 0xd9, 0x09, 0x8b, 0x11, 0x65, 0x52, 0xd3, 0x7f, 0xc4, 0x71, 0x1b,
 | 
			
		||||
	0xbf, 0x87, 0x07, 0x7b, 0xf3, 0xa9, 0x5c, 0xbd, 0x82, 0x33, 0xc2, 0x82, 0xc0, 0xcc, 0x71, 0x8e,
 | 
			
		||||
	0x81, 0xe1, 0x10, 0x48, 0x71, 0xab, 0xcd, 0x5c, 0x3f, 0x17, 0x47, 0xd6, 0xea, 0xa0, 0xc4, 0x2e,
 | 
			
		||||
	0x73, 0x27, 0xf4, 0xa1, 0xe8, 0x16, 0xb6, 0xbe, 0x3f, 0x33, 0x9e, 0x29, 0x60, 0x31, 0xb6, 0x48,
 | 
			
		||||
	0x34, 0xd9, 0x07, 0x39, 0xd9, 0xa5, 0x66, 0x38, 0x72, 0xa5, 0x1b, 0xae, 0x55, 0x7f, 0x56, 0x52,
 | 
			
		||||
	0xb0, 0x65, 0xfd, 0xdd, 0x2c, 0x48, 0x31, 0x4d, 0xf0, 0x11, 0x48, 0xf3, 0xa9, 0x08, 0x7f, 0x89,
 | 
			
		||||
	0x71, 0xdf, 0xf8, 0xf8, 0x2d, 0xad, 0x4e, 0x4b, 0xe3, 0xc7, 0xd2, 0x96, 0x0f, 0xdf, 0x7f, 0x7d,
 | 
			
		||||
	0x9e, 0x5c, 0x84, 0x45, 0x63, 0xd2, 0x77, 0x00, 0x1e, 0x2a, 0x20, 0xcd, 0x27, 0xe9, 0x64, 0xf2,
 | 
			
		||||
	0xc8, 0x54, 0x9e, 0x4c, 0x1e, 0x1d, 0xc8, 0xda, 0xaf, 0x8c, 0x7c, 0x05, 0x2e, 0xc7, 0x90, 0xf3,
 | 
			
		||||
	0x99, 0x6b, 0x3c, 0x66, 0xb7, 0xf3, 0x24, 0x14, 0x31, 0x27, 0xdf, 0x26, 0x5c, 0x9b, 0x84, 0x3f,
 | 
			
		||||
	0x32, 0x64, 0x4a, 0xd5, 0xe9, 0x89, 0x42, 0xca, 0x0a, 0x93, 0xb2, 0x04, 0x17, 0x63, 0xa4, 0x0c,
 | 
			
		||||
	0x5e, 0xf1, 0x4b, 0x05, 0xe4, 0xa2, 0xf6, 0x80, 0xb5, 0x49, 0x0c, 0xb1, 0xde, 0x2b, 0xe9, 0x57,
 | 
			
		||||
	0x4d, 0x17, 0xb2, 0xea, 0x4c, 0xd6, 0x6f, 0x70, 0x3d, 0x46, 0x16, 0x9b, 0xb2, 0x35, 0x4b, 0xd6,
 | 
			
		||||
	0xc8, 0x56, 0x35, 0x36, 0x8f, 0xbf, 0xa8, 0x89, 0xe3, 0x73, 0x55, 0x39, 0x39, 0x57, 0x95, 0xcf,
 | 
			
		||||
	0xe7, 0xaa, 0xf2, 0xf4, 0x42, 0x4d, 0x9c, 0x5c, 0xa8, 0x89, 0x0f, 0x17, 0x6a, 0xe2, 0xee, 0xe5,
 | 
			
		||||
	0x91, 0x1e, 0x62, 0xd6, 0x3a, 0xa8, 0x15, 0x70, 0xf4, 0x87, 0x1c, 0x9f, 0x19, 0xb2, 0x95, 0x66,
 | 
			
		||||
	0x1f, 0xf7, 0x3f, 0xbe, 0x05, 0x00, 0x00, 0xff, 0xff, 0x3b, 0xb1, 0x1a, 0x34, 0xed, 0x08, 0x00,
 | 
			
		||||
	0x00,
 | 
			
		||||
	// 762 bytes of a gzipped FileDescriptorProto
 | 
			
		||||
	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x55, 0xcf, 0x4f, 0x13, 0x4f,
 | 
			
		||||
	0x14, 0xef, 0xb6, 0xb4, 0x81, 0xe9, 0x17, 0xbe, 0x71, 0xa8, 0x49, 0x5b, 0x64, 0x5b, 0x96, 0x08,
 | 
			
		||||
	0x95, 0xa4, 0xbb, 0x52, 0x13, 0xbd, 0x18, 0x13, 0x2b, 0xd1, 0xe0, 0xc1, 0xe8, 0xa2, 0x1c, 0x4c,
 | 
			
		||||
	0x4c, 0x33, 0xa5, 0x93, 0x65, 0x43, 0xbb, 0xb3, 0xec, 0x4c, 0xab, 0x68, 0xbc, 0x70, 0x37, 0x31,
 | 
			
		||||
	0xf1, 0x5f, 0x30, 0x1e, 0x3c, 0xf3, 0x47, 0x70, 0x24, 0x78, 0x31, 0x1e, 0x50, 0xc1, 0xbb, 0x57,
 | 
			
		||||
	0x8f, 0x66, 0x7e, 0x2c, 0x65, 0xdb, 0x6d, 0xea, 0xa9, 0x9d, 0xf7, 0xe3, 0xf3, 0xf9, 0xbc, 0x37,
 | 
			
		||||
	0x6f, 0xde, 0x82, 0xf9, 0x1d, 0xd4, 0x43, 0x16, 0x46, 0x81, 0x67, 0xf5, 0x56, 0x9b, 0x98, 0xa1,
 | 
			
		||||
	0x55, 0x6b, 0xb7, 0x8b, 0x83, 0x3d, 0xd3, 0x0f, 0x08, 0x23, 0xf0, 0x12, 0x77, 0x9b, 0xdc, 0x6d,
 | 
			
		||||
	0x2a, 0x77, 0xb1, 0xb0, 0x45, 0x68, 0x87, 0xd0, 0x86, 0x08, 0xb0, 0xe4, 0x41, 0x46, 0x17, 0x57,
 | 
			
		||||
	0xe4, 0xc9, 0x6a, 0x22, 0x8a, 0x25, 0xcc, 0x39, 0xa8, 0x8f, 0x1c, 0xd7, 0x43, 0xcc, 0x25, 0x9e,
 | 
			
		||||
	0x8a, 0xd5, 0x2f, 0xc6, 0x86, 0x51, 0x5b, 0xc4, 0x0d, 0xfd, 0x39, 0x87, 0x38, 0x44, 0x72, 0xf0,
 | 
			
		||||
	0x7f, 0xca, 0x7a, 0xc5, 0x21, 0xc4, 0x69, 0x63, 0x0b, 0xf9, 0xae, 0x85, 0x3c, 0x8f, 0x30, 0x01,
 | 
			
		||||
	0x19, 0xf2, 0xeb, 0xc3, 0xc5, 0xf8, 0x28, 0x40, 0x9d, 0xd0, 0x5f, 0x1e, 0xf6, 0x53, 0x16, 0x20,
 | 
			
		||||
	0x86, 0x1d, 0x55, 0x6f, 0x31, 0xa6, 0x1d, 0x3d, 0xd4, 0x6d, 0x33, 0xe9, 0x36, 0x72, 0x00, 0x3e,
 | 
			
		||||
	0xe1, 0x65, 0x3d, 0x16, 0xa8, 0x36, 0xde, 0xed, 0x62, 0xca, 0x8c, 0x47, 0x60, 0x36, 0x62, 0xa5,
 | 
			
		||||
	0x3e, 0xf1, 0x28, 0x86, 0xb7, 0x40, 0x46, 0xb2, 0xe7, 0xb5, 0xb2, 0x56, 0xc9, 0xd6, 0x0a, 0xe6,
 | 
			
		||||
	0x50, 0x33, 0x4d, 0x99, 0x52, 0x9f, 0x38, 0x3c, 0x29, 0x25, 0x6c, 0x15, 0x6e, 0xac, 0x28, 0x96,
 | 
			
		||||
	0x4d, 0xce, 0x1c, 0xb2, 0xc0, 0x1c, 0x48, 0xb7, 0xb0, 0x47, 0x3a, 0x02, 0x6d, 0xca, 0x96, 0x07,
 | 
			
		||||
	0xe3, 0x99, 0xe2, 0x0e, 0x63, 0x15, 0xf7, 0x1d, 0x90, 0x11, 0xba, 0x39, 0x77, 0xaa, 0x92, 0xad,
 | 
			
		||||
	0x95, 0x63, 0xb8, 0x45, 0x4a, 0x98, 0x11, 0x4a, 0x90, 0x59, 0xc6, 0x6f, 0x0d, 0x4c, 0x47, 0xfc,
 | 
			
		||||
	0xf1, 0xf4, 0xf0, 0x3e, 0x98, 0x11, 0x19, 0x8d, 0xb0, 0x8f, 0xf9, 0x64, 0x59, 0xab, 0xcc, 0xd4,
 | 
			
		||||
	0x4a, 0x31, 0x7c, 0x1b, 0x2a, 0xe4, 0xe9, 0x9e, 0x8f, 0xed, 0x69, 0x91, 0x16, 0x9a, 0xe0, 0x02,
 | 
			
		||||
	0xf8, 0x8f, 0x11, 0x86, 0xda, 0x0d, 0xba, 0x8d, 0x02, 0x4c, 0xf3, 0x29, 0x41, 0x92, 0x15, 0xb6,
 | 
			
		||||
	0x0d, 0x61, 0x82, 0x2f, 0x80, 0x3c, 0x36, 0x7a, 0xa8, 0xdd, 0xc5, 0xf9, 0x09, 0x1e, 0x51, 0xbf,
 | 
			
		||||
	0xcd, 0x55, 0x7f, 0x3b, 0x29, 0x2d, 0x39, 0x2e, 0xdb, 0xee, 0x36, 0xcd, 0x2d, 0xd2, 0x51, 0x23,
 | 
			
		||||
	0xa9, 0x7e, 0xaa, 0xb4, 0xb5, 0x63, 0xb1, 0x3d, 0x1f, 0x53, 0x73, 0xdd, 0x63, 0xc7, 0x07, 0x55,
 | 
			
		||||
	0xa0, 0x26, 0x76, 0xdd, 0x63, 0x36, 0x10, 0x80, 0x9b, 0x1c, 0xcf, 0xf8, 0xa8, 0x81, 0x9c, 0xe8,
 | 
			
		||||
	0xe4, 0x1a, 0xf6, 0x09, 0x75, 0xfb, 0x7d, 0x37, 0x41, 0x9a, 0xbc, 0xf4, 0x70, 0x20, 0x0b, 0xaf,
 | 
			
		||||
	0xe7, 0x8f, 0x0f, 0xaa, 0x39, 0x85, 0x71, 0xb7, 0xd5, 0x0a, 0x30, 0xa5, 0x1b, 0x2c, 0x70, 0x3d,
 | 
			
		||||
	0xc7, 0x96, 0x61, 0xfd, 0x46, 0x25, 0xa3, 0x8d, 0x02, 0xfd, 0x27, 0x20, 0xca, 0xcb, 0xd6, 0x96,
 | 
			
		||||
	0x4c, 0x85, 0xc3, 0xdf, 0x80, 0x29, 0x9f, 0x5d, 0x7f, 0x30, 0x1c, 0xac, 0x14, 0xd8, 0x17, 0x32,
 | 
			
		||||
	0x8d, 0x4f, 0x1a, 0xb8, 0x3c, 0x20, 0x53, 0x5d, 0xd0, 0x1a, 0x98, 0x6c, 0x29, 0x9b, 0xba, 0x74,
 | 
			
		||||
	0x23, 0xe6, 0x12, 0x54, 0xda, 0xc0, 0xb5, 0x9f, 0x67, 0xc2, 0x07, 0x11, 0x9d, 0x49, 0xa1, 0x73,
 | 
			
		||||
	0x79, 0xac, 0x4e, 0x09, 0x16, 0x11, 0xfa, 0x47, 0x03, 0xff, 0x0f, 0x90, 0xc1, 0x9b, 0x60, 0x4a,
 | 
			
		||||
	0x11, 0x91, 0xf1, 0xed, 0xec, 0x87, 0xc2, 0x87, 0x20, 0xa3, 0xe6, 0x22, 0x29, 0x0a, 0x9b, 0x1f,
 | 
			
		||||
	0x35, 0xcd, 0x62, 0x54, 0xea, 0xb3, 0xbc, 0xa6, 0xcf, 0xdf, 0x4b, 0xd9, 0xbe, 0x8d, 0xda, 0x0a,
 | 
			
		||||
	0x01, 0x22, 0x90, 0x96, 0x03, 0x94, 0x12, 0x50, 0x85, 0x48, 0x6d, 0x21, 0xd8, 0x3d, 0xe2, 0x7a,
 | 
			
		||||
	0xf5, 0xeb, 0x0a, 0xa6, 0xf2, 0x0f, 0xb3, 0xc5, 0x13, 0xa8, 0x2d, 0x91, 0x6b, 0xef, 0x52, 0x20,
 | 
			
		||||
	0x2d, 0xee, 0x08, 0xbe, 0x06, 0x19, 0xf9, 0xc2, 0xe1, 0xd5, 0x18, 0xc9, 0xc3, 0xab, 0xa4, 0xb8,
 | 
			
		||||
	0x34, 0x2e, 0x4c, 0x76, 0xd2, 0x58, 0xd8, 0xff, 0xf2, 0xeb, 0x43, 0x72, 0x0e, 0x16, 0xac, 0x51,
 | 
			
		||||
	0x2b, 0x0f, 0xee, 0x6b, 0x20, 0x23, 0xb7, 0xc2, 0x68, 0xf2, 0xc8, 0x86, 0x19, 0x4d, 0x1e, 0x5d,
 | 
			
		||||
	0x2e, 0xc6, 0x35, 0x41, 0xbe, 0x08, 0x17, 0xac, 0x11, 0xdb, 0x92, 0x5a, 0x6f, 0xc4, 0xd4, 0xbf,
 | 
			
		||||
	0xe5, 0x22, 0x26, 0xc3, 0x49, 0x85, 0xcb, 0xa3, 0xf0, 0x07, 0x9e, 0x5c, 0xb1, 0x32, 0x3e, 0x50,
 | 
			
		||||
	0x49, 0x59, 0x14, 0x52, 0xe6, 0xe1, 0x5c, 0x8c, 0x94, 0x70, 0xa6, 0xeb, 0x6b, 0x87, 0x3f, 0xf5,
 | 
			
		||||
	0xc4, 0xe1, 0xa9, 0xae, 0x1d, 0x9d, 0xea, 0xda, 0x8f, 0x53, 0x5d, 0x7b, 0x7f, 0xa6, 0x27, 0x8e,
 | 
			
		||||
	0xce, 0xf4, 0xc4, 0xd7, 0x33, 0x3d, 0xf1, 0xfc, 0xe2, 0xea, 0xe0, 0x20, 0xd5, 0x36, 0x6a, 0x52,
 | 
			
		||||
	0x09, 0xf7, 0x4a, 0x02, 0x8a, 0x2b, 0x6e, 0x66, 0xc4, 0x27, 0xe0, 0xc6, 0xdf, 0x00, 0x00, 0x00,
 | 
			
		||||
	0xff, 0xff, 0x27, 0x75, 0x39, 0xf4, 0x32, 0x07, 0x00, 0x00,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Reference imports to suppress errors if they are not otherwise used.
 | 
			
		||||
@ -529,8 +445,6 @@ type QueryClient interface {
 | 
			
		||||
	Vaults(ctx context.Context, in *QueryVaultsRequest, opts ...grpc.CallOption) (*QueryVaultsResponse, error)
 | 
			
		||||
	// Deposits queries deposit details based on owner address and vault
 | 
			
		||||
	Deposits(ctx context.Context, in *QueryDepositsRequest, opts ...grpc.CallOption) (*QueryDepositsResponse, error)
 | 
			
		||||
	// TotalDeposited queries total deposited amount for each vault.
 | 
			
		||||
	TotalDeposited(ctx context.Context, in *QueryTotalDepositedRequest, opts ...grpc.CallOption) (*QueryTotalDepositedResponse, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type queryClient struct {
 | 
			
		||||
@ -568,15 +482,6 @@ func (c *queryClient) Deposits(ctx context.Context, in *QueryDepositsRequest, op
 | 
			
		||||
	return out, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *queryClient) TotalDeposited(ctx context.Context, in *QueryTotalDepositedRequest, opts ...grpc.CallOption) (*QueryTotalDepositedResponse, error) {
 | 
			
		||||
	out := new(QueryTotalDepositedResponse)
 | 
			
		||||
	err := c.cc.Invoke(ctx, "/kava.earn.v1beta1.Query/TotalDeposited", in, out, opts...)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return out, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// QueryServer is the server API for Query service.
 | 
			
		||||
type QueryServer interface {
 | 
			
		||||
	// Params queries all parameters of the earn module.
 | 
			
		||||
@ -585,8 +490,6 @@ type QueryServer interface {
 | 
			
		||||
	Vaults(context.Context, *QueryVaultsRequest) (*QueryVaultsResponse, error)
 | 
			
		||||
	// Deposits queries deposit details based on owner address and vault
 | 
			
		||||
	Deposits(context.Context, *QueryDepositsRequest) (*QueryDepositsResponse, error)
 | 
			
		||||
	// TotalDeposited queries total deposited amount for each vault.
 | 
			
		||||
	TotalDeposited(context.Context, *QueryTotalDepositedRequest) (*QueryTotalDepositedResponse, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UnimplementedQueryServer can be embedded to have forward compatible implementations.
 | 
			
		||||
@ -602,9 +505,6 @@ func (*UnimplementedQueryServer) Vaults(ctx context.Context, req *QueryVaultsReq
 | 
			
		||||
func (*UnimplementedQueryServer) Deposits(ctx context.Context, req *QueryDepositsRequest) (*QueryDepositsResponse, error) {
 | 
			
		||||
	return nil, status.Errorf(codes.Unimplemented, "method Deposits not implemented")
 | 
			
		||||
}
 | 
			
		||||
func (*UnimplementedQueryServer) TotalDeposited(ctx context.Context, req *QueryTotalDepositedRequest) (*QueryTotalDepositedResponse, error) {
 | 
			
		||||
	return nil, status.Errorf(codes.Unimplemented, "method TotalDeposited not implemented")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func RegisterQueryServer(s grpc1.Server, srv QueryServer) {
 | 
			
		||||
	s.RegisterService(&_Query_serviceDesc, srv)
 | 
			
		||||
@ -664,24 +564,6 @@ func _Query_Deposits_Handler(srv interface{}, ctx context.Context, dec func(inte
 | 
			
		||||
	return interceptor(ctx, in, info, handler)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func _Query_TotalDeposited_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
 | 
			
		||||
	in := new(QueryTotalDepositedRequest)
 | 
			
		||||
	if err := dec(in); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if interceptor == nil {
 | 
			
		||||
		return srv.(QueryServer).TotalDeposited(ctx, in)
 | 
			
		||||
	}
 | 
			
		||||
	info := &grpc.UnaryServerInfo{
 | 
			
		||||
		Server:     srv,
 | 
			
		||||
		FullMethod: "/kava.earn.v1beta1.Query/TotalDeposited",
 | 
			
		||||
	}
 | 
			
		||||
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
 | 
			
		||||
		return srv.(QueryServer).TotalDeposited(ctx, req.(*QueryTotalDepositedRequest))
 | 
			
		||||
	}
 | 
			
		||||
	return interceptor(ctx, in, info, handler)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _Query_serviceDesc = grpc.ServiceDesc{
 | 
			
		||||
	ServiceName: "kava.earn.v1beta1.Query",
 | 
			
		||||
	HandlerType: (*QueryServer)(nil),
 | 
			
		||||
@ -698,10 +580,6 @@ var _Query_serviceDesc = grpc.ServiceDesc{
 | 
			
		||||
			MethodName: "Deposits",
 | 
			
		||||
			Handler:    _Query_Deposits_Handler,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			MethodName: "TotalDeposited",
 | 
			
		||||
			Handler:    _Query_TotalDeposited_Handler,
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	Streams:  []grpc.StreamDesc{},
 | 
			
		||||
	Metadata: "kava/earn/v1beta1/query.proto",
 | 
			
		||||
@ -860,16 +738,13 @@ func (m *VaultResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 | 
			
		||||
	}
 | 
			
		||||
	i--
 | 
			
		||||
	dAtA[i] = 0x22
 | 
			
		||||
	{
 | 
			
		||||
		size := m.TotalSupplied.Size()
 | 
			
		||||
		i -= size
 | 
			
		||||
		if _, err := m.TotalSupplied.MarshalTo(dAtA[i:]); err != nil {
 | 
			
		||||
			return 0, err
 | 
			
		||||
		}
 | 
			
		||||
		i = encodeVarintQuery(dAtA, i, uint64(size))
 | 
			
		||||
	}
 | 
			
		||||
	if len(m.TotalShares) > 0 {
 | 
			
		||||
		i -= len(m.TotalShares)
 | 
			
		||||
		copy(dAtA[i:], m.TotalShares)
 | 
			
		||||
		i = encodeVarintQuery(dAtA, i, uint64(len(m.TotalShares)))
 | 
			
		||||
		i--
 | 
			
		||||
		dAtA[i] = 0x1a
 | 
			
		||||
	}
 | 
			
		||||
	if m.VaultStrategy != 0 {
 | 
			
		||||
		i = encodeVarintQuery(dAtA, i, uint64(m.VaultStrategy))
 | 
			
		||||
		i--
 | 
			
		||||
@ -1017,10 +892,10 @@ func (m *DepositResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 | 
			
		||||
			dAtA[i] = 0x1a
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if len(m.AmountSupplied) > 0 {
 | 
			
		||||
		for iNdEx := len(m.AmountSupplied) - 1; iNdEx >= 0; iNdEx-- {
 | 
			
		||||
	if len(m.Shares) > 0 {
 | 
			
		||||
		for iNdEx := len(m.Shares) - 1; iNdEx >= 0; iNdEx-- {
 | 
			
		||||
			{
 | 
			
		||||
				size, err := m.AmountSupplied[iNdEx].MarshalToSizedBuffer(dAtA[:i])
 | 
			
		||||
				size, err := m.Shares[iNdEx].MarshalToSizedBuffer(dAtA[:i])
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return 0, err
 | 
			
		||||
				}
 | 
			
		||||
@ -1041,73 +916,6 @@ func (m *DepositResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 | 
			
		||||
	return len(dAtA) - i, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *QueryTotalDepositedRequest) Marshal() (dAtA []byte, err error) {
 | 
			
		||||
	size := m.Size()
 | 
			
		||||
	dAtA = make([]byte, size)
 | 
			
		||||
	n, err := m.MarshalToSizedBuffer(dAtA[:size])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return dAtA[:n], nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *QueryTotalDepositedRequest) MarshalTo(dAtA []byte) (int, error) {
 | 
			
		||||
	size := m.Size()
 | 
			
		||||
	return m.MarshalToSizedBuffer(dAtA[:size])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *QueryTotalDepositedRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 | 
			
		||||
	i := len(dAtA)
 | 
			
		||||
	_ = i
 | 
			
		||||
	var l int
 | 
			
		||||
	_ = l
 | 
			
		||||
	if len(m.Denom) > 0 {
 | 
			
		||||
		i -= len(m.Denom)
 | 
			
		||||
		copy(dAtA[i:], m.Denom)
 | 
			
		||||
		i = encodeVarintQuery(dAtA, i, uint64(len(m.Denom)))
 | 
			
		||||
		i--
 | 
			
		||||
		dAtA[i] = 0xa
 | 
			
		||||
	}
 | 
			
		||||
	return len(dAtA) - i, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *QueryTotalDepositedResponse) Marshal() (dAtA []byte, err error) {
 | 
			
		||||
	size := m.Size()
 | 
			
		||||
	dAtA = make([]byte, size)
 | 
			
		||||
	n, err := m.MarshalToSizedBuffer(dAtA[:size])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return dAtA[:n], nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *QueryTotalDepositedResponse) MarshalTo(dAtA []byte) (int, error) {
 | 
			
		||||
	size := m.Size()
 | 
			
		||||
	return m.MarshalToSizedBuffer(dAtA[:size])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *QueryTotalDepositedResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 | 
			
		||||
	i := len(dAtA)
 | 
			
		||||
	_ = i
 | 
			
		||||
	var l int
 | 
			
		||||
	_ = l
 | 
			
		||||
	if len(m.SuppliedCoins) > 0 {
 | 
			
		||||
		for iNdEx := len(m.SuppliedCoins) - 1; iNdEx >= 0; iNdEx-- {
 | 
			
		||||
			{
 | 
			
		||||
				size, err := m.SuppliedCoins[iNdEx].MarshalToSizedBuffer(dAtA[:i])
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return 0, err
 | 
			
		||||
				}
 | 
			
		||||
				i -= size
 | 
			
		||||
				i = encodeVarintQuery(dAtA, i, uint64(size))
 | 
			
		||||
			}
 | 
			
		||||
			i--
 | 
			
		||||
			dAtA[i] = 0xa
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return len(dAtA) - i, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func encodeVarintQuery(dAtA []byte, offset int, v uint64) int {
 | 
			
		||||
	offset -= sovQuery(v)
 | 
			
		||||
	base := offset
 | 
			
		||||
@ -1180,8 +988,10 @@ func (m *VaultResponse) Size() (n int) {
 | 
			
		||||
	if m.VaultStrategy != 0 {
 | 
			
		||||
		n += 1 + sovQuery(uint64(m.VaultStrategy))
 | 
			
		||||
	}
 | 
			
		||||
	l = m.TotalSupplied.Size()
 | 
			
		||||
	l = len(m.TotalShares)
 | 
			
		||||
	if l > 0 {
 | 
			
		||||
		n += 1 + l + sovQuery(uint64(l))
 | 
			
		||||
	}
 | 
			
		||||
	l = m.TotalValue.Size()
 | 
			
		||||
	n += 1 + l + sovQuery(uint64(l))
 | 
			
		||||
	return n
 | 
			
		||||
@ -1237,8 +1047,8 @@ func (m *DepositResponse) Size() (n int) {
 | 
			
		||||
	if l > 0 {
 | 
			
		||||
		n += 1 + l + sovQuery(uint64(l))
 | 
			
		||||
	}
 | 
			
		||||
	if len(m.AmountSupplied) > 0 {
 | 
			
		||||
		for _, e := range m.AmountSupplied {
 | 
			
		||||
	if len(m.Shares) > 0 {
 | 
			
		||||
		for _, e := range m.Shares {
 | 
			
		||||
			l = e.Size()
 | 
			
		||||
			n += 1 + l + sovQuery(uint64(l))
 | 
			
		||||
		}
 | 
			
		||||
@ -1252,34 +1062,6 @@ func (m *DepositResponse) Size() (n int) {
 | 
			
		||||
	return n
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *QueryTotalDepositedRequest) Size() (n int) {
 | 
			
		||||
	if m == nil {
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
	var l int
 | 
			
		||||
	_ = l
 | 
			
		||||
	l = len(m.Denom)
 | 
			
		||||
	if l > 0 {
 | 
			
		||||
		n += 1 + l + sovQuery(uint64(l))
 | 
			
		||||
	}
 | 
			
		||||
	return n
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *QueryTotalDepositedResponse) Size() (n int) {
 | 
			
		||||
	if m == nil {
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
	var l int
 | 
			
		||||
	_ = l
 | 
			
		||||
	if len(m.SuppliedCoins) > 0 {
 | 
			
		||||
		for _, e := range m.SuppliedCoins {
 | 
			
		||||
			l = e.Size()
 | 
			
		||||
			n += 1 + l + sovQuery(uint64(l))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return n
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func sovQuery(x uint64) (n int) {
 | 
			
		||||
	return (math_bits.Len64(x|1) + 6) / 7
 | 
			
		||||
}
 | 
			
		||||
@ -1667,7 +1449,7 @@ func (m *VaultResponse) Unmarshal(dAtA []byte) error {
 | 
			
		||||
			}
 | 
			
		||||
		case 3:
 | 
			
		||||
			if wireType != 2 {
 | 
			
		||||
				return fmt.Errorf("proto: wrong wireType = %d for field TotalSupplied", wireType)
 | 
			
		||||
				return fmt.Errorf("proto: wrong wireType = %d for field TotalShares", wireType)
 | 
			
		||||
			}
 | 
			
		||||
			var stringLen uint64
 | 
			
		||||
			for shift := uint(0); ; shift += 7 {
 | 
			
		||||
@ -1695,9 +1477,7 @@ func (m *VaultResponse) Unmarshal(dAtA []byte) error {
 | 
			
		||||
			if postIndex > l {
 | 
			
		||||
				return io.ErrUnexpectedEOF
 | 
			
		||||
			}
 | 
			
		||||
			if err := m.TotalSupplied.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
			m.TotalShares = string(dAtA[iNdEx:postIndex])
 | 
			
		||||
			iNdEx = postIndex
 | 
			
		||||
		case 4:
 | 
			
		||||
			if wireType != 2 {
 | 
			
		||||
@ -2087,7 +1867,7 @@ func (m *DepositResponse) Unmarshal(dAtA []byte) error {
 | 
			
		||||
			iNdEx = postIndex
 | 
			
		||||
		case 2:
 | 
			
		||||
			if wireType != 2 {
 | 
			
		||||
				return fmt.Errorf("proto: wrong wireType = %d for field AmountSupplied", wireType)
 | 
			
		||||
				return fmt.Errorf("proto: wrong wireType = %d for field Shares", wireType)
 | 
			
		||||
			}
 | 
			
		||||
			var msglen int
 | 
			
		||||
			for shift := uint(0); ; shift += 7 {
 | 
			
		||||
@ -2114,8 +1894,8 @@ func (m *DepositResponse) Unmarshal(dAtA []byte) error {
 | 
			
		||||
			if postIndex > l {
 | 
			
		||||
				return io.ErrUnexpectedEOF
 | 
			
		||||
			}
 | 
			
		||||
			m.AmountSupplied = append(m.AmountSupplied, types.Coin{})
 | 
			
		||||
			if err := m.AmountSupplied[len(m.AmountSupplied)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
 | 
			
		||||
			m.Shares = append(m.Shares, VaultShare{})
 | 
			
		||||
			if err := m.Shares[len(m.Shares)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
			iNdEx = postIndex
 | 
			
		||||
@ -2174,172 +1954,6 @@ func (m *DepositResponse) Unmarshal(dAtA []byte) error {
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
func (m *QueryTotalDepositedRequest) Unmarshal(dAtA []byte) error {
 | 
			
		||||
	l := len(dAtA)
 | 
			
		||||
	iNdEx := 0
 | 
			
		||||
	for iNdEx < l {
 | 
			
		||||
		preIndex := iNdEx
 | 
			
		||||
		var wire uint64
 | 
			
		||||
		for shift := uint(0); ; shift += 7 {
 | 
			
		||||
			if shift >= 64 {
 | 
			
		||||
				return ErrIntOverflowQuery
 | 
			
		||||
			}
 | 
			
		||||
			if iNdEx >= l {
 | 
			
		||||
				return io.ErrUnexpectedEOF
 | 
			
		||||
			}
 | 
			
		||||
			b := dAtA[iNdEx]
 | 
			
		||||
			iNdEx++
 | 
			
		||||
			wire |= uint64(b&0x7F) << shift
 | 
			
		||||
			if b < 0x80 {
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		fieldNum := int32(wire >> 3)
 | 
			
		||||
		wireType := int(wire & 0x7)
 | 
			
		||||
		if wireType == 4 {
 | 
			
		||||
			return fmt.Errorf("proto: QueryTotalDepositedRequest: wiretype end group for non-group")
 | 
			
		||||
		}
 | 
			
		||||
		if fieldNum <= 0 {
 | 
			
		||||
			return fmt.Errorf("proto: QueryTotalDepositedRequest: illegal tag %d (wire type %d)", fieldNum, wire)
 | 
			
		||||
		}
 | 
			
		||||
		switch fieldNum {
 | 
			
		||||
		case 1:
 | 
			
		||||
			if wireType != 2 {
 | 
			
		||||
				return fmt.Errorf("proto: wrong wireType = %d for field Denom", wireType)
 | 
			
		||||
			}
 | 
			
		||||
			var stringLen uint64
 | 
			
		||||
			for shift := uint(0); ; shift += 7 {
 | 
			
		||||
				if shift >= 64 {
 | 
			
		||||
					return ErrIntOverflowQuery
 | 
			
		||||
				}
 | 
			
		||||
				if iNdEx >= l {
 | 
			
		||||
					return io.ErrUnexpectedEOF
 | 
			
		||||
				}
 | 
			
		||||
				b := dAtA[iNdEx]
 | 
			
		||||
				iNdEx++
 | 
			
		||||
				stringLen |= uint64(b&0x7F) << shift
 | 
			
		||||
				if b < 0x80 {
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			intStringLen := int(stringLen)
 | 
			
		||||
			if intStringLen < 0 {
 | 
			
		||||
				return ErrInvalidLengthQuery
 | 
			
		||||
			}
 | 
			
		||||
			postIndex := iNdEx + intStringLen
 | 
			
		||||
			if postIndex < 0 {
 | 
			
		||||
				return ErrInvalidLengthQuery
 | 
			
		||||
			}
 | 
			
		||||
			if postIndex > l {
 | 
			
		||||
				return io.ErrUnexpectedEOF
 | 
			
		||||
			}
 | 
			
		||||
			m.Denom = string(dAtA[iNdEx:postIndex])
 | 
			
		||||
			iNdEx = postIndex
 | 
			
		||||
		default:
 | 
			
		||||
			iNdEx = preIndex
 | 
			
		||||
			skippy, err := skipQuery(dAtA[iNdEx:])
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
			if (skippy < 0) || (iNdEx+skippy) < 0 {
 | 
			
		||||
				return ErrInvalidLengthQuery
 | 
			
		||||
			}
 | 
			
		||||
			if (iNdEx + skippy) > l {
 | 
			
		||||
				return io.ErrUnexpectedEOF
 | 
			
		||||
			}
 | 
			
		||||
			iNdEx += skippy
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if iNdEx > l {
 | 
			
		||||
		return io.ErrUnexpectedEOF
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
func (m *QueryTotalDepositedResponse) Unmarshal(dAtA []byte) error {
 | 
			
		||||
	l := len(dAtA)
 | 
			
		||||
	iNdEx := 0
 | 
			
		||||
	for iNdEx < l {
 | 
			
		||||
		preIndex := iNdEx
 | 
			
		||||
		var wire uint64
 | 
			
		||||
		for shift := uint(0); ; shift += 7 {
 | 
			
		||||
			if shift >= 64 {
 | 
			
		||||
				return ErrIntOverflowQuery
 | 
			
		||||
			}
 | 
			
		||||
			if iNdEx >= l {
 | 
			
		||||
				return io.ErrUnexpectedEOF
 | 
			
		||||
			}
 | 
			
		||||
			b := dAtA[iNdEx]
 | 
			
		||||
			iNdEx++
 | 
			
		||||
			wire |= uint64(b&0x7F) << shift
 | 
			
		||||
			if b < 0x80 {
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		fieldNum := int32(wire >> 3)
 | 
			
		||||
		wireType := int(wire & 0x7)
 | 
			
		||||
		if wireType == 4 {
 | 
			
		||||
			return fmt.Errorf("proto: QueryTotalDepositedResponse: wiretype end group for non-group")
 | 
			
		||||
		}
 | 
			
		||||
		if fieldNum <= 0 {
 | 
			
		||||
			return fmt.Errorf("proto: QueryTotalDepositedResponse: illegal tag %d (wire type %d)", fieldNum, wire)
 | 
			
		||||
		}
 | 
			
		||||
		switch fieldNum {
 | 
			
		||||
		case 1:
 | 
			
		||||
			if wireType != 2 {
 | 
			
		||||
				return fmt.Errorf("proto: wrong wireType = %d for field SuppliedCoins", wireType)
 | 
			
		||||
			}
 | 
			
		||||
			var msglen int
 | 
			
		||||
			for shift := uint(0); ; shift += 7 {
 | 
			
		||||
				if shift >= 64 {
 | 
			
		||||
					return ErrIntOverflowQuery
 | 
			
		||||
				}
 | 
			
		||||
				if iNdEx >= l {
 | 
			
		||||
					return io.ErrUnexpectedEOF
 | 
			
		||||
				}
 | 
			
		||||
				b := dAtA[iNdEx]
 | 
			
		||||
				iNdEx++
 | 
			
		||||
				msglen |= int(b&0x7F) << shift
 | 
			
		||||
				if b < 0x80 {
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if msglen < 0 {
 | 
			
		||||
				return ErrInvalidLengthQuery
 | 
			
		||||
			}
 | 
			
		||||
			postIndex := iNdEx + msglen
 | 
			
		||||
			if postIndex < 0 {
 | 
			
		||||
				return ErrInvalidLengthQuery
 | 
			
		||||
			}
 | 
			
		||||
			if postIndex > l {
 | 
			
		||||
				return io.ErrUnexpectedEOF
 | 
			
		||||
			}
 | 
			
		||||
			m.SuppliedCoins = append(m.SuppliedCoins, types.Coin{})
 | 
			
		||||
			if err := m.SuppliedCoins[len(m.SuppliedCoins)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
			iNdEx = postIndex
 | 
			
		||||
		default:
 | 
			
		||||
			iNdEx = preIndex
 | 
			
		||||
			skippy, err := skipQuery(dAtA[iNdEx:])
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
			if (skippy < 0) || (iNdEx+skippy) < 0 {
 | 
			
		||||
				return ErrInvalidLengthQuery
 | 
			
		||||
			}
 | 
			
		||||
			if (iNdEx + skippy) > l {
 | 
			
		||||
				return io.ErrUnexpectedEOF
 | 
			
		||||
			}
 | 
			
		||||
			iNdEx += skippy
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if iNdEx > l {
 | 
			
		||||
		return io.ErrUnexpectedEOF
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
func skipQuery(dAtA []byte) (n int, err error) {
 | 
			
		||||
	l := len(dAtA)
 | 
			
		||||
	iNdEx := 0
 | 
			
		||||
 | 
			
		||||
@ -139,60 +139,6 @@ func local_request_Query_Deposits_0(ctx context.Context, marshaler runtime.Marsh
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func request_Query_TotalDeposited_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
 | 
			
		||||
	var protoReq QueryTotalDepositedRequest
 | 
			
		||||
	var metadata runtime.ServerMetadata
 | 
			
		||||
 | 
			
		||||
	var (
 | 
			
		||||
		val string
 | 
			
		||||
		ok  bool
 | 
			
		||||
		err error
 | 
			
		||||
		_   = err
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	val, ok = pathParams["denom"]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "denom")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	protoReq.Denom, err = runtime.String(val)
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "denom", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	msg, err := client.TotalDeposited(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 | 
			
		||||
	return msg, metadata, err
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func local_request_Query_TotalDeposited_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
 | 
			
		||||
	var protoReq QueryTotalDepositedRequest
 | 
			
		||||
	var metadata runtime.ServerMetadata
 | 
			
		||||
 | 
			
		||||
	var (
 | 
			
		||||
		val string
 | 
			
		||||
		ok  bool
 | 
			
		||||
		err error
 | 
			
		||||
		_   = err
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	val, ok = pathParams["denom"]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "denom")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	protoReq.Denom, err = runtime.String(val)
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "denom", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	msg, err := server.TotalDeposited(ctx, &protoReq)
 | 
			
		||||
	return msg, metadata, err
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
 | 
			
		||||
// UnaryRPC     :call QueryServer directly.
 | 
			
		||||
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
 | 
			
		||||
@ -259,26 +205,6 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv
 | 
			
		||||
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	mux.Handle("GET", pattern_Query_TotalDeposited_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 | 
			
		||||
		ctx, cancel := context.WithCancel(req.Context())
 | 
			
		||||
		defer cancel()
 | 
			
		||||
		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
 | 
			
		||||
		rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		resp, md, err := local_request_Query_TotalDeposited_0(rctx, inboundMarshaler, server, req, pathParams)
 | 
			
		||||
		ctx = runtime.NewServerMetadataContext(ctx, md)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		forward_Query_TotalDeposited_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
 | 
			
		||||
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -380,26 +306,6 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie
 | 
			
		||||
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	mux.Handle("GET", pattern_Query_TotalDeposited_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 | 
			
		||||
		ctx, cancel := context.WithCancel(req.Context())
 | 
			
		||||
		defer cancel()
 | 
			
		||||
		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
 | 
			
		||||
		rctx, err := runtime.AnnotateContext(ctx, mux, req)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		resp, md, err := request_Query_TotalDeposited_0(rctx, inboundMarshaler, client, req, pathParams)
 | 
			
		||||
		ctx = runtime.NewServerMetadataContext(ctx, md)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		forward_Query_TotalDeposited_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
 | 
			
		||||
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -409,8 +315,6 @@ var (
 | 
			
		||||
	pattern_Query_Vaults_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"kava", "earn", "v1beta1", "vaults", "denom"}, "", runtime.AssumeColonVerbOpt(false)))
 | 
			
		||||
 | 
			
		||||
	pattern_Query_Deposits_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"kava", "earn", "v1beta1", "deposits"}, "", runtime.AssumeColonVerbOpt(false)))
 | 
			
		||||
 | 
			
		||||
	pattern_Query_TotalDeposited_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"kava", "earn", "v1beta1", "total-deposited", "denom"}, "", runtime.AssumeColonVerbOpt(false)))
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
@ -419,6 +323,4 @@ var (
 | 
			
		||||
	forward_Query_Vaults_0 = runtime.ForwardResponseMessage
 | 
			
		||||
 | 
			
		||||
	forward_Query_Deposits_0 = runtime.ForwardResponseMessage
 | 
			
		||||
 | 
			
		||||
	forward_Query_TotalDeposited_0 = runtime.ForwardResponseMessage
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										383
									
								
								x/earn/types/share.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										383
									
								
								x/earn/types/share.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,383 @@
 | 
			
		||||
package types
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	fmt "fmt"
 | 
			
		||||
	"sort"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
			
		||||
	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// NewVaultShare returns a new VaultShare
 | 
			
		||||
func NewVaultShare(denom string, amount sdk.Dec) VaultShare {
 | 
			
		||||
	share := VaultShare{
 | 
			
		||||
		Denom:  denom,
 | 
			
		||||
		Amount: amount,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := share.Validate(); err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return share
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Validate returns an error if a VaultShare is invalid.
 | 
			
		||||
func (share VaultShare) Validate() error {
 | 
			
		||||
	if err := sdk.ValidateDenom(share.Denom); err != nil {
 | 
			
		||||
		return sdkerrors.Wrap(ErrInvalidVaultDenom, err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if share.Amount.IsNil() {
 | 
			
		||||
		return fmt.Errorf("nil share amount: %s", share.Amount)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if share.Amount.IsNegative() {
 | 
			
		||||
		return fmt.Errorf("vault share amount %v is negative", share.Amount)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsValid returns true if the VaultShare is valid
 | 
			
		||||
func (share VaultShare) IsValid() bool {
 | 
			
		||||
	return share.Validate() == nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (share VaultShare) IsPositive() bool {
 | 
			
		||||
	return share.Amount.IsPositive()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Add adds amounts of two vault shares with same denom. If the shares differ in
 | 
			
		||||
// denom then it panics.
 | 
			
		||||
func (share VaultShare) Add(vsB VaultShare) VaultShare {
 | 
			
		||||
	if share.Denom != vsB.Denom {
 | 
			
		||||
		panic(fmt.Sprintf("invalid share denominations; %s, %s", share.Denom, vsB.Denom))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return NewVaultShare(share.Denom, share.Amount.Add(vsB.Amount))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsZero returns if this represents no shares
 | 
			
		||||
func (share VaultShare) IsZero() bool {
 | 
			
		||||
	return share.Amount.IsZero()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsNegative returns true if the share amount is negative and false otherwise.
 | 
			
		||||
func (share VaultShare) IsNegative() bool {
 | 
			
		||||
	return share.Amount.IsNegative()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Sub subtracts amounts of two vault shares with same denom. If the shares
 | 
			
		||||
// differ in denom then it panics.
 | 
			
		||||
func (share VaultShare) Sub(vsB VaultShare) VaultShare {
 | 
			
		||||
	if share.Denom != vsB.Denom {
 | 
			
		||||
		panic(fmt.Sprintf("invalid share denominations; %s, %s", share.Denom, vsB.Denom))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	res := NewVaultShare(share.Denom, share.Amount.Sub(vsB.Amount))
 | 
			
		||||
	if res.Amount.IsNegative() {
 | 
			
		||||
		panic("negative share amount")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (share VaultShare) String() string {
 | 
			
		||||
	return fmt.Sprintf("%v%v", share.Amount, share.Denom)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// VaultShares is a slice of VaultShare.
 | 
			
		||||
type VaultShares []VaultShare
 | 
			
		||||
 | 
			
		||||
// NewVaultShares returns new VaultShares
 | 
			
		||||
func NewVaultShares(shares ...VaultShare) VaultShares {
 | 
			
		||||
	newVaultShares := sanitizeVaultShares(shares)
 | 
			
		||||
	if err := newVaultShares.Validate(); err != nil {
 | 
			
		||||
		panic(fmt.Errorf("invalid share set %s: %w", newVaultShares, err))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return newVaultShares
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func sanitizeVaultShares(shares VaultShares) VaultShares {
 | 
			
		||||
	newVaultShares := removeZeroShares(shares)
 | 
			
		||||
	if len(newVaultShares) == 0 {
 | 
			
		||||
		return VaultShares{}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return newVaultShares.Sort()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Validate returns an error if a slice of VaultShares is invalid.
 | 
			
		||||
func (shares VaultShares) Validate() error {
 | 
			
		||||
	switch len(shares) {
 | 
			
		||||
	case 0:
 | 
			
		||||
		return nil
 | 
			
		||||
 | 
			
		||||
	case 1:
 | 
			
		||||
		if err := sdk.ValidateDenom(shares[0].Denom); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		if !shares[0].IsPositive() {
 | 
			
		||||
			return fmt.Errorf("share %s amount is not positive", shares[0])
 | 
			
		||||
		}
 | 
			
		||||
		return nil
 | 
			
		||||
	default:
 | 
			
		||||
		// check single share case
 | 
			
		||||
		if err := (VaultShares{shares[0]}).Validate(); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		lowDenom := shares[0].Denom
 | 
			
		||||
		seenDenoms := make(map[string]bool)
 | 
			
		||||
		seenDenoms[lowDenom] = true
 | 
			
		||||
 | 
			
		||||
		for _, share := range shares[1:] {
 | 
			
		||||
			if seenDenoms[share.Denom] {
 | 
			
		||||
				return fmt.Errorf("duplicate denomination %s", share.Denom)
 | 
			
		||||
			}
 | 
			
		||||
			if err := sdk.ValidateDenom(share.Denom); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
			if share.Denom <= lowDenom {
 | 
			
		||||
				return fmt.Errorf("denomination %s is not sorted", share.Denom)
 | 
			
		||||
			}
 | 
			
		||||
			if !share.IsPositive() {
 | 
			
		||||
				return fmt.Errorf("share %s amount is not positive", share.Denom)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// we compare each share against the last denom
 | 
			
		||||
			lowDenom = share.Denom
 | 
			
		||||
			seenDenoms[share.Denom] = true
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsValid returns true if the VaultShares are valid
 | 
			
		||||
func (shares VaultShares) IsValid() bool {
 | 
			
		||||
	return shares.Validate() == nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AmountOf returns the amount of shares of the given denom.
 | 
			
		||||
func (shares VaultShares) Add(sharesB ...VaultShare) VaultShares {
 | 
			
		||||
	return shares.safeAdd(sharesB)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// safeAdd will perform addition of two shares sets. If both share sets are
 | 
			
		||||
// empty, then an empty set is returned. If only a single set is empty, the
 | 
			
		||||
// other set is returned. Otherwise, the shares are compared in order of their
 | 
			
		||||
// denomination and addition only occurs when the denominations match, otherwise
 | 
			
		||||
// the share is simply added to the sum assuming it's not zero.
 | 
			
		||||
// The function panics if `shares` or  `sharesB` are not sorted (ascending).
 | 
			
		||||
func (shares VaultShares) safeAdd(sharesB VaultShares) VaultShares {
 | 
			
		||||
	// probably the best way will be to make Shares and interface and hide the structure
 | 
			
		||||
	// definition (type alias)
 | 
			
		||||
	if !shares.isSorted() {
 | 
			
		||||
		panic("Shares (self) must be sorted")
 | 
			
		||||
	}
 | 
			
		||||
	if !sharesB.isSorted() {
 | 
			
		||||
		panic("Wrong argument: shares must be sorted")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sum := (VaultShares)(nil)
 | 
			
		||||
	indexA, indexB := 0, 0
 | 
			
		||||
	lenA, lenB := len(shares), len(sharesB)
 | 
			
		||||
 | 
			
		||||
	for {
 | 
			
		||||
		if indexA == lenA {
 | 
			
		||||
			if indexB == lenB {
 | 
			
		||||
				// return nil shares if both sets are empty
 | 
			
		||||
				return sum
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// return set B (excluding zero shares) if set A is empty
 | 
			
		||||
			return append(sum, removeZeroShares(sharesB[indexB:])...)
 | 
			
		||||
		} else if indexB == lenB {
 | 
			
		||||
			// return set A (excluding zero shares) if set B is empty
 | 
			
		||||
			return append(sum, removeZeroShares(shares[indexA:])...)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		shareA, shareB := shares[indexA], sharesB[indexB]
 | 
			
		||||
 | 
			
		||||
		switch strings.Compare(shareA.Denom, shareB.Denom) {
 | 
			
		||||
		case -1: // share A denom < share B denom
 | 
			
		||||
			if !shareA.IsZero() {
 | 
			
		||||
				sum = append(sum, shareA)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			indexA++
 | 
			
		||||
 | 
			
		||||
		case 0: // share A denom == share B denom
 | 
			
		||||
			res := shareA.Add(shareB)
 | 
			
		||||
			if !res.IsZero() {
 | 
			
		||||
				sum = append(sum, res)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			indexA++
 | 
			
		||||
			indexB++
 | 
			
		||||
 | 
			
		||||
		case 1: // share A denom > share B denom
 | 
			
		||||
			if !shareB.IsZero() {
 | 
			
		||||
				sum = append(sum, shareB)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			indexB++
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Sub subtracts a set of shares from another.
 | 
			
		||||
//
 | 
			
		||||
// e.g.
 | 
			
		||||
// {2A, 3B} - {A} = {A, 3B}
 | 
			
		||||
// {2A} - {0B} = {2A}
 | 
			
		||||
// {A, B} - {A} = {B}
 | 
			
		||||
//
 | 
			
		||||
// CONTRACT: Sub will never return Shares where one Share has a non-positive
 | 
			
		||||
// amount. In otherwords, IsValid will always return true.
 | 
			
		||||
func (shares VaultShares) Sub(sharesB ...VaultShare) VaultShares {
 | 
			
		||||
	diff, hasNeg := shares.SafeSub(sharesB)
 | 
			
		||||
	if hasNeg {
 | 
			
		||||
		panic("negative share amount")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return diff
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SafeSub performs the same arithmetic as Sub but returns a boolean if any
 | 
			
		||||
// negative share amount was returned.
 | 
			
		||||
// The function panics if `shares` or  `sharesB` are not sorted (ascending).
 | 
			
		||||
func (shares VaultShares) SafeSub(sharesB VaultShares) (VaultShares, bool) {
 | 
			
		||||
	diff := shares.safeAdd(sharesB.negative())
 | 
			
		||||
	return diff, diff.IsAnyNegative()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsAnyNegative returns true if there is at least one share whose amount
 | 
			
		||||
// is negative; returns false otherwise. It returns false if the share set
 | 
			
		||||
// is empty too.
 | 
			
		||||
func (shares VaultShares) IsAnyNegative() bool {
 | 
			
		||||
	for _, share := range shares {
 | 
			
		||||
		if share.IsNegative() {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// negative returns a set of shares with all amount negative.
 | 
			
		||||
func (shares VaultShares) negative() VaultShares {
 | 
			
		||||
	res := make(VaultShares, 0, len(shares))
 | 
			
		||||
 | 
			
		||||
	for _, share := range shares {
 | 
			
		||||
		res = append(res, VaultShare{
 | 
			
		||||
			Denom:  share.Denom,
 | 
			
		||||
			Amount: share.Amount.Neg(),
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AmountOf returns the amount of shares of the given denom.
 | 
			
		||||
func (v VaultShares) AmountOf(denom string) sdk.Dec {
 | 
			
		||||
	for _, s := range v {
 | 
			
		||||
		if s.Denom == denom {
 | 
			
		||||
			return s.Amount
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return sdk.ZeroDec()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetShare the single share of the given denom.
 | 
			
		||||
func (v VaultShares) GetShare(denom string) VaultShare {
 | 
			
		||||
	for _, s := range v {
 | 
			
		||||
		if s.Denom == denom {
 | 
			
		||||
			return s
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return NewVaultShare(denom, sdk.ZeroDec())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsZero returns true if the VaultShares is empty.
 | 
			
		||||
func (v VaultShares) IsZero() bool {
 | 
			
		||||
	for _, s := range v {
 | 
			
		||||
		// If any amount is non-zero, false
 | 
			
		||||
		if !s.Amount.IsZero() {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (shares VaultShares) isSorted() bool {
 | 
			
		||||
	for i := 1; i < len(shares); i++ {
 | 
			
		||||
		if shares[i-1].Denom > shares[i].Denom {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (shares VaultShares) String() string {
 | 
			
		||||
	if len(shares) == 0 {
 | 
			
		||||
		return ""
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	out := ""
 | 
			
		||||
	for _, share := range shares {
 | 
			
		||||
		out += fmt.Sprintf("%v,", share.String())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return out[:len(out)-1]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// removeZeroShares removes all zero shares from the given share set in-place.
 | 
			
		||||
func removeZeroShares(shares VaultShares) VaultShares {
 | 
			
		||||
	for i := 0; i < len(shares); i++ {
 | 
			
		||||
		if shares[i].IsZero() {
 | 
			
		||||
			break
 | 
			
		||||
		} else if i == len(shares)-1 {
 | 
			
		||||
			return shares
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var result VaultShares
 | 
			
		||||
	if len(shares) > 0 {
 | 
			
		||||
		result = make(VaultShares, 0, len(shares)-1)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, share := range shares {
 | 
			
		||||
		if !share.IsZero() {
 | 
			
		||||
			result = append(result, share)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ----------------------------------------------------------------------------
 | 
			
		||||
// VaultShares sort interface
 | 
			
		||||
 | 
			
		||||
func (a VaultShares) Len() int { return len(a) }
 | 
			
		||||
 | 
			
		||||
// Less implements sort.Interface for VaultShares
 | 
			
		||||
func (shares VaultShares) Less(i, j int) bool { return shares[i].Denom < shares[j].Denom }
 | 
			
		||||
 | 
			
		||||
// Swap implements sort.Interface for VaultShares
 | 
			
		||||
func (shares VaultShares) Swap(i, j int) { shares[i], shares[j] = shares[j], shares[i] }
 | 
			
		||||
 | 
			
		||||
var _ sort.Interface = VaultShares{}
 | 
			
		||||
 | 
			
		||||
// Sort is a helper function to sort the set of vault shares in-place
 | 
			
		||||
func (shares VaultShares) Sort() VaultShares {
 | 
			
		||||
	sort.Sort(shares)
 | 
			
		||||
	return shares
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										446
									
								
								x/earn/types/share_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										446
									
								
								x/earn/types/share_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,446 @@
 | 
			
		||||
package types_test
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"strings"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/kava-labs/kava/x/earn/types"
 | 
			
		||||
	"github.com/stretchr/testify/suite"
 | 
			
		||||
 | 
			
		||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	testDenom1 = "ukava"
 | 
			
		||||
	testDenom2 = "usdx"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func d(i int64) sdk.Dec {
 | 
			
		||||
	return sdk.NewDec(i)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type vaultShareTestSuite struct {
 | 
			
		||||
	suite.Suite
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestVaultShareTestSuite(t *testing.T) {
 | 
			
		||||
	suite.Run(t, new(vaultShareTestSuite))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *vaultShareTestSuite) TestNewVaultShareFromDec() {
 | 
			
		||||
	s.Require().NotPanics(func() {
 | 
			
		||||
		types.NewVaultShare(testDenom1, sdk.NewDec(5))
 | 
			
		||||
	})
 | 
			
		||||
	s.Require().NotPanics(func() {
 | 
			
		||||
		types.NewVaultShare(testDenom1, sdk.ZeroDec())
 | 
			
		||||
	})
 | 
			
		||||
	s.Require().NotPanics(func() {
 | 
			
		||||
		types.NewVaultShare(strings.ToUpper(testDenom1), sdk.NewDec(5))
 | 
			
		||||
	})
 | 
			
		||||
	s.Require().Panics(func() {
 | 
			
		||||
		types.NewVaultShare(testDenom1, sdk.NewDec(-5))
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *vaultShareTestSuite) TestAddVaultShare() {
 | 
			
		||||
	vaultShareA1 := types.NewVaultShare(testDenom1, sdk.NewDecWithPrec(11, 1))
 | 
			
		||||
	vaultShareA2 := types.NewVaultShare(testDenom1, sdk.NewDecWithPrec(22, 1))
 | 
			
		||||
	vaultShareB1 := types.NewVaultShare(testDenom2, sdk.NewDecWithPrec(11, 1))
 | 
			
		||||
 | 
			
		||||
	// regular add
 | 
			
		||||
	res := vaultShareA1.Add(vaultShareA1)
 | 
			
		||||
	s.Require().Equal(vaultShareA2, res, "sum of shares is incorrect")
 | 
			
		||||
 | 
			
		||||
	// bad denom add
 | 
			
		||||
	s.Require().Panics(func() {
 | 
			
		||||
		vaultShareA1.Add(vaultShareB1)
 | 
			
		||||
	}, "expected panic on sum of different denoms")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *vaultShareTestSuite) TestAddVaultShares() {
 | 
			
		||||
	one := sdk.NewDec(1)
 | 
			
		||||
	zero := sdk.NewDec(0)
 | 
			
		||||
	two := sdk.NewDec(2)
 | 
			
		||||
 | 
			
		||||
	cases := []struct {
 | 
			
		||||
		inputOne types.VaultShares
 | 
			
		||||
		inputTwo types.VaultShares
 | 
			
		||||
		expected types.VaultShares
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			types.VaultShares{
 | 
			
		||||
				{testDenom1, one},
 | 
			
		||||
				{testDenom2, one},
 | 
			
		||||
			},
 | 
			
		||||
			types.VaultShares{
 | 
			
		||||
				{testDenom1, one},
 | 
			
		||||
				{testDenom2, one},
 | 
			
		||||
			},
 | 
			
		||||
			types.VaultShares{
 | 
			
		||||
				{testDenom1, two},
 | 
			
		||||
				{testDenom2, two},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			types.VaultShares{
 | 
			
		||||
				{testDenom1, zero},
 | 
			
		||||
				{testDenom2, one},
 | 
			
		||||
			},
 | 
			
		||||
			types.VaultShares{
 | 
			
		||||
				{testDenom1, zero},
 | 
			
		||||
				{testDenom2, zero},
 | 
			
		||||
			},
 | 
			
		||||
			types.VaultShares{
 | 
			
		||||
				{testDenom2, one},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			types.VaultShares{
 | 
			
		||||
				{testDenom1, zero},
 | 
			
		||||
				{testDenom2, zero},
 | 
			
		||||
			},
 | 
			
		||||
			types.VaultShares{
 | 
			
		||||
				{testDenom1, zero},
 | 
			
		||||
				{testDenom2, zero},
 | 
			
		||||
			},
 | 
			
		||||
			types.VaultShares(nil),
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for tcIndex, tc := range cases {
 | 
			
		||||
		res := tc.inputOne.Add(tc.inputTwo...)
 | 
			
		||||
		s.Require().Equal(tc.expected, res, "sum of shares is incorrect, tc #%d", tcIndex)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *vaultShareTestSuite) TestFilteredZeroVaultShares() {
 | 
			
		||||
	cases := []struct {
 | 
			
		||||
		name     string
 | 
			
		||||
		input    types.VaultShares
 | 
			
		||||
		original string
 | 
			
		||||
		expected string
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name: "all greater than zero",
 | 
			
		||||
			input: types.VaultShares{
 | 
			
		||||
				{"testa", sdk.NewDec(1)},
 | 
			
		||||
				{"testb", sdk.NewDec(2)},
 | 
			
		||||
				{"testc", sdk.NewDec(3)},
 | 
			
		||||
				{"testd", sdk.NewDec(4)},
 | 
			
		||||
				{"teste", sdk.NewDec(5)},
 | 
			
		||||
			},
 | 
			
		||||
			original: "1.000000000000000000testa,2.000000000000000000testb,3.000000000000000000testc,4.000000000000000000testd,5.000000000000000000teste",
 | 
			
		||||
			expected: "1.000000000000000000testa,2.000000000000000000testb,3.000000000000000000testc,4.000000000000000000testd,5.000000000000000000teste",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "zero share in middle",
 | 
			
		||||
			input: types.VaultShares{
 | 
			
		||||
				{"testa", sdk.NewDec(1)},
 | 
			
		||||
				{"testb", sdk.NewDec(2)},
 | 
			
		||||
				{"testc", sdk.NewDec(0)},
 | 
			
		||||
				{"testd", sdk.NewDec(4)},
 | 
			
		||||
				{"teste", sdk.NewDec(5)},
 | 
			
		||||
			},
 | 
			
		||||
			original: "1.000000000000000000testa,2.000000000000000000testb,0.000000000000000000testc,4.000000000000000000testd,5.000000000000000000teste",
 | 
			
		||||
			expected: "1.000000000000000000testa,2.000000000000000000testb,4.000000000000000000testd,5.000000000000000000teste",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "zero share end (unordered)",
 | 
			
		||||
			input: types.VaultShares{
 | 
			
		||||
				{"teste", sdk.NewDec(5)},
 | 
			
		||||
				{"testc", sdk.NewDec(3)},
 | 
			
		||||
				{"testa", sdk.NewDec(1)},
 | 
			
		||||
				{"testd", sdk.NewDec(4)},
 | 
			
		||||
				{"testb", sdk.NewDec(0)},
 | 
			
		||||
			},
 | 
			
		||||
			original: "5.000000000000000000teste,3.000000000000000000testc,1.000000000000000000testa,4.000000000000000000testd,0.000000000000000000testb",
 | 
			
		||||
			expected: "1.000000000000000000testa,3.000000000000000000testc,4.000000000000000000testd,5.000000000000000000teste",
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, tt := range cases {
 | 
			
		||||
		undertest := types.NewVaultShares(tt.input...)
 | 
			
		||||
		s.Require().Equal(tt.expected, undertest.String(), "NewVaultShares must return expected results")
 | 
			
		||||
		s.Require().Equal(tt.original, tt.input.String(), "input must be unmodified and match original")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *vaultShareTestSuite) TestIsValid() {
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		share      types.VaultShare
 | 
			
		||||
		expectPass bool
 | 
			
		||||
		msg        string
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			types.NewVaultShare("mytoken", sdk.NewDec(10)),
 | 
			
		||||
			true,
 | 
			
		||||
			"valid shares should have passed",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			types.VaultShare{Denom: "BTC", Amount: sdk.NewDec(10)},
 | 
			
		||||
			true,
 | 
			
		||||
			"valid uppercase denom",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			types.VaultShare{Denom: "Bitshare", Amount: sdk.NewDec(10)},
 | 
			
		||||
			true,
 | 
			
		||||
			"valid mixed case denom",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			types.VaultShare{Denom: "btc", Amount: sdk.NewDec(-10)},
 | 
			
		||||
			false,
 | 
			
		||||
			"negative amount",
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, tc := range tests {
 | 
			
		||||
		tc := tc
 | 
			
		||||
		if tc.expectPass {
 | 
			
		||||
			s.Require().True(tc.share.IsValid(), tc.msg)
 | 
			
		||||
		} else {
 | 
			
		||||
			s.Require().False(tc.share.IsValid(), tc.msg)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *vaultShareTestSuite) TestSubVaultShare() {
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		share      types.VaultShare
 | 
			
		||||
		expectPass bool
 | 
			
		||||
		msg        string
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			types.NewVaultShare("mytoken", sdk.NewDec(20)),
 | 
			
		||||
			true,
 | 
			
		||||
			"valid shares should have passed",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			types.NewVaultShare("othertoken", sdk.NewDec(20)),
 | 
			
		||||
			false,
 | 
			
		||||
			"denom mismatch",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			types.NewVaultShare("mytoken", sdk.NewDec(9)),
 | 
			
		||||
			false,
 | 
			
		||||
			"negative amount",
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	vaultShare := types.NewVaultShare("mytoken", sdk.NewDec(10))
 | 
			
		||||
 | 
			
		||||
	for _, tc := range tests {
 | 
			
		||||
		tc := tc
 | 
			
		||||
		if tc.expectPass {
 | 
			
		||||
			equal := tc.share.Sub(vaultShare)
 | 
			
		||||
			s.Require().Equal(equal, vaultShare, tc.msg)
 | 
			
		||||
		} else {
 | 
			
		||||
			s.Require().Panics(func() { tc.share.Sub(vaultShare) }, tc.msg)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *vaultShareTestSuite) TestSubVaultShares() {
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		shares     types.VaultShares
 | 
			
		||||
		expectPass bool
 | 
			
		||||
		msg        string
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			types.NewVaultShares(types.NewVaultShare("mytoken", d(10)), types.NewVaultShare("btc", d(20)), types.NewVaultShare("eth", d(30))),
 | 
			
		||||
			true,
 | 
			
		||||
			"sorted shares should have passed",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			types.VaultShares{types.NewVaultShare("mytoken", d(10)), types.NewVaultShare("btc", d(20)), types.NewVaultShare("eth", d(30))},
 | 
			
		||||
			false,
 | 
			
		||||
			"unorted shares should panic",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			types.VaultShares{types.VaultShare{Denom: "BTC", Amount: sdk.NewDec(10)}, types.NewVaultShare("eth", d(15)), types.NewVaultShare("mytoken", d(5))},
 | 
			
		||||
			false,
 | 
			
		||||
			"invalid denoms",
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	vaultShares := types.NewVaultShares(types.NewVaultShare("btc", d(10)), types.NewVaultShare("eth", d(15)), types.NewVaultShare("mytoken", d(5)))
 | 
			
		||||
 | 
			
		||||
	for _, tc := range tests {
 | 
			
		||||
		tc := tc
 | 
			
		||||
		if tc.expectPass {
 | 
			
		||||
			equal := tc.shares.Sub(vaultShares...)
 | 
			
		||||
			s.Require().Equal(equal, vaultShares, tc.msg)
 | 
			
		||||
		} else {
 | 
			
		||||
			s.Require().Panics(func() { tc.shares.Sub(vaultShares...) }, tc.msg)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *vaultShareTestSuite) TestSortVaultShares() {
 | 
			
		||||
	good := types.VaultShares{
 | 
			
		||||
		types.NewVaultShare("gas", d(1)),
 | 
			
		||||
		types.NewVaultShare("mineral", d(1)),
 | 
			
		||||
		types.NewVaultShare("tree", d(1)),
 | 
			
		||||
	}
 | 
			
		||||
	empty := types.VaultShares{
 | 
			
		||||
		types.NewVaultShare("gold", d(0)),
 | 
			
		||||
	}
 | 
			
		||||
	badSort1 := types.VaultShares{
 | 
			
		||||
		types.NewVaultShare("tree", d(1)),
 | 
			
		||||
		types.NewVaultShare("gas", d(1)),
 | 
			
		||||
		types.NewVaultShare("mineral", d(1)),
 | 
			
		||||
	}
 | 
			
		||||
	badSort2 := types.VaultShares{ // both are after the first one, but the second and third are in the wrong order
 | 
			
		||||
		types.NewVaultShare("gas", d(1)),
 | 
			
		||||
		types.NewVaultShare("tree", d(1)),
 | 
			
		||||
		types.NewVaultShare("mineral", d(1)),
 | 
			
		||||
	}
 | 
			
		||||
	badAmt := types.VaultShares{
 | 
			
		||||
		types.NewVaultShare("gas", d(1)),
 | 
			
		||||
		types.NewVaultShare("tree", d(0)),
 | 
			
		||||
		types.NewVaultShare("mineral", d(1)),
 | 
			
		||||
	}
 | 
			
		||||
	dup := types.VaultShares{
 | 
			
		||||
		types.NewVaultShare("gas", d(1)),
 | 
			
		||||
		types.NewVaultShare("gas", d(1)),
 | 
			
		||||
		types.NewVaultShare("mineral", d(1)),
 | 
			
		||||
	}
 | 
			
		||||
	cases := []struct {
 | 
			
		||||
		name          string
 | 
			
		||||
		shares        types.VaultShares
 | 
			
		||||
		before, after bool // valid before/after sort
 | 
			
		||||
	}{
 | 
			
		||||
		{"valid shares", good, true, true},
 | 
			
		||||
		{"empty shares", empty, false, false},
 | 
			
		||||
		{"unsorted shares (1)", badSort1, false, true},
 | 
			
		||||
		{"unsorted shares (2)", badSort2, false, true},
 | 
			
		||||
		{"zero amount shares", badAmt, false, false},
 | 
			
		||||
		{"duplicate shares", dup, false, false},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, tc := range cases {
 | 
			
		||||
		s.Require().Equal(tc.before, tc.shares.IsValid(), "share validity is incorrect before sorting; %s", tc.name)
 | 
			
		||||
		tc.shares.Sort()
 | 
			
		||||
		s.Require().Equal(tc.after, tc.shares.IsValid(), "share validity is incorrect after sorting;  %s", tc.name)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *vaultShareTestSuite) TestVaultSharesValidate() {
 | 
			
		||||
	testCases := []struct {
 | 
			
		||||
		input        types.VaultShares
 | 
			
		||||
		expectedPass bool
 | 
			
		||||
	}{
 | 
			
		||||
		{types.VaultShares{}, true},
 | 
			
		||||
		{types.VaultShares{types.VaultShare{testDenom1, sdk.NewDec(5)}}, true},
 | 
			
		||||
		{types.VaultShares{types.VaultShare{testDenom1, sdk.NewDec(5)}, types.VaultShare{testDenom2, sdk.NewDec(100000)}}, true},
 | 
			
		||||
		{types.VaultShares{types.VaultShare{testDenom1, sdk.NewDec(-5)}}, false},
 | 
			
		||||
		{types.VaultShares{types.VaultShare{"BTC", sdk.NewDec(5)}}, true},
 | 
			
		||||
		{types.VaultShares{types.VaultShare{"0BTC", sdk.NewDec(5)}}, false},
 | 
			
		||||
		{types.VaultShares{types.VaultShare{testDenom1, sdk.NewDec(5)}, types.VaultShare{"B", sdk.NewDec(100000)}}, false},
 | 
			
		||||
		{types.VaultShares{types.VaultShare{testDenom1, sdk.NewDec(5)}, types.VaultShare{testDenom2, sdk.NewDec(-100000)}}, false},
 | 
			
		||||
		{types.VaultShares{types.VaultShare{testDenom1, sdk.NewDec(-5)}, types.VaultShare{testDenom2, sdk.NewDec(100000)}}, false},
 | 
			
		||||
		{types.VaultShares{types.VaultShare{"BTC", sdk.NewDec(5)}, types.VaultShare{testDenom2, sdk.NewDec(100000)}}, true},
 | 
			
		||||
		{types.VaultShares{types.VaultShare{"0BTC", sdk.NewDec(5)}, types.VaultShare{testDenom2, sdk.NewDec(100000)}}, false},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for i, tc := range testCases {
 | 
			
		||||
		err := tc.input.Validate()
 | 
			
		||||
		if tc.expectedPass {
 | 
			
		||||
			s.Require().NoError(err, "unexpected result for test case #%d, input: %v", i, tc.input)
 | 
			
		||||
		} else {
 | 
			
		||||
			s.Require().Error(err, "unexpected result for test case #%d, input: %v", i, tc.input)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *vaultShareTestSuite) TestVaultSharesString() {
 | 
			
		||||
	testCases := []struct {
 | 
			
		||||
		input    types.VaultShares
 | 
			
		||||
		expected string
 | 
			
		||||
	}{
 | 
			
		||||
		{types.VaultShares{}, ""},
 | 
			
		||||
		{
 | 
			
		||||
			types.VaultShares{
 | 
			
		||||
				types.NewVaultShare("atom", sdk.NewDecWithPrec(5040000000000000000, sdk.Precision)),
 | 
			
		||||
				types.NewVaultShare("stake", sdk.NewDecWithPrec(4000000000000000, sdk.Precision)),
 | 
			
		||||
			},
 | 
			
		||||
			"5.040000000000000000atom,0.004000000000000000stake",
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for i, tc := range testCases {
 | 
			
		||||
		out := tc.input.String()
 | 
			
		||||
		s.Require().Equal(tc.expected, out, "unexpected result for test case #%d, input: %v", i, tc.input)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *vaultShareTestSuite) TestNewVaultSharesWithIsValid() {
 | 
			
		||||
	fake1 := append(types.NewVaultShares(types.NewVaultShare("mytoken", d(10))), types.VaultShare{Denom: "10BTC", Amount: sdk.NewDec(10)})
 | 
			
		||||
	fake2 := append(types.NewVaultShares(types.NewVaultShare("mytoken", d(10))), types.VaultShare{Denom: "BTC", Amount: sdk.NewDec(-10)})
 | 
			
		||||
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		share      types.VaultShares
 | 
			
		||||
		expectPass bool
 | 
			
		||||
		msg        string
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			types.NewVaultShares(types.NewVaultShare("mytoken", d(10))),
 | 
			
		||||
			true,
 | 
			
		||||
			"valid shares should have passed",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			fake1,
 | 
			
		||||
			false,
 | 
			
		||||
			"invalid denoms",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			fake2,
 | 
			
		||||
			false,
 | 
			
		||||
			"negative amount",
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, tc := range tests {
 | 
			
		||||
		tc := tc
 | 
			
		||||
		if tc.expectPass {
 | 
			
		||||
			s.Require().True(tc.share.IsValid(), tc.msg)
 | 
			
		||||
		} else {
 | 
			
		||||
			s.Require().False(tc.share.IsValid(), tc.msg)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *vaultShareTestSuite) TestVaultShares_AddVaultShareWithIsValid() {
 | 
			
		||||
	lengthTestVaultShares := types.NewVaultShares().Add(types.NewVaultShare("mytoken", d(10))).Add(types.VaultShare{Denom: "BTC", Amount: sdk.NewDec(10)})
 | 
			
		||||
	s.Require().Equal(2, len(lengthTestVaultShares), "should be 2")
 | 
			
		||||
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		share      types.VaultShares
 | 
			
		||||
		expectPass bool
 | 
			
		||||
		msg        string
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			types.NewVaultShares().Add(types.NewVaultShare("mytoken", d(10))),
 | 
			
		||||
			true,
 | 
			
		||||
			"valid shares should have passed",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			types.NewVaultShares().Add(types.NewVaultShare("mytoken", d(10))).Add(types.VaultShare{Denom: "0BTC", Amount: sdk.NewDec(10)}),
 | 
			
		||||
			false,
 | 
			
		||||
			"invalid denoms",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			types.NewVaultShares().Add(types.NewVaultShare("mytoken", d(10))).Add(types.VaultShare{Denom: "BTC", Amount: sdk.NewDec(-10)}),
 | 
			
		||||
			false,
 | 
			
		||||
			"negative amount",
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, tc := range tests {
 | 
			
		||||
		tc := tc
 | 
			
		||||
		if tc.expectPass {
 | 
			
		||||
			s.Require().True(tc.share.IsValid(), tc.msg)
 | 
			
		||||
		} else {
 | 
			
		||||
			s.Require().False(tc.share.IsValid(), tc.msg)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -74,6 +74,7 @@ var xxx_messageInfo_MsgDeposit proto.InternalMessageInfo
 | 
			
		||||
 | 
			
		||||
// MsgDepositResponse defines the Msg/Deposit response type.
 | 
			
		||||
type MsgDepositResponse struct {
 | 
			
		||||
	Shares VaultShare `protobuf:"bytes,1,opt,name=shares,proto3" json:"shares"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *MsgDepositResponse) Reset()         { *m = MsgDepositResponse{} }
 | 
			
		||||
@ -109,6 +110,13 @@ func (m *MsgDepositResponse) XXX_DiscardUnknown() {
 | 
			
		||||
 | 
			
		||||
var xxx_messageInfo_MsgDepositResponse proto.InternalMessageInfo
 | 
			
		||||
 | 
			
		||||
func (m *MsgDepositResponse) GetShares() VaultShare {
 | 
			
		||||
	if m != nil {
 | 
			
		||||
		return m.Shares
 | 
			
		||||
	}
 | 
			
		||||
	return VaultShare{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MsgWithdraw represents a message for withdrawing liquidity from a vault
 | 
			
		||||
type MsgWithdraw struct {
 | 
			
		||||
	// from represents the address we are withdrawing for
 | 
			
		||||
@ -153,6 +161,7 @@ var xxx_messageInfo_MsgWithdraw proto.InternalMessageInfo
 | 
			
		||||
 | 
			
		||||
// MsgWithdrawResponse defines the Msg/Withdraw response type.
 | 
			
		||||
type MsgWithdrawResponse struct {
 | 
			
		||||
	Shares VaultShare `protobuf:"bytes,1,opt,name=shares,proto3" json:"shares"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *MsgWithdrawResponse) Reset()         { *m = MsgWithdrawResponse{} }
 | 
			
		||||
@ -188,6 +197,13 @@ func (m *MsgWithdrawResponse) XXX_DiscardUnknown() {
 | 
			
		||||
 | 
			
		||||
var xxx_messageInfo_MsgWithdrawResponse proto.InternalMessageInfo
 | 
			
		||||
 | 
			
		||||
func (m *MsgWithdrawResponse) GetShares() VaultShare {
 | 
			
		||||
	if m != nil {
 | 
			
		||||
		return m.Shares
 | 
			
		||||
	}
 | 
			
		||||
	return VaultShare{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	proto.RegisterType((*MsgDeposit)(nil), "kava.earn.v1beta1.MsgDeposit")
 | 
			
		||||
	proto.RegisterType((*MsgDepositResponse)(nil), "kava.earn.v1beta1.MsgDepositResponse")
 | 
			
		||||
@ -198,30 +214,33 @@ func init() {
 | 
			
		||||
func init() { proto.RegisterFile("kava/earn/v1beta1/tx.proto", fileDescriptor_2e9dcf48a3fa0009) }
 | 
			
		||||
 | 
			
		||||
var fileDescriptor_2e9dcf48a3fa0009 = []byte{
 | 
			
		||||
	// 367 bytes of a gzipped FileDescriptorProto
 | 
			
		||||
	// 404 bytes of a gzipped FileDescriptorProto
 | 
			
		||||
	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xca, 0x4e, 0x2c, 0x4b,
 | 
			
		||||
	0xd4, 0x4f, 0x4d, 0x2c, 0xca, 0xd3, 0x2f, 0x33, 0x4c, 0x4a, 0x2d, 0x49, 0x34, 0xd4, 0x2f, 0xa9,
 | 
			
		||||
	0xd0, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x04, 0xc9, 0xe9, 0x81, 0xe4, 0xf4, 0xa0, 0x72,
 | 
			
		||||
	0x52, 0x92, 0xc9, 0xf9, 0xc5, 0xb9, 0xf9, 0xc5, 0xf1, 0x60, 0x05, 0xfa, 0x10, 0x0e, 0x44, 0xb5,
 | 
			
		||||
	0x94, 0x1c, 0x84, 0xa7, 0x9f, 0x94, 0x58, 0x9c, 0x0a, 0x37, 0x2b, 0x39, 0x3f, 0x33, 0x0f, 0x2a,
 | 
			
		||||
	0x2f, 0x92, 0x9e, 0x9f, 0x9e, 0x0f, 0xd1, 0x07, 0x62, 0x41, 0x44, 0x95, 0x9a, 0x19, 0xb9, 0xb8,
 | 
			
		||||
	0x7c, 0x8b, 0xd3, 0x5d, 0x52, 0x0b, 0xf2, 0x8b, 0x33, 0x4b, 0x84, 0xcc, 0xb8, 0x38, 0x53, 0x20,
 | 
			
		||||
	0xcc, 0xfc, 0x22, 0x09, 0x46, 0x05, 0x46, 0x0d, 0x4e, 0x27, 0x89, 0x4b, 0x5b, 0x74, 0x45, 0xa0,
 | 
			
		||||
	0x36, 0x39, 0xa6, 0xa4, 0x14, 0xa5, 0x16, 0x17, 0x07, 0x97, 0x14, 0x65, 0xe6, 0xa5, 0x07, 0x21,
 | 
			
		||||
	0x94, 0x0a, 0x99, 0x73, 0xb1, 0x25, 0xe6, 0xe6, 0x97, 0xe6, 0x95, 0x48, 0x30, 0x29, 0x30, 0x6a,
 | 
			
		||||
	0x70, 0x1b, 0x49, 0xea, 0x41, 0x75, 0x80, 0x5c, 0x03, 0x73, 0xbd, 0x9e, 0x73, 0x7e, 0x66, 0x9e,
 | 
			
		||||
	0x13, 0xcb, 0x89, 0x7b, 0xf2, 0x0c, 0x41, 0x50, 0xe5, 0x56, 0x2c, 0x1d, 0x0b, 0xe4, 0x19, 0x94,
 | 
			
		||||
	0x44, 0xb8, 0x84, 0x10, 0x8e, 0x08, 0x4a, 0x2d, 0x2e, 0xc8, 0xcf, 0x2b, 0x4e, 0x55, 0xaa, 0xe2,
 | 
			
		||||
	0xe2, 0xf6, 0x2d, 0x4e, 0x0f, 0xcf, 0x2c, 0xc9, 0x48, 0x29, 0x4a, 0x2c, 0x17, 0xd2, 0xe1, 0x62,
 | 
			
		||||
	0x49, 0x2b, 0xca, 0xcf, 0x25, 0xe8, 0x2c, 0xb0, 0x2a, 0x4a, 0x5d, 0x24, 0xca, 0x25, 0x8c, 0x64,
 | 
			
		||||
	0x37, 0xcc, 0x49, 0x46, 0xab, 0x18, 0xb9, 0x98, 0x7d, 0x8b, 0xd3, 0x85, 0xfc, 0xb9, 0xd8, 0x61,
 | 
			
		||||
	0x41, 0x26, 0xab, 0x87, 0x11, 0x4d, 0x7a, 0x08, 0xcf, 0x48, 0xa9, 0xe2, 0x95, 0x86, 0x19, 0x2c,
 | 
			
		||||
	0x14, 0xc4, 0xc5, 0x01, 0xf7, 0xa8, 0x1c, 0x76, 0x2d, 0x30, 0x79, 0x29, 0x35, 0xfc, 0xf2, 0x30,
 | 
			
		||||
	0x33, 0x9d, 0x1c, 0x4e, 0x3c, 0x92, 0x63, 0xbc, 0xf0, 0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x39, 0xc6,
 | 
			
		||||
	0x09, 0x8f, 0xe5, 0x18, 0x2e, 0x3c, 0x96, 0x63, 0xb8, 0xf1, 0x58, 0x8e, 0x21, 0x4a, 0x2d, 0x3d,
 | 
			
		||||
	0xb3, 0x24, 0xa3, 0x34, 0x49, 0x2f, 0x39, 0x3f, 0x57, 0x1f, 0x64, 0x96, 0x6e, 0x4e, 0x62, 0x52,
 | 
			
		||||
	0x31, 0x98, 0xa5, 0x5f, 0x01, 0x49, 0x8c, 0x25, 0x95, 0x05, 0xa9, 0xc5, 0x49, 0x6c, 0xe0, 0x44,
 | 
			
		||||
	0x62, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0xc0, 0x48, 0xd0, 0x39, 0xa6, 0x02, 0x00, 0x00,
 | 
			
		||||
	0x2f, 0x92, 0x9e, 0x9f, 0x9e, 0x0f, 0xd1, 0x07, 0x62, 0x41, 0x45, 0x65, 0x31, 0xed, 0x2f, 0x4b,
 | 
			
		||||
	0x2c, 0xcd, 0x29, 0x81, 0x48, 0x2b, 0x35, 0x33, 0x72, 0x71, 0xf9, 0x16, 0xa7, 0xbb, 0xa4, 0x16,
 | 
			
		||||
	0xe4, 0x17, 0x67, 0x96, 0x08, 0x99, 0x71, 0x71, 0xa6, 0x40, 0x98, 0xf9, 0x45, 0x12, 0x8c, 0x0a,
 | 
			
		||||
	0x8c, 0x1a, 0x9c, 0x4e, 0x12, 0x97, 0xb6, 0xe8, 0x8a, 0x40, 0x1d, 0xe2, 0x98, 0x92, 0x52, 0x94,
 | 
			
		||||
	0x5a, 0x5c, 0x1c, 0x5c, 0x52, 0x94, 0x99, 0x97, 0x1e, 0x84, 0x50, 0x2a, 0x64, 0xce, 0xc5, 0x96,
 | 
			
		||||
	0x98, 0x9b, 0x5f, 0x9a, 0x57, 0x22, 0xc1, 0xa4, 0xc0, 0xa8, 0xc1, 0x6d, 0x24, 0xa9, 0x07, 0xd5,
 | 
			
		||||
	0x01, 0x72, 0x2c, 0xcc, 0x73, 0x7a, 0xce, 0xf9, 0x99, 0x79, 0x4e, 0x2c, 0x27, 0xee, 0xc9, 0x33,
 | 
			
		||||
	0x04, 0x41, 0x95, 0x5b, 0xb1, 0x74, 0x2c, 0x90, 0x67, 0x50, 0x0a, 0xe4, 0x12, 0x42, 0x38, 0x22,
 | 
			
		||||
	0x28, 0xb5, 0xb8, 0x20, 0x3f, 0xaf, 0x38, 0x55, 0xc8, 0x9a, 0x8b, 0xad, 0x38, 0x23, 0xb1, 0x28,
 | 
			
		||||
	0xb5, 0x18, 0xec, 0x12, 0x6e, 0x23, 0x59, 0x3d, 0x8c, 0xf0, 0xd2, 0x0b, 0x03, 0xf9, 0x25, 0x18,
 | 
			
		||||
	0xa4, 0x0a, 0x66, 0x30, 0x44, 0x8b, 0x52, 0x15, 0x17, 0xb7, 0x6f, 0x71, 0x7a, 0x78, 0x66, 0x49,
 | 
			
		||||
	0x46, 0x4a, 0x51, 0x62, 0xb9, 0x90, 0x0e, 0x17, 0x4b, 0x5a, 0x51, 0x7e, 0x2e, 0x41, 0x3f, 0x81,
 | 
			
		||||
	0x55, 0x51, 0xea, 0x9d, 0x20, 0x2e, 0x61, 0x24, 0xbb, 0xa9, 0xe2, 0x1f, 0xa3, 0x55, 0x8c, 0x5c,
 | 
			
		||||
	0xcc, 0xbe, 0xc5, 0xe9, 0x42, 0xfe, 0x5c, 0xec, 0xb0, 0xc8, 0xc2, 0xa6, 0x1f, 0x11, 0x8c, 0x52,
 | 
			
		||||
	0xaa, 0x78, 0xa5, 0xe1, 0xae, 0x0a, 0xe2, 0xe2, 0x80, 0x87, 0x92, 0x1c, 0x76, 0x2d, 0x30, 0x79,
 | 
			
		||||
	0x29, 0x35, 0xfc, 0xf2, 0x30, 0x33, 0x9d, 0x1c, 0x4e, 0x3c, 0x92, 0x63, 0xbc, 0xf0, 0x48, 0x8e,
 | 
			
		||||
	0xf1, 0xc1, 0x23, 0x39, 0xc6, 0x09, 0x8f, 0xe5, 0x18, 0x2e, 0x3c, 0x96, 0x63, 0xb8, 0xf1, 0x58,
 | 
			
		||||
	0x8e, 0x21, 0x4a, 0x2d, 0x3d, 0xb3, 0x24, 0xa3, 0x34, 0x49, 0x2f, 0x39, 0x3f, 0x57, 0x1f, 0x64,
 | 
			
		||||
	0x96, 0x6e, 0x4e, 0x62, 0x52, 0x31, 0x98, 0xa5, 0x5f, 0x01, 0x49, 0xa5, 0x25, 0x95, 0x05, 0xa9,
 | 
			
		||||
	0xc5, 0x49, 0x6c, 0xe0, 0xe4, 0x69, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0xb4, 0xb0, 0x19, 0x18,
 | 
			
		||||
	0x3f, 0x03, 0x00, 0x00,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Reference imports to suppress errors if they are not otherwise used.
 | 
			
		||||
@ -404,6 +423,16 @@ func (m *MsgDepositResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 | 
			
		||||
	_ = i
 | 
			
		||||
	var l int
 | 
			
		||||
	_ = l
 | 
			
		||||
	{
 | 
			
		||||
		size, err := m.Shares.MarshalToSizedBuffer(dAtA[:i])
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return 0, err
 | 
			
		||||
		}
 | 
			
		||||
		i -= size
 | 
			
		||||
		i = encodeVarintTx(dAtA, i, uint64(size))
 | 
			
		||||
	}
 | 
			
		||||
	i--
 | 
			
		||||
	dAtA[i] = 0xa
 | 
			
		||||
	return len(dAtA) - i, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -467,6 +496,16 @@ func (m *MsgWithdrawResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 | 
			
		||||
	_ = i
 | 
			
		||||
	var l int
 | 
			
		||||
	_ = l
 | 
			
		||||
	{
 | 
			
		||||
		size, err := m.Shares.MarshalToSizedBuffer(dAtA[:i])
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return 0, err
 | 
			
		||||
		}
 | 
			
		||||
		i -= size
 | 
			
		||||
		i = encodeVarintTx(dAtA, i, uint64(size))
 | 
			
		||||
	}
 | 
			
		||||
	i--
 | 
			
		||||
	dAtA[i] = 0xa
 | 
			
		||||
	return len(dAtA) - i, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -502,6 +541,8 @@ func (m *MsgDepositResponse) Size() (n int) {
 | 
			
		||||
	}
 | 
			
		||||
	var l int
 | 
			
		||||
	_ = l
 | 
			
		||||
	l = m.Shares.Size()
 | 
			
		||||
	n += 1 + l + sovTx(uint64(l))
 | 
			
		||||
	return n
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -526,6 +567,8 @@ func (m *MsgWithdrawResponse) Size() (n int) {
 | 
			
		||||
	}
 | 
			
		||||
	var l int
 | 
			
		||||
	_ = l
 | 
			
		||||
	l = m.Shares.Size()
 | 
			
		||||
	n += 1 + l + sovTx(uint64(l))
 | 
			
		||||
	return n
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -679,6 +722,39 @@ func (m *MsgDepositResponse) Unmarshal(dAtA []byte) error {
 | 
			
		||||
			return fmt.Errorf("proto: MsgDepositResponse: illegal tag %d (wire type %d)", fieldNum, wire)
 | 
			
		||||
		}
 | 
			
		||||
		switch fieldNum {
 | 
			
		||||
		case 1:
 | 
			
		||||
			if wireType != 2 {
 | 
			
		||||
				return fmt.Errorf("proto: wrong wireType = %d for field Shares", wireType)
 | 
			
		||||
			}
 | 
			
		||||
			var msglen int
 | 
			
		||||
			for shift := uint(0); ; shift += 7 {
 | 
			
		||||
				if shift >= 64 {
 | 
			
		||||
					return ErrIntOverflowTx
 | 
			
		||||
				}
 | 
			
		||||
				if iNdEx >= l {
 | 
			
		||||
					return io.ErrUnexpectedEOF
 | 
			
		||||
				}
 | 
			
		||||
				b := dAtA[iNdEx]
 | 
			
		||||
				iNdEx++
 | 
			
		||||
				msglen |= int(b&0x7F) << shift
 | 
			
		||||
				if b < 0x80 {
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if msglen < 0 {
 | 
			
		||||
				return ErrInvalidLengthTx
 | 
			
		||||
			}
 | 
			
		||||
			postIndex := iNdEx + msglen
 | 
			
		||||
			if postIndex < 0 {
 | 
			
		||||
				return ErrInvalidLengthTx
 | 
			
		||||
			}
 | 
			
		||||
			if postIndex > l {
 | 
			
		||||
				return io.ErrUnexpectedEOF
 | 
			
		||||
			}
 | 
			
		||||
			if err := m.Shares.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
			iNdEx = postIndex
 | 
			
		||||
		default:
 | 
			
		||||
			iNdEx = preIndex
 | 
			
		||||
			skippy, err := skipTx(dAtA[iNdEx:])
 | 
			
		||||
@ -844,6 +920,39 @@ func (m *MsgWithdrawResponse) Unmarshal(dAtA []byte) error {
 | 
			
		||||
			return fmt.Errorf("proto: MsgWithdrawResponse: illegal tag %d (wire type %d)", fieldNum, wire)
 | 
			
		||||
		}
 | 
			
		||||
		switch fieldNum {
 | 
			
		||||
		case 1:
 | 
			
		||||
			if wireType != 2 {
 | 
			
		||||
				return fmt.Errorf("proto: wrong wireType = %d for field Shares", wireType)
 | 
			
		||||
			}
 | 
			
		||||
			var msglen int
 | 
			
		||||
			for shift := uint(0); ; shift += 7 {
 | 
			
		||||
				if shift >= 64 {
 | 
			
		||||
					return ErrIntOverflowTx
 | 
			
		||||
				}
 | 
			
		||||
				if iNdEx >= l {
 | 
			
		||||
					return io.ErrUnexpectedEOF
 | 
			
		||||
				}
 | 
			
		||||
				b := dAtA[iNdEx]
 | 
			
		||||
				iNdEx++
 | 
			
		||||
				msglen |= int(b&0x7F) << shift
 | 
			
		||||
				if b < 0x80 {
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if msglen < 0 {
 | 
			
		||||
				return ErrInvalidLengthTx
 | 
			
		||||
			}
 | 
			
		||||
			postIndex := iNdEx + msglen
 | 
			
		||||
			if postIndex < 0 {
 | 
			
		||||
				return ErrInvalidLengthTx
 | 
			
		||||
			}
 | 
			
		||||
			if postIndex > l {
 | 
			
		||||
				return io.ErrUnexpectedEOF
 | 
			
		||||
			}
 | 
			
		||||
			if err := m.Shares.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
			iNdEx = postIndex
 | 
			
		||||
		default:
 | 
			
		||||
			iNdEx = preIndex
 | 
			
		||||
			skippy, err := skipTx(dAtA[iNdEx:])
 | 
			
		||||
 | 
			
		||||
@ -8,32 +8,15 @@ import (
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// NewVaultRecord returns a new VaultRecord with 0 supply.
 | 
			
		||||
func NewVaultRecord(vaultDenom string) VaultRecord {
 | 
			
		||||
func NewVaultRecord(vaultDenom string, amount sdk.Dec) VaultRecord {
 | 
			
		||||
	return VaultRecord{
 | 
			
		||||
		Denom:       vaultDenom,
 | 
			
		||||
		TotalSupply: sdk.NewCoin(vaultDenom, sdk.ZeroInt()),
 | 
			
		||||
		TotalShares: NewVaultShare(vaultDenom, amount),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Validate returns an error if a VaultRecord is invalid.
 | 
			
		||||
func (vr *VaultRecord) Validate() error {
 | 
			
		||||
	if err := sdk.ValidateDenom(vr.Denom); err != nil {
 | 
			
		||||
		return sdkerrors.Wrap(ErrInvalidVaultDenom, err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if vr.TotalSupply.Denom != vr.Denom {
 | 
			
		||||
		return fmt.Errorf(
 | 
			
		||||
			"total supply denom %v does not match vault record denom %v",
 | 
			
		||||
			vr.TotalSupply.Denom,
 | 
			
		||||
			vr.Denom,
 | 
			
		||||
		)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := vr.TotalSupply.Validate(); err != nil {
 | 
			
		||||
		return fmt.Errorf("vault total supply is invalid: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
	return vr.TotalShares.Validate()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// VaultRecords is a slice of VaultRecord.
 | 
			
		||||
@ -48,11 +31,11 @@ func (vrs VaultRecords) Validate() error {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if denoms[vr.Denom] {
 | 
			
		||||
			return fmt.Errorf("duplicate vault denom %s", vr.Denom)
 | 
			
		||||
		if denoms[vr.TotalShares.Denom] {
 | 
			
		||||
			return fmt.Errorf("duplicate vault denom %s", vr.TotalShares.Denom)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		denoms[vr.Denom] = true
 | 
			
		||||
		denoms[vr.TotalShares.Denom] = true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
@ -60,10 +43,10 @@ func (vrs VaultRecords) Validate() error {
 | 
			
		||||
 | 
			
		||||
// NewVaultShareRecord returns a new VaultShareRecord with the provided supplied
 | 
			
		||||
// coins.
 | 
			
		||||
func NewVaultShareRecord(depositor sdk.AccAddress, supplied ...sdk.Coin) VaultShareRecord {
 | 
			
		||||
func NewVaultShareRecord(depositor sdk.AccAddress, shares VaultShares) VaultShareRecord {
 | 
			
		||||
	return VaultShareRecord{
 | 
			
		||||
		Depositor: depositor,
 | 
			
		||||
		AmountSupplied: sdk.NewCoins(supplied...),
 | 
			
		||||
		Shares:    shares,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -73,8 +56,8 @@ func (vsr VaultShareRecord) Validate() error {
 | 
			
		||||
		return fmt.Errorf("depositor is empty")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := vsr.AmountSupplied.Validate(); err != nil {
 | 
			
		||||
		return fmt.Errorf("invalid vault share record amount supplied: %w", err)
 | 
			
		||||
	if err := vsr.Shares.Validate(); err != nil {
 | 
			
		||||
		return fmt.Errorf("invalid vault share record shares: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
 | 
			
		||||
@ -6,8 +6,8 @@ package types
 | 
			
		||||
import (
 | 
			
		||||
	fmt "fmt"
 | 
			
		||||
	_ "github.com/cosmos/cosmos-proto"
 | 
			
		||||
	_ "github.com/cosmos/cosmos-sdk/types"
 | 
			
		||||
	github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types"
 | 
			
		||||
	types "github.com/cosmos/cosmos-sdk/types"
 | 
			
		||||
	_ "github.com/gogo/protobuf/gogoproto"
 | 
			
		||||
	proto "github.com/gogo/protobuf/proto"
 | 
			
		||||
	io "io"
 | 
			
		||||
@ -82,15 +82,10 @@ func (m *AllowedVault) GetVaultStrategy() StrategyType {
 | 
			
		||||
	return STRATEGY_TYPE_UNSPECIFIED
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// VaultRecord is the state of a vault and is used to store the state of a
 | 
			
		||||
// vault.
 | 
			
		||||
// VaultRecord is the state of a vault.
 | 
			
		||||
type VaultRecord struct {
 | 
			
		||||
	// Denom is the only supported denomination of the vault for deposits and
 | 
			
		||||
	// withdrawals.
 | 
			
		||||
	Denom string `protobuf:"bytes,1,opt,name=denom,proto3" json:"denom,omitempty"`
 | 
			
		||||
	// TotalSupply is the total supply of the vault, denominated **only** in the
 | 
			
		||||
	// user deposit/withdrawal denom, must be the same as the Denom field.
 | 
			
		||||
	TotalSupply types.Coin `protobuf:"bytes,2,opt,name=total_supply,json=totalSupply,proto3" json:"total_supply"`
 | 
			
		||||
	// TotalShares is the total distributed number of shares in the vault.
 | 
			
		||||
	TotalShares VaultShare `protobuf:"bytes,1,opt,name=total_shares,json=totalShares,proto3" json:"total_shares"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *VaultRecord) Reset()         { *m = VaultRecord{} }
 | 
			
		||||
@ -126,27 +121,19 @@ func (m *VaultRecord) XXX_DiscardUnknown() {
 | 
			
		||||
 | 
			
		||||
var xxx_messageInfo_VaultRecord proto.InternalMessageInfo
 | 
			
		||||
 | 
			
		||||
func (m *VaultRecord) GetDenom() string {
 | 
			
		||||
func (m *VaultRecord) GetTotalShares() VaultShare {
 | 
			
		||||
	if m != nil {
 | 
			
		||||
		return m.Denom
 | 
			
		||||
		return m.TotalShares
 | 
			
		||||
	}
 | 
			
		||||
	return ""
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *VaultRecord) GetTotalSupply() types.Coin {
 | 
			
		||||
	if m != nil {
 | 
			
		||||
		return m.TotalSupply
 | 
			
		||||
	}
 | 
			
		||||
	return types.Coin{}
 | 
			
		||||
	return VaultShare{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// VaultShareRecord defines the vault shares owned by a depositor.
 | 
			
		||||
type VaultShareRecord struct {
 | 
			
		||||
	// Depositor represents the owner of the shares
 | 
			
		||||
	Depositor github_com_cosmos_cosmos_sdk_types.AccAddress `protobuf:"bytes,1,opt,name=depositor,proto3,casttype=github.com/cosmos/cosmos-sdk/types.AccAddress" json:"depositor,omitempty"`
 | 
			
		||||
	// AmountSupplied represents the total amount a depositor has supplied to the
 | 
			
		||||
	// vault. The vault is determined by the coin denom.
 | 
			
		||||
	AmountSupplied github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,2,rep,name=amount_supplied,json=amountSupplied,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"amount_supplied"`
 | 
			
		||||
	// Shares represent the vault shares owned by the depositor.
 | 
			
		||||
	Shares VaultShares `protobuf:"bytes,2,rep,name=shares,proto3,castrepeated=VaultShares" json:"shares"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *VaultShareRecord) Reset()         { *m = VaultShareRecord{} }
 | 
			
		||||
@ -189,50 +176,97 @@ func (m *VaultShareRecord) GetDepositor() github_com_cosmos_cosmos_sdk_types.Acc
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *VaultShareRecord) GetAmountSupplied() github_com_cosmos_cosmos_sdk_types.Coins {
 | 
			
		||||
func (m *VaultShareRecord) GetShares() VaultShares {
 | 
			
		||||
	if m != nil {
 | 
			
		||||
		return m.AmountSupplied
 | 
			
		||||
		return m.Shares
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// VaultShare defines shares of a vault owned by a depositor.
 | 
			
		||||
type VaultShare struct {
 | 
			
		||||
	Denom  string                                 `protobuf:"bytes,1,opt,name=denom,proto3" json:"denom,omitempty"`
 | 
			
		||||
	Amount github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=amount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"amount"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *VaultShare) Reset()      { *m = VaultShare{} }
 | 
			
		||||
func (*VaultShare) ProtoMessage() {}
 | 
			
		||||
func (*VaultShare) Descriptor() ([]byte, []int) {
 | 
			
		||||
	return fileDescriptor_884eb89509fbdc04, []int{3}
 | 
			
		||||
}
 | 
			
		||||
func (m *VaultShare) XXX_Unmarshal(b []byte) error {
 | 
			
		||||
	return m.Unmarshal(b)
 | 
			
		||||
}
 | 
			
		||||
func (m *VaultShare) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 | 
			
		||||
	if deterministic {
 | 
			
		||||
		return xxx_messageInfo_VaultShare.Marshal(b, m, deterministic)
 | 
			
		||||
	} else {
 | 
			
		||||
		b = b[:cap(b)]
 | 
			
		||||
		n, err := m.MarshalToSizedBuffer(b)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		return b[:n], nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
func (m *VaultShare) XXX_Merge(src proto.Message) {
 | 
			
		||||
	xxx_messageInfo_VaultShare.Merge(m, src)
 | 
			
		||||
}
 | 
			
		||||
func (m *VaultShare) XXX_Size() int {
 | 
			
		||||
	return m.Size()
 | 
			
		||||
}
 | 
			
		||||
func (m *VaultShare) XXX_DiscardUnknown() {
 | 
			
		||||
	xxx_messageInfo_VaultShare.DiscardUnknown(m)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var xxx_messageInfo_VaultShare proto.InternalMessageInfo
 | 
			
		||||
 | 
			
		||||
func (m *VaultShare) GetDenom() string {
 | 
			
		||||
	if m != nil {
 | 
			
		||||
		return m.Denom
 | 
			
		||||
	}
 | 
			
		||||
	return ""
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	proto.RegisterType((*AllowedVault)(nil), "kava.earn.v1beta1.AllowedVault")
 | 
			
		||||
	proto.RegisterType((*VaultRecord)(nil), "kava.earn.v1beta1.VaultRecord")
 | 
			
		||||
	proto.RegisterType((*VaultShareRecord)(nil), "kava.earn.v1beta1.VaultShareRecord")
 | 
			
		||||
	proto.RegisterType((*VaultShare)(nil), "kava.earn.v1beta1.VaultShare")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func init() { proto.RegisterFile("kava/earn/v1beta1/vault.proto", fileDescriptor_884eb89509fbdc04) }
 | 
			
		||||
 | 
			
		||||
var fileDescriptor_884eb89509fbdc04 = []byte{
 | 
			
		||||
	// 417 bytes of a gzipped FileDescriptorProto
 | 
			
		||||
	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0xbd, 0x8e, 0xd3, 0x40,
 | 
			
		||||
	0x10, 0xc7, 0xed, 0xe3, 0x43, 0xba, 0x4d, 0x08, 0x60, 0xae, 0xc8, 0x9d, 0x84, 0x6d, 0xa5, 0x40,
 | 
			
		||||
	0x69, 0xbc, 0xe6, 0x8e, 0x17, 0x20, 0x46, 0x42, 0xd4, 0x36, 0xa2, 0xa0, 0x89, 0xd6, 0xde, 0xc5,
 | 
			
		||||
	0xb1, 0x62, 0x7b, 0x2c, 0xef, 0x3a, 0xe0, 0xb7, 0xe0, 0x39, 0xa8, 0x79, 0x88, 0x94, 0x11, 0x15,
 | 
			
		||||
	0x55, 0x40, 0xc9, 0x0b, 0x50, 0x53, 0xa1, 0xfd, 0x48, 0x40, 0x8a, 0x40, 0x54, 0xde, 0x9d, 0x99,
 | 
			
		||||
	0xff, 0xfc, 0xfe, 0x33, 0x5e, 0xf4, 0x78, 0x49, 0x56, 0x24, 0x64, 0xa4, 0xad, 0xc3, 0xd5, 0x75,
 | 
			
		||||
	0xca, 0x04, 0xb9, 0x0e, 0x57, 0xa4, 0x2b, 0x05, 0x6e, 0x5a, 0x10, 0xe0, 0x3c, 0x94, 0x69, 0x2c,
 | 
			
		||||
	0xd3, 0xd8, 0xa4, 0xaf, 0x2e, 0x33, 0xe0, 0x15, 0xf0, 0xb9, 0x2a, 0x08, 0xf5, 0x45, 0x57, 0x5f,
 | 
			
		||||
	0xb9, 0xfa, 0x16, 0xa6, 0x84, 0xb3, 0x63, 0xbb, 0x0c, 0x8a, 0xda, 0xe4, 0x2f, 0x72, 0xc8, 0x41,
 | 
			
		||||
	0xeb, 0xe4, 0xc9, 0x44, 0xfd, 0x53, 0x0b, 0x5c, 0xb4, 0x44, 0xb0, 0xbc, 0xd7, 0x15, 0x93, 0x12,
 | 
			
		||||
	0x0d, 0x67, 0x65, 0x09, 0xef, 0x19, 0x7d, 0x23, 0xbd, 0x39, 0x17, 0xe8, 0x0e, 0x65, 0x35, 0x54,
 | 
			
		||||
	0x63, 0xdb, 0xb7, 0xa7, 0xe7, 0xb1, 0xbe, 0x38, 0x2f, 0xd1, 0x48, 0x59, 0x9f, 0x1f, 0xd4, 0xe3,
 | 
			
		||||
	0x33, 0xdf, 0x9e, 0x8e, 0x6e, 0x3c, 0x7c, 0x32, 0x04, 0x4e, 0x4c, 0xc9, 0xeb, 0xbe, 0x61, 0xf1,
 | 
			
		||||
	0x3d, 0x25, 0x3b, 0x84, 0x26, 0x39, 0x1a, 0x28, 0x4c, 0xcc, 0x32, 0x68, 0xe9, 0x5f, 0x60, 0x11,
 | 
			
		||||
	0x1a, 0x0a, 0x10, 0xa4, 0x9c, 0xf3, 0xae, 0x69, 0x4a, 0x8d, 0x1a, 0xdc, 0x5c, 0x62, 0xb3, 0x0f,
 | 
			
		||||
	0xb9, 0x81, 0x23, 0xec, 0x05, 0x14, 0x75, 0x74, 0x7b, 0xbd, 0xf5, 0xac, 0x78, 0xa0, 0x44, 0x89,
 | 
			
		||||
	0xd2, 0x4c, 0x7e, 0xd8, 0xe8, 0x81, 0x22, 0x25, 0x0b, 0xd2, 0x32, 0x83, 0x7b, 0x87, 0xce, 0x29,
 | 
			
		||||
	0x6b, 0x80, 0x17, 0x02, 0x5a, 0x85, 0x1c, 0x46, 0xaf, 0x7e, 0x6e, 0xbd, 0x20, 0x2f, 0xc4, 0xa2,
 | 
			
		||||
	0x4b, 0x71, 0x06, 0x95, 0xd9, 0xb9, 0xf9, 0x04, 0x9c, 0x2e, 0x43, 0xd1, 0x37, 0x8c, 0xe3, 0x59,
 | 
			
		||||
	0x96, 0xcd, 0x28, 0x6d, 0x19, 0xe7, 0x5f, 0x3e, 0x07, 0x8f, 0x8c, 0x13, 0x13, 0x89, 0x7a, 0xc1,
 | 
			
		||||
	0x78, 0xfc, 0xbb, 0xb5, 0x23, 0xd0, 0x7d, 0x52, 0x41, 0x57, 0x0b, 0x3d, 0x41, 0xc1, 0xe8, 0xf8,
 | 
			
		||||
	0xcc, 0xbf, 0xf5, 0xef, 0x19, 0x9e, 0xca, 0x19, 0x3e, 0x7d, 0xf3, 0xa6, 0xff, 0x61, 0x46, 0x0a,
 | 
			
		||||
	0x78, 0x3c, 0xd2, 0x8c, 0xc4, 0x20, 0xa2, 0xe7, 0xeb, 0x9d, 0x6b, 0x6f, 0x76, 0xae, 0xfd, 0x7d,
 | 
			
		||||
	0xe7, 0xda, 0x1f, 0xf7, 0xae, 0xb5, 0xd9, 0xbb, 0xd6, 0xd7, 0xbd, 0x6b, 0xbd, 0x7d, 0xf2, 0x47,
 | 
			
		||||
	0x4f, 0xf9, 0xbf, 0x82, 0x92, 0xa4, 0x5c, 0x9d, 0xc2, 0x0f, 0xfa, 0x71, 0xa8, 0xbe, 0xe9, 0x5d,
 | 
			
		||||
	0xf5, 0x24, 0x9e, 0xfd, 0x0a, 0x00, 0x00, 0xff, 0xff, 0x6e, 0x80, 0xa4, 0xff, 0xb9, 0x02, 0x00,
 | 
			
		||||
	0x00,
 | 
			
		||||
	// 445 bytes of a gzipped FileDescriptorProto
 | 
			
		||||
	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x52, 0x31, 0x8f, 0xd3, 0x30,
 | 
			
		||||
	0x18, 0x4d, 0x8e, 0xa3, 0x52, 0x9d, 0x72, 0x82, 0xdc, 0x0d, 0xc7, 0x49, 0x4d, 0xa2, 0x0c, 0xa8,
 | 
			
		||||
	0x4b, 0x12, 0xb5, 0x6c, 0x88, 0x81, 0x46, 0x55, 0x85, 0x18, 0xd3, 0xc2, 0xc0, 0x52, 0x39, 0x8e,
 | 
			
		||||
	0x49, 0xab, 0x26, 0x71, 0x14, 0xbb, 0x85, 0x2c, 0xfc, 0x06, 0x46, 0x46, 0x66, 0xe6, 0xfe, 0x06,
 | 
			
		||||
	0xd4, 0xb1, 0xea, 0x84, 0x18, 0x0a, 0x6a, 0xff, 0x05, 0x13, 0xb2, 0xe3, 0x12, 0xa4, 0x82, 0xb8,
 | 
			
		||||
	0x29, 0xf6, 0xfb, 0xde, 0x7b, 0xdf, 0xfb, 0xf2, 0x19, 0xb4, 0xe7, 0x70, 0x09, 0x3d, 0x0c, 0x8b,
 | 
			
		||||
	0xcc, 0x5b, 0x76, 0x43, 0xcc, 0x60, 0xd7, 0x5b, 0xc2, 0x45, 0xc2, 0xdc, 0xbc, 0x20, 0x8c, 0xe8,
 | 
			
		||||
	0x0f, 0x78, 0xd9, 0xe5, 0x65, 0x57, 0x96, 0x6f, 0x1e, 0x22, 0x42, 0x53, 0x42, 0x27, 0x82, 0xe0,
 | 
			
		||||
	0x55, 0x97, 0x8a, 0x7d, 0x63, 0x54, 0x37, 0x2f, 0x84, 0x14, 0xff, 0xb6, 0x43, 0x64, 0x96, 0xc9,
 | 
			
		||||
	0xfa, 0x55, 0x4c, 0x62, 0x52, 0xe9, 0xf8, 0x49, 0xa2, 0xd6, 0x69, 0x04, 0xca, 0x0a, 0xc8, 0x70,
 | 
			
		||||
	0x5c, 0x56, 0x0c, 0x3b, 0x01, 0xad, 0x7e, 0x92, 0x90, 0xb7, 0x38, 0x7a, 0xc5, 0xb3, 0xe9, 0x57,
 | 
			
		||||
	0xe0, 0x6e, 0x84, 0x33, 0x92, 0x5e, 0xab, 0x96, 0xda, 0x69, 0x06, 0xd5, 0x45, 0x1f, 0x82, 0x0b,
 | 
			
		||||
	0x11, 0x7d, 0x72, 0x54, 0x5f, 0x9f, 0x59, 0x6a, 0xe7, 0xa2, 0x67, 0xba, 0x27, 0x43, 0xb8, 0x23,
 | 
			
		||||
	0x49, 0x19, 0x97, 0x39, 0x0e, 0xee, 0x09, 0xd9, 0x11, 0xb2, 0x5f, 0x02, 0x4d, 0xb4, 0x09, 0x30,
 | 
			
		||||
	0x22, 0x45, 0xa4, 0x0f, 0x41, 0x8b, 0x11, 0x06, 0x93, 0x09, 0x9d, 0xc2, 0x02, 0x53, 0xd1, 0x53,
 | 
			
		||||
	0xeb, 0xb5, 0xff, 0x62, 0x2a, 0x54, 0x23, 0xce, 0xf2, 0xcf, 0xd7, 0x3b, 0x53, 0x09, 0x34, 0x21,
 | 
			
		||||
	0x14, 0x08, 0xb5, 0xbf, 0xa8, 0xe0, 0x7e, 0xcd, 0x90, 0xe6, 0x6f, 0x40, 0x33, 0xc2, 0x39, 0xa1,
 | 
			
		||||
	0x33, 0x46, 0x0a, 0xe1, 0xdc, 0xf2, 0x9f, 0xff, 0xdc, 0x99, 0x4e, 0x3c, 0x63, 0xd3, 0x45, 0xe8,
 | 
			
		||||
	0x22, 0x92, 0xca, 0x3f, 0x2c, 0x3f, 0x0e, 0x8d, 0xe6, 0x1e, 0x2b, 0x73, 0x4c, 0xdd, 0x3e, 0x42,
 | 
			
		||||
	0xfd, 0x28, 0x2a, 0x30, 0xa5, 0xdb, 0x95, 0x73, 0x29, 0xf7, 0x20, 0x11, 0xbf, 0x64, 0x98, 0x06,
 | 
			
		||||
	0xb5, 0xb5, 0xfe, 0x02, 0x34, 0x64, 0xfc, 0x33, 0xeb, 0xce, 0xff, 0xe3, 0x5f, 0xf2, 0xf8, 0x9f,
 | 
			
		||||
	0xbf, 0x9b, 0x5a, 0x8d, 0xd1, 0x40, 0x3a, 0xd8, 0xef, 0x01, 0xa8, 0xe1, 0x7f, 0xec, 0x62, 0x0c,
 | 
			
		||||
	0x1a, 0x30, 0x25, 0x8b, 0x8c, 0x89, 0x1d, 0x34, 0xfd, 0xa7, 0xdc, 0xf0, 0xdb, 0xce, 0x7c, 0x74,
 | 
			
		||||
	0x8b, 0xc1, 0x06, 0x18, 0x6d, 0x57, 0x0e, 0x90, 0x13, 0x0d, 0x30, 0x0a, 0xa4, 0xd7, 0x93, 0xf3,
 | 
			
		||||
	0x8f, 0x9f, 0x4c, 0xc5, 0x7f, 0xb6, 0xde, 0x1b, 0xea, 0x66, 0x6f, 0xa8, 0x3f, 0xf6, 0x86, 0xfa,
 | 
			
		||||
	0xe1, 0x60, 0x28, 0x9b, 0x83, 0xa1, 0x7c, 0x3d, 0x18, 0xca, 0xeb, 0x3f, 0xdd, 0xf9, 0x7c, 0x4e,
 | 
			
		||||
	0x02, 0x43, 0x2a, 0x4e, 0xde, 0xbb, 0xea, 0x81, 0x89, 0x0e, 0x61, 0x43, 0x3c, 0xab, 0xc7, 0xbf,
 | 
			
		||||
	0x02, 0x00, 0x00, 0xff, 0xff, 0x19, 0x75, 0x6f, 0x0e, 0xfd, 0x02, 0x00, 0x00,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *AllowedVault) Marshal() (dAtA []byte, err error) {
 | 
			
		||||
@ -291,7 +325,7 @@ func (m *VaultRecord) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 | 
			
		||||
	var l int
 | 
			
		||||
	_ = l
 | 
			
		||||
	{
 | 
			
		||||
		size, err := m.TotalSupply.MarshalToSizedBuffer(dAtA[:i])
 | 
			
		||||
		size, err := m.TotalShares.MarshalToSizedBuffer(dAtA[:i])
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return 0, err
 | 
			
		||||
		}
 | 
			
		||||
@ -299,14 +333,7 @@ func (m *VaultRecord) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 | 
			
		||||
		i = encodeVarintVault(dAtA, i, uint64(size))
 | 
			
		||||
	}
 | 
			
		||||
	i--
 | 
			
		||||
	dAtA[i] = 0x12
 | 
			
		||||
	if len(m.Denom) > 0 {
 | 
			
		||||
		i -= len(m.Denom)
 | 
			
		||||
		copy(dAtA[i:], m.Denom)
 | 
			
		||||
		i = encodeVarintVault(dAtA, i, uint64(len(m.Denom)))
 | 
			
		||||
		i--
 | 
			
		||||
	dAtA[i] = 0xa
 | 
			
		||||
	}
 | 
			
		||||
	return len(dAtA) - i, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -330,10 +357,10 @@ func (m *VaultShareRecord) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 | 
			
		||||
	_ = i
 | 
			
		||||
	var l int
 | 
			
		||||
	_ = l
 | 
			
		||||
	if len(m.AmountSupplied) > 0 {
 | 
			
		||||
		for iNdEx := len(m.AmountSupplied) - 1; iNdEx >= 0; iNdEx-- {
 | 
			
		||||
	if len(m.Shares) > 0 {
 | 
			
		||||
		for iNdEx := len(m.Shares) - 1; iNdEx >= 0; iNdEx-- {
 | 
			
		||||
			{
 | 
			
		||||
				size, err := m.AmountSupplied[iNdEx].MarshalToSizedBuffer(dAtA[:i])
 | 
			
		||||
				size, err := m.Shares[iNdEx].MarshalToSizedBuffer(dAtA[:i])
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return 0, err
 | 
			
		||||
				}
 | 
			
		||||
@ -354,6 +381,46 @@ func (m *VaultShareRecord) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 | 
			
		||||
	return len(dAtA) - i, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *VaultShare) Marshal() (dAtA []byte, err error) {
 | 
			
		||||
	size := m.Size()
 | 
			
		||||
	dAtA = make([]byte, size)
 | 
			
		||||
	n, err := m.MarshalToSizedBuffer(dAtA[:size])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return dAtA[:n], nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *VaultShare) MarshalTo(dAtA []byte) (int, error) {
 | 
			
		||||
	size := m.Size()
 | 
			
		||||
	return m.MarshalToSizedBuffer(dAtA[:size])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *VaultShare) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 | 
			
		||||
	i := len(dAtA)
 | 
			
		||||
	_ = i
 | 
			
		||||
	var l int
 | 
			
		||||
	_ = l
 | 
			
		||||
	{
 | 
			
		||||
		size := m.Amount.Size()
 | 
			
		||||
		i -= size
 | 
			
		||||
		if _, err := m.Amount.MarshalTo(dAtA[i:]); err != nil {
 | 
			
		||||
			return 0, err
 | 
			
		||||
		}
 | 
			
		||||
		i = encodeVarintVault(dAtA, i, uint64(size))
 | 
			
		||||
	}
 | 
			
		||||
	i--
 | 
			
		||||
	dAtA[i] = 0x12
 | 
			
		||||
	if len(m.Denom) > 0 {
 | 
			
		||||
		i -= len(m.Denom)
 | 
			
		||||
		copy(dAtA[i:], m.Denom)
 | 
			
		||||
		i = encodeVarintVault(dAtA, i, uint64(len(m.Denom)))
 | 
			
		||||
		i--
 | 
			
		||||
		dAtA[i] = 0xa
 | 
			
		||||
	}
 | 
			
		||||
	return len(dAtA) - i, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func encodeVarintVault(dAtA []byte, offset int, v uint64) int {
 | 
			
		||||
	offset -= sovVault(v)
 | 
			
		||||
	base := offset
 | 
			
		||||
@ -387,11 +454,7 @@ func (m *VaultRecord) Size() (n int) {
 | 
			
		||||
	}
 | 
			
		||||
	var l int
 | 
			
		||||
	_ = l
 | 
			
		||||
	l = len(m.Denom)
 | 
			
		||||
	if l > 0 {
 | 
			
		||||
		n += 1 + l + sovVault(uint64(l))
 | 
			
		||||
	}
 | 
			
		||||
	l = m.TotalSupply.Size()
 | 
			
		||||
	l = m.TotalShares.Size()
 | 
			
		||||
	n += 1 + l + sovVault(uint64(l))
 | 
			
		||||
	return n
 | 
			
		||||
}
 | 
			
		||||
@ -406,8 +469,8 @@ func (m *VaultShareRecord) Size() (n int) {
 | 
			
		||||
	if l > 0 {
 | 
			
		||||
		n += 1 + l + sovVault(uint64(l))
 | 
			
		||||
	}
 | 
			
		||||
	if len(m.AmountSupplied) > 0 {
 | 
			
		||||
		for _, e := range m.AmountSupplied {
 | 
			
		||||
	if len(m.Shares) > 0 {
 | 
			
		||||
		for _, e := range m.Shares {
 | 
			
		||||
			l = e.Size()
 | 
			
		||||
			n += 1 + l + sovVault(uint64(l))
 | 
			
		||||
		}
 | 
			
		||||
@ -415,6 +478,21 @@ func (m *VaultShareRecord) Size() (n int) {
 | 
			
		||||
	return n
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *VaultShare) Size() (n int) {
 | 
			
		||||
	if m == nil {
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
	var l int
 | 
			
		||||
	_ = l
 | 
			
		||||
	l = len(m.Denom)
 | 
			
		||||
	if l > 0 {
 | 
			
		||||
		n += 1 + l + sovVault(uint64(l))
 | 
			
		||||
	}
 | 
			
		||||
	l = m.Amount.Size()
 | 
			
		||||
	n += 1 + l + sovVault(uint64(l))
 | 
			
		||||
	return n
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func sovVault(x uint64) (n int) {
 | 
			
		||||
	return (math_bits.Len64(x|1) + 6) / 7
 | 
			
		||||
}
 | 
			
		||||
@ -553,39 +631,7 @@ func (m *VaultRecord) Unmarshal(dAtA []byte) error {
 | 
			
		||||
		switch fieldNum {
 | 
			
		||||
		case 1:
 | 
			
		||||
			if wireType != 2 {
 | 
			
		||||
				return fmt.Errorf("proto: wrong wireType = %d for field Denom", wireType)
 | 
			
		||||
			}
 | 
			
		||||
			var stringLen uint64
 | 
			
		||||
			for shift := uint(0); ; shift += 7 {
 | 
			
		||||
				if shift >= 64 {
 | 
			
		||||
					return ErrIntOverflowVault
 | 
			
		||||
				}
 | 
			
		||||
				if iNdEx >= l {
 | 
			
		||||
					return io.ErrUnexpectedEOF
 | 
			
		||||
				}
 | 
			
		||||
				b := dAtA[iNdEx]
 | 
			
		||||
				iNdEx++
 | 
			
		||||
				stringLen |= uint64(b&0x7F) << shift
 | 
			
		||||
				if b < 0x80 {
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			intStringLen := int(stringLen)
 | 
			
		||||
			if intStringLen < 0 {
 | 
			
		||||
				return ErrInvalidLengthVault
 | 
			
		||||
			}
 | 
			
		||||
			postIndex := iNdEx + intStringLen
 | 
			
		||||
			if postIndex < 0 {
 | 
			
		||||
				return ErrInvalidLengthVault
 | 
			
		||||
			}
 | 
			
		||||
			if postIndex > l {
 | 
			
		||||
				return io.ErrUnexpectedEOF
 | 
			
		||||
			}
 | 
			
		||||
			m.Denom = string(dAtA[iNdEx:postIndex])
 | 
			
		||||
			iNdEx = postIndex
 | 
			
		||||
		case 2:
 | 
			
		||||
			if wireType != 2 {
 | 
			
		||||
				return fmt.Errorf("proto: wrong wireType = %d for field TotalSupply", wireType)
 | 
			
		||||
				return fmt.Errorf("proto: wrong wireType = %d for field TotalShares", wireType)
 | 
			
		||||
			}
 | 
			
		||||
			var msglen int
 | 
			
		||||
			for shift := uint(0); ; shift += 7 {
 | 
			
		||||
@ -612,7 +658,7 @@ func (m *VaultRecord) Unmarshal(dAtA []byte) error {
 | 
			
		||||
			if postIndex > l {
 | 
			
		||||
				return io.ErrUnexpectedEOF
 | 
			
		||||
			}
 | 
			
		||||
			if err := m.TotalSupply.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
 | 
			
		||||
			if err := m.TotalShares.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
			iNdEx = postIndex
 | 
			
		||||
@ -702,7 +748,7 @@ func (m *VaultShareRecord) Unmarshal(dAtA []byte) error {
 | 
			
		||||
			iNdEx = postIndex
 | 
			
		||||
		case 2:
 | 
			
		||||
			if wireType != 2 {
 | 
			
		||||
				return fmt.Errorf("proto: wrong wireType = %d for field AmountSupplied", wireType)
 | 
			
		||||
				return fmt.Errorf("proto: wrong wireType = %d for field Shares", wireType)
 | 
			
		||||
			}
 | 
			
		||||
			var msglen int
 | 
			
		||||
			for shift := uint(0); ; shift += 7 {
 | 
			
		||||
@ -729,8 +775,124 @@ func (m *VaultShareRecord) Unmarshal(dAtA []byte) error {
 | 
			
		||||
			if postIndex > l {
 | 
			
		||||
				return io.ErrUnexpectedEOF
 | 
			
		||||
			}
 | 
			
		||||
			m.AmountSupplied = append(m.AmountSupplied, types.Coin{})
 | 
			
		||||
			if err := m.AmountSupplied[len(m.AmountSupplied)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
 | 
			
		||||
			m.Shares = append(m.Shares, VaultShare{})
 | 
			
		||||
			if err := m.Shares[len(m.Shares)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
			iNdEx = postIndex
 | 
			
		||||
		default:
 | 
			
		||||
			iNdEx = preIndex
 | 
			
		||||
			skippy, err := skipVault(dAtA[iNdEx:])
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
			if (skippy < 0) || (iNdEx+skippy) < 0 {
 | 
			
		||||
				return ErrInvalidLengthVault
 | 
			
		||||
			}
 | 
			
		||||
			if (iNdEx + skippy) > l {
 | 
			
		||||
				return io.ErrUnexpectedEOF
 | 
			
		||||
			}
 | 
			
		||||
			iNdEx += skippy
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if iNdEx > l {
 | 
			
		||||
		return io.ErrUnexpectedEOF
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
func (m *VaultShare) Unmarshal(dAtA []byte) error {
 | 
			
		||||
	l := len(dAtA)
 | 
			
		||||
	iNdEx := 0
 | 
			
		||||
	for iNdEx < l {
 | 
			
		||||
		preIndex := iNdEx
 | 
			
		||||
		var wire uint64
 | 
			
		||||
		for shift := uint(0); ; shift += 7 {
 | 
			
		||||
			if shift >= 64 {
 | 
			
		||||
				return ErrIntOverflowVault
 | 
			
		||||
			}
 | 
			
		||||
			if iNdEx >= l {
 | 
			
		||||
				return io.ErrUnexpectedEOF
 | 
			
		||||
			}
 | 
			
		||||
			b := dAtA[iNdEx]
 | 
			
		||||
			iNdEx++
 | 
			
		||||
			wire |= uint64(b&0x7F) << shift
 | 
			
		||||
			if b < 0x80 {
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		fieldNum := int32(wire >> 3)
 | 
			
		||||
		wireType := int(wire & 0x7)
 | 
			
		||||
		if wireType == 4 {
 | 
			
		||||
			return fmt.Errorf("proto: VaultShare: wiretype end group for non-group")
 | 
			
		||||
		}
 | 
			
		||||
		if fieldNum <= 0 {
 | 
			
		||||
			return fmt.Errorf("proto: VaultShare: illegal tag %d (wire type %d)", fieldNum, wire)
 | 
			
		||||
		}
 | 
			
		||||
		switch fieldNum {
 | 
			
		||||
		case 1:
 | 
			
		||||
			if wireType != 2 {
 | 
			
		||||
				return fmt.Errorf("proto: wrong wireType = %d for field Denom", wireType)
 | 
			
		||||
			}
 | 
			
		||||
			var stringLen uint64
 | 
			
		||||
			for shift := uint(0); ; shift += 7 {
 | 
			
		||||
				if shift >= 64 {
 | 
			
		||||
					return ErrIntOverflowVault
 | 
			
		||||
				}
 | 
			
		||||
				if iNdEx >= l {
 | 
			
		||||
					return io.ErrUnexpectedEOF
 | 
			
		||||
				}
 | 
			
		||||
				b := dAtA[iNdEx]
 | 
			
		||||
				iNdEx++
 | 
			
		||||
				stringLen |= uint64(b&0x7F) << shift
 | 
			
		||||
				if b < 0x80 {
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			intStringLen := int(stringLen)
 | 
			
		||||
			if intStringLen < 0 {
 | 
			
		||||
				return ErrInvalidLengthVault
 | 
			
		||||
			}
 | 
			
		||||
			postIndex := iNdEx + intStringLen
 | 
			
		||||
			if postIndex < 0 {
 | 
			
		||||
				return ErrInvalidLengthVault
 | 
			
		||||
			}
 | 
			
		||||
			if postIndex > l {
 | 
			
		||||
				return io.ErrUnexpectedEOF
 | 
			
		||||
			}
 | 
			
		||||
			m.Denom = string(dAtA[iNdEx:postIndex])
 | 
			
		||||
			iNdEx = postIndex
 | 
			
		||||
		case 2:
 | 
			
		||||
			if wireType != 2 {
 | 
			
		||||
				return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType)
 | 
			
		||||
			}
 | 
			
		||||
			var stringLen uint64
 | 
			
		||||
			for shift := uint(0); ; shift += 7 {
 | 
			
		||||
				if shift >= 64 {
 | 
			
		||||
					return ErrIntOverflowVault
 | 
			
		||||
				}
 | 
			
		||||
				if iNdEx >= l {
 | 
			
		||||
					return io.ErrUnexpectedEOF
 | 
			
		||||
				}
 | 
			
		||||
				b := dAtA[iNdEx]
 | 
			
		||||
				iNdEx++
 | 
			
		||||
				stringLen |= uint64(b&0x7F) << shift
 | 
			
		||||
				if b < 0x80 {
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			intStringLen := int(stringLen)
 | 
			
		||||
			if intStringLen < 0 {
 | 
			
		||||
				return ErrInvalidLengthVault
 | 
			
		||||
			}
 | 
			
		||||
			postIndex := iNdEx + intStringLen
 | 
			
		||||
			if postIndex < 0 {
 | 
			
		||||
				return ErrInvalidLengthVault
 | 
			
		||||
			}
 | 
			
		||||
			if postIndex > l {
 | 
			
		||||
				return io.ErrUnexpectedEOF
 | 
			
		||||
			}
 | 
			
		||||
			if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
			iNdEx = postIndex
 | 
			
		||||
 | 
			
		||||
@ -25,12 +25,10 @@ func TestVaultRecordValidate(t *testing.T) {
 | 
			
		||||
			name: "valid vault records",
 | 
			
		||||
			vaultRecords: types.VaultRecords{
 | 
			
		||||
				{
 | 
			
		||||
					Denom:       "usdx",
 | 
			
		||||
					TotalSupply: sdk.NewInt64Coin("usdx", 0),
 | 
			
		||||
					TotalShares: types.NewVaultShare("usdx", sdk.NewDec(0)),
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Denom:       "ukava",
 | 
			
		||||
					TotalSupply: sdk.NewInt64Coin("ukava", 5),
 | 
			
		||||
					TotalShares: types.NewVaultShare("ukava", sdk.NewDec(5)),
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			errArgs: errArgs{
 | 
			
		||||
@ -41,12 +39,10 @@ func TestVaultRecordValidate(t *testing.T) {
 | 
			
		||||
			name: "invalid - duplicate denom",
 | 
			
		||||
			vaultRecords: types.VaultRecords{
 | 
			
		||||
				{
 | 
			
		||||
					Denom:       "usdx",
 | 
			
		||||
					TotalSupply: sdk.NewInt64Coin("usdx", 0),
 | 
			
		||||
					TotalShares: types.NewVaultShare("usdx", sdk.NewDec(0)),
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Denom:       "usdx",
 | 
			
		||||
					TotalSupply: sdk.NewInt64Coin("usdx", 5),
 | 
			
		||||
					TotalShares: types.NewVaultShare("usdx", sdk.NewDec(5)),
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			errArgs: errArgs{
 | 
			
		||||
@ -58,8 +54,7 @@ func TestVaultRecordValidate(t *testing.T) {
 | 
			
		||||
			name: "invalid - invalid denom",
 | 
			
		||||
			vaultRecords: types.VaultRecords{
 | 
			
		||||
				{
 | 
			
		||||
					Denom:       "",
 | 
			
		||||
					TotalSupply: sdk.NewInt64Coin("ukava", 0),
 | 
			
		||||
					TotalShares: types.VaultShare{Denom: "", Amount: sdk.NewDec(0)},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			errArgs: errArgs{
 | 
			
		||||
@ -67,30 +62,16 @@ func TestVaultRecordValidate(t *testing.T) {
 | 
			
		||||
				contains:   "invalid denom",
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "invalid - mismatch denom",
 | 
			
		||||
			vaultRecords: types.VaultRecords{
 | 
			
		||||
				{
 | 
			
		||||
					Denom:       "usdx",
 | 
			
		||||
					TotalSupply: sdk.NewInt64Coin("ukava", 0),
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			errArgs: errArgs{
 | 
			
		||||
				expectPass: false,
 | 
			
		||||
				contains:   "total supply denom ukava does not match vault record denom usdx",
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "invalid - negative",
 | 
			
		||||
			vaultRecords: types.VaultRecords{
 | 
			
		||||
				{
 | 
			
		||||
					Denom:       "usdx",
 | 
			
		||||
					TotalSupply: sdk.Coin{Denom: "usdx", Amount: sdk.NewInt(-1)},
 | 
			
		||||
					TotalShares: types.VaultShare{"usdx", sdk.NewDec(-5)},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			errArgs: errArgs{
 | 
			
		||||
				expectPass: false,
 | 
			
		||||
				contains:   "negative coin amount",
 | 
			
		||||
				contains:   "vault share amount -5.000000000000000000 is negative",
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
@ -127,15 +108,15 @@ func TestVaultShareRecordsValidate(t *testing.T) {
 | 
			
		||||
			vaultRecords: types.VaultShareRecords{
 | 
			
		||||
				{
 | 
			
		||||
					Depositor: addrs[0],
 | 
			
		||||
					AmountSupplied: sdk.NewCoins(
 | 
			
		||||
						sdk.NewInt64Coin("usdx", 0),
 | 
			
		||||
					Shares: types.NewVaultShares(
 | 
			
		||||
						types.NewVaultShare("usdx", sdk.NewDec(0)),
 | 
			
		||||
					),
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Depositor: addrs[1],
 | 
			
		||||
					AmountSupplied: sdk.NewCoins(
 | 
			
		||||
						sdk.NewInt64Coin("usdx", 0),
 | 
			
		||||
						sdk.NewInt64Coin("ukava", 5),
 | 
			
		||||
					Shares: types.NewVaultShares(
 | 
			
		||||
						types.NewVaultShare("usdx", sdk.NewDec(0)),
 | 
			
		||||
						types.NewVaultShare("ukava", sdk.NewDec(5)),
 | 
			
		||||
					),
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
@ -148,15 +129,15 @@ func TestVaultShareRecordsValidate(t *testing.T) {
 | 
			
		||||
			vaultRecords: types.VaultShareRecords{
 | 
			
		||||
				{
 | 
			
		||||
					Depositor: addrs[0],
 | 
			
		||||
					AmountSupplied: sdk.NewCoins(
 | 
			
		||||
						sdk.NewInt64Coin("usdx", 0),
 | 
			
		||||
					Shares: types.NewVaultShares(
 | 
			
		||||
						types.NewVaultShare("usdx", sdk.NewDec(0)),
 | 
			
		||||
					),
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Depositor: addrs[0],
 | 
			
		||||
					AmountSupplied: sdk.NewCoins(
 | 
			
		||||
						sdk.NewInt64Coin("usdx", 0),
 | 
			
		||||
						sdk.NewInt64Coin("ukava", 5),
 | 
			
		||||
					Shares: types.NewVaultShares(
 | 
			
		||||
						types.NewVaultShare("usdx", sdk.NewDec(0)),
 | 
			
		||||
						types.NewVaultShare("ukava", sdk.NewDec(5)),
 | 
			
		||||
					),
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
@ -170,8 +151,8 @@ func TestVaultShareRecordsValidate(t *testing.T) {
 | 
			
		||||
			vaultRecords: types.VaultShareRecords{
 | 
			
		||||
				{
 | 
			
		||||
					Depositor: sdk.AccAddress{},
 | 
			
		||||
					AmountSupplied: sdk.NewCoins(
 | 
			
		||||
						sdk.NewInt64Coin("usdx", 0),
 | 
			
		||||
					Shares: types.NewVaultShares(
 | 
			
		||||
						types.NewVaultShare("usdx", sdk.NewDec(0)),
 | 
			
		||||
					),
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
@ -185,14 +166,15 @@ func TestVaultShareRecordsValidate(t *testing.T) {
 | 
			
		||||
			vaultRecords: types.VaultShareRecords{
 | 
			
		||||
				{
 | 
			
		||||
					Depositor: addrs[0],
 | 
			
		||||
					AmountSupplied: sdk.Coins{
 | 
			
		||||
						sdk.Coin{Denom: "ukava", Amount: sdk.NewInt(-1)},
 | 
			
		||||
					// Direct slice, not NewVaultShares() which panics
 | 
			
		||||
					Shares: types.VaultShares{
 | 
			
		||||
						types.VaultShare{"usdx", sdk.NewDec(-5)},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			errArgs: errArgs{
 | 
			
		||||
				expectPass: false,
 | 
			
		||||
				contains:   "amount is not positive",
 | 
			
		||||
				contains:   "invalid vault share record shares: share -5.000000000000000000usdx amount is not positive",
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
@ -300,11 +282,11 @@ func TestAllowedVaultsValidate(t *testing.T) {
 | 
			
		||||
func TestNewVaultShareRecord(t *testing.T) {
 | 
			
		||||
	_, addrs := app.GeneratePrivKeyAddressPairs(1)
 | 
			
		||||
 | 
			
		||||
	coins := sdk.NewCoins(
 | 
			
		||||
		sdk.NewInt64Coin("usdx", 10),
 | 
			
		||||
		sdk.NewInt64Coin("ukava", 5),
 | 
			
		||||
	shares := types.NewVaultShares(
 | 
			
		||||
		types.NewVaultShare("usdx", sdk.NewDec(0)),
 | 
			
		||||
		types.NewVaultShare("ukava", sdk.NewDec(5)),
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	shareRecord := types.NewVaultShareRecord(addrs[0], coins...)
 | 
			
		||||
	require.Equal(t, coins, shareRecord.AmountSupplied)
 | 
			
		||||
	shareRecord := types.NewVaultShareRecord(addrs[0], shares)
 | 
			
		||||
	require.Equal(t, shares, shareRecord.Shares)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user