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

143 lines
3.9 KiB
TypeScript
Raw Normal View History

import { Bank, Group, MangoAccount } from '@blockworks-foundation/mango-v4'
import Decimal from 'decimal.js'
2022-08-26 10:17:31 -07:00
import { useMemo } from 'react'
2022-09-12 08:53:57 -07:00
import mangoStore from '@store/mangoStore'
import { floorToDecimal } from '../../utils/numbers'
2022-11-18 09:09:39 -08:00
import useMangoAccount from '../../hooks/useMangoAccount'
2022-11-20 12:32:38 -08:00
import useMangoGroup from 'hooks/useMangoGroup'
2022-12-12 21:38:12 -08:00
import { PublicKey } from '@solana/web3.js'
2022-08-26 10:17:31 -07:00
export const getMaxWithdrawForBank = (
group: Group,
bank: Bank,
mangoAccount: MangoAccount,
2023-07-21 11:47:53 -07:00
allowBorrow = false,
): Decimal => {
2022-11-19 11:20:36 -08:00
const accountBalance = mangoAccount.getTokenBalanceUi(bank)
const vaultBalance = group.getTokenVaultBalanceByMintUi(bank.mint)
2022-11-19 11:20:36 -08:00
const maxBorrow = mangoAccount.getMaxWithdrawWithBorrowForTokenUi(
2022-10-28 12:24:05 -07:00
group,
2023-07-21 11:47:53 -07:00
bank.mint,
2022-11-19 11:20:36 -08:00
)
2022-10-07 15:27:36 -07:00
const maxWithdraw = allowBorrow
2022-11-19 11:20:36 -08:00
? Decimal.min(vaultBalance, maxBorrow)
: bank.initAssetWeight.toNumber() === 0
? Decimal.min(accountBalance, vaultBalance)
2022-11-19 11:20:36 -08:00
: Decimal.min(accountBalance, vaultBalance, maxBorrow)
2022-10-07 15:27:36 -07:00
return Decimal.max(0, maxWithdraw)
}
2022-09-14 17:02:16 -07:00
export const getTokenInMax = (
mangoAccount: MangoAccount,
2022-12-12 21:38:12 -08:00
inputMint: PublicKey,
outputMint: PublicKey,
2022-09-14 17:02:16 -07:00
group: Group,
2023-07-21 11:47:53 -07:00
useMargin: boolean,
2022-09-14 17:02:16 -07:00
) => {
2022-12-12 21:38:12 -08:00
const inputBank = group.getFirstBankByMint(inputMint)
const outputBank = group.getFirstBankByMint(outputMint)
2022-09-14 17:02:16 -07:00
if (!group || !inputBank || !mangoAccount || !outputBank) {
return {
amount: new Decimal(0.0),
decimals: 6,
amountWithBorrow: new Decimal(0.0),
}
}
2023-05-11 19:25:16 -07:00
const inputReduceOnly = inputBank.areBorrowsReduceOnly()
const outputReduceOnly = outputBank.areDepositsReduceOnly()
2023-01-05 16:44:27 -08:00
const inputTokenBalance = new Decimal(
2023-07-21 11:47:53 -07:00
mangoAccount.getTokenBalanceUi(inputBank),
2022-09-14 17:02:16 -07:00
)
2023-01-05 16:44:27 -08:00
2023-02-08 16:31:53 -08:00
const outputTokenBalance = new Decimal(
2023-07-21 11:47:53 -07:00
mangoAccount.getTokenBalanceUi(outputBank),
2022-09-14 17:02:16 -07:00
)
2022-11-21 20:40:55 -08:00
2023-02-08 16:31:53 -08:00
const maxAmountWithoutMargin =
2023-05-11 19:25:16 -07:00
(inputTokenBalance.gt(0) && !outputReduceOnly) ||
(outputReduceOnly && outputTokenBalance.lt(0))
2023-02-08 16:31:53 -08:00
? inputTokenBalance
: new Decimal(0)
2023-02-09 15:26:28 -08:00
const rawMaxUiAmountWithBorrow = mangoAccount.getMaxSourceUiForTokenSwap(
group,
inputBank.mint,
2023-07-21 11:47:53 -07:00
outputBank.mint,
2022-09-14 17:02:16 -07:00
)
2022-11-21 20:40:55 -08:00
2023-02-08 16:31:53 -08:00
const maxUiAmountWithBorrow =
2023-05-11 19:25:16 -07:00
outputReduceOnly && (outputTokenBalance.gt(0) || outputTokenBalance.eq(0))
2023-02-08 16:31:53 -08:00
? new Decimal(0)
2023-02-10 02:38:05 -08:00
: rawMaxUiAmountWithBorrow > 0
2023-02-09 15:26:28 -08:00
? floorToDecimal(rawMaxUiAmountWithBorrow, inputBank.mintDecimals)
: new Decimal(0)
2023-02-08 16:31:53 -08:00
2022-11-21 20:40:55 -08:00
const inputBankVaultBalance = floorToDecimal(
group
.getTokenVaultBalanceByMintUi(inputBank.mint)
.toFixed(inputBank.mintDecimals),
2023-07-21 11:47:53 -07:00
inputBank.mintDecimals,
2022-09-14 17:02:16 -07:00
)
const maxAmount = useMargin
? Decimal.min(
maxAmountWithoutMargin,
inputBankVaultBalance,
2023-07-21 11:47:53 -07:00
maxUiAmountWithBorrow,
2022-09-14 17:02:16 -07:00
)
: Decimal.min(
maxAmountWithoutMargin,
inputBankVaultBalance,
2023-07-21 11:47:53 -07:00
maxUiAmountWithBorrow,
)
2022-09-14 17:02:16 -07:00
2023-05-11 19:25:16 -07:00
const maxAmountWithBorrow = inputReduceOnly
2023-02-08 16:31:53 -08:00
? Decimal.min(maxAmountWithoutMargin, inputBankVaultBalance)
: Decimal.min(maxUiAmountWithBorrow, inputBankVaultBalance)
2022-09-14 17:02:16 -07:00
return {
amount: maxAmount,
amountWithBorrow: maxAmountWithBorrow,
decimals: inputBank.mintDecimals,
}
}
2023-09-06 06:06:57 -07:00
export interface TokenMaxResults {
2023-02-13 19:31:53 -08:00
amount: Decimal
amountWithBorrow: Decimal
decimals: number
}
export const useTokenMax = (useMargin = true): TokenMaxResults => {
const { mangoAccount } = useMangoAccount()
2022-11-20 12:32:38 -08:00
const { group } = useMangoGroup()
2022-08-26 10:17:31 -07:00
const inputBank = mangoStore((s) => s.swap.inputBank)
2022-12-12 21:38:12 -08:00
const outputBank = mangoStore((s) => s.swap.outputBank)
2022-08-26 10:17:31 -07:00
const tokenInMax = useMemo(() => {
2023-03-12 13:01:33 -07:00
try {
if (mangoAccount && group && inputBank && outputBank) {
return getTokenInMax(
mangoAccount,
inputBank.mint,
outputBank.mint,
group,
2023-07-21 11:47:53 -07:00
useMargin,
2023-03-12 13:01:33 -07:00
)
}
} catch (e) {
console.warn('Error in useTokenMax: ', e)
}
2022-08-26 10:17:31 -07:00
return {
amount: new Decimal(0),
amountWithBorrow: new Decimal(0),
decimals: 6,
2022-08-26 10:17:31 -07:00
}
2022-12-12 21:38:12 -08:00
}, [mangoAccount, group, useMargin, inputBank, outputBank])
2022-08-26 10:17:31 -07:00
return tokenInMax
}