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

# Multi-Chain

> Operate across multiple blockchains with the iOS SDK

# Multi-Chain

The iOS SDK currently does not expose a native chain-context API — `PrivacyBoost` is initialized against a single chain via its config. Multi-chain support exists in the underlying Rust core and is exposed today on the [TypeScript](/sdk/typescript/guides/multi-chain), [React Native](/sdk/react-native/guides/multi-chain), and Web/WASM SDKs.

<Info>
  For an architectural overview of how multi-chain identity works, see [Multi-Chain Concepts](/sdk/concepts/multi-chain). The same identity keys and privacy address apply across chains regardless of which SDK creates them.
</Info>

## Single-Chain Setup

Pick a chain at SDK init time:

```swift theme={null}
let config = PrivacyBoostConfig(
    serverUrl: "https://op.example.com",
    chainId: 10,                       // Optimism
    shieldContractAddress: nil,        // discovered from server
    wethContractAddress: "0x4200000000000000000000000000000000000006",
    teePublicKey: nil,
    appId: "my-app",
    persistenceStorage: nil,
    persistenceUnlock: nil
)
let sdk = try PrivacyBoost(config: config)
```

Switching chains is a config swap — tear down the current SDK and instantiate a new one with the new server URL and `chainId`.

## Multiple SDK Instances (Workaround)

If you need to operate on more than one chain in a single app session, you can instantiate one `PrivacyBoost` per chain. Each instance keeps its own JWT and chain state, but you must authenticate each one separately.

```swift theme={null}
let optimism = try PrivacyBoost(config: PrivacyBoostConfig(
    serverUrl: "https://op.example.com",
    chainId: 10,
    shieldContractAddress: nil,
    wethContractAddress: "0x4200000000000000000000000000000000000006",
    teePublicKey: nil,
    appId: "my-app",
    persistenceStorage: nil,
    persistenceUnlock: nil
))

let ethereum = try PrivacyBoost(config: PrivacyBoostConfig(
    serverUrl: "https://eth.example.com",
    chainId: 1,
    shieldContractAddress: nil,
    wethContractAddress: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
    teePublicKey: nil,
    appId: "my-app",
    persistenceStorage: nil,
    persistenceUnlock: nil
))

// Authenticate each instance independently with the same wallet.
_ = try await optimism.authenticate(
    wallet: walletDelegate,
    keySource: .walletDerived,
    tokenProvider: nil
)
_ = try await ethereum.authenticate(
    wallet: walletDelegate,
    keySource: .walletDerived,
    tokenProvider: nil
)
```

### Caveats

* **Persistence collisions.** Both instances will try to read/write the same Keychain entries if you pass `persistenceStorage`/`persistenceUnlock`. Either leave persistence off (`nil`) on the secondary instances, or use distinct `appId`s — but distinct app IDs mean distinct identities, which defeats the multi-chain story.
* **Re-derivation per chain.** Each instance derives keys via the wallet signature and re-issues a JWT, so the user signs once per chain.
* **No cross-instance state.** Pending transactions, balances, and history are siloed per instance — your app code must aggregate.
* **No proper resource sharing.** The multi-chain `ChainContext` API on TS/RN/Web shares one identity and only multiplexes the chain JWT; with multiple iOS SDK instances you pay the full proving / state init cost on each one.

This pattern is suitable for showing balances or running occasional cross-chain operations. For production multi-chain UX, prefer the chain-context API on the platforms that expose it, or wait for native iOS support.

## Operating per Chain

Once authenticated, the API surface is identical across instances:

```swift theme={null}
let amount = try optimism.parseAmount("1.0", decimals: 18)
let opShield = try await optimism.shield(
    tokenAddress: "0x4200000000000000000000000000000000000006",
    amount: amount
)

let ethShield = try await ethereum.shield(
    tokenAddress: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
    amount: try ethereum.parseAmount("0.5", decimals: 18)
)
```

### Parallel Operations

Use Swift Concurrency to fan out:

```swift theme={null}
async let opTask  = optimism.shield(tokenAddress: "0x...", amount: opAmount)
async let ethTask = ethereum.shield(tokenAddress: "0x...", amount: ethAmount)

let (opResult, ethResult) = try await (opTask, ethTask)
```

### Aggregating Balances

```swift theme={null}
struct ChainEntry {
    let sdk: PrivacyBoost
    let token: String
}

func totalShielded(across chains: [ChainEntry]) async throws -> String {
    try await withThrowingTaskGroup(of: String.self) { group in
        for chain in chains {
            group.addTask {
                let bal = try await chain.sdk.getBalance(tokenAddress: chain.token)
                return bal.shieldedBalance
            }
        }
        var sum: UInt64 = 0
        for try await wei in group {
            sum &+= UInt64(wei) ?? 0
        }
        return String(sum)
    }
}
```

For amounts that exceed `UInt64`, use `BigInt` from a library such as [BigInt](https://github.com/attaswift/BigInt).

## Roadmap

A native `ChainContextHandle` for iOS — mirroring the React Native and TypeScript surfaces — is planned. When available, it will replace the multi-instance workaround with a single SDK instance that multiplexes JWTs and shares identity keys.

## Next Steps

* [Deposits Guide](./deposits)
* [Withdrawals Guide](./withdrawals)
* [Transfers Guide](./transfers)
* [Multi-Chain Concepts](/sdk/concepts/multi-chain)
