lev-stake-sol/components/Stake.tsx

304 lines
12 KiB
TypeScript
Raw Normal View History

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'
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'
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'
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']
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('')
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()
const handleTokenSelect = useCallback((token: string) => {
2023-09-14 19:31:59 -07:00
set((state) => {
state.selectedToken = token
})
setShowTokenSelect(false)
}, [])
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-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-06-23 23:29:28 -07:00
// if (bMaxAmount !== aMaxAmount) {
// return bMaxAmount - aMaxAmount
// } else {
// return bApy - aApy
// }
return bApy - aApy
})
}, [stakeableTokens])
// const swapUrl = `https://app.mango.markets/swap?in=USDC&out=${selectedToken}&walletSwap=true`
2023-09-25 22:36:10 -07:00
return (
<>
<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>
<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>
</div>
2024-06-23 23:29:28 -07:00
<div className="h-full max-h-[500px] overflow-auto pb-10">
{selectableTokens.map((token) => (
<TokenSelect
2024-06-23 23:29:28 -07:00
key={token.token.symbol}
onClick={() => handleTokenSelect(token.token.symbol)}
tokenInfo={token}
clientContext={
2024-06-23 23:29:28 -07:00
getStakableTokensDataForTokenName(token.token.symbol)
.clientContext
}
/>
))}
</div>
</EnterBottomExitBottom>
<div
className={`rounded-2xl border-2 border-th-fgd-1 bg-th-bkg-1 p-6 text-th-fgd-1 md:p-8`}
>
2024-06-23 23:29:28 -07:00
{selectableTokens.length ? (
!selectedToken ? (
<>
<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&apos;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`}
/>
<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
) : (
<>
<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-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>
)}
</div>
</div>
{/* {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>
) : null} */}
</>
)
}
export default Stake