> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pesapay.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# React Native with Privy

> Give each user a Stellar wallet and an EVM deposit address, and run sponsored deposits in an Expo app.

Pesa's mobile app uses Privy as the wallet layer on every chain: an embedded Stellar account for the balance, and a Privy smart wallet as the EVM deposit address, the same address on every EVM chain. This guide shows the same setup for your Expo app.

## Install

```bash theme={null}
npx expo install @privy-io/expo @privy-io/expo-native-extensions permissionless \
  react-native-passkeys expo-application expo-crypto expo-linking expo-secure-store expo-web-browser
npm install @pesa/sdk viem @stellar/stellar-sdk
```

`permissionless` is Privy's optional peer for smart wallets. Rebuild your dev client after adding native modules.

<Warning>
  `@privy-io/js-sdk-core` imports `jose`, whose package exports have no `react-native` condition. If Metro fails with `Unable to resolve module crypto`, redirect `jose` to `jose/dist/browser/index.js` in your Metro `resolveRequest`. Do not set `browser` as a global condition: it would also move `@stellar/stellar-sdk`.
</Warning>

## Providers

```tsx theme={null}
import { PrivyProvider } from "@privy-io/expo";
import { SmartWalletsProvider } from "@privy-io/expo/smart-wallets";

export function Root({ children }) {
  return (
    <PrivyProvider appId={process.env.EXPO_PUBLIC_PRIVY_APP_ID!}>
      <SmartWalletsProvider>{children}</SmartWalletsProvider>
    </PrivyProvider>
  );
}
```

Turn on smart wallets in the Privy dashboard and set a paymaster URL for each chain you sponsor.

## Wallets

```ts theme={null}
import { useCreateWallet } from "@privy-io/expo/extended-chains";
import { useSmartWallets } from "@privy-io/expo/smart-wallets";

const { createWallet } = useCreateWallet();
await createWallet({ chainType: "stellar" });            // the user's Stellar account

const { getClientForChain } = useSmartWallets();
const base = await getClientForChain({ chainId: 8453 }); // the deposit address on Base
```

## A sponsored deposit

```ts theme={null}
import { getAccessToken } from "@privy-io/expo";
import { createTransfersClient, findEvmChain, STELLAR_CCTP, verifyCctpCalls, verifySendToAddress } from "@pesa/sdk";

const pesa = createTransfersClient({ baseUrl: "https://api.pesapay.xyz", getToken: () => getAccessToken() });

const quote = await pesa.quote({
  route: "cctp-deposit",
  source_chain: "eip155:8453",
  source_address: base.account.address,
  dest_address: stellarAddress,
  amount_in: "20000000",
  funding_mode: "deposit_address",
});
const transfer = await pesa.createTransfer(quote.id, crypto.randomUUID());

// 1. Show the address until the funds arrive.
const first = await pesa.getActions(transfer.id);
verifySendToAddress(first!, { chain: "eip155:8453", address: base.account.address, amount: "20000000" });

// 2. Once FUNDED, burn in one sponsored, batched transaction.
const next = await pesa.getActions(transfer.id);
if (next?.kind === "evm_calls") {
  const calls = next.calls.map((c) => ({ ...c, value: BigInt(c.value) }));
  verifyCctpCalls(calls, {
    chain: findEvmChain("mainnet", "eip155:8453"),
    stellar: STELLAR_CCTP.mainnet,
    recipient: stellarAddress,
    amount6: 20_000_000n,
  });
  const hash = await base.sendTransaction({ calls });
  await pesa.submit(transfer.id, { kind: "evm_tx", hash });
}
```

The hash Privy returns is the bundle transaction. Submit it once it is mined. The server finds the user's burn in the receipt by its `DepositForBurn` log, so several users' burns in one bundle are fine.

## Persist before you submit

Save the burn hash with the transfer ID before calling `submit`. If the app is killed in between, submit it on the next launch. A burn submitted after the transfer expired still completes.

## Unsponsored chains

The app can list every chain in the registry. On chains where `sponsored` is false, show a warning: funds sent to the smart-wallet address there cannot be moved by the app.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.