Skip to main content

Phantom React SDK

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

Features

  • Framework Agnostic: Works with vanilla JavaScript/TypeScript and any web framework
  • Multi-Chain Support: Solana (available now); Ethereum, Bitcoin, and Sui networks (coming soon)
  • Native Transaction Support: Direct transaction object handling
  • User Wallet Integration: Connect to existing Phantom user wallets
  • TypeScript Support: Full TypeScript definitions included

Security

The React SDK connects to existing Phantom user wallets, ensuring:
  • Users control their own wallets and private keys
  • Integration with Phantom’s secure wallet infrastructure
  • No private key handling in your application
  • User maintains full control of their assets

Prerequisites

  • Register your application
    Sign up or log in to the Phantom Portal and register your application.
  • Obtain your App ID
    • In the Portal, go to your app and open URL Config (left-hand menu).
    • This page shows your allowed origins and redirect URLs.
    • Scroll down to the App ID section at the bottom of the page — your App ID is listed there, below the URL configurations.
    • Copy the App ID for use in your integration.
  • Whitelist your domains and redirect URLs
    • Add your application’s domains and redirect URLs in the Phantom Portal to enable wallet connections.

Authentication Configuration

When using the embedded provider, you’ll need to configure authentication options:
authOptions: {
  redirectUrl: "https://yourapp.com/auth/callback", // Your callback page
}
Important notes about redirectUrl:
  • Must be an existing page/route in your application
  • Must be whitelisted in your Phantom Portal app configuration
  • This is where users will be redirected after completing OAuth with Google

Installation

npm install @phantom/react-sdk@beta

Dependencies

Install additional dependencies based on the networks you want to support:
Network SupportRequired Dependencies
Solana@solana/web3.js OR @solana/kit
Ethereum/EVMviem
Example for Solana + Ethereum support:
npm install @phantom/react-sdk@beta @solana/web3.js viem

Quick Start

Basic Setup with Chain-Specific Operations

import { PhantomProvider, useConnect, useSolana, useEthereum } from "@phantom/react-sdk";
import { AddressType } from "@phantom/browser-sdk";

function App() {
  return (
    <PhantomProvider
      config={{
        providerType: "embedded", // or "injected" for browser extension
        addressTypes: [AddressType.solana, AddressType.ethereum],
        appId: "your-app-id",
        authOptions: {
          authUrl: "https://connect.phantom.app/login",
          redirectUrl: "https://yourapp.com/auth/callback", // Must be an existing page in your app and whitelisted in Phantom Portal
        },
      }}
    >
      <WalletComponent />
    </PhantomProvider>
  );
}

function WalletComponent() {
  const { connect, isConnecting } = useConnect();
  const { solana } = useSolana();
  const { ethereum } = useEthereum();

  const handleConnect = async () => {
    const { addresses } = await connect();
    console.log("Connected addresses:", addresses);
  };

  const signSolanaMessage = async () => {
    const signature = await solana.signMessage("Hello Solana!");
    console.log("Solana signature:", signature);
  };

  const signEthereumMessage = async () => {
    const accounts = await ethereum.getAccounts();
    const signature = await ethereum.signPersonalMessage("Hello Ethereum!", accounts[0]);
    console.log("Ethereum signature:", signature);
  };

  return (
    <div>
      <button onClick={handleConnect} disabled={isConnecting}>
        {isConnecting ? "Connecting..." : "Connect Wallet"}
      </button>
      <button onClick={signSolanaMessage}>Sign Solana Message</button>
      <button onClick={signEthereumMessage}>Sign Ethereum Message</button>
    </div>
  );
}

Chain-Specific Hooks

The React SDK provides dedicated hooks for each blockchain:

useSolana Hook

import { useSolana } from "@phantom/react-sdk";

function SolanaOperations() {
  const { solana } = useSolana();

  const signMessage = async () => {
    const signature = await solana.signMessage("Hello Solana!");
    console.log("Signature:", signature);
  };

  const signAndSendTransaction = async () => {
    const result = await solana.signAndSendTransaction(transaction);
    console.log("Transaction sent:", result.hash);
  };

  const switchNetwork = async () => {
    await solana.switchNetwork('devnet');
  };

  return (
    <div>
      <button onClick={signMessage}>Sign Message</button>
      <button onClick={signAndSendTransaction}>Send Transaction</button>
      <button onClick={switchNetwork}>Switch to Devnet</button>
      <p>Connected: {solana.isConnected ? 'Yes' : 'No'}</p>
    </div>
  );
}

useEthereum Hook

import { useEthereum } from "@phantom/react-sdk";

function EthereumOperations() {
  const { ethereum } = useEthereum();

  const signPersonalMessage = async () => {
    const accounts = await ethereum.getAccounts();
    const signature = await ethereum.signPersonalMessage("Hello Ethereum!", accounts[0]);
    console.log("Signature:", signature);
  };

  const sendTransaction = async () => {
    const result = await ethereum.sendTransaction({
      to: "0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E",
      value: "1000000000000000000", // 1 ETH in wei
      gas: "21000",
    });
    console.log("Transaction sent:", result.hash);
  };

  const switchChain = async () => {
    await ethereum.switchChain(137); // Switch to Polygon
  };

  return (
    <div>
      <button onClick={signPersonalMessage}>Sign Personal Message</button>
      <button onClick={sendTransaction}>Send Transaction</button>
      <button onClick={switchChain}>Switch to Polygon</button>
      <p>Connected: {ethereum.isConnected ? 'Yes' : 'No'}</p>
    </div>
  );
}

Auto-Confirm Hook (Injected Provider Only)

useAutoConfirm Hook

import { useAutoConfirm, NetworkId } from "@phantom/react-sdk";

function AutoConfirmControls() {
  const {
    enable,
    disable, 
    status,
    supportedChains,
    isLoading,
    error,
  } = useAutoConfirm();

  const handleEnable = async () => {
    // Enable auto-confirm for specific chains
    const result = await enable({
      chains: [NetworkId.SOLANA_DEVNET, NetworkId.ETHEREUM_MAINNET]
    });
    console.log("Auto-confirm enabled:", result);
  };

  const handleDisable = async () => {
    await disable();
    console.log("Auto-confirm disabled");
  };

  return (
    <div>
      <p>Status: {status?.enabled ? "Enabled" : "Disabled"}</p>
      <button onClick={handleEnable} disabled={isLoading}>
        Enable Auto-Confirm
      </button>
      <button onClick={handleDisable} disabled={isLoading}>
        Disable Auto-Confirm
      </button>
    </div>
  );
}

Available Hooks

HookPurposeReturns
useConnectConnect to wallet{ connect, isConnecting, error }
useAccountsGet wallet addressesWalletAddress[] or null
useIsExtensionInstalledCheck extension status{ isLoading, isInstalled }
useDisconnectDisconnect from wallet{ disconnect, isDisconnecting }
useAutoConfirmAuto-confirm management (injected only){ enable, disable, status, supportedChains, ... }
useSolanaSolana chain operations{ solana: { signMessage, signAndSendTransaction, ... } }
useEthereumEthereum chain operations{ ethereum: { signPersonalMessage, sendTransaction, ... } }

Next Steps

I