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

# Phantom React Native SDK

> Integrate Phantom wallets into React Native mobile apps with hooks for multi-chain transaction support.

The Phantom Connect React Native SDK provides React hooks for connecting to existing Phantom user wallets in your mobile React Native apps with native transaction support across multiple blockchains.

### Quick start

Generate a new Solana project using the **Phantom Embedded React Native Starter** template.

<Tabs>
  <Tab title="npm">
    ```bash theme={null}
    npx -y create-solana-dapp@latest -t solana-foundation/templates/community/phantom-embedded-react-native
    ```
  </Tab>

  <Tab title="pnpm">
    ```bash theme={null}
    pnpm create solana-dapp@latest -t solana-foundation/templates/community/phantom-embedded-react-native
    ```
  </Tab>

  <Tab title="yarn">
    ```bash theme={null}
    yarn create solana-dapp -t solana-foundation/templates/community/phantom-embedded-react-native
    ```
  </Tab>

  <Tab title="bun">
    ```bash theme={null}
    bun create solana-dapp@latest -t solana-foundation/templates/community/phantom-embedded-react-native
    ```
  </Tab>
</Tabs>

Run the command above in your terminal to get started.

[View template on Solana Templates →](https://solana.com/developers/templates/phantom-embedded-react-native)

***

## Features

* Built for React Native: Works in Expo environments with native modules for authentication
* Connection modal: Built-in modal for initiating wallet connections in mobile apps
* System browser authentication: Uses Safari (iOS) and Chrome Custom Tab (Android) for login and redirect handling
* Multi-chain support: Solana (available now), other chains coming soon.
* User wallet integration: Connects to existing Phantom mobile wallets through browser-based OAuth flows.

## Security

The Phantom Connect React Native SDK connects to existing Phantom user wallets:

* OAuth authentication with Google, Apple, or custom JWT providers
* PKCE support for secure OAuth flows
* Users maintain full control of their existing wallets
* Integration with Phantom's secure wallet infrastructure

## Prerequisites

* Register your app: Sign up or log in to the [Phantom Portal](https://phantom.com/portal/) and register your app.
* Obtain your App ID:
  * In Phantom Portal, expand your app in the left navigation, then select **Set Up**.
  * Your App ID appears at the top of the page.
* Allowlist your domains and redirect URLs: Add your app's domains and redirect URLs in the Phantom Portal to enable wallet connections.

## Installation

```bash theme={null}
npm install @phantom/react-native-sdk
```

### Install peer dependencies

```bash theme={null}
# For Expo projects
npx expo install expo-secure-store expo-web-browser expo-auth-session expo-router react-native-svg

# For bare React Native projects (additional setup required)
npm install expo-secure-store expo-web-browser expo-auth-session react-native-svg

# Required polyfill for cryptographic operations
npm install react-native-get-random-values
```

### Required polyfill

You must polyfill random byte generation to ensure cryptographic operations work properly. Add this import *at the very top* of your app's entry point (before any other imports):

```tsx theme={null}
// index.js, App.tsx, or _layout.tsx - MUST be the first import
import "react-native-get-random-values";

import { PhantomProvider } from "@phantom/react-native-sdk";
// ... other imports
```

<Warning>
  The polyfill import must be the first import in your app's entry point.
</Warning>

### Configure your app scheme

#### Expo projects

Add your custom scheme to `app.json`:

```json theme={null}
{
  "expo": {
    "name": "My Wallet App",
    "slug": "my-wallet-app",
    "scheme": "mywalletapp",
    "plugins": ["expo-router", "expo-secure-store", "expo-web-browser", "expo-auth-session"]
  }
}
```

## Quick start

```tsx theme={null}
// App.tsx or _layout.tsx (for Expo Router)
import { PhantomProvider, AddressType, darkTheme } from "@phantom/react-native-sdk";

export default function App() {
  return (
    <PhantomProvider
      config={{
        providers: ["google", "apple"], // Enabled auth providers for React Native
        appId: "your-app-id",
        scheme: "mywalletapp",
        addressTypes: [AddressType.solana],
        authOptions: {
          redirectUrl: "mywalletapp://phantom-auth-callback",
        },
      }}
      theme={darkTheme} // Optional: Customize modal appearance
      appIcon="https://your-app.com/icon.png" // Optional: Your app icon
      appName="Your App Name" // Optional: Your app name
    >
      <WalletScreen />
    </PhantomProvider>
  );
}

// WalletScreen.tsx
import { View, Button, Text } from "react-native";
import { useModal, usePhantom } from "@phantom/react-native-sdk";

export function WalletScreen() {
  const { open, close, isOpened } = useModal();
  const { isConnected } = usePhantom();

  if (isConnected) {
    return (
      <View style={{ padding: 20 }}>
        <Text>Connected</Text>
      </View>
    );
  }

  return (
    <View style={{ padding: 20 }}>
      <Button title="Connect Wallet" onPress={open} />
    </View>
  );
}
```

### Use the connection modal (Recommended)

The SDK includes a built-in bottom sheet modal that provides a user-friendly interface for connecting to Phantom. The modal supports multiple authentication methods (Google, Apple) and handles all connection logic automatically.

```tsx theme={null}
// WalletScreen.tsx
import React from "react";
import { View, Button, Text } from "react-native";
import { useModal, useAccounts } from "@phantom/react-native-sdk";

export function WalletScreen() {
  const modal = useModal();
  const { isConnected, addresses } = useAccounts();

  if (!isConnected) {
    return (
      <View style={{ padding: 20 }}>
        <Button title="Connect Wallet" onPress={() => modal.open()} />
      </View>
    );
  }

  return (
    <View style={{ padding: 20 }}>
      <Text style={{ fontSize: 18, marginBottom: 10 }}>Wallet Connected</Text>
      {addresses.map((addr, index) => (
        <Text key={index}>
          {addr.addressType}: {addr.address}
        </Text>
      ))}
      <Button title="Manage Wallet" onPress={() => modal.open()} />
    </View>
  );
}
```

Modal features:

* *Multiple auth providers*: Google, Apple
* *Bottom sheet UI*: Native bottom sheet design for mobile
* *Automatic state management*: Shows connect screen when disconnected, wallet management when connected
* *Error handling*: Clear error messages displayed in the modal
* *Loading states*: Visual feedback during connection attempts

### Or use hooks directly

```tsx theme={null}
// WalletScreen.tsx
import React from "react";
import { View, Button, Text, Alert } from "react-native";
import { useConnect, useAccounts, useSolana, useEthereum, useDisconnect } from "@phantom/react-native-sdk";

export function WalletScreen() {
  const { connect, isConnecting, error: connectError } = useConnect();
  const { addresses, isConnected } = useAccounts();
  const { solana } = useSolana();
  const { ethereum } = useEthereum();
  const { disconnect } = useDisconnect();

  const handleConnect = async () => {
    try {
      await connect({ provider: "google" });
      Alert.alert("Success", "Wallet connected!");
    } catch (error) {
      Alert.alert("Error", `Failed to connect: ${error.message}`);
    }
  };

  const handleSignSolanaMessage = async () => {
    try {
      const signature = await solana.signMessage("Hello from Solana!");
      Alert.alert("Solana Signed!", `Signature: ${signature.signature.slice(0, 10)}...`);
    } catch (error) {
      Alert.alert("Error", `Failed to sign: ${error.message}`);
    }
  };

  const handleSignEthereumMessage = async () => {
    try {
      const accounts = await ethereum.getAccounts();
      const signature = await ethereum.signPersonalMessage("Hello from Ethereum!", accounts[0]);
      Alert.alert("Ethereum Signed!", `Signature: ${signature.signature.slice(0, 10)}...`);
    } catch (error) {
      Alert.alert("Error", `Failed to sign: ${error.message}`);
    }
  };

  if (!isConnected) {
    return (
      <View style={{ padding: 20 }}>
        <Button
          title={isConnecting ? "Connecting..." : "Connect Wallet"}
          onPress={handleConnect}
          disabled={isConnecting}
        />
        {connectError && <Text style={{ color: "red", marginTop: 10 }}>Error: {connectError.message}</Text>}
      </View>
    );
  }

  return (
    <View style={{ padding: 20 }}>
      <Text style={{ fontSize: 18, marginBottom: 10 }}>Wallet Connected</Text>
      {addresses.map((addr, index) => (
        <Text key={index}>
          {addr.addressType}: {addr.address}
        </Text>
      ))}

      <Button title="Sign Solana Message" onPress={handleSignSolanaMessage} />

      <Button title="Sign Ethereum Message" onPress={handleSignEthereumMessage} />

      <Button title="Disconnect" onPress={disconnect} />
    </View>
  );
}
```

## Chain-specific operations

### Solana operations

```typescript theme={null}
import { useSolana } from "@phantom/react-native-sdk";

const { solana } = useSolana();
await solana.signMessage("Hello Solana!");
await solana.signAndSendTransaction(transaction);
```

### Ethereum operations

<Info>
  EVM support for Phantom Connect embedded wallets will go live later in 2026. The following Ethereum methods are currently available for injected provider (Phantom extension) connections only.
</Info>

```typescript theme={null}
import { useEthereum } from "@phantom/react-native-sdk";

const { ethereum } = useEthereum();
const accounts = await ethereum.getAccounts();
await ethereum.signPersonalMessage("Hello Ethereum!", accounts[0]);
await ethereum.sendTransaction(transactionData);
```

## Hooks

### useModal

Control the connection modal visibility. The modal automatically shows the appropriate content based on connection status.

```typescript theme={null}
const modal = useModal();

// Open the modal
modal.open(); // Shows connect options when disconnected, wallet management when connected

// Close the modal
modal.close();

// Check if modal is open
const isOpen = modal.isOpened;
```

Returns:

* `open()` - Function to open the modal
* `close()` - Function to close the modal
* `isOpened` - Boolean indicating if modal is currently visible

Modal behavior:

* *When disconnected*: Shows authentication provider options (Google, Apple)
* *When connected*: Shows connected wallet addresses and disconnect button

### useConnect

Manages wallet connection functionality.

```typescript theme={null}
const { connect, isConnecting, error } = useConnect();

// Connect with specific provider (React Native supported providers)
await connect({ provider: "google" }); // Google OAuth
await connect({ provider: "apple" }); // Apple ID
```

### useAccounts

Provides access to connected wallet information.

```typescript theme={null}
const {
  addresses, // Array of wallet addresses
  isConnected, // Connection status
  walletId, // Phantom wallet ID
} = useAccounts();
```

### useSolana

Provides access to Solana-specific operations.

```typescript theme={null}
const { solana, isAvailable } = useSolana();

if (isAvailable) {
  // Sign a message
  const signature = await solana.signMessage("Hello Solana!");

  // Sign a transaction (without sending)
  const signedTx = await solana.signTransaction(transaction);

  // Sign and send a transaction
  const result = await solana.signAndSendTransaction(transaction);
}
```

### useEthereum

Provides access to Ethereum-specific operations.

<Info>
  EVM support for Phantom Connect embedded wallets will go live later in 2026.
</Info>

```typescript theme={null}
const { ethereum, isAvailable } = useEthereum();

if (isAvailable) {
  // Get accounts
  const accounts = await ethereum.getAccounts();

  // Sign a personal message
  const signature = await ethereum.signPersonalMessage("Hello Ethereum!", accounts[0]);

  // Sign a transaction (without sending)
  const signedTx = await ethereum.signTransaction(transactionData);

  // Send a transaction
  const result = await ethereum.sendTransaction(transactionData);

  // Get current chain ID
  const chainId = await ethereum.getChainId();

  // Switch to a different EVM network
  await ethereum.switchChain(137); // Switch to Polygon
  await ethereum.switchChain("0x89"); // Also accepts hex strings
}
```

**Supported EVM Networks:**

| Network          | Chain ID   | Usage                            |
| ---------------- | ---------- | -------------------------------- |
| Ethereum Mainnet | `1`        | `ethereum.switchChain(1)`        |
| Ethereum Sepolia | `11155111` | `ethereum.switchChain(11155111)` |
| Polygon Mainnet  | `137`      | `ethereum.switchChain(137)`      |
| Polygon Amoy     | `80002`    | `ethereum.switchChain(80002)`    |
| Base Mainnet     | `8453`     | `ethereum.switchChain(8453)`     |
| Base Sepolia     | `84532`    | `ethereum.switchChain(84532)`    |
| Arbitrum One     | `42161`    | `ethereum.switchChain(42161)`    |
| Arbitrum Sepolia | `421614`   | `ethereum.switchChain(421614)`   |
| Monad Mainnet    | `143`      | `ethereum.switchChain(143)`      |
| Monad Testnet    | `10143`    | `ethereum.switchChain(10143)`    |

### useDisconnect

Manages wallet disconnection.

```typescript theme={null}
const { disconnect, isDisconnecting } = useDisconnect();

await disconnect();
```

## Authentication flows

### Available providers

The SDK supports multiple authentication providers that you specify in the `providers` array:

* *Google* (`"google"`) - Google OAuth authentication
* *Apple* (`"apple"`) - Apple ID authentication

Example configuration:

```tsx theme={null}
<PhantomProvider
  config={{
    providers: ["google", "apple"], // Specify enabled providers
    appId: "your-app-id",
    scheme: "myapp",
    addressTypes: [AddressType.solana],
  }}
>
  <App />
</PhantomProvider>
```

Example usage:

```tsx theme={null}
// Google OAuth
await connect({ provider: "google" });

// Apple ID
await connect({ provider: "apple" });
```

### Authentication process

1. User taps **Connect Wallet** in your app.
2. System browser opens (Safari on iOS, Chrome Custom Tab on Android).
3. User authenticates with their chosen provider.
4. Browser redirects back to your app using the custom scheme.
5. SDK automatically processes the authentication result.
6. Wallet is connected and ready to use.

### Deep-link handling

The SDK automatically handles deep link redirects. Ensure your app's URL scheme is properly configured.

Redirect URL format:

```
{scheme}://phantom-auth-callback?wallet_id=...&session_id=...
```

## Security considerations

The Phantom Connect React Native SDK uses platform-level secure storage and system browsers during authentication:

### Secure storage

* iOS uses Keychain Services with hardware security.
* Android uses Android Keystore with hardware-backed keys.

### Secure authentication

* Uses the system browser rather than in-app webviews.
* Verifies redirect origins automatically.

## Configuration examples

### Basic configuration

```tsx theme={null}
import { PhantomProvider, AddressType } from "@phantom/react-native-sdk";

<PhantomProvider
  config={{
    providers: ["google", "apple"],
    appId: "your-app-id",
    scheme: "myapp",
    addressTypes: [AddressType.solana],
  }}
>
  <App />
</PhantomProvider>;
```

### Multi-chain configuration

```tsx theme={null}
import { PhantomProvider, AddressType, darkTheme } from "@phantom/react-native-sdk";

<PhantomProvider
  config={{
    providers: ["google", "apple"],
    appId: "your-app-id",
    scheme: "mycompany-wallet",
    addressTypes: [AddressType.solana, AddressType.ethereum],
    authOptions: {
      redirectUrl: "mycompany-wallet://auth/success",
    },
  }}
  theme={darkTheme}
  appIcon="https://your-app.com/icon.png"
  appName="Your App"
>
  <App />
</PhantomProvider>;
```

## Debug configuration

Configure debug logging by passing a `debugConfig` prop to `PhantomProvider`:

```tsx theme={null}
import { PhantomProvider, AddressType } from "@phantom/react-native-sdk";

function App() {
  const debugConfig = {
    enabled: true, // Enable debug logging
  };

  return (
    <PhantomProvider
      config={{
        providers: ["google", "apple"],
        appId: "your-app-id",
        scheme: "mywalletapp",
        addressTypes: [AddressType.solana],
      }}
      debugConfig={debugConfig}
    >
      <YourApp />
    </PhantomProvider>
  );
}
```

Debug configuration properties:

| Property  | Type      | Description                           |
| --------- | --------- | ------------------------------------- |
| `enabled` | `boolean` | Enable debug logging (default: false) |

## What you can do

<CardGroup cols={3}>
  <Card title="Connect to wallets" icon="plug" href="/sdks/react-native-sdk/connect">
    Learn how to connect to Phantom wallets in mobile apps
  </Card>

  <Card title="Sign messages" icon="signature" href="/sdks/react-native-sdk/sign-messages">
    Implement message signing for authentication and verification
  </Card>

  <Card title="Sign and send transactions" icon="paper-plane" href="/sdks/react-native-sdk/sign-and-send-transaction">
    Handle transaction signing and broadcasting across blockchains
  </Card>
</CardGroup>

## Starter kits and examples

Mobile-specific templates and examples:

<CardGroup cols={2}>
  <Card title="React Native demo app" icon="mobile" href="https://github.com/phantom/phantom-connect-sdk/tree/main/examples/react-native-sdk-demo-app">
    Full-featured React Native example with Expo
  </Card>

  <Card title="All examples" icon="github" href="https://github.com/phantom/phantom-connect-sdk/tree/main/examples">
    Browse all example apps on GitHub
  </Card>

  <Card title="Code recipes" icon="book-open" href="/resources/recipes">
    Mobile implementation patterns and snippets
  </Card>

  <Card title="Mobile deep links" icon="link" href="/phantom-deeplinks/deeplinks-ios-and-android">
    Alternative integration for Solana mobile apps
  </Card>
</CardGroup>

## Additional resources

<CardGroup cols={3}>
  <Card title="SDK overview" icon="book" href="/wallet-sdks-overview">
    Compare all Phantom SDKs and choose the right one
  </Card>

  <Card title="Phantom Connect" icon="link" href="/phantom-connect">
    Learn about authentication flows and user experience
  </Card>

  <Card title="JWT authentication" icon="key" href="/sdks/guides/wallet-authentication-with-jwts">
    Implement custom JWT-based authentication for mobile
  </Card>
</CardGroup>
