leverage and usdc fixes

This commit is contained in:
Adrian Brzeziński 2024-03-24 23:03:44 +01:00
parent a382829e72
commit 01fecedcff
9 changed files with 74 additions and 47 deletions

View File

@ -3,16 +3,12 @@ import mangoStore from '@store/mangoStore'
import { Keypair } from '@solana/web3.js' import { Keypair } from '@solana/web3.js'
import useMangoAccount from 'hooks/useMangoAccount' import useMangoAccount from 'hooks/useMangoAccount'
import useInterval from './shared/useInterval' import useInterval from './shared/useInterval'
import { import { LAST_WALLET_NAME, PRIORITY_FEE_KEY, SECONDS } from 'utils/constants'
LAST_WALLET_NAME,
PRIORITY_FEE_KEY,
SECONDS,
STAKEABLE_TOKENS_DATA,
} from 'utils/constants'
import useNetworkSpeed from 'hooks/useNetworkSpeed' import useNetworkSpeed from 'hooks/useNetworkSpeed'
import { useWallet } from '@solana/wallet-adapter-react' import { useWallet } from '@solana/wallet-adapter-react'
import useLocalStorageState from 'hooks/useLocalStorageState' import useLocalStorageState from 'hooks/useLocalStorageState'
import { DEFAULT_PRIORITY_FEE_LEVEL } from './settings/RpcSettings' import { DEFAULT_PRIORITY_FEE_LEVEL } from './settings/RpcSettings'
import { getStakableTokensDataForTokenName } from 'utils/tokens'
const set = mangoStore.getState().set const set = mangoStore.getState().set
const actions = mangoStore.getState().actions const actions = mangoStore.getState().actions
@ -20,9 +16,8 @@ const actions = mangoStore.getState().actions
const HydrateStore = () => { const HydrateStore = () => {
const { mangoAccountPk } = useMangoAccount() const { mangoAccountPk } = useMangoAccount()
const selectedToken = mangoStore((s) => s.selectedToken) const selectedToken = mangoStore((s) => s.selectedToken)
const clientContext = STAKEABLE_TOKENS_DATA.find( const clientContext =
(x) => x.name === selectedToken, getStakableTokensDataForTokenName(selectedToken).clientContext
)!.clientContext
const connection = mangoStore((s) => s.connection) const connection = mangoStore((s) => s.connection)

View File

@ -4,8 +4,11 @@ import TabUnderline from './shared/TabUnderline'
import StakeForm from '@components/StakeForm' import StakeForm from '@components/StakeForm'
import UnstakeForm from '@components/UnstakeForm' import UnstakeForm from '@components/UnstakeForm'
import mangoStore from '@store/mangoStore' import mangoStore from '@store/mangoStore'
import { STAKEABLE_TOKENS, STAKEABLE_TOKENS_DATA } from 'utils/constants' import { STAKEABLE_TOKENS } from 'utils/constants'
import { formatTokenSymbol } from 'utils/tokens' import {
formatTokenSymbol,
getStakableTokensDataForTokenName,
} from 'utils/tokens'
import { useViewport } from 'hooks/useViewport' import { useViewport } from 'hooks/useViewport'
import { ArrowTopRightOnSquareIcon } from '@heroicons/react/20/solid' import { ArrowTopRightOnSquareIcon } from '@heroicons/react/20/solid'
import DespositForm from './DepositForm' import DespositForm from './DepositForm'
@ -104,7 +107,7 @@ const Stake = () => {
<DespositForm <DespositForm
token="USDC" token="USDC"
clientContext={ clientContext={
STAKEABLE_TOKENS_DATA.find((x) => x.name === 'USDC')! getStakableTokensDataForTokenName('USDC')
.clientContext .clientContext
} }
/> />
@ -113,7 +116,7 @@ const Stake = () => {
<UnstakeForm <UnstakeForm
token="USDC" token="USDC"
clientContext={ clientContext={
STAKEABLE_TOKENS_DATA.find((x) => x.name === 'USDC')! getStakableTokensDataForTokenName('USDC')
.clientContext .clientContext
} }
/> />
@ -125,9 +128,8 @@ const Stake = () => {
<StakeForm <StakeForm
token={selectedToken} token={selectedToken}
clientContext={ clientContext={
STAKEABLE_TOKENS_DATA.find( getStakableTokensDataForTokenName(selectedToken)
(x) => x.name === selectedToken, .clientContext
)!.clientContext
} }
/> />
) : null} ) : null}
@ -135,9 +137,8 @@ const Stake = () => {
<UnstakeForm <UnstakeForm
token={selectedToken} token={selectedToken}
clientContext={ clientContext={
STAKEABLE_TOKENS_DATA.find( getStakableTokensDataForTokenName(selectedToken)
(x) => x.name === selectedToken, .clientContext
)!.clientContext
} }
/> />
) : null} ) : null}

View File

@ -112,7 +112,7 @@ function StakeForm({ token: selectedToken, clientContext }: StakeFormProps) {
leverage, leverage,
) )
const leverageMax = useLeverageMax(selectedToken) const leverageMax = useLeverageMax(selectedToken)
console.log(leverageMax)
const [stakeBank, borrowBank] = useMemo(() => { const [stakeBank, borrowBank] = useMemo(() => {
const stakeBank = const stakeBank =
clientContext === 'jlp' clientContext === 'jlp'
@ -175,9 +175,17 @@ function StakeForm({ token: selectedToken, clientContext }: StakeFormProps) {
const borrowPrice = borrowBank?.uiPrice const borrowPrice = borrowBank?.uiPrice
const stakePrice = stakeBank?.uiPrice const stakePrice = stakeBank?.uiPrice
if (!borrowPrice || !stakePrice || !Number(inputAmount)) return 0 if (!borrowPrice || !stakePrice || !Number(inputAmount)) return 0
if (clientContext === 'jlp') {
const borrowAmount = const borrowAmount =
stakeBank?.uiPrice * Number(inputAmount) * (leverage - 1) stakeBank?.uiPrice * Number(inputAmount) * (leverage - 1)
return borrowAmount return borrowAmount
} else {
const priceDifference = (stakePrice - borrowPrice) / borrowPrice
const borrowAmount =
(1 + priceDifference) * Number(inputAmount) * Math.min(leverage - 1, 1)
return borrowAmount
}
}, [leverage, borrowBank, stakeBank, inputAmount]) }, [leverage, borrowBank, stakeBank, inputAmount])
const availableVaultBalance = useMemo(() => { const availableVaultBalance = useMemo(() => {
@ -213,7 +221,7 @@ function StakeForm({ token: selectedToken, clientContext }: StakeFormProps) {
const accNumber = getNextAccountNumber(mangoAccounts) const accNumber = getNextAccountNumber(mangoAccounts)
if (!group) return if (!group) return
console.log(mangoAccounts)
set((state) => { set((state) => {
state.submittingBoost = true state.submittingBoost = true
}) })

View File

@ -101,10 +101,11 @@ function UnstakeForm({
borrowBankAmount && borrowBankAmount &&
borrowBankAmount.toNumber() < 0 borrowBankAmount.toNumber() < 0
) { ) {
const lev = stakeBankAmount const stakeAmountValue = stakeBankAmount.mul(stakeBank.getAssetPrice())
const lev = stakeAmountValue
.div( .div(
stakeBankAmount.sub( stakeAmountValue.sub(
borrowBankAmount.abs().div(stakeBank.getAssetPrice()), borrowBankAmount.abs().mul(borrowBank.getAssetPrice()),
), ),
) )
.toNumber() .toNumber()
@ -259,10 +260,14 @@ function UnstakeForm({
if (!mangoAccount || !stakeBank) return 0 if (!mangoAccount || !stakeBank) return 0
const group = clientContext === 'jlp' ? jlpGroup : lstGroup const group = clientContext === 'jlp' ? jlpGroup : lstGroup
if (!group) return 0 if (!group) return 0
try {
return mangoAccount.getMaxWithdrawWithBorrowForTokenUi( return mangoAccount.getMaxWithdrawWithBorrowForTokenUi(
group, group,
stakeBank.mint, stakeBank.mint,
) )
} catch (e) {
return 0
}
}, [jlpGroup, lstGroup, mangoAccount, stakeBank, clientContext]) }, [jlpGroup, lstGroup, mangoAccount, stakeBank, clientContext])
const showInsufficientBalance = const showInsufficientBalance =
@ -414,7 +419,9 @@ function UnstakeForm({
</span> </span>
</div> </div>
<div className="flex justify-between"> <div className="flex justify-between">
<p className="text-th-fgd-4">USDC borrowed</p> <p className="text-th-fgd-4">
{borrowBank.name} borrowed
</p>
{borrowBank ? ( {borrowBank ? (
<span <span
className={`font-bold ${ className={`font-bold ${

View File

@ -87,9 +87,7 @@ export default function useBankRates(selectedToken: string, leverage: number) {
// Total APY, comparing the end value (deposits - borrows) to the starting value (1) // Total APY, comparing the end value (deposits - borrows) to the starting value (1)
const APY = (deposits - borrows - 1) * 100 const APY = (deposits - borrows - 1) * 100
console.log(selectedToken, {
stakeRates,
})
// Comparisons to outside // Comparisons to outside
const nonMangoAPY = tokenStakeRateAPY * leverage * 100 const nonMangoAPY = tokenStakeRateAPY * leverage * 100
const diffToNonMango = APY - nonMangoAPY const diffToNonMango = APY - nonMangoAPY

View File

@ -1,11 +1,8 @@
import { useMemo } from 'react' import { useMemo } from 'react'
import useMangoGroup from './useMangoGroup' import useMangoGroup from './useMangoGroup'
import { floorToDecimal } from 'utils/numbers' import { floorToDecimal } from 'utils/numbers'
import { import { JLP_BORROW_TOKEN, LST_BORROW_TOKEN } from 'utils/constants'
JLP_BORROW_TOKEN, import { getStakableTokensDataForTokenName } from 'utils/tokens'
LST_BORROW_TOKEN,
STAKEABLE_TOKENS_DATA,
} from 'utils/constants'
export default function useLeverageMax(selectedToken: string) { export default function useLeverageMax(selectedToken: string) {
const { jlpGroup, lstGroup } = useMangoGroup() const { jlpGroup, lstGroup } = useMangoGroup()
@ -35,8 +32,7 @@ export default function useLeverageMax(selectedToken: string) {
const x = stakeInitAssetWeight.toNumber() / borrowInitLiabWeight.toNumber() const x = stakeInitAssetWeight.toNumber() / borrowInitLiabWeight.toNumber()
if ( if (
STAKEABLE_TOKENS_DATA.find((x) => x.name === selectedToken) getStakableTokensDataForTokenName(selectedToken).clientContext === 'jlp'
?.clientContext === 'jlp'
) { ) {
const leverageFactor = 1 / (1 - x) const leverageFactor = 1 / (1 - x)

View File

@ -10,6 +10,7 @@ export const STAKEABLE_TOKENS_DATA: {
active: boolean active: boolean
mint_address: string mint_address: string
clientContext: ClientContextKeys clientContext: ClientContextKeys
borrowToken: 'USDC' | 'SOL'
}[] = [ }[] = [
{ {
name: 'JLP', name: 'JLP',
@ -17,6 +18,7 @@ export const STAKEABLE_TOKENS_DATA: {
active: true, active: true,
mint_address: '27G8MtK7VtTcCHkpASjSDdkWWYfoqT6ggEuKidVJidD4', mint_address: '27G8MtK7VtTcCHkpASjSDdkWWYfoqT6ggEuKidVJidD4',
clientContext: 'jlp', clientContext: 'jlp',
borrowToken: 'USDC',
}, },
{ {
name: 'USDC', name: 'USDC',
@ -24,6 +26,7 @@ export const STAKEABLE_TOKENS_DATA: {
active: true, active: true,
mint_address: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', mint_address: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
clientContext: 'jlp', clientContext: 'jlp',
borrowToken: 'USDC',
}, },
{ {
name: 'MSOL', name: 'MSOL',
@ -31,6 +34,7 @@ export const STAKEABLE_TOKENS_DATA: {
active: true, active: true,
mint_address: 'mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So', mint_address: 'mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So',
clientContext: 'lst', clientContext: 'lst',
borrowToken: 'SOL',
}, },
{ {
name: 'JitoSOL', name: 'JitoSOL',
@ -38,6 +42,7 @@ export const STAKEABLE_TOKENS_DATA: {
active: true, active: true,
mint_address: 'J1toso1uCk3RLmjorhTtrVwY9HJ7X8V9yYac6Y7kGCPn', mint_address: 'J1toso1uCk3RLmjorhTtrVwY9HJ7X8V9yYac6Y7kGCPn',
clientContext: 'lst', clientContext: 'lst',
borrowToken: 'SOL',
}, },
{ {
name: 'bSOL', name: 'bSOL',
@ -45,6 +50,7 @@ export const STAKEABLE_TOKENS_DATA: {
active: true, active: true,
mint_address: 'bSo13r4TkiE4KumL71LsHTPpL2euBYLFx6h9HP3piy1', mint_address: 'bSo13r4TkiE4KumL71LsHTPpL2euBYLFx6h9HP3piy1',
clientContext: 'lst', clientContext: 'lst',
borrowToken: 'SOL',
}, },
] ]

View File

@ -1,6 +1,7 @@
import { PublicKey, Connection } from '@solana/web3.js' import { PublicKey, Connection } from '@solana/web3.js'
import { TokenInstructions } from '@project-serum/serum' import { TokenInstructions } from '@project-serum/serum'
import { toUiDecimals } from '@blockworks-foundation/mango-v4' import { toUiDecimals } from '@blockworks-foundation/mango-v4'
import { STAKEABLE_TOKENS_DATA } from './constants'
export class TokenAccount { export class TokenAccount {
publicKey!: PublicKey publicKey!: PublicKey
@ -26,7 +27,7 @@ export class TokenAccount {
} }
} }
function exists<T>(item: T | null | undefined): item is T { export function exists<T>(item: T | null | undefined): item is T {
return !!item return !!item
} }
@ -74,3 +75,11 @@ export const formatTokenSymbol = (symbol: string) => {
} }
return symbol === 'MSOL' ? 'mSOL' : symbol return symbol === 'MSOL' ? 'mSOL' : symbol
} }
export const getStakableTokensDataForMint = (mintPk: string) => {
return STAKEABLE_TOKENS_DATA.find((x) => x.mint_address === mintPk)!
}
export const getStakableTokensDataForTokenName = (tokenName: string) => {
return STAKEABLE_TOKENS_DATA.find((x) => x.name === tokenName)!
}

View File

@ -37,6 +37,7 @@ import {
import { floorToDecimal } from './numbers' import { floorToDecimal } from './numbers'
import { BOOST_ACCOUNT_PREFIX } from './constants' import { BOOST_ACCOUNT_PREFIX } from './constants'
import { notify } from './notifications' import { notify } from './notifications'
import { getStakableTokensDataForMint } from './tokens'
export const withdrawAndClose = async ( export const withdrawAndClose = async (
client: MangoClient, client: MangoClient,
@ -47,10 +48,12 @@ export const withdrawAndClose = async (
) => { ) => {
console.log('withdraw and close') console.log('withdraw and close')
const borrowBank = group?.banksMapByName.get('USDC')?.[0] const borrowBank = group?.banksMapByName.get(
getStakableTokensDataForMint(stakeMintPk.toBase58()).borrowToken,
)?.[0]
const stakeBank = group?.banksMapByMint.get(stakeMintPk.toString())?.[0] const stakeBank = group?.banksMapByMint.get(stakeMintPk.toString())?.[0]
const instructions: TransactionInstruction[] = [] const instructions: TransactionInstruction[] = []
console.log(borrowBank, stakeBank, mangoAccount)
if (!borrowBank || !stakeBank || !mangoAccount) { if (!borrowBank || !stakeBank || !mangoAccount) {
throw Error('Unable to find USDC bank or stake bank or mango account') throw Error('Unable to find USDC bank or stake bank or mango account')
} }
@ -117,7 +120,9 @@ export const unstakeAndSwap = async (
console.log('unstake and swap') console.log('unstake and swap')
const payer = (client.program.provider as AnchorProvider).wallet.publicKey const payer = (client.program.provider as AnchorProvider).wallet.publicKey
const borrowBank = group?.banksMapByName.get('USDC')?.[0] const borrowBank = group?.banksMapByName.get(
getStakableTokensDataForMint(stakeMintPk.toBase58()).borrowToken,
)?.[0]
const stakeBank = group?.banksMapByMint.get(stakeMintPk.toString())?.[0] const stakeBank = group?.banksMapByMint.get(stakeMintPk.toString())?.[0]
const instructions: TransactionInstruction[] = [] const instructions: TransactionInstruction[] = []
@ -208,7 +213,9 @@ export const stakeAndCreate = async (
name?: string, name?: string,
): Promise<MangoSignatureStatus> => { ): Promise<MangoSignatureStatus> => {
const payer = (client.program.provider as AnchorProvider).wallet.publicKey const payer = (client.program.provider as AnchorProvider).wallet.publicKey
const borrowBank = group?.banksMapByName.get('USDC')?.[0] const borrowBank = group?.banksMapByName.get(
getStakableTokensDataForMint(stakeMintPk.toBase58()).borrowToken,
)?.[0]
const stakeBank = group?.banksMapByMint.get(stakeMintPk.toString())?.[0] const stakeBank = group?.banksMapByMint.get(stakeMintPk.toString())?.[0]
const instructions: TransactionInstruction[] = [] const instructions: TransactionInstruction[] = []