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, ¶ms) 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, ¶ms) 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 }