From 22e7f536054b66e473b0ba9639318b66aa2d6b26 Mon Sep 17 00:00:00 2001 From: saml33 Date: Wed, 17 Jul 2024 21:08:38 +1000 Subject: [PATCH] show apys upfront --- components/Footer.tsx | 14 +-- components/HeroTokenButton.tsx | 2 +- components/Stake.tsx | 163 ++++-------------------------- components/icons/MangoMade.tsx | 176 +++++++++++++++++++++++++++++++++ hooks/useStakeRates.ts | 66 +++++++------ 5 files changed, 239 insertions(+), 182 deletions(-) create mode 100644 components/icons/MangoMade.tsx diff --git a/components/Footer.tsx b/components/Footer.tsx index 4e949c5..3e5f95b 100644 --- a/components/Footer.tsx +++ b/components/Footer.tsx @@ -1,23 +1,19 @@ import Link from 'next/link' import DiscordIcon from './icons/DiscordIcon' import { XIcon } from './icons/XIcon' +import MangoMade from './icons/MangoMade' const Footer = () => { return ( <>
- Powered by - logo +
The max APY is favorable right now. Rates can change very quickly. Make sure you understand the risks - before boosting. + before using this product.

Risks diff --git a/components/Stake.tsx b/components/Stake.tsx index ca0fcc1..1d6d618 100644 --- a/components/Stake.tsx +++ b/components/Stake.tsx @@ -8,7 +8,6 @@ import { EnterBottomExitBottom } from './shared/Transitions' import TokenSelect from './TokenSelect' import { IconButton } from './shared/Button' import HeroTokenButton from './HeroTokenButton' -import Image from 'next/image' import useStakeableTokens, { StakeableToken } from 'hooks/useStakeableTokens' import { useTheme } from 'next-themes' @@ -28,14 +27,11 @@ export const SOL_YIELD = [ 'mangoSOL', 'compassSOL', ] -const USDC_YIELD = ['JLP', 'USDC'] const Stake = () => { const { theme } = useTheme() - const [tokensToShow, setTokensToShow] = useState('') const [showTokenSelect, setShowTokenSelect] = useState(false) const selectedToken = mangoStore((s) => s.selectedToken) - // const walletTokens = mangoStore((s) => s.wallet.tokens) const { stakeableTokens } = useStakeableTokens() const handleTokenSelect = useCallback((token: string) => { @@ -47,33 +43,8 @@ const Stake = () => { 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, - // ) - - // const aMaxAmount = aWalletBalance.maxAmount - // const bMaxAmount = bWalletBalance.maxAmount const aApy = a.estNetApy const bApy = b.estNetApy - - // if (bMaxAmount !== aMaxAmount) { - // return bMaxAmount - aMaxAmount - // } else { - // return bApy - aApy - // } return bApy - aApy }) }, [stakeableTokens]) @@ -136,92 +107,26 @@ const Stake = () => { : `bg-[url('/images/zigzag-repeat-dark.svg')]` } bg-contain opacity-20`} /> -
-

- I want to earn -

-
- - -
-
- {tokensToShow ? ( - <> -
-
-

- By adding leverage to -

- {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 ( - - set((state) => { - state.selectedToken = symbol - }) - } - tokenInfo={token} - /> - ) - })} -
- - ) : null} +
+

+ Select to earn leveraged yield +

+ {selectableTokens.map((token) => { + const { symbol } = token.token + return ( + + set((state) => { + state.selectedToken = symbol + }) + } + tokenInfo={token} + /> + ) + })} +
) : ( <> @@ -266,36 +171,6 @@ const Stake = () => { )}
- {/* {selectedToken ? ( -
- {isDesktop ? ( - -
-

Buy

-

- {formatTokenSymbol(selectedToken)} -

-
-
- ) : ( -
- -
- {`Buy ${formatTokenSymbol( - selectedToken, - )}`} - -
-
-
- )} -
- ) : null} */} ) } diff --git a/components/icons/MangoMade.tsx b/components/icons/MangoMade.tsx new file mode 100644 index 0000000..5045b6c --- /dev/null +++ b/components/icons/MangoMade.tsx @@ -0,0 +1,176 @@ +const MangoMade = ({ className }: { className?: string }) => { + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ) +} + +export default MangoMade diff --git a/hooks/useStakeRates.ts b/hooks/useStakeRates.ts index 0d3e5fa..75dc01a 100644 --- a/hooks/useStakeRates.ts +++ b/hooks/useStakeRates.ts @@ -1,12 +1,17 @@ import { useQuery } from '@tanstack/react-query' import { OHLCVPairItem, fetchOHLCPair } from 'apis/birdeye/helpers' -import { SOL_MINT, STAKEABLE_TOKENS_DATA, USDC_MINT } from 'utils/constants' +import { + SOL_MINT, + STAKEABLE_TOKENS_DATA, + StakeableTokensData, + USDC_MINT, +} from 'utils/constants' const avgOpenClose = (i: OHLCVPairItem) => (i.c + i.o) * 0.5 const sum = (x: number, y: number) => x + y const ANNUAL_SECONDS = 60 * 60 * 24 * 365 -const calculateRate = (ohlcvs: OHLCVPairItem[]) => { +const calculateRateFromOhlcv = (ohlcvs: OHLCVPairItem[]) => { if (ohlcvs && ohlcvs?.length > 30) { // basic least squares regression: // https://www.ncl.ac.uk/webtemplate/ask-assets/external/maths-resources/statistics/regression-and-correlation/simple-linear-regression.html @@ -41,25 +46,16 @@ const fetchRates = async () => { const dailyCandles = await fetchOHLCPair(t.mint_address, quoteMint, '90') return dailyCandles }) + + const monthlyLstPriceChanges = await fetchApyToSol(STAKEABLE_TOKENS_DATA) const [ jlpPrices, msolPrices, jitoPrices, bsolPrices, - jsolPrices, infPrices, - hubSOLPrices, - digitSOLPrices, - dualSOLPrices, - mangoSOLPrices, - compassSOLPrices, + jsolPrices, ] = await Promise.all(promises) - console.log({ - digitSOLPrices, - dualSOLPrices, - mangoSOLPrices, - compassSOLPrices, - }) // may be null if the price range cannot be calculated /* @@ -69,21 +65,20 @@ const fetchRates = async () => { const lidoRange = getPriceRangeFromPeriod(lidoPrices, PERIOD.DAYS_30) */ - + console.log(monthlyLstPriceChanges) const rateData: Record = {} - rateData.jlp = calculateRate(jlpPrices)?.rate ?? rateData.jlp - rateData.msol = calculateRate(msolPrices)?.rate ?? rateData.msol - rateData.jitosol = calculateRate(jitoPrices)?.rate ?? rateData.jitosol - rateData.bsol = calculateRate(bsolPrices)?.rate ?? rateData.bsol - rateData.jsol = calculateRate(jsolPrices)?.rate ?? rateData.jsol - rateData.inf = calculateRate(infPrices)?.rate ?? rateData.inf - rateData.hubsol = calculateRate(hubSOLPrices)?.rate ?? rateData.hubsol - rateData.digitsol = calculateRate(digitSOLPrices)?.rate ?? rateData.digitsol - rateData.dualsol = calculateRate(dualSOLPrices)?.rate ?? rateData.dualsol - rateData.mangosol = calculateRate(mangoSOLPrices)?.rate ?? rateData.mangosol - rateData.compasssol = - calculateRate(compassSOLPrices)?.rate ?? rateData.compasssol - + rateData.jlp = calculateRateFromOhlcv(jlpPrices)?.rate ?? rateData.jlp + rateData.msol = calculateRateFromOhlcv(msolPrices)?.rate ?? rateData.msol + rateData.jitosol = + calculateRateFromOhlcv(jitoPrices)?.rate ?? rateData.jitosol + rateData.bsol = calculateRateFromOhlcv(bsolPrices)?.rate ?? rateData.bsol + rateData.inf = calculateRateFromOhlcv(infPrices)?.rate ?? rateData.inf + rateData.jsol = calculateRateFromOhlcv(jsolPrices)?.rate ?? rateData.jsol + rateData.hubsol = monthlyLstPriceChanges['hubsol'] ?? 0 + rateData.digitsol = monthlyLstPriceChanges['digitsol'] ?? 0 + rateData.dualsol = monthlyLstPriceChanges['dualsol'] ?? 0 + rateData.mangosol = monthlyLstPriceChanges['mangosol'] ?? 0 + rateData.compasssol = monthlyLstPriceChanges['compasssol'] ?? 0 return rateData } catch (e) { return {} @@ -103,3 +98,18 @@ export default function useStakeRates() { isLoading: response.isFetching || response.isLoading, } } + +async function fetchApyToSol(tokensData: StakeableTokensData[]) { + const resp = await fetch( + 'https://api.mngo.cloud/data/boost/stats/monthly-sol-price', + ) + const json: { data: { mint: string; monthly_price_change: number }[] } = + await resp.json() + const tokenToApy: { [key: string]: number } = {} + for (const token of tokensData) { + const record = json.data.find((x) => x.mint === token.mint_address) + const apy = (1 + (record?.monthly_price_change || 0)) ** 12 - 1 + tokenToApy[token.symbol.toLowerCase()] = apy + } + return tokenToApy +}