@phantom/phantom-openclaw-plugin
v0.2.1
Published
OpenClaw plugin that bridges tool calls to Phantom's MCP server for wallet operations.
Keywords
Readme
Phantom OpenClaw Plugin
⚠️ PREVIEW DISCLAIMER
This OpenClaw plugin is currently in preview and may break or change at any time without notice.
Always use a separate Phantom account specifically for testing with AI agents. These accounts should not contain significant assets.
Phantom makes no guarantees whatsoever around anything your agent may do using this plugin. Use at your own risk.
Direct integration with Phantom wallet for OpenClaw agents. This plugin wraps the Phantom MCP Server to provide seamless wallet operations including address retrieval, message signing, transaction signing, token transfers, and token swaps.
Overview
The Phantom OpenClaw Plugin provides native integration with Phantom wallet functionality. Instead of being a generic MCP bridge, it directly integrates the Phantom MCP Server tools as OpenClaw tools, providing a seamless experience for AI agents.
Quick Start
Get up and running in under 5 minutes:
Installation Checklist
[ ] Step 1: Get your App ID from phantom.com/portal
- Sign in with Gmail or Apple
- Click "Create App"
- Go to Dashboard → View App → Redirect URLs
- Add
http://localhost:8080/callbackas a redirect URL - Navigate to "Phantom Connect" tab
- Copy your App ID
[ ] Step 2: Install the plugin
openclaw plugins install @phantom/phantom-openclaw-plugin[ ] Step 3: Configure in
~/.openclaw/openclaw.json{ "plugins": { "enabled": true, "entries": { "phantom-openclaw-plugin": { "enabled": true, "config": { "PHANTOM_APP_ID": "your_app_id_from_portal" } } } } }[ ] Step 4: Restart OpenClaw
[ ] Step 5: Test with your agent
Ask: "What are my Phantom wallet addresses?"
⚠️ Important: Use the same email address for both the Phantom Portal and OpenClaw authentication!
See Prerequisites below for detailed setup instructions.
Features
- Direct Integration: Built on top of
@phantom/mcp-serverfor reliable wallet operations - Automatic Authentication: Handles OAuth flow and session management automatically
- Type-Safe: Full TypeScript support with proper type definitions
- Simple Setup: Minimal configuration - just enable the plugin and use
Prerequisites
Before using this plugin, you must obtain an App ID from the Phantom Portal:
- Visit the Phantom Portal: Go to phantom.com/portal
- Sign in: Use your Gmail or Apple account to sign in
- Create an App: Click "Create App" and fill in the required details
- Configure Redirect URL:
- Navigate to Dashboard → View App → Redirect URLs
- Add
http://localhost:8080/callbackas a redirect URL - This allows the OAuth callback to work correctly
- Get Your App ID: Navigate to the "Phantom Connect" tab to find your App ID
- Your app is automatically approved for development use
- Copy the App ID for the configuration below
Important: The email you use to sign in to the Phantom Portal must match the email you use when authenticating with the plugin. If these don't match, authentication will fail.
Installation
openclaw plugins install @phantom/phantom-openclaw-pluginConfiguration
Configure the plugin in your OpenClaw configuration file (~/.openclaw/openclaw.json):
{
"plugins": {
"enabled": true,
"entries": {
"phantom-openclaw-plugin": {
"enabled": true,
"config": {
"PHANTOM_APP_ID": "your_app_id_from_portal"
}
}
}
}
}Configuration Options
PHANTOM_APP_ID(required): Your App ID from the Phantom PortalPHANTOM_CLIENT_SECRET(optional): Client secret for confidential clientsPHANTOM_CALLBACK_PORT(optional): OAuth callback port (default: 8080)PHANTOM_MCP_DEBUG(optional): Enable debug logging (set to "1")
Note: Most users only need to provide PHANTOM_APP_ID. The other options are for advanced use cases.
Troubleshooting: DCR 404 During Startup
If startup fails with Failed to register OAuth client and status code 404, OpenClaw likely did not provide a valid PHANTOM_APP_ID to the plugin.
Verify your config is nested exactly at:
plugins.entries["phantom-openclaw-plugin"].config.PHANTOM_APP_ID
PHANTOM_APP_ID values are issued from phantom.com/portal.
Available Tools
The plugin exposes the following tools from the Phantom MCP Server:
get_connection_status
Lightweight local check of the wallet connection state. No network call — reads session state only. Use this first to confirm the user is authenticated.
Parameters: None
get_wallet_addresses
Retrieve wallet addresses for all supported blockchain chains (Solana, Ethereum, Bitcoin, Sui).
Parameters:
derivationIndex(number, optional): Derivation index for the wallet (default: 0)
Example:
{
"derivationIndex": 0
}get_token_balances
Get all fungible token balances for the authenticated wallet with live USD prices and 24h price change.
Parameters: None
send_solana_transaction
Sign and broadcast a pre-built Solana transaction. Accepts a base64-encoded serialized transaction.
Parameters:
transaction(string, required): Base64-encoded serialized Solana transactionnetworkId(string, optional): Solana network (default:"solana:mainnet")walletId(string, optional): Wallet ID (defaults to authenticated wallet)derivationIndex(number, optional): Derivation index (default: 0)
Example:
{
"transaction": "AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQABAgME..."
}sign_solana_message
Sign a UTF-8 message with the Solana wallet. Returns a base58-encoded signature.
Parameters:
message(string, required): The UTF-8 message to signnetworkId(string, required): Solana network (e.g.,"solana:mainnet")derivationIndex(number, optional): Derivation index (default: 0)
Example:
{
"message": "Verify ownership of my wallet",
"networkId": "solana:mainnet"
}send_evm_transaction
Sign and broadcast an EVM transaction. Nonce, gas, and gasPrice are optional — fetched from the network if omitted.
Parameters:
chainId(number, required): EVM chain ID (e.g.,1for Ethereum,8453for Base,137for Polygon,42161for Arbitrum,143for Monad)to(string, optional): Recipient addressvalue(string, optional): Amount in wei as hex (e.g.,"0x38D7EA4C68000")data(string, optional): Encoded calldata (0x-prefixed hex)gas,gasPrice,maxFeePerGas,maxPriorityFeePerGas,nonce(string, optional): All auto-fetched if omittedderivationIndex(number, optional): Derivation index (default: 0)
Example:
{
"chainId": 1,
"to": "0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E",
"value": "0x38D7EA4C68000"
}sign_evm_personal_message
Sign a UTF-8 message using EIP-191 personal_sign with the EVM wallet. Returns a hex-encoded signature.
Parameters:
message(string, required): The UTF-8 message to signchainId(number, required): EVM chain ID (e.g.,1for Ethereum,8453for Base,137for Polygon,143for Monad)derivationIndex(number, optional): Derivation index (default: 0)
Example:
{
"message": "Sign in to My App\nNonce: 12345",
"chainId": 1
}sign_evm_typed_data
Sign EIP-712 typed structured data. Used for DeFi permit signatures, order signing (0x, Seaport), and other structured off-chain approvals.
Parameters:
typedData(object, required): EIP-712 typed data withtypes,primaryType,domain, andmessagefieldschainId(number, required): EVM chain ID (e.g.,1for Ethereum,8453for Base,137for Polygon,143for Monad)derivationIndex(number, optional): Derivation index (default: 0)
transfer_tokens
Transfer native tokens or fungible tokens on Solana and EVM chains. Builds, signs, and sends the transaction immediately.
Parameters:
networkId(string, required): Network — Solana ("solana:mainnet","solana:devnet") or EVM ("eip155:1","eip155:8453","eip155:137","eip155:42161","eip155:143")to(string, required): Recipient — Solana base58 address or EVM0x-prefixed addressamount(string, required): Transfer amount (e.g., "0.1" or "1000000")amountUnit(string, optional):"ui"for human-readable units or"base"for atomic units. Default:"ui"tokenMint(string, optional): Token contract — Solana SPL mint or EVM ERC-200xaddress. Omit for native token.decimals(number, optional): Token decimals — optional on Solana (auto-fetched); required for ERC-20 withamountUnit: "ui"derivationIndex(number, optional): Derivation index (default: 0)createAssociatedTokenAccount(boolean, optional): Solana only — create destination ATA if missing (default: true)
Example (SOL):
{
"networkId": "solana:mainnet",
"to": "H8FpYTgx4Uy9aF9Nk9fCTqKKFLYQ9KfC6UJhMkMDzCBh",
"amount": "0.1",
"amountUnit": "ui"
}Example (ETH on Base):
{
"networkId": "eip155:8453",
"to": "0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E",
"amount": "0.01",
"amountUnit": "ui"
}Example (ERC-20 USDC on Ethereum):
{
"networkId": "eip155:1",
"to": "0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E",
"tokenMint": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"amount": "100",
"amountUnit": "ui",
"decimals": 6
}⚠️ Warning: This tool submits transactions immediately and irreversibly.
buy_token
Fetch a swap quote from Phantom's routing engine. Supports same-chain Solana, same-chain EVM, and cross-chain swaps between Solana and EVM chains. Optionally execute immediately.
Parameters:
sellChainId(string, optional): CAIP-2 chain for the sell token (default:"solana:mainnet"). Supported:solana:*andeip155:*(e.g."eip155:1","eip155:8453").buyChainId(string, optional): CAIP-2 chain for the buy token (defaults tosellChainId). Supported:solana:*andeip155:*. Set differently for cross-chain.sellTokenIsNative(boolean, optional): Sell the native token (default: true if sellTokenMint not provided)sellTokenMint(string, optional): Token to sell — Solana mint or EVM0xcontractbuyTokenIsNative(boolean, optional): Buy the native tokenbuyTokenMint(string, optional): Token to buy — Solana mint or EVM0xcontractamount(string, required): Swap amountamountUnit(string, optional):"ui"for token units or"base"for atomic units. Default:"base"slippageTolerance(number, optional): Slippage tolerance in percent (0-100)execute(boolean, optional): Sign and send the initiation transaction immediately. For cross-chain swaps (sellChainId≠buyChainId) this sends the source-chain transaction; the bridge completes the destination side automatically. Default: falsederivationIndex(number, optional): Derivation index (default: 0)quoteApiUrl(string, optional): Phantom-compatible quotes API override. Leave unset for normal use.
Example (Solana swap):
{
"sellChainId": "solana:mainnet",
"sellTokenIsNative": true,
"buyTokenMint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"amount": "0.5",
"amountUnit": "ui",
"slippageTolerance": 1,
"execute": true
}Example (EVM swap — ETH → USDC on Base):
{
"sellChainId": "eip155:8453",
"sellTokenIsNative": true,
"buyTokenMint": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"amount": "1000000000000000000",
"slippageTolerance": 1,
"execute": true
}⚠️ Warning: When execute: true, this tool submits transactions immediately and irreversibly.
Network IDs Reference
Network identifiers follow the CAIP-2/CAIP-10 format. Here are the supported networks:
Solana
- Mainnet:
solana:mainnet - Devnet:
solana:devnet - Testnet:
solana:testnet
Ethereum / EVM Chains
- Ethereum Mainnet:
eip155:1 - Ethereum Sepolia:
eip155:11155111 - Polygon Mainnet:
eip155:137 - Polygon Amoy:
eip155:80002 - Base Mainnet:
eip155:8453 - Base Sepolia:
eip155:84532 - Arbitrum One:
eip155:42161 - Arbitrum Sepolia:
eip155:421614
Bitcoin
- Mainnet:
bip122:000000000019d6689c085ae165831e93
Sui
- Mainnet:
sui:mainnet - Testnet:
sui:testnet
Authentication
On first use, the plugin will automatically initiate the Phantom OAuth flow:
- A browser window will open to
https://connect.phantom.app - Sign in with your Google or Apple account
- Important: Use the same email you used to sign in to the Phantom Portal
- Authorize the application
- The session will be saved for future use
Sessions are stored securely in ~/.phantom-mcp/session.json with restricted permissions and persist across restarts. The plugin uses stamper keypair authentication which doesn't expire.
Usage Examples
Check Wallet Addresses
User: What are my wallet addresses?
Agent: Let me check your Phantom wallet addresses.
[Calls get_wallet_addresses]Sign a Message
User: Sign this message: "Verify ownership of my wallet"
Agent: I'll sign that message for you using your Phantom wallet.
[Calls sign_message with the message]Sign a Transaction
User: Sign this Solana transaction: [transaction data]
Agent: I'll sign that transaction with your Phantom wallet.
[Calls sign_transaction with the transaction data]Architecture
phantom-openclaw-plugin/
├── src/
│ ├── index.ts # Plugin entry point
│ ├── session.ts # Session management wrapper
│ ├── client/
│ │ └── types.ts # OpenClaw API types
│ └── tools/
│ └── register-tools.ts # Tool registration logic
├── skills/
│ └── phantom-wallet/ # Wallet operations skill
└── openclaw.plugin.json # Plugin manifestDevelopment
For contributors or those testing unreleased versions.
Prerequisites
- Node.js 18+
- yarn
- Phantom wallet account for testing
- App ID from Phantom Portal
Local Installation
Clone and build the plugin:
# From the phantom-connect-sdk repository root yarn install yarn workspace @phantom/mcp-server build yarn workspace @phantom/phantom-openclaw-plugin buildInstall locally into OpenClaw:
openclaw plugins install -l ./packages/phantom-openclaw-pluginConfigure in
~/.openclaw/openclaw.json:{ "plugins": { "enabled": true, "entries": { "phantom-openclaw-plugin": { "enabled": true, "config": { "PHANTOM_APP_ID": "your_app_id_from_portal" } } } } }Verify installation:
openclaw plugins listTest with an agent:
openclaw chat > What are my Phantom wallet addresses?
Build Commands
# Build the plugin
yarn build
# Development mode with watch
yarn dev
# Type checking
yarn check-types
# Linting
yarn lint
# Format code
yarn prettierTroubleshooting
Plugin Not Loading
- Verify the plugin is enabled in
openclaw.json - Check that the build completed successfully (
dist/directory exists) - Ensure both the plugin and
@phantom/mcp-serverare built
Authentication Fails
- Check your internet connection
- Ensure you have a Phantom wallet account
- Try clearing the session cache:
rm -rf ~/.phantom-mcp/session.json - Check the console logs for specific error messages
Tool Execution Errors
- Ensure you're authenticated (the plugin will prompt if not)
- Verify the tool parameters match the expected schema
- Check that the Phantom wallet supports the requested operation
Related Projects
- @phantom/mcp-server - The underlying MCP server providing wallet functionality
- Phantom Wallet - The Phantom wallet application
Contributing
Contributions are welcome! Please ensure:
- TypeScript types are properly defined
- Code follows the existing style (run
yarn prettier) - All builds pass (
yarn build) - Type checking passes (
yarn check-types)
License
MIT
Support
For issues or questions:
- GitHub Issues: https://github.com/phantom/phantom-connect-sdk/issues
- Phantom Support: https://help.phantom.app
