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

# Getting started

# Getting Started

This guide walks you through integrating the Privacy Boost React Native SDK into your app.

<Info>
  For a minimal copy-paste example, see the [React Native Quickstart](/sdk/quickstart/react-native). This guide explains each step in detail.
</Info>

## Prerequisites

* An [App ID](/sdk/concepts/app-setup) and server URL (see [Configuration](/sdk/concepts/configuration))
* A wallet integration (WalletConnect, custom, etc.)
* Familiarity with [authentication options](/sdk/concepts/authentication) (optional for development, required for production)

## Overview

The React Native SDK follows a simple flow:

1. **Initialize** - Create SDK instance with configuration
2. **Authenticate** - Connect wallet and authenticate via `WalletDelegate`
3. **Use** - Deposit, unshield, transfer tokens

## Basic Setup

### 1. Import the SDK

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

### 2. Configure the SDK

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

const config = PrivacyBoostConfig.create({
  serverUrl: 'https://optimism.sepolia.privacyboost.io',
  chainId: undefined,                   // optional; discovered from server
  shieldContractAddress: undefined,     // optional; discovered from server
  wethContractAddress: '0x4200000000000000000000000000000000000006',
  appId: 'app_abc123xyz',
  teePublicKey: undefined,              // optional; discovered from server
  persistenceStorage: undefined,        // see "Session Persistence" below
  persistenceUnlock: undefined,
});
```

`PrivacyBoostConfig.create()` validates the fields and fills in defaults. Only
`serverUrl` and `appId` are required — `chainId`, `shieldContractAddress`, and
`teePublicKey` are automatically discovered from the server if omitted.
Passing `undefined` explicitly is required for nullable fields because the
generated types declare them as required-but-nullable.

### 3. Initialize

```typescript theme={null}
try {
  const sdk = new PrivacyBoost(config);
} catch (error) {
  console.error('Failed to initialize SDK:', error);
}
```

## Connecting a Wallet

The SDK uses the `WalletDelegate` interface to interact with wallets. You must implement this interface:

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

const walletDelegate: WalletDelegate = {
  getAddress: async (): Promise<string> => {
    // Return the connected wallet address
    return '0x...';
  },

  getChainId: async (): Promise<bigint> => {
    // Return the current chain ID
    return BigInt(1);
  },

  signMessage: async (message: string): Promise<string> => {
    // Sign using EIP-191 personal_sign
    // Return signature as hex string with 0x prefix
    return '0x...';
  },

  signTypedData: async (typedDataJson: string): Promise<string> => {
    // Sign using EIP-712 eth_signTypedData_v4
    return '0x...';
  },

  sendTransaction: async (
    toAddress: string,
    value: string,
    data: string
  ): Promise<string> => {
    // Submit transaction and return hash
    return '0x...';
  },

  waitForTransactionReceipt: async (txHash: string) => {
    // Poll for the receipt. Return { txHash, status, logs }.
    // `status` is true for success. `logs` is an array of { address, topics, data }.
    return { txHash, status: true, logs: [] };
  },
};
```

You can use any React Native web3 library (such as ethers.js, viem, or WalletConnect) to implement this delegate.

Then authenticate. `authenticate()` returns a tagged union with four possible
outcomes — you must handle each:

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

try {
  // Default: wallet-derived keys. Also accepts:
  //   new KeySource.Mnemonic('twelve word seed phrase ...')
  //   new KeySource.RawSeed('0xdeadbeef...')
  const result = await sdk.authenticate(
    walletDelegate,
    new KeySource.WalletDerived(),
    undefined // optional TokenProvider for app auth
  );

  switch (result.tag) {
    case 'Authenticated':
      // Returning user.
      console.log('Privacy Address:', result.loginResult.privacyAddress);
      console.log('MPK:', result.loginResult.mpk);
      console.log('Is new user:', result.loginResult.isNewUser);
      break;

    case 'MnemonicGenerated':
      // First-time user — SDK generated a recovery phrase. Show it to the
      // user, have them confirm they've saved it, then continue:
      console.log('Save this phrase:', result.mnemonic);
      const loginResult = await sdk.proceedAfterMnemonic(undefined);
      console.log('Privacy Address:', loginResult.privacyAddress);
      break;

    case 'CredentialRequired':
      // Persistence with PIN/password/biometric/passkey unlock is configured.
      // Prompt the user for their credential, then:
      const credentialResult = await sdk.submitCredential(credential, undefined);
      console.log('Privacy Address:', credentialResult.privacyAddress);
      break;

    case 'RecoveryRequired':
      // Device storage is inconsistent — account exists but local keys are
      // missing. Prompt the user to enter their recovery mnemonic and
      // re-authenticate with KeySource.Mnemonic.
      console.log('Recovery needed:', result.challenge.reason);
      break;
  }
} catch (error) {
  console.error('Authentication failed:', error);
}
```

<Info>
  `CredentialRequired` only fires when persistence with PIN/password/biometric
  unlock is configured (see the `persistenceUnlock` field on `PrivacyBoostConfig`).
  For the simple case (no persistence), `authenticate()` returns `Authenticated`
  (returning user) or `MnemonicGenerated` (first-time user) directly.
</Info>

### App Authentication (TokenProvider)

If your backend issues app-level auth tokens, implement `TokenProvider` and
pass it to `authenticate()`:

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

const tokenProvider: TokenProvider = {
  async getToken(loginPayloadJson: string): Promise<TokenResponse> {
    const resp = await fetch('https://your-backend/auth', {
      method: 'POST',
      body: loginPayloadJson,
    });
    const { token, expiresIn } = await resp.json();
    return { token, expiresIn: BigInt(expiresIn) };
  },
};

await sdk.authenticate(walletDelegate, new KeySource.WalletDerived(), tokenProvider);
```

## Core Operations

### Check Balance

```typescript theme={null}
try {
  const balance = await sdk.getBalance('0x...');
  console.log('Shielded:', balance.shieldedBalance);
  console.log('Wallet:', balance.walletBalance);
} catch (error) {
  console.error('Failed to get balance:', error);
}
```

### Deposit Tokens

Move tokens from wallet to shielded pool:

```typescript theme={null}
try {
  const result = await sdk.shield(
    '0x...', // token address
    '1000000000000000000' // 1 token (18 decimals)
  );
  console.log('Deposit TX:', result.txHash);
  console.log('Commitment:', result.commitment);
  console.log('Request ID:', result.requestId);
  if (result.wrapTxHash) {
    console.log('Wrap TX (ETH→WETH):', result.wrapTxHash);
  }
} catch (error) {
  console.error('Deposit failed:', error);
}
```

Use `requestId` with `sdk.getShieldStatus(requestId)` to poll the shield's
finality state. `wrapTxHash` is only present when depositing native ETH (the
SDK wraps to WETH first).

### Withdraw Tokens

Move tokens from shielded pool to wallet:

```typescript theme={null}
try {
  const result = await sdk.unshield(
    '0x...', // token address
    '500000000000000000', // amount
    '0x...' // recipient address
  );
  console.log('Withdraw TX:', result.txHash);
} catch (error) {
  console.error('Withdraw failed:', error);
}
```

### Private Transfer

Send tokens privately to another user:

```typescript theme={null}
try {
  const result = await sdk.send(
    '0x...', // token address
    '250000000000000000', // amount
    '0x04...' // 194-char privacy address
  );
  console.log('Transfer TX:', result.txHash);
} catch (error) {
  console.error('Transfer failed:', error);
}
```

## Error Handling

The SDK throws `SDKError` for various failure conditions:

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

try {
  const result = await sdk.shield(tokenAddress, amount);
} catch (error) {
  // SdkError is a tagged union. Each variant is a class you can instanceof-check.
  if (SdkError.NotConnected.instanceOf(error)) {
    console.log('Wallet not connected');
  } else if (SdkError.NotAuthenticated.instanceOf(error)) {
    console.log('Not logged in');
  } else if (SdkError.InsufficientBalance.instanceOf(error)) {
    console.log('Insufficient balance');
  } else if (SdkError.InvalidAmount.instanceOf(error)) {
    console.log('Invalid amount format');
  } else if (SdkError.WalletError.instanceOf(error)) {
    console.log('Wallet error:', (error as any).inner?.message);
  } else if (SdkError.NetworkError.instanceOf(error)) {
    console.log('Network error:', (error as any).inner?.message);
  } else {
    console.log('Unknown error:', error);
  }
}
```

## Session Persistence

Save and restore sessions to avoid re-signing:

```typescript theme={null}
import AsyncStorage from '@react-native-async-storage/async-storage';

// Export session
const session = sdk.exportSession();
if (session) {
  await AsyncStorage.setItem('privacy_session', JSON.stringify(session));
}

// Import session
const stored = await AsyncStorage.getItem('privacy_session');
if (stored) {
  try {
    const session = JSON.parse(stored);
    const success = sdk.importSession(session);
    if (success) {
      console.log('Session restored');
    }
  } catch (error) {
    console.log('Session expired or invalid');
  }
}
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Deposits" href="/sdk/react-native/guides/deposits">
    Deposit tokens into the shielded pool
  </Card>

  <Card title="Withdrawals" href="/sdk/react-native/guides/withdrawals">
    Withdraw tokens from the shielded pool
  </Card>

  <Card title="Private Transfers" href="/sdk/react-native/guides/transfers">
    Send tokens privately between users
  </Card>

  <Card title="Balances" href="/sdk/react-native/guides/balances">
    Query and display token balances
  </Card>

  <Card title="Transaction History" href="/sdk/react-native/guides/transactions">
    View and filter transaction history
  </Card>

  <Card title="Wallet Integration" href="/sdk/react-native/guides/wallet-integration">
    Connect wallets and authenticate
  </Card>

  <Card title="Session Storage" href="/sdk/react-native/guides/session-storage">
    Secure persistence with AsyncStorage and Keychain
  </Card>

  <Card title="Error Handling" href="/sdk/react-native/guides/error-handling">
    Error codes and recovery patterns
  </Card>
</CardGroup>
