Skip to main content

Unstake

This guide outlines the implementation approach for unstaking user deposits.

How to unstake from a StakeWise V3 vault

To unstake (withdraw) user assets from a vault, fetch the current stake balance and the maximum withdrawable amount, check whether any osToken must be burned first via getBurnAmountForUnstake, then call sdk.vault.withdraw. The withdrawal lands in the vault's exit queue, which you can read with sdk.vault.getExitQueuePositions after the subgraph has indexed the transaction.

import { BrowserProvider, parseEther, formatEther } from 'ethers'
import { StakeWiseSDK, Network } from '@stakewise/v3-sdk'

const eip1193Provider = window.ethereum

const browserProvider = new BrowserProvider(eip1193Provider, {
chainId: Network.Mainnet,
name: 'mainnet',
})

const sdk = new StakeWiseSDK({
network: Network.Mainnet,
provider: browserProvider,
})

type Input = {
amount: string
userAddress: string
vaultAddress: string
}

const unstake = async (values: Input) => {
const { amount, userAddress, vaultAddress } = values

try {
const assets = parseEther(amount)

const [ stake, maxWithdrawAssets, burnAmount ] = await Promise.all([
sdk.vault.getStakeBalance({ userAddress, vaultAddress }),
sdk.vault.getMaxWithdrawAmount({ userAddress, vaultAddress }),
sdk.osToken.getBurnAmountForUnstake({ userAddress, vaultAddress }),
])

if (!stake.assets) {
throw new Error('You have no tokens to unstake.')
}

if (assets > maxWithdrawAssets) {
throw new Error('You do not have enough tokens to withdraw.')
}

if (burnAmount) {
const value = formatEther(burnAmount)

console.warn(`To withdraw your tokens in full, you must first burn an ${value} osToken.`)
}

const hash = await sdk.vault.withdraw({
vaultAddress,
userAddress,
assets,
})

await sdk.provider.waitForTransaction(hash)

await sdk.utils.waitForSubgraph({ hash })

const positions = await sdk.vault.getExitQueuePositions({ userAddress, vaultAddress })

// After unstaking, the withdrawal of funds will be added to the exit queue, which can be obtained using the SDK.
console.log('positions:', positions)
}
catch (error) {
console.error(error)
}
}

unstake({
amount: '3.33',
userAddress: 'USER_ADDRESS',
vaultAddress: 'VAULT_ADDRESS',
})