refactor useTokenMax to fix regressions

This commit is contained in:
tjs 2022-09-22 17:35:07 -04:00
parent 545470cf1f
commit 661fed8ce9
5 changed files with 138 additions and 160 deletions

View File

@ -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}>

View File

@ -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

View File

@ -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)) {

View File

@ -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))

View File

@ -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
}