Skip to main content

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

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

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 for full handling of each AuthResult variant, including the mnemonic flow for first-time users.

WalletConnect Integration

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 }],
      });
    },
  };
}

Logout

MethodWhat it doesNext login
logout()Clears everything (keys, token, connection)Full re-auth with wallet
clearSession()Clears JWT only, keeps keysFast — no wallet signing
// Full logout
sdk.logout();

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

State Accessors

sdk.isConnected();        // boolean
sdk.isAuthenticated();    // boolean
sdk.getPrivacyAddress();  // string | undefined
sdk.getMpk();             // string | undefined
sdk.getWalletAddress();   // string | undefined

Complete Example

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

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.

3. Show Connection State

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

Next Steps