2024-03-28 07:52:55 -07:00
|
|
|
import { useCallback, useMemo, useState } from 'react'
|
2024-06-23 23:29:28 -07:00
|
|
|
import StakeForm from '@components/StakeForm'
|
2023-09-14 19:31:59 -07:00
|
|
|
import mangoStore from '@store/mangoStore'
|
2024-07-04 15:59:46 -07:00
|
|
|
import { getStakableTokensDataForTokenName } from 'utils/tokens'
|
|
|
|
import { ArrowLeftIcon, XMarkIcon } from '@heroicons/react/20/solid'
|
2024-02-20 11:23:39 -08:00
|
|
|
import DespositForm from './DepositForm'
|
2024-03-28 07:52:55 -07:00
|
|
|
import { EnterBottomExitBottom } from './shared/Transitions'
|
|
|
|
import TokenSelect from './TokenSelect'
|
|
|
|
import { IconButton } from './shared/Button'
|
2024-07-08 20:04:58 -07:00
|
|
|
import HeroTokenButton from './HeroTokenButton'
|
2024-06-23 23:29:28 -07:00
|
|
|
import Image from 'next/image'
|
|
|
|
import useStakeableTokens, { StakeableToken } from 'hooks/useStakeableTokens'
|
2024-07-08 20:04:58 -07:00
|
|
|
import { useTheme } from 'next-themes'
|
2023-09-14 18:48:02 -07:00
|
|
|
|
|
|
|
const set = mangoStore.getState().set
|
|
|
|
|
2024-07-08 20:04:58 -07:00
|
|
|
export const YIELD_BUTTON_CLASSES = `flex items-center justify-center rounded-xl raised-button-neutral group after:rounded-xl h-32 px-6 md:px-6 w-full after:border after:border-th-bkg-3 focus:outline-none disabled:cursor-not-allowed disabled:opacity-50`
|
|
|
|
|
2024-06-18 02:54:05 -07:00
|
|
|
export const SOL_YIELD = [
|
|
|
|
'bSOL',
|
|
|
|
'MSOL',
|
|
|
|
'JitoSOL',
|
|
|
|
'JSOL',
|
|
|
|
'INF',
|
|
|
|
'hubSOL',
|
|
|
|
'digitSOL',
|
|
|
|
'dualSOL',
|
|
|
|
'mangoSOL',
|
|
|
|
'compassSOL',
|
|
|
|
]
|
2024-05-06 20:13:25 -07:00
|
|
|
const USDC_YIELD = ['JLP', 'USDC']
|
|
|
|
|
2023-09-14 18:48:02 -07:00
|
|
|
const Stake = () => {
|
2024-07-08 20:04:58 -07:00
|
|
|
const { theme } = useTheme()
|
2024-06-23 23:29:28 -07:00
|
|
|
const [tokensToShow, setTokensToShow] = useState('')
|
2024-03-28 07:52:55 -07:00
|
|
|
const [showTokenSelect, setShowTokenSelect] = useState(false)
|
2023-09-14 19:31:59 -07:00
|
|
|
const selectedToken = mangoStore((s) => s.selectedToken)
|
2024-06-23 23:29:28 -07:00
|
|
|
// const walletTokens = mangoStore((s) => s.wallet.tokens)
|
|
|
|
const { stakeableTokens } = useStakeableTokens()
|
2023-09-14 18:48:02 -07:00
|
|
|
|
|
|
|
const handleTokenSelect = useCallback((token: string) => {
|
2023-09-14 19:31:59 -07:00
|
|
|
set((state) => {
|
|
|
|
state.selectedToken = token
|
|
|
|
})
|
2024-03-28 07:52:55 -07:00
|
|
|
setShowTokenSelect(false)
|
2023-09-14 18:48:02 -07:00
|
|
|
}, [])
|
|
|
|
|
2024-06-23 23:29:28 -07:00
|
|
|
const selectableTokens = useMemo(() => {
|
|
|
|
return stakeableTokens.sort((a: StakeableToken, b: StakeableToken) => {
|
|
|
|
// const aClientContext = getStakableTokensDataForTokenName(
|
|
|
|
// a.token.symbol,
|
|
|
|
// ).clientContext
|
|
|
|
// const aWalletBalance = walletBalanceForToken(
|
|
|
|
// walletTokens,
|
|
|
|
// a.token.symbol,
|
|
|
|
// aClientContext,
|
|
|
|
// )
|
|
|
|
// const bClientContext = getStakableTokensDataForTokenName(
|
|
|
|
// b.token.symbol,
|
|
|
|
// ).clientContext
|
|
|
|
// const bWalletBalance = walletBalanceForToken(
|
|
|
|
// walletTokens,
|
|
|
|
// b.token.symbol,
|
|
|
|
// bClientContext,
|
|
|
|
// )
|
2024-03-28 07:52:55 -07:00
|
|
|
|
2024-06-23 23:29:28 -07:00
|
|
|
// const aMaxAmount = aWalletBalance.maxAmount
|
|
|
|
// const bMaxAmount = bWalletBalance.maxAmount
|
2024-06-24 21:05:34 -07:00
|
|
|
const aApy = a.estNetApy
|
|
|
|
const bApy = b.estNetApy
|
2024-03-28 07:52:55 -07:00
|
|
|
|
2024-06-23 23:29:28 -07:00
|
|
|
// if (bMaxAmount !== aMaxAmount) {
|
|
|
|
// return bMaxAmount - aMaxAmount
|
|
|
|
// } else {
|
|
|
|
// return bApy - aApy
|
|
|
|
// }
|
|
|
|
return bApy - aApy
|
|
|
|
})
|
|
|
|
}, [stakeableTokens])
|
2024-03-28 07:52:55 -07:00
|
|
|
|
2024-07-04 15:59:46 -07:00
|
|
|
// const swapUrl = `https://app.mango.markets/swap?in=USDC&out=${selectedToken}&walletSwap=true`
|
2023-09-25 22:36:10 -07:00
|
|
|
|
2023-09-14 18:48:02 -07:00
|
|
|
return (
|
|
|
|
<>
|
2024-03-28 07:52:55 -07:00
|
|
|
<div className="relative overflow-hidden">
|
|
|
|
<EnterBottomExitBottom
|
|
|
|
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}
|
|
|
|
>
|
|
|
|
<div className="mb-4 flex items-center justify-between">
|
|
|
|
<div className="h-10 w-10" />
|
2024-06-23 23:29:28 -07:00
|
|
|
<h2>Select token to Boost!</h2>
|
2024-03-28 07:52:55 -07:00
|
|
|
<IconButton
|
|
|
|
onClick={() => setShowTokenSelect(false)}
|
|
|
|
hideBg
|
|
|
|
size="medium"
|
|
|
|
>
|
|
|
|
<XMarkIcon className="h-6 w-6" />
|
|
|
|
</IconButton>
|
|
|
|
</div>
|
|
|
|
<div className="mb-2 flex justify-between px-3">
|
|
|
|
<p className="text-sm text-th-fgd-4">Token</p>
|
2024-06-23 23:29:28 -07:00
|
|
|
<p className="text-sm text-th-fgd-4">Wallet Balance</p>
|
2024-03-28 07:52:55 -07:00
|
|
|
</div>
|
2024-06-23 23:29:28 -07:00
|
|
|
<div className="h-full max-h-[500px] overflow-auto pb-10">
|
2024-03-28 07:52:55 -07:00
|
|
|
{selectableTokens.map((token) => (
|
|
|
|
<TokenSelect
|
2024-06-23 23:29:28 -07:00
|
|
|
key={token.token.symbol}
|
|
|
|
onClick={() => handleTokenSelect(token.token.symbol)}
|
|
|
|
tokenInfo={token}
|
2024-03-28 07:52:55 -07:00
|
|
|
clientContext={
|
2024-06-23 23:29:28 -07:00
|
|
|
getStakableTokensDataForTokenName(token.token.symbol)
|
|
|
|
.clientContext
|
2024-03-28 07:52:55 -07:00
|
|
|
}
|
|
|
|
/>
|
|
|
|
))}
|
|
|
|
</div>
|
|
|
|
</EnterBottomExitBottom>
|
2023-09-14 18:48:02 -07:00
|
|
|
<div
|
2024-07-04 15:59:46 -07:00
|
|
|
className={`rounded-2xl border-2 border-th-fgd-1 bg-th-bkg-1 p-6 text-th-fgd-1 md:p-8`}
|
2023-09-14 18:48:02 -07:00
|
|
|
>
|
2024-06-23 23:29:28 -07:00
|
|
|
{selectableTokens.length ? (
|
|
|
|
!selectedToken ? (
|
|
|
|
<>
|
2024-07-04 15:59:46 -07:00
|
|
|
<div className="flex flex-col items-center">
|
2024-07-08 20:04:58 -07:00
|
|
|
<div className="w-full pb-6 text-center md:pb-8">
|
2024-07-09 22:15:53 -07:00
|
|
|
<h1 className="mb-1">Welcome yield fan 👋</h1>
|
2024-07-08 20:04:58 -07:00
|
|
|
<p>
|
|
|
|
It's time to leverage up your liquid staking yield.
|
|
|
|
</p>
|
2024-06-23 23:29:28 -07:00
|
|
|
</div>
|
2024-07-08 20:04:58 -07:00
|
|
|
<div
|
|
|
|
className={`bg-x-repeat h-2 w-full ${
|
|
|
|
theme === 'Light'
|
|
|
|
? `bg-[url('/images/zigzag-repeat.svg')]`
|
|
|
|
: `bg-[url('/images/zigzag-repeat-dark.svg')]`
|
|
|
|
} bg-contain opacity-20`}
|
|
|
|
/>
|
2024-07-04 15:59:46 -07:00
|
|
|
<div className="w-full py-6 md:py-8">
|
2024-06-24 21:05:34 -07:00
|
|
|
<h2 className="mb-3 text-center text-lg font-normal">
|
2024-07-08 20:04:58 -07:00
|
|
|
I want to earn
|
2024-06-23 23:29:28 -07:00
|
|
|
</h2>
|
|
|
|
<div className="grid grid-cols-2 gap-4 text-lg font-bold">
|
|
|
|
<button
|
2024-07-08 20:04:58 -07:00
|
|
|
className={`${YIELD_BUTTON_CLASSES} ${
|
|
|
|
tokensToShow === 'SOL'
|
|
|
|
? 'after:bg-th-bkg-2 after:md:hover:bg-th-bkg-2'
|
|
|
|
: ''
|
2024-06-23 23:29:28 -07:00
|
|
|
}`}
|
|
|
|
onClick={() => setTokensToShow('SOL')}
|
|
|
|
>
|
2024-07-08 20:04:58 -07:00
|
|
|
<div className="mt-1 flex w-full flex-col items-center group-hover:mt-2 group-active:mt-3">
|
|
|
|
<div className="rounded-full border-4 border-th-bkg-1">
|
2024-06-23 23:29:28 -07:00
|
|
|
<Image
|
|
|
|
src={`/icons/sol.svg`}
|
2024-07-08 20:04:58 -07:00
|
|
|
width={40}
|
|
|
|
height={40}
|
2024-06-23 23:29:28 -07:00
|
|
|
alt="Select a token"
|
|
|
|
/>
|
|
|
|
</div>
|
2024-07-08 20:04:58 -07:00
|
|
|
<span className="mt-3 leading-none">SOL</span>
|
2024-06-23 23:29:28 -07:00
|
|
|
</div>
|
|
|
|
</button>
|
|
|
|
<button
|
2024-07-08 20:04:58 -07:00
|
|
|
className={`${YIELD_BUTTON_CLASSES} ${
|
|
|
|
tokensToShow === 'USDC'
|
|
|
|
? 'after:bg-th-bkg-2 after:md:hover:bg-th-bkg-2'
|
|
|
|
: ''
|
2024-06-23 23:29:28 -07:00
|
|
|
}`}
|
|
|
|
onClick={() => setTokensToShow('USDC')}
|
|
|
|
>
|
2024-07-08 20:04:58 -07:00
|
|
|
<div className="mt-1 flex w-full flex-col items-center group-hover:mt-2 group-active:mt-3">
|
|
|
|
<div className="rounded-full border-4 border-th-bkg-1">
|
2024-06-23 23:29:28 -07:00
|
|
|
<Image
|
|
|
|
src={`/icons/usdc.svg`}
|
2024-07-08 20:04:58 -07:00
|
|
|
width={40}
|
|
|
|
height={40}
|
2024-06-23 23:29:28 -07:00
|
|
|
alt="Select a token"
|
|
|
|
/>
|
|
|
|
</div>
|
2024-07-08 20:04:58 -07:00
|
|
|
<span className="mt-3 leading-none">USDC</span>
|
2024-06-23 23:29:28 -07:00
|
|
|
</div>
|
|
|
|
</button>
|
2024-05-06 20:13:25 -07:00
|
|
|
</div>
|
|
|
|
</div>
|
2024-06-23 23:29:28 -07:00
|
|
|
</div>
|
|
|
|
{tokensToShow ? (
|
2024-07-08 20:04:58 -07:00
|
|
|
<>
|
|
|
|
<div
|
|
|
|
className={`bg-x-repeat h-2 w-full ${
|
|
|
|
theme === 'Light'
|
|
|
|
? `bg-[url('/images/zigzag-repeat.svg')]`
|
|
|
|
: `bg-[url('/images/zigzag-repeat-dark.svg')]`
|
|
|
|
} bg-contain opacity-20`}
|
|
|
|
/>
|
|
|
|
<div className="space-y-3 pt-6 md:pt-8">
|
|
|
|
<h2 className="text-center text-lg font-normal">
|
|
|
|
By adding leverage to
|
|
|
|
</h2>
|
|
|
|
{selectableTokens
|
|
|
|
.filter((t) => {
|
|
|
|
if (tokensToShow === 'SOL') {
|
|
|
|
return SOL_YIELD.includes(t.token.symbol)
|
|
|
|
} else if (tokensToShow === 'USDC') {
|
|
|
|
return USDC_YIELD.includes(t.token.symbol)
|
|
|
|
} else return
|
|
|
|
})
|
|
|
|
.map((token) => {
|
|
|
|
const { symbol } = token.token
|
|
|
|
return (
|
|
|
|
<HeroTokenButton
|
|
|
|
key={symbol}
|
|
|
|
onClick={() =>
|
|
|
|
set((state) => {
|
|
|
|
state.selectedToken = symbol
|
|
|
|
})
|
|
|
|
}
|
|
|
|
tokenInfo={token}
|
|
|
|
/>
|
|
|
|
)
|
|
|
|
})}
|
|
|
|
</div>
|
|
|
|
</>
|
2024-06-23 23:29:28 -07:00
|
|
|
) : null}
|
|
|
|
</>
|
2024-02-20 13:41:06 -08:00
|
|
|
) : (
|
2024-07-04 15:59:46 -07:00
|
|
|
<>
|
|
|
|
<div className="mb-6 flex items-center space-x-3">
|
2024-06-24 21:05:34 -07:00
|
|
|
<IconButton
|
|
|
|
onClick={() =>
|
|
|
|
set((state) => {
|
|
|
|
state.selectedToken = ''
|
|
|
|
})
|
|
|
|
}
|
|
|
|
size="small"
|
|
|
|
isPrimary
|
|
|
|
>
|
|
|
|
<ArrowLeftIcon className="h-5 w-5" />
|
|
|
|
</IconButton>
|
2024-07-09 22:15:53 -07:00
|
|
|
<h2>Add {selectedToken}</h2>
|
2024-06-24 21:05:34 -07:00
|
|
|
</div>
|
2024-06-23 23:29:28 -07:00
|
|
|
{selectedToken === 'USDC' ? (
|
|
|
|
<DespositForm
|
|
|
|
token="USDC"
|
|
|
|
clientContext={
|
|
|
|
getStakableTokensDataForTokenName('USDC').clientContext
|
|
|
|
}
|
|
|
|
/>
|
|
|
|
) : (
|
|
|
|
<StakeForm
|
|
|
|
token={selectedToken}
|
|
|
|
clientContext={
|
|
|
|
getStakableTokensDataForTokenName(selectedToken)
|
|
|
|
?.clientContext
|
|
|
|
}
|
|
|
|
/>
|
|
|
|
)}
|
2024-07-04 15:59:46 -07:00
|
|
|
</>
|
2024-06-23 23:29:28 -07:00
|
|
|
)
|
|
|
|
) : (
|
|
|
|
<div className="p-10">
|
|
|
|
<p className="text-center text-th-fgd-4">
|
|
|
|
No positions to remove
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
)}
|
2023-09-14 18:48:02 -07:00
|
|
|
</div>
|
|
|
|
</div>
|
2024-07-04 15:59:46 -07:00
|
|
|
{/* {selectedToken ? (
|
2024-02-21 17:05:33 -08:00
|
|
|
<div className="fixed bottom-0 left-0 z-20 w-full lg:bottom-8 lg:left-8 lg:w-auto">
|
2023-09-25 21:41:37 -07:00
|
|
|
{isDesktop ? (
|
2023-09-25 22:36:10 -07:00
|
|
|
<a
|
2023-10-02 05:30:58 -07:00
|
|
|
className="raised-button text-shadow group flex h-20 w-20 cursor-pointer items-center justify-center p-3 text-center text-base font-extrabold after:rounded-full"
|
2023-09-25 22:36:10 -07:00
|
|
|
href={swapUrl}
|
|
|
|
rel="noopener noreferrer"
|
|
|
|
target="_blank"
|
|
|
|
>
|
2023-10-02 05:30:58 -07:00
|
|
|
<div className="group-hover:mt-1 group-active:mt-2">
|
2023-09-25 21:41:37 -07:00
|
|
|
<p className="text-th-bkg-1">Buy</p>
|
|
|
|
<p className="-mt-1.5 text-th-bkg-1">
|
|
|
|
{formatTokenSymbol(selectedToken)}
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
</a>
|
|
|
|
) : (
|
|
|
|
<div className="flex justify-end border-t-2 border-th-fgd-1 bg-th-bkg-1 px-4 py-3">
|
2023-09-25 22:36:10 -07:00
|
|
|
<a href={swapUrl} rel="noopener noreferrer" target="_blank">
|
2023-09-25 21:41:37 -07:00
|
|
|
<div className="flex items-center">
|
|
|
|
<span className="mr-1.5 font-bold">{`Buy ${formatTokenSymbol(
|
|
|
|
selectedToken,
|
|
|
|
)}`}</span>
|
|
|
|
<ArrowTopRightOnSquareIcon className="-mt-0.5 h-5 w-5" />
|
|
|
|
</div>
|
|
|
|
</a>
|
2023-09-22 06:33:36 -07:00
|
|
|
</div>
|
2023-09-25 21:41:37 -07:00
|
|
|
)}
|
2023-09-22 06:33:36 -07:00
|
|
|
</div>
|
2024-07-04 15:59:46 -07:00
|
|
|
) : null} */}
|
2023-09-14 18:48:02 -07:00
|
|
|
</>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
export default Stake
|