The Phantom Wallet SDK allows you to integrate Phantom's wallet functionality directly into your web application.
# Using npm
npm install @phantom/wallet-sdk
# Using yarn
yarn add @phantom/wallet-sdk
# Using pnpm
pnpm add @phantom/wallet-sdk
The SDK supports two primary integration modes:
In this mode, the Phantom wallet appears as a floating widget on your page in one of the predefined positions (bottom-right, bottom-left, top-right, top-left). This is the simplest integration method.
import { createPhantom, Position } from "@phantom/wallet-sdk";
// Initialize the Phantom wallet as a popup
const phantom = await createPhantom({
position: Position.bottomRight, // Choose from bottomRight, bottomLeft, topRight, topLeft
hideLauncherBeforeOnboarded: false,
namespace: "my-app",
});
// Show the wallet UI
phantom.show();
In this mode, the Phantom wallet renders inside a specific HTML element that you provide. This gives you complete control over the wallet's positioning and layout within your application.
import { createPhantom } from "@phantom/wallet-sdk";
// Make sure the container element exists in your DOM
// <div id="wallet-container" style="width: 400px; height: 600px;"></div>
// Initialize the Phantom wallet inside your container
const phantom = await createPhantom({
element: "wallet-container", // ID of the container element
namespace: "my-app",
});
// The wallet will automatically show in the container
// You can still use show/hide methods
phantom.show();
When you initialize the SDK without specifying a namespace:
const phantom = await createPhantom();
The SDK behaves as follows:
-
If the Phantom browser extension is already installed, the SDK will not initialize a new embedded wallet to avoid conflicts. Your dApp will continue to use the extension.
-
If no extension is detected, the SDK will:
- Attach the wallet instance to
window.phantom
- Expose blockchain RPC providers to their standard window objects:
window.solana
for Solanawindow.ethereum
for Ethereum- And other blockchain providers
- Attach the wallet instance to
This means that existing dApps built for the Phantom extension can work with the embedded wallet without code changes - the same window objects they already use will be populated by the SDK.
When you specify a custom namespace:
const phantom = await createPhantom({ namespace: "myCustomWallet" });
The SDK will:
- Initialize even if the Phantom extension is installed (allowing both to coexist)
- Attach the wallet instance to
window.myCustomWallet
instead ofwindow.phantom
- Not automatically expose providers to standard window objects to avoid conflicts with the extension
In this case, you must use the returned object for all interactions:
// Connect to Solana using your namespaced instance
const publicKey = await phantom.solana.connect();
For existing dApps that detect and use standard provider patterns:
- Extension Installed: The dApp will use the extension as normal
- No Extension, Default Namespace: The dApp will use the embedded wallet through the standard window objects
- Custom Namespace: You'll need to modify your dApp code to use the custom instance
The createPhantom
function accepts the following configuration options:
export type CreatePhantomConfig = Partial<{
zIndex: number; // Set the z-index of the wallet UI
hideLauncherBeforeOnboarded: boolean; // Hide the launcher for new users
colorScheme: string; // Light or dark mode
paddingBottom: number; // Padding from bottom of screen
paddingRight: number; // Padding from right of screen
paddingTop: number; // Padding from top of screen
paddingLeft: number; // Padding from left of screen
position: Position; // Position on screen (bottomRight, bottomLeft, topRight, topLeft)
sdkURL: string; // Custom SDK URL
element: string; // ID of element to render wallet in (for custom positioning)
namespace: string; // Namespace for the wallet instance
}>;
Note: When using Element Mode, the position
setting is ignored since the wallet will render inside your specified container element.
The createPhantom
function returns a Phantom
interface with the following methods and properties:
export interface Phantom {
// UI Controls
show: () => void; // Show the wallet UI
hide: () => void; // Hide the wallet UI
// Wallet Actions
buy: (options: { amount?: number; buy: string }) => void; // Buy tokens
swap: (options: { buy: string; sell?: string; amount?: string }) => void; // Swap tokens
navigate: ({ route, params }: { route: string; params?: any }) => void; // Navigate within wallet
// Blockchain RPC Interfaces
solana?: any; // Solana RPC interface
ethereum?: any; // Ethereum RPC interface
sui?: any; // Sui RPC interface
bitcoin?: any; // Bitcoin RPC interface
// App Interface
app: PhantomApp; // Phantom app interface
}
The SDK exposes blockchain-specific RPC interfaces through the Phantom instance:
// Connect to wallet
const publicKey = await phantom.solana.connect();
// Sign a message
const message = new TextEncoder().encode("Hello, Solana!");
const signature = await phantom.solana.signMessage(message);
// Send a transaction
const transaction = new Transaction();
// ... add instructions ...
const signature = await phantom.solana.signAndSendTransaction(transaction);
For detailed examples, see Solana documentation.
// Connect to wallet
const accounts = await phantom.ethereum.request({
method: "eth_requestAccounts",
});
// Sign a message
const from = accounts[0];
const message = "Hello, Ethereum!";
const signature = await phantom.ethereum.request({
method: "personal_sign",
params: [message, from],
});
// Send a transaction
const txHash = await phantom.ethereum.request({
method: "eth_sendTransaction",
params: [
{
from,
to: "0x...",
value: "0x...",
// other tx params
},
],
});
For detailed examples, see Ethereum documentation.
// Connect to wallet
const accounts = await phantom.sui.connect();
// Sign a transaction
// ... create transaction ...
const signedTx = await phantom.sui.signTransaction(tx);
For detailed examples, see Sui documentation.
// Connect to wallet
const accounts = await phantom.bitcoin.connect();
// Sign a PSBT
// ... create PSBT ...
const signedPsbt = await phantom.bitcoin.signPsbt(psbt);
For detailed examples, see Bitcoin documentation.
// Buy SOL with default amount
phantom.buy({ buy: "solana:101/nativeToken:501" });
// Buy SOL with specific amount
phantom.buy({ buy: "solana:101/nativeToken:501", amount: 10 });
// Swap SOL to USDC
phantom.swap({
sell: "solana:101/nativeToken:501",
buy: "solana:101/address:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
});
// Swap SOL to USDC with specific amount
phantom.swap({
sell: "solana:101/nativeToken:501",
buy: "solana:101/address:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
amount: "1000000000",
});