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.
Private Transfers
This guide covers sending tokens privately between privacy addresses.
Basic Transfer
try {
val result = withContext(Dispatchers.IO) {
sdk.send(
tokenAddress = "0x...token-address",
amount = "1000000000000000000", // 1 token
recipientPrivacyAddress = "0x04..." // 194-char privacy address
)
}
println("Transaction hash: ${result.txHash}")
} catch (e: SDKError) {
println("Transfer failed: $e")
}
Transfer Parameters
| Parameter | Type | Required | Description |
|---|
tokenAddress | String | Yes | Token contract address |
amount | String | Yes | Amount in wei (smallest unit) |
recipientPrivacyAddress | String | Yes | Recipient’s 194-character privacy address |
Transfer Result
data class TransferResult(
val txHash: String, // Transaction hash
val fee: String // Fee paid (in wei)
)
Privacy Address Validation
Always validate privacy addresses before sending:
val recipientAddress = "0x04..."
require(sdk.isValidPrivacyAddress(recipientAddress)) { "Invalid privacy address" }
val result = withContext(Dispatchers.IO) {
sdk.send(
tokenAddress = "0x...",
amount = "1000000000000000000",
recipientPrivacyAddress = recipientAddress
)
}
Looking Up Privacy Addresses
If you have a user’s MPK or Ethereum address, you can look up their privacy address:
val identity = withContext(Dispatchers.IO) {
sdk.resolveIdentity(identifier = "0x...ethereum-address")
}
println("Privacy address: ${identity.privacyAddress}")
// Now send to their privacy address
val result = withContext(Dispatchers.IO) {
sdk.send(
tokenAddress = "0x...",
amount = "1000000000000000000",
recipientPrivacyAddress = identity.privacyAddress
)
}
Checking Balance Before Transfer
suspend fun safeTransfer(
tokenAddress: String,
amount: String,
recipient: String
): TransferResult {
val balance = withContext(Dispatchers.IO) {
sdk.getBalance(tokenAddress = tokenAddress)
}
val shielded = balance.shieldedBalance.toBigInteger()
val requested = amount.toBigInteger()
require(requested <= shielded) {
"Insufficient balance. Have: ${balance.shieldedBalance}, Need: $amount"
}
return withContext(Dispatchers.IO) {
sdk.send(
tokenAddress = tokenAddress,
amount = amount,
recipientPrivacyAddress = recipient
)
}
}
Transfer Privacy
Private transfers provide:
- Sender Privacy: Your wallet address is not linked to the transaction
- Recipient Privacy: The recipient’s wallet address is not revealed
- Amount Privacy: The transfer amount is encrypted
- Relationship Privacy: No public link between sender and recipient
Only the sender and recipient can see the transfer details.
Error Handling
try {
val result = withContext(Dispatchers.IO) {
sdk.send(
tokenAddress = tokenAddress,
amount = amount,
recipientPrivacyAddress = recipient
)
}
} catch (e: SDKError) {
when (e) {
is SDKError.InsufficientBalance ->
println("Not enough shielded balance")
is SDKError.InvalidAddress ->
println("Invalid privacy address")
is SDKError.InvalidAmount ->
println("Invalid amount")
is SDKError.WalletError ->
println("Wallet error: ${e.message}")
is SDKError.NetworkError ->
println("Network error: ${e.message}")
is SDKError.TransferError ->
println("Transfer error [${e.code}]: ${e.message}")
else ->
println("Transfer error: $e")
}
}
Best Practices
fun validateTransfer(
tokenAddress: String,
amount: String,
recipient: String
) {
require(sdk.isValidAddress(tokenAddress)) { "Invalid token address" }
require(sdk.isValidPrivacyAddress(recipient)) { "Invalid privacy address" }
val value = amount.toBigIntegerOrNull()
requireNotNull(value) { "Invalid amount format" }
require(value > BigInteger.ZERO) { "Amount must be positive" }
}
2. Confirm Large Transfers
suspend fun transferWithConfirmation(
tokenAddress: String,
amount: String,
recipient: String,
onConfirm: suspend (String) -> Boolean
): TransferResult {
val formatted = sdk.formatAmount(amount, decimals = 18u)
val confirmed = onConfirm(
"Send $formatted tokens to ${recipient.take(10)}...?"
)
require(confirmed) { "Transfer cancelled by user" }
return withContext(Dispatchers.IO) {
sdk.send(
tokenAddress = tokenAddress,
amount = amount,
recipientPrivacyAddress = recipient
)
}
}
3. Handle Network Delays
suspend fun transferWithRetry(
tokenAddress: String,
amount: String,
recipient: String,
maxRetries: Int = 3
): TransferResult {
for (attempt in 1..maxRetries) {
try {
return withContext(Dispatchers.IO) {
sdk.send(
tokenAddress = tokenAddress,
amount = amount,
recipientPrivacyAddress = recipient
)
}
} catch (e: SDKError.NetworkError) {
if (attempt == maxRetries) throw e
delay(2000L * attempt)
}
}
throw SDKError.NetworkError("Max retries exceeded")
}
Next Steps