diff --git a/components/UnstakeForm.tsx b/components/UnstakeForm.tsx index 53fb816..7db249a 100644 --- a/components/UnstakeForm.tsx +++ b/components/UnstakeForm.tsx @@ -100,13 +100,39 @@ function UnstakeForm({ token: selectedToken }: UnstakeFormProps) { const { connected, publicKey } = useWallet() + const stakeBankAmount = + mangoAccount && stakeBank && mangoAccount.getTokenBalance(stakeBank) + + const borrowAmount = + mangoAccount && borrowBank && mangoAccount.getTokenBalance(borrowBank) + + const leverage = useMemo(() => { + try { + if (stakeBankAmount && borrowAmount) { + const lev = stakeBankAmount + .div( + stakeBankAmount.sub( + borrowAmount.abs().div(stakeBank.getAssetPrice()), + ), + ) + .toNumber() + + return Math.sign(lev) !== -1 ? lev : 1 + } + return 1 + } catch (e) { + console.log(e) + return 1 + } + }, [stakeBankAmount, borrowAmount, stakeBank]) + const tokenMax = useMemo(() => { if (!stakeBank || !mangoAccount) return { maxAmount: 0.0, maxDecimals: 6 } return { - maxAmount: mangoAccount.getTokenBalanceUi(stakeBank), + maxAmount: mangoAccount.getTokenBalanceUi(stakeBank) / leverage, maxDecimals: stakeBank.mintDecimals, } - }, [stakeBank, mangoAccount]) + }, [stakeBank, mangoAccount, leverage]) const setMax = useCallback(() => { const max = floorToDecimal(tokenMax.maxAmount, tokenMax.maxDecimals) @@ -168,18 +194,22 @@ function UnstakeForm({ token: selectedToken }: UnstakeFormProps) { mangoAccount.getTokenBalanceUi(borrowBank), ) + const amountToRepay = (leverage - 1) * Number(inputAmount) + const { signature: tx } = await unstakeAndSwap( client, group, mangoAccount, stakeBank.mint, + amountToRepay, ) + notify({ title: 'Swap Transaction confirmed.', type: 'success', txid: tx, }) - await sleep(300) + await sleep(500) await actions.fetchMangoAccounts(mangoAccount.owner) await actions.fetchWalletTokens(publicKey) mangoAccount = mangoStore.getState().mangoAccount.current @@ -207,7 +237,12 @@ function UnstakeForm({ token: selectedToken }: UnstakeFormProps) { await actions.fetchMangoAccounts(mangoAccount.owner) await actions.fetchWalletTokens(publicKey) } catch (e) { - console.error('Error depositing:', e) + console.error('Error withdrawing:', e) + notify({ + title: 'Error withdrawing', + description: `${e}`, + type: 'error', + }) setSubmitting(false) if (!isMangoError(e)) return notify({ @@ -217,7 +252,7 @@ function UnstakeForm({ token: selectedToken }: UnstakeFormProps) { type: 'error', }) } - }, [borrowBank, stakeBank, publicKey, inputAmount]) + }, [ipAllowed, stakeBank, borrowBank, publicKey, inputAmount, leverage]) const maxWithdraw = group && mangoAccount && stakeBank @@ -351,6 +386,27 @@ function UnstakeForm({ token: selectedToken }: UnstakeFormProps) { /> +
+

+ Staked Amount with borrow +

+ + + +
+
+

Leverage

+ + + x + +

USDC borrowed

{borrowBank ? ( diff --git a/utils/transactions.ts b/utils/transactions.ts index 6ddd8c6..423ef70 100644 --- a/utils/transactions.ts +++ b/utils/transactions.ts @@ -14,6 +14,7 @@ import { createAssociatedTokenAccountIdempotentInstruction, getAssociatedTokenAddress, toNative, + toNativeI80F48, toUiDecimals, } from '@blockworks-foundation/mango-v4' import { TOKEN_PROGRAM_ID } from '@solana/spl-governance' @@ -36,6 +37,7 @@ import { } from '@solana/web3.js' import { floorToDecimal } from './numbers' import { BOOST_ACCOUNT_PREFIX } from './constants' +import { notify } from './notifications' export const withdrawAndClose = async ( client: MangoClient, @@ -111,6 +113,7 @@ export const unstakeAndSwap = async ( group: Group, mangoAccount: MangoAccount, stakeMintPk: PublicKey, + amountToRepay?: number, ): Promise => { console.log('unstake and swap') @@ -123,15 +126,27 @@ export const unstakeAndSwap = async ( throw Error('Unable to find borrow bank or stake bank or mango account') } const borrowed = mangoAccount.getTokenBalance(borrowBank) - console.log(borrowed) + let swapAlts: AddressLookupTableAccount[] = [] if (borrowed.toNumber() < 0) { + const toRepay = Math.ceil( + (amountToRepay + ? toNativeI80F48(amountToRepay, stakeBank.mintDecimals).mul( + stakeBank.getAssetPrice(), + ) + : borrowed.abs() + ) + .add(I80F48.fromNumber(100)) + .toNumber(), + ) + console.log('borrowedSol amount: ', borrowed.toNumber()) + console.log('borrow needed to repay for withdraw', toRepay) const { bestRoute: selectedRoute } = await fetchJupiterRoutes( stakeMintPk.toString(), borrowBank.mint.toString(), - Math.ceil(borrowed.abs().add(I80F48.fromNumber(100)).toNumber()), + toRepay, 500, 'ExactOut', ) @@ -749,12 +764,18 @@ const fetchJupiterRoutes = async ( `https://quote-api.jup.ag/v6/quote?${paramsString}`, ) const res = await response.json() - + if (res.error) { + throw res.error + } return { bestRoute: res as RouteInfo | null, } } catch (e) { console.log(e, 'Error finding jupiter route') + notify({ + title: `Error finding jupiter route ${e}`, + type: 'info', + }) return { bestRoute: null, }