add more details to token select list
This commit is contained in:
parent
41bdb0509d
commit
623a047a5a
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue