From 32016c233f07e22fa0ad890b92e95122ad73f8bc Mon Sep 17 00:00:00 2001 From: tjs Date: Wed, 20 Sep 2023 17:41:45 -0400 Subject: [PATCH] wire up positions, add estimated net apr --- components/Positions.tsx | 19 ++++++----- components/StakeForm.tsx | 64 +++++++++++++++++++++++++++----------- components/TokenButton.tsx | 10 ++---- hooks/useStakeAccounts.ts | 20 ++++++++++++ hooks/useStakeRates.ts | 13 +++++--- pages/index.tsx | 4 +-- store/mangoStore.ts | 4 +-- utils/constants.ts | 2 ++ utils/transactions.ts | 29 +++++++++-------- 9 files changed, 108 insertions(+), 57 deletions(-) create mode 100644 hooks/useStakeAccounts.ts diff --git a/components/Positions.tsx b/components/Positions.tsx index 0ad97a8..6f41e9f 100644 --- a/components/Positions.tsx +++ b/components/Positions.tsx @@ -9,6 +9,8 @@ import Switch from './forms/Switch' import useLocalStorageState from 'hooks/useLocalStorageState' import useStakeRates from 'hooks/useStakeRates' import SheenLoader from './shared/SheenLoader' +import useStakeAccounts from 'hooks/useStakeAccounts' +import FormatNumericValue from './shared/FormatNumericValue' const set = mangoStore.getState().set @@ -21,6 +23,7 @@ const Positions = ({ const { data: stakeRates, isLoading: loadingRates } = useStakeRates() const [showInactivePositions, setShowInactivePositions] = useLocalStorageState(SHOW_INACTIVE_POSITIONS_KEY, true) + const { stakeAccounts } = useStakeAccounts() const banks = useMemo(() => { if (!group) return [] @@ -33,20 +36,21 @@ const Positions = ({ }, [group]) const positions = useMemo(() => { - if (!banks.length) return [] + if (!banks.length || !stakeAccounts?.length) return [] const positions = [] for (const bank of banks) { - let balance = 0 - if (bank?.name === 'JitoSOL') { - balance = 100 - } + if (!bank) continue + const acct = stakeAccounts.find((acc) => acc.getTokenBalanceUi(bank) > 0) + const balance = acct ? acct.getTokenBalanceUi(bank) : 0 positions.push({ balance, bank }) } const sortedPositions = positions.sort((a, b) => b.balance - a.balance) return showInactivePositions ? sortedPositions : sortedPositions.filter((pos) => pos.balance > 0) - }, [banks, showInactivePositions]) + }, [banks, showInactivePositions, stakeAccounts]) + + console.log('positions', positions) const numberOfPositions = useMemo(() => { if (!positions.length) return 0 @@ -106,7 +110,8 @@ const Positions = ({

Position Size

- {balance} {formatTokenSymbol(bank.name)} + {' '} + {formatTokenSymbol(bank.name)}
diff --git a/components/StakeForm.tsx b/components/StakeForm.tsx index b60bb2e..95c0ec9 100644 --- a/components/StakeForm.tsx +++ b/components/StakeForm.tsx @@ -36,6 +36,7 @@ import FormatNumericValue from './shared/FormatNumericValue' import { stakeAndCreate } from 'utils/transactions' import { MangoAccount } from '@blockworks-foundation/mango-v4' import { AnchorProvider } from '@project-serum/anchor' +import useStakeRates from 'hooks/useStakeRates' const set = mangoStore.getState().set @@ -92,12 +93,13 @@ function DepositForm({ onSuccess, token: selectedToken }: DepositFormProps) { // const banks = useBanksWithBalances('walletBalance') const { usedTokens, totalTokens } = useMangoAccountAccounts() const { group } = useMangoGroup() + const { data: stakeRates } = useStakeRates() const stakeBank = useMemo(() => { return group?.banksMapByName.get(selectedToken)?.[0] }, [selectedToken, group]) - const solBank = useMemo(() => { + const borrowBank = useMemo(() => { return group?.banksMapByName.get('SOL')?.[0] }, [group]) @@ -126,8 +128,8 @@ function DepositForm({ onSuccess, token: selectedToken }: DepositFormProps) { // setShowTokenList(false) // } - const solAmountToBorrow = useMemo(() => { - const solPrice = solBank?.uiPrice + const amountToBorrow = useMemo(() => { + const solPrice = borrowBank?.uiPrice const stakePrice = stakeBank?.uiPrice if (!solPrice || !stakePrice || !Number(inputAmount)) return 0 const priceDifference = (stakePrice - solPrice) / solPrice @@ -135,7 +137,7 @@ function DepositForm({ onSuccess, token: selectedToken }: DepositFormProps) { (1 + priceDifference) * Number(inputAmount) * Math.min(leverage - 1, 1) return borrowAmount - }, [leverage, solBank, stakeBank, inputAmount]) + }, [leverage, borrowBank, stakeBank, inputAmount]) const handleRefreshWalletBalances = useCallback(async () => { if (!publicKey) return @@ -157,14 +159,14 @@ function DepositForm({ onSuccess, token: selectedToken }: DepositFormProps) { setSubmitting(true) try { console.log('starting deposit') - console.log('solAmountToBorrow', solAmountToBorrow) + console.log('amountToBorrow', amountToBorrow) const newAccountNum = getNextAccountNumber(mangoAccounts) const { signature: tx, slot } = await stakeAndCreate( client, group, mangoAccount, - solAmountToBorrow, + amountToBorrow, stakeBank.mint, parseFloat(inputAmount), newAccountNum + 300, @@ -195,7 +197,7 @@ function DepositForm({ onSuccess, token: selectedToken }: DepositFormProps) { type: 'error', }) } - }, [stakeBank, publicKey, inputAmount, solAmountToBorrow, onSuccess]) + }, [stakeBank, publicKey, inputAmount, amountToBorrow, onSuccess]) const showInsufficientBalance = tokenMax.maxAmount < Number(inputAmount) || @@ -212,6 +214,28 @@ function DepositForm({ onSuccess, token: selectedToken }: DepositFormProps) { }) }, [selectedToken]) + const stakeBankDepositRate = useMemo(() => { + return stakeBank ? stakeBank.getDepositRateUi() : 0 + }, [stakeBank]) + + const borrowBankBorrowRate = useMemo(() => { + return borrowBank ? borrowBank.getBorrowRateUi() : 0 + }, [borrowBank]) + + const borrowBankStakeRate = useMemo(() => { + return stakeRates ? stakeRates[selectedToken.toLowerCase()] * 100 : 0 + }, [stakeRates, selectedToken]) + + const leveragedAPY = useMemo(() => { + return borrowBankStakeRate ? borrowBankStakeRate * leverage : 0 + }, [borrowBankStakeRate, leverage]) + + const estimatedNetAPY = useMemo(() => { + return ( + borrowBankStakeRate * leverage - borrowBankBorrowRate * (leverage - 1) + ) + }, [borrowBankStakeRate, leverage, borrowBankBorrowRate]) + return ( <>
- {stakeBank && solBank ? ( + {stakeBank && borrowBank ? ( <>
@@ -327,10 +351,10 @@ function DepositForm({ onSuccess, token: selectedToken }: DepositFormProps) {

SOL Borrowed

- {solBank ? ( + {borrowBank ? ( @@ -339,20 +363,26 @@ function DepositForm({ onSuccess, token: selectedToken }: DepositFormProps) {
-

{formatTokenSymbol(selectedToken)} Leveraged APY

- +

Estimated Net APY

+ %
+
+

{formatTokenSymbol(selectedToken)} Leveraged APY

+ + % + +

{formatTokenSymbol(selectedToken)} Deposit Rate

% @@ -360,11 +390,9 @@ function DepositForm({ onSuccess, token: selectedToken }: DepositFormProps) {

SOL Borrow Rate

- + % diff --git a/components/TokenButton.tsx b/components/TokenButton.tsx index 1dbf8e2..cb37769 100644 --- a/components/TokenButton.tsx +++ b/components/TokenButton.tsx @@ -12,13 +12,7 @@ const TokenButton = ({ selectedToken: string handleTokenSelect: (v: string) => void }) => { - const { - data: stakeRates, - isLoading: loadingStakeRates, - isFetching: fetchingStakeRates, - } = useStakeRates() - - const loadingRates = loadingStakeRates || fetchingStakeRates + const { data: stakeRates, isLoading } = useStakeRates() return (