github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/ammswap/keeper/keeper.go (about)

     1  package keeper
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/fibonacci-chain/fbc/x/common"
     7  
     8  	"github.com/fibonacci-chain/fbc/libs/tendermint/libs/log"
     9  
    10  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec"
    11  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
    12  	"github.com/fibonacci-chain/fbc/x/ammswap/types"
    13  	tokentypes "github.com/fibonacci-chain/fbc/x/token/types"
    14  )
    15  
    16  // Keeper of the swap store
    17  type Keeper struct {
    18  	supplyKeeper types.SupplyKeeper
    19  	tokenKeeper  types.TokenKeeper
    20  
    21  	storeKey       sdk.StoreKey
    22  	cdc            *codec.Codec
    23  	paramSpace     types.ParamSubspace
    24  	ObserverKeeper []types.BackendKeeper
    25  }
    26  
    27  // NewKeeper creates a swap keeper
    28  func NewKeeper(supplyKeeper types.SupplyKeeper, tokenKeeper types.TokenKeeper, cdc *codec.Codec, key sdk.StoreKey, paramspace types.ParamSubspace) Keeper {
    29  	keeper := Keeper{
    30  		supplyKeeper: supplyKeeper,
    31  		tokenKeeper:  tokenKeeper,
    32  		storeKey:     key,
    33  		cdc:          cdc,
    34  		paramSpace:   paramspace.WithKeyTable(types.ParamKeyTable()),
    35  	}
    36  	return keeper
    37  }
    38  
    39  // Logger returns a module-specific logger.
    40  func (k Keeper) Logger(ctx sdk.Context) log.Logger {
    41  	return ctx.Logger().With("module", fmt.Sprintf("x/%s", types.ModuleName))
    42  }
    43  
    44  // GetSwapTokenPair gets SwapTokenPair with quote token name
    45  func (k Keeper) GetSwapTokenPair(ctx sdk.Context, tokenPairName string) (types.SwapTokenPair, error) {
    46  	store := ctx.KVStore(k.storeKey)
    47  	var item types.SwapTokenPair
    48  	byteKey := types.GetTokenPairKey(tokenPairName)
    49  	rawItem := store.Get(byteKey)
    50  	if rawItem == nil {
    51  		return types.SwapTokenPair{}, types.ErrNonExistSwapTokenPair(tokenPairName)
    52  	}
    53  	err := k.cdc.UnmarshalBinaryLengthPrefixed(rawItem, &item)
    54  	if err != nil {
    55  		return types.SwapTokenPair{}, common.ErrUnMarshalJSONFailed(err.Error())
    56  	}
    57  
    58  	return item, nil
    59  }
    60  
    61  // SetSwapTokenPair sets the entire SwapTokenPair data struct for a quote token name
    62  func (k Keeper) SetSwapTokenPair(ctx sdk.Context, tokenPairName string, swapTokenPair types.SwapTokenPair) {
    63  	store := ctx.KVStore(k.storeKey)
    64  	bz := k.cdc.MustMarshalBinaryLengthPrefixed(swapTokenPair)
    65  	store.Set(types.GetTokenPairKey(tokenPairName), bz)
    66  }
    67  
    68  // DeleteSwapTokenPair deletes the entire SwapTokenPair data struct for a quote token name
    69  func (k Keeper) DeleteSwapTokenPair(ctx sdk.Context, tokenPairName string) {
    70  	store := ctx.KVStore(k.storeKey)
    71  	store.Delete(types.GetTokenPairKey(tokenPairName))
    72  }
    73  
    74  // GetSwapTokenPairsIterator get an iterator over all SwapTokenPairs in which the keys are the names and the values are the whois
    75  func (k Keeper) GetSwapTokenPairsIterator(ctx sdk.Context) sdk.Iterator {
    76  	store := ctx.KVStore(k.storeKey)
    77  	return sdk.KVStorePrefixIterator(store, types.TokenPairPrefixKey)
    78  }
    79  
    80  func (k Keeper) GetSwapTokenPairs(ctx sdk.Context) []types.SwapTokenPair {
    81  	var result []types.SwapTokenPair
    82  	iterator := k.GetSwapTokenPairsIterator(ctx)
    83  	for ; iterator.Valid(); iterator.Next() {
    84  		tokenPair := types.SwapTokenPair{}
    85  		types.ModuleCdc.MustUnmarshalBinaryLengthPrefixed(iterator.Value(), &tokenPair)
    86  		result = append(result, tokenPair)
    87  	}
    88  	return result
    89  }
    90  
    91  // NewPoolToken new token
    92  func (k Keeper) NewPoolToken(ctx sdk.Context, symbol string) {
    93  	poolToken := types.InitPoolToken(symbol)
    94  	k.tokenKeeper.NewToken(ctx, poolToken)
    95  }
    96  
    97  // GetPoolTokenInfo gets the token's info
    98  func (k Keeper) GetPoolTokenInfo(ctx sdk.Context, symbol string) (tokentypes.Token, error) {
    99  	poolToken := k.tokenKeeper.GetTokenInfo(ctx, symbol)
   100  	if poolToken.Owner == nil {
   101  		return poolToken, types.ErrNonExistPoolToken(symbol)
   102  	}
   103  	return poolToken, nil
   104  }
   105  
   106  // GetPoolTokenAmount gets the amount of the specified poolToken name
   107  func (k Keeper) GetPoolTokenAmount(ctx sdk.Context, poolTokenName string) sdk.Dec {
   108  	return k.supplyKeeper.GetSupplyByDenom(ctx, poolTokenName)
   109  }
   110  
   111  // MintPoolCoinsToUser mints coins and send them to the specified user address
   112  func (k Keeper) MintPoolCoinsToUser(ctx sdk.Context, coins sdk.SysCoins, addr sdk.AccAddress) error {
   113  	err := k.supplyKeeper.MintCoins(ctx, types.ModuleName, coins)
   114  	if err != nil {
   115  		return types.ErrCodeMinCoinsFailed(err)
   116  	}
   117  	return k.supplyKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, addr, coins)
   118  }
   119  
   120  // BurnPoolCoinsFromUser sends coins to account module and burns them
   121  func (k Keeper) BurnPoolCoinsFromUser(ctx sdk.Context, coins sdk.SysCoins, addr sdk.AccAddress) error {
   122  	err := k.supplyKeeper.SendCoinsFromAccountToModule(ctx, addr, types.ModuleName, coins)
   123  	if err != nil {
   124  		return types.ErrSendCoinsFromAccountToModule(err)
   125  	}
   126  	return k.supplyKeeper.BurnCoins(ctx, types.ModuleName, coins)
   127  }
   128  
   129  // SendCoinsToPool sends coins from user account to module account
   130  func (k Keeper) SendCoinsToPool(ctx sdk.Context, coins sdk.SysCoins, addr sdk.AccAddress) error {
   131  	return k.supplyKeeper.SendCoinsFromAccountToModule(ctx, addr, types.ModuleName, coins)
   132  }
   133  
   134  // SendCoinsFromPoolToAccount sends coins from module account to user account
   135  func (k Keeper) SendCoinsFromPoolToAccount(ctx sdk.Context, coins sdk.SysCoins, addr sdk.AccAddress) error {
   136  	return k.supplyKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, addr, coins)
   137  }
   138  
   139  // nolint
   140  func (k Keeper) GetTokenKeeper() types.TokenKeeper {
   141  	return k.tokenKeeper
   142  }
   143  
   144  // GetParams gets inflation params from the global param store
   145  func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) {
   146  	k.paramSpace.GetParamSet(ctx, &params)
   147  	return params
   148  }
   149  
   150  // SetParams sets inflation params from the global param store
   151  func (k Keeper) SetParams(ctx sdk.Context, params types.Params) {
   152  	k.paramSpace.SetParamSet(ctx, &params)
   153  }
   154  
   155  func (k Keeper) GetRedeemableAssets(ctx sdk.Context, baseAmountName, quoteAmountName string, liquidity sdk.Dec) (baseAmount, quoteAmount sdk.SysCoin, err error) {
   156  	err = types.ValidateBaseAndQuoteAmount(baseAmountName, quoteAmountName)
   157  	if err != nil {
   158  		return baseAmount, quoteAmount, types.ErrValidateSwapAmountName()
   159  	}
   160  	swapTokenPairName := types.GetSwapTokenPairName(baseAmountName, quoteAmountName)
   161  	swapTokenPair, err := k.GetSwapTokenPair(ctx, swapTokenPairName)
   162  	if err != nil {
   163  		return baseAmount, quoteAmount, err
   164  	}
   165  	poolTokenAmount := k.GetPoolTokenAmount(ctx, swapTokenPair.PoolTokenName)
   166  	if poolTokenAmount.LT(liquidity) {
   167  		return baseAmount, quoteAmount, types.ErrInsufficientPoolToken()
   168  	}
   169  
   170  	baseDec := common.MulAndQuo(swapTokenPair.BasePooledCoin.Amount, liquidity, poolTokenAmount)
   171  	quoteDec := common.MulAndQuo(swapTokenPair.QuotePooledCoin.Amount, liquidity, poolTokenAmount)
   172  	baseAmount = sdk.NewDecCoinFromDec(swapTokenPair.BasePooledCoin.Denom, baseDec)
   173  	quoteAmount = sdk.NewDecCoinFromDec(swapTokenPair.QuotePooledCoin.Denom, quoteDec)
   174  	return baseAmount, quoteAmount, nil
   175  }
   176  
   177  // CalculateTokenToBuy calculates the amount to buy
   178  func CalculateTokenToBuy(swapTokenPair types.SwapTokenPair, sellToken sdk.SysCoin, buyTokenDenom string, params types.Params) sdk.SysCoin {
   179  	var inputReserve, outputReserve sdk.Dec
   180  	if buyTokenDenom < sellToken.Denom {
   181  		inputReserve = swapTokenPair.QuotePooledCoin.Amount
   182  		outputReserve = swapTokenPair.BasePooledCoin.Amount
   183  	} else {
   184  		inputReserve = swapTokenPair.BasePooledCoin.Amount
   185  		outputReserve = swapTokenPair.QuotePooledCoin.Amount
   186  	}
   187  	tokenBuyAmt := GetInputPrice(sellToken.Amount, inputReserve, outputReserve, params.FeeRate)
   188  	tokenBuy := sdk.NewDecCoinFromDec(buyTokenDenom, tokenBuyAmt)
   189  
   190  	return tokenBuy
   191  }
   192  
   193  func GetInputPrice(inputAmount, inputReserve, outputReserve, feeRate sdk.Dec) sdk.Dec {
   194  	inputAmountWithFee := inputAmount.MulTruncate(sdk.OneDec().Sub(feeRate).MulTruncate(sdk.NewDec(1000)))
   195  	denominator := inputReserve.MulTruncate(sdk.NewDec(1000)).Add(inputAmountWithFee)
   196  	return common.MulAndQuo(inputAmountWithFee, outputReserve, denominator)
   197  }
   198  
   199  func (k *Keeper) SetObserverKeeper(bk types.BackendKeeper) {
   200  	k.ObserverKeeper = append(k.ObserverKeeper, bk)
   201  }
   202  
   203  func (k Keeper) OnSwapToken(ctx sdk.Context, address sdk.AccAddress, swapTokenPair types.SwapTokenPair, sellAmount sdk.SysCoin, buyAmount sdk.SysCoin) {
   204  	for _, observer := range k.ObserverKeeper {
   205  		observer.OnSwapToken(ctx, address, swapTokenPair, sellAmount, buyAmount)
   206  	}
   207  }
   208  
   209  func (k Keeper) OnCreateExchange(ctx sdk.Context, swapTokenPair types.SwapTokenPair) {
   210  	for _, observer := range k.ObserverKeeper {
   211  		observer.OnSwapCreateExchange(ctx, swapTokenPair)
   212  	}
   213  }