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
try {
val result = withContext(Dispatchers.IO) {
sdk.unshield(
tokenAddress = "0x...token-address",
amount = "1000000000000000000", // 1 token
recipient = "0x...recipient-address"
)
}
println("Transaction hash: ${result.txHash}")
} catch (e: SDKError) {
println("Withdrawal failed: $e")
}
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
data class UnshieldResult(
val txHash: String, // Main withdrawal transaction hash
val fee: String // Fee paid (in wei)
)
Withdraw to Self
Withdraw to your connected wallet address:
val myAddress = sdk.getWalletAddress()!!
val result = withContext(Dispatchers.IO) {
sdk.unshield(
tokenAddress = "0x...",
amount = "1000000000000000000",
recipient = myAddress
)
}
Withdraw to Any Address
You can withdraw to any valid Ethereum address:
val recipientAddress = "0x..."
// Validate address first
require(sdk.isValidAddress(recipientAddress)) { "Invalid recipient address" }
val result = withContext(Dispatchers.IO) {
sdk.unshield(
tokenAddress = "0x...",
amount = "1000000000000000000",
recipient = recipientAddress
)
}
Partial Withdrawals
Withdraw any amount up to your shielded balance:
// Check available balance first
val balance = withContext(Dispatchers.IO) {
sdk.getBalance(tokenAddress = tokenAddress)
}
val shielded = balance.shieldedBalance.toBigInteger()
val unshieldAmount = amount.toBigInteger()
require(unshieldAmount <= shielded) { "Insufficient shielded balance" }
val result = withContext(Dispatchers.IO) {
sdk.unshield(
tokenAddress = tokenAddress,
amount = amount,
recipient = recipientAddress
)
}
Error Handling
try {
val result = withContext(Dispatchers.IO) {
sdk.unshield(
tokenAddress = tokenAddress,
amount = amount,
recipient = recipient
)
}
} catch (e: SDKError) {
when (e) {
is SDKError.InsufficientBalance ->
println("Not enough shielded balance")
is SDKError.InvalidAddress ->
println("Invalid recipient address")
is SDKError.InvalidAmount ->
println("Invalid amount format")
is SDKError.WalletError ->
println("Wallet error: ${e.message}")
is SDKError.NetworkError ->
println("Network error: ${e.message}")
else ->
println("Withdrawal error: $e")
}
}
Best Practices
1. Validate Balance Before Withdrawal
suspend fun validateWithdrawal(tokenAddress: String, amount: String) {
val balance = withContext(Dispatchers.IO) {
sdk.getBalance(tokenAddress = tokenAddress)
}
val shielded = balance.shieldedBalance.toBigInteger()
val requested = amount.toBigInteger()
require(requested <= shielded) {
"Insufficient balance. Available: ${balance.shieldedBalance}, Requested: $amount"
}
}
2. Validate Recipient Address
fun validateRecipient(address: String) {
require(sdk.isValidAddress(address)) { "Invalid Ethereum address" }
require(address != "0x0000000000000000000000000000000000000000") {
"Cannot withdraw to zero address"
}
}
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.
// In a ViewModel
viewModelScope.launch {
_state.value = WithdrawState.Loading("Generating proof... This may take up to 30 seconds.")
try {
val result = withContext(Dispatchers.IO) {
sdk.unshield(
tokenAddress = tokenAddress,
amount = amount,
recipient = recipient
)
}
_state.value = WithdrawState.Success(result.txHash)
} catch (e: SDKError) {
_state.value = WithdrawState.Error(e)
}
}
Next Steps