From f64d2a78ff42b4d4635843e189d117f9e2569a4d Mon Sep 17 00:00:00 2001 From: Yusuf Seyrek Date: Tue, 29 Aug 2023 16:38:17 +0300 Subject: [PATCH] feat(auto-unlend): implemented to the withdraws (#406) --- .../FundWithdraw/WithdrawFromAccount.tsx | 30 +++++++++++++++---- src/hooks/useHealthComputer.tsx | 3 ++ src/store/slices/broadcast.ts | 13 ++++++-- src/types/interfaces/store/broadcast.d.ts | 8 ++++- src/utils/constants.ts | 2 ++ 5 files changed, 47 insertions(+), 9 deletions(-) diff --git a/src/components/Modals/FundWithdraw/WithdrawFromAccount.tsx b/src/components/Modals/FundWithdraw/WithdrawFromAccount.tsx index 996f34bb..cced291b 100644 --- a/src/components/Modals/FundWithdraw/WithdrawFromAccount.tsx +++ b/src/components/Modals/FundWithdraw/WithdrawFromAccount.tsx @@ -29,8 +29,7 @@ export default function WithdrawFromAccount(props: Props) { const [isConfirming, setIsConfirming] = useToggle() const [currentAsset, setCurrentAsset] = useState(defaultAsset) const [amount, setAmount] = useState(BN_ZERO) - const { updatedAccount, removeDepositAndLendsByDenom, removeDeposits, addDebts } = - useUpdatedAccount(account) + const { updatedAccount, removeDeposits, removeLends, addDebts } = useUpdatedAccount(account) const { computeMaxWithdrawAmount } = useHealthComputer(account) const { computeMaxBorrowAmount } = useHealthComputer(updatedAccount) const maxWithdrawAmount = computeMaxWithdrawAmount(currentAsset.denom) @@ -42,10 +41,17 @@ export default function WithdrawFromAccount(props: Props) { const debtAmount = isWithinBalance ? BN_ZERO : amount.minus(maxWithdrawAmount) const max = withdrawWithBorrowing ? maxWithdrawWithBorrowAmount : maxWithdrawAmount + const accountDeposit = account.deposits.find(byDenom(currentAsset.denom))?.amount ?? BN_ZERO + const shouldReclaim = + amount.isGreaterThan(accountDeposit) && !withdrawWithBorrowing && currentAsset.isAutoLendEnabled + const reclaimAmount = shouldReclaim ? amount.minus(accountDeposit) : BN_ZERO + const isReclaimingMaxAmount = maxWithdrawAmount.isEqualTo(amount) + function onChangeAmount(val: BigNumber) { setAmount(val) removeDeposits([BNCoin.fromDenomAndBigNumber(currentAsset.denom, withdrawAmount)]) addDebts([BNCoin.fromDenomAndBigNumber(currentAsset.denom, debtAmount)]) + removeLends([BNCoin.fromDenomAndBigNumber(currentAsset.denom, reclaimAmount)]) } function resetState() { @@ -55,12 +61,24 @@ export default function WithdrawFromAccount(props: Props) { async function onConfirm() { setIsConfirming(true) + + const coins = [BNCoin.fromDenomAndBigNumber(currentAsset.denom, amount)] + const borrow = !debtAmount.isZero() + ? [BNCoin.fromDenomAndBigNumber(currentAsset.denom, debtAmount)] + : [] + const reclaims = !reclaimAmount.isZero() + ? [ + BNCoin.fromDenomAndBigNumber(currentAsset.denom, reclaimAmount).toActionCoin( + isReclaimingMaxAmount, + ), + ] + : [] + const result = await withdraw({ accountId: account.id, - coins: [BNCoin.fromDenomAndBigNumber(currentAsset.denom, amount)], - borrow: debtAmount.isZero() - ? [] - : [BNCoin.fromDenomAndBigNumber(currentAsset.denom, debtAmount)], + coins, + borrow, + reclaims, }) setIsConfirming(false) diff --git a/src/hooks/useHealthComputer.tsx b/src/hooks/useHealthComputer.tsx index 13d0c514..debf37c4 100644 --- a/src/hooks/useHealthComputer.tsx +++ b/src/hooks/useHealthComputer.tsx @@ -24,6 +24,7 @@ import { SwapKind, } from 'utils/health_computer' import { BN } from 'utils/helpers' +import { LTV_BUFFER } from 'utils/constants' export default function useHealthComputer(account?: Account) { const { data: prices } = usePrices() @@ -145,6 +146,8 @@ export default function useHealthComputer(account?: Account) { if (!healthComputer) return BN_ZERO try { return BN(max_borrow_estimate_js(healthComputer, denom, target)) + .multipliedBy(1 - LTV_BUFFER) + .integerValue() } catch (err) { console.error(err) return BN_ZERO diff --git a/src/store/slices/broadcast.ts b/src/store/slices/broadcast.ts index 5a78da29..634dae71 100644 --- a/src/store/slices/broadcast.ts +++ b/src/store/slices/broadcast.ts @@ -8,6 +8,7 @@ import { BNCoin } from 'types/classes/BNCoin' import { ExecuteMsg as AccountNftExecuteMsg } from 'types/generated/mars-account-nft/MarsAccountNft.types' import { Action, + ActionCoin, Action as CreditManagerAction, ExecuteMsg as CreditManagerExecuteMsg, } from 'types/generated/mars-credit-manager/MarsCreditManager.types' @@ -318,7 +319,15 @@ export default function createBroadcastSlice( handleResponseMessages(response, `Deposited into vault`) return !!response.result }, - withdraw: async (options: { accountId: string; coins: BNCoin[]; borrow: BNCoin[] }) => { + withdraw: async (options: { + accountId: string + coins: BNCoin[] + borrow: BNCoin[] + reclaims: ActionCoin[] + }) => { + const reclaimActions = options.reclaims.map((coin) => ({ + reclaim: coin, + })) const withdrawActions = options.coins.map((coin) => ({ withdraw: coin.toCoin(), })) @@ -329,7 +338,7 @@ export default function createBroadcastSlice( const msg: CreditManagerExecuteMsg = { update_credit_account: { account_id: options.accountId, - actions: [...borrowActions, ...withdrawActions], + actions: [...reclaimActions, ...borrowActions, ...withdrawActions], }, } diff --git a/src/types/interfaces/store/broadcast.d.ts b/src/types/interfaces/store/broadcast.d.ts index 01a13c09..01d7fa23 100644 --- a/src/types/interfaces/store/broadcast.d.ts +++ b/src/types/interfaces/store/broadcast.d.ts @@ -1,4 +1,5 @@ const BNCoin = import('types/classes/BNCoin').BNCoin +const ActionCoin = import('types/generated').ActionCoin interface BroadcastResult { result?: import('@delphi-labs/shuttle-react').TxBroadcastResult @@ -41,5 +42,10 @@ interface BroadcastSlice { amount: string }) => Promise withdrawFromVaults: (options: { accountId: string; vaults: DepositedVault[] }) => Promise - withdraw: (options: { accountId: string; coins: BNCoin[]; borrow: BNCoin[] }) => Promise + withdraw: (options: { + accountId: string + coins: BNCoin[] + borrow: BNCoin[] + reclaims: ActionCoin[] + }) => Promise } diff --git a/src/utils/constants.ts b/src/utils/constants.ts index fb59eac3..7b82e94d 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -9,3 +9,5 @@ export const defaultFee: StdFee = { } export const SECONDS_IN_A_YEAR = 31540000 + +export const LTV_BUFFER = 0.01