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

# addPhantomRedirectSolanaExtension

> Enable Phantom wallet support via deep link redirect on mobile

Adds support for connecting and signing with [Phantom](https://phantom.app) on mobile using Phantom's
[deep link redirect protocol](https://docs.phantom.app/phantom-deeplinks/deeplinks-ios-and-android).
This is the recommended integration method for mobile web apps that want to use Phantom on iOS and
Android without relying on browser extension injection.

The extension handles the full redirect lifecycle: building encrypted deep links, waiting for Phantom
to redirect back to your app, and completing the operation.

## Installation

```bash theme={"system"}
npm install @dynamic-labs-sdk/solana
```

## Usage

<Tabs>
  <Tab title="JavaScript">
    Call `addPhantomRedirectSolanaExtension` once during app initialization, passing the current URL so
    the extension can detect and complete any in-progress Phantom redirect:

    ```javascript theme={"system"}
    import { createDynamicClient } from '@dynamic-labs-sdk/client';
    import { addPhantomRedirectSolanaExtension } from '@dynamic-labs-sdk/solana/phantom-redirect';

    const client = createDynamicClient({
      environmentId: 'YOUR_ENVIRONMENT_ID',
    });

    addPhantomRedirectSolanaExtension(
      { url: new URL(window.location.href) },
      client
    );
    ```
  </Tab>

  <Tab title="React">
    In React, call `addPhantomRedirectSolanaExtension` at module level in your client setup file — it must run on every page load so the extension can detect and complete any in-progress Phantom redirect:

    ```tsx theme={"system"}
    // dynamicClient.ts
    import { createDynamicClient, initializeClient } from '@dynamic-labs-sdk/client';
    import { addSolanaWalletStandardExtension } from '@dynamic-labs-sdk/solana/walletStandard';
    import { addPhantomRedirectSolanaExtension } from '@dynamic-labs-sdk/solana/phantom-redirect';

    export const dynamicClient = createDynamicClient({
      environmentId: 'YOUR_ENVIRONMENT_ID',
    });

    addSolanaWalletStandardExtension();

    // Must run on every page load — pass the current URL so the extension
    // can detect and complete any in-progress Phantom redirect
    addPhantomRedirectSolanaExtension({ url: new URL(window.location.href) });

    void initializeClient();
    ```

    The module is imported once when the app loads, so the extension automatically detects return redirects from Phantom on every navigation.
  </Tab>
</Tabs>

## Parameters

| Parameter                       | Type                       | Description                                                                                                                                                                                            |
| ------------------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `url`                           | `URL` (optional)           | The current page URL. Used to detect and complete a pending Phantom redirect. Pass `new URL(window.location.href)` on every page load.                                                                 |
| `onCloseTab`                    | `() => void` (optional)    | Callback invoked when the redirect tab should close itself. By default, the SDK calls `window.close()`. Provide a custom handler if you need different behavior (e.g. navigating to a fallback route). |
| `disableAutoRedirectCompletion` | `boolean` (optional)       | When `true`, the extension will not automatically detect and complete pending redirects on load. Defaults to `false`.                                                                                  |
| `client`                        | `DynamicClient` (optional) | The Dynamic client instance. Only required when using multiple clients.                                                                                                                                |

## How it works

Phantom's redirect protocol works as follows:

1. Your app calls a standard wallet operation (connect, sign, send, disconnect) on the Phantom redirect provider
2. The SDK builds an encrypted deep link and redirects the user to the Phantom mobile app
3. The user approves the request inside Phantom
4. Phantom redirects back to your app. For connect and sign operations, the redirect URL includes an
   encrypted response. For disconnect, Phantom redirects back with no query parameters.
5. On the next page load, `addPhantomRedirectSolanaExtension` detects the redirect,
   decrypts the response (if present), and completes the operation

Phantom opens the redirect in a new browser tab. The SDK uses cross-tab broadcast messaging to
deliver the result back to the original tab where the operation was initiated, then closes the
redirect tab automatically via the `onCloseTab` callback.

All payloads between your app and Phantom are encrypted end-to-end using NaCl box encryption with
ephemeral key pairs.

## Supported operations

Once registered, the Phantom redirect provider supports all standard Solana wallet operations:

* `connect` — request wallet connection
* `disconnect` — end the wallet session
* `signMessage` — sign an arbitrary message
* `signTransaction` — sign a transaction
* `signAllTransactions` — sign multiple transactions
* `signAndSendTransaction` — sign and submit a transaction

These are used via the same functions as any other Solana wallet in Dynamic — see
[Signing and sending transactions](/javascript/reference/solana/signing-sending-transactions).

## Connect and verify on mobile

<Warning>
  `connectAndVerifyWithWalletProvider` is **not supported** with Phantom redirect on mobile. It will
  throw a `DeeplinkConnectAndVerifyUnsupportedError`.
</Warning>

On mobile, `connectAndVerifyWithWalletProvider` triggers two sequential deep links — one to connect
and another to sign for verification. iOS will not honor the second deep link because it is no longer
tied to a user gesture. Android may handle this differently, but this restriction applies to all
mobile platforms to ensure a stable experience and prevent production-only errors.

Instead, use `connectWithWalletProvider` and `verifyWalletAccount` as two separate user actions:

```javascript theme={"system"}
import {
  connectWithWalletProvider,
  verifyWalletAccount,
  DeeplinkConnectAndVerifyUnsupportedError,
} from '@dynamic-labs-sdk/client';

// Step 1: Connect the wallet (first user tap)
const walletAccount = await connectWithWalletProvider({
  walletProviderKey: 'phantomsol:deepLink',
  addToDynamicWalletAccounts: false,
});

// Step 2: Verify ownership from a separate user action (e.g. a "Verify Ownership" button)
await verifyWalletAccount({ walletAccount });
```

Alternatively, you can catch the error from `connectAndVerifyWithWalletProvider` and fall back to
the two-step flow:

```javascript theme={"system"}
import {
  connectAndVerifyWithWalletProvider,
  connectWithWalletProvider,
  verifyWalletAccount,
  DeeplinkConnectAndVerifyUnsupportedError,
} from '@dynamic-labs-sdk/client';

try {
  await connectAndVerifyWithWalletProvider({
    walletProviderKey: key,
  });
} catch (error) {
  if (error instanceof DeeplinkConnectAndVerifyUnsupportedError) {
    // Mobile deep link provider — connect only, then verify separately
    const walletAccount = await connectWithWalletProvider({
      walletProviderKey: key,
      addToDynamicWalletAccounts: false,
    });

    // Present a "Verify Ownership" button to the user, then:
    await verifyWalletAccount({ walletAccount });
  } else {
    throw error;
  }
}
```

See [Connecting and Verifying a Wallet](/javascript/reference/wallets/connect-and-verify-wallet)
for more details on the connect and verify flow.

## Setting a redirect URL

Phantom redirects back to your app after the user approves or rejects a request. Make sure your app
handles the redirect URL on the page that calls `addPhantomRedirectSolanaExtension`, so the extension
can complete the pending operation automatically.

```javascript theme={"system"}
// On every page load, pass the current URL
addPhantomRedirectSolanaExtension(
  { url: new URL(window.location.href) },
  client
);

// If Phantom redirected here with a response, the extension completes it automatically.
// If not, it simply registers the provider for future use.
```

## Limitations

* Requires the user to have the Phantom mobile app installed
* The redirect flow causes a full page navigation — ensure your app state is restored on return
* Each operation generates a new ephemeral encryption key pair; sessions do not persist across devices
* Only supported on Solana
* `connectAndVerifyWithWalletProvider` is not supported on mobile — see [Connect and verify on mobile](#connect-and-verify-on-mobile) above

## Related functions

* [addSolanaExtension](/javascript/reference/solana/adding-solana-extensions) - Register standard Solana wallet providers
* [Connecting and Verifying a Wallet](/javascript/reference/wallets/connect-and-verify-wallet) - Connect and verify wallet accounts
* [signing-sending-transactions](/javascript/reference/solana/signing-sending-transactions) - Sign and send transactions with any Solana wallet
