From 1345ea51857db43ad51c4ac6e1f8ebb8d13c2f39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20Brzezin=CC=81ski?= Date: Tue, 20 Feb 2024 22:41:06 +0100 Subject: [PATCH] fix --- components/DepositForm.tsx | 501 ++++++++++++++++++------------------- components/HomePage.tsx | 3 - components/Positions.tsx | 34 +-- components/Stake.tsx | 16 +- components/TokenButton.tsx | 15 +- 5 files changed, 270 insertions(+), 299 deletions(-) diff --git a/components/DepositForm.tsx b/components/DepositForm.tsx index 57e8d82..f4111c9 100644 --- a/components/DepositForm.tsx +++ b/components/DepositForm.tsx @@ -1,11 +1,7 @@ -import { - ArrowPathIcon, - ChevronDownIcon, - ExclamationCircleIcon, -} from '@heroicons/react/20/solid' +import { ArrowPathIcon, ExclamationCircleIcon } from '@heroicons/react/20/solid' import { useWallet } from '@solana/wallet-adapter-react' import { useTranslation } from 'next-i18next' -import React, { useCallback, useEffect, useMemo, useState } from 'react' +import React, { useCallback, useMemo, useState } from 'react' import NumberFormat, { NumberFormatValues } from 'react-number-format' import mangoStore from '@store/mangoStore' import { notify } from '../utils/notifications' @@ -24,17 +20,11 @@ import SecondaryConnectButton from './shared/SecondaryConnectButton' import useMangoAccountAccounts from 'hooks/useMangoAccountAccounts' import InlineNotification from './shared/InlineNotification' import Link from 'next/link' -import LeverageSlider from './shared/LeverageSlider' import useMangoGroup from 'hooks/useMangoGroup' -import FormatNumericValue from './shared/FormatNumericValue' -import { depositAndCreate, stakeAndCreate } from 'utils/transactions' +import { depositAndCreate } from 'utils/transactions' // import { MangoAccount } from '@blockworks-foundation/mango-v4' import { AnchorProvider } from '@project-serum/anchor' -import useBankRates from 'hooks/useBankRates' -import { Disclosure } from '@headlessui/react' import SheenLoader from './shared/SheenLoader' -import useLeverageMax from 'hooks/useLeverageMax' -import { STAKEABLE_TOKENS_DATA } from 'utils/constants' import { sleep } from 'utils' import ButtonGroup from './forms/ButtonGroup' import Decimal from 'decimal.js' @@ -42,32 +32,31 @@ import Decimal from 'decimal.js' const set = mangoStore.getState().set export const NUMBERFORMAT_CLASSES = - 'inner-shadow-top-sm w-full rounded-xl border border-th-bkg-3 bg-th-input-bkg p-3 pl-12 pr-4 text-left font-bold text-xl text-th-fgd-1 focus:outline-none focus-visible:border-th-fgd-4 md:hover:border-th-bkg-4 md:hover:focus-visible:border-th-fgd-4' + 'inner-shadow-top-sm w-full rounded-xl border border-th-bkg-3 bg-th-input-bkg p-3 pl-12 pr-4 text-left font-bold text-xl text-th-fgd-1 focus:outline-none focus-visible:border-th-fgd-4 md:hover:border-th-bkg-4 md:hover:focus-visible:border-th-fgd-4' interface StakeFormProps { - token: string + token: string } export const walletBalanceForToken = ( - walletTokens: TokenAccount[], - token: string, + walletTokens: TokenAccount[], + token: string, ): { maxAmount: number; maxDecimals: number } => { - const group = mangoStore.getState().group - const bank = group?.banksMapByName.get(token)?.[0] + const group = mangoStore.getState().group + const bank = group?.banksMapByName.get(token)?.[0] - let walletToken - if (bank) { - const tokenMint = bank?.mint - walletToken = tokenMint - ? walletTokens.find((t) => t.mint.toString() === tokenMint.toString()) - : null - } + let walletToken + if (bank) { + const tokenMint = bank?.mint + walletToken = tokenMint + ? walletTokens.find((t) => t.mint.toString() === tokenMint.toString()) + : null + } - - return { - maxAmount: walletToken ? walletToken.uiAmount : 0, - maxDecimals: bank?.mintDecimals || 6, - } + return { + maxAmount: walletToken ? walletToken.uiAmount : 0, + maxDecimals: bank?.mintDecimals || 6, + } } // const getNextAccountNumber = (accounts: MangoAccount[]): number => { @@ -84,242 +73,240 @@ export const walletBalanceForToken = ( // } function DespositForm({ token: selectedToken }: StakeFormProps) { - const { t } = useTranslation(['common', 'account']) - const [inputAmount, setInputAmount] = useState('') - const submitting = mangoStore((s) => s.submittingBoost) - const [refreshingWalletTokens, setRefreshingWalletTokens] = useState(false) - const { maxSolDeposit } = useSolBalance() - const { usedTokens, totalTokens } = useMangoAccountAccounts() - const { group } = useMangoGroup() - const groupLoaded = mangoStore((s) => s.groupLoaded) - const { connected, publicKey } = useWallet() - const walletTokens = mangoStore((s) => s.wallet.tokens) - const [sizePercentage, setSizePercentage] = useState('') + const { t } = useTranslation(['common', 'account']) + const [inputAmount, setInputAmount] = useState('') + const submitting = mangoStore((s) => s.submittingBoost) + const [refreshingWalletTokens, setRefreshingWalletTokens] = useState(false) + const { maxSolDeposit } = useSolBalance() + const { usedTokens, totalTokens } = useMangoAccountAccounts() + const { group } = useMangoGroup() + const groupLoaded = mangoStore((s) => s.groupLoaded) + const { connected, publicKey } = useWallet() + const walletTokens = mangoStore((s) => s.wallet.tokens) + const [sizePercentage, setSizePercentage] = useState('') - const depositBank = useMemo(() => { - return group?.banksMapByName.get(selectedToken)?.[0] - }, [selectedToken, group]) + const depositBank = useMemo(() => { + return group?.banksMapByName.get(selectedToken)?.[0] + }, [selectedToken, group]) - const tokenMax = useMemo(() => { - return walletBalanceForToken(walletTokens, selectedToken) - }, [walletTokens, selectedToken]) + const tokenMax = useMemo(() => { + return walletBalanceForToken(walletTokens, selectedToken) + }, [walletTokens, selectedToken]) - const setMax = useCallback(() => { - const max = floorToDecimal(tokenMax.maxAmount, 6) - setInputAmount(max.toFixed()) - }, [tokenMax]) + const setMax = useCallback(() => { + const max = floorToDecimal(tokenMax.maxAmount, 6) + setInputAmount(max.toFixed()) + }, [tokenMax]) - const handleRefreshWalletBalances = useCallback(async () => { - if (!publicKey) return - const actions = mangoStore.getState().actions - setRefreshingWalletTokens(true) - await actions.fetchWalletTokens(publicKey) - setRefreshingWalletTokens(false) - }, [publicKey]) + const handleRefreshWalletBalances = useCallback(async () => { + if (!publicKey) return + const actions = mangoStore.getState().actions + setRefreshingWalletTokens(true) + await actions.fetchWalletTokens(publicKey) + setRefreshingWalletTokens(false) + }, [publicKey]) - const tokenPositionsFull = useMemo(() => { - if (!depositBank || !usedTokens.length || !totalTokens.length) return false - const hasTokenPosition = usedTokens.find( - (token) => token.tokenIndex === depositBank.tokenIndex, + const tokenPositionsFull = useMemo(() => { + if (!depositBank || !usedTokens.length || !totalTokens.length) return false + const hasTokenPosition = usedTokens.find( + (token) => token.tokenIndex === depositBank.tokenIndex, + ) + return hasTokenPosition ? false : usedTokens.length >= totalTokens.length + }, [depositBank, usedTokens, totalTokens]) + + const handleDeposit = useCallback(async () => { + const client = mangoStore.getState().client + const group = mangoStore.getState().group + const actions = mangoStore.getState().actions + const mangoAccounts = mangoStore.getState().mangoAccounts + const mangoAccount = mangoStore.getState().mangoAccount.current + + if (!group || !depositBank || !publicKey) return + + set((state) => { + state.submittingBoost = true + }) + try { + notify({ + title: 'Building transaction. This may take a moment.', + type: 'info', + }) + const { signature: tx, slot } = await depositAndCreate( + client, + group, + mangoAccount, + depositBank.mint, + parseFloat(inputAmount), + mangoAccounts?.length + 1 ?? 0, + ) + notify({ + title: 'Transaction confirmed', + type: 'success', + txid: tx, + }) + set((state) => { + state.submittingBoost = false + }) + setInputAmount('') + await sleep(500) + if (!mangoAccount) { + await actions.fetchMangoAccounts( + (client.program.provider as AnchorProvider).wallet.publicKey, ) - return hasTokenPosition ? false : usedTokens.length >= totalTokens.length - }, [depositBank, usedTokens, totalTokens]) + } + await actions.reloadMangoAccount(slot) + await actions.fetchWalletTokens(publicKey) + } catch (e) { + console.error('Error depositing:', e) + set((state) => { + state.submittingBoost = false + }) + if (!isMangoError(e)) return + notify({ + title: 'Transaction failed', + description: e.message, + txid: e?.txid, + type: 'error', + }) + } + }, [depositBank, publicKey, inputAmount]) - const handleDeposit = useCallback(async () => { - const client = mangoStore.getState().client - const group = mangoStore.getState().group - const actions = mangoStore.getState().actions - const mangoAccounts = mangoStore.getState().mangoAccounts - const mangoAccount = mangoStore.getState().mangoAccount.current + const showInsufficientBalance = + tokenMax.maxAmount < Number(inputAmount) || + (selectedToken === 'USDC' && maxSolDeposit <= 0) - if (!group || !depositBank || !publicKey) return + const handleSizePercentage = useCallback( + (percentage: string) => { + if (!depositBank) return + setSizePercentage(percentage) + const amount = floorToDecimal( + new Decimal(percentage).div(100).mul(tokenMax.maxAmount), + depositBank.mintDecimals, + ) + setInputAmount(amount.toFixed()) + }, + [tokenMax, depositBank], + ) - set((state) => { - state.submittingBoost = true - }) - try { - notify({ - title: 'Building transaction. This may take a moment.', - type: 'info', - }) - const { signature: tx, slot } = await depositAndCreate( - client, - group, - mangoAccount, - depositBank.mint, - parseFloat(inputAmount), - mangoAccounts?.length + 1 ?? 0, - ) - notify({ - title: 'Transaction confirmed', - type: 'success', - txid: tx, - }) - set((state) => { - state.submittingBoost = false - }) - setInputAmount('') - await sleep(500) - if (!mangoAccount) { - await actions.fetchMangoAccounts( - (client.program.provider as AnchorProvider).wallet.publicKey, - ) - } - await actions.reloadMangoAccount(slot) - await actions.fetchWalletTokens(publicKey) - } catch (e) { - console.error('Error depositing:', e) - set((state) => { - state.submittingBoost = false - }) - if (!isMangoError(e)) return - notify({ - title: 'Transaction failed', - description: e.message, - txid: e?.txid, - type: 'error', - }) - } - }, [depositBank, publicKey, inputAmount]) - - const showInsufficientBalance = - tokenMax.maxAmount < Number(inputAmount) || - (selectedToken === 'USDC' && maxSolDeposit <= 0) - - const handleSizePercentage = useCallback( - (percentage: string) => { - if (!depositBank) return - setSizePercentage(percentage) - const amount = floorToDecimal( - new Decimal(percentage).div(100).mul(tokenMax.maxAmount), - depositBank.mintDecimals, - ) - setInputAmount(amount.toFixed()) - }, - [tokenMax, depositBank], - ) - - - return ( - <> -
-
- -
-
-
-
-
- { - setInputAmount( - !Number.isNaN(Number(e.value)) ? e.value : '', - ) - }} - isAllowed={withValueLimit} - /> -
- -
-
- - {formatTokenSymbol(selectedToken)} - -
-
-
-
- handleSizePercentage(p)} - values={['10', '25', '50', '75', '100']} - unit="%" - /> -
-
- {depositBank ? ( -
-
- ) : !groupLoaded ? ( -
- -
- -
- ) : null} -
- {connected ? ( - - ) : ( - - )} - {tokenPositionsFull ? ( - - {t('error-token-positions-full')}{' '} - - {t('manage')} - - - } - /> - ) : null} + return ( + <> +
+
+ +
+
+
- - ) +
+
+ { + setInputAmount( + !Number.isNaN(Number(e.value)) ? e.value : '', + ) + }} + isAllowed={withValueLimit} + /> +
+ +
+
+ + {formatTokenSymbol(selectedToken)} + +
+
+
+
+ handleSizePercentage(p)} + values={['10', '25', '50', '75', '100']} + unit="%" + /> +
+
+ {depositBank ? ( +
+ ) : !groupLoaded ? ( +
+ +
+ +
+ ) : null} +
+ {connected ? ( + + ) : ( + + )} + {tokenPositionsFull ? ( + + {t('error-token-positions-full')}{' '} + + {t('manage')} + + + } + /> + ) : null} +
+ + ) } export default DespositForm diff --git a/components/HomePage.tsx b/components/HomePage.tsx index 38458c4..61c20f1 100644 --- a/components/HomePage.tsx +++ b/components/HomePage.tsx @@ -6,7 +6,6 @@ import TransactionHistory from './TransactionHistory' import mangoStore, { ActiveTab } from '@store/mangoStore' import { useCallback, useEffect } from 'react' import { BOOST_ACCOUNT_PREFIX } from 'utils/constants' -import useMangoAccount from 'hooks/useMangoAccount' const set = mangoStore.getState().set @@ -34,8 +33,6 @@ const HomePage = () => { }) }, [selectedToken]) - - return ( <>
diff --git a/components/Positions.tsx b/components/Positions.tsx index f223574..fbe5277 100644 --- a/components/Positions.tsx +++ b/components/Positions.tsx @@ -43,7 +43,8 @@ const Positions = ({ }: { setActiveTab: (tab: ActiveTab) => void }) => { - const [showInactivePositions, setShowInactivePositions] = useLocalStorageState(SHOW_INACTIVE_POSITIONS_KEY, true) + const [showInactivePositions, setShowInactivePositions] = + useLocalStorageState(SHOW_INACTIVE_POSITIONS_KEY, true) const { borrowBank, positions } = usePositions(showInactivePositions) console.log(showInactivePositions) @@ -55,8 +56,9 @@ const Positions = ({ return ( <>
-

{`You have ${numberOfPositions} active position${numberOfPositions !== 1 ? 's' : '' - }`}

+

{`You have ${numberOfPositions} active position${ + numberOfPositions !== 1 ? 's' : '' + }`}

setShowInactivePositions(checked)} @@ -133,21 +135,13 @@ const PositionItem = ({ const liqPriceChangePercentage = ((parseFloat(liqRatio) - currentPriceRatio) / currentPriceRatio) * 100 - return [liqRatio, liqPriceChangePercentage.toFixed(2)] }, [bank, borrowBalance, borrowBank, stakeBalance]) - - const liquidationPrice = useMemo(() => { - const borrowMaintLiabWeight = borrowBank?.maintLiabWeight - const stakeMaintAssetWeight = position.bank?.maintAssetWeight - const price = Number(position.bank?.uiPrice) * (Number(borrowMaintLiabWeight) / Number(stakeMaintAssetWeight)) * (1 - (1 / leverage)) - - return price - }, [position.bank, borrowBank, leverage]) - - - const { estimatedNetAPY, borrowBankBorrowRate } = useBankRates(bank.name, leverage) + const { estimatedNetAPY, borrowBankBorrowRate } = useBankRates( + bank.name, + leverage, + ) const uiRate = bank.name == 'USDC' ? borrowBankBorrowRate : estimatedNetAPY return ( @@ -190,10 +184,9 @@ const PositionItem = ({ %
- {position.bank.name == 'USDC' ? - <> - - : + {position.bank.name == 'USDC' ? ( + <> + ) : ( <>

Leverage

@@ -225,8 +218,7 @@ const PositionItem = ({
- } - + )}
) diff --git a/components/Stake.tsx b/components/Stake.tsx index b7812f8..8235709 100644 --- a/components/Stake.tsx +++ b/components/Stake.tsx @@ -9,7 +9,6 @@ import { formatTokenSymbol } from 'utils/tokens' import { useViewport } from 'hooks/useViewport' import { ArrowTopRightOnSquareIcon } from '@heroicons/react/20/solid' import DespositForm from './DepositForm' -import WithdrawForm from './WithdrawForm' const set = mangoStore.getState().set @@ -50,24 +49,23 @@ const Stake = () => { onChange={(v) => setActiveFormTab(v)} />
- {selectedToken == 'USDC' ? + {selectedToken == 'USDC' ? ( <> - {activeFormTab === 'Add' ? ( - - ) : null} + {activeFormTab === 'Add' ? : null} {activeFormTab === 'Remove' ? ( - + ) : null} - : + ) : ( <> {activeFormTab === 'Add' ? ( ) : null} {activeFormTab === 'Remove' ? ( - ) : null} - } + ) : null} + + )} diff --git a/components/TokenButton.tsx b/components/TokenButton.tsx index 4544691..e3d869b 100644 --- a/components/TokenButton.tsx +++ b/components/TokenButton.tsx @@ -13,14 +13,12 @@ const TokenButton = ({ handleTokenSelect: (v: string) => void }) => { const leverage = useLeverageMax(tokenName) - const { - stakeBankDepositRate, - borrowBankBorrowRate, - borrowBankStakeRate, - leveragedAPY, - estimatedNetAPY, - } = useBankRates(tokenName, leverage) - const UiRate = tokenName == 'USDC' ? borrowBankBorrowRate : borrowBankStakeRate + const { borrowBankBorrowRate, borrowBankStakeRate } = useBankRates( + tokenName, + leverage, + ) + const UiRate = + tokenName == 'USDC' ? borrowBankBorrowRate : borrowBankStakeRate return (