Documentation Index
Fetch the complete documentation index at: https://docs.privacyboost.io/llms.txt
Use this file to discover all available pages before exploring further.
Withdrawals
This guide covers withdrawing tokens from your private balance to any public Ethereum address.
Basic Withdrawal
do {
let result = try await sdk.unshield(
tokenAddress: "0x...token-address",
amount: "1000000000000000000", // 1 token
recipient: "0x...recipient-address"
)
print("Transaction hash: \(result.txHash)")
} catch {
print("Withdrawal failed: \(error)")
}
Withdrawal Parameters
| Parameter | Type | Required | Description |
|---|
tokenAddress | String | Yes | Token contract address |
amount | String | Yes | Amount in wei (smallest unit) |
recipient | String | Yes | Destination Ethereum address |
Withdrawal Steps
Withdrawals involve zero-knowledge proof generation, which can take up to 30 seconds:
| Step | Description |
|---|
| Preparing | Preparing withdrawal data |
| Signing | Signing transaction data |
| Proving | Generating zero-knowledge proof |
| Unshielding | Executing withdrawal transaction |
| Unwrapping | Unwrapping WETH to ETH (if applicable) |
Withdrawal Result
struct UnshieldResult {
let txHash: String // Main withdrawal transaction hash
let fee: String // Fee paid (in wei)
}
Withdraw to Self
Withdraw to your connected wallet address:
let myAddress = sdk.getWalletAddress()!
let result = try await sdk.unshield(
tokenAddress: "0x...",
amount: "1000000000000000000",
recipient: myAddress
)
Withdraw to Any Address
You can withdraw to any valid Ethereum address:
let recipientAddress = "0x..."
// Validate address first
guard sdk.isValidAddress(recipientAddress) else {
print("Invalid recipient address")
return
}
let result = try await sdk.unshield(
tokenAddress: "0x...",
amount: "1000000000000000000",
recipient: recipientAddress
)
Partial Withdrawals
Withdraw any amount up to your shielded balance:
// Check available balance first
let balance = try await sdk.getBalance(tokenAddress: tokenAddress)
guard let shielded = UInt64(balance.shieldedBalance),
let unshieldAmount = UInt64(amount),
unshieldAmount <= shielded else {
print("Insufficient shielded balance")
return
}
let result = try await sdk.unshield(
tokenAddress: tokenAddress,
amount: amount,
recipient: recipientAddress
)
Error Handling
do {
let result = try await sdk.unshield(
tokenAddress: tokenAddress,
amount: amount,
recipient: recipient
)
} catch SDKError.insufficientBalance {
print("Not enough shielded balance")
} catch SDKError.invalidAddress {
print("Invalid recipient address")
} catch SDKError.invalidAmount {
print("Invalid amount format")
} catch SDKError.walletError(let message) {
print("Wallet error: \(message)")
} catch SDKError.networkError(let message) {
print("Network error: \(message)")
} catch {
print("Withdrawal error: \(error)")
}
Best Practices
1. Validate Balance Before Withdrawal
func validateWithdrawal(tokenAddress: String, amount: String) async throws {
let balance = try await sdk.getBalance(tokenAddress: tokenAddress)
guard let shielded = UInt64(balance.shieldedBalance),
let requested = UInt64(amount),
requested <= shielded else {
throw SDKError.insufficientBalance
}
}
2. Validate Recipient Address
func validateRecipient(_ address: String) throws {
guard sdk.isValidAddress(address) else {
throw SDKError.invalidAddress
}
guard address != "0x0000000000000000000000000000000000000000" else {
throw SDKError.invalidAddress
}
}
3. Handle Long Operations
Withdrawals include zero-knowledge proof generation which can take up to 30 seconds. Show a loading indicator and inform users about the expected wait time.
// Show estimated time in your UI
statusLabel.text = "Generating proof... This may take up to 30 seconds."
let result = try await sdk.unshield(
tokenAddress: tokenAddress,
amount: amount,
recipient: recipient
)
statusLabel.text = "Withdrawal complete!"
Next Steps