add more details to token select list

This commit is contained in:
saml33 2024-03-25 13:29:37 +11:00
parent 41bdb0509d
commit 623a047a5a
3 changed files with 134 additions and 33 deletions

View File

@ -21,7 +21,7 @@ import Tooltip from './shared/Tooltip'
const set = mangoStore.getState().set
type Position = {
export type Position = {
borrowBalance: number
stakeBalance: number
pnl: number

View File

@ -1,7 +1,7 @@
import TokenButton from './TokenButton'
import { useCallback, useMemo, useState } from 'react'
import TabUnderline from './shared/TabUnderline'
import StakeForm from '@components/StakeForm'
import StakeForm, { walletBalanceForToken } from '@components/StakeForm'
import UnstakeForm from '@components/UnstakeForm'
import mangoStore from '@store/mangoStore'
import { STAKEABLE_TOKENS } from 'utils/constants'
@ -23,6 +23,7 @@ const Stake = () => {
const [activeFormTab, setActiveFormTab] = useState('Add')
const [showTokenSelect, setShowTokenSelect] = useState(false)
const selectedToken = mangoStore((s) => s.selectedToken)
const walletTokens = mangoStore((s) => s.wallet.tokens)
const { isDesktop } = useViewport()
const { positions } = usePositions()
@ -52,12 +53,40 @@ const Stake = () => {
const selectableTokens = useMemo(() => {
if (activeFormTab === 'Add') {
return STAKEABLE_TOKENS
return STAKEABLE_TOKENS.sort((a: string, b: string) => {
if (activeFormTab === 'Add') {
const aClientContext =
getStakableTokensDataForTokenName(a).clientContext
const aWalletBalance = walletBalanceForToken(
walletTokens,
a,
aClientContext,
)
const bClientContext =
getStakableTokensDataForTokenName(b).clientContext
const bWalletBalance = walletBalanceForToken(
walletTokens,
b,
bClientContext,
)
return bWalletBalance.maxAmount - aWalletBalance.maxAmount
} else {
const aHasPosition = positions.find((pos) => pos.bank.name === a)
const bHasPosition = positions.find((pos) => pos.bank.name === b)
const aPositionValue = aHasPosition
? aHasPosition.stakeBalance * aHasPosition.bank.uiPrice
: 0
const bPositionValue = bHasPosition
? bHasPosition.stakeBalance * bHasPosition.bank.uiPrice
: 0
return bPositionValue - aPositionValue
}
})
} else if (positions?.length) {
const positionTokens = positions.map((position) => position.bank.name)
return positionTokens
} else return []
}, [activeFormTab, positions])
}, [activeFormTab, positions, walletTokens])
const swapUrl = `https://app.mango.markets/swap?in=USDC&out=${selectedToken}&walletSwap=true`
@ -65,18 +94,28 @@ const Stake = () => {
<>
<div className="relative overflow-hidden">
<EnterBottomExitBottom
className="thin-scroll absolute bottom-0 left-0 z-20 h-full w-full overflow-auto rounded-2xl border-2 border-th-fgd-1 bg-th-bkg-1 p-6 pb-0"
className="absolute bottom-0 left-0 z-20 h-full w-full overflow-hidden rounded-2xl border-2 border-th-fgd-1 bg-th-bkg-1 px-3 py-6 pb-0"
show={!!showTokenSelect}
>
<h2 className="mb-4 text-center">
Select token to {activeFormTab === 'Add' ? 'Boost!' : 'Unboost'}
</h2>
<div className="space-y-4">
<div className="mb-2 flex justify-between px-3">
<p className="text-sm text-th-fgd-4">Token</p>
<p className="text-sm text-th-fgd-4">
{activeFormTab === 'Add' ? 'Wallet Balance' : 'Position Size'}
</p>
</div>
<div>
{selectableTokens.map((token) => (
<TokenSelect
key={token}
onClick={() => handleTokenSelect(token)}
tokenName={token}
clientContext={
getStakableTokensDataForTokenName(token).clientContext
}
showPositionSize={activeFormTab === 'Remove'}
/>
))}
</div>

View File

@ -4,16 +4,27 @@ import useBankRates from 'hooks/useBankRates'
import useLeverageMax from 'hooks/useLeverageMax'
import mangoStore from '@store/mangoStore'
import SheenLoader from './shared/SheenLoader'
import { useMemo } from 'react'
import FormatNumericValue from './shared/FormatNumericValue'
import { walletBalanceForToken } from './StakeForm'
import usePositions from 'hooks/usePositions'
import { ClientContextKeys } from 'utils/constants'
const TokenSelect = ({
onClick,
tokenName,
clientContext,
showPositionSize,
}: {
tokenName: string
onClick: () => void
clientContext: ClientContextKeys
showPositionSize?: boolean
}) => {
const leverage = useLeverageMax(tokenName)
const groupLoaded = mangoStore((s) => s.groupLoaded)
const walletTokens = mangoStore((s) => s.wallet.tokens)
const { positions } = usePositions()
const { stakeBankDepositRate, financialMetrics } = useBankRates(
tokenName,
@ -25,6 +36,15 @@ const TokenSelect = ({
1,
)
const walletBalance = useMemo(() => {
return walletBalanceForToken(walletTokens, tokenName, clientContext)
}, [walletTokens, tokenName, clientContext])
const position = useMemo(() => {
if (!positions || !positions?.length) return
return positions.find((position) => position.bank.name === tokenName)
}, [positions, tokenName])
const APY_Daily_Compound =
Math.pow(1 + Number(stakeBankDepositRate) / 365, 365) - 1
const UiRate =
@ -33,35 +53,77 @@ const TokenSelect = ({
: Math.max(estimatedNetAPYFor1xLev.APY, financialMetrics.APY)
return (
<button className="w-full" onClick={onClick}>
<div className="flex items-center space-x-3">
<div
className={`inner-shadow-bottom-sm flex h-12 w-12 items-center justify-center rounded-full border border-th-bkg-2 bg-gradient-to-b from-th-bkg-1 to-th-bkg-2`}
>
<Image
src={`/icons/${tokenName.toLowerCase()}.svg`}
width={24}
height={24}
alt="Select a token"
/>
<button
className="default-transition w-full rounded-lg p-3 md:hover:bg-th-bkg-2"
onClick={onClick}
>
<div className="flex items-center justify-between">
<div className="flex items-center space-x-3">
<div
className={`inner-shadow-bottom-sm flex h-12 w-12 shrink-0 items-center justify-center rounded-full border border-th-bkg-2 bg-gradient-to-b from-th-bkg-1 to-th-bkg-2`}
>
<Image
src={`/icons/${tokenName.toLowerCase()}.svg`}
width={24}
height={24}
alt="Select a token"
/>
</div>
<div className="text-left">
<p className={`text-sm font-bold text-th-fgd-1 sm:text-lg`}>
{formatTokenSymbol(tokenName)}
</p>
<span className={`text-sm text-th-fgd-4`}>
{!groupLoaded ? (
<SheenLoader>
<div className={`h-5 w-10 bg-th-bkg-2`} />
</SheenLoader>
) : !UiRate || isNaN(UiRate) ? (
'Rate Unavailable'
) : tokenName === 'USDC' ? (
`${UiRate.toFixed(2)}% APY`
) : (
`Up to ${UiRate.toFixed(2)}% APY`
)}
</span>
</div>
</div>
<div className="text-left">
<p className={`text-lg font-bold text-th-fgd-1`}>
{formatTokenSymbol(tokenName)}
</p>
<span className={`font-medium text-th-fgd-4`}>
{!groupLoaded ? (
<SheenLoader>
<div className={`h-5 w-10 bg-th-bkg-2`} />
</SheenLoader>
) : !UiRate || isNaN(UiRate) ? (
'Rate Unavailable'
) : tokenName === 'USDC' ? (
`${UiRate.toFixed(2)}% APY`
<div className="pl-3 text-right">
{showPositionSize ? (
position ? (
<>
<span className="text-sm font-bold text-th-fgd-1 sm:text-lg">
<FormatNumericValue
value={
position.stakeBalance *
(position.bank.name != 'USDC'
? position.bank?.uiPrice
: 1)
}
decimals={2}
/>{' '}
{'USDC'}
</span>
{position.bank.name !== 'USDC' ? (
<p className="text-sm text-th-fgd-4">
<FormatNumericValue
roundUp={true}
value={position.stakeBalance}
decimals={3}
/>{' '}
{formatTokenSymbol(position.bank.name)}
</p>
) : null}
</>
) : (
`Up to ${UiRate.toFixed(2)}% APY`
)}
</span>
''
)
) : (
<FormatNumericValue
value={walletBalance.maxAmount}
decimals={walletBalance.maxDecimals}
/>
)}
</div>
</div>
</button>