> ## 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.

# Transfers

# Private Transfers

This guide covers sending tokens privately between privacy addresses.

## Basic Transfer

```kotlin theme={null}
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

```kotlin theme={null}
data class TransferResult(
    val txHash: String,  // Transaction hash
    val fee: String      // Fee paid (in wei)
)
```

## Privacy Address Validation

Always validate privacy addresses before sending:

```kotlin theme={null}
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:

```kotlin theme={null}
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

```kotlin theme={null}
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

```kotlin theme={null}
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

### 1. Validate All Inputs

```kotlin theme={null}
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

```kotlin theme={null}
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

```kotlin theme={null}
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

* [Deposits Guide](./deposits)
* [Withdrawals Guide](./withdrawals)
* [Balances Guide](./balances)
* [Error Handling](./error-handling)
