> ## 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 React Native SDK

# Multi-Chain

This guide covers using `ChainContextHandle` to operate on multiple blockchains from a single React Native SDK instance.

<Info>
  For an overview of multi-chain concepts, see [Multi-Chain Concepts](/sdk/concepts/multi-chain).
</Info>

## Setup

Initialize the parent SDK against your primary chain, then open a chain context for each additional chain:

```typescript theme={null}
import {
  PrivacyBoost,
  PrivacyBoostConfig,
  ChainContextConfig,
} from '@sunnyside-io/privacy-boost-react-native';

const sdk = new PrivacyBoost(
  PrivacyBoostConfig.create({
    serverUrl: 'https://op.example.com',
    appId: 'my-app',
    // chainId / shieldContractAddress / wethContractAddress
    // are discovered from the server when omitted.
    chainId: undefined,
    shieldContractAddress: undefined,
    wethContractAddress: undefined,
    teePublicKey: undefined,
    persistenceStorage: undefined,
    persistenceUnlock: undefined,
  }),
);

// After authenticating the parent SDK once, open per-chain contexts.
const ethereum = sdk.createChainContext({
  serverUrl: 'https://eth.example.com',
  chainId: 1n,
  shieldContractAddress: undefined,
  wethContractAddress: undefined,
  rpcUrl: undefined,
  teePublicKey: undefined,
  timeoutMs: 30_000n,
});

const base = sdk.createChainContext({
  serverUrl: 'https://base.example.com',
  chainId: 8453n,
  shieldContractAddress: undefined,
  wethContractAddress: undefined,
  rpcUrl: undefined,
  teePublicKey: undefined,
  timeoutMs: 30_000n,
});
```

`ChainContextConfig.chainId` is a `bigint` and is required. Pass `undefined` for the optional fields to let the SDK discover them from the server.

## Authentication

Each chain context needs to authenticate before it can operate. Authentication shares your privacy keys from the parent SDK but obtains a chain-specific JWT and registration:

```typescript theme={null}
// Authenticate the parent SDK once — establishes identity keys.
await sdk.authenticate(walletDelegate, undefined, undefined);

// Authenticate each chain context with the same wallet.
const ethLogin = await ethereum.authenticate(walletDelegate);
const baseLogin = await base.authenticate(walletDelegate);

console.log('Ethereum chain id:', ethereum.chainId());
console.log('Ethereum authenticated:', ethereum.isAuthenticated());
console.log('Ethereum registered:', ethereum.isRegistered());
```

`ChainContextHandle.authenticate()` only takes a `WalletDelegate` — `keySource` and `tokenProvider` come from the parent SDK.

## Operations

Once authenticated, a `ChainContextHandle` exposes the same per-chain operations as the parent SDK:

### Deposits

```typescript theme={null}
const amount = sdk.parseAmount('1.0', 18);
const result = await ethereum.shield(
  '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', // WETH on Ethereum
  amount,
);
console.log('Ethereum shield tx:', result.txHash);
```

### Private Transfers

```typescript theme={null}
const identity = await ethereum.resolveIdentity?.('0x1234...abcd');
// resolveIdentity is on the parent SDK; ChainContextHandle inherits identity.
const recipient = sdk.resolveIdentity('0x1234...abcd');

const transfer = await base.send(
  '0x...token-on-base',
  sdk.parseAmount('0.5', 18),
  recipient.privacyAddress,
);
console.log('Base transfer tx:', transfer.txHash);
```

### Withdrawals

```typescript theme={null}
await ethereum.unshield(
  '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
  sdk.parseAmount('0.25', 18),
  '0x...destination',
);
```

### Balances

```typescript theme={null}
const ethBalance = await ethereum.getBalance(
  '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
);
const baseBalance = await base.getBalance('0x...token-on-base');

console.log('Ethereum shielded:', ethBalance.shieldedBalance);
console.log('Base shielded:', baseBalance.shieldedBalance);
```

### Status polling and history

```typescript theme={null}
const status = await ethereum.getShieldStatus(result.requestId);
const history = await base.getTransactionHistory(undefined, 20, undefined);
const notes = await ethereum.getUnspentNotes(undefined);
```

## Cross-Chain Patterns

### Parallel Operations

Chain contexts are independent — run operations concurrently:

```typescript theme={null}
const [ethResult, baseResult] = await Promise.all([
  ethereum.shield('0x...', sdk.parseAmount('1.0', 18)),
  base.shield('0x...', sdk.parseAmount('2.0', 18)),
]);
```

### Multi-Chain Balance Aggregation

```typescript theme={null}
import type { ChainContextHandle } from '@sunnyside-io/privacy-boost-react-native';

async function totalShielded(
  chains: { ctx: ChainContextHandle; token: string }[],
): Promise<bigint> {
  const balances = await Promise.all(
    chains.map(({ ctx, token }) => ctx.getBalance(token)),
  );
  return balances.reduce(
    (sum, b) => sum + BigInt(b.shieldedBalance),
    0n,
  );
}

const total = await totalShielded([
  { ctx: ethereum, token: '0x...' },
  { ctx: base, token: '0x...' },
]);
```

### Chain Selection

```typescript theme={null}
const chains = new Map<string, ChainContextHandle>([
  ['ethereum', ethereum],
  ['base', base],
]);

function getChain(name: string): ChainContextHandle {
  const ctx = chains.get(name);
  if (!ctx) throw new Error(`Unknown chain: ${name}`);
  return ctx;
}

await getChain('ethereum').shield('0x...', sdk.parseAmount('1.0', 18));
```

### React Hook Pattern

```tsx theme={null}
import { useEffect, useRef } from 'react';
import {
  PrivacyBoost,
  ChainContextHandle,
  ChainContextConfig,
} from '@sunnyside-io/privacy-boost-react-native';

function useChainContext(
  sdk: PrivacyBoost,
  config: ChainContextConfig,
): ChainContextHandle {
  const ref = useRef<ChainContextHandle | null>(null);
  if (ref.current === null) {
    ref.current = sdk.createChainContext(config);
  }
  useEffect(() => {
    return () => {
      ref.current?.clearSession();
    };
  }, []);
  return ref.current;
}
```

## Cleanup

Each chain context can drop its JWT independently while keeping the parent SDK identity intact:

```typescript theme={null}
ethereum.clearSession();   // drop just Ethereum's JWT
sdk.clearSession();        // drop the parent JWT (does not clear contexts)
sdk.logout();              // end the whole session and clear identity
```

## Next Steps

* [Deposits Guide](./deposits) — detailed shield operations
* [Withdrawals Guide](./withdrawals) — withdrawal operations
* [Transfers Guide](./transfers) — private transfers
* [Multi-Chain Concepts](/sdk/concepts/multi-chain) — architecture overview
