Withdraw
Withdrawals unshield tokens from the privacy pool back to a regular EVM address.
Overview
Input UTXO → zk-SNARK proof → ERC-20 tokens released to recipientA withdrawal:
- Selects an input UTXO
- Generates a zk-SNARK proof
- Submits the proof to a relayer
- The relayer verifies, posts the transaction, and the contract releases tokens
Basic Usage
ts
// Derive owner key pair
const ownerKeyPair = sdk.keys.deriveKeyPair(seed, nonce);
// Prepare withdrawal
const prepared = await sdk.ops.prepareWithdraw({
chainId: 11155111,
assetId: 'my-token-id',
amount: 500000n,
recipient: '0x1234...abcd', // EVM address to receive tokens
ownerKeyPair,
publicClient,
});
// Submit to relayer
const result = await sdk.ops.submitRelayerRequest({
prepared,
publicClient,
});
const txHash = await result.waitRelayerTxHash;
const receipt = await result.transactionReceipt;Gas Drop
Request native ETH along with the withdrawal (for gas on the receiving chain):
ts
const prepared = await sdk.ops.prepareWithdraw({
chainId: 11155111,
assetId: 'my-token-id',
amount: 500000n,
recipient: '0x1234...abcd',
ownerKeyPair,
publicClient,
gasDropValue: 10000000000000000n, // 0.01 ETH
});Fee Estimation
ts
const estimate = await sdk.planner.estimate({
chainId: 11155111,
assetId: 'my-token-id',
action: 'withdraw',
amount: 500000n,
});
console.log('Relayer fee:', estimate.feeSummary.relayerFeeTotal);
console.log('Protocol fee:', estimate.feeSummary.protocolFeeTotal);Max Withdrawable
ts
const max = await sdk.planner.estimateMax({
chainId: 11155111,
assetId: 'my-token-id',
action: 'withdraw',
});
console.log('Max output:', max.maxSummary.outputAmount);After Withdrawal
After the withdrawal transaction confirms:
- The UTXO is marked as spent (nullifier published on-chain)
- ERC-20 tokens are transferred to the recipient address
- Run
sdk.sync.syncOnce()to update local UTXO state - The wallet balance decreases by the withdrawn amount + fees