mango-v4-ui/components/swap/useTokenMax.tsx

111 lines
2.8 KiB
TypeScript

import { Bank, Group, MangoAccount } from '@blockworks-foundation/mango-v4'
import Decimal from 'decimal.js'
import { useMemo } from 'react'
import mangoStore from '@store/mangoStore'
import { floorToDecimal } from '../../utils/numbers'
import useMangoAccount from '../../hooks/useMangoAccount'
import useMangoGroup from 'hooks/useMangoGroup'
export const getMaxWithdrawForBank = (
group: Group,
bank: Bank,
mangoAccount: MangoAccount,
allowBorrow = false
): Decimal => {
const accountBalance = mangoAccount.getTokenBalanceUi(bank)
const vaultBalance = group.getTokenVaultBalanceByMintUi(bank.mint)
const maxBorrow = mangoAccount.getMaxWithdrawWithBorrowForTokenUi(
group,
bank.mint
)
const maxWithdraw = allowBorrow
? Decimal.min(vaultBalance, maxBorrow)
: Decimal.min(accountBalance, vaultBalance, maxBorrow)
return Decimal.max(0, maxWithdraw)
}
export const getTokenInMax = (
mangoAccount: MangoAccount,
inputTokenAddress: string,
group: Group,
useMargin: boolean
) => {
const outputBank = mangoStore.getState().swap.outputBank
const inputBank = group.banksMapByMint.get(inputTokenAddress)?.[0]
if (!group || !inputBank || !mangoAccount || !outputBank) {
return {
amount: new Decimal(0.0),
decimals: 6,
amountWithBorrow: new Decimal(0.0),
}
}
const inputTokenBalance = floorToDecimal(
mangoAccount.getTokenBalanceUi(inputBank),
inputBank.mintDecimals
)
const maxAmountWithoutMargin = inputTokenBalance.gt(0)
? inputTokenBalance
: new Decimal(0)
const maxUiAmountWithBorrow = floorToDecimal(
mangoAccount.getMaxSourceUiForTokenSwap(
group,
inputBank.mint,
outputBank.mint,
1
),
inputBank.mintDecimals
)
const inputBankVaultBalance = floorToDecimal(
group.getTokenVaultBalanceByMintUi(inputBank.mint),
inputBank.mintDecimals
)
const maxAmount = useMargin
? Decimal.min(
maxAmountWithoutMargin,
inputBankVaultBalance,
maxUiAmountWithBorrow
)
: Decimal.min(maxAmountWithoutMargin, inputBankVaultBalance)
const maxAmountWithBorrow = Decimal.min(
maxUiAmountWithBorrow,
inputBankVaultBalance
)
return {
amount: maxAmount,
amountWithBorrow: maxAmountWithBorrow,
decimals: inputBank.mintDecimals,
}
}
export const useTokenMax = (useMargin = true) => {
const { mangoAccount } = useMangoAccount()
const { group } = useMangoGroup()
const inputBank = mangoStore((s) => s.swap.inputBank)
const tokenInMax = useMemo(() => {
if (mangoAccount && group && inputBank) {
return getTokenInMax(
mangoAccount,
inputBank?.mint.toString(),
group,
useMargin
)
}
return {
amount: new Decimal(0),
amountWithBorrow: new Decimal(0),
decimals: 6,
}
}, [mangoAccount, group, useMargin, inputBank])
return tokenInMax
}