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

# Deposits

# Deposits

This guide covers depositing tokens from your wallet into your private balance.

## Basic Deposit

```swift theme={null}
do {
    let result = try await sdk.shield(
        tokenAddress: "0x...token-address",
        amount: "1000000000000000000" // 1 token (18 decimals)
    )
    print("Transaction hash: \(result.txHash)")
    print("Commitment: \(result.commitment)")
} catch {
    print("Deposit failed: \(error)")
}
```

## Deposit Parameters

| Parameter      | Type     | Required | Description                   |
| -------------- | -------- | -------- | ----------------------------- |
| `tokenAddress` | `String` | Yes      | ERC-20 token contract address |
| `amount`       | `String` | Yes      | Amount in wei (smallest unit) |

## Deposit Steps

When a deposit is submitted, the SDK executes these steps in order:

| Step        | Description                                     |
| ----------- | ----------------------------------------------- |
| Wrapping    | Wrapping ETH to WETH (if depositing ETH)        |
| Approving   | Approving token spending on the shield contract |
| Shielding   | Executing the deposit transaction               |
| Registering | Registering the deposit with the indexer        |
| Compliance  | Waiting for compliance verification             |

## Deposit Result

```swift theme={null}
struct ShieldResult {
    let txHash: String      // Main deposit transaction hash
    let commitment: String  // Note commitment
    let fee: String         // Fee paid (in wei)
}
```

## Depositing ETH

To deposit native ETH, use the zero address. The SDK automatically wraps ETH to WETH:

```swift theme={null}
let ethAddress = "0x0000000000000000000000000000000000000000"

do {
    let result = try await sdk.shield(
        tokenAddress: ethAddress,
        amount: "1000000000000000000" // 1 ETH
    )
    print("Deposit tx: \(result.txHash)")
} catch {
    print("ETH deposit failed: \(error)")
}
```

The SDK automatically:

1. Wraps ETH to WETH
2. Approves WETH spending
3. Deposits WETH to the shield contract

## Parsing Amounts

Use helper functions to convert between human-readable and wei formats:

```swift theme={null}
// Parse human-readable amount to wei string
let weiAmount = try sdk.parseAmount("1.5", decimals: 18)
// Returns: "1500000000000000000"

// Format wei string to human-readable
let formatted = try sdk.formatAmount("1500000000000000000", decimals: 18)
// Returns: "1.5"

// For USDC (6 decimals)
let usdcWei = try sdk.parseAmount("100.0", decimals: 6)
// Returns: "100000000"
```

## Error Handling

```swift theme={null}
do {
    let result = try await sdk.shield(
        tokenAddress: tokenAddress,
        amount: amount
    )
} catch SDKError.insufficientBalance {
    print("Not enough tokens in wallet")
} catch SDKError.invalidAmount {
    print("Invalid amount format")
} catch SDKError.walletError(let message) {
    print("Wallet error: \(message)")
} catch SDKError.signatureRejected {
    print("User rejected the transaction")
} catch SDKError.networkError(let message) {
    print("Network error: \(message)")
} catch {
    print("Deposit error: \(error)")
}
```

## Best Practices

### 1. Validate Amounts Before Depositing

```swift theme={null}
func validateDepositAmount(_ amount: String, walletBalance: String) throws {
    guard let amountValue = UInt64(amount), amountValue > 0 else {
        throw SDKError.invalidAmount
    }
    guard let balanceValue = UInt64(walletBalance),
          amountValue <= balanceValue else {
        throw SDKError.insufficientBalance(message: "Insufficient wallet balance")
    }
}
```

### 2. Refresh Balance After Deposit

```swift theme={null}
let result = try await sdk.shield(
    tokenAddress: tokenAddress,
    amount: amount
)

// Refresh balance to reflect the deposit
let updatedBalance = try await sdk.getBalance(tokenAddress: tokenAddress)
print("New shielded balance: \(updatedBalance.shieldedBalance)")
```

### 3. Handle Long Operations

Deposits involve multiple on-chain transactions and may take time. Show appropriate loading states in your UI and avoid blocking the main thread.

## Relayed Deposits (build calldata, relay yourself)

If your users don't submit transactions directly — they hold funds at addresses
you relay for (a gasless relayer, an EIP-7702 session key, a custom pipeline) —
build the deposit calldata without submitting it, relay it through your own
infrastructure, then finalize from the mined receipt.

```swift theme={null}
// 1. Build the calldata (nothing submitted)
let prepared = try await sdk.prepareShield(
    tokenAddress: "0x...",
    amount: "1000000000000000000",
    recipient: nil  // pass a privacy address to shield to someone else
)

// prepared.wrap / prepared.approve / prepared.shield are Call { to, value, data }
// values — relay them in order (wrap?, approve?, shield).
let calls = [prepared.wrap, prepared.approve, prepared.shield].compactMap { $0 }
let receipt = try await myRelayer.submit(calls)

// 2. Finalize from the mined receipt to recover the request id
let result = try finalizeShield(
    receipt: receipt,
    shieldContract: prepared.finalize.shieldContract,
    commitment: prepared.commitment
)
print("Request ID: \(result.requestId)")
```

Each `Call` is `{ to, value, data }`, so the array drops directly into an
EIP-5792 / Porto `wallet_prepareCalls` bundle.

### Server-side (no session)

A backend that holds only a recipient's privacy address can build a deposit on
their behalf with the top-level `buildShieldPayload` — no signed-in session and
no private keys:

```swift theme={null}
let prepared = try buildShieldPayload(
    tokenAddress: "0x...",
    amount: "1000000000000000000",
    recipient: userPrivacyAddress,
    tokenId: tokenId,                       // from the token catalog
    shieldContractAddress: shieldContractAddress,
    wethContractAddress: nil,               // required only for native ETH
    teePublicKey: teePublicKey,
    minShieldAmount: minShieldAmount,       // optional: reject below the per-token minimum
    emitApprove: true
)
```

The note's owner is bound cryptographically to the recipient's privacy address,
so only they can spend it; the ephemeral sender used to encrypt the deposit is
generated and discarded internally.

## Next Steps

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