mirror of
				https://github.com/0glabs/0g-chain.git
				synced 2025-10-31 23:17:27 +00:00 
			
		
		
		
	Add GetSynchronizedClaim and swap adapter (#1386)
* Add source adapters to keeper, implement GetSynchronizedClaim * Iterate acc shares sorted * Add swap adapter, update tests to use swap claimtype * Add swap adapter test * Add tests for non-empty pools * Iterate over source ids instead of sorted keys
This commit is contained in:
		
							parent
							
								
									c2061f626e
								
							
						
					
					
						commit
						f52a581ea9
					
				
							
								
								
									
										46
									
								
								x/incentive/keeper/adapters/swap/adapter.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								x/incentive/keeper/adapters/swap/adapter.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,46 @@ | |||||||
|  | package swap | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	sdk "github.com/cosmos/cosmos-sdk/types" | ||||||
|  | 
 | ||||||
|  | 	"github.com/kava-labs/kava/x/incentive/types" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | var _ types.SourceAdapter = SourceAdapter{} | ||||||
|  | 
 | ||||||
|  | type SourceAdapter struct { | ||||||
|  | 	keeper types.SwapKeeper | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func NewSourceAdapter(keeper types.SwapKeeper) SourceAdapter { | ||||||
|  | 	return SourceAdapter{ | ||||||
|  | 		keeper: keeper, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (f SourceAdapter) TotalSharesBySource(ctx sdk.Context, sourceID string) sdk.Dec { | ||||||
|  | 	shares, found := f.keeper.GetPoolShares(ctx, sourceID) | ||||||
|  | 	if !found { | ||||||
|  | 		shares = sdk.ZeroInt() | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return shares.ToDec() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (f SourceAdapter) OwnerSharesBySource( | ||||||
|  | 	ctx sdk.Context, | ||||||
|  | 	owner sdk.AccAddress, | ||||||
|  | 	sourceIDs []string, | ||||||
|  | ) map[string]sdk.Dec { | ||||||
|  | 	shares := make(map[string]sdk.Dec) | ||||||
|  | 	for _, id := range sourceIDs { | ||||||
|  | 		s, found := f.keeper.GetDepositorSharesAmount(ctx, owner, id) | ||||||
|  | 		if !found { | ||||||
|  | 			s = sdk.ZeroInt() | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		shares[id] = s.ToDec() | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return shares | ||||||
|  | } | ||||||
							
								
								
									
										283
									
								
								x/incentive/keeper/adapters/swap/adapter_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										283
									
								
								x/incentive/keeper/adapters/swap/adapter_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,283 @@ | |||||||
|  | package swap_test | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"testing" | ||||||
|  | 	"time" | ||||||
|  | 
 | ||||||
|  | 	sdk "github.com/cosmos/cosmos-sdk/types" | ||||||
|  | 
 | ||||||
|  | 	tmprototypes "github.com/tendermint/tendermint/proto/tendermint/types" | ||||||
|  | 
 | ||||||
|  | 	"github.com/kava-labs/kava/app" | ||||||
|  | 	"github.com/kava-labs/kava/x/incentive/keeper/adapters/swap" | ||||||
|  | 	swaptypes "github.com/kava-labs/kava/x/swap/types" | ||||||
|  | 	"github.com/stretchr/testify/suite" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type SwapAdapterTestSuite struct { | ||||||
|  | 	suite.Suite | ||||||
|  | 
 | ||||||
|  | 	app app.TestApp | ||||||
|  | 	ctx sdk.Context | ||||||
|  | 
 | ||||||
|  | 	genesisTime time.Time | ||||||
|  | 	addrs       []sdk.AccAddress | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestSwapAdapterTestSuite(t *testing.T) { | ||||||
|  | 	suite.Run(t, new(SwapAdapterTestSuite)) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (suite *SwapAdapterTestSuite) SetupTest() { | ||||||
|  | 	config := sdk.GetConfig() | ||||||
|  | 	app.SetBech32AddressPrefixes(config) | ||||||
|  | 
 | ||||||
|  | 	_, suite.addrs = app.GeneratePrivKeyAddressPairs(5) | ||||||
|  | 
 | ||||||
|  | 	suite.genesisTime = time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC) | ||||||
|  | 	suite.app = app.NewTestApp() | ||||||
|  | 
 | ||||||
|  | 	suite.ctx = suite.app.NewContext(true, tmprototypes.Header{Time: suite.genesisTime}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (suite *SwapAdapterTestSuite) TestSwapAdapter_OwnerSharesBySource_Empty() { | ||||||
|  | 	adapter := swap.NewSourceAdapter(suite.app.GetSwapKeeper()) | ||||||
|  | 
 | ||||||
|  | 	tests := []struct { | ||||||
|  | 		name          string | ||||||
|  | 		giveOwner     sdk.AccAddress | ||||||
|  | 		giveSourceIDs []string | ||||||
|  | 		wantShares    map[string]sdk.Dec | ||||||
|  | 	}{ | ||||||
|  | 		{ | ||||||
|  | 			"empty requests", | ||||||
|  | 			suite.addrs[0], | ||||||
|  | 			[]string{}, | ||||||
|  | 			map[string]sdk.Dec{}, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			"empty pools are zero", | ||||||
|  | 			suite.addrs[0], | ||||||
|  | 			[]string{ | ||||||
|  | 				"pool1", | ||||||
|  | 				"pool2", | ||||||
|  | 				"pool3", | ||||||
|  | 			}, | ||||||
|  | 			map[string]sdk.Dec{ | ||||||
|  | 				"pool1": sdk.ZeroDec(), | ||||||
|  | 				"pool2": sdk.ZeroDec(), | ||||||
|  | 				"pool3": sdk.ZeroDec(), | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for _, tt := range tests { | ||||||
|  | 		suite.Run(tt.name, func() { | ||||||
|  | 			shares := adapter.OwnerSharesBySource(suite.ctx, tt.giveOwner, tt.giveSourceIDs) | ||||||
|  | 
 | ||||||
|  | 			suite.Equal(tt.wantShares, shares) | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (suite *SwapAdapterTestSuite) TestSwapAdapter_OwnerSharesBySource() { | ||||||
|  | 	poolDenomA := "ukava" | ||||||
|  | 	poolDenomB := "usdx" | ||||||
|  | 
 | ||||||
|  | 	swapKeeper := suite.app.GetSwapKeeper() | ||||||
|  | 	swapKeeper.SetParams(suite.ctx, swaptypes.NewParams( | ||||||
|  | 		swaptypes.NewAllowedPools( | ||||||
|  | 			swaptypes.NewAllowedPool(poolDenomA, poolDenomB), | ||||||
|  | 		), | ||||||
|  | 		sdk.ZeroDec(), | ||||||
|  | 	)) | ||||||
|  | 
 | ||||||
|  | 	suite.app.FundAccount( | ||||||
|  | 		suite.ctx, | ||||||
|  | 		suite.addrs[0], | ||||||
|  | 		sdk.NewCoins( | ||||||
|  | 			sdk.NewCoin(poolDenomA, sdk.NewInt(1000000000000)), | ||||||
|  | 			sdk.NewCoin(poolDenomB, sdk.NewInt(1000000000000)), | ||||||
|  | 		), | ||||||
|  | 	) | ||||||
|  | 	suite.app.FundAccount( | ||||||
|  | 		suite.ctx, | ||||||
|  | 		suite.addrs[1], | ||||||
|  | 		sdk.NewCoins( | ||||||
|  | 			sdk.NewCoin(poolDenomA, sdk.NewInt(1000000000000)), | ||||||
|  | 			sdk.NewCoin(poolDenomB, sdk.NewInt(1000000000000)), | ||||||
|  | 		), | ||||||
|  | 	) | ||||||
|  | 
 | ||||||
|  | 	err := swapKeeper.Deposit( | ||||||
|  | 		suite.ctx, | ||||||
|  | 		suite.addrs[0], | ||||||
|  | 		sdk.NewCoin(poolDenomA, sdk.NewInt(100)), | ||||||
|  | 		sdk.NewCoin(poolDenomB, sdk.NewInt(100)), | ||||||
|  | 		sdk.NewDecWithPrec(1, 1), | ||||||
|  | 	) | ||||||
|  | 	suite.NoError(err) | ||||||
|  | 
 | ||||||
|  | 	err = swapKeeper.Deposit( | ||||||
|  | 		suite.ctx, | ||||||
|  | 		suite.addrs[1], | ||||||
|  | 		sdk.NewCoin(poolDenomA, sdk.NewInt(250)), | ||||||
|  | 		sdk.NewCoin(poolDenomB, sdk.NewInt(250)), | ||||||
|  | 		sdk.NewDecWithPrec(1, 0), | ||||||
|  | 	) | ||||||
|  | 	suite.NoError(err) | ||||||
|  | 
 | ||||||
|  | 	adapter := swap.NewSourceAdapter(suite.app.GetSwapKeeper()) | ||||||
|  | 
 | ||||||
|  | 	tests := []struct { | ||||||
|  | 		name          string | ||||||
|  | 		giveOwner     sdk.AccAddress | ||||||
|  | 		giveSourceIDs []string | ||||||
|  | 		wantShares    map[string]sdk.Dec | ||||||
|  | 	}{ | ||||||
|  | 		{ | ||||||
|  | 			"depositor has shares", | ||||||
|  | 			suite.addrs[0], | ||||||
|  | 			[]string{ | ||||||
|  | 				swaptypes.PoolID(poolDenomA, poolDenomB), | ||||||
|  | 			}, | ||||||
|  | 			map[string]sdk.Dec{ | ||||||
|  | 				swaptypes.PoolID(poolDenomA, poolDenomB): sdk.NewDecWithPrec(100, 0), | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			"depositor has shares - including empty deposits", | ||||||
|  | 			suite.addrs[1], | ||||||
|  | 			[]string{ | ||||||
|  | 				swaptypes.PoolID(poolDenomA, poolDenomB), | ||||||
|  | 				"pool2", | ||||||
|  | 			}, | ||||||
|  | 			map[string]sdk.Dec{ | ||||||
|  | 				swaptypes.PoolID(poolDenomA, poolDenomB): sdk.NewDecWithPrec(250, 0), | ||||||
|  | 				"pool2":                                  sdk.ZeroDec(), | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			"non-depositor has zero shares", | ||||||
|  | 			suite.addrs[2], | ||||||
|  | 			[]string{ | ||||||
|  | 				swaptypes.PoolID(poolDenomA, poolDenomB), | ||||||
|  | 			}, | ||||||
|  | 			map[string]sdk.Dec{ | ||||||
|  | 				swaptypes.PoolID(poolDenomA, poolDenomB): sdk.ZeroDec(), | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for _, tt := range tests { | ||||||
|  | 		suite.Run(tt.name, func() { | ||||||
|  | 			shares := adapter.OwnerSharesBySource(suite.ctx, tt.giveOwner, tt.giveSourceIDs) | ||||||
|  | 
 | ||||||
|  | 			suite.Equal(tt.wantShares, shares) | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (suite *SwapAdapterTestSuite) TestSwapAdapter_TotalSharesBySource_Empty() { | ||||||
|  | 	adapter := swap.NewSourceAdapter(suite.app.GetSwapKeeper()) | ||||||
|  | 
 | ||||||
|  | 	tests := []struct { | ||||||
|  | 		name         string | ||||||
|  | 		giveSourceID string | ||||||
|  | 		wantShares   sdk.Dec | ||||||
|  | 	}{ | ||||||
|  | 		{ | ||||||
|  | 			"empty/invalid pools are zero", | ||||||
|  | 			"pool1", | ||||||
|  | 			sdk.ZeroDec(), | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			"invalid request returns zero", | ||||||
|  | 			"", | ||||||
|  | 			sdk.ZeroDec(), | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for _, tt := range tests { | ||||||
|  | 		suite.Run(tt.name, func() { | ||||||
|  | 			shares := adapter.TotalSharesBySource(suite.ctx, tt.giveSourceID) | ||||||
|  | 
 | ||||||
|  | 			suite.Equal(tt.wantShares, shares) | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (suite *SwapAdapterTestSuite) TestSwapAdapter_TotalSharesBySource() { | ||||||
|  | 	poolDenomA := "ukava" | ||||||
|  | 	poolDenomB := "usdx" | ||||||
|  | 
 | ||||||
|  | 	swapKeeper := suite.app.GetSwapKeeper() | ||||||
|  | 	swapKeeper.SetParams(suite.ctx, swaptypes.NewParams( | ||||||
|  | 		swaptypes.NewAllowedPools( | ||||||
|  | 			swaptypes.NewAllowedPool(poolDenomA, poolDenomB), | ||||||
|  | 		), | ||||||
|  | 		sdk.ZeroDec(), | ||||||
|  | 	)) | ||||||
|  | 
 | ||||||
|  | 	suite.app.FundAccount( | ||||||
|  | 		suite.ctx, | ||||||
|  | 		suite.addrs[0], | ||||||
|  | 		sdk.NewCoins( | ||||||
|  | 			sdk.NewCoin(poolDenomA, sdk.NewInt(1000000000000)), | ||||||
|  | 			sdk.NewCoin(poolDenomB, sdk.NewInt(1000000000000)), | ||||||
|  | 		), | ||||||
|  | 	) | ||||||
|  | 	suite.app.FundAccount( | ||||||
|  | 		suite.ctx, | ||||||
|  | 		suite.addrs[1], | ||||||
|  | 		sdk.NewCoins( | ||||||
|  | 			sdk.NewCoin(poolDenomA, sdk.NewInt(1000000000000)), | ||||||
|  | 			sdk.NewCoin(poolDenomB, sdk.NewInt(1000000000000)), | ||||||
|  | 		), | ||||||
|  | 	) | ||||||
|  | 
 | ||||||
|  | 	err := swapKeeper.Deposit( | ||||||
|  | 		suite.ctx, | ||||||
|  | 		suite.addrs[0], | ||||||
|  | 		sdk.NewCoin(poolDenomA, sdk.NewInt(100)), | ||||||
|  | 		sdk.NewCoin(poolDenomB, sdk.NewInt(100)), | ||||||
|  | 		sdk.NewDecWithPrec(1, 1), | ||||||
|  | 	) | ||||||
|  | 	suite.NoError(err) | ||||||
|  | 
 | ||||||
|  | 	err = swapKeeper.Deposit( | ||||||
|  | 		suite.ctx, | ||||||
|  | 		suite.addrs[1], | ||||||
|  | 		sdk.NewCoin(poolDenomA, sdk.NewInt(250)), | ||||||
|  | 		sdk.NewCoin(poolDenomB, sdk.NewInt(250)), | ||||||
|  | 		sdk.NewDecWithPrec(1, 0), | ||||||
|  | 	) | ||||||
|  | 	suite.NoError(err) | ||||||
|  | 
 | ||||||
|  | 	adapter := swap.NewSourceAdapter(suite.app.GetSwapKeeper()) | ||||||
|  | 
 | ||||||
|  | 	tests := []struct { | ||||||
|  | 		name         string | ||||||
|  | 		giveSourceID string | ||||||
|  | 		wantShares   sdk.Dec | ||||||
|  | 	}{ | ||||||
|  | 		{ | ||||||
|  | 			"total shares", | ||||||
|  | 			swaptypes.PoolID(poolDenomA, poolDenomB), | ||||||
|  | 			sdk.NewDecWithPrec(350, 0), | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			"empty or invalid pool empty", | ||||||
|  | 			"pool2", | ||||||
|  | 			sdk.ZeroDec(), | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for _, tt := range tests { | ||||||
|  | 		suite.Run(tt.name, func() { | ||||||
|  | 			shares := adapter.TotalSharesBySource(suite.ctx, tt.giveSourceID) | ||||||
|  | 
 | ||||||
|  | 			suite.Equal(tt.wantShares, shares) | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @ -1,12 +1,14 @@ | |||||||
| package keeper | package keeper | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
|  | 	"fmt" | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
| 	"github.com/cosmos/cosmos-sdk/codec" | 	"github.com/cosmos/cosmos-sdk/codec" | ||||||
| 	"github.com/cosmos/cosmos-sdk/store/prefix" | 	"github.com/cosmos/cosmos-sdk/store/prefix" | ||||||
| 	sdk "github.com/cosmos/cosmos-sdk/types" | 	sdk "github.com/cosmos/cosmos-sdk/types" | ||||||
| 
 | 
 | ||||||
|  | 	"github.com/kava-labs/kava/x/incentive/keeper/adapters/swap" | ||||||
| 	"github.com/kava-labs/kava/x/incentive/types" | 	"github.com/kava-labs/kava/x/incentive/types" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| @ -25,6 +27,8 @@ type Keeper struct { | |||||||
| 	liquidKeeper  types.LiquidKeeper | 	liquidKeeper  types.LiquidKeeper | ||||||
| 	earnKeeper    types.EarnKeeper | 	earnKeeper    types.EarnKeeper | ||||||
| 
 | 
 | ||||||
|  | 	adapters map[types.ClaimType]types.SourceAdapter | ||||||
|  | 
 | ||||||
| 	// Keepers used for APY queries
 | 	// Keepers used for APY queries
 | ||||||
| 	mintKeeper      types.MintKeeper | 	mintKeeper      types.MintKeeper | ||||||
| 	distrKeeper     types.DistrKeeper | 	distrKeeper     types.DistrKeeper | ||||||
| @ -55,6 +59,11 @@ func NewKeeper( | |||||||
| 		savingsKeeper: svk, | 		savingsKeeper: svk, | ||||||
| 		liquidKeeper:  lqk, | 		liquidKeeper:  lqk, | ||||||
| 		earnKeeper:    ek, | 		earnKeeper:    ek, | ||||||
|  | 
 | ||||||
|  | 		adapters: map[types.ClaimType]types.SourceAdapter{ | ||||||
|  | 			types.CLAIM_TYPE_SWAP: swap.NewSourceAdapter(swpk), | ||||||
|  | 		}, | ||||||
|  | 
 | ||||||
| 		mintKeeper:      mk, | 		mintKeeper:      mk, | ||||||
| 		distrKeeper:     dk, | 		distrKeeper:     dk, | ||||||
| 		pricefeedKeeper: pfk, | 		pricefeedKeeper: pfk, | ||||||
| @ -885,6 +894,15 @@ func (k Keeper) IterateEarnRewardAccrualTimes(ctx sdk.Context, cb func(string, t | |||||||
| // -----------------------------------------------------------------------------
 | // -----------------------------------------------------------------------------
 | ||||||
| // New deduplicated methods
 | // New deduplicated methods
 | ||||||
| 
 | 
 | ||||||
|  | func (k Keeper) GetSourceAdapter(claimType types.ClaimType) types.SourceAdapter { | ||||||
|  | 	fetcher, found := k.adapters[claimType] | ||||||
|  | 	if !found { | ||||||
|  | 		panic(fmt.Sprintf("no source share fetcher for claim type %s", claimType)) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return fetcher | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // GetClaim returns the claim in the store corresponding the the owner and
 | // GetClaim returns the claim in the store corresponding the the owner and
 | ||||||
| // claimType, and a boolean for if the claim was found
 | // claimType, and a boolean for if the claim was found
 | ||||||
| func (k Keeper) GetClaim( | func (k Keeper) GetClaim( | ||||||
|  | |||||||
| @ -36,7 +36,7 @@ func (k Keeper) SynchronizeClaim( | |||||||
| 	claimType types.ClaimType, | 	claimType types.ClaimType, | ||||||
| 	sourceID string, | 	sourceID string, | ||||||
| 	owner sdk.AccAddress, | 	owner sdk.AccAddress, | ||||||
| 	shares sdk.Int, | 	shares sdk.Dec, | ||||||
| ) { | ) { | ||||||
| 	claim, found := k.GetClaim(ctx, claimType, owner) | 	claim, found := k.GetClaim(ctx, claimType, owner) | ||||||
| 	if !found { | 	if !found { | ||||||
| @ -53,7 +53,7 @@ func (k *Keeper) synchronizeClaim( | |||||||
| 	claim types.Claim, | 	claim types.Claim, | ||||||
| 	sourceID string, | 	sourceID string, | ||||||
| 	owner sdk.AccAddress, | 	owner sdk.AccAddress, | ||||||
| 	shares sdk.Int, | 	shares sdk.Dec, | ||||||
| ) types.Claim { | ) types.Claim { | ||||||
| 	globalRewardIndexes, found := k.GetRewardIndexesOfClaimType(ctx, claim.Type, sourceID) | 	globalRewardIndexes, found := k.GetRewardIndexesOfClaimType(ctx, claim.Type, sourceID) | ||||||
| 	if !found { | 	if !found { | ||||||
| @ -74,7 +74,7 @@ func (k *Keeper) synchronizeClaim( | |||||||
| 		userRewardIndexes = types.RewardIndexes{} | 		userRewardIndexes = types.RewardIndexes{} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	newRewards, err := k.CalculateRewards(userRewardIndexes, globalRewardIndexes, shares.ToDec()) | 	newRewards, err := k.CalculateRewards(userRewardIndexes, globalRewardIndexes, shares) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		// Global reward factors should never decrease, as it would lead to a negative update to claim.Rewards.
 | 		// 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.
 | 		// This panics if a global reward factor decreases or disappears between the old and new indexes.
 | ||||||
| @ -86,3 +86,33 @@ func (k *Keeper) synchronizeClaim( | |||||||
| 
 | 
 | ||||||
| 	return claim | 	return claim | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | // GetSynchronizedClaim fetches a claim from the store and syncs rewards for all
 | ||||||
|  | // rewarded sourceIDs.
 | ||||||
|  | func (k Keeper) GetSynchronizedClaim( | ||||||
|  | 	ctx sdk.Context, | ||||||
|  | 	claimType types.ClaimType, | ||||||
|  | 	owner sdk.AccAddress, | ||||||
|  | ) (types.Claim, bool) { | ||||||
|  | 	claim, found := k.GetClaim(ctx, claimType, owner) | ||||||
|  | 	if !found { | ||||||
|  | 		return types.Claim{}, false | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Fetch all source IDs from indexes
 | ||||||
|  | 	var sourceIDs []string | ||||||
|  | 	k.IterateRewardIndexesByClaimType(ctx, claimType, func(rewardIndexes types.TypedRewardIndexes) bool { | ||||||
|  | 		sourceIDs = append(sourceIDs, rewardIndexes.CollateralType) | ||||||
|  | 		return false | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	adapter := k.GetSourceAdapter(claimType) | ||||||
|  | 	accShares := adapter.OwnerSharesBySource(ctx, owner, sourceIDs) | ||||||
|  | 
 | ||||||
|  | 	// Synchronize claim for each source ID
 | ||||||
|  | 	for _, sourceID := range sourceIDs { | ||||||
|  | 		claim = k.synchronizeClaim(ctx, claim, sourceID, owner, accShares[sourceID]) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return claim, true | ||||||
|  | } | ||||||
|  | |||||||
| @ -68,7 +68,7 @@ func (suite *SynchronizeClaimTests) TestClaimUpdatedWhenGlobalIndexesHaveIncreas | |||||||
| 
 | 
 | ||||||
| 	userShares := i(1e9) | 	userShares := i(1e9) | ||||||
| 
 | 
 | ||||||
| 	suite.keeper.SynchronizeClaim(suite.ctx, claimType, collateralType, claim.Owner, userShares) | 	suite.keeper.SynchronizeClaim(suite.ctx, claimType, collateralType, claim.Owner, userShares.ToDec()) | ||||||
| 
 | 
 | ||||||
| 	syncedClaim, _ := suite.keeper.GetClaim(suite.ctx, claimType, claim.Owner) | 	syncedClaim, _ := suite.keeper.GetClaim(suite.ctx, claimType, claim.Owner) | ||||||
| 	// indexes updated from global
 | 	// indexes updated from global
 | ||||||
| @ -110,7 +110,7 @@ func (suite *SynchronizeClaimTests) TestClaimUnchangedWhenGlobalIndexesUnchanged | |||||||
| 
 | 
 | ||||||
| 	userShares := i(1e9) | 	userShares := i(1e9) | ||||||
| 
 | 
 | ||||||
| 	suite.keeper.SynchronizeClaim(suite.ctx, claimType, collateralType, claim.Owner, userShares) | 	suite.keeper.SynchronizeClaim(suite.ctx, claimType, collateralType, claim.Owner, userShares.ToDec()) | ||||||
| 
 | 
 | ||||||
| 	syncedClaim, _ := suite.keeper.GetClaim(suite.ctx, claimType, claim.Owner) | 	syncedClaim, _ := suite.keeper.GetClaim(suite.ctx, claimType, claim.Owner) | ||||||
| 	// claim should have the same rewards and indexes as before
 | 	// claim should have the same rewards and indexes as before
 | ||||||
| @ -169,7 +169,7 @@ func (suite *SynchronizeClaimTests) TestClaimUpdatedWhenNewRewardAdded() { | |||||||
| 
 | 
 | ||||||
| 	userShares := i(1e9) | 	userShares := i(1e9) | ||||||
| 
 | 
 | ||||||
| 	suite.keeper.SynchronizeClaim(suite.ctx, claimType, newlyRewardcollateralType, claim.Owner, userShares) | 	suite.keeper.SynchronizeClaim(suite.ctx, claimType, newlyRewardcollateralType, claim.Owner, userShares.ToDec()) | ||||||
| 
 | 
 | ||||||
| 	syncedClaim, _ := suite.keeper.GetClaim(suite.ctx, claimType, claim.Owner) | 	syncedClaim, _ := suite.keeper.GetClaim(suite.ctx, claimType, claim.Owner) | ||||||
| 	// the new indexes should be added to the claim, but the old ones should be unchanged
 | 	// the new indexes should be added to the claim, but the old ones should be unchanged
 | ||||||
| @ -203,7 +203,7 @@ func (suite *SynchronizeClaimTests) TestClaimUnchangedWhenNoReward() { | |||||||
| 
 | 
 | ||||||
| 	userShares := i(1e9) | 	userShares := i(1e9) | ||||||
| 
 | 
 | ||||||
| 	suite.keeper.SynchronizeClaim(suite.ctx, claimType, collateralType, claim.Owner, userShares) | 	suite.keeper.SynchronizeClaim(suite.ctx, claimType, collateralType, claim.Owner, userShares.ToDec()) | ||||||
| 
 | 
 | ||||||
| 	syncedClaim, _ := suite.keeper.GetClaim(suite.ctx, claimType, claim.Owner) | 	syncedClaim, _ := suite.keeper.GetClaim(suite.ctx, claimType, claim.Owner) | ||||||
| 	suite.Equal(claim, syncedClaim) | 	suite.Equal(claim, syncedClaim) | ||||||
| @ -256,7 +256,7 @@ func (suite *SynchronizeClaimTests) TestClaimUpdatedWhenNewRewardDenomAdded() { | |||||||
| 
 | 
 | ||||||
| 	userShares := i(1e9) | 	userShares := i(1e9) | ||||||
| 
 | 
 | ||||||
| 	suite.keeper.SynchronizeClaim(suite.ctx, claimType, collateralType, claim.Owner, userShares) | 	suite.keeper.SynchronizeClaim(suite.ctx, claimType, collateralType, claim.Owner, userShares.ToDec()) | ||||||
| 
 | 
 | ||||||
| 	syncedClaim, _ := suite.keeper.GetClaim(suite.ctx, claimType, claim.Owner) | 	syncedClaim, _ := suite.keeper.GetClaim(suite.ctx, claimType, claim.Owner) | ||||||
| 	// indexes should have the new reward denom added
 | 	// indexes should have the new reward denom added
 | ||||||
| @ -310,7 +310,7 @@ func (suite *SynchronizeClaimTests) TestClaimUpdatedWhenGlobalIndexesIncreasedAn | |||||||
| 
 | 
 | ||||||
| 	userShares := i(0) | 	userShares := i(0) | ||||||
| 
 | 
 | ||||||
| 	suite.keeper.SynchronizeClaim(suite.ctx, claimType, collateralType, claim.Owner, userShares) | 	suite.keeper.SynchronizeClaim(suite.ctx, claimType, collateralType, claim.Owner, userShares.ToDec()) | ||||||
| 
 | 
 | ||||||
| 	syncedClaim, _ := suite.keeper.GetClaim(suite.ctx, claimType, claim.Owner) | 	syncedClaim, _ := suite.keeper.GetClaim(suite.ctx, claimType, claim.Owner) | ||||||
| 	// indexes updated from global
 | 	// indexes updated from global
 | ||||||
| @ -318,3 +318,155 @@ func (suite *SynchronizeClaimTests) TestClaimUpdatedWhenGlobalIndexesIncreasedAn | |||||||
| 	// reward is unchanged
 | 	// reward is unchanged
 | ||||||
| 	suite.Equal(claim.Reward, syncedClaim.Reward) | 	suite.Equal(claim.Reward, syncedClaim.Reward) | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func (suite *SynchronizeClaimTests) TestGetSyncedClaim_ClaimUnchangedWhenNoGlobalIndexes() { | ||||||
|  | 	collateralType_1 := "btcb:usdx" | ||||||
|  | 	owner := arbitraryAddress() | ||||||
|  | 	claimType := types.CLAIM_TYPE_SWAP | ||||||
|  | 
 | ||||||
|  | 	swapKeeper := newFakeSwapKeeper(). | ||||||
|  | 		addDeposit(collateralType_1, owner, i(1e9)) | ||||||
|  | 	suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, swapKeeper, nil, nil, nil) | ||||||
|  | 
 | ||||||
|  | 	claim := types.Claim{ | ||||||
|  | 		Type:   claimType, | ||||||
|  | 		Owner:  owner, | ||||||
|  | 		Reward: nil, | ||||||
|  | 		RewardIndexes: types.MultiRewardIndexes{ | ||||||
|  | 			{ | ||||||
|  | 				CollateralType: collateralType_1, | ||||||
|  | 				RewardIndexes:  nil, // this state only happens because Init stores empty indexes
 | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 	suite.keeper.SetClaim(suite.ctx, claim) | ||||||
|  | 
 | ||||||
|  | 	// no global indexes for any pool
 | ||||||
|  | 
 | ||||||
|  | 	syncedClaim, f := suite.keeper.GetSynchronizedClaim(suite.ctx, claimType, claim.Owner) | ||||||
|  | 	suite.True(f) | ||||||
|  | 
 | ||||||
|  | 	// indexes are unchanged
 | ||||||
|  | 	suite.Equal(claim.RewardIndexes, syncedClaim.RewardIndexes) | ||||||
|  | 	// reward is unchanged
 | ||||||
|  | 	suite.Equal(claim.Reward, syncedClaim.Reward) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (suite *SynchronizeClaimTests) TestGetSyncedClaim_ClaimUpdatedWhenMissingIndexAndHasNoSourceShares() { | ||||||
|  | 	collateralType_1 := "btcb:usdx" | ||||||
|  | 	collateralType_2 := "ukava:usdx" | ||||||
|  | 	owner := arbitraryAddress() | ||||||
|  | 	claimType := types.CLAIM_TYPE_SWAP | ||||||
|  | 
 | ||||||
|  | 	// owner has no shares in any pool
 | ||||||
|  | 	suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, newFakeSwapKeeper(), nil, nil, nil) | ||||||
|  | 
 | ||||||
|  | 	claim := types.Claim{ | ||||||
|  | 		Type:   claimType, | ||||||
|  | 		Owner:  owner, | ||||||
|  | 		Reward: arbitraryCoins(), | ||||||
|  | 		RewardIndexes: types.MultiRewardIndexes{ | ||||||
|  | 			{ | ||||||
|  | 				CollateralType: collateralType_1, | ||||||
|  | 				RewardIndexes: types.RewardIndexes{ | ||||||
|  | 					{ | ||||||
|  | 						CollateralType: "rewarddenom1", | ||||||
|  | 						RewardFactor:   d("1000.001"), | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 	suite.keeper.SetClaim(suite.ctx, claim) | ||||||
|  | 
 | ||||||
|  | 	globalIndexes := types.MultiRewardIndexes{ | ||||||
|  | 		{ | ||||||
|  | 			CollateralType: collateralType_1, | ||||||
|  | 			RewardIndexes: types.RewardIndexes{ | ||||||
|  | 				{ | ||||||
|  | 					CollateralType: "rewarddenom1", | ||||||
|  | 					RewardFactor:   d("2000.002"), | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			CollateralType: collateralType_2, | ||||||
|  | 			RewardIndexes: types.RewardIndexes{ | ||||||
|  | 				{ | ||||||
|  | 					CollateralType: "rewarddenom2", | ||||||
|  | 					RewardFactor:   d("2000.002"), | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 	suite.storeGlobalIndexes(claimType, globalIndexes) | ||||||
|  | 
 | ||||||
|  | 	syncedClaim, f := suite.keeper.GetSynchronizedClaim(suite.ctx, claimType, claim.Owner) | ||||||
|  | 	suite.True(f) | ||||||
|  | 
 | ||||||
|  | 	// indexes updated from global
 | ||||||
|  | 	suite.Equal(globalIndexes, syncedClaim.RewardIndexes) | ||||||
|  | 	// reward is unchanged
 | ||||||
|  | 	suite.Equal(claim.Reward, syncedClaim.Reward) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (suite *SynchronizeClaimTests) TestGetSyncedClaim_ClaimUpdatedWhenMissingIndexButHasSourceShares() { | ||||||
|  | 	collateralType_1 := "btcb:usdx" | ||||||
|  | 	collateralType_2 := "ukava:usdx" | ||||||
|  | 	owner := arbitraryAddress() | ||||||
|  | 	claimType := types.CLAIM_TYPE_SWAP | ||||||
|  | 
 | ||||||
|  | 	swapKeeper := newFakeSwapKeeper(). | ||||||
|  | 		addDeposit(collateralType_1, owner, i(1e9)). | ||||||
|  | 		addDeposit(collateralType_2, owner, i(1e9)) | ||||||
|  | 	suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, swapKeeper, nil, nil, nil) | ||||||
|  | 
 | ||||||
|  | 	claim := types.Claim{ | ||||||
|  | 		Type:   claimType, | ||||||
|  | 		Owner:  owner, | ||||||
|  | 		Reward: arbitraryCoins(), | ||||||
|  | 		RewardIndexes: types.MultiRewardIndexes{ | ||||||
|  | 			{ | ||||||
|  | 				CollateralType: collateralType_1, | ||||||
|  | 				RewardIndexes: types.RewardIndexes{ | ||||||
|  | 					{ | ||||||
|  | 						CollateralType: "rewarddenom1", | ||||||
|  | 						RewardFactor:   d("1000.001"), | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 	suite.keeper.SetClaim(suite.ctx, claim) | ||||||
|  | 
 | ||||||
|  | 	globalIndexes := types.MultiRewardIndexes{ | ||||||
|  | 		{ | ||||||
|  | 			CollateralType: collateralType_1, | ||||||
|  | 			RewardIndexes: types.RewardIndexes{ | ||||||
|  | 				{ | ||||||
|  | 					CollateralType: "rewarddenom1", | ||||||
|  | 					RewardFactor:   d("2000.002"), | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			CollateralType: collateralType_2, | ||||||
|  | 			RewardIndexes: types.RewardIndexes{ | ||||||
|  | 				{ | ||||||
|  | 					CollateralType: "rewarddenom2", | ||||||
|  | 					RewardFactor:   d("2000.002"), | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 	suite.storeGlobalIndexes(claimType, globalIndexes) | ||||||
|  | 
 | ||||||
|  | 	syncedClaim, f := suite.keeper.GetSynchronizedClaim(suite.ctx, claimType, claim.Owner) | ||||||
|  | 	suite.True(f) | ||||||
|  | 
 | ||||||
|  | 	// indexes updated from global
 | ||||||
|  | 	suite.Equal(globalIndexes, syncedClaim.RewardIndexes) | ||||||
|  | 	// reward is incremented
 | ||||||
|  | 	expectedReward := cs(c("rewarddenom1", 1_000_001_000_000), c("rewarddenom2", 2_000_002_000_000)) | ||||||
|  | 	suite.Equal(claim.Reward.Add(expectedReward...), syncedClaim.Reward) | ||||||
|  | } | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Derrick Lee
						Derrick Lee