diff --git a/x/incentive/handler.go b/x/incentive/handler.go index d17cca65..d01dda3a 100644 --- a/x/incentive/handler.go +++ b/x/incentive/handler.go @@ -24,7 +24,7 @@ func NewHandler(k keeper.Keeper) sdk.Handler { func handleMsgClaimReward(ctx sdk.Context, k keeper.Keeper, msg types.MsgClaimReward) (*sdk.Result, error) { - claims, found := k.GetClaimsByAddressAndCollateralType(ctx, msg.Sender, msg.CollateralType) + claims, found := k.GetActiveClaimsByAddressAndCollateralType(ctx, msg.Sender, msg.CollateralType) if !found { return nil, sdkerrors.Wrapf(types.ErrNoClaimsFound, "address: %s, collateral type: %s", msg.Sender, msg.CollateralType) } diff --git a/x/incentive/keeper/keeper_test.go b/x/incentive/keeper/keeper_test.go index afdc20a6..5948d87e 100644 --- a/x/incentive/keeper/keeper_test.go +++ b/x/incentive/keeper/keeper_test.go @@ -159,8 +159,8 @@ func (suite *KeeperTestSuite) addObjectsToStore() { suite.keeper.SetClaimPeriod(suite.ctx, cp1) suite.keeper.SetClaimPeriod(suite.ctx, cp2) - suite.keeper.SetNextClaimPeriodID(suite.ctx, "bnb", 1) - suite.keeper.SetNextClaimPeriodID(suite.ctx, "xrp", 1) + suite.keeper.SetNextClaimPeriodID(suite.ctx, "bnb", 2) + suite.keeper.SetNextClaimPeriodID(suite.ctx, "xrp", 2) c1 := types.NewClaim(suite.addrs[0], c("ukava", 1000000), "bnb", 1) c2 := types.NewClaim(suite.addrs[0], c("ukava", 1000000), "xrp", 1) diff --git a/x/incentive/keeper/payout.go b/x/incentive/keeper/payout.go index 94624274..65b5d11f 100644 --- a/x/incentive/keeper/payout.go +++ b/x/incentive/keeper/payout.go @@ -118,8 +118,8 @@ func (k Keeper) DeleteExpiredClaimsAndClaimPeriods(ctx sdk.Context) { }) } -// GetClaimsByAddressAndCollateralType returns all claims for a specific user and address and a bool for if any were found -func (k Keeper) GetClaimsByAddressAndCollateralType(ctx sdk.Context, addr sdk.AccAddress, collateralType string) (claims types.Claims, found bool) { +// GetActiveClaimsByAddressAndCollateralType returns all claims for a specific user and address and a bool for if any were found +func (k Keeper) GetActiveClaimsByAddressAndCollateralType(ctx sdk.Context, addr sdk.AccAddress, collateralType string) (claims types.Claims, found bool) { found = false k.IterateClaimPeriods(ctx, func(cp types.ClaimPeriod) (stop bool) { if cp.CollateralType != collateralType { @@ -136,6 +136,32 @@ func (k Keeper) GetClaimsByAddressAndCollateralType(ctx sdk.Context, addr sdk.Ac return claims, found } +// GetAllClaimsByAddressAndCollateralType returns all claims for a specific user and address and a bool for if any were found +func (k Keeper) GetAllClaimsByAddressAndCollateralType(ctx sdk.Context, addr sdk.AccAddress, collateralType string) (claims types.AugmentedClaims, found bool) { + found = false + k.IterateClaimPeriods(ctx, func(cp types.ClaimPeriod) (stop bool) { + if cp.CollateralType != collateralType { + return false + } + c, hasClaim := k.GetClaim(ctx, addr, cp.CollateralType, cp.ID) + if !hasClaim { + return false + } + ac := types.NewAugmentedClaim(c, true) + found = true + claims = append(claims, ac) + return false + }) + nextClaimID := k.GetNextClaimPeriodID(ctx, collateralType) + c, hasClaim := k.GetClaim(ctx, addr, collateralType, nextClaimID) + if !hasClaim { + return claims, found + } + ac := types.NewAugmentedClaim(c, false) + claims = append(claims, ac) + return claims, true +} + // addCoinsToVestingSchedule adds coins to the input account's vesting schedule where length is the amount of time (from the current block time), in seconds, that the coins will be vesting for // the input address must be a periodic vesting account func (k Keeper) addCoinsToVestingSchedule(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins, length int64) { diff --git a/x/incentive/keeper/querier.go b/x/incentive/keeper/querier.go index 21267566..d068311b 100644 --- a/x/incentive/keeper/querier.go +++ b/x/incentive/keeper/querier.go @@ -73,7 +73,7 @@ func queryGetClaims(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, e if err != nil { return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) } - claims, _ := k.GetClaimsByAddressAndCollateralType(ctx, requestParams.Owner, requestParams.CollateralType) + claims, _ := k.GetAllClaimsByAddressAndCollateralType(ctx, requestParams.Owner, requestParams.CollateralType) bz, err := codec.MarshalJSONIndent(k.cdc, claims) if err != nil { diff --git a/x/incentive/keeper/querier_test.go b/x/incentive/keeper/querier_test.go index 39fb9c21..e5646bc3 100644 --- a/x/incentive/keeper/querier_test.go +++ b/x/incentive/keeper/querier_test.go @@ -26,10 +26,12 @@ func (suite *KeeperTestSuite) TestQuerier() { } bz, err = querier(suite.ctx, []string{types.QueryGetClaims}, query) - var claims types.Claims + var claims types.AugmentedClaims suite.Nil(types.ModuleCdc.UnmarshalJSON(bz, &claims)) suite.Equal(1, len(claims)) - suite.Equal(types.Claims{types.NewClaim(suite.addrs[0], c("ukava", 1000000), "bnb", 1)}, claims) + suite.Equal(types.AugmentedClaims{ + types.NewAugmentedClaim(types.NewClaim(suite.addrs[0], c("ukava", 1000000), "bnb", 1), true), + }, claims) var rp types.RewardPeriods bz, err = querier(suite.ctx, []string{types.QueryGetRewardPeriods}, abci.RequestQuery{}) diff --git a/x/incentive/simulation/operations.go b/x/incentive/simulation/operations.go index cace1334..9cd37ad6 100644 --- a/x/incentive/simulation/operations.go +++ b/x/incentive/simulation/operations.go @@ -78,7 +78,7 @@ func SimulateMsgClaimReward(ak auth.AccountKeeper, sk types.SupplyKeeper, k keep claimer, claim, found := findValidAccountClaimPair(accs, openClaims, func(acc simulation.Account, claim types.Claim) bool { if validAccounts[acc.Address.String()] { // Address must be valid type if claim.Owner.Equals(acc.Address) { // Account must be claim owner - allClaims, found := k.GetClaimsByAddressAndCollateralType(ctx, claim.Owner, claim.CollateralType) + allClaims, found := k.GetActiveClaimsByAddressAndCollateralType(ctx, claim.Owner, claim.CollateralType) if found { // found should always be true var rewards sdk.Coins for _, individualClaim := range allClaims { diff --git a/x/incentive/types/rewards.go b/x/incentive/types/rewards.go index 3f0b5c45..38eda75c 100644 --- a/x/incentive/types/rewards.go +++ b/x/incentive/types/rewards.go @@ -206,6 +206,35 @@ func (c Claim) String() string { // Claims array of Claim type Claims []Claim +// AugmentedClaim claim type with information about whether the claim is currently claimable +type AugmentedClaim struct { + Claim Claim `json:"claim" yaml:"claim"` + + Claimable bool `json:"claimable" yaml:"claimable"` +} + +func (ac AugmentedClaim) String() string { + return fmt.Sprintf(`Claim: + Owner: %s, + Collateral Type: %s, + Reward: %s, + Claim Period ID: %d, + Claimable: %t, + `, ac.Claim.Owner, ac.Claim.CollateralType, ac.Claim.Reward, ac.Claim.ClaimPeriodID, ac.Claimable, + ) +} + +// NewAugmentedClaim returns a new augmented claim struct +func NewAugmentedClaim(claim Claim, claimable bool) AugmentedClaim { + return AugmentedClaim{ + Claim: claim, + Claimable: claimable, + } +} + +// AugmentedClaims array of AugmentedClaim +type AugmentedClaims []AugmentedClaim + // Validate checks if all the claims are valid and there are no duplicated // entries. func (cs Claims) Validate() error {