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

# Wallet integration

# Wallet Integration

This guide covers connecting wallets and authenticating users with the Privacy Boost React Native SDK.

## WalletDelegate Interface

The SDK interacts with wallets through the `WalletDelegate` interface:

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

interface WalletDelegate {
  getAddress(): Promise<string>;
  getChainId(): Promise<bigint>;
  signMessage(message: string): Promise<string>;
  signTypedData(typedDataJson: string): Promise<string>;
  sendTransaction(toAddress: string, value: string, data: string): Promise<string>;
  waitForTransactionReceipt(txHash: string): Promise<TransactionReceipt>;
}

interface TransactionReceipt {
  txHash: string;
  status: boolean;              // true on success, false on revert
  logs: Array<{
    address: string;
    topics: string[];
    data: string;
  }>;
}
```

The SDK calls `waitForTransactionReceipt` after `sendTransaction` to confirm
on-chain inclusion and read emitted events (e.g. the `Shield` event). It
should poll `eth_getTransactionReceipt` until the receipt is available.

## Basic Authentication

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

const walletDelegate: WalletDelegate = {
  getAddress: async () => '0x...wallet-address',
  getChainId: async () => BigInt(1),
  signMessage: async (message) => {
    // Use your wallet library to sign
    return '0x...signature';
  },
  signTypedData: async (typedDataJson) => {
    return '0x...signature';
  },
  sendTransaction: async (to, value, data) => {
    return '0x...txHash';
  },
  waitForTransactionReceipt: async (txHash) => {
    // Poll eth_getTransactionReceipt until available.
    return { txHash, status: true, logs: [] };
  },
};

const result = await sdk.authenticate(walletDelegate);

switch (result.tag) {
  case 'Authenticated':
    console.log('Privacy Address:', result.loginResult.privacyAddress);
    break;
  case 'MnemonicGenerated':
    console.log('Recovery phrase:', result.mnemonic);
    await sdk.proceedAfterMnemonic(undefined);
    break;
  case 'CredentialRequired':
    const loginResult = await sdk.submitCredential(credential, undefined);
    console.log('Privacy Address:', loginResult.privacyAddress);
    break;
  case 'RecoveryRequired':
    console.log('Recovery required:', result.challenge.reason);
    break;
}
```

See [Getting Started → Connecting a Wallet](../getting-started#connecting-a-wallet)
for full handling of each `AuthResult` variant, including the mnemonic flow
for first-time users.

## WalletConnect Integration

```typescript theme={null}
import { useWalletConnectModal } from '@walletconnect/modal-react-native';

function createWalletConnectDelegate(provider: any): WalletDelegate {
  return {
    getAddress: async () => {
      const accounts = await provider.request({ method: 'eth_accounts' });
      return accounts[0];
    },
    getChainId: async () => {
      const chainId = await provider.request({ method: 'eth_chainId' });
      return BigInt(parseInt(chainId, 16));
    },
    signMessage: async (message) => {
      const address = await provider.request({ method: 'eth_accounts' }).then((a: string[]) => a[0]);
      return provider.request({
        method: 'personal_sign',
        params: [message, address],
      });
    },
    signTypedData: async (typedDataJson) => {
      const address = await provider.request({ method: 'eth_accounts' }).then((a: string[]) => a[0]);
      return provider.request({
        method: 'eth_signTypedData_v4',
        params: [address, typedDataJson],
      });
    },
    sendTransaction: async (to, value, data) => {
      const address = await provider.request({ method: 'eth_accounts' }).then((a: string[]) => a[0]);
      return provider.request({
        method: 'eth_sendTransaction',
        params: [{ from: address, to, value: '0x' + BigInt(value).toString(16), data }],
      });
    },
    waitForTransactionReceipt: async (txHash) => {
      while (true) {
        const receipt = await provider.request({
          method: 'eth_getTransactionReceipt',
          params: [txHash],
        });

        if (receipt) {
          return {
            txHash,
            status: receipt.status === '0x1',
            logs: receipt.logs.map((log: any) => ({
              address: log.address,
              topics: log.topics,
              data: log.data,
            })),
          };
        }

        await new Promise((resolve) => setTimeout(resolve, 1_000));
      }
    },
  };
}
```

## Logout

| Method           | What it does                                | Next login               |
| ---------------- | ------------------------------------------- | ------------------------ |
| `logout()`       | Clears everything (keys, token, connection) | Full re-auth with wallet |
| `clearSession()` | Clears JWT only, keeps keys                 | Fast — no wallet signing |

```typescript theme={null}
// Full logout
sdk.logout();

// Quick session clear (keeps keys)
sdk.clearSession();
```

## State Accessors

```typescript theme={null}
sdk.isConnected();        // boolean
sdk.isAuthenticated();    // boolean
sdk.getPrivacyAddress();  // string | undefined
sdk.getMpk();             // string | undefined
sdk.getWalletAddress();   // string | undefined
```

## Complete Example

```tsx theme={null}
import React, { useState } from 'react';
import { View, Text, Button, ActivityIndicator } from 'react-native';

function ConnectScreen({ sdk }: { sdk: PrivacyBoost }) {
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [privacyAddress, setPrivacyAddress] = useState<string | null>(null);

  const handleConnect = async () => {
    setLoading(true);
    setError(null);

    try {
      const result = await sdk.authenticate(walletDelegate);
      if (result.tag === 'Authenticated') {
        setPrivacyAddress(result.loginResult.privacyAddress);
      }
    } catch (err: any) {
      if (err.tag !== 'SignatureRejected') {
        setError(err.message ?? 'Authentication failed');
      }
    } finally {
      setLoading(false);
    }
  };

  if (privacyAddress) {
    return (
      <View style={{ padding: 16 }}>
        <Text>Connected: {privacyAddress.slice(0, 10)}...</Text>
        <Button title="Logout" onPress={() => { sdk.logout(); setPrivacyAddress(null); }} />
      </View>
    );
  }

  return (
    <View style={{ padding: 16 }}>
      {error && <Text style={{ color: 'red' }}>{error}</Text>}
      {loading ? (
        <ActivityIndicator />
      ) : (
        <Button title="Connect Wallet" onPress={handleConnect} />
      )}
    </View>
  );
}
```

## Error Handling

```typescript theme={null}
try {
  await sdk.authenticate(walletDelegate);
} catch (error: any) {
  switch (error.tag) {
    case 'SignatureRejected':
      return; // User cancelled
    case 'WalletError':
      console.log('Wallet error:', error.message);
      break;
    case 'NetworkError':
      console.log('Network error:', error.message);
      break;
    case 'InvalidConfig':
      console.log('SDK configuration error');
      break;
    default:
      console.log('Auth error:', error);
  }
}
```

## Best Practices

### 1. Handle Signature Rejection Silently

When users cancel the wallet signature, don't show an error.

### 2. Save Session After Authentication

Use session persistence to avoid re-signing on app restart. See [Session Storage](./session-storage).

### 3. Show Connection State

Display the privacy address so users can verify which account is active.

## Next Steps

* [Session Storage](./session-storage)
* [Deposits Guide](./deposits)
* [Error Handling](./error-handling)
* [API Reference](/sdk/react-native/api-reference)
