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:
Derrick Lee 2022-09-12 09:23:26 -07:00 committed by GitHub
parent fe89ba938d
commit b5e162a930
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 2477 additions and 1552 deletions

View File

@ -604,8 +604,8 @@ func NewApp(
earnSubspace, earnSubspace,
app.accountKeeper, app.accountKeeper,
app.bankKeeper, app.bankKeeper,
hardKeeper, &hardKeeper,
savingsKeeper, &savingsKeeper,
) )
// create committee keeper with router // create committee keeper with router

View File

@ -184,6 +184,7 @@
- [kava/earn/v1beta1/vault.proto](#kava/earn/v1beta1/vault.proto) - [kava/earn/v1beta1/vault.proto](#kava/earn/v1beta1/vault.proto)
- [AllowedVault](#kava.earn.v1beta1.AllowedVault) - [AllowedVault](#kava.earn.v1beta1.AllowedVault)
- [VaultRecord](#kava.earn.v1beta1.VaultRecord) - [VaultRecord](#kava.earn.v1beta1.VaultRecord)
- [VaultShare](#kava.earn.v1beta1.VaultShare)
- [VaultShareRecord](#kava.earn.v1beta1.VaultShareRecord) - [VaultShareRecord](#kava.earn.v1beta1.VaultShareRecord)
- [kava/earn/v1beta1/params.proto](#kava/earn/v1beta1/params.proto) - [kava/earn/v1beta1/params.proto](#kava/earn/v1beta1/params.proto)
@ -198,8 +199,6 @@
- [QueryDepositsResponse](#kava.earn.v1beta1.QueryDepositsResponse) - [QueryDepositsResponse](#kava.earn.v1beta1.QueryDepositsResponse)
- [QueryParamsRequest](#kava.earn.v1beta1.QueryParamsRequest) - [QueryParamsRequest](#kava.earn.v1beta1.QueryParamsRequest)
- [QueryParamsResponse](#kava.earn.v1beta1.QueryParamsResponse) - [QueryParamsResponse](#kava.earn.v1beta1.QueryParamsResponse)
- [QueryTotalDepositedRequest](#kava.earn.v1beta1.QueryTotalDepositedRequest)
- [QueryTotalDepositedResponse](#kava.earn.v1beta1.QueryTotalDepositedResponse)
- [QueryVaultsRequest](#kava.earn.v1beta1.QueryVaultsRequest) - [QueryVaultsRequest](#kava.earn.v1beta1.QueryVaultsRequest)
- [QueryVaultsResponse](#kava.earn.v1beta1.QueryVaultsResponse) - [QueryVaultsResponse](#kava.earn.v1beta1.QueryVaultsResponse)
- [VaultResponse](#kava.earn.v1beta1.VaultResponse) - [VaultResponse](#kava.earn.v1beta1.VaultResponse)
@ -2817,14 +2816,28 @@ modified via parameter governance.
<a name="kava.earn.v1beta1.VaultRecord"></a> <a name="kava.earn.v1beta1.VaultRecord"></a>
### VaultRecord ### VaultRecord
VaultRecord is the state of a vault and is used to store the state of a VaultRecord is the state of a vault.
vault.
| Field | Type | Label | Description | | Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- | | ----- | ---- | ----- | ----------- |
| `denom` | [string](#string) | | Denom is the only supported denomination of the vault for deposits and withdrawals. | | `total_shares` | [VaultShare](#kava.earn.v1beta1.VaultShare) | | TotalShares is the total distributed number of shares in the vault. |
| `total_supply` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | TotalSupply is the total supply of the vault, denominated **only** in the user deposit/withdrawal denom, must be the same as the Denom field. |
<a name="kava.earn.v1beta1.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 | | Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- | | ----- | ---- | ----- | ----------- |
| `depositor` | [bytes](#bytes) | | Depositor represents the owner of the shares | | `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 | | Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- | | ----- | ---- | ----- | ----------- |
| `depositor` | [string](#string) | | depositor represents the owner of the deposit. | | `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. | | `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> <a name="kava.earn.v1beta1.QueryVaultsRequest"></a>
### QueryVaultsRequest ### QueryVaultsRequest
@ -3072,7 +3055,7 @@ VaultResponse is the response type for a vault.
| ----- | ---- | ----- | ----------- | | ----- | ---- | ----- | ----------- |
| `denom` | [string](#string) | | denom represents the denom of the vault | | `denom` | [string](#string) | | denom represents the denom of the vault |
| `vault_strategy` | [StrategyType](#kava.earn.v1beta1.StrategyType) | | VaultStrategy is the strategy used for this vault. | | `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. | | `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| | `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}| | `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| | `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 --> <!-- end services -->
@ -3131,6 +3113,11 @@ MsgDeposit represents a message for depositing assedts into a vault
MsgDepositResponse defines the Msg/Deposit response type. 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. MsgWithdrawResponse defines the Msg/Withdraw response type.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `shares` | [VaultShare](#kava.earn.v1beta1.VaultShare) | | |

View File

@ -11,6 +11,7 @@ import "gogoproto/gogo.proto";
import "google/api/annotations.proto"; import "google/api/annotations.proto";
import "kava/earn/v1beta1/params.proto"; import "kava/earn/v1beta1/params.proto";
import "kava/earn/v1beta1/strategy.proto"; import "kava/earn/v1beta1/strategy.proto";
import "kava/earn/v1beta1/vault.proto";
// Query defines the gRPC querier service for earn module // Query defines the gRPC querier service for earn module
service Query { service Query {
@ -28,11 +29,6 @@ service Query {
rpc Deposits(QueryDepositsRequest) returns (QueryDepositsResponse) { rpc Deposits(QueryDepositsRequest) returns (QueryDepositsResponse) {
option (google.api.http).get = "/kava/earn/v1beta1/deposits"; 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. // 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. // QueryParamsResponse defines the response type for querying x/earn parameters.
message QueryParamsResponse { message QueryParamsResponse {
// params represents the earn module parameters // params represents the earn module parameters
Params params = 1 [(gogoproto.nullable) = false]; Params params = 1 [(gogoproto.nullable) = false];
} }
@ -65,12 +60,8 @@ message VaultResponse {
// VaultStrategy is the strategy used for this vault. // VaultStrategy is the strategy used for this vault.
StrategyType vault_strategy = 2; StrategyType vault_strategy = 2;
// TotalSupplied is the total amount of denom coins supplied to the vault. // TotalShares is the total amount of shares issued to depositors.
string total_supplied = 3 [ string total_shares = 3;
(cosmos_proto.scalar) = "cosmos.Int",
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.nullable) = false
];
// TotalValue is the total value of denom coins supplied to the vault if the // TotalValue is the total value of denom coins supplied to the vault if the
// vault were to be liquidated. // vault were to be liquidated.
@ -107,9 +98,8 @@ message DepositResponse {
// depositor represents the owner of the deposit. // depositor represents the owner of the deposit.
string depositor = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; string depositor = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
// Amount represents the amount supplied to vaults. // Shares represent the issued shares from their corresponding vaults.
repeated cosmos.base.v1beta1.Coin amount_supplied = 2 repeated VaultShare shares = 2 [(gogoproto.castrepeated) = "VaultShares", (gogoproto.nullable) = false];
[(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins", (gogoproto.nullable) = false];
// Value represents the total accumulated value of denom coins supplied to // Value represents the total accumulated value of denom coins supplied to
// vaults. This may be greater than or equal to amount_supplied depending on // 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 repeated cosmos.base.v1beta1.Coin value = 3
[(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins", (gogoproto.nullable) = false]; [(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];
}

View File

@ -4,6 +4,7 @@ package kava.earn.v1beta1;
import "cosmos_proto/cosmos.proto"; import "cosmos_proto/cosmos.proto";
import "cosmos/base/v1beta1/coin.proto"; import "cosmos/base/v1beta1/coin.proto";
import "gogoproto/gogo.proto"; import "gogoproto/gogo.proto";
import "kava/earn/v1beta1/vault.proto";
option go_package = "github.com/kava-labs/kava/x/earn/types"; option go_package = "github.com/kava-labs/kava/x/earn/types";
@ -27,7 +28,9 @@ message MsgDeposit {
} }
// MsgDepositResponse defines the Msg/Deposit response type. // 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 // MsgWithdraw represents a message for withdrawing liquidity from a vault
message MsgWithdraw { message MsgWithdraw {
@ -42,4 +45,6 @@ message MsgWithdraw {
} }
// MsgWithdrawResponse defines the Msg/Withdraw response type. // MsgWithdrawResponse defines the Msg/Withdraw response type.
message MsgWithdrawResponse {} message MsgWithdrawResponse {
VaultShare shares = 1 [(gogoproto.nullable) = false];
}

View File

@ -18,15 +18,10 @@ message AllowedVault {
StrategyType vault_strategy = 2; StrategyType vault_strategy = 2;
} }
// VaultRecord is the state of a vault and is used to store the state of a // VaultRecord is the state of a vault.
// vault.
message VaultRecord { message VaultRecord {
// Denom is the only supported denomination of the vault for deposits and // TotalShares is the total distributed number of shares in the vault.
// withdrawals. VaultShare total_shares = 1 [(gogoproto.nullable) = false];
string denom = 1;
// TotalSupply is the total supply of the vault, denominated **only** in the
// user deposit/withdrawal denom, must be the same as the Denom field.
cosmos.base.v1beta1.Coin total_supply = 2 [(gogoproto.nullable) = false];
} }
// VaultShareRecord defines the vault shares owned by a depositor. // VaultShareRecord defines the vault shares owned by a depositor.
@ -36,8 +31,18 @@ message VaultShareRecord {
(cosmos_proto.scalar) = "cosmos.AddressBytes", (cosmos_proto.scalar) = "cosmos.AddressBytes",
(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress" (gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"
]; ];
// AmountSupplied represents the total amount a depositor has supplied to the // Shares represent the vault shares owned by the depositor.
// vault. The vault is determined by the coin denom. repeated VaultShare shares = 2 [(gogoproto.castrepeated) = "VaultShares", (gogoproto.nullable) = false];
repeated cosmos.base.v1beta1.Coin amount_supplied = 2 }
[(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins", (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
];
}

View File

@ -33,7 +33,6 @@ func GetQueryCmd() *cobra.Command {
queryParamsCmd(), queryParamsCmd(),
queryVaultsCmd(), queryVaultsCmd(),
queryDepositsCmd(), queryDepositsCmd(),
queryTotalDepositedCmd(),
} }
for _, cmd := range cmds { for _, cmd := range cmds {
@ -155,35 +154,3 @@ func queryDepositsCmd() *cobra.Command {
return cmd 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)
},
}
}

View File

@ -21,14 +21,14 @@ func InitGenesis(
} }
// Total of all vault share records, vault record total supply should equal this // Total of all vault share records, vault record total supply should equal this
vaultTotalSupplies := sdk.NewCoins() vaultTotalShares := types.NewVaultShares()
for _, vaultShareRecord := range gs.VaultShareRecords { for _, vaultShareRecord := range gs.VaultShareRecords {
if err := vaultShareRecord.Validate(); err != nil { if err := vaultShareRecord.Validate(); err != nil {
panic(fmt.Sprintf("invalid vault share: %s", err)) panic(fmt.Sprintf("invalid vault share: %s", err))
} }
vaultTotalSupplies = vaultTotalSupplies.Add(vaultShareRecord.AmountSupplied...) vaultTotalShares = vaultTotalShares.Add(vaultShareRecord.Shares...)
k.SetVaultShareRecord(ctx, vaultShareRecord) k.SetVaultShareRecord(ctx, vaultShareRecord)
} }
@ -38,12 +38,12 @@ func InitGenesis(
panic(fmt.Sprintf("invalid vault record: %s", err)) 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( panic(fmt.Sprintf(
"invalid vault record total supply for %s, got %s but sum of vault shares is %s", "invalid vault record total supply for %s, got %s but sum of vault shares is %s",
vaultRecord.Denom, vaultRecord.TotalShares.Denom,
vaultRecord.TotalSupply.Amount, vaultRecord.TotalShares.Amount,
vaultTotalSupplies.AmountOf(vaultRecord.Denom), vaultTotalShares.AmountOf(vaultRecord.TotalShares.Denom),
)) ))
} }

View File

@ -25,8 +25,9 @@ func (suite *genesisTestSuite) Test_InitGenesis_ValidationPanic() {
}, },
types.VaultRecords{ types.VaultRecords{
{ {
Denom: "", TotalShares: types.VaultShare{
TotalSupply: sdk.NewInt64Coin("usdx", 0), Denom: "", Amount: sdk.NewDec(1),
},
}, },
}, },
types.VaultShareRecords{}, types.VaultShareRecords{},
@ -53,22 +54,26 @@ func (suite *genesisTestSuite) Test_InitAndExportGenesis() {
}, },
types.VaultRecords{ types.VaultRecords{
types.VaultRecord{ types.VaultRecord{
Denom: "ukava", TotalShares: types.NewVaultShare("ukava", sdk.NewDec(3800000)),
TotalSupply: sdk.NewInt64Coin("ukava", 2000000),
}, },
types.VaultRecord{ types.VaultRecord{
Denom: "usdx", TotalShares: types.NewVaultShare("usdx", sdk.NewDec(1000000)),
TotalSupply: sdk.NewInt64Coin("usdx", 1000000),
}, },
}, },
types.VaultShareRecords{ types.VaultShareRecords{
types.VaultShareRecord{ types.VaultShareRecord{
Depositor: depositor_1, 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{ types.VaultShareRecord{
Depositor: depositor_2, 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.VaultRecords{
types.VaultRecord{ types.VaultRecord{
Denom: "ukava", TotalShares: types.NewVaultShare("ukava", sdk.NewDec(3800000)),
TotalSupply: sdk.NewInt64Coin("ukava", 2000000),
}, },
types.VaultRecord{ types.VaultRecord{
Denom: "usdx", TotalShares: types.NewVaultShare("usdx", sdk.NewDec(1000000)),
TotalSupply: sdk.NewInt64Coin("usdx", 1000000),
}, },
}, },
types.VaultShareRecords{ types.VaultShareRecords{
types.VaultShareRecord{ types.VaultShareRecord{
Depositor: depositor_1, 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{ types.VaultShareRecord{
Depositor: depositor_2, 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)),
),
}, },
}, },
) )

View File

@ -1,6 +1,8 @@
package keeper package keeper
import ( import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/kava-labs/kava/x/earn/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) vaultRecord, found := k.GetVaultRecord(ctx, amount.Denom)
if !found { if !found {
// Create a new VaultRecord with 0 supply // 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 // 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) vaultShareRecord, found := k.GetVaultShareRecord(ctx, depositor)
if !found { if !found {
// Create a new empty VaultShareRecord with 0 supply // Create a new empty VaultShareRecord with 0 supply
vaultShareRecord = types.NewVaultShareRecord(depositor) vaultShareRecord = types.NewVaultShareRecord(depositor, types.NewVaultShares())
} }
// Increment VaultRecord supply shares, err := k.ConvertToShares(ctx, amount)
vaultRecord.TotalSupply = vaultRecord.TotalSupply.Add(amount) if err != nil {
return fmt.Errorf("failed to convert assets to shares: %w", err)
}
// Increment VaultShareRecord supply // Increment VaultRecord total shares and account shares
vaultShareRecord.AmountSupplied = vaultShareRecord.AmountSupplied.Add(amount) vaultRecord.TotalShares = vaultRecord.TotalShares.Add(shares)
vaultShareRecord.Shares = vaultShareRecord.Shares.Add(shares)
// Update VaultRecord and VaultShareRecord // Update VaultRecord and VaultShareRecord
k.SetVaultRecord(ctx, vaultRecord) k.SetVaultRecord(ctx, vaultRecord)
@ -68,6 +73,7 @@ func (k *Keeper) Deposit(ctx sdk.Context, depositor sdk.AccAddress, amount sdk.C
types.EventTypeVaultDeposit, types.EventTypeVaultDeposit,
sdk.NewAttribute(types.AttributeKeyVaultDenom, amount.Denom), sdk.NewAttribute(types.AttributeKeyVaultDenom, amount.Denom),
sdk.NewAttribute(types.AttributeKeyDepositor, depositor.String()), sdk.NewAttribute(types.AttributeKeyDepositor, depositor.String()),
sdk.NewAttribute(types.AttributeKeyShares, shares.Amount.String()),
sdk.NewAttribute(sdk.AttributeKeyAmount, amount.Amount.String()), sdk.NewAttribute(sdk.AttributeKeyAmount, amount.Amount.String()),
), ),
) )

View File

@ -51,7 +51,9 @@ func (suite *depositTestSuite) TestDeposit_Balances() {
) )
suite.VaultTotalValuesEqual(sdk.NewCoins(depositAmount)) 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() { func (suite *depositTestSuite) TestDeposit_Exceed() {

View File

@ -69,10 +69,10 @@ func (s queryServer) Vaults(
vaults := []types.VaultResponse{} vaults := []types.VaultResponse{}
for _, allowedVault := range queriedAllowedVaults { for _, allowedVault := range queriedAllowedVaults {
totalSupplied, err := s.keeper.GetVaultTotalSupplied(sdkCtx, allowedVault.Denom) vaultTotalShares, found := s.keeper.GetVaultTotalShares(sdkCtx, allowedVault.Denom)
if err != nil { if !found {
// No supply yet, no error just zero // 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) totalValue, err := s.keeper.GetVaultTotalValue(sdkCtx, allowedVault.Denom)
@ -83,7 +83,7 @@ func (s queryServer) Vaults(
vaults = append(vaults, types.VaultResponse{ vaults = append(vaults, types.VaultResponse{
Denom: allowedVault.Denom, Denom: allowedVault.Denom,
VaultStrategy: allowedVault.VaultStrategy, VaultStrategy: allowedVault.VaultStrategy,
TotalSupplied: totalSupplied.Amount, TotalShares: vaultTotalShares.Amount.String(),
TotalValue: totalValue.Amount, TotalValue: totalValue.Amount,
}) })
} }
@ -106,126 +106,159 @@ func (s queryServer) Deposits(
// 1. Specific account and specific vault // 1. Specific account and specific vault
if req.Owner != "" && req.Denom != "" { if req.Owner != "" && req.Denom != "" {
owner, err := sdk.AccAddressFromBech32(req.Owner) return s.getAccountVaultDeposit(sdkCtx, req)
if err != nil {
return nil, status.Error(codes.InvalidArgument, "Invalid address")
}
shareRecord, found := s.keeper.GetVaultShareRecord(sdkCtx, owner)
if !found {
return nil, status.Error(codes.NotFound, "No deposit found for owner")
}
if shareRecord.AmountSupplied.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)
if err != nil {
return nil, status.Error(codes.InvalidArgument, err.Error())
}
return &types.QueryDepositsResponse{
Deposits: []types.DepositResponse{
{
Depositor: owner.String(),
AmountSupplied: shareRecord.AmountSupplied,
Value: value,
},
},
Pagination: nil,
}, nil
} }
// 2. All accounts, specific vault // 2. All accounts, specific vault
if req.Owner == "" && req.Denom != "" { if req.Owner == "" && req.Denom != "" {
_, found := s.keeper.GetVaultRecord(sdkCtx, req.Denom) return s.getVaultAllDeposits(sdkCtx, req)
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)
pageRes, err := query.FilteredPaginate(
store,
req.Pagination,
func(key []byte, value []byte, accumulate bool) (bool, error) {
var record types.VaultShareRecord
err := s.keeper.cdc.Unmarshal(value, &record)
if err != nil {
return false, err
}
// Only those that have amount of requested denom
if record.AmountSupplied.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)
if err != nil {
return false, err
}
// only add to results if paginate tells us to
deposits = append(deposits, types.DepositResponse{
Depositor: record.Depositor.String(),
AmountSupplied: record.AmountSupplied,
Value: accValue,
})
}
// inform paginate that were was a match on this key
return true, nil
},
)
if err != nil {
return nil, err
}
return &types.QueryDepositsResponse{
Deposits: deposits,
Pagination: pageRes,
}, nil
} }
// 3. Specific account, all vaults // 3. Specific account, all vaults
if req.Owner != "" && req.Denom == "" { if req.Owner != "" && req.Denom == "" {
owner, err := sdk.AccAddressFromBech32(req.Owner) return s.getAccountAllDeposits(sdkCtx, req)
if err != nil {
return nil, status.Error(codes.InvalidArgument, "Invalid address")
}
deposits := []types.DepositResponse{}
accountShare, found := s.keeper.GetVaultShareRecord(sdkCtx, owner)
if !found {
return nil, status.Error(codes.NotFound, "No deposit found for owner")
}
value, err := getAccountValue(sdkCtx, s.keeper, owner, accountShare.AmountSupplied)
if err != nil {
return nil, status.Error(codes.InvalidArgument, err.Error())
}
deposits = append(deposits, types.DepositResponse{
Depositor: owner.String(),
AmountSupplied: accountShare.AmountSupplied,
Value: value,
})
return &types.QueryDepositsResponse{
Deposits: deposits,
Pagination: nil,
}, nil
} }
// 4. All accounts, all vaults // 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(ctx, owner)
if !found {
return nil, status.Error(codes.NotFound, "No deposit found for owner")
}
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(ctx, s.keeper, owner, shareRecord.Shares)
if err != nil {
return nil, status.Error(codes.InvalidArgument, err.Error())
}
return &types.QueryDepositsResponse{
Deposits: []types.DepositResponse{
{
Depositor: owner.String(),
Shares: shareRecord.Shares,
Value: value,
},
},
Pagination: nil,
}, nil
}
// 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{} 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,
req.Pagination,
func(key []byte, value []byte, accumulate bool) (bool, error) {
var record types.VaultShareRecord
err := s.keeper.cdc.Unmarshal(value, &record)
if err != nil {
return false, err
}
// Only those that have amount of requested denom
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(ctx, s.keeper, record.Depositor, record.Shares)
if err != nil {
return false, err
}
// only add to results if paginate tells us to
deposits = append(deposits, types.DepositResponse{
Depositor: record.Depositor.String(),
Shares: record.Shares,
Value: accValue,
})
}
// inform paginate that were was a match on this key
return true, nil
},
)
if err != nil {
return nil, err
}
return &types.QueryDepositsResponse{
Deposits: deposits,
Pagination: pageRes,
}, nil
}
// 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")
}
deposits := []types.DepositResponse{}
accountShare, found := s.keeper.GetVaultShareRecord(ctx, owner)
if !found {
return nil, status.Error(codes.NotFound, "No deposit found for owner")
}
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(),
Shares: accountShare.Shares,
Value: value,
})
return &types.QueryDepositsResponse{
Deposits: deposits,
Pagination: nil,
}, nil
}
// 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(ctx.KVStore(s.keeper.key), types.VaultShareRecordKeyPrefix)
pageRes, err := query.Paginate( pageRes, err := query.Paginate(
store, store,
@ -237,16 +270,16 @@ func (s queryServer) Deposits(
return err 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 { if err != nil {
return err return err
} }
// only add to results if paginate tells us to // only add to results if paginate tells us to
deposits = append(deposits, types.DepositResponse{ deposits = append(deposits, types.DepositResponse{
Depositor: record.Depositor.String(), Depositor: record.Depositor.String(),
AmountSupplied: record.AmountSupplied, Shares: record.Shares,
Value: accValue, Value: accValue,
}) })
return nil return nil
@ -263,56 +296,21 @@ func (s queryServer) Deposits(
}, nil }, 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( func getAccountValue(
ctx sdk.Context, ctx sdk.Context,
keeper Keeper, keeper Keeper,
account sdk.AccAddress, account sdk.AccAddress,
supplied sdk.Coins, shares types.VaultShares,
) (sdk.Coins, error) { ) (sdk.Coins, error) {
value := sdk.NewCoins() value := sdk.NewCoins()
for _, coin := range supplied { for _, share := range shares {
accValue, err := keeper.GetVaultAccountValue(ctx, coin.Denom, account) accValue, err := keeper.GetVaultAccountValue(ctx, share.Denom, account)
if err != nil { if err != nil {
return nil, err return nil, err
} }
value = value.Add(sdk.NewCoin(coin.Denom, accValue.Amount)) value = value.Add(sdk.NewCoin(share.Denom, accValue.Amount))
} }
return value, nil return value, nil

View File

@ -70,7 +70,7 @@ func (suite *grpcQueryTestSuite) TestVaults_ZeroSupply() {
types.VaultResponse{ types.VaultResponse{
Denom: "usdx", Denom: "usdx",
VaultStrategy: types.STRATEGY_TYPE_HARD, VaultStrategy: types.STRATEGY_TYPE_HARD,
TotalSupplied: sdk.NewInt(0), TotalShares: sdk.NewDec(0).String(),
TotalValue: sdk.NewInt(0), TotalValue: sdk.NewInt(0),
}, },
res.Vaults[0], res.Vaults[0],
@ -86,13 +86,13 @@ func (suite *grpcQueryTestSuite) TestVaults_ZeroSupply() {
{ {
Denom: "usdx", Denom: "usdx",
VaultStrategy: types.STRATEGY_TYPE_HARD, VaultStrategy: types.STRATEGY_TYPE_HARD,
TotalSupplied: sdk.NewInt(0), TotalShares: sdk.NewDec(0).String(),
TotalValue: sdk.NewInt(0), TotalValue: sdk.NewInt(0),
}, },
{ {
Denom: "busd", Denom: "busd",
VaultStrategy: types.STRATEGY_TYPE_HARD, VaultStrategy: types.STRATEGY_TYPE_HARD,
TotalSupplied: sdk.NewInt(0), TotalShares: sdk.NewDec(0).String(),
TotalValue: sdk.NewInt(0), TotalValue: sdk.NewInt(0),
}, },
}, },
@ -121,7 +121,7 @@ func (suite *grpcQueryTestSuite) TestVaults_WithSupply() {
types.VaultResponse{ types.VaultResponse{
Denom: "usdx", Denom: "usdx",
VaultStrategy: types.STRATEGY_TYPE_HARD, VaultStrategy: types.STRATEGY_TYPE_HARD,
TotalSupplied: depositAmount.Amount, TotalShares: depositAmount.Amount.ToDec().String(),
TotalValue: depositAmount.Amount, TotalValue: depositAmount.Amount,
}, },
res.Vaults[0], res.Vaults[0],
@ -183,8 +183,11 @@ func (suite *grpcQueryTestSuite) TestDeposits() {
{ {
Depositor: acc1.String(), Depositor: acc1.String(),
// Still includes all deposits // Still includes all deposits
AmountSupplied: sdk.NewCoins(deposit1Amount, deposit2Amount), Shares: types.NewVaultShares(
Value: sdk.NewCoins(deposit1Amount, deposit2Amount), types.NewVaultShare(deposit1Amount.Denom, deposit1Amount.Amount.ToDec()),
types.NewVaultShare(deposit2Amount.Denom, deposit2Amount.Amount.ToDec()),
),
Value: sdk.NewCoins(deposit1Amount, deposit2Amount),
}, },
}, },
res.Deposits, res.Deposits,
@ -213,9 +216,12 @@ func (suite *grpcQueryTestSuite) TestDeposits() {
suite.Require().ElementsMatch( suite.Require().ElementsMatch(
[]types.DepositResponse{ []types.DepositResponse{
{ {
Depositor: acc1.String(), Depositor: acc1.String(),
AmountSupplied: sdk.NewCoins(deposit1Amount, deposit2Amount), Shares: types.NewVaultShares(
Value: sdk.NewCoins(deposit1Amount, deposit2Amount), types.NewVaultShare(deposit1Amount.Denom, deposit1Amount.Amount.ToDec()),
types.NewVaultShare(deposit2Amount.Denom, deposit2Amount.Amount.ToDec()),
),
Value: sdk.NewCoins(deposit1Amount, deposit2Amount),
}, },
}, },
res.Deposits, res.Deposits,
@ -233,9 +239,12 @@ func (suite *grpcQueryTestSuite) TestDeposits() {
suite.Require().ElementsMatch( suite.Require().ElementsMatch(
[]types.DepositResponse{ []types.DepositResponse{
{ {
Depositor: acc2.String(), Depositor: acc2.String(),
AmountSupplied: sdk.NewCoins(deposit1Amount, deposit3Amount), Shares: types.NewVaultShares(
Value: sdk.NewCoins(deposit1Amount, deposit3Amount), types.NewVaultShare(deposit1Amount.Denom, deposit1Amount.Amount.ToDec()),
types.NewVaultShare(deposit3Amount.Denom, deposit3Amount.Amount.ToDec()),
),
Value: sdk.NewCoins(deposit1Amount, deposit3Amount),
}, },
}, },
res.Deposits, res.Deposits,
@ -253,14 +262,20 @@ func (suite *grpcQueryTestSuite) TestDeposits() {
suite.Require().ElementsMatchf( suite.Require().ElementsMatchf(
[]types.DepositResponse{ []types.DepositResponse{
{ {
Depositor: acc1.String(), Depositor: acc1.String(),
AmountSupplied: sdk.NewCoins(deposit1Amount, deposit2Amount), Shares: types.NewVaultShares(
Value: sdk.NewCoins(deposit1Amount, deposit2Amount), types.NewVaultShare(deposit1Amount.Denom, deposit1Amount.Amount.ToDec()),
types.NewVaultShare(deposit2Amount.Denom, deposit2Amount.Amount.ToDec()),
),
Value: sdk.NewCoins(deposit1Amount, deposit2Amount),
}, },
{ {
Depositor: acc2.String(), Depositor: acc2.String(),
AmountSupplied: sdk.NewCoins(deposit1Amount, deposit3Amount), Shares: types.NewVaultShares(
Value: sdk.NewCoins(deposit1Amount, deposit3Amount), types.NewVaultShare(deposit1Amount.Denom, deposit1Amount.Amount.ToDec()),
types.NewVaultShare(deposit3Amount.Denom, deposit3Amount.Amount.ToDec()),
),
Value: sdk.NewCoins(deposit1Amount, deposit3Amount),
}, },
}, },
res.Deposits, res.Deposits,
@ -294,103 +309,3 @@ func (suite *grpcQueryTestSuite) TestDeposits_InvalidAddress() {
suite.Require().Error(err) suite.Require().Error(err)
suite.Require().ErrorIs(err, status.Error(codes.InvalidArgument, "Invalid address")) 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",
)
}

View File

@ -68,6 +68,8 @@ func (suite *msgServerTestSuite) TestDeposit() {
types.EventTypeVaultDeposit, types.EventTypeVaultDeposit,
sdk.NewAttribute(types.AttributeKeyVaultDenom, depositAmount.Denom), sdk.NewAttribute(types.AttributeKeyVaultDenom, depositAmount.Denom),
sdk.NewAttribute(types.AttributeKeyDepositor, acc.GetAddress().String()), 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()), sdk.NewAttribute(sdk.AttributeKeyAmount, depositAmount.Amount.String()),
), ),
) )
@ -120,6 +122,7 @@ func (suite *msgServerTestSuite) TestWithdraw() {
types.EventTypeVaultWithdraw, types.EventTypeVaultWithdraw,
sdk.NewAttribute(types.AttributeKeyVaultDenom, depositAmount.Denom), sdk.NewAttribute(types.AttributeKeyVaultDenom, depositAmount.Denom),
sdk.NewAttribute(types.AttributeKeyOwner, acc.GetAddress().String()), sdk.NewAttribute(types.AttributeKeyOwner, acc.GetAddress().String()),
sdk.NewAttribute(types.AttributeKeyShares, depositAmount.Amount.ToDec().String()),
sdk.NewAttribute(sdk.AttributeKeyAmount, depositAmount.Amount.String()), sdk.NewAttribute(sdk.AttributeKeyAmount, depositAmount.Amount.String()),
), ),
) )

View File

@ -45,7 +45,9 @@ func (suite *strategyHardTestSuite) TestDeposit_SingleAcc() {
suite.HardDepositAmountEqual(sdk.NewCoins(depositAmount)) suite.HardDepositAmountEqual(sdk.NewCoins(depositAmount))
suite.VaultTotalValuesEqual(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 // Query vault total
totalValue, err := suite.Keeper.GetVaultTotalValue(suite.Ctx, vaultDenom) 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) err = suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount)
suite.Require().NoError(err) suite.Require().NoError(err)
expectedVaultBalance := sdk.NewCoins(depositAmount.Add(depositAmount)) expectedVaultBalance := depositAmount.Add(depositAmount)
suite.HardDepositAmountEqual(expectedVaultBalance) suite.HardDepositAmountEqual(sdk.NewCoins(expectedVaultBalance))
suite.VaultTotalValuesEqual(expectedVaultBalance) suite.VaultTotalValuesEqual(sdk.NewCoins(expectedVaultBalance))
suite.VaultTotalSuppliedEqual(expectedVaultBalance) suite.VaultTotalSharesEqual(types.NewVaultShares(
types.NewVaultShare(expectedVaultBalance.Denom, expectedVaultBalance.Amount.ToDec()),
))
// Query vault total // Query vault total
totalValue, err := suite.Keeper.GetVaultTotalValue(suite.Ctx, vaultDenom) totalValue, err := suite.Keeper.GetVaultTotalValue(suite.Ctx, vaultDenom)
@ -107,7 +111,9 @@ func (suite *strategyHardTestSuite) TestDeposit_MultipleAcc_MultipleDeposits() {
suite.HardDepositAmountEqual(sdk.NewCoins(expectedTotalValue)) suite.HardDepositAmountEqual(sdk.NewCoins(expectedTotalValue))
suite.VaultTotalValuesEqual(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 // Query vault total
totalValue, err := suite.Keeper.GetVaultTotalValue(suite.Ctx, vaultDenom) totalValue, err := suite.Keeper.GetVaultTotalValue(suite.Ctx, vaultDenom)
@ -183,7 +189,7 @@ func (suite *strategyHardTestSuite) TestWithdraw() {
suite.HardDepositAmountEqual(sdk.NewCoins()) suite.HardDepositAmountEqual(sdk.NewCoins())
suite.VaultTotalValuesEqual(sdk.NewCoins()) suite.VaultTotalValuesEqual(sdk.NewCoins())
suite.VaultTotalSuppliedEqual(sdk.NewCoins()) suite.VaultTotalSharesEqual(types.NewVaultShares())
totalValue, err = suite.Keeper.GetVaultTotalValue(suite.Ctx, vaultDenom) totalValue, err = suite.Keeper.GetVaultTotalValue(suite.Ctx, vaultDenom)
suite.Require().NoError(err) suite.Require().NoError(err)
@ -232,26 +238,32 @@ func (suite *strategyHardTestSuite) TestWithdraw_WithAccumulatedHard() {
suite.CreateVault(vaultDenom, types.STRATEGY_TYPE_HARD) suite.CreateVault(vaultDenom, types.STRATEGY_TYPE_HARD)
// Deposits from 2 accounts // Deposits accounts
acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0).GetAddress() acc := suite.CreateAccount(sdk.NewCoins(startBalance), 0).GetAddress()
acc2 := suite.CreateAccount(sdk.NewCoins(startBalance), 1).GetAddress()
err := suite.Keeper.Deposit(suite.Ctx, acc, depositAmount) err := suite.Keeper.Deposit(suite.Ctx, acc, depositAmount)
suite.Require().NoError(err) 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 // 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) 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 // Query account value
accValue, err := suite.Keeper.GetVaultAccountValue(suite.Ctx, vaultDenom, acc) accValue, err := suite.Keeper.GetVaultAccountValue(suite.Ctx, vaultDenom, acc)
suite.Require().NoError(err) suite.Require().NoError(err)
suite.Equal(depositAmount.AddAmount(sdk.NewInt(10)), accValue) suite.Equal(depositAmount.AddAmount(sdk.NewInt(10)), accValue)
// Withdraw 10, 10 remaining // Withdraw 100, 10 remaining
err = suite.Keeper.Withdraw(suite.Ctx, acc, depositAmount) err = suite.Keeper.Withdraw(suite.Ctx, acc, depositAmount)
suite.Require().NoError(err) suite.Require().NoError(err)
// Withdraw again -- too much // Withdraw 100 again -- too much
err = suite.Keeper.Withdraw(suite.Ctx, acc, depositAmount) err = suite.Keeper.Withdraw(suite.Ctx, acc, depositAmount)
suite.Require().Error(err) suite.Require().Error(err)
suite.Require().ErrorIs( 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))) err = suite.Keeper.Withdraw(suite.Ctx, acc, sdk.NewCoin(vaultDenom, sdk.NewInt(5)))
suite.Require().NoError(err) suite.Require().NoError(err)
_, err = suite.Keeper.GetVaultAccountValue(suite.Ctx, vaultDenom, acc) accValue, err = suite.Keeper.GetVaultAccountValue(suite.Ctx, vaultDenom, acc)
suite.Require().Error(err) suite.Require().Errorf(
suite.Require().ErrorIs(err, types.ErrVaultRecordNotFound) 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)
} }

View File

@ -1,24 +1,25 @@
package keeper package keeper
import ( import (
"github.com/cosmos/cosmos-sdk/store/prefix" "fmt"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/kava-labs/kava/x/earn/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 // 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. // 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, ctx sdk.Context,
denom string, denom string,
) (sdk.Coin, error) { ) (types.VaultShare, bool) {
vault, found := k.GetVaultRecord(ctx, denom) vault, found := k.GetVaultRecord(ctx, denom)
if !found { 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, // 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 // GetVaultAccountSupplied returns the supplied amount for a single address
// within a vault. // within a vault.
func (k *Keeper) GetVaultAccountSupplied( func (k *Keeper) GetVaultAccountShares(
ctx sdk.Context, ctx sdk.Context,
acc sdk.AccAddress, acc sdk.AccAddress,
) (sdk.Coins, error) { ) (types.VaultShares, bool) {
vaultShareRecord, found := k.GetVaultShareRecord(ctx, acc) vaultShareRecord, found := k.GetVaultShareRecord(ctx, acc)
if !found { 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 // GetVaultAccountValue returns the value of a single address within a vault
@ -66,190 +67,10 @@ func (k *Keeper) GetVaultAccountValue(
denom string, denom string,
acc sdk.AccAddress, acc sdk.AccAddress,
) (sdk.Coin, error) { ) (sdk.Coin, error) {
totalSupplied, err := k.GetVaultTotalSupplied(ctx, denom) accShares, found := k.GetVaultAccountShares(ctx, acc)
if err != nil { if !found {
return sdk.Coin{}, err return sdk.Coin{}, fmt.Errorf("account vault share record for %s not found", denom)
} }
accSupplied, err := k.GetVaultAccountSupplied(ctx, acc) return k.ConvertToAssets(ctx, accShares.GetShare(denom))
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
} }

View 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
}

View 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
}

View 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
}

View 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")
}

View 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)
}

View File

@ -23,7 +23,7 @@ func TestVaultTestSuite(t *testing.T) {
suite.Run(t, new(vaultTestSuite)) suite.Run(t, new(vaultTestSuite))
} }
func (suite *vaultTestSuite) TestGetVaultTotalSupplied() { func (suite *vaultTestSuite) TestGetVaultTotalShares() {
vaultDenom := "usdx" vaultDenom := "usdx"
startBalance := sdk.NewInt64Coin(vaultDenom, 1000) startBalance := sdk.NewInt64Coin(vaultDenom, 1000)
depositAmount := sdk.NewInt64Coin(vaultDenom, 100) depositAmount := sdk.NewInt64Coin(vaultDenom, 100)
@ -35,22 +35,27 @@ func (suite *vaultTestSuite) TestGetVaultTotalSupplied() {
err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount) err := suite.Keeper.Deposit(suite.Ctx, acc.GetAddress(), depositAmount)
suite.Require().NoError(err) suite.Require().NoError(err)
vaultTotalSupplied, err := suite.Keeper.GetVaultTotalSupplied(suite.Ctx, vaultDenom) vaultTotalShares, found := suite.Keeper.GetVaultTotalShares(suite.Ctx, vaultDenom)
suite.Require().NoError(err) 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" vaultDenom := "usdx"
_, err := suite.Keeper.GetVaultTotalSupplied(suite.Ctx, vaultDenom) _, found := suite.Keeper.GetVaultTotalShares(suite.Ctx, vaultDenom)
suite.Require().Error(err) suite.Require().False(found)
suite.Require().ErrorIs(err, types.ErrVaultRecordNotFound)
} }
func (suite *vaultTestSuite) TestGetVaultTotalValue() { 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() { func (suite *vaultTestSuite) TestGetVaultTotalValue_NotFound() {
@ -83,17 +88,14 @@ func (suite *vaultTestSuite) TestGetVaultAccountSupplied() {
// Before deposit, account supplied is 0 // Before deposit, account supplied is 0
_, err := suite.Keeper.GetVaultAccountSupplied(suite.Ctx, acc1.GetAddress()) _, found := suite.Keeper.GetVaultShareRecord(suite.Ctx, acc1.GetAddress())
suite.Require().Error(err) suite.Require().False(found)
suite.Require().ErrorIs(err, types.ErrVaultShareRecordNotFound)
_, err = suite.Keeper.GetVaultAccountSupplied(suite.Ctx, acc2.GetAddress()) _, found = suite.Keeper.GetVaultShareRecord(suite.Ctx, acc2.GetAddress())
suite.Require().Error(err) suite.Require().False(found)
suite.Require().ErrorIs(err, types.ErrVaultShareRecordNotFound)
// Deposits from both accounts // Deposits from both accounts
err := suite.Keeper.Deposit(suite.Ctx, acc1.GetAddress(), deposit1Amount)
err = suite.Keeper.Deposit(suite.Ctx, acc1.GetAddress(), deposit1Amount)
suite.Require().NoError(err) suite.Require().NoError(err)
err = suite.Keeper.Deposit(suite.Ctx, acc2.GetAddress(), deposit2Amount) err = suite.Keeper.Deposit(suite.Ctx, acc2.GetAddress(), deposit2Amount)
@ -101,15 +103,15 @@ func (suite *vaultTestSuite) TestGetVaultAccountSupplied() {
// Check balances // Check balances
vaultAcc1Supplied, err := suite.Keeper.GetVaultAccountSupplied(suite.Ctx, acc1.GetAddress()) vaultAcc1Supplied, found := suite.Keeper.GetVaultShareRecord(suite.Ctx, acc1.GetAddress())
suite.Require().NoError(err) suite.Require().True(found)
vaultAcc2Supplied, err := suite.Keeper.GetVaultAccountSupplied(suite.Ctx, acc2.GetAddress()) vaultAcc2Supplied, found := suite.Keeper.GetVaultShareRecord(suite.Ctx, acc2.GetAddress())
suite.Require().NoError(err) suite.Require().True(found)
// Account supply only includes the deposit from respective accounts // Account supply only includes the deposit from respective accounts
suite.Equal(sdk.NewCoins(deposit1Amount), vaultAcc1Supplied) suite.Equal(deposit1Amount.Amount.ToDec(), vaultAcc1Supplied.Shares.AmountOf(vaultDenom))
suite.Equal(sdk.NewCoins(deposit1Amount), vaultAcc2Supplied) suite.Equal(deposit1Amount.Amount.ToDec(), vaultAcc2Supplied.Shares.AmountOf(vaultDenom))
} }
func (suite *vaultTestSuite) TestGetVaultAccountValue() { func (suite *vaultTestSuite) TestGetVaultAccountValue() {
@ -135,7 +137,7 @@ func (suite *vaultTestSuite) TestGetVaultAccountValue_VaultNotFound() {
_, err := suite.Keeper.GetVaultAccountValue(suite.Ctx, vaultDenom, acc.GetAddress()) _, err := suite.Keeper.GetVaultAccountValue(suite.Ctx, vaultDenom, acc.GetAddress())
suite.Require().Error(err) 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() { func (suite *vaultTestSuite) TestGetVaultAccountValue_ShareNotFound() {
@ -155,87 +157,5 @@ func (suite *vaultTestSuite) TestGetVaultAccountValue_ShareNotFound() {
// Query from acc2 with no share record // Query from acc2 with no share record
_, err = suite.Keeper.GetVaultAccountValue(suite.Ctx, vaultDenom, acc2.GetAddress()) _, err = suite.Keeper.GetVaultAccountValue(suite.Ctx, vaultDenom, acc2.GetAddress())
suite.Require().Error(err) suite.Require().Error(err)
suite.Require().ErrorIs(err, types.ErrVaultShareRecordNotFound) suite.Require().Equal("account vault share record for usdx not found", err.Error())
}
// ----------------------------------------------------------------------------
// 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")
} }

View File

@ -28,34 +28,48 @@ func (k *Keeper) Withdraw(ctx sdk.Context, from sdk.AccAddress, wantAmount sdk.C
return types.ErrVaultRecordNotFound 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 // Get account share record for the vault
vaultShareRecord, found := k.GetVaultShareRecord(ctx, from) vaultShareRecord, found := k.GetVaultShareRecord(ctx, from)
if !found { if !found {
return types.ErrVaultShareRecordNotFound return types.ErrVaultShareRecordNotFound
} }
// Percent of vault account value the account is withdrawing withdrawShares, err := k.ConvertToShares(ctx, wantAmount)
// This is the total account value, not just the supplied amount. if err != nil {
withdrawAmountPercent := wantAmount.Amount.ToDec().Quo(vaultAccValue.Amount.ToDec()) return fmt.Errorf("failed to convert assets to shares: %w", err)
}
// Check if account is not withdrawing more than they have accCurrentShares := vaultShareRecord.Shares.AmountOf(wantAmount.Denom)
// account value < want withdraw amount // Check if account is not withdrawing more shares than they have
if vaultAccValue.Amount.LT(wantAmount.Amount) { if accCurrentShares.LT(withdrawShares.Amount) {
return sdkerrors.Wrapf( return sdkerrors.Wrapf(
types.ErrInsufficientValue, types.ErrInsufficientValue,
"account vault value of %s is less than %s desired withdraw amount", "account has less %s vault shares than withdraw shares, %s < %s",
vaultAccValue, wantAmount.Denom,
wantAmount, 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 // Not necessary to check if amount denom is allowed for the strategy, as
// there would be no vault record if it weren't allowed. // there would be no vault record if it weren't allowed.
// Withdraw the wantAmount from the strategy // Withdraw the withdrawAmount from the strategy
if err := strategy.Withdraw(ctx, wantAmount); err != nil { if err := strategy.Withdraw(ctx, withdrawAmount); err != nil {
return fmt.Errorf("failed to withdraw from strategy: %w", err) 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, ctx,
types.ModuleName, types.ModuleName,
from, from,
sdk.NewCoins(wantAmount), sdk.NewCoins(withdrawAmount),
); err != nil { ); err != nil {
return err return err
} }
// Shares withdrawn from vault // Check if new account balance of shares results in account share value
// For example: // of < 1 of a sdk.Coin. This share value is not able to be withdrawn and
// account supplied = 10hard // should just be removed.
// account value = 20hard isDust, err := k.ShareIsDust(
// wantAmount = 10hard ctx,
// withdrawAmountPercent = 10hard / 20hard = 0.5 vaultShareRecord.Shares.GetShare(withdrawAmount.Denom).Sub(withdrawShares),
// sharesWithdrawn = 0.5 * 10hard = 5hard )
vaultShareAmount := vaultShareRecord.AmountSupplied.AmountOf(wantAmount.Denom) if err != nil {
sharesWithdrawn := sdk.NewCoin(wantAmount.Denom, vaultShareAmount. return err
ToDec(). }
Mul(withdrawAmountPercent).
TruncateInt())
// Decrement VaultRecord and VaultShareRecord supplies if isDust {
vaultRecord.TotalSupply = vaultRecord.TotalSupply.Sub(sharesWithdrawn) // Modify withdrawShares to subtract entire share balance for denom
vaultShareRecord.AmountSupplied = vaultShareRecord.AmountSupplied.Sub(sdk.NewCoins(sharesWithdrawn)) // 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 // Update VaultRecord and VaultShareRecord, deletes if zero supply
k.UpdateVaultRecord(ctx, vaultRecord) k.UpdateVaultRecord(ctx, vaultRecord)
@ -108,9 +128,10 @@ func (k *Keeper) Withdraw(ctx sdk.Context, from sdk.AccAddress, wantAmount sdk.C
ctx.EventManager().EmitEvent( ctx.EventManager().EmitEvent(
sdk.NewEvent( sdk.NewEvent(
types.EventTypeVaultWithdraw, types.EventTypeVaultWithdraw,
sdk.NewAttribute(types.AttributeKeyVaultDenom, wantAmount.Denom), sdk.NewAttribute(types.AttributeKeyVaultDenom, withdrawAmount.Denom),
sdk.NewAttribute(types.AttributeKeyOwner, from.String()), 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()),
), ),
) )

View File

@ -76,7 +76,9 @@ func (suite *withdrawTestSuite) TestWithdraw_NoVaultShareRecord() {
) )
suite.VaultTotalValuesEqual(sdk.NewCoins(acc1DepositAmount)) 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() { func (suite *withdrawTestSuite) TestWithdraw_ExceedBalance() {
@ -103,7 +105,9 @@ func (suite *withdrawTestSuite) TestWithdraw_ExceedBalance() {
) )
suite.VaultTotalValuesEqual(sdk.NewCoins(depositAmount)) 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() { func (suite *withdrawTestSuite) TestWithdraw_Zero() {

View File

@ -256,21 +256,29 @@ func (suite *Suite) VaultTotalValuesEqual(expected sdk.Coins) {
} }
} }
func (suite *Suite) VaultTotalSuppliedEqual(expected sdk.Coins) { func (suite *Suite) VaultTotalSharesEqual(expected types.VaultShares) {
for _, coin := range expected { for _, share := range expected {
vaultBal, err := suite.Keeper.GetVaultTotalSupplied(suite.Ctx, coin.Denom) vaultBal, found := suite.Keeper.GetVaultTotalShares(suite.Ctx, share.Denom)
suite.Require().NoError(err, "failed to get vault balance") suite.Require().Truef(found, "%s vault does not exist", share.Denom)
suite.Require().Equal(coin, vaultBal) 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 { for i, acc := range accs {
coins := supplies[i] coins := supplies[i]
accVaultBal, err := suite.Keeper.GetVaultAccountSupplied(suite.Ctx, acc) accVaultBal, found := suite.Keeper.GetVaultAccountShares(suite.Ctx, acc)
suite.Require().NoError(err) suite.Require().True(found)
suite.Require().True(coins.IsEqual(accVaultBal), "expected account vault balance to equal coins %s, but got %s", coins, accVaultBal)
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,
)
}
} }
} }

View File

@ -26,10 +26,3 @@ func NewQueryDepositsRequest(
Pagination: pagination, Pagination: pagination,
} }
} }
// NewQueryTotalDepositedRequest returns a new QueryTotalDepositedRequest
func NewQueryTotalDepositedRequest(denom string) *QueryTotalDepositedRequest {
return &QueryTotalDepositedRequest{
Denom: denom,
}
}

View File

@ -193,8 +193,8 @@ type VaultResponse struct {
Denom string `protobuf:"bytes,1,opt,name=denom,proto3" json:"denom,omitempty"` Denom string `protobuf:"bytes,1,opt,name=denom,proto3" json:"denom,omitempty"`
// VaultStrategy is the strategy used for this vault. // VaultStrategy is the strategy used for this vault.
VaultStrategy StrategyType `protobuf:"varint,2,opt,name=vault_strategy,json=vaultStrategy,proto3,enum=kava.earn.v1beta1.StrategyType" json:"vault_strategy,omitempty"` 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. // TotalShares is the total amount of shares issued to depositors.
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 string `protobuf:"bytes,3,opt,name=total_shares,json=totalShares,proto3" json:"total_shares,omitempty"`
// TotalValue is the total value of denom coins supplied to the vault if the // TotalValue is the total value of denom coins supplied to the vault if the
// vault were to be liquidated. // 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"` 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 { type DepositResponse struct {
// depositor represents the owner of the deposit. // depositor represents the owner of the deposit.
Depositor string `protobuf:"bytes,1,opt,name=depositor,proto3" json:"depositor,omitempty"` Depositor string `protobuf:"bytes,1,opt,name=depositor,proto3" json:"depositor,omitempty"`
// Amount represents the amount supplied to vaults. // Shares represent the issued shares from their corresponding 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 VaultShares `protobuf:"bytes,2,rep,name=shares,proto3,castrepeated=VaultShares" json:"shares"`
// Value represents the total accumulated value of denom coins supplied to // Value represents the total accumulated value of denom coins supplied to
// vaults. This may be greater than or equal to amount_supplied depending on // vaults. This may be greater than or equal to amount_supplied depending on
// the strategy. // the strategy.
@ -362,83 +362,6 @@ func (m *DepositResponse) XXX_DiscardUnknown() {
var xxx_messageInfo_DepositResponse proto.InternalMessageInfo 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() { func init() {
proto.RegisterType((*QueryParamsRequest)(nil), "kava.earn.v1beta1.QueryParamsRequest") proto.RegisterType((*QueryParamsRequest)(nil), "kava.earn.v1beta1.QueryParamsRequest")
proto.RegisterType((*QueryParamsResponse)(nil), "kava.earn.v1beta1.QueryParamsResponse") proto.RegisterType((*QueryParamsResponse)(nil), "kava.earn.v1beta1.QueryParamsResponse")
@ -448,67 +371,60 @@ func init() {
proto.RegisterType((*QueryDepositsRequest)(nil), "kava.earn.v1beta1.QueryDepositsRequest") proto.RegisterType((*QueryDepositsRequest)(nil), "kava.earn.v1beta1.QueryDepositsRequest")
proto.RegisterType((*QueryDepositsResponse)(nil), "kava.earn.v1beta1.QueryDepositsResponse") proto.RegisterType((*QueryDepositsResponse)(nil), "kava.earn.v1beta1.QueryDepositsResponse")
proto.RegisterType((*DepositResponse)(nil), "kava.earn.v1beta1.DepositResponse") 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) } func init() { proto.RegisterFile("kava/earn/v1beta1/query.proto", fileDescriptor_63f8dee2f3192a6b) }
var fileDescriptor_63f8dee2f3192a6b = []byte{ var fileDescriptor_63f8dee2f3192a6b = []byte{
// 833 bytes of a gzipped FileDescriptorProto // 762 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x55, 0x4f, 0x6f, 0xd3, 0x48, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x55, 0xcf, 0x4f, 0x13, 0x4f,
0x14, 0x8f, 0xd3, 0x26, 0x6a, 0x27, 0x4a, 0xaa, 0x9d, 0xcd, 0x4a, 0x49, 0xba, 0x75, 0x52, 0x57, 0x14, 0xef, 0xb6, 0xb4, 0x81, 0xe9, 0x17, 0xbe, 0x71, 0xa8, 0x49, 0x5b, 0x64, 0x5b, 0x96, 0x08,
0xdb, 0x66, 0xab, 0x8d, 0xbd, 0xcd, 0x4a, 0xbb, 0x97, 0xd5, 0x4a, 0x9b, 0xad, 0x16, 0xf5, 0x82, 0x95, 0xa4, 0xbb, 0x52, 0x13, 0xbd, 0x18, 0x13, 0x2b, 0xd1, 0xe0, 0xc1, 0xe8, 0xa2, 0x1c, 0x4c,
0xc0, 0x2d, 0x3d, 0x20, 0xa1, 0x68, 0x12, 0x8f, 0x8c, 0xd5, 0xc4, 0xe3, 0xda, 0x93, 0x40, 0x41, 0x4c, 0x33, 0xa5, 0x93, 0x65, 0x43, 0xbb, 0xb3, 0xec, 0x4c, 0xab, 0x68, 0xbc, 0x70, 0x37, 0x31,
0x5c, 0xfa, 0x09, 0x40, 0x7c, 0x03, 0x40, 0x1c, 0xb8, 0x21, 0xfa, 0x21, 0x7a, 0xac, 0xca, 0x05, 0xf1, 0x5f, 0x30, 0x1e, 0x3c, 0xf3, 0x47, 0x70, 0x24, 0x78, 0x31, 0x1e, 0x50, 0xc1, 0xbb, 0x57,
0x71, 0x28, 0xd0, 0xf2, 0x41, 0x90, 0xe7, 0x4f, 0x52, 0x27, 0x0e, 0xe9, 0xa1, 0xa7, 0x64, 0xe6, 0x8f, 0x66, 0x7e, 0x2c, 0x65, 0xdb, 0x6d, 0xea, 0xa9, 0x9d, 0xf7, 0xe3, 0xf3, 0xf9, 0xbc, 0x37,
0xbd, 0xf7, 0xfb, 0xfd, 0xe6, 0xcd, 0x6f, 0x9e, 0xc1, 0xd2, 0x1e, 0xea, 0x23, 0x03, 0x23, 0xdf, 0x6f, 0xde, 0x82, 0xf9, 0x1d, 0xd4, 0x43, 0x16, 0x46, 0x81, 0x67, 0xf5, 0x56, 0x9b, 0x98, 0xa1,
0x35, 0xfa, 0x1b, 0x2d, 0x4c, 0xd1, 0x86, 0xb1, 0xdf, 0xc3, 0xfe, 0x81, 0xee, 0xf9, 0x84, 0x12, 0x55, 0x6b, 0xb7, 0x8b, 0x83, 0x3d, 0xd3, 0x0f, 0x08, 0x23, 0xf0, 0x12, 0x77, 0x9b, 0xdc, 0x6d,
0xf8, 0x43, 0x18, 0xd6, 0xc3, 0xb0, 0x2e, 0xc2, 0xa5, 0x62, 0x9b, 0x04, 0x5d, 0x12, 0x34, 0x59, 0x2a, 0x77, 0xb1, 0xb0, 0x45, 0x68, 0x87, 0xd0, 0x86, 0x08, 0xb0, 0xe4, 0x41, 0x46, 0x17, 0x57,
0x82, 0xc1, 0x17, 0x3c, 0xbb, 0xb4, 0xce, 0x57, 0x46, 0x0b, 0x05, 0x98, 0xc3, 0x0c, 0x40, 0x3d, 0xe4, 0xc9, 0x6a, 0x22, 0x8a, 0x25, 0xcc, 0x39, 0xa8, 0x8f, 0x1c, 0xd7, 0x43, 0xcc, 0x25, 0x9e,
0x64, 0x3b, 0x2e, 0xa2, 0x0e, 0x71, 0x45, 0xae, 0x7a, 0x39, 0x57, 0x66, 0xb5, 0x89, 0x23, 0xe3, 0x8a, 0xd5, 0x2f, 0xc6, 0x86, 0x51, 0x5b, 0xc4, 0x0d, 0xfd, 0x39, 0x87, 0x38, 0x44, 0x72, 0xf0,
0x79, 0x9b, 0xd8, 0x84, 0x73, 0x84, 0xff, 0xc4, 0xee, 0xcf, 0x36, 0x21, 0x76, 0x07, 0x1b, 0xc8, 0x7f, 0xca, 0x7a, 0xc5, 0x21, 0xc4, 0x69, 0x63, 0x0b, 0xf9, 0xae, 0x85, 0x3c, 0x8f, 0x30, 0x01,
0x73, 0x0c, 0xe4, 0xba, 0x84, 0x32, 0x48, 0xc9, 0xaf, 0x8e, 0x1f, 0xc6, 0x43, 0x3e, 0xea, 0xca, 0x19, 0xf2, 0xeb, 0xc3, 0xc5, 0xf8, 0x28, 0x40, 0x9d, 0xd0, 0x5f, 0x1e, 0xf6, 0x53, 0x16, 0x20,
0x78, 0x65, 0x3c, 0x1e, 0x50, 0x1f, 0x51, 0x6c, 0x8b, 0xf3, 0x6a, 0x79, 0x00, 0x6f, 0x87, 0xba, 0x86, 0x1d, 0x55, 0x6f, 0x31, 0xa6, 0x1d, 0x3d, 0xd4, 0x6d, 0x33, 0xe9, 0x36, 0x72, 0x00, 0x3e,
0x6f, 0xb1, 0x32, 0x13, 0xef, 0xf7, 0x70, 0x40, 0xb5, 0x9b, 0xe0, 0xc7, 0xc8, 0x6e, 0xe0, 0x11, 0xe1, 0x65, 0x3d, 0x16, 0xa8, 0x36, 0xde, 0xed, 0x62, 0xca, 0x8c, 0x47, 0x60, 0x36, 0x62, 0xa5,
0x37, 0xc0, 0xf0, 0x2f, 0x90, 0xe6, 0xf0, 0x05, 0xa5, 0xa2, 0x54, 0x33, 0xf5, 0xa2, 0x3e, 0xd6, 0x3e, 0xf1, 0x28, 0x86, 0xb7, 0x40, 0x46, 0xb2, 0xe7, 0xb5, 0xb2, 0x56, 0xc9, 0xd6, 0x0a, 0xe6,
0x2d, 0x9d, 0x97, 0x34, 0x66, 0x8f, 0xcf, 0xca, 0x09, 0x53, 0xa4, 0x6b, 0xeb, 0x82, 0x65, 0x17, 0x50, 0x33, 0x4d, 0x99, 0x52, 0x9f, 0x38, 0x3c, 0x29, 0x25, 0x6c, 0x15, 0x6e, 0xac, 0x28, 0x96,
0xf5, 0x3a, 0x54, 0xb2, 0xc0, 0x3c, 0x48, 0x59, 0xd8, 0x25, 0x5d, 0x86, 0x36, 0x6f, 0xf2, 0x85, 0x4d, 0xce, 0x1c, 0xb2, 0xc0, 0x1c, 0x48, 0xb7, 0xb0, 0x47, 0x3a, 0x02, 0x6d, 0xca, 0x96, 0x07,
0x76, 0x47, 0x70, 0xcb, 0x5c, 0xc1, 0xfd, 0x0f, 0x48, 0xf7, 0xd9, 0x4e, 0x41, 0xa9, 0xcc, 0x54, 0xe3, 0x99, 0xe2, 0x0e, 0x63, 0x15, 0xf7, 0x1d, 0x90, 0x11, 0xba, 0x39, 0x77, 0xaa, 0x92, 0xad,
0x33, 0xf5, 0x4a, 0x0c, 0x37, 0x2b, 0x91, 0x15, 0x52, 0x02, 0xaf, 0xd2, 0xde, 0x26, 0x41, 0x36, 0x95, 0x63, 0xb8, 0x45, 0x4a, 0x98, 0x11, 0x4a, 0x90, 0x59, 0xc6, 0x6f, 0x0d, 0x4c, 0x47, 0xfc,
0x12, 0x8f, 0xa7, 0x87, 0xff, 0x83, 0x1c, 0xab, 0x68, 0xca, 0x46, 0x15, 0x92, 0x15, 0xa5, 0x9a, 0xf1, 0xf4, 0xf0, 0x3e, 0x98, 0x11, 0x19, 0x8d, 0xb0, 0x8f, 0xf9, 0x64, 0x59, 0xab, 0xcc, 0xd4,
0xab, 0x97, 0x63, 0xf8, 0xb6, 0x45, 0xca, 0xce, 0x81, 0x87, 0xcd, 0x2c, 0x2b, 0x93, 0x5b, 0xb0, 0x4a, 0x31, 0x7c, 0x1b, 0x2a, 0xe4, 0xe9, 0x9e, 0x8f, 0xed, 0x69, 0x91, 0x16, 0x9a, 0xe0, 0x02,
0x0d, 0x72, 0x94, 0x50, 0xd4, 0x69, 0x06, 0x3d, 0xcf, 0xeb, 0x38, 0xd8, 0x2a, 0xcc, 0x84, 0x34, 0xf8, 0x8f, 0x11, 0x86, 0xda, 0x0d, 0xba, 0x8d, 0x02, 0x4c, 0xf3, 0x29, 0x41, 0x92, 0x15, 0xb6,
0x8d, 0xbf, 0x43, 0x55, 0x1f, 0xcf, 0xca, 0xab, 0xb6, 0x43, 0xef, 0xf7, 0x5a, 0x7a, 0x9b, 0x74, 0x0d, 0x61, 0x82, 0x2f, 0x80, 0x3c, 0x36, 0x7a, 0xa8, 0xdd, 0xc5, 0xf9, 0x09, 0x1e, 0x51, 0xbf,
0x85, 0xa7, 0xc4, 0x4f, 0x2d, 0xb0, 0xf6, 0x0c, 0x7a, 0xe0, 0xe1, 0x40, 0xdf, 0x72, 0xe9, 0xe9, 0xcd, 0x55, 0x7f, 0x3b, 0x29, 0x2d, 0x39, 0x2e, 0xdb, 0xee, 0x36, 0xcd, 0x2d, 0xd2, 0x51, 0x23,
0x51, 0x0d, 0x08, 0xcb, 0x6d, 0xb9, 0xd4, 0xcc, 0x32, 0xcc, 0x6d, 0x01, 0x09, 0xef, 0x81, 0x0c, 0xa9, 0x7e, 0xaa, 0xb4, 0xb5, 0x63, 0xb1, 0x3d, 0x1f, 0x53, 0x73, 0xdd, 0x63, 0xc7, 0x07, 0x55,
0x27, 0xe9, 0xa3, 0x4e, 0x0f, 0x17, 0x66, 0xaf, 0x81, 0x01, 0x30, 0xc0, 0xdd, 0x10, 0x4f, 0x7b, 0xa0, 0x26, 0x76, 0xdd, 0x63, 0x36, 0x10, 0x80, 0x9b, 0x1c, 0xcf, 0xf8, 0xa8, 0x81, 0x9c, 0xe8,
0xa5, 0x80, 0x3c, 0xbb, 0x8b, 0x4d, 0xec, 0x91, 0xc0, 0x19, 0xde, 0x9c, 0x0e, 0x52, 0xe4, 0x81, 0xe4, 0x1a, 0xf6, 0x09, 0x75, 0xfb, 0x7d, 0x37, 0x41, 0x9a, 0xbc, 0xf4, 0x70, 0x20, 0x0b, 0xaf,
0x8b, 0x7d, 0xde, 0xba, 0x46, 0xe1, 0xf4, 0xa8, 0x96, 0x17, 0x18, 0xff, 0x5a, 0x96, 0x8f, 0x83, 0xe7, 0x8f, 0x0f, 0xaa, 0x39, 0x85, 0x71, 0xb7, 0xd5, 0x0a, 0x30, 0xa5, 0x1b, 0x2c, 0x70, 0x3d,
0x60, 0x9b, 0xfa, 0x8e, 0x6b, 0x9b, 0x3c, 0x6d, 0xd8, 0xea, 0x64, 0xb4, 0xd5, 0x60, 0xf8, 0x4a, 0xc7, 0x96, 0x61, 0xfd, 0x46, 0x25, 0xa3, 0x8d, 0x02, 0xfd, 0x27, 0x20, 0xca, 0xcb, 0xd6, 0x96,
0x58, 0x7b, 0x32, 0xf5, 0x55, 0x5d, 0xe0, 0x84, 0xcf, 0x44, 0xe7, 0x2f, 0x73, 0x68, 0x2d, 0x1b, 0x4c, 0x85, 0xc3, 0xdf, 0x80, 0x29, 0x9f, 0x5d, 0x7f, 0x30, 0x1c, 0xac, 0x14, 0xd8, 0x17, 0x32,
0x0b, 0x05, 0xe6, 0xa5, 0x4a, 0xed, 0xb5, 0x02, 0x7e, 0x1a, 0x91, 0x29, 0xae, 0x78, 0x13, 0xcc, 0x8d, 0x4f, 0x1a, 0xb8, 0x3c, 0x20, 0x53, 0x5d, 0xd0, 0x1a, 0x98, 0x6c, 0x29, 0x9b, 0xba, 0x74,
0x59, 0x62, 0x4f, 0xd8, 0x46, 0x8b, 0xb9, 0x46, 0x51, 0x36, 0x62, 0x9c, 0x41, 0x25, 0xbc, 0x11, 0x23, 0xe6, 0x12, 0x54, 0xda, 0xc0, 0xb5, 0x9f, 0x67, 0xc2, 0x07, 0x11, 0x9d, 0x49, 0xa1, 0x73,
0xd1, 0x99, 0x64, 0x3a, 0xd7, 0xa6, 0xea, 0xe4, 0x60, 0x11, 0xa1, 0x2f, 0x92, 0x60, 0x61, 0x84, 0x79, 0xac, 0x4e, 0x09, 0x16, 0x11, 0xfa, 0x47, 0x03, 0xff, 0x0f, 0x90, 0xc1, 0x9b, 0x60, 0x4a,
0x0c, 0xfe, 0x09, 0xe6, 0x05, 0x11, 0x99, 0xde, 0xce, 0x61, 0x2a, 0xa4, 0x60, 0x01, 0x75, 0x49, 0x11, 0x91, 0xf1, 0xed, 0xec, 0x87, 0xc2, 0x87, 0x20, 0xa3, 0xe6, 0x22, 0x29, 0x0a, 0x9b, 0x1f,
0xcf, 0xa5, 0x43, 0x83, 0x25, 0xd9, 0x09, 0x8b, 0x11, 0x65, 0x52, 0xd3, 0x7f, 0xc4, 0x71, 0x1b, 0x35, 0xcd, 0x62, 0x54, 0xea, 0xb3, 0xbc, 0xa6, 0xcf, 0xdf, 0x4b, 0xd9, 0xbe, 0x8d, 0xda, 0x0a,
0xbf, 0x87, 0x07, 0x7b, 0xf3, 0xa9, 0x5c, 0xbd, 0x82, 0x33, 0xc2, 0x82, 0xc0, 0xcc, 0x71, 0x8e, 0x01, 0x22, 0x90, 0x96, 0x03, 0x94, 0x12, 0x50, 0x85, 0x48, 0x6d, 0x21, 0xd8, 0x3d, 0xe2, 0x7a,
0x81, 0xe1, 0x10, 0x48, 0x71, 0xab, 0xcd, 0x5c, 0x3f, 0x17, 0x47, 0xd6, 0xea, 0xa0, 0xc4, 0x2e, 0xf5, 0xeb, 0x0a, 0xa6, 0xf2, 0x0f, 0xb3, 0xc5, 0x13, 0xa8, 0x2d, 0x91, 0x6b, 0xef, 0x52, 0x20,
0x73, 0x27, 0xf4, 0xa1, 0xe8, 0x16, 0xb6, 0xbe, 0x3f, 0x33, 0x9e, 0x29, 0x60, 0x31, 0xb6, 0x48, 0x2d, 0xee, 0x08, 0xbe, 0x06, 0x19, 0xf9, 0xc2, 0xe1, 0xd5, 0x18, 0xc9, 0xc3, 0xab, 0xa4, 0xb8,
0x34, 0xd9, 0x07, 0x39, 0xd9, 0xa5, 0x66, 0x38, 0x72, 0xa5, 0x1b, 0xae, 0x55, 0x7f, 0x56, 0x52, 0x34, 0x2e, 0x4c, 0x76, 0xd2, 0x58, 0xd8, 0xff, 0xf2, 0xeb, 0x43, 0x72, 0x0e, 0x16, 0xac, 0x51,
0xb0, 0x65, 0xfd, 0xdd, 0x2c, 0x48, 0x31, 0x4d, 0xf0, 0x11, 0x48, 0xf3, 0xa9, 0x08, 0x7f, 0x89, 0x2b, 0x0f, 0xee, 0x6b, 0x20, 0x23, 0xb7, 0xc2, 0x68, 0xf2, 0xc8, 0x86, 0x19, 0x4d, 0x1e, 0x5d,
0x71, 0xdf, 0xf8, 0xf8, 0x2d, 0xad, 0x4e, 0x4b, 0xe3, 0xc7, 0xd2, 0x96, 0x0f, 0xdf, 0x7f, 0x7d, 0x2e, 0xc6, 0x35, 0x41, 0xbe, 0x08, 0x17, 0xac, 0x11, 0xdb, 0x92, 0x5a, 0x6f, 0xc4, 0xd4, 0xbf,
0x9e, 0x5c, 0x84, 0x45, 0x63, 0xd2, 0x77, 0x00, 0x1e, 0x2a, 0x20, 0xcd, 0x27, 0xe9, 0x64, 0xf2, 0xe5, 0x22, 0x26, 0xc3, 0x49, 0x85, 0xcb, 0xa3, 0xf0, 0x07, 0x9e, 0x5c, 0xb1, 0x32, 0x3e, 0x50,
0xc8, 0x54, 0x9e, 0x4c, 0x1e, 0x1d, 0xc8, 0xda, 0xaf, 0x8c, 0x7c, 0x05, 0x2e, 0xc7, 0x90, 0xf3, 0x49, 0x59, 0x14, 0x52, 0xe6, 0xe1, 0x5c, 0x8c, 0x94, 0x70, 0xa6, 0xeb, 0x6b, 0x87, 0x3f, 0xf5,
0x99, 0x6b, 0x3c, 0x66, 0xb7, 0xf3, 0x24, 0x14, 0x31, 0x27, 0xdf, 0x26, 0x5c, 0x9b, 0x84, 0x3f, 0xc4, 0xe1, 0xa9, 0xae, 0x1d, 0x9d, 0xea, 0xda, 0x8f, 0x53, 0x5d, 0x7b, 0x7f, 0xa6, 0x27, 0x8e,
0x32, 0x64, 0x4a, 0xd5, 0xe9, 0x89, 0x42, 0xca, 0x0a, 0x93, 0xb2, 0x04, 0x17, 0x63, 0xa4, 0x0c, 0xce, 0xf4, 0xc4, 0xd7, 0x33, 0x3d, 0xf1, 0xfc, 0xe2, 0xea, 0xe0, 0x20, 0xd5, 0x36, 0x6a, 0x52,
0x5e, 0xf1, 0x4b, 0x05, 0xe4, 0xa2, 0xf6, 0x80, 0xb5, 0x49, 0x0c, 0xb1, 0xde, 0x2b, 0xe9, 0x57, 0x09, 0xf7, 0x4a, 0x02, 0x8a, 0x2b, 0x6e, 0x66, 0xc4, 0x27, 0xe0, 0xc6, 0xdf, 0x00, 0x00, 0x00,
0x4d, 0x17, 0xb2, 0xea, 0x4c, 0xd6, 0x6f, 0x70, 0x3d, 0x46, 0x16, 0x9b, 0xb2, 0x35, 0x4b, 0xd6, 0xff, 0xff, 0x27, 0x75, 0x39, 0xf4, 0x32, 0x07, 0x00, 0x00,
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,
} }
// Reference imports to suppress errors if they are not otherwise used. // 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) Vaults(ctx context.Context, in *QueryVaultsRequest, opts ...grpc.CallOption) (*QueryVaultsResponse, error)
// Deposits queries deposit details based on owner address and vault // Deposits queries deposit details based on owner address and vault
Deposits(ctx context.Context, in *QueryDepositsRequest, opts ...grpc.CallOption) (*QueryDepositsResponse, error) 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 { type queryClient struct {
@ -568,15 +482,6 @@ func (c *queryClient) Deposits(ctx context.Context, in *QueryDepositsRequest, op
return out, nil 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. // QueryServer is the server API for Query service.
type QueryServer interface { type QueryServer interface {
// Params queries all parameters of the earn module. // Params queries all parameters of the earn module.
@ -585,8 +490,6 @@ type QueryServer interface {
Vaults(context.Context, *QueryVaultsRequest) (*QueryVaultsResponse, error) Vaults(context.Context, *QueryVaultsRequest) (*QueryVaultsResponse, error)
// Deposits queries deposit details based on owner address and vault // Deposits queries deposit details based on owner address and vault
Deposits(context.Context, *QueryDepositsRequest) (*QueryDepositsResponse, error) 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. // 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) { func (*UnimplementedQueryServer) Deposits(ctx context.Context, req *QueryDepositsRequest) (*QueryDepositsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Deposits not implemented") 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) { func RegisterQueryServer(s grpc1.Server, srv QueryServer) {
s.RegisterService(&_Query_serviceDesc, srv) 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) 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{ var _Query_serviceDesc = grpc.ServiceDesc{
ServiceName: "kava.earn.v1beta1.Query", ServiceName: "kava.earn.v1beta1.Query",
HandlerType: (*QueryServer)(nil), HandlerType: (*QueryServer)(nil),
@ -698,10 +580,6 @@ var _Query_serviceDesc = grpc.ServiceDesc{
MethodName: "Deposits", MethodName: "Deposits",
Handler: _Query_Deposits_Handler, Handler: _Query_Deposits_Handler,
}, },
{
MethodName: "TotalDeposited",
Handler: _Query_TotalDeposited_Handler,
},
}, },
Streams: []grpc.StreamDesc{}, Streams: []grpc.StreamDesc{},
Metadata: "kava/earn/v1beta1/query.proto", Metadata: "kava/earn/v1beta1/query.proto",
@ -860,16 +738,13 @@ func (m *VaultResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
} }
i-- i--
dAtA[i] = 0x22 dAtA[i] = 0x22
{ if len(m.TotalShares) > 0 {
size := m.TotalSupplied.Size() i -= len(m.TotalShares)
i -= size copy(dAtA[i:], m.TotalShares)
if _, err := m.TotalSupplied.MarshalTo(dAtA[i:]); err != nil { i = encodeVarintQuery(dAtA, i, uint64(len(m.TotalShares)))
return 0, err i--
} dAtA[i] = 0x1a
i = encodeVarintQuery(dAtA, i, uint64(size))
} }
i--
dAtA[i] = 0x1a
if m.VaultStrategy != 0 { if m.VaultStrategy != 0 {
i = encodeVarintQuery(dAtA, i, uint64(m.VaultStrategy)) i = encodeVarintQuery(dAtA, i, uint64(m.VaultStrategy))
i-- i--
@ -1017,10 +892,10 @@ func (m *DepositResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
dAtA[i] = 0x1a dAtA[i] = 0x1a
} }
} }
if len(m.AmountSupplied) > 0 { if len(m.Shares) > 0 {
for iNdEx := len(m.AmountSupplied) - 1; iNdEx >= 0; iNdEx-- { 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 { if err != nil {
return 0, err return 0, err
} }
@ -1041,73 +916,6 @@ func (m *DepositResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
return len(dAtA) - i, nil 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 { func encodeVarintQuery(dAtA []byte, offset int, v uint64) int {
offset -= sovQuery(v) offset -= sovQuery(v)
base := offset base := offset
@ -1180,8 +988,10 @@ func (m *VaultResponse) Size() (n int) {
if m.VaultStrategy != 0 { if m.VaultStrategy != 0 {
n += 1 + sovQuery(uint64(m.VaultStrategy)) n += 1 + sovQuery(uint64(m.VaultStrategy))
} }
l = m.TotalSupplied.Size() l = len(m.TotalShares)
n += 1 + l + sovQuery(uint64(l)) if l > 0 {
n += 1 + l + sovQuery(uint64(l))
}
l = m.TotalValue.Size() l = m.TotalValue.Size()
n += 1 + l + sovQuery(uint64(l)) n += 1 + l + sovQuery(uint64(l))
return n return n
@ -1237,8 +1047,8 @@ func (m *DepositResponse) Size() (n int) {
if l > 0 { if l > 0 {
n += 1 + l + sovQuery(uint64(l)) n += 1 + l + sovQuery(uint64(l))
} }
if len(m.AmountSupplied) > 0 { if len(m.Shares) > 0 {
for _, e := range m.AmountSupplied { for _, e := range m.Shares {
l = e.Size() l = e.Size()
n += 1 + l + sovQuery(uint64(l)) n += 1 + l + sovQuery(uint64(l))
} }
@ -1252,34 +1062,6 @@ func (m *DepositResponse) Size() (n int) {
return n 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) { func sovQuery(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7 return (math_bits.Len64(x|1) + 6) / 7
} }
@ -1667,7 +1449,7 @@ func (m *VaultResponse) Unmarshal(dAtA []byte) error {
} }
case 3: case 3:
if wireType != 2 { 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 var stringLen uint64
for shift := uint(0); ; shift += 7 { for shift := uint(0); ; shift += 7 {
@ -1695,9 +1477,7 @@ func (m *VaultResponse) Unmarshal(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
if err := m.TotalSupplied.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { m.TotalShares = string(dAtA[iNdEx:postIndex])
return err
}
iNdEx = postIndex iNdEx = postIndex
case 4: case 4:
if wireType != 2 { if wireType != 2 {
@ -2087,7 +1867,7 @@ func (m *DepositResponse) Unmarshal(dAtA []byte) error {
iNdEx = postIndex iNdEx = postIndex
case 2: case 2:
if wireType != 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 var msglen int
for shift := uint(0); ; shift += 7 { for shift := uint(0); ; shift += 7 {
@ -2114,8 +1894,8 @@ func (m *DepositResponse) Unmarshal(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
m.AmountSupplied = append(m.AmountSupplied, types.Coin{}) m.Shares = append(m.Shares, VaultShare{})
if err := m.AmountSupplied[len(m.AmountSupplied)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { if err := m.Shares[len(m.Shares)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err return err
} }
iNdEx = postIndex iNdEx = postIndex
@ -2174,172 +1954,6 @@ func (m *DepositResponse) Unmarshal(dAtA []byte) error {
} }
return nil 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) { func skipQuery(dAtA []byte) (n int, err error) {
l := len(dAtA) l := len(dAtA)
iNdEx := 0 iNdEx := 0

View File

@ -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". // RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
// UnaryRPC :call QueryServer directly. // UnaryRPC :call QueryServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. // 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 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 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_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_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 ( var (
@ -419,6 +323,4 @@ var (
forward_Query_Vaults_0 = runtime.ForwardResponseMessage forward_Query_Vaults_0 = runtime.ForwardResponseMessage
forward_Query_Deposits_0 = runtime.ForwardResponseMessage forward_Query_Deposits_0 = runtime.ForwardResponseMessage
forward_Query_TotalDeposited_0 = runtime.ForwardResponseMessage
) )

383
x/earn/types/share.go Normal file
View 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
View 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)
}
}
}

View File

@ -74,6 +74,7 @@ var xxx_messageInfo_MsgDeposit proto.InternalMessageInfo
// MsgDepositResponse defines the Msg/Deposit response type. // MsgDepositResponse defines the Msg/Deposit response type.
type MsgDepositResponse struct { type MsgDepositResponse struct {
Shares VaultShare `protobuf:"bytes,1,opt,name=shares,proto3" json:"shares"`
} }
func (m *MsgDepositResponse) Reset() { *m = MsgDepositResponse{} } func (m *MsgDepositResponse) Reset() { *m = MsgDepositResponse{} }
@ -109,6 +110,13 @@ func (m *MsgDepositResponse) XXX_DiscardUnknown() {
var xxx_messageInfo_MsgDepositResponse proto.InternalMessageInfo 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 // MsgWithdraw represents a message for withdrawing liquidity from a vault
type MsgWithdraw struct { type MsgWithdraw struct {
// from represents the address we are withdrawing for // 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. // MsgWithdrawResponse defines the Msg/Withdraw response type.
type MsgWithdrawResponse struct { type MsgWithdrawResponse struct {
Shares VaultShare `protobuf:"bytes,1,opt,name=shares,proto3" json:"shares"`
} }
func (m *MsgWithdrawResponse) Reset() { *m = MsgWithdrawResponse{} } func (m *MsgWithdrawResponse) Reset() { *m = MsgWithdrawResponse{} }
@ -188,6 +197,13 @@ func (m *MsgWithdrawResponse) XXX_DiscardUnknown() {
var xxx_messageInfo_MsgWithdrawResponse proto.InternalMessageInfo var xxx_messageInfo_MsgWithdrawResponse proto.InternalMessageInfo
func (m *MsgWithdrawResponse) GetShares() VaultShare {
if m != nil {
return m.Shares
}
return VaultShare{}
}
func init() { func init() {
proto.RegisterType((*MsgDeposit)(nil), "kava.earn.v1beta1.MsgDeposit") proto.RegisterType((*MsgDeposit)(nil), "kava.earn.v1beta1.MsgDeposit")
proto.RegisterType((*MsgDepositResponse)(nil), "kava.earn.v1beta1.MsgDepositResponse") 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) } func init() { proto.RegisterFile("kava/earn/v1beta1/tx.proto", fileDescriptor_2e9dcf48a3fa0009) }
var fileDescriptor_2e9dcf48a3fa0009 = []byte{ 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, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xca, 0x4e, 0x2c, 0x4b,
0xd4, 0x4f, 0x4d, 0x2c, 0xca, 0xd3, 0x2f, 0x33, 0x4c, 0x4a, 0x2d, 0x49, 0x34, 0xd4, 0x2f, 0xa9, 0xd4, 0x4f, 0x4d, 0x2c, 0xca, 0xd3, 0x2f, 0x33, 0x4c, 0x4a, 0x2d, 0x49, 0x34, 0xd4, 0x2f, 0xa9,
0xd0, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x04, 0xc9, 0xe9, 0x81, 0xe4, 0xf4, 0xa0, 0x72, 0xd0, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x04, 0xc9, 0xe9, 0x81, 0xe4, 0xf4, 0xa0, 0x72,
0x52, 0x92, 0xc9, 0xf9, 0xc5, 0xb9, 0xf9, 0xc5, 0xf1, 0x60, 0x05, 0xfa, 0x10, 0x0e, 0x44, 0xb5, 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, 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, 0x2f, 0x92, 0x9e, 0x9f, 0x9e, 0x0f, 0xd1, 0x07, 0x62, 0x41, 0x45, 0x65, 0x31, 0xed, 0x2f, 0x4b,
0x7c, 0x8b, 0xd3, 0x5d, 0x52, 0x0b, 0xf2, 0x8b, 0x33, 0x4b, 0x84, 0xcc, 0xb8, 0x38, 0x53, 0x20, 0x2c, 0xcd, 0x29, 0x81, 0x48, 0x2b, 0x35, 0x33, 0x72, 0x71, 0xf9, 0x16, 0xa7, 0xbb, 0xa4, 0x16,
0xcc, 0xfc, 0x22, 0x09, 0x46, 0x05, 0x46, 0x0d, 0x4e, 0x27, 0x89, 0x4b, 0x5b, 0x74, 0x45, 0xa0, 0xe4, 0x17, 0x67, 0x96, 0x08, 0x99, 0x71, 0x71, 0xa6, 0x40, 0x98, 0xf9, 0x45, 0x12, 0x8c, 0x0a,
0x36, 0x39, 0xa6, 0xa4, 0x14, 0xa5, 0x16, 0x17, 0x07, 0x97, 0x14, 0x65, 0xe6, 0xa5, 0x07, 0x21, 0x8c, 0x1a, 0x9c, 0x4e, 0x12, 0x97, 0xb6, 0xe8, 0x8a, 0x40, 0x1d, 0xe2, 0x98, 0x92, 0x52, 0x94,
0x94, 0x0a, 0x99, 0x73, 0xb1, 0x25, 0xe6, 0xe6, 0x97, 0xe6, 0x95, 0x48, 0x30, 0x29, 0x30, 0x6a, 0x5a, 0x5c, 0x1c, 0x5c, 0x52, 0x94, 0x99, 0x97, 0x1e, 0x84, 0x50, 0x2a, 0x64, 0xce, 0xc5, 0x96,
0x70, 0x1b, 0x49, 0xea, 0x41, 0x75, 0x80, 0x5c, 0x03, 0x73, 0xbd, 0x9e, 0x73, 0x7e, 0x66, 0x9e, 0x98, 0x9b, 0x5f, 0x9a, 0x57, 0x22, 0xc1, 0xa4, 0xc0, 0xa8, 0xc1, 0x6d, 0x24, 0xa9, 0x07, 0xd5,
0x13, 0xcb, 0x89, 0x7b, 0xf2, 0x0c, 0x41, 0x50, 0xe5, 0x56, 0x2c, 0x1d, 0x0b, 0xe4, 0x19, 0x94, 0x01, 0x72, 0x2c, 0xcc, 0x73, 0x7a, 0xce, 0xf9, 0x99, 0x79, 0x4e, 0x2c, 0x27, 0xee, 0xc9, 0x33,
0x44, 0xb8, 0x84, 0x10, 0x8e, 0x08, 0x4a, 0x2d, 0x2e, 0xc8, 0xcf, 0x2b, 0x4e, 0x55, 0xaa, 0xe2, 0x04, 0x41, 0x95, 0x5b, 0xb1, 0x74, 0x2c, 0x90, 0x67, 0x50, 0x0a, 0xe4, 0x12, 0x42, 0x38, 0x22,
0xe2, 0xf6, 0x2d, 0x4e, 0x0f, 0xcf, 0x2c, 0xc9, 0x48, 0x29, 0x4a, 0x2c, 0x17, 0xd2, 0xe1, 0x62, 0x28, 0xb5, 0xb8, 0x20, 0x3f, 0xaf, 0x38, 0x55, 0xc8, 0x9a, 0x8b, 0xad, 0x38, 0x23, 0xb1, 0x28,
0x49, 0x2b, 0xca, 0xcf, 0x25, 0xe8, 0x2c, 0xb0, 0x2a, 0x4a, 0x5d, 0x24, 0xca, 0x25, 0x8c, 0x64, 0xb5, 0x18, 0xec, 0x12, 0x6e, 0x23, 0x59, 0x3d, 0x8c, 0xf0, 0xd2, 0x0b, 0x03, 0xf9, 0x25, 0x18,
0x37, 0xcc, 0x49, 0x46, 0xab, 0x18, 0xb9, 0x98, 0x7d, 0x8b, 0xd3, 0x85, 0xfc, 0xb9, 0xd8, 0x61, 0xa4, 0x0a, 0x66, 0x30, 0x44, 0x8b, 0x52, 0x15, 0x17, 0xb7, 0x6f, 0x71, 0x7a, 0x78, 0x66, 0x49,
0x41, 0x26, 0xab, 0x87, 0x11, 0x4d, 0x7a, 0x08, 0xcf, 0x48, 0xa9, 0xe2, 0x95, 0x86, 0x19, 0x2c, 0x46, 0x4a, 0x51, 0x62, 0xb9, 0x90, 0x0e, 0x17, 0x4b, 0x5a, 0x51, 0x7e, 0x2e, 0x41, 0x3f, 0x81,
0x14, 0xc4, 0xc5, 0x01, 0xf7, 0xa8, 0x1c, 0x76, 0x2d, 0x30, 0x79, 0x29, 0x35, 0xfc, 0xf2, 0x30, 0x55, 0x51, 0xea, 0x9d, 0x20, 0x2e, 0x61, 0x24, 0xbb, 0xa9, 0xe2, 0x1f, 0xa3, 0x55, 0x8c, 0x5c,
0x33, 0x9d, 0x1c, 0x4e, 0x3c, 0x92, 0x63, 0xbc, 0xf0, 0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x39, 0xc6, 0xcc, 0xbe, 0xc5, 0xe9, 0x42, 0xfe, 0x5c, 0xec, 0xb0, 0xc8, 0xc2, 0xa6, 0x1f, 0x11, 0x8c, 0x52,
0x09, 0x8f, 0xe5, 0x18, 0x2e, 0x3c, 0x96, 0x63, 0xb8, 0xf1, 0x58, 0x8e, 0x21, 0x4a, 0x2d, 0x3d, 0xaa, 0x78, 0xa5, 0xe1, 0xae, 0x0a, 0xe2, 0xe2, 0x80, 0x87, 0x92, 0x1c, 0x76, 0x2d, 0x30, 0x79,
0xb3, 0x24, 0xa3, 0x34, 0x49, 0x2f, 0x39, 0x3f, 0x57, 0x1f, 0x64, 0x96, 0x6e, 0x4e, 0x62, 0x52, 0x29, 0x35, 0xfc, 0xf2, 0x30, 0x33, 0x9d, 0x1c, 0x4e, 0x3c, 0x92, 0x63, 0xbc, 0xf0, 0x48, 0x8e,
0x31, 0x98, 0xa5, 0x5f, 0x01, 0x49, 0x8c, 0x25, 0x95, 0x05, 0xa9, 0xc5, 0x49, 0x6c, 0xe0, 0x44, 0xf1, 0xc1, 0x23, 0x39, 0xc6, 0x09, 0x8f, 0xe5, 0x18, 0x2e, 0x3c, 0x96, 0x63, 0xb8, 0xf1, 0x58,
0x62, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0xc0, 0x48, 0xd0, 0x39, 0xa6, 0x02, 0x00, 0x00, 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. // Reference imports to suppress errors if they are not otherwise used.
@ -404,6 +423,16 @@ func (m *MsgDepositResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i _ = i
var l int var l int
_ = l _ = 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 return len(dAtA) - i, nil
} }
@ -467,6 +496,16 @@ func (m *MsgWithdrawResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i _ = i
var l int var l int
_ = l _ = 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 return len(dAtA) - i, nil
} }
@ -502,6 +541,8 @@ func (m *MsgDepositResponse) Size() (n int) {
} }
var l int var l int
_ = l _ = l
l = m.Shares.Size()
n += 1 + l + sovTx(uint64(l))
return n return n
} }
@ -526,6 +567,8 @@ func (m *MsgWithdrawResponse) Size() (n int) {
} }
var l int var l int
_ = l _ = l
l = m.Shares.Size()
n += 1 + l + sovTx(uint64(l))
return n 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) return fmt.Errorf("proto: MsgDepositResponse: illegal tag %d (wire type %d)", fieldNum, wire)
} }
switch fieldNum { 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: default:
iNdEx = preIndex iNdEx = preIndex
skippy, err := skipTx(dAtA[iNdEx:]) 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) return fmt.Errorf("proto: MsgWithdrawResponse: illegal tag %d (wire type %d)", fieldNum, wire)
} }
switch fieldNum { 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: default:
iNdEx = preIndex iNdEx = preIndex
skippy, err := skipTx(dAtA[iNdEx:]) skippy, err := skipTx(dAtA[iNdEx:])

View File

@ -8,32 +8,15 @@ import (
) )
// NewVaultRecord returns a new VaultRecord with 0 supply. // NewVaultRecord returns a new VaultRecord with 0 supply.
func NewVaultRecord(vaultDenom string) VaultRecord { func NewVaultRecord(vaultDenom string, amount sdk.Dec) VaultRecord {
return VaultRecord{ return VaultRecord{
Denom: vaultDenom, TotalShares: NewVaultShare(vaultDenom, amount),
TotalSupply: sdk.NewCoin(vaultDenom, sdk.ZeroInt()),
} }
} }
// Validate returns an error if a VaultRecord is invalid. // Validate returns an error if a VaultRecord is invalid.
func (vr *VaultRecord) Validate() error { func (vr *VaultRecord) Validate() error {
if err := sdk.ValidateDenom(vr.Denom); err != nil { return vr.TotalShares.Validate()
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
} }
// VaultRecords is a slice of VaultRecord. // VaultRecords is a slice of VaultRecord.
@ -48,11 +31,11 @@ func (vrs VaultRecords) Validate() error {
return err return err
} }
if denoms[vr.Denom] { if denoms[vr.TotalShares.Denom] {
return fmt.Errorf("duplicate vault denom %s", vr.Denom) return fmt.Errorf("duplicate vault denom %s", vr.TotalShares.Denom)
} }
denoms[vr.Denom] = true denoms[vr.TotalShares.Denom] = true
} }
return nil return nil
@ -60,10 +43,10 @@ func (vrs VaultRecords) Validate() error {
// NewVaultShareRecord returns a new VaultShareRecord with the provided supplied // NewVaultShareRecord returns a new VaultShareRecord with the provided supplied
// coins. // coins.
func NewVaultShareRecord(depositor sdk.AccAddress, supplied ...sdk.Coin) VaultShareRecord { func NewVaultShareRecord(depositor sdk.AccAddress, shares VaultShares) VaultShareRecord {
return VaultShareRecord{ return VaultShareRecord{
Depositor: depositor, Depositor: depositor,
AmountSupplied: sdk.NewCoins(supplied...), Shares: shares,
} }
} }
@ -73,8 +56,8 @@ func (vsr VaultShareRecord) Validate() error {
return fmt.Errorf("depositor is empty") return fmt.Errorf("depositor is empty")
} }
if err := vsr.AmountSupplied.Validate(); err != nil { if err := vsr.Shares.Validate(); err != nil {
return fmt.Errorf("invalid vault share record amount supplied: %w", err) return fmt.Errorf("invalid vault share record shares: %w", err)
} }
return nil return nil

View File

@ -6,8 +6,8 @@ package types
import ( import (
fmt "fmt" fmt "fmt"
_ "github.com/cosmos/cosmos-proto" _ "github.com/cosmos/cosmos-proto"
_ "github.com/cosmos/cosmos-sdk/types"
github_com_cosmos_cosmos_sdk_types "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" _ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto" proto "github.com/gogo/protobuf/proto"
io "io" io "io"
@ -82,15 +82,10 @@ func (m *AllowedVault) GetVaultStrategy() StrategyType {
return STRATEGY_TYPE_UNSPECIFIED return STRATEGY_TYPE_UNSPECIFIED
} }
// VaultRecord is the state of a vault and is used to store the state of a // VaultRecord is the state of a vault.
// vault.
type VaultRecord struct { type VaultRecord struct {
// Denom is the only supported denomination of the vault for deposits and // TotalShares is the total distributed number of shares in the vault.
// withdrawals. TotalShares VaultShare `protobuf:"bytes,1,opt,name=total_shares,json=totalShares,proto3" json:"total_shares"`
Denom string `protobuf:"bytes,1,opt,name=denom,proto3" json:"denom,omitempty"`
// TotalSupply is the total supply of the vault, denominated **only** in the
// user deposit/withdrawal denom, must be the same as the Denom field.
TotalSupply types.Coin `protobuf:"bytes,2,opt,name=total_supply,json=totalSupply,proto3" json:"total_supply"`
} }
func (m *VaultRecord) Reset() { *m = VaultRecord{} } func (m *VaultRecord) Reset() { *m = VaultRecord{} }
@ -126,27 +121,19 @@ func (m *VaultRecord) XXX_DiscardUnknown() {
var xxx_messageInfo_VaultRecord proto.InternalMessageInfo var xxx_messageInfo_VaultRecord proto.InternalMessageInfo
func (m *VaultRecord) GetDenom() string { func (m *VaultRecord) GetTotalShares() VaultShare {
if m != nil { if m != nil {
return m.Denom return m.TotalShares
} }
return "" return VaultShare{}
}
func (m *VaultRecord) GetTotalSupply() types.Coin {
if m != nil {
return m.TotalSupply
}
return types.Coin{}
} }
// VaultShareRecord defines the vault shares owned by a depositor. // VaultShareRecord defines the vault shares owned by a depositor.
type VaultShareRecord struct { type VaultShareRecord struct {
// Depositor represents the owner of the shares // 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"` 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 // Shares represent the vault shares owned by the depositor.
// vault. The vault is determined by the coin denom. Shares VaultShares `protobuf:"bytes,2,rep,name=shares,proto3,castrepeated=VaultShares" json:"shares"`
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"`
} }
func (m *VaultShareRecord) Reset() { *m = VaultShareRecord{} } func (m *VaultShareRecord) Reset() { *m = VaultShareRecord{} }
@ -189,50 +176,97 @@ func (m *VaultShareRecord) GetDepositor() github_com_cosmos_cosmos_sdk_types.Acc
return nil return nil
} }
func (m *VaultShareRecord) GetAmountSupplied() github_com_cosmos_cosmos_sdk_types.Coins { func (m *VaultShareRecord) GetShares() VaultShares {
if m != nil { if m != nil {
return m.AmountSupplied return m.Shares
} }
return nil 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() { func init() {
proto.RegisterType((*AllowedVault)(nil), "kava.earn.v1beta1.AllowedVault") proto.RegisterType((*AllowedVault)(nil), "kava.earn.v1beta1.AllowedVault")
proto.RegisterType((*VaultRecord)(nil), "kava.earn.v1beta1.VaultRecord") proto.RegisterType((*VaultRecord)(nil), "kava.earn.v1beta1.VaultRecord")
proto.RegisterType((*VaultShareRecord)(nil), "kava.earn.v1beta1.VaultShareRecord") 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) } func init() { proto.RegisterFile("kava/earn/v1beta1/vault.proto", fileDescriptor_884eb89509fbdc04) }
var fileDescriptor_884eb89509fbdc04 = []byte{ var fileDescriptor_884eb89509fbdc04 = []byte{
// 417 bytes of a gzipped FileDescriptorProto // 445 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0xbd, 0x8e, 0xd3, 0x40, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x52, 0x31, 0x8f, 0xd3, 0x30,
0x10, 0xc7, 0xed, 0xe3, 0x43, 0xba, 0x4d, 0x08, 0x60, 0xae, 0xc8, 0x9d, 0x84, 0x6d, 0xa5, 0x40, 0x18, 0x4d, 0x8e, 0xa3, 0x52, 0x9d, 0x72, 0x82, 0xdc, 0x0d, 0xc7, 0x49, 0x4d, 0xa2, 0x0c, 0xa8,
0x69, 0xbc, 0xe6, 0x8e, 0x17, 0x20, 0x46, 0x42, 0xd4, 0x36, 0xa2, 0xa0, 0x89, 0xd6, 0xde, 0xc5, 0x4b, 0x12, 0xb5, 0x6c, 0x88, 0x81, 0x46, 0x55, 0x85, 0x18, 0xd3, 0xc2, 0xc0, 0x52, 0x39, 0x8e,
0xb1, 0x62, 0x7b, 0x2c, 0xef, 0x3a, 0xe0, 0xb7, 0xe0, 0x39, 0xa8, 0x79, 0x88, 0x94, 0x11, 0x15, 0x49, 0xab, 0x26, 0x71, 0x14, 0xbb, 0x85, 0x2c, 0xfc, 0x06, 0x46, 0x46, 0x66, 0xe6, 0xfe, 0x06,
0x55, 0x40, 0xc9, 0x0b, 0x50, 0x53, 0xa1, 0xfd, 0x48, 0x40, 0x8a, 0x40, 0x54, 0xde, 0x9d, 0x99, 0xd4, 0xb1, 0xea, 0x84, 0x18, 0x0a, 0x6a, 0xff, 0x05, 0x13, 0xb2, 0xe3, 0x12, 0xa4, 0x82, 0xb8,
0xff, 0xfc, 0xfe, 0x33, 0x5e, 0xf4, 0x78, 0x49, 0x56, 0x24, 0x64, 0xa4, 0xad, 0xc3, 0xd5, 0x75, 0x29, 0xf6, 0xfb, 0xde, 0x7b, 0xdf, 0xfb, 0xf2, 0x19, 0xb4, 0xe7, 0x70, 0x09, 0x3d, 0x0c, 0x8b,
0xca, 0x04, 0xb9, 0x0e, 0x57, 0xa4, 0x2b, 0x05, 0x6e, 0x5a, 0x10, 0xe0, 0x3c, 0x94, 0x69, 0x2c, 0xcc, 0x5b, 0x76, 0x43, 0xcc, 0x60, 0xd7, 0x5b, 0xc2, 0x45, 0xc2, 0xdc, 0xbc, 0x20, 0x8c, 0xe8,
0xd3, 0xd8, 0xa4, 0xaf, 0x2e, 0x33, 0xe0, 0x15, 0xf0, 0xb9, 0x2a, 0x08, 0xf5, 0x45, 0x57, 0x5f, 0x0f, 0x78, 0xd9, 0xe5, 0x65, 0x57, 0x96, 0x6f, 0x1e, 0x22, 0x42, 0x53, 0x42, 0x27, 0x82, 0xe0,
0xb9, 0xfa, 0x16, 0xa6, 0x84, 0xb3, 0x63, 0xbb, 0x0c, 0x8a, 0xda, 0xe4, 0x2f, 0x72, 0xc8, 0x41, 0x55, 0x97, 0x8a, 0x7d, 0x63, 0x54, 0x37, 0x2f, 0x84, 0x14, 0xff, 0xb6, 0x43, 0x64, 0x96, 0xc9,
0xeb, 0xe4, 0xc9, 0x44, 0xfd, 0x53, 0x0b, 0x5c, 0xb4, 0x44, 0xb0, 0xbc, 0xd7, 0x15, 0x93, 0x12, 0xfa, 0x55, 0x4c, 0x62, 0x52, 0xe9, 0xf8, 0x49, 0xa2, 0xd6, 0x69, 0x04, 0xca, 0x0a, 0xc8, 0x70,
0x0d, 0x67, 0x65, 0x09, 0xef, 0x19, 0x7d, 0x23, 0xbd, 0x39, 0x17, 0xe8, 0x0e, 0x65, 0x35, 0x54, 0x5c, 0x56, 0x0c, 0x3b, 0x01, 0xad, 0x7e, 0x92, 0x90, 0xb7, 0x38, 0x7a, 0xc5, 0xb3, 0xe9, 0x57,
0x63, 0xdb, 0xb7, 0xa7, 0xe7, 0xb1, 0xbe, 0x38, 0x2f, 0xd1, 0x48, 0x59, 0x9f, 0x1f, 0xd4, 0xe3, 0xe0, 0x6e, 0x84, 0x33, 0x92, 0x5e, 0xab, 0x96, 0xda, 0x69, 0x06, 0xd5, 0x45, 0x1f, 0x82, 0x0b,
0x33, 0xdf, 0x9e, 0x8e, 0x6e, 0x3c, 0x7c, 0x32, 0x04, 0x4e, 0x4c, 0xc9, 0xeb, 0xbe, 0x61, 0xf1, 0x11, 0x7d, 0x72, 0x54, 0x5f, 0x9f, 0x59, 0x6a, 0xe7, 0xa2, 0x67, 0xba, 0x27, 0x43, 0xb8, 0x23,
0x3d, 0x25, 0x3b, 0x84, 0x26, 0x39, 0x1a, 0x28, 0x4c, 0xcc, 0x32, 0x68, 0xe9, 0x5f, 0x60, 0x11, 0x49, 0x19, 0x97, 0x39, 0x0e, 0xee, 0x09, 0xd9, 0x11, 0xb2, 0x5f, 0x02, 0x4d, 0xb4, 0x09, 0x30,
0x1a, 0x0a, 0x10, 0xa4, 0x9c, 0xf3, 0xae, 0x69, 0x4a, 0x8d, 0x1a, 0xdc, 0x5c, 0x62, 0xb3, 0x0f, 0x22, 0x45, 0xa4, 0x0f, 0x41, 0x8b, 0x11, 0x06, 0x93, 0x09, 0x9d, 0xc2, 0x02, 0x53, 0xd1, 0x53,
0xb9, 0x81, 0x23, 0xec, 0x05, 0x14, 0x75, 0x74, 0x7b, 0xbd, 0xf5, 0xac, 0x78, 0xa0, 0x44, 0x89, 0xeb, 0xb5, 0xff, 0x62, 0x2a, 0x54, 0x23, 0xce, 0xf2, 0xcf, 0xd7, 0x3b, 0x53, 0x09, 0x34, 0x21,
0xd2, 0x4c, 0x7e, 0xd8, 0xe8, 0x81, 0x22, 0x25, 0x0b, 0xd2, 0x32, 0x83, 0x7b, 0x87, 0xce, 0x29, 0x14, 0x08, 0xb5, 0xbf, 0xa8, 0xe0, 0x7e, 0xcd, 0x90, 0xe6, 0x6f, 0x40, 0x33, 0xc2, 0x39, 0xa1,
0x6b, 0x80, 0x17, 0x02, 0x5a, 0x85, 0x1c, 0x46, 0xaf, 0x7e, 0x6e, 0xbd, 0x20, 0x2f, 0xc4, 0xa2, 0x33, 0x46, 0x0a, 0xe1, 0xdc, 0xf2, 0x9f, 0xff, 0xdc, 0x99, 0x4e, 0x3c, 0x63, 0xd3, 0x45, 0xe8,
0x4b, 0x71, 0x06, 0x95, 0xd9, 0xb9, 0xf9, 0x04, 0x9c, 0x2e, 0x43, 0xd1, 0x37, 0x8c, 0xe3, 0x59, 0x22, 0x92, 0xca, 0x3f, 0x2c, 0x3f, 0x0e, 0x8d, 0xe6, 0x1e, 0x2b, 0x73, 0x4c, 0xdd, 0x3e, 0x42,
0x96, 0xcd, 0x28, 0x6d, 0x19, 0xe7, 0x5f, 0x3e, 0x07, 0x8f, 0x8c, 0x13, 0x13, 0x89, 0x7a, 0xc1, 0xfd, 0x28, 0x2a, 0x30, 0xa5, 0xdb, 0x95, 0x73, 0x29, 0xf7, 0x20, 0x11, 0xbf, 0x64, 0x98, 0x06,
0x78, 0xfc, 0xbb, 0xb5, 0x23, 0xd0, 0x7d, 0x52, 0x41, 0x57, 0x0b, 0x3d, 0x41, 0xc1, 0xe8, 0xf8, 0xb5, 0xb5, 0xfe, 0x02, 0x34, 0x64, 0xfc, 0x33, 0xeb, 0xce, 0xff, 0xe3, 0x5f, 0xf2, 0xf8, 0x9f,
0xcc, 0xbf, 0xf5, 0xef, 0x19, 0x9e, 0xca, 0x19, 0x3e, 0x7d, 0xf3, 0xa6, 0xff, 0x61, 0x46, 0x0a, 0xbf, 0x9b, 0x5a, 0x8d, 0xd1, 0x40, 0x3a, 0xd8, 0xef, 0x01, 0xa8, 0xe1, 0x7f, 0xec, 0x62, 0x0c,
0x78, 0x3c, 0xd2, 0x8c, 0xc4, 0x20, 0xa2, 0xe7, 0xeb, 0x9d, 0x6b, 0x6f, 0x76, 0xae, 0xfd, 0x7d, 0x1a, 0x30, 0x25, 0x8b, 0x8c, 0x89, 0x1d, 0x34, 0xfd, 0xa7, 0xdc, 0xf0, 0xdb, 0xce, 0x7c, 0x74,
0xe7, 0xda, 0x1f, 0xf7, 0xae, 0xb5, 0xd9, 0xbb, 0xd6, 0xd7, 0xbd, 0x6b, 0xbd, 0x7d, 0xf2, 0x47, 0x8b, 0xc1, 0x06, 0x18, 0x6d, 0x57, 0x0e, 0x90, 0x13, 0x0d, 0x30, 0x0a, 0xa4, 0xd7, 0x93, 0xf3,
0x4f, 0xf9, 0xbf, 0x82, 0x92, 0xa4, 0x5c, 0x9d, 0xc2, 0x0f, 0xfa, 0x71, 0xa8, 0xbe, 0xe9, 0x5d, 0x8f, 0x9f, 0x4c, 0xc5, 0x7f, 0xb6, 0xde, 0x1b, 0xea, 0x66, 0x6f, 0xa8, 0x3f, 0xf6, 0x86, 0xfa,
0xf5, 0x24, 0x9e, 0xfd, 0x0a, 0x00, 0x00, 0xff, 0xff, 0x6e, 0x80, 0xa4, 0xff, 0xb9, 0x02, 0x00, 0xe1, 0x60, 0x28, 0x9b, 0x83, 0xa1, 0x7c, 0x3d, 0x18, 0xca, 0xeb, 0x3f, 0xdd, 0xf9, 0x7c, 0x4e,
0x00, 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) { func (m *AllowedVault) Marshal() (dAtA []byte, err error) {
@ -291,7 +325,7 @@ func (m *VaultRecord) MarshalToSizedBuffer(dAtA []byte) (int, error) {
var l int var l int
_ = l _ = l
{ {
size, err := m.TotalSupply.MarshalToSizedBuffer(dAtA[:i]) size, err := m.TotalShares.MarshalToSizedBuffer(dAtA[:i])
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -299,14 +333,7 @@ func (m *VaultRecord) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i = encodeVarintVault(dAtA, i, uint64(size)) i = encodeVarintVault(dAtA, i, uint64(size))
} }
i-- i--
dAtA[i] = 0x12 dAtA[i] = 0xa
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 return len(dAtA) - i, nil
} }
@ -330,10 +357,10 @@ func (m *VaultShareRecord) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i _ = i
var l int var l int
_ = l _ = l
if len(m.AmountSupplied) > 0 { if len(m.Shares) > 0 {
for iNdEx := len(m.AmountSupplied) - 1; iNdEx >= 0; iNdEx-- { 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 { if err != nil {
return 0, err return 0, err
} }
@ -354,6 +381,46 @@ func (m *VaultShareRecord) MarshalToSizedBuffer(dAtA []byte) (int, error) {
return len(dAtA) - i, nil 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 { func encodeVarintVault(dAtA []byte, offset int, v uint64) int {
offset -= sovVault(v) offset -= sovVault(v)
base := offset base := offset
@ -387,11 +454,7 @@ func (m *VaultRecord) Size() (n int) {
} }
var l int var l int
_ = l _ = l
l = len(m.Denom) l = m.TotalShares.Size()
if l > 0 {
n += 1 + l + sovVault(uint64(l))
}
l = m.TotalSupply.Size()
n += 1 + l + sovVault(uint64(l)) n += 1 + l + sovVault(uint64(l))
return n return n
} }
@ -406,8 +469,8 @@ func (m *VaultShareRecord) Size() (n int) {
if l > 0 { if l > 0 {
n += 1 + l + sovVault(uint64(l)) n += 1 + l + sovVault(uint64(l))
} }
if len(m.AmountSupplied) > 0 { if len(m.Shares) > 0 {
for _, e := range m.AmountSupplied { for _, e := range m.Shares {
l = e.Size() l = e.Size()
n += 1 + l + sovVault(uint64(l)) n += 1 + l + sovVault(uint64(l))
} }
@ -415,6 +478,21 @@ func (m *VaultShareRecord) Size() (n int) {
return n 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) { func sovVault(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7 return (math_bits.Len64(x|1) + 6) / 7
} }
@ -553,39 +631,7 @@ func (m *VaultRecord) Unmarshal(dAtA []byte) error {
switch fieldNum { switch fieldNum {
case 1: case 1:
if wireType != 2 { if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Denom", wireType) return fmt.Errorf("proto: wrong wireType = %d for field TotalShares", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowVault
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthVault
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthVault
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Denom = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field TotalSupply", wireType)
} }
var msglen int var msglen int
for shift := uint(0); ; shift += 7 { for shift := uint(0); ; shift += 7 {
@ -612,7 +658,7 @@ func (m *VaultRecord) Unmarshal(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF 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 return err
} }
iNdEx = postIndex iNdEx = postIndex
@ -702,7 +748,7 @@ func (m *VaultShareRecord) Unmarshal(dAtA []byte) error {
iNdEx = postIndex iNdEx = postIndex
case 2: case 2:
if wireType != 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 var msglen int
for shift := uint(0); ; shift += 7 { for shift := uint(0); ; shift += 7 {
@ -729,8 +775,124 @@ func (m *VaultShareRecord) Unmarshal(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
m.AmountSupplied = append(m.AmountSupplied, types.Coin{}) m.Shares = append(m.Shares, VaultShare{})
if err := m.AmountSupplied[len(m.AmountSupplied)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { 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 return err
} }
iNdEx = postIndex iNdEx = postIndex

View File

@ -25,12 +25,10 @@ func TestVaultRecordValidate(t *testing.T) {
name: "valid vault records", name: "valid vault records",
vaultRecords: types.VaultRecords{ vaultRecords: types.VaultRecords{
{ {
Denom: "usdx", TotalShares: types.NewVaultShare("usdx", sdk.NewDec(0)),
TotalSupply: sdk.NewInt64Coin("usdx", 0),
}, },
{ {
Denom: "ukava", TotalShares: types.NewVaultShare("ukava", sdk.NewDec(5)),
TotalSupply: sdk.NewInt64Coin("ukava", 5),
}, },
}, },
errArgs: errArgs{ errArgs: errArgs{
@ -41,12 +39,10 @@ func TestVaultRecordValidate(t *testing.T) {
name: "invalid - duplicate denom", name: "invalid - duplicate denom",
vaultRecords: types.VaultRecords{ vaultRecords: types.VaultRecords{
{ {
Denom: "usdx", TotalShares: types.NewVaultShare("usdx", sdk.NewDec(0)),
TotalSupply: sdk.NewInt64Coin("usdx", 0),
}, },
{ {
Denom: "usdx", TotalShares: types.NewVaultShare("usdx", sdk.NewDec(5)),
TotalSupply: sdk.NewInt64Coin("usdx", 5),
}, },
}, },
errArgs: errArgs{ errArgs: errArgs{
@ -58,8 +54,7 @@ func TestVaultRecordValidate(t *testing.T) {
name: "invalid - invalid denom", name: "invalid - invalid denom",
vaultRecords: types.VaultRecords{ vaultRecords: types.VaultRecords{
{ {
Denom: "", TotalShares: types.VaultShare{Denom: "", Amount: sdk.NewDec(0)},
TotalSupply: sdk.NewInt64Coin("ukava", 0),
}, },
}, },
errArgs: errArgs{ errArgs: errArgs{
@ -67,30 +62,16 @@ func TestVaultRecordValidate(t *testing.T) {
contains: "invalid denom", 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", name: "invalid - negative",
vaultRecords: types.VaultRecords{ vaultRecords: types.VaultRecords{
{ {
Denom: "usdx", TotalShares: types.VaultShare{"usdx", sdk.NewDec(-5)},
TotalSupply: sdk.Coin{Denom: "usdx", Amount: sdk.NewInt(-1)},
}, },
}, },
errArgs: errArgs{ errArgs: errArgs{
expectPass: false, 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{ vaultRecords: types.VaultShareRecords{
{ {
Depositor: addrs[0], Depositor: addrs[0],
AmountSupplied: sdk.NewCoins( Shares: types.NewVaultShares(
sdk.NewInt64Coin("usdx", 0), types.NewVaultShare("usdx", sdk.NewDec(0)),
), ),
}, },
{ {
Depositor: addrs[1], Depositor: addrs[1],
AmountSupplied: sdk.NewCoins( Shares: types.NewVaultShares(
sdk.NewInt64Coin("usdx", 0), types.NewVaultShare("usdx", sdk.NewDec(0)),
sdk.NewInt64Coin("ukava", 5), types.NewVaultShare("ukava", sdk.NewDec(5)),
), ),
}, },
}, },
@ -148,15 +129,15 @@ func TestVaultShareRecordsValidate(t *testing.T) {
vaultRecords: types.VaultShareRecords{ vaultRecords: types.VaultShareRecords{
{ {
Depositor: addrs[0], Depositor: addrs[0],
AmountSupplied: sdk.NewCoins( Shares: types.NewVaultShares(
sdk.NewInt64Coin("usdx", 0), types.NewVaultShare("usdx", sdk.NewDec(0)),
), ),
}, },
{ {
Depositor: addrs[0], Depositor: addrs[0],
AmountSupplied: sdk.NewCoins( Shares: types.NewVaultShares(
sdk.NewInt64Coin("usdx", 0), types.NewVaultShare("usdx", sdk.NewDec(0)),
sdk.NewInt64Coin("ukava", 5), types.NewVaultShare("ukava", sdk.NewDec(5)),
), ),
}, },
}, },
@ -170,8 +151,8 @@ func TestVaultShareRecordsValidate(t *testing.T) {
vaultRecords: types.VaultShareRecords{ vaultRecords: types.VaultShareRecords{
{ {
Depositor: sdk.AccAddress{}, Depositor: sdk.AccAddress{},
AmountSupplied: sdk.NewCoins( Shares: types.NewVaultShares(
sdk.NewInt64Coin("usdx", 0), types.NewVaultShare("usdx", sdk.NewDec(0)),
), ),
}, },
}, },
@ -185,14 +166,15 @@ func TestVaultShareRecordsValidate(t *testing.T) {
vaultRecords: types.VaultShareRecords{ vaultRecords: types.VaultShareRecords{
{ {
Depositor: addrs[0], Depositor: addrs[0],
AmountSupplied: sdk.Coins{ // Direct slice, not NewVaultShares() which panics
sdk.Coin{Denom: "ukava", Amount: sdk.NewInt(-1)}, Shares: types.VaultShares{
types.VaultShare{"usdx", sdk.NewDec(-5)},
}, },
}, },
}, },
errArgs: errArgs{ errArgs: errArgs{
expectPass: false, 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) { func TestNewVaultShareRecord(t *testing.T) {
_, addrs := app.GeneratePrivKeyAddressPairs(1) _, addrs := app.GeneratePrivKeyAddressPairs(1)
coins := sdk.NewCoins( shares := types.NewVaultShares(
sdk.NewInt64Coin("usdx", 10), types.NewVaultShare("usdx", sdk.NewDec(0)),
sdk.NewInt64Coin("ukava", 5), types.NewVaultShare("ukava", sdk.NewDec(5)),
) )
shareRecord := types.NewVaultShareRecord(addrs[0], coins...) shareRecord := types.NewVaultShareRecord(addrs[0], shares)
require.Equal(t, coins, shareRecord.AmountSupplied) require.Equal(t, shares, shareRecord.Shares)
} }