fix position apy

This commit is contained in:
tjs 2023-10-01 21:36:50 -04:00
parent f18757a96c
commit 68f10e23b1
4 changed files with 146 additions and 126 deletions

View File

@ -11,7 +11,7 @@ const AccountStats = ({ token }: { token: string }) => {
const solBank = useMemo(() => { const solBank = useMemo(() => {
return group?.banksMapByName.get('SOL')?.[0] return group?.banksMapByName.get('SOL')?.[0]
}, [group, token]) }, [group])
const tokenBank = useMemo(() => { const tokenBank = useMemo(() => {
return group?.banksMapByName.get(token)?.[0] return group?.banksMapByName.get(token)?.[0]

View File

@ -7,36 +7,23 @@ import { formatTokenSymbol } from 'utils/tokens'
import mangoStore from '@store/mangoStore' import mangoStore from '@store/mangoStore'
import Switch from './forms/Switch' import Switch from './forms/Switch'
import useLocalStorageState from 'hooks/useLocalStorageState' import useLocalStorageState from 'hooks/useLocalStorageState'
import useStakeRates from 'hooks/useStakeRates'
import SheenLoader from './shared/SheenLoader'
import useStakeAccounts from 'hooks/useStakeAccounts' import useStakeAccounts from 'hooks/useStakeAccounts'
import FormatNumericValue from './shared/FormatNumericValue' import FormatNumericValue from './shared/FormatNumericValue'
import { import {
Bank, Bank,
Group,
MangoAccount, MangoAccount,
toUiDecimalsForQuote, toUiDecimalsForQuote,
} from '@blockworks-foundation/mango-v4' } from '@blockworks-foundation/mango-v4'
import useBankRates from 'hooks/useBankRates'
const set = mangoStore.getState().set const set = mangoStore.getState().set
const BORROW_TOKEN = 'SOL' const BORROW_TOKEN = 'SOL'
const getLeverage = (group: Group, mangoAccount: MangoAccount): number => { type Position = {
if (!group || !mangoAccount) return 0 borrowBalance: number
const accountValue = toUiDecimalsForQuote( stakeBalance: number
mangoAccount.getEquity(group).toNumber(), bank: Bank
) acct: MangoAccount | undefined
const assetsValue = toUiDecimalsForQuote(
mangoAccount.getAssetsValue(group).toNumber(),
)
if (isNaN(assetsValue / accountValue)) {
return 0
} else {
return Math.abs(1 - assetsValue / accountValue) + 1
}
} }
const getLiquidationRatio = ( const getLiquidationRatio = (
@ -57,7 +44,6 @@ const Positions = ({
setActiveTab: (tab: string) => void setActiveTab: (tab: string) => void
}) => { }) => {
const { group } = useMangoGroup() const { group } = useMangoGroup()
const { data: stakeRates, isLoading: loadingRates } = useStakeRates()
const [showInactivePositions, setShowInactivePositions] = const [showInactivePositions, setShowInactivePositions] =
useLocalStorageState(SHOW_INACTIVE_POSITIONS_KEY, true) useLocalStorageState(SHOW_INACTIVE_POSITIONS_KEY, true)
const { stakeAccounts } = useStakeAccounts() const { stakeAccounts } = useStakeAccounts()
@ -100,13 +86,6 @@ const Positions = ({
return positions.filter((pos) => pos.stakeBalance > 0).length return positions.filter((pos) => pos.stakeBalance > 0).length
}, [positions]) }, [positions])
const handleAddOrManagePosition = (token: string) => {
setActiveTab('Stake')
set((state) => {
state.selectedToken = token
})
}
return ( return (
<> <>
<div className="mb-2 flex items-center justify-between rounded-lg border-2 border-th-fgd-1 bg-th-bkg-1 px-6 py-3.5"> <div className="mb-2 flex items-center justify-between rounded-lg border-2 border-th-fgd-1 bg-th-bkg-1 px-6 py-3.5">
@ -122,92 +101,14 @@ const Positions = ({
</div> </div>
<div className="grid grid-cols-1 gap-2"> <div className="grid grid-cols-1 gap-2">
{positions.length ? ( {positions.length ? (
positions.map((position, i) => { positions.map((position) => {
const { stakeBalance, borrowBalance, bank, acct } = position return position.bank ? (
return bank ? ( <PositionItem
<div key={position.bank.name}
className="rounded-2xl border-2 border-th-fgd-1 bg-th-bkg-1 p-6" position={position}
key={i + stakeBalance} setActiveTab={setActiveTab}
> borrowBank={borrowBank}
<div className="mb-4 flex flex-col border-b border-th-bkg-3 pb-4 md:flex-row md:items-center md:justify-between"> />
<div className="mb-4 flex items-center space-x-3 md:mb-0">
<div
className={`inner-shadow-bottom-sm flex h-14 w-14 items-center justify-center rounded-full border border-th-bkg-2 bg-gradient-to-b from-th-bkg-1 to-th-bkg-2`}
>
<TokenLogo bank={bank} size={32} />
</div>
<div>
<h3>{formatTokenSymbol(bank.name)}</h3>
<span
className={`text-sm ${
stakeBalance ? 'text-th-fgd-1' : 'text-th-fgd-4'
}`}
>
{stakeBalance ? 'Opened 2 weeks ago' : 'No Position'}
</span>
</div>
</div>
<Button onClick={() => handleAddOrManagePosition(bank.name)}>
<span className="mt-1 text-base tracking-wider">
{stakeBalance ? 'Manage' : 'Add Position'}
</span>
</Button>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<p className="mb-1 text-th-fgd-4">Position Size</p>
<span className="text-xl font-bold text-th-fgd-1">
<FormatNumericValue value={stakeBalance} decimals={6} />{' '}
{formatTokenSymbol(bank.name)}
</span>
</div>
<div>
<p className="mb-1 text-th-fgd-4">Est. APY</p>
<span className="text-xl font-bold text-th-fgd-1">
{loadingRates ? (
<SheenLoader className="mt-1">
<div className="h-6 w-16 bg-th-bkg-2" />
</SheenLoader>
) : stakeRates?.[bank.name.toLowerCase()] ? (
`${(
stakeRates?.[bank.name.toLowerCase()] * 100
).toFixed(1)}%`
) : null}
</span>
</div>
<div>
<p className="mb-1 text-th-fgd-4">Leverage</p>
<span className="text-xl font-bold text-th-fgd-1">
{group && acct
? getLeverage(group, acct).toFixed(2)
: 0.0}
x
</span>
</div>
{/* <div>
<p className="mb-1 text-th-fgd-4">Earned</p>
<span className="text-xl font-bold text-th-fgd-1">
{stakeBalance
? `X.XX ${formatTokenSymbol(bank.name)}`
: `0 ${formatTokenSymbol(bank.name)}`}
</span>
</div> */}
<div>
<p className="mb-1 text-th-fgd-4">Est. Liquidation Ratio</p>
<span className="whitespace-nowrap text-xl font-bold text-th-fgd-1">
{borrowBalance && borrowBank
? getLiquidationRatio(
borrowBalance,
stakeBalance,
bank,
borrowBank,
)
: '0.00'}{' '}
{`${formatTokenSymbol(bank.name)}/${BORROW_TOKEN}`}
</span>
</div>
</div>
</div>
) : null ) : null
}) })
) : ( ) : (
@ -220,4 +121,113 @@ const Positions = ({
) )
} }
const PositionItem = ({
position,
setActiveTab,
borrowBank,
}: {
position: Position
setActiveTab: (v: string) => void
borrowBank: Bank | undefined
}) => {
const { group } = useMangoGroup()
const { stakeBalance, borrowBalance, bank, acct } = position
const handleAddOrManagePosition = (token: string) => {
setActiveTab('Stake')
set((state) => {
state.selectedToken = token
})
}
const leverage = useMemo(() => {
if (!group || !acct) return 0
const accountValue = toUiDecimalsForQuote(acct.getEquity(group).toNumber())
const assetsValue = toUiDecimalsForQuote(
acct.getAssetsValue(group).toNumber(),
)
if (isNaN(assetsValue / accountValue)) {
return 0
} else {
return Math.abs(1 - assetsValue / accountValue) + 1
}
}, [group, acct])
const { estimatedNetAPY } = useBankRates(bank.name, leverage)
return (
<div className="rounded-2xl border-2 border-th-fgd-1 bg-th-bkg-1 p-6">
<div className="mb-4 flex flex-col border-b border-th-bkg-3 pb-4 md:flex-row md:items-center md:justify-between">
<div className="mb-4 flex items-center space-x-3 md:mb-0">
<div
className={`inner-shadow-bottom-sm flex h-14 w-14 items-center justify-center rounded-full border border-th-bkg-2 bg-gradient-to-b from-th-bkg-1 to-th-bkg-2`}
>
<TokenLogo bank={bank} size={32} />
</div>
<div>
<h3>{formatTokenSymbol(bank.name)}</h3>
<span
className={`text-sm ${
stakeBalance ? 'text-th-fgd-1' : 'text-th-fgd-4'
}`}
>
{stakeBalance ? 'Opened 2 weeks ago' : 'No Position'}
</span>
</div>
</div>
<Button onClick={() => handleAddOrManagePosition(bank.name)}>
<span className="mt-1 text-base tracking-wider">
{stakeBalance ? 'Manage' : 'Add Position'}
</span>
</Button>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<p className="mb-1 text-th-fgd-4">Position Size</p>
<span className="text-xl font-bold text-th-fgd-1">
<FormatNumericValue value={stakeBalance} decimals={6} />{' '}
{formatTokenSymbol(bank.name)}
</span>
</div>
<div>
<p className="mb-1 text-th-fgd-4">Est. APY</p>
<span className="text-xl font-bold text-th-fgd-1">
<FormatNumericValue value={estimatedNetAPY} decimals={2} />%
</span>
</div>
<div>
<p className="mb-1 text-th-fgd-4">Leverage</p>
<span className="text-xl font-bold text-th-fgd-1">
{leverage ? leverage.toFixed(2) : 0.0}x
</span>
</div>
{/* <div>
<p className="mb-1 text-th-fgd-4">Earned</p>
<span className="text-xl font-bold text-th-fgd-1">
{stakeBalance
? `X.XX ${formatTokenSymbol(bank.name)}`
: `0 ${formatTokenSymbol(bank.name)}`}
</span>
</div> */}
<div>
<p className="mb-1 text-th-fgd-4">Est. Liquidation Ratio</p>
<span className="whitespace-nowrap text-xl font-bold text-th-fgd-1">
{borrowBalance && borrowBank
? getLiquidationRatio(
borrowBalance,
stakeBalance,
bank,
borrowBank,
)
: '0.00'}{' '}
{`${formatTokenSymbol(bank.name)}/${BORROW_TOKEN}`}
</span>
</div>
</div>
</div>
)
}
export default Positions export default Positions

View File

@ -13,7 +13,7 @@ const TokenButton = ({
handleTokenSelect: (v: string) => void handleTokenSelect: (v: string) => void
}) => { }) => {
const leverage = useLeverageMax(tokenName) const leverage = useLeverageMax(tokenName)
const { estimatedNetAPY } = useBankRates(tokenName, leverage) const { estimatedMaxAPY } = useBankRates(tokenName, leverage)
return ( return (
<button <button
@ -59,7 +59,7 @@ const TokenButton = ({
// /> // />
// </SheenLoader> // </SheenLoader>
// ) : // ) :
`${estimatedNetAPY.toFixed(2)}%` `${estimatedMaxAPY.toFixed(2)}%`
} }
</span> </span>
</div> </div>

View File

@ -1,14 +1,16 @@
import { useEffect, useMemo } from 'react' import { useMemo } from 'react'
import useStakeRates from './useStakeRates' import useStakeRates from './useStakeRates'
import useMangoGroup from './useMangoGroup' import useMangoGroup from './useMangoGroup'
import mangoStore from '@store/mangoStore' // import mangoStore from '@store/mangoStore'
import useLeverageMax from './useLeverageMax'
const set = mangoStore.getState().set // const set = mangoStore.getState().set
export default function useBankRates(selectedToken: string, leverage: number) { export default function useBankRates(selectedToken: string, leverage: number) {
const { data: stakeRates } = useStakeRates() const { data: stakeRates } = useStakeRates()
const { group } = useMangoGroup() const { group } = useMangoGroup()
const estimatedMaxAPY = mangoStore((s) => s.estimatedMaxAPY.current) // const estimatedMaxAPY = mangoStore((s) => s.estimatedMaxAPY.current)
const leverageMax = useLeverageMax(selectedToken)
const stakeBank = useMemo(() => { const stakeBank = useMemo(() => {
return group?.banksMapByName.get(selectedToken)?.[0] return group?.banksMapByName.get(selectedToken)?.[0]
@ -40,12 +42,20 @@ export default function useBankRates(selectedToken: string, leverage: number) {
) )
}, [borrowBankStakeRate, leverage, borrowBankBorrowRate]) }, [borrowBankStakeRate, leverage, borrowBankBorrowRate])
useEffect(() => { // useEffect(() => {
set((s) => { // set((s) => {
s.estimatedMaxAPY.current = // s.estimatedMaxAPY.current =
borrowBankStakeRate * 3 - borrowBankBorrowRate * 2 // borrowBankStakeRate * leverageMax -
}) // borrowBankBorrowRate * (leverageMax - 1)
}, [borrowBankStakeRate, borrowBankBorrowRate]) // })
// }, [borrowBankStakeRate, borrowBankBorrowRate, leverageMax])
const estimatedMaxAPY = useMemo(() => {
return (
borrowBankStakeRate * leverageMax -
borrowBankBorrowRate * (leverageMax - 1)
)
}, [borrowBankStakeRate, borrowBankBorrowRate, leverageMax])
return { return {
stakeBankDepositRate, stakeBankDepositRate,