(goCtx context.Context, msg *types.MsgRemoveLiquidity)
| 881 | } |
| 882 | |
| 883 | func (k msgServer) RemoveLiquidity(goCtx context.Context, msg *types.MsgRemoveLiquidity) (*types.MsgRemoveLiquidityResponse, error) { |
| 884 | ctx := sdk.UnwrapSDKContext(goCtx) |
| 885 | registry := k.tokenRegistryKeeper.GetRegistry(ctx) |
| 886 | eAsset, err := k.tokenRegistryKeeper.GetEntry(registry, msg.ExternalAsset.Symbol) |
| 887 | if err != nil { |
| 888 | return nil, types.ErrTokenNotSupported |
| 889 | } |
| 890 | if !k.tokenRegistryKeeper.CheckEntryPermissions(eAsset, []tokenregistrytypes.Permission{tokenregistrytypes.Permission_CLP}) { |
| 891 | return nil, tokenregistrytypes.ErrPermissionDenied |
| 892 | } |
| 893 | pool, err := k.Keeper.GetPool(ctx, msg.ExternalAsset.Symbol) |
| 894 | if err != nil { |
| 895 | return nil, types.ErrPoolDoesNotExist |
| 896 | } |
| 897 | //Get LP |
| 898 | lp, err := k.Keeper.GetLiquidityProvider(ctx, msg.ExternalAsset.Symbol, msg.Signer) |
| 899 | |
| 900 | if err != nil { |
| 901 | return nil, types.ErrLiquidityProviderDoesNotExist |
| 902 | } |
| 903 | |
| 904 | pmtpCurrentRunningRate := k.GetPmtpRateParams(ctx).PmtpCurrentRunningRate |
| 905 | externalSwapFeeRate := k.GetSwapFeeRate(ctx, *msg.ExternalAsset, false) |
| 906 | nativeSwapFeeRate := k.GetSwapFeeRate(ctx, types.GetSettlementAsset(), false) |
| 907 | // Prune pools |
| 908 | params := k.GetRewardsParams(ctx) |
| 909 | k.PruneUnlockRecords(ctx, &lp, params.LiquidityRemovalLockPeriod, params.LiquidityRemovalCancelPeriod) |
| 910 | |
| 911 | if !msg.Asymmetry.IsZero() { |
| 912 | return nil, types.ErrAsymmetricRemove |
| 913 | } |
| 914 | |
| 915 | // ensure requested removal amount is less than available - what is already on the queue |
| 916 | lpQueuedUnits := k.GetRemovalQueueUnitsForLP(ctx, lp) |
| 917 | msgUnits := ConvWBasisPointsToUnits(lp.LiquidityProviderUnits, msg.WBasisPoints) |
| 918 | if msgUnits.GT(lp.LiquidityProviderUnits.Sub(lpQueuedUnits)) { |
| 919 | return nil, sdkerrors.Wrap(types.ErrUnableToRemoveLiquidity, fmt.Sprintf("WithdrawUnits %s greater than total LP units %s minus queued removals", msgUnits, lp.LiquidityProviderUnits)) |
| 920 | } |
| 921 | |
| 922 | nativeAssetDepth, externalAssetDepth := pool.ExtractDebt(pool.NativeAssetBalance, pool.ExternalAssetBalance, false) |
| 923 | |
| 924 | //Calculate amount to withdraw |
| 925 | withdrawNativeAssetAmount, withdrawExternalAssetAmount, lpUnitsLeft, swapAmount := CalculateWithdrawal(pool.PoolUnits, |
| 926 | nativeAssetDepth.String(), externalAssetDepth.String(), lp.LiquidityProviderUnits.String(), |
| 927 | msg.WBasisPoints.String(), msg.Asymmetry) |
| 928 | |
| 929 | err = k.Keeper.UseUnlockedLiquidity(ctx, lp, lp.LiquidityProviderUnits.Sub(lpUnitsLeft), false) |
| 930 | if err != nil { |
| 931 | return nil, err |
| 932 | } |
| 933 | |
| 934 | // Skip pools that are not margin enabled, to avoid health being zero and queueing being triggered. |
| 935 | if k.GetMarginKeeper().IsPoolEnabled(ctx, eAsset.Denom) { |
| 936 | extRowanValue := CalculateWithdrawalRowanValue(withdrawExternalAssetAmount, types.GetSettlementAsset(), pool, pmtpCurrentRunningRate, externalSwapFeeRate) |
| 937 | |
| 938 | futurePool := pool |
| 939 | futurePool.NativeAssetBalance = futurePool.NativeAssetBalance.Sub(withdrawNativeAssetAmount) |
| 940 | futurePool.ExternalAssetBalance = futurePool.ExternalAssetBalance.Sub(withdrawExternalAssetAmount) |
nothing calls this directly
no test coverage detected