
Security News
/Research
Wallet-Draining npm Package Impersonates Nodemailer to Hijack Crypto Transactions
Malicious npm package impersonates Nodemailer and drains wallets by hijacking crypto transactions across multiple blockchains.
@phantom/wallet-sdk
Advanced tools
The Phantom Wallet SDK allows you to integrate Phantom's wallet functionality directly into your web application.
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:
window.phantom
window.solana
for Solanawindow.ethereum
for EthereumThis 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:
window.myCustomWallet
instead of window.phantom
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:
When you set skipInjection
to true
:
const phantom = await createPhantom({ skipInjection: true });
The SDK will:
This is useful when you want to avoid any global namespace pollution and prefer to access all functionality through the returned Phantom 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
skipInjection: boolean; // Skip injecting providers into the window object
}>;
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",
});
FAQs
The Phantom Wallet SDK allows you to integrate Phantom's wallet functionality directly into your web application.
We found that @phantom/wallet-sdk demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 3 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
/Research
Malicious npm package impersonates Nodemailer and drains wallets by hijacking crypto transactions across multiple blockchains.
Security News
This episode explores the hard problem of reachability analysis, from static analysis limits to handling dynamic languages and massive dependency trees.
Security News
/Research
Malicious Nx npm versions stole secrets and wallet info using AI CLI tools; Socket’s AI scanner detected the supply chain attack and flagged the malware.