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

> Use a single SDK instance to operate across multiple blockchains

# Multi-Chain

Privacy Boost supports operating across multiple EVM-compatible blockchains from a single SDK instance. Your cryptographic identity (keys) is shared across all chains, while each chain maintains its own authentication state, balances, and transaction history.

## How It Works

The multi-chain architecture has two layers:

1. **Parent SDK** (`PrivacyBoost`) — initialized once with your primary chain. Holds your identity keys.
2. **Chain clients** (`ChainClient`) — created per chain via `sdk.forChain()`. Each has its own server connection, JWT, and chain state, but shares the parent's identity.

```
PrivacyBoost (identity keys, primary chain)
├── ChainClient (Optimism) — own auth, balances, transactions
├── ChainClient (Ethereum) — own auth, balances, transactions
└── ChainClient (Base)     — own auth, balances, transactions
```

This means you authenticate once per chain, but your privacy address is consistent across all of them.

## Quick Example

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { PrivacyBoost } from '@sunnyside-io/privacy-boost';

  // Initialize SDK with your primary chain
  const sdk = await PrivacyBoost.create({
    serverUrl: 'https://op.example.com',
    appId: 'my-app',
  });

  // Create chain clients for other chains
  const ethereum = sdk.forChain({ serverUrl: 'https://eth.example.com' });
  const base = sdk.forChain({ serverUrl: 'https://base.example.com' });

  // Authenticate on each chain (uses shared identity keys)
  await ethereum.authenticate(walletAdapter);
  await base.authenticate(walletAdapter);

  // Operate independently per chain
  await ethereum.vault.shield({ tokenAddress: '0x...', amount: 1000n });
  await base.vault.send({ to: '0x04...', tokenAddress: '0x...', amount: 500n });
  ```

  ```tsx React theme={null}
  import { useChain } from '@sunnyside-io/privacy-boost-react';

  function MultiChainApp() {
    const ethereum = useChain({ serverUrl: 'https://eth.example.com' });
    const base = useChain({ serverUrl: 'https://base.example.com' });

    // Each chain client is independent
    const depositOnEthereum = async () => {
      await ethereum?.vault.shield({ tokenAddress: '0x...', amount: 1000n });
    };

    const sendOnBase = async () => {
      await base?.vault.send({ to: '0x04...', tokenAddress: '0x...', amount: 500n });
    };

    return (
      <div>
        <button onClick={depositOnEthereum}>Deposit on Ethereum</button>
        <button onClick={sendOnBase}>Send on Base</button>
      </div>
    );
  }
  ```
</CodeGroup>

## ChainClient Configuration

Only `serverUrl` is required. All other fields are auto-discovered from the chain's server `/api/v1/info` endpoint.

| Parameter               | Type     | Required | Description                               |
| ----------------------- | -------- | -------- | ----------------------------------------- |
| `serverUrl`             | `string` | Yes      | URL of this chain's server                |
| `chainId`               | `number` | No       | EVM chain ID (auto-discovered)            |
| `shieldContractAddress` | `string` | No       | Shield contract address (auto-discovered) |
| `wethContractAddress`   | `string` | No       | WETH contract address (for ETH wrapping)  |
| `rpcUrl`                | `string` | No       | RPC URL for on-chain reads                |
| `tokenRegistryAddress`  | `string` | No       | Token registry contract (auto-discovered) |
| `teePublicKey`          | `string` | No       | TEE public key (auto-discovered)          |

## Caching

Chain clients are cached by `serverUrl`. Calling `sdk.forChain()` with the same URL returns the same instance:

```typescript theme={null}
const a = sdk.forChain({ serverUrl: 'https://eth.example.com' });
const b = sdk.forChain({ serverUrl: 'https://eth.example.com' });
// a === b (same instance)
```

This means you can call `sdk.forChain()` freely in components or functions without worrying about creating duplicate clients.

## Per-Chain Authentication

Each chain client must be authenticated independently. The authentication uses shared identity keys from the parent SDK, but obtains a separate JWT for each chain's server.

```typescript theme={null}
const eth = sdk.forChain({ serverUrl: 'https://eth.example.com' });

// Must authenticate before using vault/transactions
await eth.authenticate(walletAdapter);

// Now you can use chain-scoped operations
console.log('Chain ID:', eth.chainId);
console.log('Authenticated:', eth.isAuthenticated);
const balance = await eth.vault.getBalance('0x...');
```

## Available Operations

A `ChainClient` provides the same core operations as the parent SDK:

| Resource       | Operations                                                             |
| -------------- | ---------------------------------------------------------------------- |
| `vault`        | `shield()`, `unshield()`, `send()`, `getBalance()`, `getAllBalances()` |
| `transactions` | Transaction history and status polling                                 |
| `audit`        | Auditor-specific operations                                            |

```typescript theme={null}
// Deposit on a specific chain
await eth.vault.shield({ tokenAddress: '0x...', amount: 1000n });

// Check balance on that chain
const balance = await eth.vault.getBalance('0x...');

// Send privately on that chain
await eth.vault.send({ to: '0x04...', tokenAddress: '0x...', amount: 500n });

// Withdraw from that chain
await eth.vault.unshield({
  tokenAddress: '0x...',
  amount: 250n,
  recipientAddress: '0x...',
});
```

## Identity Lookup

Look up a user's privacy address on a specific chain:

```typescript theme={null}
const identity = await eth.resolveIdentity('0x1234...abcd');
console.log('Privacy address:', identity.privacyAddress);
```

## Cleanup

Chain clients are disposed automatically when the parent SDK is disposed. You can also dispose individual clients:

```typescript theme={null}
// Dispose a single chain client
eth.clearSession(); // Clear JWT and pending transactions
eth.dispose();      // Release all resources

// Or dispose everything at once
sdk.dispose(); // Disposes parent + all chain clients
```

## Next Steps

<CardGroup cols={2}>
  <Card title="TypeScript Multi-Chain Guide" href="/sdk/typescript/guides/multi-chain">
    Detailed TypeScript examples and patterns
  </Card>

  <Card title="React Multi-Chain Guide" href="/sdk/react/guides/multi-chain">
    React hooks and component patterns for multi-chain
  </Card>

  <Card title="Configuration" href="/sdk/concepts/configuration">
    SDK configuration and auto-discovery
  </Card>

  <Card title="Authentication" href="/sdk/concepts/authentication">
    Authentication methods and wallet integration
  </Card>
</CardGroup>
