refactor useTokenMax to fix regressions
This commit is contained in:
parent
545470cf1f
commit
661fed8ce9
|
@ -145,7 +145,9 @@ function BorrowModal({ isOpen, onClose, token }: ModalCombinedProps) {
|
|||
return mangoAccount ? mangoAccount.getHealthRatioUi(HealthType.init) : 100
|
||||
}, [mangoAccount])
|
||||
|
||||
const showInsufficientBalance = inputAmount ? tokenMax.lt(inputAmount) : false
|
||||
const showInsufficientBalance = Number(inputAmount)
|
||||
? tokenMax.lt(inputAmount)
|
||||
: false
|
||||
|
||||
return (
|
||||
<Modal isOpen={isOpen} onClose={onClose}>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import Decimal from 'decimal.js'
|
||||
import { ChangeEvent, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import mangoStore from '../../store/mangoStore'
|
||||
import { getTokenInMax } from './useTokenMax'
|
||||
import { getTokenInMax, useTokenMax } from './useTokenMax'
|
||||
|
||||
const LeverageSlider = ({
|
||||
amount,
|
||||
|
@ -69,22 +69,14 @@ const LeverageSlider = ({
|
|||
export const SwapLeverageSlider = ({
|
||||
amount,
|
||||
onChange,
|
||||
useMargin,
|
||||
}: {
|
||||
amount: number
|
||||
onChange: (x: string) => void
|
||||
useMargin: boolean
|
||||
}) => {
|
||||
const mangoAccount = mangoStore((s) => s.mangoAccount.current)
|
||||
const inputTokenInfo = mangoStore((s) => s.swap.inputTokenInfo)
|
||||
|
||||
const { amountWithBorrow } = useMemo(() => {
|
||||
const group = mangoStore.getState().group
|
||||
if (inputTokenInfo && group) {
|
||||
return getTokenInMax(inputTokenInfo.address, group, true)
|
||||
}
|
||||
return {
|
||||
amountWithBorrow: new Decimal(0),
|
||||
}
|
||||
}, [inputTokenInfo])
|
||||
const { amountWithBorrow } = useTokenMax(useMargin)
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -101,24 +93,24 @@ export const SwapLeverageSlider = ({
|
|||
)
|
||||
}
|
||||
|
||||
export const BorrowLeverageSlider = ({
|
||||
amount,
|
||||
tokenMax,
|
||||
onChange,
|
||||
}: {
|
||||
amount: number
|
||||
tokenMax: number
|
||||
onChange: (x: string) => any
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
<LeverageSlider
|
||||
amount={amount}
|
||||
leverageMax={tokenMax}
|
||||
onChange={onChange}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
// export const BorrowLeverageSlider = ({
|
||||
// amount,
|
||||
// tokenMax,
|
||||
// onChange,
|
||||
// }: {
|
||||
// amount: number
|
||||
// tokenMax: number
|
||||
// onChange: (x: string) => any
|
||||
// }) => {
|
||||
// return (
|
||||
// <>
|
||||
// <LeverageSlider
|
||||
// amount={amount}
|
||||
// leverageMax={tokenMax}
|
||||
// onChange={onChange}
|
||||
// />
|
||||
// </>
|
||||
// )
|
||||
// }
|
||||
|
||||
export default LeverageSlider
|
||||
|
|
|
@ -33,7 +33,7 @@ import {
|
|||
INPUT_TOKEN_DEFAULT,
|
||||
OUTPUT_TOKEN_DEFAULT,
|
||||
} from '../../utils/constants'
|
||||
import { getTokenInMax } from './useTokenMax'
|
||||
import { getTokenInMax, useTokenMax } from './useTokenMax'
|
||||
import WalletIcon from '../icons/WalletIcon'
|
||||
import Tooltip from '@components/shared/Tooltip'
|
||||
|
||||
|
@ -63,22 +63,6 @@ const SwapForm = () => {
|
|||
const connected = mangoStore((s) => s.connected)
|
||||
const [debouncedAmountIn] = useDebounce(amountInFormValue, 300)
|
||||
|
||||
const {
|
||||
amount: tokenMax,
|
||||
amountWithBorrow,
|
||||
decimals,
|
||||
} = useMemo(() => {
|
||||
const group = mangoStore.getState().group
|
||||
if (inputTokenInfo && group) {
|
||||
return getTokenInMax(inputTokenInfo.address, group, useMargin)
|
||||
}
|
||||
return {
|
||||
amount: new Decimal(0),
|
||||
amountWithBorrow: new Decimal(0),
|
||||
decimals: 6,
|
||||
}
|
||||
}, [inputTokenInfo, useMargin, connected])
|
||||
|
||||
const amountIn: Decimal | null = useMemo(() => {
|
||||
return Number(debouncedAmountIn)
|
||||
? new Decimal(debouncedAmountIn)
|
||||
|
@ -195,18 +179,14 @@ const SwapForm = () => {
|
|||
: Math.trunc(simulatedHealthRatio!)
|
||||
}, [mangoAccount, inputTokenInfo, outputTokenInfo, amountIn, amountOut])
|
||||
|
||||
const isLoadingTradeDetails = useMemo(() => {
|
||||
const loadingSwapDetails: boolean = useMemo(() => {
|
||||
return (
|
||||
amountIn.toNumber() && connected && (!selectedRoute || !outputTokenInfo)
|
||||
!!amountIn.toNumber() && connected && (!selectedRoute || !outputTokenInfo)
|
||||
)
|
||||
}, [amountIn, connected, selectedRoute, outputTokenInfo])
|
||||
|
||||
const showHealthImpact = !!inputTokenInfo && !!outputTokenInfo && !!amountOut
|
||||
|
||||
const showInsufficientBalance = useMargin
|
||||
? amountWithBorrow.lt(amountIn)
|
||||
: tokenMax.lt(amountIn)
|
||||
|
||||
return (
|
||||
<ContentBox
|
||||
hidePadding
|
||||
|
@ -271,11 +251,8 @@ const SwapForm = () => {
|
|||
<div id="step-nine" className="mb-2 flex items-center justify-between">
|
||||
<p className="text-th-fgd-3">{t('swap:from')}</p>
|
||||
<MaxSwapAmount
|
||||
amountWithBorrow={amountWithBorrow}
|
||||
useMargin={useMargin}
|
||||
setAmountIn={setAmountInFormValue}
|
||||
tokenMax={tokenMax}
|
||||
decimals={decimals}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-3 grid grid-cols-2">
|
||||
|
@ -305,9 +282,8 @@ const SwapForm = () => {
|
|||
{!useMargin ? (
|
||||
<PercentageSelectButtons
|
||||
amountIn={amountInFormValue}
|
||||
decimals={decimals}
|
||||
setAmountIn={setAmountInFormValue}
|
||||
tokenMax={tokenMax}
|
||||
useMargin={useMargin}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
|
@ -336,7 +312,7 @@ const SwapForm = () => {
|
|||
/>
|
||||
</div>
|
||||
<div className="flex h-[54px] w-full items-center justify-end rounded-r-lg border border-th-bkg-4 bg-th-bkg-3 text-right text-xl font-bold text-th-fgd-3">
|
||||
{isLoadingTradeDetails ? (
|
||||
{loadingSwapDetails ? (
|
||||
<div className="w-full">
|
||||
<SheenLoader className="flex flex-1 rounded-l-none">
|
||||
<div className="h-[52px] w-full rounded-r-lg bg-th-bkg-4" />
|
||||
|
@ -356,47 +332,20 @@ const SwapForm = () => {
|
|||
{/* <p className="text-th-fgd-1">0.00x</p> */}
|
||||
</div>
|
||||
<SwapLeverageSlider
|
||||
useMargin={useMargin}
|
||||
amount={amountIn.toNumber()}
|
||||
onChange={setAmountInFormValue}
|
||||
/>
|
||||
</>
|
||||
) : null}
|
||||
<Button
|
||||
onClick={() => setShowConfirm(true)}
|
||||
className="mt-6 flex w-full items-center justify-center text-base"
|
||||
disabled={
|
||||
!amountIn.toNumber() ||
|
||||
!connected ||
|
||||
!routes?.length ||
|
||||
!selectedRoute ||
|
||||
!outputTokenInfo ||
|
||||
showInsufficientBalance
|
||||
}
|
||||
size="large"
|
||||
>
|
||||
{connected ? (
|
||||
showInsufficientBalance ? (
|
||||
<div className="flex items-center">
|
||||
<ExclamationCircleIcon className="mr-2 h-5 w-5 flex-shrink-0" />
|
||||
{t('swap:insufficient-balance', {
|
||||
symbol: inputTokenInfo?.symbol,
|
||||
})}
|
||||
</div>
|
||||
) : isLoadingTradeDetails ? (
|
||||
<Loading />
|
||||
) : (
|
||||
<div className="flex items-center">
|
||||
<MagnifyingGlassIcon className="mr-2 h-5 w-5" />
|
||||
{t('swap:review-swap')}
|
||||
</div>
|
||||
)
|
||||
) : (
|
||||
<div className="flex items-center">
|
||||
<WalletIcon className="mr-2 h-5 w-5" />
|
||||
{t('connect')}
|
||||
</div>
|
||||
)}
|
||||
</Button>
|
||||
<SwapFormSubmitButton
|
||||
loadingSwapDetails={loadingSwapDetails}
|
||||
useMargin={useMargin}
|
||||
setShowConfirm={setShowConfirm}
|
||||
amountIn={amountIn}
|
||||
inputSymbol={inputTokenInfo?.symbol}
|
||||
amountOut={amountOut}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
id="step-ten"
|
||||
|
@ -444,21 +393,87 @@ const SwapForm = () => {
|
|||
|
||||
export default SwapForm
|
||||
|
||||
const MaxSwapAmount = ({
|
||||
amountWithBorrow,
|
||||
setAmountIn,
|
||||
tokenMax,
|
||||
const SwapFormSubmitButton = ({
|
||||
amountIn,
|
||||
amountOut,
|
||||
inputSymbol,
|
||||
loadingSwapDetails,
|
||||
setShowConfirm,
|
||||
useMargin,
|
||||
decimals,
|
||||
}: {
|
||||
amountWithBorrow: Decimal
|
||||
setAmountIn: (x: string) => void
|
||||
tokenMax: Decimal
|
||||
amountIn: Decimal
|
||||
amountOut: Decimal
|
||||
inputSymbol: string | undefined
|
||||
loadingSwapDetails: boolean
|
||||
setShowConfirm: (x: any) => any
|
||||
useMargin: boolean
|
||||
decimals: number
|
||||
}) => {
|
||||
const mangoAccountLoading = mangoStore((s) => s.mangoAccount.initialLoad)
|
||||
const { t } = useTranslation('common')
|
||||
const connected = mangoStore((s) => s.connected)
|
||||
const { amount: tokenMax, amountWithBorrow } = useTokenMax(useMargin)
|
||||
|
||||
const showInsufficientBalance = useMargin
|
||||
? amountWithBorrow.lt(amountIn)
|
||||
: tokenMax.lt(amountIn)
|
||||
|
||||
const disabled =
|
||||
!amountIn.toNumber() ||
|
||||
!connected ||
|
||||
showInsufficientBalance ||
|
||||
!amountOut.gt(0)
|
||||
|
||||
return (
|
||||
<Button
|
||||
onClick={() => setShowConfirm(true)}
|
||||
className="mt-6 flex w-full items-center justify-center text-base"
|
||||
disabled={disabled}
|
||||
size="large"
|
||||
>
|
||||
{connected ? (
|
||||
showInsufficientBalance ? (
|
||||
<div className="flex items-center">
|
||||
<ExclamationCircleIcon className="mr-2 h-5 w-5 flex-shrink-0" />
|
||||
{t('swap:insufficient-balance', {
|
||||
symbol: inputSymbol,
|
||||
})}
|
||||
</div>
|
||||
) : loadingSwapDetails ? (
|
||||
<Loading />
|
||||
) : disabled ? (
|
||||
<div className="flex items-center">
|
||||
<ExclamationCircleIcon className="mr-2 h-5 w-5 flex-shrink-0" />
|
||||
No routes found
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex items-center">
|
||||
<MagnifyingGlassIcon className="mr-2 h-5 w-5" />
|
||||
{t('swap:review-swap')}
|
||||
</div>
|
||||
)
|
||||
) : (
|
||||
<div className="flex items-center">
|
||||
<WalletIcon className="mr-2 h-5 w-5" />
|
||||
{t('connect')}
|
||||
</div>
|
||||
)}
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
const MaxSwapAmount = ({
|
||||
setAmountIn,
|
||||
useMargin,
|
||||
}: {
|
||||
setAmountIn: (x: string) => void
|
||||
useMargin: boolean
|
||||
}) => {
|
||||
const { t } = useTranslation('common')
|
||||
const mangoAccountLoading = mangoStore((s) => s.mangoAccount.initialLoad)
|
||||
const {
|
||||
amount: tokenMax,
|
||||
amountWithBorrow,
|
||||
decimals,
|
||||
} = useTokenMax(useMargin)
|
||||
|
||||
const setMaxInputAmount = () => {
|
||||
const amountIn = useMargin ? amountWithBorrow : tokenMax
|
||||
|
@ -481,16 +496,15 @@ const MaxSwapAmount = ({
|
|||
|
||||
const PercentageSelectButtons = ({
|
||||
amountIn,
|
||||
decimals,
|
||||
setAmountIn,
|
||||
tokenMax,
|
||||
useMargin,
|
||||
}: {
|
||||
amountIn: string
|
||||
decimals: number
|
||||
setAmountIn: (x: string) => any
|
||||
tokenMax: Decimal
|
||||
useMargin: boolean
|
||||
}) => {
|
||||
const [sizePercentage, setSizePercentage] = useState('')
|
||||
const { amount: tokenMax, decimals } = useTokenMax(useMargin)
|
||||
|
||||
useEffect(() => {
|
||||
if (tokenMax.gt(0) && amountIn && tokenMax.eq(amountIn)) {
|
||||
|
|
|
@ -140,7 +140,12 @@ const SwapFormTokenList = ({
|
|||
) {
|
||||
const filteredSortedTokens = tokens
|
||||
.map((token) => {
|
||||
const max = getTokenInMax(token.address, group, useMargin)
|
||||
const max = getTokenInMax(
|
||||
mangoAccount,
|
||||
token.address,
|
||||
group,
|
||||
useMargin
|
||||
)
|
||||
return { ...token, ...max }
|
||||
})
|
||||
.filter((token) => (token.symbol === outputBank?.name ? false : true))
|
||||
|
|
|
@ -23,11 +23,11 @@ export const getMaxWithdrawForBank = (
|
|||
}
|
||||
|
||||
export const getTokenInMax = (
|
||||
mangoAccount: MangoAccount,
|
||||
inputTokenAddress: string,
|
||||
group: Group,
|
||||
useMargin: boolean
|
||||
) => {
|
||||
const mangoAccount = mangoStore.getState().mangoAccount.current
|
||||
const outputBank = mangoStore.getState().swap.outputBank
|
||||
const inputBank = group.banksMapByMint.get(inputTokenAddress)![0]
|
||||
|
||||
|
@ -81,60 +81,25 @@ export const getTokenInMax = (
|
|||
|
||||
export const useTokenMax = (useMargin = true) => {
|
||||
const { mangoAccount } = useMangoAccount()
|
||||
const group = mangoStore((s) => s.group)
|
||||
const inputBank = mangoStore((s) => s.swap.inputBank)
|
||||
const outputBank = mangoStore((s) => s.swap.outputBank)
|
||||
|
||||
const tokenInMax = useMemo(() => {
|
||||
const group = mangoStore.getState().group
|
||||
if (!group || !inputBank || !mangoAccount || !outputBank)
|
||||
return {
|
||||
amount: new Decimal(0.0),
|
||||
decimals: 6,
|
||||
amountWithBorrow: new Decimal(0.0),
|
||||
}
|
||||
|
||||
const inputBankFromGroup = group.getFirstBankByMint(inputBank.mint)
|
||||
const tokenBalance = floorToDecimal(
|
||||
mangoAccount?.getTokenBalanceUi(inputBankFromGroup),
|
||||
inputBankFromGroup.mintDecimals
|
||||
)
|
||||
|
||||
const inputBankVaultBalance = group.getTokenVaultBalanceByMintUi(
|
||||
inputBank.mint
|
||||
)
|
||||
const maxAmountWithoutMargin = tokenBalance.gt(0)
|
||||
? tokenBalance
|
||||
: new Decimal(0)
|
||||
|
||||
const maxUiAmountWithBorrow = floorToDecimal(
|
||||
mangoAccount?.getMaxSourceUiForTokenSwap(
|
||||
if (mangoAccount && group && inputBank) {
|
||||
return getTokenInMax(
|
||||
mangoAccount,
|
||||
inputBank?.mint.toString(),
|
||||
group,
|
||||
inputBank.mint,
|
||||
outputBank.mint,
|
||||
1
|
||||
)!,
|
||||
inputBank.mintDecimals
|
||||
)
|
||||
|
||||
const maxAmount = useMargin
|
||||
? Decimal.min(
|
||||
maxAmountWithoutMargin,
|
||||
inputBankVaultBalance,
|
||||
maxUiAmountWithBorrow!
|
||||
)
|
||||
: Decimal.min(maxAmountWithoutMargin, inputBankVaultBalance)
|
||||
|
||||
const maxAmountWithBorrow = Decimal.min(
|
||||
maxUiAmountWithBorrow!,
|
||||
inputBankVaultBalance
|
||||
)
|
||||
useMargin
|
||||
)
|
||||
}
|
||||
|
||||
return {
|
||||
amount: maxAmount,
|
||||
amountWithBorrow: maxAmountWithBorrow,
|
||||
decimals: inputBank.mintDecimals,
|
||||
amount: new Decimal(0),
|
||||
amountWithBorrow: new Decimal(0),
|
||||
decimals: 6,
|
||||
}
|
||||
}, [inputBank, mangoAccount, outputBank, useMargin])
|
||||
}, [mangoAccount, group, useMargin, inputBank])
|
||||
|
||||
return tokenInMax
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue