Swap users accumulate rewards (#950)

* add swap claim type

* add store methods for swap claims

* add swap claims to genesis state

* tidy up cdp and hard hook doc comments

* add uncalled hooks to the swap keeper

* add swap rewards sync method

* add swap rewards init method

* connect swap rewards via swap hooks

* Update querier and client for swap claims (#951)

* refactor querier to dedupe code

* add swap claims querier endpoint

* add swap claim querying to rest

* add swap claim querying to cli

* add keeper method to iterate swap reward indexes

* simplify reward-factors query endpoint, add swap

* update swap hook to match latest swap branch

* rename func to not collide with latest swap branch

* Squash merge swap-acceptance branch (#956)

* add failing acceptance test for a user depositing into a pool

* implement GetAccount test helper

* implement swap.MsgDeposit for creating and adding liquidity to a pool

* update aliases, add event types, and fix typo/compiler errors in handler
test

* use only aliases names in handler test (don't use swap types -- ensures
we have run aliasgen), add assertion for even type message

* implement account and module account balance checks in handler test

* fill out handler assertions for testing keeper state and events

* update signed json representation and register swap/MsgDeposit for
proper encoding

* fill out boilerplate to get handler test to compile

* alias gen for pool

* add handling of message type; fill in deposit keeper method for
succesful compile; noop but test assertions now run up to module acc not
nil check

* add module account permissions for swap module -- fixes module account
creation; pass account keeper and supply keeper into swap keeper to
allow the ability to work with user and module accounts

* implement create pool logic for msg deposit; allows creation of a of new
pool, checking params to see if it is allowed.  Initi shares are set,
and senders number of shares are stored

* Swap migrations scaffolding (#925)

* swap module scaffolding

* global swap fee

* can't think of a reason for begin blocker; removing for abci.go for now;

* test pair types; refactor pair name logic; simplify pairs validation and
fix stack overflow error

* check comparison

* use test package

* init swap module genesis

* add basic marshall tests

* remove reward apy from pairs

* fix integration helpers

* use max swap fee constant; fix validation of swap fee; add tests to
cover param validation and param set setup

* use noerror over nil

* start genesis tests

* test param set validation mirrors param validation

* add genesis tests

* remove print statement

* add subtests for genesis test cases; add extra querier test for unknown
route; add keeper params testing

* add spec

* update swagger

* find replace hard -> swap in comments

* remove unused method

* rename pairs to allowed pools; pool is more commonly used, and
allowedPool makes it more clear what swap parameter is for.  In
addition, we won't conflict with Pool data structure for storing a
created pool in the store.

* remove generated link

* missed spec rename

* validate token order for allowed pools

* fix swagger

* json should be snakecase; change allowedPools to allowed_pools

* add legacy types

* add swap genesis to v0_15 migration

* add legacy types

* add swap genesis to v0_15 migration

* migration revisions

Co-authored-by: Nick DeLuca <nickdeluca08@gmail.com>

* keeper todos

* update keeper tests

* type todos

* update types tests

* tx deposit cli cmd

* tx deposit rest

* Swap module simulation scaffolding (#924)

* sims scaffolding

* add noop operation

* genesis revisions

* add param changes

* mvoe persistance methods to main keeper file, consolidate tests

* make helper methods private. they are tested via deposit method, and
unit testing them would make test suite brittle and refactoring
difficult

* use more clear coin variables

* code 1 is reserved, use code 2 and sequence all errors

* remove todo

* Implement deadline for swap module module message. This is implemented in
handler with a interface to easily apply to it to all messages, and
separate msg validation concerns from the keeper

* move allowed pools to params -- let pool and pool_test focus on pool domain logic, not
parameter & governance concerns

* update alias

* add unitless implementatin of constant product liquidity pool to
isolate and enapsulate liquidity logic.  Swap methods interfaces are
added, but implementation not yet added

* nits and todos

* add ErrInvalidPool

* add tests for edge cases around pool depletion; add explicit panic for
edge case that results in a pool reserve being zero; handle pool
reinitialization if it is empty

* touch up comments and flush out the rest of assertions

* add data structures for keeper state storage separate from pool domain
objects, and improve structure for easier querying

* rename pool name to pool key for events

* add support for a denominated pool that uses sdk.Coins and sdk.Coin
arguments, keeping tracking of the units in the base pool.  This gives
nice separation between pool logic, and coin/denom logic

* refactor keeper to use new records for storage, and implement pool
deposit using the denominated pool

* address previous PR comment - reminder for migration if changing
account permissions

* msg deposit should validate that denoms are not equal

* add godoc comments

* golint and some poolName -> poolID cleanup

* implement adding liquidity to an existing pool

* hardcode pools in sims

* touch up comment

* withdraw keeper logic

* withdraw type updates

* add withdraw msg tx handler

* initial withdraw test

* fix panic

* use new denominated pool with existing shares

* fix: check args on deposit cmd

* add slippage limit check for depositing to an existing pool

* send coins just before event emission

* check liquidity returned is greater than zero for both coins; ensure
returned number of shares are greater than zero

* add deadline to msgwithdraw

* register msgwithdraw

* scaffold msgwithdraw types test

* register the correct msg

* modify swap functions to also return the amount paid for the pool swap
fee.  This will be used to calculate slippage and for event tracking

* add slippage types

* add expected withdrawal coins

* calculate slippage against expected coins

* update withdraw keeper tests

* spelling, improve comments on add liquidity math

* typo

* typo

* grammer

* typo / grammer

* remove pool_id from withdraw msg

* add slippage to tx cmd

* TestWithdraw_Partial

* nit

* add withdraw no pool, no deposit record tests

* drop event check on partial withdraw test

* fix broken link

* fix broken link

* resolve merge conflicts

* ensure swap fee can not be equal to 1; add full implementation of swap
pool methods;  these implementation ensure that the pool invariant is
always greater or equal to the previous invariant

* refactor duplicated code into private swap methods

* add runtime assertion to always ensure invariant is greater or equal
to the previous invariant sub fee on swaps

* improve comments for base pool swap functions

* add swap exact input and output methods to denominated pool that wrap
the base pool interface for swapping

* comment touch ups

* more comment touchups

* fix msg deposit struct tag (#943)

* use better name for swap calculation private methods

* nits: golint

* fix misspelling in method name

* Add HARD token governance committee for Hard module (#941)

* add hard gov token committee

* revisions: update migration

* revisions: update test/data file

* initial revisions

* add TokenCommittee JSONMarshal test

* fix SetPermissions method

* remove BaseCommittee Type field

* add incentive params to allowed params

* Add SWP token governance committee for Swap module (#946)

* add swp token commitee to migration

* update test, add gen export utility method

* final revisions: add TODO

* remove slippage from withdraw to use min values for coins; add
additional validation test cases

* update alias for swap module

* add withdraw tests to handler for increased coverage; note: first pass,
improvements still yet to be made here

* refact withdraw keeper to use min amounts; panic for cases that do not
happen in normal situations

* lint fixes

* use total shares to track if pool should be deleted; add more in depth
withdraw comment

* add exact args for withdraw cmd

* extract record update methods

* update depositor share record if it exists -- do not overwrite an
existing record; ensures no loss of shares if the same address deposits
more than once

* Swap queries: deposit, pool, pools (#949)

* query deposits types

* implement deposit querier keeper methods

* query deposits CLI

* query deposits REST

* query types for pool/pools

* pool/pools querier keeper methods

* pool/pools CLI

* pool/pools REST

* basic pool/pools query tests

* basic deposit querier test

* iterate share records via owner bytes

* nit: add example for querying deposits by owner only

Co-authored-by: karzak <kjydavis3@gmail.com>

* feat: add REST tx handler for swap LP withdrawals

Co-authored-by: Nick DeLuca <nickdeluca08@gmail.com>
Co-authored-by: Denali Marsh <denali@kava.io>
Co-authored-by: denalimarsh <denalimarsh@gmail.com>
Co-authored-by: karzak <kjydavis3@gmail.com>

* expand incentive cli query docs

Co-authored-by: Nick DeLuca <nickdeluca08@gmail.com>
Co-authored-by: Denali Marsh <denali@kava.io>
Co-authored-by: denalimarsh <denalimarsh@gmail.com>
Co-authored-by: karzak <kjydavis3@gmail.com>

* minor update to godoc comment

Co-authored-by: Nick DeLuca <nickdeluca08@gmail.com>
Co-authored-by: Denali Marsh <denali@kava.io>
Co-authored-by: denalimarsh <denalimarsh@gmail.com>
Co-authored-by: karzak <kjydavis3@gmail.com>
This commit is contained in:
Ruaridh 2021-07-13 13:35:02 +01:00 committed by GitHub
parent 65052ce31a
commit 4beaf0de54
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 1427 additions and 931 deletions

View File

@ -390,7 +390,7 @@ func NewApp(logger log.Logger, db dbm.DB, traceStore io.Writer, appOpts AppOptio
app.accountKeeper, app.accountKeeper,
app.supplyKeeper, app.supplyKeeper,
) )
app.swapKeeper = swap.NewKeeper( swapKeeper := swap.NewKeeper(
app.cdc, app.cdc,
keys[swap.StoreKey], keys[swap.StoreKey],
swapSubspace, swapSubspace,
@ -406,11 +406,11 @@ func NewApp(logger log.Logger, db dbm.DB, traceStore io.Writer, appOpts AppOptio
&hardKeeper, &hardKeeper,
app.accountKeeper, app.accountKeeper,
&stakingKeeper, &stakingKeeper,
app.swapKeeper, &swapKeeper,
) )
// register the staking hooks // register the staking hooks
// NOTE: stakingKeeper above is passed by reference, so that it will contain these hooks // NOTE: These keepers are passed by reference above, so they will contain these hooks.
app.stakingKeeper = *stakingKeeper.SetHooks( app.stakingKeeper = *stakingKeeper.SetHooks(
staking.NewMultiStakingHooks(app.distrKeeper.Hooks(), app.slashingKeeper.Hooks(), app.incentiveKeeper.Hooks())) staking.NewMultiStakingHooks(app.distrKeeper.Hooks(), app.slashingKeeper.Hooks(), app.incentiveKeeper.Hooks()))
@ -418,6 +418,8 @@ func NewApp(logger log.Logger, db dbm.DB, traceStore io.Writer, appOpts AppOptio
app.hardKeeper = *hardKeeper.SetHooks(hard.NewMultiHARDHooks(app.incentiveKeeper.Hooks())) app.hardKeeper = *hardKeeper.SetHooks(hard.NewMultiHARDHooks(app.incentiveKeeper.Hooks()))
app.swapKeeper = *swapKeeper.SetHooks(app.incentiveKeeper.Hooks())
// create the module manager (Note: Any module instantiated in the module manager that is later modified // create the module manager (Note: Any module instantiated in the module manager that is later modified
// must be passed by reference here.) // must be passed by reference here.)
app.mm = module.NewManager( app.mm = module.NewManager(

View File

@ -448,9 +448,10 @@ func Incentive(incentiveGS v0_14incentive.GenesisState) v0_15incentive.GenesisSt
hardSupplyAccumulationTimes, hardSupplyAccumulationTimes,
hardBorrowAccumulationTimes, hardBorrowAccumulationTimes,
hardDelegatorAccumulationTimes, hardDelegatorAccumulationTimes,
v0_15incentive.DefaultGenesisAccumulationTimes, // There is no previous swap rewards to accumulation starts at genesis time. v0_15incentive.DefaultGenesisAccumulationTimes, // There is no previous swap rewards so accumulation starts at genesis time.
usdxMintingClaims, usdxMintingClaims,
hardClaims, hardClaims,
delegatorClaims, delegatorClaims,
v0_15incentive.DefaultSwapClaims,
) )
} }

View File

@ -45,10 +45,10 @@ func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, paramstore subspace.Subspace,
} }
} }
// SetHooks sets the cdp keeper hooks // SetHooks adds hooks to the keeper.
func (k *Keeper) SetHooks(hooks types.CDPHooks) *Keeper { func (k *Keeper) SetHooks(hooks types.CDPHooks) *Keeper {
if k.hooks != nil { if k.hooks != nil {
panic("cannot set validator hooks twice") panic("cannot set cdp hooks twice")
} }
k.hooks = hooks k.hooks = hooks
return k return k

View File

@ -45,10 +45,10 @@ func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, paramstore subspace.Subspace,
} }
} }
// SetHooks sets the cdp keeper hooks // SetHooks adds hooks to the keeper.
func (k *Keeper) SetHooks(hooks types.HARDHooks) *Keeper { func (k *Keeper) SetHooks(hooks types.HARDHooks) *Keeper {
if k.hooks != nil { if k.hooks != nil {
panic("cannot set validator hooks twice") panic("cannot set hard hooks twice")
} }
k.hooks = hooks k.hooks = hooks
return k return k

View File

@ -1,8 +1,5 @@
// nolint // Code generated by aliasgen tool (github.com/rhuairahrighairidh/aliasgen) DO NOT EDIT.
// autogenerated code using github.com/rigelrozanski/multitool
// aliases generated for the following subdirectories:
// ALIASGEN: github.com/kava-labs/kava/x/incentive/types
// ALIASGEN: github.com/kava-labs/kava/x/incentive/keeper
package incentive package incentive
import ( import (
@ -11,166 +8,175 @@ import (
) )
const ( const (
USDXMintingClaimType = types.USDXMintingClaimType BeginningOfMonth = keeper.BeginningOfMonth
HardLiquidityProviderClaimType = types.HardLiquidityProviderClaimType MidMonth = keeper.MidMonth
PaymentHour = keeper.PaymentHour
AttributeKeyClaimAmount = types.AttributeKeyClaimAmount
AttributeKeyClaimPeriod = types.AttributeKeyClaimPeriod
AttributeKeyClaimType = types.AttributeKeyClaimType
AttributeKeyClaimedBy = types.AttributeKeyClaimedBy
AttributeKeyRewardPeriod = types.AttributeKeyRewardPeriod
AttributeValueCategory = types.AttributeValueCategory
BondDenom = types.BondDenom BondDenom = types.BondDenom
DefaultParamspace = types.DefaultParamspace
DelegatorClaimType = types.DelegatorClaimType
EventTypeClaim = types.EventTypeClaim EventTypeClaim = types.EventTypeClaim
EventTypeRewardPeriod = types.EventTypeRewardPeriod
EventTypeClaimPeriod = types.EventTypeClaimPeriod EventTypeClaimPeriod = types.EventTypeClaimPeriod
EventTypeClaimPeriodExpiry = types.EventTypeClaimPeriodExpiry EventTypeClaimPeriodExpiry = types.EventTypeClaimPeriodExpiry
AttributeValueCategory = types.AttributeValueCategory EventTypeRewardPeriod = types.EventTypeRewardPeriod
AttributeKeyClaimedBy = types.AttributeKeyClaimedBy HardLiquidityProviderClaimType = types.HardLiquidityProviderClaimType
AttributeKeyClaimAmount = types.AttributeKeyClaimAmount
AttributeKeyClaimType = types.AttributeKeyClaimType
AttributeKeyRewardPeriod = types.AttributeKeyRewardPeriod
AttributeKeyClaimPeriod = types.AttributeKeyClaimPeriod
ModuleName = types.ModuleName
StoreKey = types.StoreKey
RouterKey = types.RouterKey
DefaultParamspace = types.DefaultParamspace
QuerierRoute = types.QuerierRoute
Small = types.Small
Medium = types.Medium
Large = types.Large Large = types.Large
QueryGetRewards = types.QueryGetRewards Medium = types.Medium
ModuleName = types.ModuleName
QuerierRoute = types.QuerierRoute
QueryGetDelegatorRewards = types.QueryGetDelegatorRewards
QueryGetHardRewards = types.QueryGetHardRewards QueryGetHardRewards = types.QueryGetHardRewards
QueryGetHardRewardsUnsynced = types.QueryGetHardRewardsUnsynced
QueryGetUSDXMintingRewards = types.QueryGetUSDXMintingRewards
QueryGetUSDXMintingRewardsUnsynced = types.QueryGetUSDXMintingRewardsUnsynced
QueryGetRewardFactors = types.QueryGetRewardFactors
QueryGetParams = types.QueryGetParams QueryGetParams = types.QueryGetParams
QueryGetRewardPeriods = types.QueryGetRewardPeriods QueryGetRewardFactors = types.QueryGetRewardFactors
QueryGetClaimPeriods = types.QueryGetClaimPeriods QueryGetSwapRewards = types.QueryGetSwapRewards
QueryGetUSDXMintingRewards = types.QueryGetUSDXMintingRewards
RestClaimCollateralType = types.RestClaimCollateralType RestClaimCollateralType = types.RestClaimCollateralType
RestClaimOwner = types.RestClaimOwner RestClaimOwner = types.RestClaimOwner
RestClaimType = types.RestClaimType RestClaimType = types.RestClaimType
RestUnsynced = types.RestUnsynced RestUnsynced = types.RestUnsynced
BeginningOfMonth = keeper.BeginningOfMonth RouterKey = types.RouterKey
MidMonth = keeper.MidMonth Small = types.Small
PaymentHour = keeper.PaymentHour StoreKey = types.StoreKey
SwapClaimType = types.SwapClaimType
USDXMintingClaimType = types.USDXMintingClaimType
) )
var ( var (
// functions aliases // function aliases
GetTotalVestingPeriodLength = types.GetTotalVestingPeriodLength CalculateTimeElapsed = keeper.CalculateTimeElapsed
NewUSDXMintingClaim = types.NewUSDXMintingClaim
NewHardLiquidityProviderClaim = types.NewHardLiquidityProviderClaim
NewMultiRewardPeriod = types.NewMultiRewardPeriod
NewRewardIndex = types.NewRewardIndex
NewMultiRewardIndex = types.NewMultiRewardIndex
RegisterCodec = types.RegisterCodec
NewGenesisState = types.NewGenesisState
DefaultGenesisState = types.DefaultGenesisState
NewGenesisAccumulationTime = types.NewGenesisAccumulationTime
NewMsgClaimUSDXMintingReward = types.NewMsgClaimUSDXMintingReward
NewMsgClaimUSDXMintingRewardVVesting = types.NewMsgClaimUSDXMintingRewardVVesting
NewMsgClaimHardReward = types.NewMsgClaimHardReward
NewMsgClaimHardRewardVVesting = types.NewMsgClaimHardRewardVVesting
NewParams = types.NewParams
DefaultParams = types.DefaultParams
ParamKeyTable = types.ParamKeyTable
NewRewardPeriod = types.NewRewardPeriod
NewMultiplier = types.NewMultiplier
NewPeriod = types.NewPeriod
NewQueryRewardsParams = types.NewQueryRewardsParams
NewQueryUSDXMintingRewardsParams = types.NewQueryUSDXMintingRewardsParams
NewQueryUSDXMintingRewardsUnsyncedParams = types.NewQueryUSDXMintingRewardsUnsyncedParams
NewQueryHardRewardsParams = types.NewQueryHardRewardsParams
NewQueryHardRewardsUnsyncedParams = types.NewQueryHardRewardsUnsyncedParams
NewQueryRewardFactorsParams = types.NewQueryRewardFactorsParams
NewRewardFactor = types.NewRewardFactor
NewKeeper = keeper.NewKeeper NewKeeper = keeper.NewKeeper
NewQuerier = keeper.NewQuerier NewQuerier = keeper.NewQuerier
CalculateTimeElapsed = keeper.CalculateTimeElapsed DefaultGenesisState = types.DefaultGenesisState
DefaultParams = types.DefaultParams
GetTotalVestingPeriodLength = types.GetTotalVestingPeriodLength
NewAccumulator = types.NewAccumulator
NewDelegatorClaim = types.NewDelegatorClaim
NewGenesisAccumulationTime = types.NewGenesisAccumulationTime
NewGenesisState = types.NewGenesisState
NewHardLiquidityProviderClaim = types.NewHardLiquidityProviderClaim
NewMsgClaimDelegatorReward = types.NewMsgClaimDelegatorReward
NewMsgClaimDelegatorRewardVVesting = types.NewMsgClaimDelegatorRewardVVesting
NewMsgClaimHardReward = types.NewMsgClaimHardReward
NewMsgClaimHardRewardVVesting = types.NewMsgClaimHardRewardVVesting
NewMsgClaimUSDXMintingReward = types.NewMsgClaimUSDXMintingReward
NewMsgClaimUSDXMintingRewardVVesting = types.NewMsgClaimUSDXMintingRewardVVesting
NewMultiRewardIndex = types.NewMultiRewardIndex
NewMultiRewardPeriod = types.NewMultiRewardPeriod
NewMultiplier = types.NewMultiplier
NewParams = types.NewParams
NewPeriod = types.NewPeriod
NewQueryGetRewardFactorsResponse = types.NewQueryGetRewardFactorsResponse
NewQueryRewardsParams = types.NewQueryRewardsParams
NewRewardIndex = types.NewRewardIndex
NewRewardPeriod = types.NewRewardPeriod
NewSwapClaim = types.NewSwapClaim
NewUSDXMintingClaim = types.NewUSDXMintingClaim
ParamKeyTable = types.ParamKeyTable
RegisterCodec = types.RegisterCodec
// variable aliases // variable aliases
ModuleCdc = types.ModuleCdc
ErrClaimNotFound = types.ErrClaimNotFound
ErrRewardPeriodNotFound = types.ErrRewardPeriodNotFound
ErrInvalidAccountType = types.ErrInvalidAccountType
ErrNoClaimsFound = types.ErrNoClaimsFound
ErrInsufficientModAccountBalance = types.ErrInsufficientModAccountBalance
ErrAccountNotFound = types.ErrAccountNotFound
ErrInvalidMultiplier = types.ErrInvalidMultiplier
ErrZeroClaim = types.ErrZeroClaim
ErrClaimExpired = types.ErrClaimExpired
ErrInvalidClaimType = types.ErrInvalidClaimType
ErrInvalidClaimOwner = types.ErrInvalidClaimOwner
USDXMintingClaimKeyPrefix = types.USDXMintingClaimKeyPrefix
USDXMintingRewardFactorKeyPrefix = types.USDXMintingRewardFactorKeyPrefix
PreviousUSDXMintingRewardAccrualTimeKeyPrefix = types.PreviousUSDXMintingRewardAccrualTimeKeyPrefix
HardLiquidityClaimKeyPrefix = types.HardLiquidityClaimKeyPrefix
HardSupplyRewardIndexesKeyPrefix = types.HardSupplyRewardIndexesKeyPrefix
PreviousHardSupplyRewardAccrualTimeKeyPrefix = types.PreviousHardSupplyRewardAccrualTimeKeyPrefix
HardBorrowRewardIndexesKeyPrefix = types.HardBorrowRewardIndexesKeyPrefix
PreviousHardBorrowRewardAccrualTimeKeyPrefix = types.PreviousHardBorrowRewardAccrualTimeKeyPrefix
DelegatorRewardIndexesKeyPrefix = types.DelegatorRewardIndexesKeyPrefix
PreviousDelegatorRewardAccrualTimeKeyPrefix = types.PreviousDelegatorRewardAccrualTimeKeyPrefix
USDXMintingRewardDenom = types.USDXMintingRewardDenom
HardLiquidityRewardDenom = types.HardLiquidityRewardDenom
KeyUSDXMintingRewardPeriods = types.KeyUSDXMintingRewardPeriods
KeyHardSupplyRewardPeriods = types.KeyHardSupplyRewardPeriods
KeyHardBorrowRewardPeriods = types.KeyHardBorrowRewardPeriods
KeyDelegatorRewardPeriods = types.KeyDelegatorRewardPeriods
KeyClaimEnd = types.KeyClaimEnd
KeyMultipliers = types.KeyMultipliers
DefaultActive = types.DefaultActive DefaultActive = types.DefaultActive
DefaultRewardPeriods = types.DefaultRewardPeriods DefaultClaimEnd = types.DefaultClaimEnd
DefaultDelegatorClaims = types.DefaultDelegatorClaims
DefaultGenesisAccumulationTimes = types.DefaultGenesisAccumulationTimes
DefaultHardClaims = types.DefaultHardClaims
DefaultMultiRewardPeriods = types.DefaultMultiRewardPeriods DefaultMultiRewardPeriods = types.DefaultMultiRewardPeriods
DefaultMultipliers = types.DefaultMultipliers DefaultMultipliers = types.DefaultMultipliers
DefaultDelegatorClaims = types.DefaultDelegatorClaims DefaultRewardPeriods = types.DefaultRewardPeriods
DefaultSwapClaims = types.DefaultSwapClaims
DefaultUSDXClaims = types.DefaultUSDXClaims DefaultUSDXClaims = types.DefaultUSDXClaims
DefaultHardClaims = types.DefaultHardClaims DelegatorClaimKeyPrefix = types.DelegatorClaimKeyPrefix
DefaultGenesisAccumulationTimes = types.DefaultGenesisAccumulationTimes DelegatorRewardIndexesKeyPrefix = types.DelegatorRewardIndexesKeyPrefix
DefaultClaimEnd = types.DefaultClaimEnd ErrAccountNotFound = types.ErrAccountNotFound
ErrClaimExpired = types.ErrClaimExpired
ErrClaimNotFound = types.ErrClaimNotFound
ErrDecreasingRewardFactor = types.ErrDecreasingRewardFactor
ErrInsufficientModAccountBalance = types.ErrInsufficientModAccountBalance
ErrInvalidAccountType = types.ErrInvalidAccountType
ErrInvalidClaimOwner = types.ErrInvalidClaimOwner
ErrInvalidClaimType = types.ErrInvalidClaimType
ErrInvalidMultiplier = types.ErrInvalidMultiplier
ErrNoClaimsFound = types.ErrNoClaimsFound
ErrRewardPeriodNotFound = types.ErrRewardPeriodNotFound
ErrZeroClaim = types.ErrZeroClaim
GovDenom = types.GovDenom GovDenom = types.GovDenom
PrincipalDenom = types.PrincipalDenom HardBorrowRewardIndexesKeyPrefix = types.HardBorrowRewardIndexesKeyPrefix
HardLiquidityClaimKeyPrefix = types.HardLiquidityClaimKeyPrefix
HardLiquidityRewardDenom = types.HardLiquidityRewardDenom
HardSupplyRewardIndexesKeyPrefix = types.HardSupplyRewardIndexesKeyPrefix
IncentiveMacc = types.IncentiveMacc IncentiveMacc = types.IncentiveMacc
KeyClaimEnd = types.KeyClaimEnd
KeyDelegatorRewardPeriods = types.KeyDelegatorRewardPeriods
KeyHardBorrowRewardPeriods = types.KeyHardBorrowRewardPeriods
KeyHardSupplyRewardPeriods = types.KeyHardSupplyRewardPeriods
KeyMultipliers = types.KeyMultipliers
KeySwapRewardPeriods = types.KeySwapRewardPeriods
KeyUSDXMintingRewardPeriods = types.KeyUSDXMintingRewardPeriods
ModuleCdc = types.ModuleCdc
PreviousDelegatorRewardAccrualTimeKeyPrefix = types.PreviousDelegatorRewardAccrualTimeKeyPrefix
PreviousHardBorrowRewardAccrualTimeKeyPrefix = types.PreviousHardBorrowRewardAccrualTimeKeyPrefix
PreviousHardSupplyRewardAccrualTimeKeyPrefix = types.PreviousHardSupplyRewardAccrualTimeKeyPrefix
PreviousSwapRewardAccrualTimeKeyPrefix = types.PreviousSwapRewardAccrualTimeKeyPrefix
PreviousUSDXMintingRewardAccrualTimeKeyPrefix = types.PreviousUSDXMintingRewardAccrualTimeKeyPrefix
PrincipalDenom = types.PrincipalDenom
SwapClaimKeyPrefix = types.SwapClaimKeyPrefix
SwapRewardIndexesKeyPrefix = types.SwapRewardIndexesKeyPrefix
USDXMintingClaimKeyPrefix = types.USDXMintingClaimKeyPrefix
USDXMintingRewardDenom = types.USDXMintingRewardDenom
USDXMintingRewardFactorKeyPrefix = types.USDXMintingRewardFactorKeyPrefix
) )
type ( type (
Claim = types.Claim
Claims = types.Claims
BaseClaim = types.BaseClaim
BaseMultiClaim = types.BaseMultiClaim
USDXMintingClaim = types.USDXMintingClaim
USDXMintingClaims = types.USDXMintingClaims
HardLiquidityProviderClaim = types.HardLiquidityProviderClaim
HardLiquidityProviderClaims = types.HardLiquidityProviderClaims
MultiRewardPeriod = types.MultiRewardPeriod
MultiRewardPeriods = types.MultiRewardPeriods
RewardIndex = types.RewardIndex
RewardIndexes = types.RewardIndexes
MultiRewardIndex = types.MultiRewardIndex
MultiRewardIndexes = types.MultiRewardIndexes
SupplyKeeper = types.SupplyKeeper
StakingKeeper = types.StakingKeeper
CdpKeeper = types.CdpKeeper
HardKeeper = types.HardKeeper
AccountKeeper = types.AccountKeeper
CDPHooks = types.CDPHooks
HARDHooks = types.HARDHooks
GenesisState = types.GenesisState
GenesisAccumulationTime = types.GenesisAccumulationTime
GenesisAccumulationTimes = types.GenesisAccumulationTimes
MsgClaimUSDXMintingReward = types.MsgClaimUSDXMintingReward
MsgClaimUSDXMintingRewardVVesting = types.MsgClaimUSDXMintingRewardVVesting
MsgClaimHardReward = types.MsgClaimHardReward
MsgClaimHardRewardVVesting = types.MsgClaimHardRewardVVesting
Params = types.Params
RewardPeriod = types.RewardPeriod
RewardPeriods = types.RewardPeriods
Multiplier = types.Multiplier
Multipliers = types.Multipliers
MultiplierName = types.MultiplierName
QueryRewardsParams = types.QueryRewardsParams
QueryUSDXMintingRewardsParams = types.QueryUSDXMintingRewardsParams
QueryUSDXMintingRewardsUnsyncedParams = types.QueryUSDXMintingRewardsUnsyncedParams
QueryHardRewardsParams = types.QueryHardRewardsParams
QueryHardRewardsUnsyncedParams = types.QueryHardRewardsUnsyncedParams
QueryRewardFactorsParams = types.QueryRewardFactorsParams
RewardFactor = types.RewardFactor
RewardFactors = types.RewardFactors
Hooks = keeper.Hooks Hooks = keeper.Hooks
Keeper = keeper.Keeper Keeper = keeper.Keeper
AccountKeeper = types.AccountKeeper
Accumulator = types.Accumulator
BaseClaim = types.BaseClaim
BaseMultiClaim = types.BaseMultiClaim
CDPHooks = types.CDPHooks
CdpKeeper = types.CdpKeeper
Claim = types.Claim
Claims = types.Claims
DelegatorClaim = types.DelegatorClaim
DelegatorClaims = types.DelegatorClaims
GenesisAccumulationTime = types.GenesisAccumulationTime
GenesisAccumulationTimes = types.GenesisAccumulationTimes
GenesisState = types.GenesisState
HARDHooks = types.HARDHooks
HardKeeper = types.HardKeeper
HardLiquidityProviderClaim = types.HardLiquidityProviderClaim
HardLiquidityProviderClaims = types.HardLiquidityProviderClaims
MsgClaimDelegatorReward = types.MsgClaimDelegatorReward
MsgClaimDelegatorRewardVVesting = types.MsgClaimDelegatorRewardVVesting
MsgClaimHardReward = types.MsgClaimHardReward
MsgClaimHardRewardVVesting = types.MsgClaimHardRewardVVesting
MsgClaimUSDXMintingReward = types.MsgClaimUSDXMintingReward
MsgClaimUSDXMintingRewardVVesting = types.MsgClaimUSDXMintingRewardVVesting
MultiRewardIndex = types.MultiRewardIndex
MultiRewardIndexes = types.MultiRewardIndexes
MultiRewardPeriod = types.MultiRewardPeriod
MultiRewardPeriods = types.MultiRewardPeriods
Multiplier = types.Multiplier
MultiplierName = types.MultiplierName
Multipliers = types.Multipliers
ParamSubspace = types.ParamSubspace
Params = types.Params
QueryGetRewardFactorsResponse = types.QueryGetRewardFactorsResponse
QueryRewardsParams = types.QueryRewardsParams
RewardIndex = types.RewardIndex
RewardIndexes = types.RewardIndexes
RewardPeriod = types.RewardPeriod
RewardPeriods = types.RewardPeriods
StakingKeeper = types.StakingKeeper
SupplyKeeper = types.SupplyKeeper
SwapClaim = types.SwapClaim
SwapClaims = types.SwapClaims
SwapKeeper = types.SwapKeeper
USDXMintingClaim = types.USDXMintingClaim
USDXMintingClaims = types.USDXMintingClaims
) )

View File

@ -21,8 +21,15 @@ const (
flagType = "type" flagType = "type"
flagUnsynced = "unsynced" flagUnsynced = "unsynced"
flagDenom = "denom" flagDenom = "denom"
typeDelegator = "delegator"
typeHard = "hard"
typeUSDXMinting = "usdx-minting"
typeSwap = "swap"
) )
var rewardTypes = []string{typeDelegator, typeHard, typeUSDXMinting, typeSwap}
// GetQueryCmd returns the cli query commands for the incentive module // GetQueryCmd returns the cli query commands for the incentive module
func GetQueryCmd(queryRoute string, cdc *codec.Codec) *cobra.Command { func GetQueryCmd(queryRoute string, cdc *codec.Codec) *cobra.Command {
incentiveQueryCmd := &cobra.Command{ incentiveQueryCmd := &cobra.Command{
@ -52,13 +59,14 @@ func queryRewardsCmd(queryRoute string, cdc *codec.Codec) *cobra.Command {
$ %s query %s rewards --type hard $ %s query %s rewards --type hard
$ %s query %s rewards --type usdx-minting $ %s query %s rewards --type usdx-minting
$ %s query %s rewards --type delegator $ %s query %s rewards --type delegator
$ %s query %s rewards --type swap
$ %s query %s rewards --type hard --owner kava15qdefkmwswysgg4qxgqpqr35k3m49pkx2jdfnw $ %s query %s rewards --type hard --owner kava15qdefkmwswysgg4qxgqpqr35k3m49pkx2jdfnw
$ %s query %s rewards --type hard --unsynced true $ %s query %s rewards --type hard --unsynced
`, `,
version.ClientName, types.ModuleName, version.ClientName, types.ModuleName, version.ClientName, types.ModuleName, version.ClientName, types.ModuleName,
version.ClientName, types.ModuleName, version.ClientName, types.ModuleName, version.ClientName, types.ModuleName, version.ClientName, types.ModuleName,
version.ClientName, types.ModuleName, version.ClientName, types.ModuleName, version.ClientName, types.ModuleName, version.ClientName, types.ModuleName,
version.ClientName, types.ModuleName)), version.ClientName, types.ModuleName, version.ClientName, types.ModuleName)),
Args: cobra.NoArgs, Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
cliCtx := context.NewCLIContext().WithCodec(cdc) cliCtx := context.NewCLIContext().WithCodec(cdc)
@ -76,91 +84,53 @@ func queryRewardsCmd(queryRoute string, cdc *codec.Codec) *cobra.Command {
} }
switch strings.ToLower(strType) { switch strings.ToLower(strType) {
case "hard": case typeHard:
var claims types.HardLiquidityProviderClaims params := types.NewQueryRewardsParams(page, limit, owner, boolUnsynced)
if boolUnsynced { claims, err := executeHardRewardsQuery(queryRoute, cdc, cliCtx, params)
params := types.NewQueryHardRewardsUnsyncedParams(page, limit, owner)
claims, err = executeHardRewardsUnsyncedQuery(queryRoute, cdc, cliCtx, params)
if err != nil { if err != nil {
return err return err
} }
} else {
params := types.NewQueryHardRewardsParams(page, limit, owner)
claims, err = executeHardRewardsQuery(queryRoute, cdc, cliCtx, params)
if err != nil {
return err
}
}
return cliCtx.PrintOutput(claims) return cliCtx.PrintOutput(claims)
case "usdx-minting": case typeUSDXMinting:
var claims types.USDXMintingClaims params := types.NewQueryRewardsParams(page, limit, owner, boolUnsynced)
if boolUnsynced { claims, err := executeUSDXMintingRewardsQuery(queryRoute, cdc, cliCtx, params)
params := types.NewQueryUSDXMintingRewardsUnsyncedParams(page, limit, owner)
claims, err = executeUSDXMintingRewardsUnsyncedQuery(queryRoute, cdc, cliCtx, params)
if err != nil { if err != nil {
return err return err
} }
} else {
params := types.NewQueryUSDXMintingRewardsParams(page, limit, owner)
claims, err = executeUSDXMintingRewardsQuery(queryRoute, cdc, cliCtx, params)
if err != nil {
return err
}
}
return cliCtx.PrintOutput(claims) return cliCtx.PrintOutput(claims)
case "delegator": case typeDelegator:
var claims types.DelegatorClaims params := types.NewQueryRewardsParams(page, limit, owner, boolUnsynced)
if boolUnsynced { claims, err := executeDelegatorRewardsQuery(queryRoute, cdc, cliCtx, params)
params := types.NewQueryDelegatorRewardsUnsyncedParams(page, limit, owner)
claims, err = executeDelegatorRewardsUnsyncedQuery(queryRoute, cdc, cliCtx, params)
if err != nil { if err != nil {
return err return err
} }
} else { return cliCtx.PrintOutput(claims)
params := types.NewQueryDelegatorRewardsParams(page, limit, owner) case typeSwap:
claims, err = executeDelegatorRewardsQuery(queryRoute, cdc, cliCtx, params) params := types.NewQueryRewardsParams(page, limit, owner, boolUnsynced)
claims, err := executeSwapRewardsQuery(queryRoute, cdc, cliCtx, params)
if err != nil { if err != nil {
return err return err
} }
}
return cliCtx.PrintOutput(claims) return cliCtx.PrintOutput(claims)
default: default:
var hardClaims types.HardLiquidityProviderClaims params := types.NewQueryRewardsParams(page, limit, owner, boolUnsynced)
var usdxMintingClaims types.USDXMintingClaims
var delegatorClaims types.DelegatorClaims hardClaims, err := executeHardRewardsQuery(queryRoute, cdc, cliCtx, params)
if boolUnsynced {
paramsHard := types.NewQueryHardRewardsUnsyncedParams(page, limit, owner)
hardClaims, err = executeHardRewardsUnsyncedQuery(queryRoute, cdc, cliCtx, paramsHard)
if err != nil { if err != nil {
return err return err
} }
paramsUSDXMinting := types.NewQueryUSDXMintingRewardsUnsyncedParams(page, limit, owner) usdxMintingClaims, err := executeUSDXMintingRewardsQuery(queryRoute, cdc, cliCtx, params)
usdxMintingClaims, err = executeUSDXMintingRewardsUnsyncedQuery(queryRoute, cdc, cliCtx, paramsUSDXMinting)
if err != nil { if err != nil {
return err return err
} }
paramsDelegator := types.NewQueryDelegatorRewardsUnsyncedParams(page, limit, owner) delegatorClaims, err := executeDelegatorRewardsQuery(queryRoute, cdc, cliCtx, params)
delegatorClaims, err = executeDelegatorRewardsUnsyncedQuery(queryRoute, cdc, cliCtx, paramsDelegator)
if err != nil { if err != nil {
return err return err
} }
} else { swapClaims, err := executeSwapRewardsQuery(queryRoute, cdc, cliCtx, params)
paramsHard := types.NewQueryHardRewardsParams(page, limit, owner)
hardClaims, err = executeHardRewardsQuery(queryRoute, cdc, cliCtx, paramsHard)
if err != nil { if err != nil {
return err return err
} }
paramsUSDXMinting := types.NewQueryUSDXMintingRewardsParams(page, limit, owner)
usdxMintingClaims, err = executeUSDXMintingRewardsQuery(queryRoute, cdc, cliCtx, paramsUSDXMinting)
if err != nil {
return err
}
paramsDelegator := types.NewQueryDelegatorRewardsParams(page, limit, owner)
delegatorClaims, err = executeDelegatorRewardsQuery(queryRoute, cdc, cliCtx, paramsDelegator)
if err != nil {
return err
}
}
if len(hardClaims) > 0 { if len(hardClaims) > 0 {
cliCtx.PrintOutput(hardClaims) cliCtx.PrintOutput(hardClaims)
} }
@ -170,13 +140,16 @@ func queryRewardsCmd(queryRoute string, cdc *codec.Codec) *cobra.Command {
if len(delegatorClaims) > 0 { if len(delegatorClaims) > 0 {
cliCtx.PrintOutput(delegatorClaims) cliCtx.PrintOutput(delegatorClaims)
} }
if len(swapClaims) > 0 {
cliCtx.PrintOutput(swapClaims)
}
} }
return nil return nil
}, },
} }
cmd.Flags().String(flagOwner, "", "(optional) filter by owner address") cmd.Flags().String(flagOwner, "", "(optional) filter by owner address")
cmd.Flags().String(flagType, "", "(optional) filter by reward type") cmd.Flags().String(flagType, "", fmt.Sprintf("(optional) filter by a reward type: %s", strings.Join(rewardTypes, "|")))
cmd.Flags().String(flagUnsynced, "", "(optional) get unsynced claims") cmd.Flags().Bool(flagUnsynced, false, "(optional) get unsynced claims")
cmd.Flags().Int(flags.FlagPage, 1, "pagination page rewards of to to query for") cmd.Flags().Int(flags.FlagPage, 1, "pagination page rewards of to to query for")
cmd.Flags().Int(flags.FlagLimit, 100, "pagination limit of rewards to query for") cmd.Flags().Int(flags.FlagLimit, 100, "pagination limit of rewards to query for")
return cmd return cmd
@ -213,47 +186,32 @@ func queryRewardFactorsCmd(queryRoute string, cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "reward-factors", Use: "reward-factors",
Short: "get current global reward factors", Short: "get current global reward factors",
Long: strings.TrimSpace(`get current global reward factors: Long: `Get current global reward factors for all reward types.`,
Example:
$ kvcli q hard reward-factors
$ kvcli q hard reward-factors --denom bnb`,
),
Args: cobra.NoArgs, Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
cliCtx := context.NewCLIContext().WithCodec(cdc) cliCtx := context.NewCLIContext().WithCodec(cdc)
denom := viper.GetString(flagDenom)
// Construct query with params
params := types.NewQueryRewardFactorsParams(denom)
bz, err := cdc.MarshalJSON(params)
if err != nil {
return err
}
// Execute query // Execute query
route := fmt.Sprintf("custom/%s/%s", queryRoute, types.QueryGetRewardFactors) route := fmt.Sprintf("custom/%s/%s", queryRoute, types.QueryGetRewardFactors)
res, height, err := cliCtx.QueryWithData(route, bz) res, height, err := cliCtx.QueryWithData(route, nil)
if err != nil { if err != nil {
return err return err
} }
cliCtx = cliCtx.WithHeight(height) cliCtx = cliCtx.WithHeight(height)
// Decode and print results // Decode and print results
var rewardFactors types.RewardFactors var response types.QueryGetRewardFactorsResponse
if err := cdc.UnmarshalJSON(res, &rewardFactors); err != nil { if err := cdc.UnmarshalJSON(res, &response); err != nil {
return fmt.Errorf("failed to unmarshal reward factors: %w", err) return fmt.Errorf("failed to unmarshal reward factors: %w", err)
} }
return cliCtx.PrintOutput(rewardFactors) return cliCtx.PrintOutput(response)
}, },
} }
cmd.Flags().String(flagDenom, "", "(optional) filter reward factors by denom") cmd.Flags().String(flagDenom, "", "(optional) filter reward factors by denom")
return cmd return cmd
} }
func executeHardRewardsQuery(queryRoute string, cdc *codec.Codec, cliCtx context.CLIContext, func executeHardRewardsQuery(queryRoute string, cdc *codec.Codec, cliCtx context.CLIContext, params types.QueryRewardsParams) (types.HardLiquidityProviderClaims, error) {
params types.QueryHardRewardsParams) (types.HardLiquidityProviderClaims, error) {
bz, err := cdc.MarshalJSON(params) bz, err := cdc.MarshalJSON(params)
if err != nil { if err != nil {
return types.HardLiquidityProviderClaims{}, err return types.HardLiquidityProviderClaims{}, err
@ -275,31 +233,7 @@ func executeHardRewardsQuery(queryRoute string, cdc *codec.Codec, cliCtx context
return claims, nil return claims, nil
} }
func executeHardRewardsUnsyncedQuery(queryRoute string, cdc *codec.Codec, cliCtx context.CLIContext, func executeUSDXMintingRewardsQuery(queryRoute string, cdc *codec.Codec, cliCtx context.CLIContext, params types.QueryRewardsParams) (types.USDXMintingClaims, error) {
params types.QueryHardRewardsUnsyncedParams) (types.HardLiquidityProviderClaims, error) {
bz, err := cdc.MarshalJSON(params)
if err != nil {
return types.HardLiquidityProviderClaims{}, err
}
route := fmt.Sprintf("custom/%s/%s", queryRoute, types.QueryGetHardRewardsUnsynced)
res, height, err := cliCtx.QueryWithData(route, bz)
if err != nil {
return types.HardLiquidityProviderClaims{}, err
}
cliCtx = cliCtx.WithHeight(height)
var claims types.HardLiquidityProviderClaims
if err := cdc.UnmarshalJSON(res, &claims); err != nil {
return types.HardLiquidityProviderClaims{}, fmt.Errorf("failed to unmarshal claims: %w", err)
}
return claims, nil
}
func executeUSDXMintingRewardsQuery(queryRoute string, cdc *codec.Codec, cliCtx context.CLIContext,
params types.QueryUSDXMintingRewardsParams) (types.USDXMintingClaims, error) {
bz, err := cdc.MarshalJSON(params) bz, err := cdc.MarshalJSON(params)
if err != nil { if err != nil {
return types.USDXMintingClaims{}, err return types.USDXMintingClaims{}, err
@ -321,31 +255,7 @@ func executeUSDXMintingRewardsQuery(queryRoute string, cdc *codec.Codec, cliCtx
return claims, nil return claims, nil
} }
func executeUSDXMintingRewardsUnsyncedQuery(queryRoute string, cdc *codec.Codec, cliCtx context.CLIContext, func executeDelegatorRewardsQuery(queryRoute string, cdc *codec.Codec, cliCtx context.CLIContext, params types.QueryRewardsParams) (types.DelegatorClaims, error) {
params types.QueryUSDXMintingRewardsUnsyncedParams) (types.USDXMintingClaims, error) {
bz, err := cdc.MarshalJSON(params)
if err != nil {
return types.USDXMintingClaims{}, err
}
route := fmt.Sprintf("custom/%s/%s", queryRoute, types.QueryGetUSDXMintingRewardsUnsynced)
res, height, err := cliCtx.QueryWithData(route, bz)
if err != nil {
return types.USDXMintingClaims{}, err
}
cliCtx = cliCtx.WithHeight(height)
var claims types.USDXMintingClaims
if err := cdc.UnmarshalJSON(res, &claims); err != nil {
return types.USDXMintingClaims{}, fmt.Errorf("failed to unmarshal claims: %w", err)
}
return claims, nil
}
func executeDelegatorRewardsQuery(queryRoute string, cdc *codec.Codec, cliCtx context.CLIContext,
params types.QueryDelegatorRewardsParams) (types.DelegatorClaims, error) {
bz, err := cdc.MarshalJSON(params) bz, err := cdc.MarshalJSON(params)
if err != nil { if err != nil {
return types.DelegatorClaims{}, err return types.DelegatorClaims{}, err
@ -367,24 +277,23 @@ func executeDelegatorRewardsQuery(queryRoute string, cdc *codec.Codec, cliCtx co
return claims, nil return claims, nil
} }
func executeDelegatorRewardsUnsyncedQuery(queryRoute string, cdc *codec.Codec, cliCtx context.CLIContext, func executeSwapRewardsQuery(queryRoute string, cdc *codec.Codec, cliCtx context.CLIContext, params types.QueryRewardsParams) (types.SwapClaims, error) {
params types.QueryDelegatorRewardsUnsyncedParams) (types.DelegatorClaims, error) {
bz, err := cdc.MarshalJSON(params) bz, err := cdc.MarshalJSON(params)
if err != nil { if err != nil {
return types.DelegatorClaims{}, err return types.SwapClaims{}, err
} }
route := fmt.Sprintf("custom/%s/%s", queryRoute, types.QueryGetDelegatorRewardsUnsynced) route := fmt.Sprintf("custom/%s/%s", queryRoute, types.QueryGetSwapRewards)
res, height, err := cliCtx.QueryWithData(route, bz) res, height, err := cliCtx.QueryWithData(route, bz)
if err != nil { if err != nil {
return types.DelegatorClaims{}, err return types.SwapClaims{}, err
} }
cliCtx = cliCtx.WithHeight(height) cliCtx = cliCtx.WithHeight(height)
var claims types.DelegatorClaims var claims types.SwapClaims
if err := cdc.UnmarshalJSON(res, &claims); err != nil { if err := cdc.UnmarshalJSON(res, &claims); err != nil {
return types.DelegatorClaims{}, fmt.Errorf("failed to unmarshal claims: %w", err) return types.SwapClaims{}, fmt.Errorf("failed to unmarshal claims: %w", err)
} }
return claims, nil return claims, nil

View File

@ -58,40 +58,18 @@ func queryRewardsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
} }
} }
if unsynced { params := types.NewQueryRewardsParams(page, limit, owner, unsynced)
switch strings.ToLower(rewardType) { switch strings.ToLower(rewardType) {
case "hard": case "hard":
params := types.NewQueryHardRewardsUnsyncedParams(page, limit, owner)
executeHardRewardsUnsyncedQuery(w, cliCtx, params)
case "usdx_minting":
params := types.NewQueryUSDXMintingRewardsUnsyncedParams(page, limit, owner)
executeUSDXMintingRewardsUnsyncedQuery(w, cliCtx, params)
case "delegator":
params := types.NewQueryDelegatorRewardsUnsyncedParams(page, limit, owner)
executeDelegatorRewardsUnsyncedQuery(w, cliCtx, params)
default:
hardParams := types.NewQueryHardRewardsUnsyncedParams(page, limit, owner)
usdxMintingParams := types.NewQueryUSDXMintingRewardsUnsyncedParams(page, limit, owner)
delegatorParams := types.NewQueryDelegatorRewardsUnsyncedParams(page, limit, owner)
executeAllUnsyncedRewardQueries(w, cliCtx, hardParams, usdxMintingParams, delegatorParams)
}
} else {
switch strings.ToLower(rewardType) {
case "hard":
params := types.NewQueryHardRewardsParams(page, limit, owner)
executeHardRewardsQuery(w, cliCtx, params) executeHardRewardsQuery(w, cliCtx, params)
case "usdx_minting": case "usdx_minting":
params := types.NewQueryUSDXMintingRewardsParams(page, limit, owner)
executeUSDXMintingRewardsQuery(w, cliCtx, params) executeUSDXMintingRewardsQuery(w, cliCtx, params)
case "delegator": case "delegator":
params := types.NewQueryDelegatorRewardsParams(page, limit, owner)
executeDelegatorRewardsQuery(w, cliCtx, params) executeDelegatorRewardsQuery(w, cliCtx, params)
case "swap":
executeSwapRewardsQuery(w, cliCtx, params)
default: default:
hardParams := types.NewQueryHardRewardsParams(page, limit, owner) executeAllRewardQueries(w, cliCtx, params)
usdxMintingParams := types.NewQueryUSDXMintingRewardsParams(page, limit, owner)
delegatorParams := types.NewQueryDelegatorRewardsParams(page, limit, owner)
executeAllRewardQueries(w, cliCtx, hardParams, usdxMintingParams, delegatorParams)
}
} }
} }
} }
@ -118,43 +96,25 @@ func queryParamsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
func queryRewardFactorsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { func queryRewardFactorsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
_, _, _, err := rest.ParseHTTPArgsWithLimit(r, 0)
if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
}
// Parse the query height
cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r) cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok { if !ok {
return return
} }
var denom string
if x := r.URL.Query().Get(RestDenom); len(x) != 0 {
denom = strings.TrimSpace(x)
}
params := types.NewQueryRewardFactorsParams(denom)
bz, err := cliCtx.Codec.MarshalJSON(params)
if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
}
route := fmt.Sprintf("custom/%s/%s", types.ModuleName, types.QueryGetRewardFactors) route := fmt.Sprintf("custom/%s/%s", types.ModuleName, types.QueryGetRewardFactors)
res, height, err := cliCtx.QueryWithData(route, bz)
cliCtx = cliCtx.WithHeight(height) res, height, err := cliCtx.QueryWithData(route, nil)
if err != nil { if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return return
} }
cliCtx = cliCtx.WithHeight(height)
rest.PostProcessResponse(w, cliCtx, res) rest.PostProcessResponse(w, cliCtx, res)
} }
} }
func executeHardRewardsQuery(w http.ResponseWriter, cliCtx context.CLIContext, params types.QueryHardRewardsParams) { func executeHardRewardsQuery(w http.ResponseWriter, cliCtx context.CLIContext, params types.QueryRewardsParams) {
bz, err := cliCtx.Codec.MarshalJSON(params) bz, err := cliCtx.Codec.MarshalJSON(params)
if err != nil { if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("failed to marshal query params: %s", err)) rest.WriteErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("failed to marshal query params: %s", err))
@ -171,24 +131,7 @@ func executeHardRewardsQuery(w http.ResponseWriter, cliCtx context.CLIContext, p
rest.PostProcessResponse(w, cliCtx, res) rest.PostProcessResponse(w, cliCtx, res)
} }
func executeHardRewardsUnsyncedQuery(w http.ResponseWriter, cliCtx context.CLIContext, params types.QueryHardRewardsUnsyncedParams) { func executeUSDXMintingRewardsQuery(w http.ResponseWriter, cliCtx context.CLIContext, params types.QueryRewardsParams) {
bz, err := cliCtx.Codec.MarshalJSON(params)
if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("failed to marshal query params: %s", err))
return
}
res, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/incentive/%s", types.QueryGetHardRewardsUnsynced), bz)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
cliCtx = cliCtx.WithHeight(height)
rest.PostProcessResponse(w, cliCtx, res)
}
func executeUSDXMintingRewardsQuery(w http.ResponseWriter, cliCtx context.CLIContext, params types.QueryUSDXMintingRewardsParams) {
bz, err := cliCtx.Codec.MarshalJSON(params) bz, err := cliCtx.Codec.MarshalJSON(params)
if err != nil { if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("failed to marshal query params: %s", err)) rest.WriteErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("failed to marshal query params: %s", err))
@ -205,24 +148,7 @@ func executeUSDXMintingRewardsQuery(w http.ResponseWriter, cliCtx context.CLICon
rest.PostProcessResponse(w, cliCtx, res) rest.PostProcessResponse(w, cliCtx, res)
} }
func executeUSDXMintingRewardsUnsyncedQuery(w http.ResponseWriter, cliCtx context.CLIContext, params types.QueryUSDXMintingRewardsUnsyncedParams) { func executeDelegatorRewardsQuery(w http.ResponseWriter, cliCtx context.CLIContext, params types.QueryRewardsParams) {
bz, err := cliCtx.Codec.MarshalJSON(params)
if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("failed to marshal query params: %s", err))
return
}
res, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/incentive/%s", types.QueryGetUSDXMintingRewardsUnsynced), bz)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
cliCtx = cliCtx.WithHeight(height)
rest.PostProcessResponse(w, cliCtx, res)
}
func executeDelegatorRewardsQuery(w http.ResponseWriter, cliCtx context.CLIContext, params types.QueryDelegatorRewardsParams) {
bz, err := cliCtx.Codec.MarshalJSON(params) bz, err := cliCtx.Codec.MarshalJSON(params)
if err != nil { if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("failed to marshal query params: %s", err)) rest.WriteErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("failed to marshal query params: %s", err))
@ -239,14 +165,14 @@ func executeDelegatorRewardsQuery(w http.ResponseWriter, cliCtx context.CLIConte
rest.PostProcessResponse(w, cliCtx, res) rest.PostProcessResponse(w, cliCtx, res)
} }
func executeDelegatorRewardsUnsyncedQuery(w http.ResponseWriter, cliCtx context.CLIContext, params types.QueryDelegatorRewardsUnsyncedParams) { func executeSwapRewardsQuery(w http.ResponseWriter, cliCtx context.CLIContext, params types.QueryRewardsParams) {
bz, err := cliCtx.Codec.MarshalJSON(params) bz, err := cliCtx.Codec.MarshalJSON(params)
if err != nil { if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("failed to marshal query params: %s", err)) rest.WriteErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("failed to marshal query params: %s", err))
return return
} }
res, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/incentive/%s", types.QueryGetDelegatorRewardsUnsynced), bz) res, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/incentive/%s", types.QueryGetSwapRewards), bz)
if err != nil { if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return return
@ -256,16 +182,14 @@ func executeDelegatorRewardsUnsyncedQuery(w http.ResponseWriter, cliCtx context.
rest.PostProcessResponse(w, cliCtx, res) rest.PostProcessResponse(w, cliCtx, res)
} }
func executeAllRewardQueries(w http.ResponseWriter, cliCtx context.CLIContext, func executeAllRewardQueries(w http.ResponseWriter, cliCtx context.CLIContext, params types.QueryRewardsParams) {
hardParams types.QueryHardRewardsParams, usdxMintingParams types.QueryUSDXMintingRewardsParams,
delegatorParams types.QueryDelegatorRewardsParams) { paramsBz, err := cliCtx.Codec.MarshalJSON(params)
hardBz, err := cliCtx.Codec.MarshalJSON(hardParams)
if err != nil { if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("failed to marshal query params: %s", err)) rest.WriteErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("failed to marshal query params: %s", err))
return return
} }
hardRes, _, err := cliCtx.QueryWithData(fmt.Sprintf("custom/incentive/%s", types.QueryGetHardRewards), paramsBz)
hardRes, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/incentive/%s", types.QueryGetHardRewards), hardBz)
if err != nil { if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return return
@ -273,13 +197,7 @@ func executeAllRewardQueries(w http.ResponseWriter, cliCtx context.CLIContext,
var hardClaims types.HardLiquidityProviderClaims var hardClaims types.HardLiquidityProviderClaims
cliCtx.Codec.MustUnmarshalJSON(hardRes, &hardClaims) cliCtx.Codec.MustUnmarshalJSON(hardRes, &hardClaims)
usdxMintingBz, err := cliCtx.Codec.MarshalJSON(usdxMintingParams) usdxMintingRes, _, err := cliCtx.QueryWithData(fmt.Sprintf("custom/incentive/%s", types.QueryGetUSDXMintingRewards), paramsBz)
if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("failed to marshal query params: %s", err))
return
}
usdxMintingRes, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/incentive/%s", types.QueryGetUSDXMintingRewards), usdxMintingBz)
if err != nil { if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return return
@ -287,81 +205,7 @@ func executeAllRewardQueries(w http.ResponseWriter, cliCtx context.CLIContext,
var usdxMintingClaims types.USDXMintingClaims var usdxMintingClaims types.USDXMintingClaims
cliCtx.Codec.MustUnmarshalJSON(usdxMintingRes, &usdxMintingClaims) cliCtx.Codec.MustUnmarshalJSON(usdxMintingRes, &usdxMintingClaims)
delegatorBz, err := cliCtx.Codec.MarshalJSON(delegatorParams) delegatorRes, _, err := cliCtx.QueryWithData(fmt.Sprintf("custom/incentive/%s", types.QueryGetDelegatorRewards), paramsBz)
if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("failed to marshal query params: %s", err))
return
}
delegatorRes, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/incentive/%s", types.QueryGetDelegatorRewards), delegatorBz)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
var delegatorClaims types.DelegatorClaims
cliCtx.Codec.MustUnmarshalJSON(delegatorRes, &delegatorClaims)
cliCtx = cliCtx.WithHeight(height)
type rewardResult struct {
HardClaims types.HardLiquidityProviderClaims `json:"hard_claims" yaml:"hard_claims"`
UsdxMintingClaims types.USDXMintingClaims `json:"usdx_minting_claims" yaml:"usdx_minting_claims"`
DelegatorClaims types.DelegatorClaims `json:"delegator_claims" yaml:"delegator_claims"`
}
res := rewardResult{
HardClaims: hardClaims,
UsdxMintingClaims: usdxMintingClaims,
DelegatorClaims: delegatorClaims,
}
resBz, err := cliCtx.Codec.MarshalJSON(res)
if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("failed to marshal result: %s", err))
return
}
rest.PostProcessResponse(w, cliCtx, resBz)
}
func executeAllUnsyncedRewardQueries(w http.ResponseWriter, cliCtx context.CLIContext,
hardParams types.QueryHardRewardsUnsyncedParams, usdxMintingParams types.QueryUSDXMintingRewardsUnsyncedParams,
delegatorParams types.QueryDelegatorRewardsUnsyncedParams) {
hardBz, err := cliCtx.Codec.MarshalJSON(hardParams)
if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("failed to marshal query params: %s", err))
return
}
hardRes, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/incentive/%s", types.QueryGetHardRewardsUnsynced), hardBz)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
var hardClaims types.HardLiquidityProviderClaims
cliCtx.Codec.MustUnmarshalJSON(hardRes, &hardClaims)
usdxMintingBz, err := cliCtx.Codec.MarshalJSON(usdxMintingParams)
if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("failed to marshal query params: %s", err))
return
}
usdxMintingRes, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/incentive/%s", types.QueryGetUSDXMintingRewardsUnsynced), usdxMintingBz)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
var usdxMintingClaims types.USDXMintingClaims
cliCtx.Codec.MustUnmarshalJSON(usdxMintingRes, &usdxMintingClaims)
delegatorBz, err := cliCtx.Codec.MarshalJSON(delegatorParams)
if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("failed to marshal query params: %s", err))
return
}
delegatorRes, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/incentive/%s", types.QueryGetDelegatorRewardsUnsynced), delegatorBz)
if err != nil { if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return return
@ -369,18 +213,28 @@ func executeAllUnsyncedRewardQueries(w http.ResponseWriter, cliCtx context.CLICo
var delegatorClaims types.DelegatorClaims var delegatorClaims types.DelegatorClaims
cliCtx.Codec.MustUnmarshalJSON(delegatorRes, &delegatorClaims) cliCtx.Codec.MustUnmarshalJSON(delegatorRes, &delegatorClaims)
swapRes, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/incentive/%s", types.QueryGetSwapRewards), paramsBz)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
var swapClaims types.SwapClaims
cliCtx.Codec.MustUnmarshalJSON(swapRes, &swapClaims)
cliCtx = cliCtx.WithHeight(height) cliCtx = cliCtx.WithHeight(height)
type rewardResult struct { type rewardResult struct {
HardClaims types.HardLiquidityProviderClaims `json:"hard_claims" yaml:"hard_claims"` HardClaims types.HardLiquidityProviderClaims `json:"hard_claims" yaml:"hard_claims"`
UsdxMintingClaims types.USDXMintingClaims `json:"usdx_minting_claims" yaml:"usdx_minting_claims"` UsdxMintingClaims types.USDXMintingClaims `json:"usdx_minting_claims" yaml:"usdx_minting_claims"`
DelegatorClaims types.DelegatorClaims `json:"delegator_claims" yaml:"delegator_claims"` DelegatorClaims types.DelegatorClaims `json:"delegator_claims" yaml:"delegator_claims"`
SwapClaims types.SwapClaims `json:"swap_claims" yaml:"swap_claims"`
} }
res := rewardResult{ res := rewardResult{
HardClaims: hardClaims, HardClaims: hardClaims,
UsdxMintingClaims: usdxMintingClaims, UsdxMintingClaims: usdxMintingClaims,
DelegatorClaims: delegatorClaims, DelegatorClaims: delegatorClaims,
SwapClaims: swapClaims,
} }
resBz, err := cliCtx.Codec.MarshalJSON(res) resBz, err := cliCtx.Codec.MarshalJSON(res)

View File

@ -115,6 +115,11 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, supplyKeeper types.SupplyKeep
} }
k.SetDelegatorClaim(ctx, claim) k.SetDelegatorClaim(ctx, claim)
} }
// TODO no synchronization of swap claims as it is about to be removed in a subsequent PR
for _, claim := range gs.SwapClaims {
k.SetSwapClaim(ctx, claim)
}
} }
// ExportGenesis export genesis state for incentive module // ExportGenesis export genesis state for incentive module
@ -124,10 +129,12 @@ func ExportGenesis(ctx sdk.Context, k keeper.Keeper) types.GenesisState {
usdxClaims := k.GetAllUSDXMintingClaims(ctx) usdxClaims := k.GetAllUSDXMintingClaims(ctx)
hardClaims := k.GetAllHardLiquidityProviderClaims(ctx) hardClaims := k.GetAllHardLiquidityProviderClaims(ctx)
delegatorClaims := k.GetAllDelegatorClaims(ctx) delegatorClaims := k.GetAllDelegatorClaims(ctx)
swapClaims := k.GetAllSwapClaims(ctx)
synchronizedUsdxClaims := types.USDXMintingClaims{} synchronizedUsdxClaims := types.USDXMintingClaims{}
synchronizedHardClaims := types.HardLiquidityProviderClaims{} synchronizedHardClaims := types.HardLiquidityProviderClaims{}
synchronizedDelegatorClaims := types.DelegatorClaims{} synchronizedDelegatorClaims := types.DelegatorClaims{}
// TODO no synchronization of swap claims as it is about to be removed in a subsequent PR
for _, usdxClaim := range usdxClaims { for _, usdxClaim := range usdxClaims {
claim, err := k.SynchronizeUSDXMintingClaim(ctx, usdxClaim) claim, err := k.SynchronizeUSDXMintingClaim(ctx, usdxClaim)
@ -222,7 +229,9 @@ func ExportGenesis(ctx sdk.Context, k keeper.Keeper) types.GenesisState {
swapGats = append(swapGats, gat) swapGats = append(swapGats, gat)
} }
return types.NewGenesisState(params, usdxMintingGats, hardSupplyGats, return types.NewGenesisState(
hardBorrowGats, delegatorGats, swapGats, synchronizedUsdxClaims, params,
synchronizedHardClaims, synchronizedDelegatorClaims) usdxMintingGats, hardSupplyGats, hardBorrowGats, delegatorGats, swapGats,
synchronizedUsdxClaims, synchronizedHardClaims, synchronizedDelegatorClaims, swapClaims,
)
} }

View File

@ -77,6 +77,7 @@ func (suite *GenesisTestSuite) SetupTest() {
incentive.DefaultUSDXClaims, incentive.DefaultUSDXClaims,
incentive.DefaultHardClaims, incentive.DefaultHardClaims,
incentive.DefaultDelegatorClaims, incentive.DefaultDelegatorClaims,
incentive.DefaultSwapClaims,
) )
tApp.InitializeFromGenesisStatesWithTime( tApp.InitializeFromGenesisStatesWithTime(
suite.genesisTime, suite.genesisTime,

View File

@ -60,6 +60,7 @@ func (suite *HandlerTestSuite) SetupTest() {
incentive.DefaultUSDXClaims, incentive.DefaultUSDXClaims,
incentive.DefaultHardClaims, incentive.DefaultHardClaims,
incentive.DefaultDelegatorClaims, incentive.DefaultDelegatorClaims,
incentive.DefaultSwapClaims,
) )
tApp.InitializeFromGenesisStates(authGS, app.GenesisState{incentive.ModuleName: incentive.ModuleCdc.MustMarshalJSON(incentiveGS)}, NewCDPGenStateMulti(), NewPricefeedGenStateMulti()) tApp.InitializeFromGenesisStates(authGS, app.GenesisState{incentive.ModuleName: incentive.ModuleCdc.MustMarshalJSON(incentiveGS)}, NewCDPGenStateMulti(), NewPricefeedGenStateMulti())

View File

@ -6,6 +6,7 @@ import (
cdptypes "github.com/kava-labs/kava/x/cdp/types" cdptypes "github.com/kava-labs/kava/x/cdp/types"
hardtypes "github.com/kava-labs/kava/x/hard/types" hardtypes "github.com/kava-labs/kava/x/hard/types"
swaptypes "github.com/kava-labs/kava/x/swap/types"
) )
// Hooks wrapper struct for hooks // Hooks wrapper struct for hooks
@ -16,6 +17,7 @@ type Hooks struct {
var _ cdptypes.CDPHooks = Hooks{} var _ cdptypes.CDPHooks = Hooks{}
var _ hardtypes.HARDHooks = Hooks{} var _ hardtypes.HARDHooks = Hooks{}
var _ stakingtypes.StakingHooks = Hooks{} var _ stakingtypes.StakingHooks = Hooks{}
var _ swaptypes.SwapHooks = Hooks{}
// Hooks create new incentive hooks // Hooks create new incentive hooks
func (k Keeper) Hooks() Hooks { return Hooks{k} } func (k Keeper) Hooks() Hooks { return Hooks{k} }
@ -149,3 +151,13 @@ func (h Hooks) BeforeValidatorModified(ctx sdk.Context, valAddr sdk.ValAddress)
// AfterValidatorRemoved runs after a validator is removed // AfterValidatorRemoved runs after a validator is removed
func (h Hooks) AfterValidatorRemoved(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) { func (h Hooks) AfterValidatorRemoved(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) {
} }
// ------------------- Swap Module Hooks -------------------
func (h Hooks) AfterPoolDepositCreated(ctx sdk.Context, poolID string, depositor sdk.AccAddress, _ sdk.Int) {
h.k.InitializeSwapReward(ctx, poolID, depositor)
}
func (h Hooks) BeforePoolDepositModified(ctx sdk.Context, poolID string, depositor sdk.AccAddress, sharesOwned sdk.Int) {
h.k.SynchronizeSwapReward(ctx, poolID, depositor, sharesOwned)
}

View File

@ -259,6 +259,55 @@ func (k Keeper) GetAllDelegatorClaims(ctx sdk.Context) types.DelegatorClaims {
return cs return cs
} }
// GetSwapClaim returns the claim in the store corresponding the the input address.
func (k Keeper) GetSwapClaim(ctx sdk.Context, addr sdk.AccAddress) (types.SwapClaim, bool) {
store := prefix.NewStore(ctx.KVStore(k.key), types.SwapClaimKeyPrefix)
bz := store.Get(addr)
if bz == nil {
return types.SwapClaim{}, false
}
var c types.SwapClaim
k.cdc.MustUnmarshalBinaryBare(bz, &c)
return c, true
}
// SetSwapClaim sets the claim in the store corresponding to the input address.
func (k Keeper) SetSwapClaim(ctx sdk.Context, c types.SwapClaim) {
store := prefix.NewStore(ctx.KVStore(k.key), types.SwapClaimKeyPrefix)
bz := k.cdc.MustMarshalBinaryBare(c)
store.Set(c.Owner, bz)
}
// DeleteSwapClaim deletes the claim in the store corresponding to the input address.
func (k Keeper) DeleteSwapClaim(ctx sdk.Context, owner sdk.AccAddress) {
store := prefix.NewStore(ctx.KVStore(k.key), types.SwapClaimKeyPrefix)
store.Delete(owner)
}
// IterateSwapClaims iterates over all claim objects in the store and preforms a callback function
func (k Keeper) IterateSwapClaims(ctx sdk.Context, cb func(c types.SwapClaim) (stop bool)) {
store := prefix.NewStore(ctx.KVStore(k.key), types.SwapClaimKeyPrefix)
iterator := sdk.KVStorePrefixIterator(store, []byte{})
defer iterator.Close()
for ; iterator.Valid(); iterator.Next() {
var c types.SwapClaim
k.cdc.MustUnmarshalBinaryBare(iterator.Value(), &c)
if cb(c) {
break
}
}
}
// GetAllSwapClaims returns all Claim objects in the store
func (k Keeper) GetAllSwapClaims(ctx sdk.Context) types.SwapClaims {
cs := types.SwapClaims{}
k.IterateSwapClaims(ctx, func(c types.SwapClaim) (stop bool) {
cs = append(cs, c)
return false
})
return cs
}
// SetHardSupplyRewardIndexes sets the current reward indexes for an individual denom // SetHardSupplyRewardIndexes sets the current reward indexes for an individual denom
func (k Keeper) SetHardSupplyRewardIndexes(ctx sdk.Context, denom string, indexes types.RewardIndexes) { func (k Keeper) SetHardSupplyRewardIndexes(ctx sdk.Context, denom string, indexes types.RewardIndexes) {
store := prefix.NewStore(ctx.KVStore(k.key), types.HardSupplyRewardIndexesKeyPrefix) store := prefix.NewStore(ctx.KVStore(k.key), types.HardSupplyRewardIndexesKeyPrefix)
@ -428,6 +477,20 @@ func (k Keeper) GetSwapRewardIndexes(ctx sdk.Context, poolID string) (types.Rewa
return rewardIndexes, true return rewardIndexes, true
} }
// IterateSwapRewardIndexes iterates over all swap reward index objects in the store and preforms a callback function
func (k Keeper) IterateSwapRewardIndexes(ctx sdk.Context, cb func(poolID string, indexes types.RewardIndexes) (stop bool)) {
store := prefix.NewStore(ctx.KVStore(k.key), types.SwapRewardIndexesKeyPrefix)
iterator := sdk.KVStorePrefixIterator(store, []byte{})
defer iterator.Close()
for ; iterator.Valid(); iterator.Next() {
var indexes types.RewardIndexes
k.cdc.MustUnmarshalBinaryBare(iterator.Value(), &indexes)
if cb(string(iterator.Key()), indexes) {
break
}
}
}
// GetSwapRewardAccrualTime fetches the last time rewards were accrued for a swap pool. // GetSwapRewardAccrualTime fetches the last time rewards were accrued for a swap pool.
func (k Keeper) GetSwapRewardAccrualTime(ctx sdk.Context, poolID string) (blockTime time.Time, found bool) { func (k Keeper) GetSwapRewardAccrualTime(ctx sdk.Context, poolID string) (blockTime time.Time, found bool) {
store := prefix.NewStore(ctx.KVStore(k.key), types.PreviousSwapRewardAccrualTimeKeyPrefix) store := prefix.NewStore(ctx.KVStore(k.key), types.PreviousSwapRewardAccrualTimeKeyPrefix)

View File

@ -82,6 +82,46 @@ func (suite *KeeperTestSuite) TestIterateUSDXMintingClaims() {
suite.Require().Equal(len(suite.addrs), len(claims)) suite.Require().Equal(len(suite.addrs), len(claims))
} }
func (suite *KeeperTestSuite) TestGetSetDeleteSwapClaims() {
suite.SetupApp()
c := types.NewSwapClaim(suite.addrs[0], arbitraryCoins(), nonEmptyMultiRewardIndexes)
_, found := suite.keeper.GetSwapClaim(suite.ctx, suite.addrs[0])
suite.Require().False(found)
suite.Require().NotPanics(func() {
suite.keeper.SetSwapClaim(suite.ctx, c)
})
testC, found := suite.keeper.GetSwapClaim(suite.ctx, suite.addrs[0])
suite.Require().True(found)
suite.Require().Equal(c, testC)
suite.Require().NotPanics(func() {
suite.keeper.DeleteSwapClaim(suite.ctx, suite.addrs[0])
})
_, found = suite.keeper.GetSwapClaim(suite.ctx, suite.addrs[0])
suite.Require().False(found)
}
func (suite *KeeperTestSuite) TestIterateSwapClaims() {
suite.SetupApp()
claims := types.SwapClaims{
types.NewSwapClaim(suite.addrs[0], arbitraryCoins(), nonEmptyMultiRewardIndexes),
types.NewSwapClaim(suite.addrs[1], nil, nil), // different claim to the first
}
for _, claim := range claims {
suite.keeper.SetSwapClaim(suite.ctx, claim)
}
var actualClaims types.SwapClaims
suite.keeper.IterateSwapClaims(suite.ctx, func(c types.SwapClaim) bool {
actualClaims = append(actualClaims, c)
return false
})
suite.Require().Equal(claims, actualClaims)
}
func (suite *KeeperTestSuite) TestGetSetSwapRewardIndexes() { func (suite *KeeperTestSuite) TestGetSetSwapRewardIndexes() {
testCases := []struct { testCases := []struct {
name string name string
@ -155,6 +195,45 @@ func (suite *KeeperTestSuite) TestGetSetSwapRewardIndexes() {
} }
} }
func (suite *KeeperTestSuite) TestIterateSwapRewardIndexes() {
suite.SetupApp()
multiIndexes := types.MultiRewardIndexes{
{
CollateralType: "bnb/usdx",
RewardIndexes: types.RewardIndexes{
{
CollateralType: "swap",
RewardFactor: d("0.0000002"),
},
{
CollateralType: "ukava",
RewardFactor: d("0.04"),
},
},
},
{
CollateralType: "btcb/usdx",
RewardIndexes: types.RewardIndexes{
{
CollateralType: "hard",
RewardFactor: d("0.02"),
},
},
},
}
for _, mi := range multiIndexes {
suite.keeper.SetSwapRewardIndexes(suite.ctx, mi.CollateralType, mi.RewardIndexes)
}
var actualMultiIndexes types.MultiRewardIndexes
suite.keeper.IterateSwapRewardIndexes(suite.ctx, func(poolID string, i types.RewardIndexes) bool {
actualMultiIndexes = actualMultiIndexes.With(poolID, i)
return false
})
suite.Require().Equal(multiIndexes, actualMultiIndexes)
}
func (suite *KeeperTestSuite) TestGetSetSwapRewardAccrualTimes() { func (suite *KeeperTestSuite) TestGetSetSwapRewardAccrualTimes() {
testCases := []struct { testCases := []struct {
name string name string

View File

@ -17,18 +17,16 @@ func NewQuerier(k Keeper) sdk.Querier {
switch path[0] { switch path[0] {
case types.QueryGetParams: case types.QueryGetParams:
return queryGetParams(ctx, req, k) return queryGetParams(ctx, req, k)
case types.QueryGetHardRewards: case types.QueryGetHardRewards:
return queryGetHardRewards(ctx, req, k) return queryGetHardRewards(ctx, req, k)
case types.QueryGetHardRewardsUnsynced:
return queryGetHardRewardsUnsynced(ctx, req, k)
case types.QueryGetUSDXMintingRewards: case types.QueryGetUSDXMintingRewards:
return queryGetUSDXMintingRewards(ctx, req, k) return queryGetUSDXMintingRewards(ctx, req, k)
case types.QueryGetUSDXMintingRewardsUnsynced:
return queryGetUSDXMintingRewardsUnsynced(ctx, req, k)
case types.QueryGetDelegatorRewards: case types.QueryGetDelegatorRewards:
return queryGetDelegatorRewards(ctx, req, k) return queryGetDelegatorRewards(ctx, req, k)
case types.QueryGetDelegatorRewardsUnsynced: case types.QueryGetSwapRewards:
return queryGetDelegatorRewardsUnsynced(ctx, req, k) return queryGetSwapRewards(ctx, req, k)
case types.QueryGetRewardFactors: case types.QueryGetRewardFactors:
return queryGetRewardFactors(ctx, req, k) return queryGetRewardFactors(ctx, req, k)
default: default:
@ -51,7 +49,7 @@ func queryGetParams(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, e
} }
func queryGetHardRewards(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) { func queryGetHardRewards(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) {
var params types.QueryHardRewardsParams var params types.QueryRewardsParams
err := types.ModuleCdc.UnmarshalJSON(req.Data, &params) err := types.ModuleCdc.UnmarshalJSON(req.Data, &params)
if err != nil { if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
@ -77,45 +75,10 @@ func queryGetHardRewards(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]by
paginatedHardClaims = hardClaims[startH:endH] paginatedHardClaims = hardClaims[startH:endH]
} }
var augmentedHardClaims types.HardLiquidityProviderClaims if !params.Unsynchronized {
for _, claim := range paginatedHardClaims { for i, claim := range paginatedHardClaims {
augmentedClaim := k.SimulateHardSynchronization(ctx, claim) paginatedHardClaims[i] = k.SimulateHardSynchronization(ctx, claim)
augmentedHardClaims = append(augmentedHardClaims, augmentedClaim)
} }
// Marshal Hard claims
bz, err := codec.MarshalJSONIndent(k.cdc, augmentedHardClaims)
if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
}
return bz, nil
}
func queryGetHardRewardsUnsynced(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) {
var params types.QueryHardRewardsUnsyncedParams
err := types.ModuleCdc.UnmarshalJSON(req.Data, &params)
if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
}
owner := len(params.Owner) > 0
var hardClaims types.HardLiquidityProviderClaims
switch {
case owner:
hardClaim, foundHardClaim := k.GetHardLiquidityProviderClaim(ctx, params.Owner)
if foundHardClaim {
hardClaims = append(hardClaims, hardClaim)
}
default:
hardClaims = k.GetAllHardLiquidityProviderClaims(ctx)
}
var paginatedHardClaims types.HardLiquidityProviderClaims
startH, endH := client.Paginate(len(hardClaims), params.Page, params.Limit, 100)
if startH < 0 || endH < 0 {
paginatedHardClaims = types.HardLiquidityProviderClaims{}
} else {
paginatedHardClaims = hardClaims[startH:endH]
} }
// Marshal Hard claims // Marshal Hard claims
@ -127,7 +90,7 @@ func queryGetHardRewardsUnsynced(ctx sdk.Context, req abci.RequestQuery, k Keepe
} }
func queryGetUSDXMintingRewards(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) { func queryGetUSDXMintingRewards(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) {
var params types.QueryUSDXMintingRewardsParams var params types.QueryRewardsParams
err := types.ModuleCdc.UnmarshalJSON(req.Data, &params) err := types.ModuleCdc.UnmarshalJSON(req.Data, &params)
if err != nil { if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
@ -153,45 +116,10 @@ func queryGetUSDXMintingRewards(ctx sdk.Context, req abci.RequestQuery, k Keeper
paginatedUsdxMintingClaims = usdxMintingClaims[startU:endU] paginatedUsdxMintingClaims = usdxMintingClaims[startU:endU]
} }
var augmentedUsdxMintingClaims types.USDXMintingClaims if !params.Unsynchronized {
for _, claim := range paginatedUsdxMintingClaims { for i, claim := range paginatedUsdxMintingClaims {
augmentedClaim := k.SimulateUSDXMintingSynchronization(ctx, claim) paginatedUsdxMintingClaims[i] = k.SimulateUSDXMintingSynchronization(ctx, claim)
augmentedUsdxMintingClaims = append(augmentedUsdxMintingClaims, augmentedClaim)
} }
// Marshal USDX minting claims
bz, err := codec.MarshalJSONIndent(k.cdc, augmentedUsdxMintingClaims)
if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
}
return bz, nil
}
func queryGetUSDXMintingRewardsUnsynced(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) {
var params types.QueryUSDXMintingRewardsUnsyncedParams
err := types.ModuleCdc.UnmarshalJSON(req.Data, &params)
if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
}
owner := len(params.Owner) > 0
var usdxMintingClaims types.USDXMintingClaims
switch {
case owner:
usdxMintingClaim, foundUsdxMintingClaim := k.GetUSDXMintingClaim(ctx, params.Owner)
if foundUsdxMintingClaim {
usdxMintingClaims = append(usdxMintingClaims, usdxMintingClaim)
}
default:
usdxMintingClaims = k.GetAllUSDXMintingClaims(ctx)
}
var paginatedUsdxMintingClaims types.USDXMintingClaims
startU, endU := client.Paginate(len(usdxMintingClaims), params.Page, params.Limit, 100)
if startU < 0 || endU < 0 {
paginatedUsdxMintingClaims = types.USDXMintingClaims{}
} else {
paginatedUsdxMintingClaims = usdxMintingClaims[startU:endU]
} }
// Marshal USDX minting claims // Marshal USDX minting claims
@ -203,7 +131,7 @@ func queryGetUSDXMintingRewardsUnsynced(ctx sdk.Context, req abci.RequestQuery,
} }
func queryGetDelegatorRewards(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) { func queryGetDelegatorRewards(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) {
var params types.QueryDelegatorRewardsParams var params types.QueryRewardsParams
err := types.ModuleCdc.UnmarshalJSON(req.Data, &params) err := types.ModuleCdc.UnmarshalJSON(req.Data, &params)
if err != nil { if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
@ -229,45 +157,10 @@ func queryGetDelegatorRewards(ctx sdk.Context, req abci.RequestQuery, k Keeper)
paginatedDelegatorClaims = delegatorClaims[startH:endH] paginatedDelegatorClaims = delegatorClaims[startH:endH]
} }
var augmentedDelegatorClaims types.DelegatorClaims if !params.Unsynchronized {
for _, claim := range paginatedDelegatorClaims { for i, claim := range paginatedDelegatorClaims {
augmentedClaim := k.SimulateDelegatorSynchronization(ctx, claim) paginatedDelegatorClaims[i] = k.SimulateDelegatorSynchronization(ctx, claim)
augmentedDelegatorClaims = append(augmentedDelegatorClaims, augmentedClaim)
} }
// Marshal Hard claims
bz, err := codec.MarshalJSONIndent(k.cdc, augmentedDelegatorClaims)
if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
}
return bz, nil
}
func queryGetDelegatorRewardsUnsynced(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) {
var params types.QueryDelegatorRewardsUnsyncedParams
err := types.ModuleCdc.UnmarshalJSON(req.Data, &params)
if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
}
owner := len(params.Owner) > 0
var delegatorClaims types.DelegatorClaims
switch {
case owner:
delegatorClaim, foundHardClaim := k.GetDelegatorClaim(ctx, params.Owner)
if foundHardClaim {
delegatorClaims = append(delegatorClaims, delegatorClaim)
}
default:
delegatorClaims = k.GetAllDelegatorClaims(ctx)
}
var paginatedDelegatorClaims types.DelegatorClaims
startH, endH := client.Paginate(len(delegatorClaims), params.Page, params.Limit, 100)
if startH < 0 || endH < 0 {
paginatedDelegatorClaims = types.DelegatorClaims{}
} else {
paginatedDelegatorClaims = delegatorClaims[startH:endH]
} }
// Marshal Hard claims // Marshal Hard claims
@ -278,89 +171,92 @@ func queryGetDelegatorRewardsUnsynced(ctx sdk.Context, req abci.RequestQuery, k
return bz, nil return bz, nil
} }
func queryGetRewardFactors(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) { func queryGetSwapRewards(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) {
var params types.QueryRewardFactorsParams var params types.QueryRewardsParams
err := types.ModuleCdc.UnmarshalJSON(req.Data, &params) err := types.ModuleCdc.UnmarshalJSON(req.Data, &params)
if err != nil { if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
} }
owner := len(params.Owner) > 0
var rewardFactors types.RewardFactors var claims types.SwapClaims
if len(params.Denom) > 0 { switch {
// Fetch reward factors for a single denom case owner:
rewardFactor := types.RewardFactor{} claim, found := k.GetSwapClaim(ctx, params.Owner)
rewardFactor.Denom = params.Denom if found {
claims = append(claims, claim)
}
default:
claims = k.GetAllSwapClaims(ctx)
}
usdxMintingRewardFactor, found := k.GetUSDXMintingRewardFactor(ctx, params.Denom) var paginatedClaims types.SwapClaims
if found { startH, endH := client.Paginate(len(claims), params.Page, params.Limit, 100)
rewardFactor.USDXMintingRewardFactor = usdxMintingRewardFactor if startH < 0 || endH < 0 {
} paginatedClaims = types.SwapClaims{}
hardSupplyRewardIndexes, found := k.GetHardSupplyRewardIndexes(ctx, params.Denom)
if found {
rewardFactor.HardSupplyRewardFactors = hardSupplyRewardIndexes
}
hardBorrowRewardIndexes, found := k.GetHardBorrowRewardIndexes(ctx, params.Denom)
if found {
rewardFactor.HardBorrowRewardFactors = hardBorrowRewardIndexes
}
delegatorRewardIndexes, found := k.GetDelegatorRewardIndexes(ctx, params.Denom)
if found {
rewardFactor.DelegatorRewardFactors = delegatorRewardIndexes
}
rewardFactors = append(rewardFactors, rewardFactor)
} else { } else {
rewardFactorMap := make(map[string]types.RewardFactor) paginatedClaims = claims[startH:endH]
}
// Populate mapping with usdx minting reward factors if !params.Unsynchronized {
k.IterateUSDXMintingRewardFactors(ctx, func(denom string, factor sdk.Dec) (stop bool) { for i, claim := range paginatedClaims {
rewardFactor := types.RewardFactor{Denom: denom, USDXMintingRewardFactor: factor} syncedClaim, found := k.GetSynchronizedSwapClaim(ctx, claim.Owner)
rewardFactorMap[denom] = rewardFactor if !found {
panic("previously found claim should still be found")
}
paginatedClaims[i] = syncedClaim
}
}
// Marshal claims
bz, err := codec.MarshalJSONIndent(k.cdc, paginatedClaims)
if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
}
return bz, nil
}
func queryGetRewardFactors(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) {
var usdxFactors types.RewardIndexes
k.IterateUSDXMintingRewardFactors(ctx, func(collateralType string, factor sdk.Dec) (stop bool) {
usdxFactors = usdxFactors.With(collateralType, factor)
return false return false
}) })
// Populate mapping with Hard supply reward factors var supplyFactors types.MultiRewardIndexes
k.IterateHardSupplyRewardIndexes(ctx, func(denom string, indexes types.RewardIndexes) (stop bool) { k.IterateHardSupplyRewardIndexes(ctx, func(denom string, indexes types.RewardIndexes) (stop bool) {
rewardFactor, ok := rewardFactorMap[denom] supplyFactors = supplyFactors.With(denom, indexes)
if !ok {
rewardFactor = types.RewardFactor{Denom: denom, HardSupplyRewardFactors: indexes}
} else {
rewardFactor.HardSupplyRewardFactors = indexes
}
rewardFactorMap[denom] = rewardFactor
return false return false
}) })
// Populate mapping with Hard borrow reward factors var borrowFactors types.MultiRewardIndexes
k.IterateHardBorrowRewardIndexes(ctx, func(denom string, indexes types.RewardIndexes) (stop bool) { k.IterateHardBorrowRewardIndexes(ctx, func(denom string, indexes types.RewardIndexes) (stop bool) {
rewardFactor, ok := rewardFactorMap[denom] borrowFactors = borrowFactors.With(denom, indexes)
if !ok {
rewardFactor = types.RewardFactor{Denom: denom, HardBorrowRewardFactors: indexes}
} else {
rewardFactor.HardBorrowRewardFactors = indexes
}
rewardFactorMap[denom] = rewardFactor
return false return false
}) })
// Populate mapping with delegator reward factors var delegatorFactors types.MultiRewardIndexes
k.IterateDelegatorRewardIndexes(ctx, func(denom string, indexes types.RewardIndexes) (stop bool) { k.IterateDelegatorRewardIndexes(ctx, func(denom string, indexes types.RewardIndexes) (stop bool) {
rewardFactor, ok := rewardFactorMap[denom] delegatorFactors = delegatorFactors.With(denom, indexes)
if !ok {
rewardFactor = types.RewardFactor{Denom: denom, DelegatorRewardFactors: indexes}
} else {
rewardFactor.DelegatorRewardFactors = indexes
}
rewardFactorMap[denom] = rewardFactor
return false return false
}) })
// Translate mapping to slice var swapFactors types.MultiRewardIndexes
for _, val := range rewardFactorMap { k.IterateSwapRewardIndexes(ctx, func(poolID string, indexes types.RewardIndexes) (stop bool) {
rewardFactors = append(rewardFactors, val) swapFactors = swapFactors.With(poolID, indexes)
} return false
} })
bz, err := codec.MarshalJSONIndent(types.ModuleCdc, rewardFactors) response := types.NewQueryGetRewardFactorsResponse(
usdxFactors,
supplyFactors,
borrowFactors,
delegatorFactors,
swapFactors,
)
bz, err := codec.MarshalJSONIndent(types.ModuleCdc, response)
if err != nil { if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
} }

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/incentive/types" "github.com/kava-labs/kava/x/incentive/types"
@ -24,10 +26,10 @@ func (k Keeper) AccumulateSwapRewards(ctx sdk.Context, rewardPeriod types.MultiR
totalShares, found := k.swapKeeper.GetPoolShares(ctx, rewardPeriod.CollateralType) totalShares, found := k.swapKeeper.GetPoolShares(ctx, rewardPeriod.CollateralType)
if !found { if !found {
totalShares = sdk.ZeroDec() totalShares = sdk.ZeroInt()
} }
acc.Accumulate(rewardPeriod, totalShares, ctx.BlockTime()) acc.Accumulate(rewardPeriod, totalShares.ToDec(), ctx.BlockTime())
k.SetSwapRewardAccrualTime(ctx, rewardPeriod.CollateralType, acc.PreviousAccumulationTime) k.SetSwapRewardAccrualTime(ctx, rewardPeriod.CollateralType, acc.PreviousAccumulationTime)
if len(acc.Indexes) > 0 { if len(acc.Indexes) > 0 {
@ -35,3 +37,85 @@ func (k Keeper) AccumulateSwapRewards(ctx sdk.Context, rewardPeriod types.MultiR
k.SetSwapRewardIndexes(ctx, rewardPeriod.CollateralType, acc.Indexes) k.SetSwapRewardIndexes(ctx, rewardPeriod.CollateralType, acc.Indexes)
} }
} }
// InitializeSwapReward creates a new claim with zero rewards and indexes matching the global indexes.
// If the claim already exists it just updates the indexes.
func (k Keeper) InitializeSwapReward(ctx sdk.Context, poolID string, owner sdk.AccAddress) {
claim, found := k.GetSwapClaim(ctx, owner)
if !found {
claim = types.NewSwapClaim(owner, sdk.Coins{}, nil)
}
globalRewardIndexes, found := k.GetSwapRewardIndexes(ctx, poolID)
if !found {
globalRewardIndexes = types.RewardIndexes{}
}
claim.RewardIndexes = claim.RewardIndexes.With(poolID, globalRewardIndexes)
k.SetSwapClaim(ctx, claim)
}
// SynchronizeSwapReward updates the claim object by adding any accumulated rewards
// and updating the reward index value.
func (k Keeper) SynchronizeSwapReward(ctx sdk.Context, poolID string, owner sdk.AccAddress, shares sdk.Int) {
claim, found := k.GetSwapClaim(ctx, owner)
if !found {
return
}
claim = k.synchronizeSwapReward(ctx, claim, poolID, owner, shares)
k.SetSwapClaim(ctx, claim)
}
// synchronizeSwapReward updates the reward in a swap claim for one pool.
func (k *Keeper) synchronizeSwapReward(ctx sdk.Context, claim types.SwapClaim, poolID string, owner sdk.AccAddress, shares sdk.Int) types.SwapClaim {
globalRewardIndexes, found := k.GetSwapRewardIndexes(ctx, poolID)
if !found {
// The global factor is only not found if
// - the pool has not started accumulating rewards yet (either there is no reward specified in params, or the reward start time hasn't been hit)
// - OR it was wrongly deleted from state (factors should never be removed while unsynced claims exist)
// If not found we could either skip this sync, or assume the global factor is zero.
// Skipping will avoid storing unnecessary factors in the claim for non rewarded pools.
// And in the event a global factor is wrongly deleted, it will avoid this function panicking when calculating rewards.
return claim
}
userRewardIndexes, found := claim.RewardIndexes.Get(poolID)
if !found {
// Normally the reward indexes should always be found.
// But if a pool was not rewarded then becomes rewarded (ie a reward period is added to params), then the indexes will be missing from claims for that pool.
// So given the reward period was just added, assume the starting value for any global reward indexes, which is an empty slice.
userRewardIndexes = types.RewardIndexes{}
}
newRewards, err := k.CalculateRewards(userRewardIndexes, globalRewardIndexes, shares.ToDec())
if err != nil {
// Global reward factors should never decrease, as it would lead to a negative update to claim.Rewards.
// This panics if a global reward factor decreases or disappears between the old and new indexes.
panic(fmt.Sprintf("corrupted global reward indexes found: %v", err))
}
claim.Reward = claim.Reward.Add(newRewards...)
claim.RewardIndexes = claim.RewardIndexes.With(poolID, globalRewardIndexes)
return claim
}
// GetSynchronizedSwapClaim fetches a swap claim from the store and syncs rewards for all pools.
func (k Keeper) GetSynchronizedSwapClaim(ctx sdk.Context, owner sdk.AccAddress) (types.SwapClaim, bool) {
claim, found := k.GetSwapClaim(ctx, owner)
if !found {
return types.SwapClaim{}, false
}
for _, indexes := range claim.RewardIndexes {
poolID := indexes.CollateralType
shares, found := k.swapKeeper.GetDepositorSharesInPool(ctx, owner, poolID)
if !found {
shares = sdk.ZeroInt()
}
claim = k.synchronizeSwapReward(ctx, claim, poolID, owner, shares)
}
return claim, true
}

View File

@ -0,0 +1,195 @@
package keeper_test
import (
"testing"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/suite"
"github.com/kava-labs/kava/x/incentive/types"
)
// InitializeSwapRewardTests runs unit tests for the keeper.InitializeSwapReward method
//
// inputs
// - claim in store if it exists
// - global indexes in store
//
// outputs
// - sets or creates a claim
type InitializeSwapRewardTests struct {
unitTester
}
func TestInitializeSwapReward(t *testing.T) {
suite.Run(t, new(InitializeSwapRewardTests))
}
func (suite *InitializeSwapRewardTests) TestClaimAddedWhenClaimDoesNotExistAndNoRewards() {
// When a claim doesn't exist, and a user deposits to a non-rewarded pool;
// then a claim is added with no rewards and no indexes
poolID := "base/quote"
// no global indexes stored as this pool is not rewarded
owner := arbitraryAddress()
suite.keeper.InitializeSwapReward(suite.ctx, poolID, owner)
syncedClaim, found := suite.keeper.GetSwapClaim(suite.ctx, owner)
suite.True(found)
// A new claim should have empty indexes. It doesn't strictly need the poolID either.
expectedIndexes := types.MultiRewardIndexes{{
CollateralType: poolID,
RewardIndexes: nil,
}}
suite.Equal(expectedIndexes, syncedClaim.RewardIndexes)
// a new claim should start with 0 rewards
suite.Equal(sdk.Coins(nil), syncedClaim.Reward)
}
func (suite *InitializeSwapRewardTests) TestClaimAddedWhenClaimDoesNotExistAndRewardsExist() {
// When a claim doesn't exist, and a user deposits to a rewarded pool;
// then a claim is added with no rewards and indexes matching the global indexes
poolID := "base/quote"
globalIndexes := types.MultiRewardIndexes{
{
CollateralType: poolID,
RewardIndexes: types.RewardIndexes{
{
CollateralType: "rewarddenom",
RewardFactor: d("1000.001"),
},
},
},
}
suite.storeGlobalSwapIndexes(globalIndexes)
owner := arbitraryAddress()
suite.keeper.InitializeSwapReward(suite.ctx, poolID, owner)
syncedClaim, found := suite.keeper.GetSwapClaim(suite.ctx, owner)
suite.True(found)
// a new claim should start with the current global indexes
suite.Equal(globalIndexes, syncedClaim.RewardIndexes)
// a new claim should start with 0 rewards
suite.Equal(sdk.Coins(nil), syncedClaim.Reward)
}
func (suite *InitializeSwapRewardTests) TestClaimUpdatedWhenClaimExistsAndNoRewards() {
// When a claim exists, and a user deposits to a new non-rewarded pool;
// then the claim's rewards don't change
preexistingPoolID := "preexisting"
preexistingIndexes := types.RewardIndexes{
{
CollateralType: "rewarddenom",
RewardFactor: d("1000.001"),
},
}
newPoolID := "btcb/usdx"
claim := types.SwapClaim{
BaseMultiClaim: types.BaseMultiClaim{
Owner: arbitraryAddress(),
Reward: arbitraryCoins(),
},
RewardIndexes: types.MultiRewardIndexes{
{
CollateralType: preexistingPoolID,
RewardIndexes: preexistingIndexes,
},
},
}
suite.storeSwapClaim(claim)
// no global indexes stored as the new pool is not rewarded
suite.keeper.InitializeSwapReward(suite.ctx, newPoolID, claim.Owner)
syncedClaim, _ := suite.keeper.GetSwapClaim(suite.ctx, claim.Owner)
// The preexisting indexes shouldn't be changed. It doesn't strictly need the new poolID either.
expectedIndexes := types.MultiRewardIndexes{
{
CollateralType: preexistingPoolID,
RewardIndexes: preexistingIndexes,
},
{
CollateralType: newPoolID,
RewardIndexes: nil,
},
}
suite.Equal(expectedIndexes, syncedClaim.RewardIndexes)
// init should never alter the rewards
suite.Equal(claim.Reward, syncedClaim.Reward)
}
func (suite *InitializeSwapRewardTests) TestClaimUpdatedWhenClaimExistsAndRewardsExist() {
// When a claim exists, and a user deposits to a new rewarded pool;
// then the claim's rewards don't change and the indexes are updated to match the global indexes
preexistingPoolID := "preexisting"
preexistingIndexes := types.RewardIndexes{
{
CollateralType: "rewarddenom",
RewardFactor: d("1000.001"),
},
}
newPoolID := "btcb/usdx"
newIndexes := types.RewardIndexes{
{
CollateralType: "otherrewarddenom",
RewardFactor: d("1000.001"),
},
}
claim := types.SwapClaim{
BaseMultiClaim: types.BaseMultiClaim{
Owner: arbitraryAddress(),
Reward: arbitraryCoins(),
},
RewardIndexes: types.MultiRewardIndexes{
{
CollateralType: preexistingPoolID,
RewardIndexes: preexistingIndexes,
},
},
}
suite.storeSwapClaim(claim)
globalIndexes := types.MultiRewardIndexes{
{
CollateralType: preexistingPoolID,
RewardIndexes: increaseRewardFactors(preexistingIndexes),
},
{
CollateralType: newPoolID,
RewardIndexes: newIndexes,
},
}
suite.storeGlobalSwapIndexes(globalIndexes)
suite.keeper.InitializeSwapReward(suite.ctx, newPoolID, claim.Owner)
syncedClaim, _ := suite.keeper.GetSwapClaim(suite.ctx, claim.Owner)
// only the indexes for the new pool should be updated
expectedIndexes := types.MultiRewardIndexes{
{
CollateralType: preexistingPoolID,
RewardIndexes: preexistingIndexes,
},
{
CollateralType: newPoolID,
RewardIndexes: newIndexes,
},
}
suite.Equal(expectedIndexes, syncedClaim.RewardIndexes)
// init should never alter the rewards
suite.Equal(claim.Reward, syncedClaim.Reward)
}

View File

@ -0,0 +1,317 @@
package keeper_test
import (
"testing"
"github.com/stretchr/testify/suite"
"github.com/kava-labs/kava/x/incentive/types"
)
// SynchronizeSwapRewardTests runs unit tests for the keeper.SynchronizeSwapReward method
//
// inputs
// - claim in store (only claim.RewardIndexes, claim.Reward)
// - global indexes in store
// - shares function arg
//
// outputs
// - sets a claim
type SynchronizeSwapRewardTests struct {
unitTester
}
func TestSynchronizeSwapReward(t *testing.T) {
suite.Run(t, new(SynchronizeSwapRewardTests))
}
func (suite *SynchronizeSwapRewardTests) TestClaimUpdatedWhenGlobalIndexesHaveIncreased() {
// This is the normal case
// Given some time has passed (meaning the global indexes have increased)
// When the claim is synced
// The user earns rewards for the time passed, and the claim indexes are updated
originalReward := arbitraryCoins()
poolID := "base/quote"
claim := types.SwapClaim{
BaseMultiClaim: types.BaseMultiClaim{
Owner: arbitraryAddress(),
Reward: originalReward,
},
RewardIndexes: types.MultiRewardIndexes{
{
CollateralType: poolID,
RewardIndexes: types.RewardIndexes{
{
CollateralType: "rewarddenom",
RewardFactor: d("1000.001"),
},
},
},
},
}
suite.storeSwapClaim(claim)
globalIndexes := types.MultiRewardIndexes{
{
CollateralType: poolID,
RewardIndexes: types.RewardIndexes{
{
CollateralType: "rewarddenom",
RewardFactor: d("2000.002"),
},
},
},
}
suite.storeGlobalSwapIndexes(globalIndexes)
userShares := i(1e9)
suite.keeper.SynchronizeSwapReward(suite.ctx, poolID, claim.Owner, userShares)
syncedClaim, _ := suite.keeper.GetSwapClaim(suite.ctx, claim.Owner)
// indexes updated from global
suite.Equal(globalIndexes, syncedClaim.RewardIndexes)
// new reward is (new index - old index) * user shares
suite.Equal(
cs(c("rewarddenom", 1_000_001_000_000)).Add(originalReward...),
syncedClaim.Reward,
)
}
func (suite *SynchronizeSwapRewardTests) TestClaimUnchangedWhenGlobalIndexesUnchanged() {
// It should be safe to call SynchronizeSwapReward multiple times
poolID := "base/quote"
unchangingIndexes := types.MultiRewardIndexes{
{
CollateralType: poolID,
RewardIndexes: types.RewardIndexes{
{
CollateralType: "rewarddenom",
RewardFactor: d("1000.001"),
},
},
},
}
claim := types.SwapClaim{
BaseMultiClaim: types.BaseMultiClaim{
Owner: arbitraryAddress(),
Reward: arbitraryCoins(),
},
RewardIndexes: unchangingIndexes,
}
suite.storeSwapClaim(claim)
suite.storeGlobalSwapIndexes(unchangingIndexes)
userShares := i(1e9)
suite.keeper.SynchronizeSwapReward(suite.ctx, poolID, claim.Owner, userShares)
syncedClaim, _ := suite.keeper.GetSwapClaim(suite.ctx, claim.Owner)
// claim should have the same rewards and indexes as before
suite.Equal(claim, syncedClaim)
}
func (suite *SynchronizeSwapRewardTests) TestClaimUpdatedWhenNewRewardAdded() {
// When a new reward is added (via gov) for a pool the user has already deposited to, and the claim is synced;
// Then the user earns rewards for the time since the reward was added, and the indexes are added to the claim.
originalReward := arbitraryCoins()
newlyRewardPoolID := "newlyRewardedPool"
claim := types.SwapClaim{
BaseMultiClaim: types.BaseMultiClaim{
Owner: arbitraryAddress(),
Reward: originalReward,
},
RewardIndexes: types.MultiRewardIndexes{
{
CollateralType: "currentlyRewardedPool",
RewardIndexes: types.RewardIndexes{
{
CollateralType: "reward",
RewardFactor: d("1000.001"),
},
},
},
},
}
suite.storeSwapClaim(claim)
globalIndexes := types.MultiRewardIndexes{
{
CollateralType: "currentlyRewardedPool",
RewardIndexes: types.RewardIndexes{
{
CollateralType: "reward",
RewardFactor: d("2000.002"),
},
},
},
{
CollateralType: newlyRewardPoolID,
RewardIndexes: types.RewardIndexes{
{
CollateralType: "otherreward",
// Indexes start at 0 when the reward is added by gov,
// so this represents the syncing happening some time later.
RewardFactor: d("1000.001"),
},
},
},
}
suite.storeGlobalSwapIndexes(globalIndexes)
userShares := i(1e9)
suite.keeper.SynchronizeSwapReward(suite.ctx, newlyRewardPoolID, claim.Owner, userShares)
syncedClaim, _ := suite.keeper.GetSwapClaim(suite.ctx, claim.Owner)
// the new indexes should be added to the claim, but the old ones should be unchanged
newlyRewrdedIndexes, _ := globalIndexes.Get(newlyRewardPoolID)
expectedIndexes := claim.RewardIndexes.With(newlyRewardPoolID, newlyRewrdedIndexes)
suite.Equal(expectedIndexes, syncedClaim.RewardIndexes)
// new reward is (new index - old index) * shares for the synced pool
// The old index for `newlyrewarded` isn't in the claim, so it's added starting at 0 for calculating the reward.
suite.Equal(
cs(c("otherreward", 1_000_001_000_000)).Add(originalReward...),
syncedClaim.Reward,
)
}
func (suite *SynchronizeSwapRewardTests) TestClaimUnchangedWhenNoReward() {
// When a pool is not rewarded but the user has deposited to that pool, and the claim is synced;
// Then the claim should be the same.
claim := types.SwapClaim{
BaseMultiClaim: types.BaseMultiClaim{
Owner: arbitraryAddress(),
Reward: arbitraryCoins(),
},
RewardIndexes: nonEmptyMultiRewardIndexes,
}
suite.storeSwapClaim(claim)
poolID := "nonRewardPool"
// No global indexes stored as this pool is not rewarded
userShares := i(1e9)
suite.keeper.SynchronizeSwapReward(suite.ctx, poolID, claim.Owner, userShares)
syncedClaim, _ := suite.keeper.GetSwapClaim(suite.ctx, claim.Owner)
suite.Equal(claim, syncedClaim)
}
func (suite *SynchronizeSwapRewardTests) TestClaimUpdatedWhenNewRewardDenomAdded() {
// When a new reward coin is added (via gov) to an already rewarded pool (that the user has already deposited to), and the claim is synced;
// Then the user earns rewards for the time since the reward was added, and the new indexes are added.
originalReward := arbitraryCoins()
poolID := "base/quote"
claim := types.SwapClaim{
BaseMultiClaim: types.BaseMultiClaim{
Owner: arbitraryAddress(),
Reward: originalReward,
},
RewardIndexes: types.MultiRewardIndexes{
{
CollateralType: poolID,
RewardIndexes: types.RewardIndexes{
{
CollateralType: "reward",
RewardFactor: d("1000.001"),
},
},
},
},
}
suite.storeSwapClaim(claim)
globalIndexes := types.MultiRewardIndexes{
{
CollateralType: poolID,
RewardIndexes: types.RewardIndexes{
{
CollateralType: "reward",
RewardFactor: d("2000.002"),
},
{
CollateralType: "otherreward",
// Indexes start at 0 when the reward is added by gov,
// so this represents the syncing happening some time later.
RewardFactor: d("1000.001"),
},
},
},
}
suite.storeGlobalSwapIndexes(globalIndexes)
userShares := i(1e9)
suite.keeper.SynchronizeSwapReward(suite.ctx, poolID, claim.Owner, userShares)
syncedClaim, _ := suite.keeper.GetSwapClaim(suite.ctx, claim.Owner)
// indexes should have the new reward denom added
suite.Equal(globalIndexes, syncedClaim.RewardIndexes)
// new reward is (new index - old index) * shares
// The old index for `otherreward` isn't in the claim, so it's added starting at 0 for calculating the reward.
suite.Equal(
cs(c("reward", 1_000_001_000_000), c("otherreward", 1_000_001_000_000)).Add(originalReward...),
syncedClaim.Reward,
)
}
func (suite *SynchronizeSwapRewardTests) TestClaimUpdatedWhenGlobalIndexesIncreasedAndSourceIsZero() {
// Given some time has passed (meaning the global indexes have increased)
// When the claim is synced, but the user has no shares
// The user earns no rewards for the time passed, but the claim indexes are updated
poolID := "base/quote"
claim := types.SwapClaim{
BaseMultiClaim: types.BaseMultiClaim{
Owner: arbitraryAddress(),
Reward: arbitraryCoins(),
},
RewardIndexes: types.MultiRewardIndexes{
{
CollateralType: poolID,
RewardIndexes: types.RewardIndexes{
{
CollateralType: "rewarddenom",
RewardFactor: d("1000.001"),
},
},
},
},
}
suite.storeSwapClaim(claim)
globalIndexes := types.MultiRewardIndexes{
{
CollateralType: poolID,
RewardIndexes: types.RewardIndexes{
{
CollateralType: "rewarddenom",
RewardFactor: d("2000.002"),
},
},
},
}
suite.storeGlobalSwapIndexes(globalIndexes)
userShares := i(0)
suite.keeper.SynchronizeSwapReward(suite.ctx, poolID, claim.Owner, userShares)
syncedClaim, _ := suite.keeper.GetSwapClaim(suite.ctx, claim.Owner)
// indexes updated from global
suite.Equal(globalIndexes, syncedClaim.RewardIndexes)
// reward is unchanged
suite.Equal(claim.Reward, syncedClaim.Reward)
}

View File

@ -31,7 +31,7 @@ func TestAccumulateSwapRewards(t *testing.T) {
} }
func (suite *AccumulateSwapRewardsTests) TestStateUpdatedWhenBlockTimeHasIncreased() { func (suite *AccumulateSwapRewardsTests) TestStateUpdatedWhenBlockTimeHasIncreased() {
swapKeeper := &fakeSwapKeeper{d("1000000")} swapKeeper := &fakeSwapKeeper{i(1e6)}
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, swapKeeper) suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, swapKeeper)
pool := "btc/usdx" pool := "btc/usdx"
@ -84,7 +84,7 @@ func (suite *AccumulateSwapRewardsTests) TestStateUpdatedWhenBlockTimeHasIncreas
} }
func (suite *AccumulateSwapRewardsTests) TestLimitsOfAccumulationPrecision() { func (suite *AccumulateSwapRewardsTests) TestLimitsOfAccumulationPrecision() {
swapKeeper := &fakeSwapKeeper{d("100000000000000000")} // approximate shares in a $1B pool of 10^8 precision assets swapKeeper := &fakeSwapKeeper{i(1e17)} // approximate shares in a $1B pool of 10^8 precision ~$1 asset
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, swapKeeper) suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, swapKeeper)
pool := "btc/usdx" pool := "btc/usdx"
@ -130,7 +130,7 @@ func (suite *AccumulateSwapRewardsTests) TestLimitsOfAccumulationPrecision() {
} }
func (suite *AccumulateSwapRewardsTests) TestStateUnchangedWhenBlockTimeHasNotIncreased() { func (suite *AccumulateSwapRewardsTests) TestStateUnchangedWhenBlockTimeHasNotIncreased() {
swapKeeper := &fakeSwapKeeper{d("1000000")} swapKeeper := &fakeSwapKeeper{i(1e6)}
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, swapKeeper) suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, swapKeeper)
pool := "btc/usdx" pool := "btc/usdx"
@ -182,7 +182,7 @@ func (suite *AccumulateSwapRewardsTests) TestStateUnchangedWhenBlockTimeHasNotIn
} }
func (suite *AccumulateSwapRewardsTests) TestStateAddedWhenStateDoesNotExist() { func (suite *AccumulateSwapRewardsTests) TestStateAddedWhenStateDoesNotExist() {
swapKeeper := &fakeSwapKeeper{d("1000000")} swapKeeper := &fakeSwapKeeper{i(1e6)}
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, swapKeeper) suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, swapKeeper)
pool := "btc/usdx" pool := "btc/usdx"
@ -225,7 +225,7 @@ func (suite *AccumulateSwapRewardsTests) TestStateAddedWhenStateDoesNotExist() {
suite.checkStoredIndexesEqual(pool, expectedIndexes) suite.checkStoredIndexesEqual(pool, expectedIndexes)
} }
func (suite *AccumulateSwapRewardsTests) TestNoPanicWhenStateDoesNotExist() { func (suite *AccumulateSwapRewardsTests) TestNoPanicWhenStateDoesNotExist() {
swapKeeper := &fakeSwapKeeper{d("0")} swapKeeper := &fakeSwapKeeper{i(0)}
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, swapKeeper) suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, swapKeeper)
pool := "btc/usdx" pool := "btc/usdx"
@ -252,12 +252,16 @@ func (suite *AccumulateSwapRewardsTests) TestNoPanicWhenStateDoesNotExist() {
} }
type fakeSwapKeeper struct { type fakeSwapKeeper struct {
poolShares sdk.Dec poolShares sdk.Int
} }
func (k fakeSwapKeeper) GetPoolShares(ctx sdk.Context, poolID string) (sdk.Dec, bool) { func (k fakeSwapKeeper) GetPoolShares(ctx sdk.Context, poolID string) (sdk.Int, bool) {
return k.poolShares, true return k.poolShares, true
} }
func (k fakeSwapKeeper) GetDepositorSharesInPool(ctx sdk.Context, depositor sdk.AccAddress, poolID string) (sdk.Int, bool) {
// This is just to implement the swap keeper interface.
return sdk.Int{}, false
}
// note: amino panics when encoding times ≥ the start of year 10000. // note: amino panics when encoding times ≥ the start of year 10000.
var distantFuture = time.Date(9000, 1, 1, 0, 0, 0, 0, time.UTC) var distantFuture = time.Date(9000, 1, 1, 0, 0, 0, 0, time.UTC)

View File

@ -87,10 +87,12 @@ func (suite *unitTester) storeGlobalSwapIndexes(indexes types.MultiRewardIndexes
func (suite *unitTester) storeHardClaim(claim types.HardLiquidityProviderClaim) { func (suite *unitTester) storeHardClaim(claim types.HardLiquidityProviderClaim) {
suite.keeper.SetHardLiquidityProviderClaim(suite.ctx, claim) suite.keeper.SetHardLiquidityProviderClaim(suite.ctx, claim)
} }
func (suite *unitTester) storeDelegatorClaim(claim types.DelegatorClaim) { func (suite *unitTester) storeDelegatorClaim(claim types.DelegatorClaim) {
suite.keeper.SetDelegatorClaim(suite.ctx, claim) suite.keeper.SetDelegatorClaim(suite.ctx, claim)
} }
func (suite *unitTester) storeSwapClaim(claim types.SwapClaim) {
suite.keeper.SetSwapClaim(suite.ctx, claim)
}
type fakeParamSubspace struct { type fakeParamSubspace struct {
params types.Params params types.Params

View File

@ -12,6 +12,7 @@ const (
USDXMintingClaimType = "usdx_minting" USDXMintingClaimType = "usdx_minting"
HardLiquidityProviderClaimType = "hard_liquidity_provider" HardLiquidityProviderClaimType = "hard_liquidity_provider"
DelegatorClaimType = "delegator_claim" DelegatorClaimType = "delegator_claim"
SwapClaimType = "swap"
BondDenom = "ukava" BondDenom = "ukava"
) )
@ -314,6 +315,71 @@ func (cs DelegatorClaims) Validate() error {
return nil return nil
} }
// SwapClaim stores the swap rewards that can be claimed by owner
type SwapClaim struct {
BaseMultiClaim `json:"base_claim" yaml:"base_claim"`
RewardIndexes MultiRewardIndexes `json:"reward_indexes" yaml:"reward_indexes"`
}
// NewSwapClaim returns a new SwapClaim
func NewSwapClaim(owner sdk.AccAddress, rewards sdk.Coins, rewardIndexes MultiRewardIndexes) SwapClaim {
return SwapClaim{
BaseMultiClaim: BaseMultiClaim{
Owner: owner,
Reward: rewards,
},
RewardIndexes: rewardIndexes,
}
}
// GetType returns the claim's type
func (c SwapClaim) GetType() string { return SwapClaimType }
// GetReward returns the claim's reward coin
func (c SwapClaim) GetReward() sdk.Coins { return c.Reward }
// GetOwner returns the claim's owner
func (c SwapClaim) GetOwner() sdk.AccAddress { return c.Owner }
// Validate performs a basic check of a SwapClaim fields
func (c SwapClaim) Validate() error {
if err := c.RewardIndexes.Validate(); err != nil {
return err
}
return c.BaseMultiClaim.Validate()
}
// String implements fmt.Stringer
func (c SwapClaim) String() string {
return fmt.Sprintf(`%s
Reward Indexes: %s,
`, c.BaseMultiClaim, c.RewardIndexes)
}
// HasRewardIndex check if a claim has a reward index for the input pool ID.
func (c SwapClaim) HasRewardIndex(poolID string) (int64, bool) {
for index, ri := range c.RewardIndexes {
if ri.CollateralType == poolID {
return int64(index), true
}
}
return 0, false
}
// SwapClaims slice of SwapClaim
type SwapClaims []SwapClaim
// Validate checks if all the claims are valid.
func (cs SwapClaims) Validate() error {
for _, c := range cs {
if err := c.Validate(); err != nil {
return err
}
}
return nil
}
// ---------------------- Reward indexes are used internally in the store ---------------------- // ---------------------- Reward indexes are used internally in the store ----------------------
// RewardIndex stores reward accumulation information // RewardIndex stores reward accumulation information

View File

@ -18,11 +18,13 @@ func c(denom string, amount int64) sdk.Coin { return sdk.NewInt64Coin(denom, amo
// c is a helper function for created sdk.Coins types in tests // c is a helper function for created sdk.Coins types in tests
func cs(coins ...sdk.Coin) sdk.Coins { return sdk.NewCoins(coins...) } func cs(coins ...sdk.Coin) sdk.Coins { return sdk.NewCoins(coins...) }
func TestClaimsValidate(t *testing.T) { func TestClaims_Validate(t *testing.T) {
owner := sdk.AccAddress(crypto.AddressHash([]byte("KavaTestUser1"))) owner := sdk.AccAddress(crypto.AddressHash([]byte("KavaTestUser1")))
t.Run("USDXMintingClaims", func(t *testing.T) {
testCases := []struct { testCases := []struct {
msg string name string
claims USDXMintingClaims claims USDXMintingClaims
expPass bool expPass bool
}{ }{
@ -72,13 +74,69 @@ func TestClaimsValidate(t *testing.T) {
} }
for _, tc := range testCases { for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
err := tc.claims.Validate() err := tc.claims.Validate()
if tc.expPass { if tc.expPass {
require.NoError(t, err, tc.msg) require.NoError(t, err)
} else { } else {
require.Error(t, err, tc.msg) require.Error(t, err)
} }
})
} }
})
t.Run("SwapClaims", func(t *testing.T) {
validRewardIndexes := RewardIndexes{}.With("swap", d("0.002"))
validMultiRewardIndexes := MultiRewardIndexes{}.With("btcb/usdx", validRewardIndexes)
invalidRewardIndexes := RewardIndexes{}.With("swap", d("-0.002"))
invalidMultiRewardIndexes := MultiRewardIndexes{}.With("btcb/usdx", invalidRewardIndexes)
testCases := []struct {
name string
claims SwapClaims
expPass bool
}{
{
name: "valid",
claims: SwapClaims{
NewSwapClaim(owner, cs(c("bnb", 1)), validMultiRewardIndexes),
},
expPass: true,
},
{
name: "invalid owner",
claims: SwapClaims{
NewSwapClaim(nil, cs(c("bnb", 1)), validMultiRewardIndexes),
},
expPass: false,
},
{
name: "invalid reward",
claims: SwapClaims{
NewSwapClaim(owner, sdk.Coins{sdk.Coin{Denom: "invalid😫"}}, validMultiRewardIndexes),
},
expPass: false,
},
{
name: "invalid indexes",
claims: SwapClaims{
NewSwapClaim(nil, cs(c("bnb", 1)), invalidMultiRewardIndexes),
},
expPass: false,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
err := tc.claims.Validate()
if tc.expPass {
require.NoError(t, err)
} else {
require.Error(t, err)
}
})
}
})
} }
func TestRewardIndexes(t *testing.T) { func TestRewardIndexes(t *testing.T) {

View File

@ -53,7 +53,8 @@ type HardKeeper interface {
// SwapKeeper defines the required methods needed by this modules keeper // SwapKeeper defines the required methods needed by this modules keeper
type SwapKeeper interface { type SwapKeeper interface {
GetPoolShares(ctx sdk.Context, poolID string) (shares sdk.Dec, found bool) GetPoolShares(ctx sdk.Context, poolID string) (shares sdk.Int, found bool)
GetDepositorSharesInPool(ctx sdk.Context, depositor sdk.AccAddress, poolID string) (shares sdk.Int, found bool)
} }
// AccountKeeper defines the expected keeper interface for interacting with account // AccountKeeper defines the expected keeper interface for interacting with account

View File

@ -17,11 +17,12 @@ type GenesisState struct {
USDXMintingClaims USDXMintingClaims `json:"usdx_minting_claims" yaml:"usdx_minting_claims"` USDXMintingClaims USDXMintingClaims `json:"usdx_minting_claims" yaml:"usdx_minting_claims"`
HardLiquidityProviderClaims HardLiquidityProviderClaims `json:"hard_liquidity_provider_claims" yaml:"hard_liquidity_provider_claims"` HardLiquidityProviderClaims HardLiquidityProviderClaims `json:"hard_liquidity_provider_claims" yaml:"hard_liquidity_provider_claims"`
DelegatorClaims DelegatorClaims `json:"delegator_claims" yaml:"delegator_claims"` DelegatorClaims DelegatorClaims `json:"delegator_claims" yaml:"delegator_claims"`
SwapClaims SwapClaims `json:"swap_claims" yaml:"swap_claims"`
} }
// NewGenesisState returns a new genesis state // NewGenesisState returns a new genesis state
func NewGenesisState(params Params, usdxAccumTimes, hardSupplyAccumTimes, hardBorrowAccumTimes, delegatorAccumTimes, func NewGenesisState(params Params, usdxAccumTimes, hardSupplyAccumTimes, hardBorrowAccumTimes, delegatorAccumTimes,
swapAccumTimes GenesisAccumulationTimes, c USDXMintingClaims, hc HardLiquidityProviderClaims, dc DelegatorClaims) GenesisState { swapAccumTimes GenesisAccumulationTimes, c USDXMintingClaims, hc HardLiquidityProviderClaims, dc DelegatorClaims, sc SwapClaims) GenesisState {
return GenesisState{ return GenesisState{
Params: params, Params: params,
USDXAccumulationTimes: usdxAccumTimes, USDXAccumulationTimes: usdxAccumTimes,
@ -32,6 +33,7 @@ func NewGenesisState(params Params, usdxAccumTimes, hardSupplyAccumTimes, hardBo
USDXMintingClaims: c, USDXMintingClaims: c,
HardLiquidityProviderClaims: hc, HardLiquidityProviderClaims: hc,
DelegatorClaims: dc, DelegatorClaims: dc,
SwapClaims: sc,
} }
} }
@ -47,6 +49,7 @@ func DefaultGenesisState() GenesisState {
USDXMintingClaims: DefaultUSDXClaims, USDXMintingClaims: DefaultUSDXClaims,
HardLiquidityProviderClaims: DefaultHardClaims, HardLiquidityProviderClaims: DefaultHardClaims,
DelegatorClaims: DefaultDelegatorClaims, DelegatorClaims: DefaultDelegatorClaims,
SwapClaims: DefaultSwapClaims,
} }
} }
@ -72,13 +75,16 @@ func (gs GenesisState) Validate() error {
return err return err
} }
if err := gs.HardLiquidityProviderClaims.Validate(); err != nil {
return err
}
if err := gs.USDXMintingClaims.Validate(); err != nil { if err := gs.USDXMintingClaims.Validate(); err != nil {
return err return err
} }
return gs.DelegatorClaims.Validate() if err := gs.HardLiquidityProviderClaims.Validate(); err != nil {
return err
}
if err := gs.DelegatorClaims.Validate(); err != nil {
return err
}
return gs.SwapClaims.Validate()
} }
// Equal checks whether two gov GenesisState structs are equivalent // Equal checks whether two gov GenesisState structs are equivalent

View File

@ -141,6 +141,7 @@ func TestGenesisStateValidate(t *testing.T) {
tc.args.claims, tc.args.claims,
DefaultHardClaims, DefaultHardClaims,
DefaultDelegatorClaims, DefaultDelegatorClaims,
DefaultSwapClaims,
) )
err := gs.Validate() err := gs.Validate()
if tc.errArgs.expectPass { if tc.errArgs.expectPass {

View File

@ -34,8 +34,9 @@ var (
DelegatorClaimKeyPrefix = []byte{0x09} // prefix for keys that store delegator claims DelegatorClaimKeyPrefix = []byte{0x09} // prefix for keys that store delegator claims
DelegatorRewardIndexesKeyPrefix = []byte{0x10} // prefix for key that stores delegator reward indexes DelegatorRewardIndexesKeyPrefix = []byte{0x10} // prefix for key that stores delegator reward indexes
PreviousDelegatorRewardAccrualTimeKeyPrefix = []byte{0x11} // prefix for key that stores the previous time delegator rewards accrued PreviousDelegatorRewardAccrualTimeKeyPrefix = []byte{0x11} // prefix for key that stores the previous time delegator rewards accrued
SwapRewardIndexesKeyPrefix = []byte{0x12} // prefix for key that stores swap reward indexes SwapClaimKeyPrefix = []byte{0x12} // prefix for keys that store swap claims
PreviousSwapRewardAccrualTimeKeyPrefix = []byte{0x13} // prefix for key that stores the previous time swap rewards accrued SwapRewardIndexesKeyPrefix = []byte{0x13} // prefix for key that stores swap reward indexes
PreviousSwapRewardAccrualTimeKeyPrefix = []byte{0x14} // prefix for key that stores the previous time swap rewards accrued
USDXMintingRewardDenom = "ukava" USDXMintingRewardDenom = "ukava"
HardLiquidityRewardDenom = "hard" HardLiquidityRewardDenom = "hard"

View File

@ -38,6 +38,7 @@ var (
DefaultUSDXClaims = USDXMintingClaims{} DefaultUSDXClaims = USDXMintingClaims{}
DefaultHardClaims = HardLiquidityProviderClaims{} DefaultHardClaims = HardLiquidityProviderClaims{}
DefaultDelegatorClaims = DelegatorClaims{} DefaultDelegatorClaims = DelegatorClaims{}
DefaultSwapClaims = SwapClaims{}
DefaultGenesisAccumulationTimes = GenesisAccumulationTimes{} DefaultGenesisAccumulationTimes = GenesisAccumulationTimes{}
DefaultClaimEnd = tmtime.Canonical(time.Unix(1, 0)) DefaultClaimEnd = tmtime.Canonical(time.Unix(1, 0))
GovDenom = cdptypes.DefaultGovDenom GovDenom = cdptypes.DefaultGovDenom

View File

@ -6,169 +6,54 @@ import (
// Querier routes for the incentive module // Querier routes for the incentive module
const ( const (
QueryGetRewards = "rewards"
QueryGetHardRewards = "hard-rewards" QueryGetHardRewards = "hard-rewards"
QueryGetHardRewardsUnsynced = "hard-rewards-unsynced"
QueryGetUSDXMintingRewards = "usdx-minting-rewards" QueryGetUSDXMintingRewards = "usdx-minting-rewards"
QueryGetUSDXMintingRewardsUnsynced = "usdx-minting-rewards-unsynced"
QueryGetDelegatorRewards = "delegator-rewards" QueryGetDelegatorRewards = "delegator-rewards"
QueryGetDelegatorRewardsUnsynced = "delegator-rewards-unsynced" QueryGetSwapRewards = "swap-rewards"
QueryGetRewardFactors = "reward-factors" QueryGetRewardFactors = "reward-factors"
QueryGetParams = "parameters" QueryGetParams = "parameters"
QueryGetRewardPeriods = "reward-periods"
QueryGetClaimPeriods = "claim-periods"
RestClaimCollateralType = "collateral_type" RestClaimCollateralType = "collateral_type"
RestClaimOwner = "owner" RestClaimOwner = "owner"
RestClaimType = "type" RestClaimType = "type"
RestUnsynced = "unsynced" RestUnsynced = "unsynced"
) )
// QueryRewardsParams params for query /incentive/rewards // QueryRewardsParams params for query /incentive/rewards/<claim type>
type QueryRewardsParams struct { type QueryRewardsParams struct {
Page int `json:"page" yaml:"page"` Page int `json:"page" yaml:"page"`
Limit int `json:"limit" yaml:"limit"` Limit int `json:"limit" yaml:"limit"`
Owner sdk.AccAddress Owner sdk.AccAddress `json:"owner" yaml:"owner"`
Type string Unsynchronized bool `json:"unsynchronized" yaml:"unsynchronized"`
} }
// NewQueryRewardsParams returns QueryRewardsParams // NewQueryRewardsParams returns QueryRewardsParams
func NewQueryRewardsParams(page, limit int, owner sdk.AccAddress, rewardType string) QueryRewardsParams { func NewQueryRewardsParams(page, limit int, owner sdk.AccAddress, unsynchronized bool) QueryRewardsParams {
return QueryRewardsParams{ return QueryRewardsParams{
Page: page, Page: page,
Limit: limit, Limit: limit,
Owner: owner, Owner: owner,
Type: rewardType, Unsynchronized: unsynchronized,
} }
} }
// QueryUSDXMintingRewardsParams params for query /incentive/rewards type usdx-minting // QueryGetRewardFactorsResponse holds the response to a reward factor query
type QueryUSDXMintingRewardsParams struct { type QueryGetRewardFactorsResponse struct {
Page int `json:"page" yaml:"page"` USDXMintingRewardFactors RewardIndexes `json:"usdx_minting_reward_factors" yaml:"usdx_minting_reward_factors"`
Limit int `json:"limit" yaml:"limit"` HardSupplyRewardFactors MultiRewardIndexes `json:"hard_supply_reward_factors" yaml:"hard_supply_reward_factors"`
Owner sdk.AccAddress HardBorrowRewardFactors MultiRewardIndexes `json:"hard_borrow_reward_factors" yaml:"hard_borrow_reward_factors"`
DelegatorRewardFactors MultiRewardIndexes `json:"delegator_reward_factors" yaml:"delegator_reward_factors"`
SwapRewardFactors MultiRewardIndexes `json:"swap_reward_factors" yaml:"swap_reward_factors"`
} }
// NewQueryUSDXMintingRewardsParams returns QueryUSDXMintingRewardsParams // NewQueryGetRewardFactorsResponse returns a new instance of QueryAllRewardFactorsResponse
func NewQueryUSDXMintingRewardsParams(page, limit int, owner sdk.AccAddress) QueryUSDXMintingRewardsParams { func NewQueryGetRewardFactorsResponse(usdxMintingFactors RewardIndexes, supplyFactors,
return QueryUSDXMintingRewardsParams{ hardBorrowFactors, delegatorFactors, swapFactors MultiRewardIndexes) QueryGetRewardFactorsResponse {
Page: page, return QueryGetRewardFactorsResponse{
Limit: limit, USDXMintingRewardFactors: usdxMintingFactors,
Owner: owner, HardSupplyRewardFactors: supplyFactors,
HardBorrowRewardFactors: hardBorrowFactors,
DelegatorRewardFactors: delegatorFactors,
SwapRewardFactors: swapFactors,
} }
} }
// QueryUSDXMintingRewardsUnsyncedParams params for query unsynced /incentive/rewards type usdx-minting
type QueryUSDXMintingRewardsUnsyncedParams struct {
Page int `json:"page" yaml:"page"`
Limit int `json:"limit" yaml:"limit"`
Owner sdk.AccAddress
}
// NewQueryUSDXMintingRewardsUnsyncedParams returns QueryUSDXMintingRewardsUnsyncedParams
func NewQueryUSDXMintingRewardsUnsyncedParams(page, limit int, owner sdk.AccAddress) QueryUSDXMintingRewardsUnsyncedParams {
return QueryUSDXMintingRewardsUnsyncedParams{
Page: page,
Limit: limit,
Owner: owner,
}
}
// QueryHardRewardsParams params for query /incentive/rewards type hard
type QueryHardRewardsParams struct {
Page int `json:"page" yaml:"page"`
Limit int `json:"limit" yaml:"limit"`
Owner sdk.AccAddress
}
// NewQueryHardRewardsParams returns QueryHardRewardsParams
func NewQueryHardRewardsParams(page, limit int, owner sdk.AccAddress) QueryHardRewardsParams {
return QueryHardRewardsParams{
Page: page,
Limit: limit,
Owner: owner,
}
}
// QueryHardRewardsUnsyncedParams params for query unsynced /incentive/rewards type hard
type QueryHardRewardsUnsyncedParams struct {
Page int `json:"page" yaml:"page"`
Limit int `json:"limit" yaml:"limit"`
Owner sdk.AccAddress
}
// NewQueryHardRewardsUnsyncedParams returns QueryHardRewardsUnsyncedParams
func NewQueryHardRewardsUnsyncedParams(page, limit int, owner sdk.AccAddress) QueryHardRewardsUnsyncedParams {
return QueryHardRewardsUnsyncedParams{
Page: page,
Limit: limit,
Owner: owner,
}
}
// QueryRewardFactorsParams is the params for a filtered reward factors query
type QueryRewardFactorsParams struct {
Denom string `json:"denom" yaml:"denom"`
}
// NewQueryRewardFactorsParams creates a new QueryRewardFactorsParams
func NewQueryRewardFactorsParams(denom string) QueryRewardFactorsParams {
return QueryRewardFactorsParams{
Denom: denom,
}
}
// QueryDelegatorRewardsParams params for query /incentive/rewards type delegator
type QueryDelegatorRewardsParams struct {
Page int `json:"page" yaml:"page"`
Limit int `json:"limit" yaml:"limit"`
Owner sdk.AccAddress
}
// NewQueryDelegatorRewardsParams returns QueryDelegatorRewardsParams
func NewQueryDelegatorRewardsParams(page, limit int, owner sdk.AccAddress) QueryDelegatorRewardsParams {
return QueryDelegatorRewardsParams{
Page: page,
Limit: limit,
Owner: owner,
}
}
// QueryDelegatorRewardsUnsyncedParams params for query unsynced /incentive/rewards type delegator
type QueryDelegatorRewardsUnsyncedParams struct {
Page int `json:"page" yaml:"page"`
Limit int `json:"limit" yaml:"limit"`
Owner sdk.AccAddress
}
// NewQueryDelegatorRewardsUnsyncedParams returns QueryDelegatorRewardsUnsyncedParams
func NewQueryDelegatorRewardsUnsyncedParams(page, limit int, owner sdk.AccAddress) QueryDelegatorRewardsUnsyncedParams {
return QueryDelegatorRewardsUnsyncedParams{
Page: page,
Limit: limit,
Owner: owner,
}
}
// RewardFactor is a unique type returned by reward factor queries
type RewardFactor struct {
Denom string `json:"denom" yaml:"denom"`
USDXMintingRewardFactor sdk.Dec `json:"usdx_minting_reward_factor" yaml:"usdx_minting_reward_factor"`
HardSupplyRewardFactors RewardIndexes `json:"hard_supply_reward_factors" yaml:"hard_supply_reward_factors"`
HardBorrowRewardFactors RewardIndexes `json:"hard_borrow_reward_factors" yaml:"hard_borrow_reward_factors"`
DelegatorRewardFactors RewardIndexes `json:"delegator_reward_factors" yaml:"delegator_reward_factors"`
}
// NewRewardFactor returns a new instance of RewardFactor
func NewRewardFactor(denom string, usdxMintingRewardFactor sdk.Dec, hardSupplyRewardFactors,
hardBorrowRewardFactors, delegatorRewardFactors RewardIndexes) RewardFactor {
return RewardFactor{
Denom: denom,
USDXMintingRewardFactor: usdxMintingRewardFactor,
HardSupplyRewardFactors: hardSupplyRewardFactors,
HardBorrowRewardFactors: hardBorrowRewardFactors,
DelegatorRewardFactors: delegatorRewardFactors,
}
}
// RewardFactors is a slice of RewardFactor
type RewardFactors = []RewardFactor

View File

@ -2,9 +2,35 @@ package keeper
import ( import (
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/kava-labs/kava/x/swap/types"
) )
func (k Keeper) GetPoolShares(ctx sdk.Context, poolID string) (sdk.Dec, bool) { func (k Keeper) GetPoolShares(ctx sdk.Context, poolID string) (sdk.Int, bool) {
// FIXME return pool shares once merged with acceptance branch // FIXME return pool shares once merged with acceptance branch
return sdk.Dec{}, false return sdk.Int{}, false
}
func (k *Keeper) GetDepositorSharesInPool(ctx sdk.Context, depositor sdk.AccAddress, poolID string) (sdk.Int, bool) {
// FIXME return depositor shares once merged with acceptance branch
return sdk.Int{}, false
}
// Implements SwapHooks interface
var _ types.SwapHooks = Keeper{}
// FIXME call hooks within pool logic
// AfterPoolDepositCreated - call hook if registered
func (k Keeper) AfterPoolDepositCreated(ctx sdk.Context, poolID string, depositor sdk.AccAddress, sharesOwned sdk.Int) {
if k.hooks != nil {
k.hooks.AfterPoolDepositCreated(ctx, poolID, depositor, sharesOwned)
}
}
// BeforePoolDepositModified - call hook if registered
func (k Keeper) BeforePoolDepositModified(ctx sdk.Context, poolID string, depositor sdk.AccAddress, sharesOwned sdk.Int) {
if k.hooks != nil {
k.hooks.BeforePoolDepositModified(ctx, poolID, depositor, sharesOwned)
}
} }

View File

@ -14,6 +14,7 @@ type Keeper struct {
key sdk.StoreKey key sdk.StoreKey
cdc *codec.Codec cdc *codec.Codec
paramSubspace subspace.Subspace paramSubspace subspace.Subspace
hooks types.SwapHooks
accountKeeper types.AccountKeeper accountKeeper types.AccountKeeper
supplyKeeper types.SupplyKeeper supplyKeeper types.SupplyKeeper
} }
@ -39,6 +40,15 @@ func NewKeeper(
} }
} }
// SetHooks adds hooks to the keeper.
func (k *Keeper) SetHooks(sh types.SwapHooks) *Keeper {
if k.hooks != nil {
panic("cannot set swap hooks twice")
}
k.hooks = sh
return k
}
// GetParams returns the params from the store // GetParams returns the params from the store
func (k Keeper) GetParams(ctx sdk.Context) types.Params { func (k Keeper) GetParams(ctx sdk.Context) types.Params {
var p types.Params var p types.Params

View File

@ -1,4 +1,4 @@
package types // noalias package types
import ( import (
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
@ -20,3 +20,9 @@ type AccountKeeper interface {
GetAccount(ctx sdk.Context, addr sdk.AccAddress) authexported.Account GetAccount(ctx sdk.Context, addr sdk.AccAddress) authexported.Account
SetAccount(ctx sdk.Context, acc authexported.Account) SetAccount(ctx sdk.Context, acc authexported.Account)
} }
// SwapHooks are event hooks called when a user's deposit to a swap pool changes.
type SwapHooks interface {
AfterPoolDepositCreated(ctx sdk.Context, poolID string, depositor sdk.AccAddress, sharedOwned sdk.Int)
BeforePoolDepositModified(ctx sdk.Context, poolID string, depositor sdk.AccAddress, sharedOwned sdk.Int)
}