@phantom/phantom-openclaw-plugin 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +562 -0
- package/openclaw.plugin.json +73 -0
- package/package.json +58 -0
- package/skills/phantom-wallet/skill.md +281 -0
package/README.md
ADDED
|
@@ -0,0 +1,562 @@
|
|
|
1
|
+
# Phantom OpenClaw Plugin
|
|
2
|
+
|
|
3
|
+
> **⚠️ PREVIEW DISCLAIMER**
|
|
4
|
+
>
|
|
5
|
+
> This OpenClaw plugin is currently in **preview** and may break or change at any time without notice.
|
|
6
|
+
>
|
|
7
|
+
> **Always use a separate Phantom account specifically for testing with AI agents. These accounts should not contain significant assets.**
|
|
8
|
+
>
|
|
9
|
+
> **Phantom makes no guarantees whatsoever around anything your agent may do using this plugin.** Use at your own risk.
|
|
10
|
+
|
|
11
|
+
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.
|
|
12
|
+
|
|
13
|
+
## Overview
|
|
14
|
+
|
|
15
|
+
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.
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
Get up and running in under 5 minutes:
|
|
20
|
+
|
|
21
|
+
### Installation Checklist
|
|
22
|
+
|
|
23
|
+
- [ ] **Step 1:** Get your App ID from [phantom.com/portal](https://phantom.com/portal)
|
|
24
|
+
- Sign in with Gmail or Apple
|
|
25
|
+
- Click "Create App"
|
|
26
|
+
- Go to Dashboard → View App → Redirect URLs
|
|
27
|
+
- Add `http://localhost:8080/callback` as a redirect URL
|
|
28
|
+
- Navigate to "Phantom Connect" tab
|
|
29
|
+
- Copy your App ID
|
|
30
|
+
|
|
31
|
+
- [ ] **Step 2:** Install the plugin
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
openclaw plugins install @phantom/phantom-openclaw-plugin
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
- [ ] **Step 3:** Configure in `~/.openclaw/openclaw.json`
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
{
|
|
41
|
+
"plugins": {
|
|
42
|
+
"enabled": true,
|
|
43
|
+
"entries": {
|
|
44
|
+
"phantom-openclaw-plugin": {
|
|
45
|
+
"enabled": true,
|
|
46
|
+
"config": {
|
|
47
|
+
"PHANTOM_APP_ID": "your_app_id_from_portal"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
- [ ] **Step 4:** Restart OpenClaw
|
|
56
|
+
|
|
57
|
+
- [ ] **Step 5:** Test with your agent
|
|
58
|
+
```text
|
|
59
|
+
Ask: "What are my Phantom wallet addresses?"
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**⚠️ Important:** Use the same email address for both the Phantom Portal and OpenClaw authentication!
|
|
63
|
+
|
|
64
|
+
See [Prerequisites](#prerequisites) below for detailed setup instructions.
|
|
65
|
+
|
|
66
|
+
## Features
|
|
67
|
+
|
|
68
|
+
- **Direct Integration**: Built on top of `@phantom/mcp-server` for reliable wallet operations
|
|
69
|
+
- **Automatic Authentication**: Handles OAuth flow and session management automatically
|
|
70
|
+
- **Type-Safe**: Full TypeScript support with proper type definitions
|
|
71
|
+
- **Simple Setup**: Minimal configuration - just enable the plugin and use
|
|
72
|
+
|
|
73
|
+
## Prerequisites
|
|
74
|
+
|
|
75
|
+
Before using this plugin, you **must** obtain an App ID from the Phantom Portal:
|
|
76
|
+
|
|
77
|
+
1. **Visit the Phantom Portal**: Go to [phantom.com/portal](https://phantom.com/portal)
|
|
78
|
+
2. **Sign in**: Use your Gmail or Apple account to sign in
|
|
79
|
+
3. **Create an App**: Click "Create App" and fill in the required details
|
|
80
|
+
4. **Configure Redirect URL**:
|
|
81
|
+
- Navigate to Dashboard → View App → Redirect URLs
|
|
82
|
+
- Add `http://localhost:8080/callback` as a redirect URL
|
|
83
|
+
- This allows the OAuth callback to work correctly
|
|
84
|
+
5. **Get Your App ID**: Navigate to the "Phantom Connect" tab to find your App ID
|
|
85
|
+
- Your app is automatically approved for development use
|
|
86
|
+
- Copy the App ID for the configuration below
|
|
87
|
+
|
|
88
|
+
**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.
|
|
89
|
+
|
|
90
|
+
## Installation
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
openclaw plugins install @phantom/phantom-openclaw-plugin
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Configuration
|
|
97
|
+
|
|
98
|
+
Configure the plugin in your OpenClaw configuration file (`~/.openclaw/openclaw.json`):
|
|
99
|
+
|
|
100
|
+
```json
|
|
101
|
+
{
|
|
102
|
+
"plugins": {
|
|
103
|
+
"enabled": true,
|
|
104
|
+
"entries": {
|
|
105
|
+
"phantom-openclaw-plugin": {
|
|
106
|
+
"enabled": true,
|
|
107
|
+
"config": {
|
|
108
|
+
"PHANTOM_APP_ID": "your_app_id_from_portal"
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Configuration Options
|
|
117
|
+
|
|
118
|
+
- **`PHANTOM_APP_ID`** (required): Your App ID from the Phantom Portal
|
|
119
|
+
- **`PHANTOM_CLIENT_SECRET`** (optional): Client secret for confidential clients
|
|
120
|
+
- **`PHANTOM_CALLBACK_PORT`** (optional): OAuth callback port (default: 8080)
|
|
121
|
+
- **`PHANTOM_MCP_DEBUG`** (optional): Enable debug logging (set to "1")
|
|
122
|
+
|
|
123
|
+
**Note:** Most users only need to provide `PHANTOM_APP_ID`. The other options are for advanced use cases.
|
|
124
|
+
|
|
125
|
+
### Troubleshooting: `DCR 404` During Startup
|
|
126
|
+
|
|
127
|
+
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.
|
|
128
|
+
|
|
129
|
+
Verify your config is nested exactly at:
|
|
130
|
+
|
|
131
|
+
`plugins.entries["phantom-openclaw-plugin"].config.PHANTOM_APP_ID`
|
|
132
|
+
|
|
133
|
+
`PHANTOM_APP_ID` values are issued from [phantom.com/portal](https://phantom.com/portal).
|
|
134
|
+
|
|
135
|
+
## Available Tools
|
|
136
|
+
|
|
137
|
+
The plugin exposes the following tools from the Phantom MCP Server:
|
|
138
|
+
|
|
139
|
+
### `get_connection_status`
|
|
140
|
+
|
|
141
|
+
Lightweight local check of the wallet connection state. No network call — reads session state only. Use this first to confirm the user is authenticated.
|
|
142
|
+
|
|
143
|
+
**Parameters:** None
|
|
144
|
+
|
|
145
|
+
### `get_wallet_addresses`
|
|
146
|
+
|
|
147
|
+
Retrieve wallet addresses for all supported blockchain chains (Solana, Ethereum, Bitcoin, Sui).
|
|
148
|
+
|
|
149
|
+
**Parameters:**
|
|
150
|
+
|
|
151
|
+
- `derivationIndex` (number, optional): Derivation index for the wallet (default: 0)
|
|
152
|
+
|
|
153
|
+
**Example:**
|
|
154
|
+
|
|
155
|
+
```json
|
|
156
|
+
{
|
|
157
|
+
"derivationIndex": 0
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### `get_token_balances`
|
|
162
|
+
|
|
163
|
+
Get all fungible token balances for the authenticated wallet with live USD prices and 24h price change.
|
|
164
|
+
|
|
165
|
+
**Parameters:** None
|
|
166
|
+
|
|
167
|
+
### `send_solana_transaction`
|
|
168
|
+
|
|
169
|
+
Sign and broadcast a pre-built Solana transaction. Accepts a base64-encoded serialized transaction.
|
|
170
|
+
|
|
171
|
+
**Parameters:**
|
|
172
|
+
|
|
173
|
+
- `transaction` (string, required): Base64-encoded serialized Solana transaction
|
|
174
|
+
- `networkId` (string, optional): Solana network (default: `"solana:mainnet"`)
|
|
175
|
+
- `walletId` (string, optional): Wallet ID (defaults to authenticated wallet)
|
|
176
|
+
- `derivationIndex` (number, optional): Derivation index (default: 0)
|
|
177
|
+
|
|
178
|
+
**Example:**
|
|
179
|
+
|
|
180
|
+
```json
|
|
181
|
+
{
|
|
182
|
+
"transaction": "AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQABAgME..."
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### `sign_solana_message`
|
|
187
|
+
|
|
188
|
+
Sign a UTF-8 message with the Solana wallet. Returns a base58-encoded signature.
|
|
189
|
+
|
|
190
|
+
**Parameters:**
|
|
191
|
+
|
|
192
|
+
- `message` (string, required): The UTF-8 message to sign
|
|
193
|
+
- `networkId` (string, required): Solana network (e.g., `"solana:mainnet"`)
|
|
194
|
+
- `derivationIndex` (number, optional): Derivation index (default: 0)
|
|
195
|
+
|
|
196
|
+
**Example:**
|
|
197
|
+
|
|
198
|
+
```json
|
|
199
|
+
{
|
|
200
|
+
"message": "Verify ownership of my wallet",
|
|
201
|
+
"networkId": "solana:mainnet"
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### `send_evm_transaction`
|
|
206
|
+
|
|
207
|
+
Sign and broadcast an EVM transaction. Nonce, gas, and gasPrice are optional — fetched from the network if omitted.
|
|
208
|
+
|
|
209
|
+
**Parameters:**
|
|
210
|
+
|
|
211
|
+
- `chainId` (number, required): EVM chain ID (e.g., `1` for Ethereum, `8453` for Base, `137` for Polygon, `42161` for Arbitrum, `143` for Monad)
|
|
212
|
+
- `to` (string, optional): Recipient address
|
|
213
|
+
- `value` (string, optional): Amount in wei as hex (e.g., `"0x38D7EA4C68000"`)
|
|
214
|
+
- `data` (string, optional): Encoded calldata (0x-prefixed hex)
|
|
215
|
+
- `gas`, `gasPrice`, `maxFeePerGas`, `maxPriorityFeePerGas`, `nonce` (string, optional): All auto-fetched if omitted
|
|
216
|
+
- `derivationIndex` (number, optional): Derivation index (default: 0)
|
|
217
|
+
|
|
218
|
+
**Example:**
|
|
219
|
+
|
|
220
|
+
```json
|
|
221
|
+
{
|
|
222
|
+
"chainId": 1,
|
|
223
|
+
"to": "0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E",
|
|
224
|
+
"value": "0x38D7EA4C68000"
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### `sign_evm_personal_message`
|
|
229
|
+
|
|
230
|
+
Sign a UTF-8 message using EIP-191 `personal_sign` with the EVM wallet. Returns a hex-encoded signature.
|
|
231
|
+
|
|
232
|
+
**Parameters:**
|
|
233
|
+
|
|
234
|
+
- `message` (string, required): The UTF-8 message to sign
|
|
235
|
+
- `chainId` (number, required): EVM chain ID (e.g., `1` for Ethereum, `8453` for Base, `137` for Polygon, `143` for Monad)
|
|
236
|
+
- `derivationIndex` (number, optional): Derivation index (default: 0)
|
|
237
|
+
|
|
238
|
+
**Example:**
|
|
239
|
+
|
|
240
|
+
```json
|
|
241
|
+
{
|
|
242
|
+
"message": "Sign in to My App\nNonce: 12345",
|
|
243
|
+
"chainId": 1
|
|
244
|
+
}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### `sign_evm_typed_data`
|
|
248
|
+
|
|
249
|
+
Sign EIP-712 typed structured data. Used for DeFi permit signatures, order signing (0x, Seaport), and other structured off-chain approvals.
|
|
250
|
+
|
|
251
|
+
**Parameters:**
|
|
252
|
+
|
|
253
|
+
- `typedData` (object, required): EIP-712 typed data with `types`, `primaryType`, `domain`, and `message` fields
|
|
254
|
+
- `chainId` (number, required): EVM chain ID (e.g., `1` for Ethereum, `8453` for Base, `137` for Polygon, `143` for Monad)
|
|
255
|
+
- `derivationIndex` (number, optional): Derivation index (default: 0)
|
|
256
|
+
|
|
257
|
+
### `transfer_tokens`
|
|
258
|
+
|
|
259
|
+
Transfer native tokens or fungible tokens on Solana and EVM chains. Builds, signs, and sends the transaction immediately.
|
|
260
|
+
|
|
261
|
+
**Parameters:**
|
|
262
|
+
|
|
263
|
+
- `networkId` (string, required): Network — Solana (`"solana:mainnet"`, `"solana:devnet"`) or EVM (`"eip155:1"`, `"eip155:8453"`, `"eip155:137"`, `"eip155:42161"`, `"eip155:143"`)
|
|
264
|
+
- `to` (string, required): Recipient — Solana base58 address or EVM `0x`-prefixed address
|
|
265
|
+
- `amount` (string, required): Transfer amount (e.g., "0.1" or "1000000")
|
|
266
|
+
- `amountUnit` (string, optional): `"ui"` for human-readable units or `"base"` for atomic units. Default: `"ui"`
|
|
267
|
+
- `tokenMint` (string, optional): Token contract — Solana SPL mint or EVM ERC-20 `0x` address. Omit for native token.
|
|
268
|
+
- `decimals` (number, optional): Token decimals — optional on Solana (auto-fetched); required for ERC-20 with `amountUnit: "ui"`
|
|
269
|
+
- `derivationIndex` (number, optional): Derivation index (default: 0)
|
|
270
|
+
- `createAssociatedTokenAccount` (boolean, optional): Solana only — create destination ATA if missing (default: true)
|
|
271
|
+
|
|
272
|
+
**Example (SOL):**
|
|
273
|
+
|
|
274
|
+
```json
|
|
275
|
+
{
|
|
276
|
+
"networkId": "solana:mainnet",
|
|
277
|
+
"to": "H8FpYTgx4Uy9aF9Nk9fCTqKKFLYQ9KfC6UJhMkMDzCBh",
|
|
278
|
+
"amount": "0.1",
|
|
279
|
+
"amountUnit": "ui"
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
**Example (ETH on Base):**
|
|
284
|
+
|
|
285
|
+
```json
|
|
286
|
+
{
|
|
287
|
+
"networkId": "eip155:8453",
|
|
288
|
+
"to": "0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E",
|
|
289
|
+
"amount": "0.01",
|
|
290
|
+
"amountUnit": "ui"
|
|
291
|
+
}
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
**Example (ERC-20 USDC on Ethereum):**
|
|
295
|
+
|
|
296
|
+
```json
|
|
297
|
+
{
|
|
298
|
+
"networkId": "eip155:1",
|
|
299
|
+
"to": "0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E",
|
|
300
|
+
"tokenMint": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
|
301
|
+
"amount": "100",
|
|
302
|
+
"amountUnit": "ui",
|
|
303
|
+
"decimals": 6
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
**⚠️ Warning:** This tool submits transactions immediately and irreversibly.
|
|
308
|
+
|
|
309
|
+
### `buy_token`
|
|
310
|
+
|
|
311
|
+
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.
|
|
312
|
+
|
|
313
|
+
**Parameters:**
|
|
314
|
+
|
|
315
|
+
- `sellChainId` (string, optional): CAIP-2 chain for the sell token (default: `"solana:mainnet"`). Supported: `solana:*` and `eip155:*` (e.g. `"eip155:1"`, `"eip155:8453"`).
|
|
316
|
+
- `buyChainId` (string, optional): CAIP-2 chain for the buy token (defaults to `sellChainId`). Supported: `solana:*` and `eip155:*`. Set differently for cross-chain.
|
|
317
|
+
- `sellTokenIsNative` (boolean, optional): Sell the native token (default: true if sellTokenMint not provided)
|
|
318
|
+
- `sellTokenMint` (string, optional): Token to sell — Solana mint or EVM `0x` contract
|
|
319
|
+
- `buyTokenIsNative` (boolean, optional): Buy the native token
|
|
320
|
+
- `buyTokenMint` (string, optional): Token to buy — Solana mint or EVM `0x` contract
|
|
321
|
+
- `amount` (string, required): Swap amount
|
|
322
|
+
- `amountUnit` (string, optional): `"ui"` for token units or `"base"` for atomic units. Default: `"base"`
|
|
323
|
+
- `slippageTolerance` (number, optional): Slippage tolerance in percent (0-100)
|
|
324
|
+
- `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: false
|
|
325
|
+
- `derivationIndex` (number, optional): Derivation index (default: 0)
|
|
326
|
+
- `quoteApiUrl` (string, optional): Phantom-compatible quotes API override. Leave unset for normal use.
|
|
327
|
+
|
|
328
|
+
**Example (Solana swap):**
|
|
329
|
+
|
|
330
|
+
```json
|
|
331
|
+
{
|
|
332
|
+
"sellChainId": "solana:mainnet",
|
|
333
|
+
"sellTokenIsNative": true,
|
|
334
|
+
"buyTokenMint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
|
|
335
|
+
"amount": "0.5",
|
|
336
|
+
"amountUnit": "ui",
|
|
337
|
+
"slippageTolerance": 1,
|
|
338
|
+
"execute": true
|
|
339
|
+
}
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
**Example (EVM swap — ETH → USDC on Base):**
|
|
343
|
+
|
|
344
|
+
```json
|
|
345
|
+
{
|
|
346
|
+
"sellChainId": "eip155:8453",
|
|
347
|
+
"sellTokenIsNative": true,
|
|
348
|
+
"buyTokenMint": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
349
|
+
"amount": "1000000000000000000",
|
|
350
|
+
"slippageTolerance": 1,
|
|
351
|
+
"execute": true
|
|
352
|
+
}
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
**⚠️ Warning:** When `execute: true`, this tool submits transactions immediately and irreversibly.
|
|
356
|
+
|
|
357
|
+
## Network IDs Reference
|
|
358
|
+
|
|
359
|
+
Network identifiers follow the CAIP-2/CAIP-10 format. Here are the supported networks:
|
|
360
|
+
|
|
361
|
+
### Solana
|
|
362
|
+
|
|
363
|
+
- Mainnet: `solana:mainnet`
|
|
364
|
+
- Devnet: `solana:devnet`
|
|
365
|
+
- Testnet: `solana:testnet`
|
|
366
|
+
|
|
367
|
+
### Ethereum / EVM Chains
|
|
368
|
+
|
|
369
|
+
- Ethereum Mainnet: `eip155:1`
|
|
370
|
+
- Ethereum Sepolia: `eip155:11155111`
|
|
371
|
+
- Polygon Mainnet: `eip155:137`
|
|
372
|
+
- Polygon Amoy: `eip155:80002`
|
|
373
|
+
- Base Mainnet: `eip155:8453`
|
|
374
|
+
- Base Sepolia: `eip155:84532`
|
|
375
|
+
- Arbitrum One: `eip155:42161`
|
|
376
|
+
- Arbitrum Sepolia: `eip155:421614`
|
|
377
|
+
|
|
378
|
+
### Bitcoin
|
|
379
|
+
|
|
380
|
+
- Mainnet: `bip122:000000000019d6689c085ae165831e93`
|
|
381
|
+
|
|
382
|
+
### Sui
|
|
383
|
+
|
|
384
|
+
- Mainnet: `sui:mainnet`
|
|
385
|
+
- Testnet: `sui:testnet`
|
|
386
|
+
|
|
387
|
+
## Authentication
|
|
388
|
+
|
|
389
|
+
On first use, the plugin will automatically initiate the Phantom OAuth flow:
|
|
390
|
+
|
|
391
|
+
1. A browser window will open to `https://connect.phantom.app`
|
|
392
|
+
2. Sign in with your Google or Apple account
|
|
393
|
+
- **Important:** Use the same email you used to sign in to the Phantom Portal
|
|
394
|
+
3. Authorize the application
|
|
395
|
+
4. The session will be saved for future use
|
|
396
|
+
|
|
397
|
+
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.
|
|
398
|
+
|
|
399
|
+
## Usage Examples
|
|
400
|
+
|
|
401
|
+
### Check Wallet Addresses
|
|
402
|
+
|
|
403
|
+
```text
|
|
404
|
+
User: What are my wallet addresses?
|
|
405
|
+
Agent: Let me check your Phantom wallet addresses.
|
|
406
|
+
[Calls get_wallet_addresses]
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
### Sign a Message
|
|
410
|
+
|
|
411
|
+
```text
|
|
412
|
+
User: Sign this message: "Verify ownership of my wallet"
|
|
413
|
+
Agent: I'll sign that message for you using your Phantom wallet.
|
|
414
|
+
[Calls sign_message with the message]
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
### Sign a Transaction
|
|
418
|
+
|
|
419
|
+
```text
|
|
420
|
+
User: Sign this Solana transaction: [transaction data]
|
|
421
|
+
Agent: I'll sign that transaction with your Phantom wallet.
|
|
422
|
+
[Calls sign_transaction with the transaction data]
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
## Architecture
|
|
426
|
+
|
|
427
|
+
```text
|
|
428
|
+
phantom-openclaw-plugin/
|
|
429
|
+
├── src/
|
|
430
|
+
│ ├── index.ts # Plugin entry point
|
|
431
|
+
│ ├── session.ts # Session management wrapper
|
|
432
|
+
│ ├── client/
|
|
433
|
+
│ │ └── types.ts # OpenClaw API types
|
|
434
|
+
│ └── tools/
|
|
435
|
+
│ └── register-tools.ts # Tool registration logic
|
|
436
|
+
├── skills/
|
|
437
|
+
│ └── phantom-wallet/ # Wallet operations skill
|
|
438
|
+
└── openclaw.plugin.json # Plugin manifest
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
## Development
|
|
442
|
+
|
|
443
|
+
For contributors or those testing unreleased versions.
|
|
444
|
+
|
|
445
|
+
### Prerequisites
|
|
446
|
+
|
|
447
|
+
- Node.js 18+
|
|
448
|
+
- yarn
|
|
449
|
+
- Phantom wallet account for testing
|
|
450
|
+
- App ID from [Phantom Portal](https://phantom.com/portal)
|
|
451
|
+
|
|
452
|
+
### Local Installation
|
|
453
|
+
|
|
454
|
+
1. Clone and build the plugin:
|
|
455
|
+
|
|
456
|
+
```bash
|
|
457
|
+
# From the phantom-connect-sdk repository root
|
|
458
|
+
yarn install
|
|
459
|
+
yarn workspace @phantom/mcp-server build
|
|
460
|
+
yarn workspace @phantom/phantom-openclaw-plugin build
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
2. Install locally into OpenClaw:
|
|
464
|
+
|
|
465
|
+
```bash
|
|
466
|
+
openclaw plugins install -l ./packages/phantom-openclaw-plugin
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
3. Configure in `~/.openclaw/openclaw.json`:
|
|
470
|
+
|
|
471
|
+
```json
|
|
472
|
+
{
|
|
473
|
+
"plugins": {
|
|
474
|
+
"enabled": true,
|
|
475
|
+
"entries": {
|
|
476
|
+
"phantom-openclaw-plugin": {
|
|
477
|
+
"enabled": true,
|
|
478
|
+
"config": {
|
|
479
|
+
"PHANTOM_APP_ID": "your_app_id_from_portal"
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
4. Verify installation:
|
|
488
|
+
|
|
489
|
+
```bash
|
|
490
|
+
openclaw plugins list
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
5. Test with an agent:
|
|
494
|
+
```bash
|
|
495
|
+
openclaw chat
|
|
496
|
+
> What are my Phantom wallet addresses?
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
### Build Commands
|
|
500
|
+
|
|
501
|
+
```bash
|
|
502
|
+
# Build the plugin
|
|
503
|
+
yarn build
|
|
504
|
+
|
|
505
|
+
# Development mode with watch
|
|
506
|
+
yarn dev
|
|
507
|
+
|
|
508
|
+
# Type checking
|
|
509
|
+
yarn check-types
|
|
510
|
+
|
|
511
|
+
# Linting
|
|
512
|
+
yarn lint
|
|
513
|
+
|
|
514
|
+
# Format code
|
|
515
|
+
yarn prettier
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
## Troubleshooting
|
|
519
|
+
|
|
520
|
+
### Plugin Not Loading
|
|
521
|
+
|
|
522
|
+
- Verify the plugin is enabled in `openclaw.json`
|
|
523
|
+
- Check that the build completed successfully (`dist/` directory exists)
|
|
524
|
+
- Ensure both the plugin and `@phantom/mcp-server` are built
|
|
525
|
+
|
|
526
|
+
### Authentication Fails
|
|
527
|
+
|
|
528
|
+
- Check your internet connection
|
|
529
|
+
- Ensure you have a Phantom wallet account
|
|
530
|
+
- Try clearing the session cache: `rm -rf ~/.phantom-mcp/session.json`
|
|
531
|
+
- Check the console logs for specific error messages
|
|
532
|
+
|
|
533
|
+
### Tool Execution Errors
|
|
534
|
+
|
|
535
|
+
- Ensure you're authenticated (the plugin will prompt if not)
|
|
536
|
+
- Verify the tool parameters match the expected schema
|
|
537
|
+
- Check that the Phantom wallet supports the requested operation
|
|
538
|
+
|
|
539
|
+
## Related Projects
|
|
540
|
+
|
|
541
|
+
- [@phantom/mcp-server](../mcp-server) - The underlying MCP server providing wallet functionality
|
|
542
|
+
- [Phantom Wallet](https://phantom.app) - The Phantom wallet application
|
|
543
|
+
|
|
544
|
+
## Contributing
|
|
545
|
+
|
|
546
|
+
Contributions are welcome! Please ensure:
|
|
547
|
+
|
|
548
|
+
- TypeScript types are properly defined
|
|
549
|
+
- Code follows the existing style (run `yarn prettier`)
|
|
550
|
+
- All builds pass (`yarn build`)
|
|
551
|
+
- Type checking passes (`yarn check-types`)
|
|
552
|
+
|
|
553
|
+
## License
|
|
554
|
+
|
|
555
|
+
MIT
|
|
556
|
+
|
|
557
|
+
## Support
|
|
558
|
+
|
|
559
|
+
For issues or questions:
|
|
560
|
+
|
|
561
|
+
- GitHub Issues: https://github.com/phantom/phantom-connect-sdk/issues
|
|
562
|
+
- Phantom Support: https://help.phantom.app
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "phantom-openclaw-plugin",
|
|
3
|
+
"name": "Phantom Wallet",
|
|
4
|
+
"description": "Phantom embedded wallet for AI agents — check balances, transfer tokens, swap on Solana, and sign transactions and messages. Powered by Phantom, the leading multi-chain crypto wallet.",
|
|
5
|
+
"skills": ["./skills"],
|
|
6
|
+
"configSchema": {
|
|
7
|
+
"type": "object",
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"PHANTOM_APP_ID": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"minLength": 1,
|
|
13
|
+
"description": "Application ID from Phantom Portal."
|
|
14
|
+
},
|
|
15
|
+
"PHANTOM_CLIENT_ID": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"minLength": 1,
|
|
18
|
+
"description": "Legacy alias for PHANTOM_APP_ID."
|
|
19
|
+
},
|
|
20
|
+
"PHANTOM_CLIENT_SECRET": {
|
|
21
|
+
"type": "string",
|
|
22
|
+
"minLength": 1,
|
|
23
|
+
"description": "Optional client secret for confidential clients."
|
|
24
|
+
},
|
|
25
|
+
"PHANTOM_AUTH_BASE_URL": {
|
|
26
|
+
"type": "string",
|
|
27
|
+
"minLength": 1
|
|
28
|
+
},
|
|
29
|
+
"PHANTOM_CONNECT_BASE_URL": {
|
|
30
|
+
"type": "string",
|
|
31
|
+
"minLength": 1
|
|
32
|
+
},
|
|
33
|
+
"PHANTOM_API_BASE_URL": {
|
|
34
|
+
"type": "string",
|
|
35
|
+
"minLength": 1
|
|
36
|
+
},
|
|
37
|
+
"PHANTOM_CALLBACK_PORT": {
|
|
38
|
+
"type": "integer",
|
|
39
|
+
"minimum": 1,
|
|
40
|
+
"maximum": 65535
|
|
41
|
+
},
|
|
42
|
+
"PHANTOM_CALLBACK_PATH": {
|
|
43
|
+
"type": "string",
|
|
44
|
+
"minLength": 1
|
|
45
|
+
},
|
|
46
|
+
"PHANTOM_SSO_PROVIDER": {
|
|
47
|
+
"type": "string",
|
|
48
|
+
"minLength": 1
|
|
49
|
+
},
|
|
50
|
+
"PHANTOM_MCP_DEBUG": {
|
|
51
|
+
"type": "string"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
"uiHints": {
|
|
56
|
+
"PHANTOM_APP_ID": {
|
|
57
|
+
"label": "Phantom App ID",
|
|
58
|
+
"placeholder": "your_app_id_from_portal"
|
|
59
|
+
},
|
|
60
|
+
"PHANTOM_CLIENT_SECRET": {
|
|
61
|
+
"label": "Phantom Client Secret",
|
|
62
|
+
"sensitive": true
|
|
63
|
+
},
|
|
64
|
+
"PHANTOM_CALLBACK_PORT": {
|
|
65
|
+
"label": "Callback Port",
|
|
66
|
+
"placeholder": "8080"
|
|
67
|
+
},
|
|
68
|
+
"PHANTOM_MCP_DEBUG": {
|
|
69
|
+
"label": "Enable Debug Logging",
|
|
70
|
+
"placeholder": "1"
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@phantom/phantom-openclaw-plugin",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "OpenClaw plugin that bridges tool calls to Phantom's MCP server for wallet operations.",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/phantom/phantom-connect-sdk",
|
|
8
|
+
"directory": "packages/phantom-openclaw-plugin"
|
|
9
|
+
},
|
|
10
|
+
"main": "dist/index.js",
|
|
11
|
+
"module": "dist/index.mjs",
|
|
12
|
+
"types": "dist/index.d.ts",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"import": "./dist/index.mjs",
|
|
16
|
+
"require": "./dist/index.js",
|
|
17
|
+
"types": "./dist/index.d.ts"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"openclaw": {
|
|
21
|
+
"extensions": [
|
|
22
|
+
"./dist/index.js"
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
"scripts": {
|
|
26
|
+
"?pack-release": "When https://github.com/changesets/changesets/issues/432 has a solution we can remove this trick",
|
|
27
|
+
"pack-release": "rimraf ./_release && yarn pack && mkdir ./_release && tar zxvf ./package.tgz --directory ./_release && rm ./package.tgz",
|
|
28
|
+
"build": "rimraf ./dist && tsup",
|
|
29
|
+
"dev": "tsup --watch",
|
|
30
|
+
"clean": "rimraf dist",
|
|
31
|
+
"test": "jest",
|
|
32
|
+
"test:watch": "jest --watch",
|
|
33
|
+
"lint": "tsc --noEmit && eslint --cache . --ext .ts,.tsx",
|
|
34
|
+
"check-types": "tsc --noEmit",
|
|
35
|
+
"prettier": "prettier --write \"src/**/*.{ts,tsx}\""
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@types/node": "^20.11.0",
|
|
39
|
+
"eslint": "8.53.0",
|
|
40
|
+
"prettier": "^3.5.2",
|
|
41
|
+
"rimraf": "^6.0.1",
|
|
42
|
+
"tsup": "^6.7.0",
|
|
43
|
+
"typescript": "^5.0.4"
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"@phantom/mcp-server": "workspace:^",
|
|
47
|
+
"@sinclair/typebox": "^0.32.0"
|
|
48
|
+
},
|
|
49
|
+
"files": [
|
|
50
|
+
"dist",
|
|
51
|
+
"openclaw.plugin.json",
|
|
52
|
+
"skills",
|
|
53
|
+
"README.md"
|
|
54
|
+
],
|
|
55
|
+
"publishConfig": {
|
|
56
|
+
"directory": "_release/package"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: phantom-wallet
|
|
3
|
+
description: Interact with Phantom wallet - check balances, get addresses, transfer tokens, swap, and sign messages and transactions
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
emoji: 👻
|
|
6
|
+
homepage: https://phantom.com
|
|
7
|
+
always: false
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Phantom Wallet Operations
|
|
11
|
+
|
|
12
|
+
You are helping the user interact with their Phantom wallet. You have direct access to Phantom wallet tools integrated from the Phantom MCP Server.
|
|
13
|
+
|
|
14
|
+
## Available Tools
|
|
15
|
+
|
|
16
|
+
### get_connection_status
|
|
17
|
+
|
|
18
|
+
Lightweight local check of the wallet connection state. No network call — reads session state only. Use this first to confirm the user is authenticated.
|
|
19
|
+
|
|
20
|
+
**Parameters:** None
|
|
21
|
+
|
|
22
|
+
### get_wallet_addresses
|
|
23
|
+
|
|
24
|
+
Retrieve wallet addresses for all supported blockchain chains (Solana, Ethereum, Bitcoin, Sui).
|
|
25
|
+
|
|
26
|
+
**Parameters:**
|
|
27
|
+
|
|
28
|
+
```json
|
|
29
|
+
{
|
|
30
|
+
"derivationIndex": 0
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### get_token_balances
|
|
35
|
+
|
|
36
|
+
Get all fungible token balances for the authenticated wallet with live USD prices. Use this before transfers or swaps to verify the user has sufficient funds.
|
|
37
|
+
|
|
38
|
+
**Parameters:** None
|
|
39
|
+
|
|
40
|
+
### send_solana_transaction
|
|
41
|
+
|
|
42
|
+
Sign and broadcast a pre-built Solana transaction. **Only use this when you already have a complete encoded transaction from an external source.** For transfers use `transfer_tokens`; for swaps use `buy_token`.
|
|
43
|
+
|
|
44
|
+
**Important:** This submits the transaction to the network immediately — it is irreversible.
|
|
45
|
+
|
|
46
|
+
**Parameters:**
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
{
|
|
50
|
+
"transaction": "base64-encoded-solana-transaction",
|
|
51
|
+
"networkId": "solana:mainnet",
|
|
52
|
+
"derivationIndex": 0
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### sign_solana_message
|
|
57
|
+
|
|
58
|
+
Sign a UTF-8 message with the Solana wallet. Returns a base58-encoded signature. Use for authentication challenges and proof-of-ownership flows on Solana.
|
|
59
|
+
|
|
60
|
+
**Parameters:**
|
|
61
|
+
|
|
62
|
+
```json
|
|
63
|
+
{
|
|
64
|
+
"message": "Message to sign",
|
|
65
|
+
"networkId": "solana:mainnet",
|
|
66
|
+
"derivationIndex": 0
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### send_evm_transaction
|
|
71
|
+
|
|
72
|
+
Sign and broadcast an EVM transaction using the authenticated wallet. Pass the fields you have — `nonce`, `gas`, and `gasPrice` are fetched from the network automatically if omitted. Use this when you have a transaction object from an external source (e.g. a DeFi aggregator) or when constructing a transaction directly.
|
|
73
|
+
|
|
74
|
+
**Important:** This submits the transaction to the network immediately — it is irreversible.
|
|
75
|
+
|
|
76
|
+
**Parameters:**
|
|
77
|
+
|
|
78
|
+
```json
|
|
79
|
+
{
|
|
80
|
+
"chainId": 1,
|
|
81
|
+
"to": "0xRecipientAddress",
|
|
82
|
+
"value": "0x38D7EA4C68000",
|
|
83
|
+
"derivationIndex": 0
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### sign_evm_personal_message
|
|
88
|
+
|
|
89
|
+
Sign a UTF-8 message using EIP-191 `personal_sign` with the EVM wallet. Returns a hex-encoded signature. Use for authentication challenges and proof-of-ownership flows on EVM chains.
|
|
90
|
+
|
|
91
|
+
**Parameters:**
|
|
92
|
+
|
|
93
|
+
```json
|
|
94
|
+
{
|
|
95
|
+
"message": "Message to sign",
|
|
96
|
+
"chainId": 1,
|
|
97
|
+
"derivationIndex": 0
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### sign_evm_typed_data
|
|
102
|
+
|
|
103
|
+
Sign EIP-712 typed structured data with the EVM wallet. Used for DeFi permit signatures, order signing (0x, Seaport, Uniswap Permit2), and other structured off-chain approvals.
|
|
104
|
+
|
|
105
|
+
**Parameters:**
|
|
106
|
+
|
|
107
|
+
```json
|
|
108
|
+
{
|
|
109
|
+
"typedData": {
|
|
110
|
+
"types": { "Permit": [{ "name": "owner", "type": "address" }] },
|
|
111
|
+
"primaryType": "Permit",
|
|
112
|
+
"domain": { "name": "USD Coin", "chainId": 1, "verifyingContract": "0x..." },
|
|
113
|
+
"message": { "owner": "0x...", "spender": "0x...", "value": "1000000000", "nonce": 0, "deadline": 1893456000 }
|
|
114
|
+
},
|
|
115
|
+
"chainId": 1,
|
|
116
|
+
"derivationIndex": 0
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### transfer_tokens
|
|
121
|
+
|
|
122
|
+
Transfer native tokens or fungible tokens on Solana and EVM chains. **Warning:** This tool builds, signs, and sends transactions immediately and irreversibly once called.
|
|
123
|
+
|
|
124
|
+
**Parameters:**
|
|
125
|
+
|
|
126
|
+
- `networkId`: Network — Solana (`solana:mainnet`, `solana:devnet`) or EVM (`eip155:1`, `eip155:8453`, `eip155:137`, `eip155:42161`, `eip155:143`)
|
|
127
|
+
- `to`: Recipient — Solana base58 address or EVM `0x`-prefixed address
|
|
128
|
+
- `amount`: Transfer amount (e.g., "0.1", 0.1, "1000000")
|
|
129
|
+
- `amountUnit`: `"ui"` for human-readable units, `"base"` for atomic units (default: `"ui"`)
|
|
130
|
+
- `tokenMint`: (Optional) Token contract — Solana SPL mint or EVM ERC-20 `0x` address. Omit for native token.
|
|
131
|
+
- `decimals`: (Optional) Token decimals — Solana fetches from chain if omitted; ERC-20 requires this when `amountUnit: "ui"`
|
|
132
|
+
- `derivationIndex`: Account derivation index (default: 0)
|
|
133
|
+
- `createAssociatedTokenAccount`: (Solana only) Create destination ATA if missing (default: true)
|
|
134
|
+
|
|
135
|
+
**Example (SOL):**
|
|
136
|
+
|
|
137
|
+
```json
|
|
138
|
+
{ "networkId": "solana:mainnet", "to": "recipient-address", "amount": "0.1", "amountUnit": "ui" }
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**Example (ETH on Base):**
|
|
142
|
+
|
|
143
|
+
```json
|
|
144
|
+
{ "networkId": "eip155:8453", "to": "0xRecipient", "amount": "0.01", "amountUnit": "ui" }
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**Example (ERC-20 USDC on Ethereum):**
|
|
148
|
+
|
|
149
|
+
```json
|
|
150
|
+
{
|
|
151
|
+
"networkId": "eip155:1",
|
|
152
|
+
"to": "0xRecipient",
|
|
153
|
+
"tokenMint": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
|
154
|
+
"amount": "100",
|
|
155
|
+
"amountUnit": "ui",
|
|
156
|
+
"decimals": 6
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
**Before Transfer Checklist:**
|
|
161
|
+
|
|
162
|
+
1. Verify the recipient address matches the chain type (Solana base58 vs EVM `0x`)
|
|
163
|
+
2. Confirm balance covers amount + fees (`get_token_balances`)
|
|
164
|
+
3. For ERC-20: confirm `decimals` value is correct
|
|
165
|
+
4. Get explicit user confirmation before sending
|
|
166
|
+
|
|
167
|
+
### buy_token
|
|
168
|
+
|
|
169
|
+
Fetch a swap quote from Phantom's routing engine. Supports Solana same-chain, EVM same-chain, and cross-chain swaps. Optionally execute immediately.
|
|
170
|
+
|
|
171
|
+
**Parameters:**
|
|
172
|
+
|
|
173
|
+
- `sellChainId`: (Optional) Chain for the sell token — default: `"solana:mainnet"`. EVM: `"eip155:1"`, `"eip155:8453"`, `"eip155:137"`, etc.
|
|
174
|
+
- `buyChainId`: (Optional) Chain for the buy token — defaults to `sellChainId`. Set differently for cross-chain.
|
|
175
|
+
- `sellTokenIsNative`: Sell the native token (default: true if `sellTokenMint` not provided)
|
|
176
|
+
- `sellTokenMint`: Token to sell — Solana mint or EVM `0x` contract
|
|
177
|
+
- `buyTokenIsNative`: Buy the native token
|
|
178
|
+
- `buyTokenMint`: Token to buy — Solana mint or EVM `0x` contract
|
|
179
|
+
- `amount`: Swap amount
|
|
180
|
+
- `amountUnit`: `"ui"` for token units, `"base"` for atomic units (default: `"base"`)
|
|
181
|
+
- `exactOut`: If true, `amount` is the buy amount instead of sell amount
|
|
182
|
+
- `slippageTolerance`: Max slippage in percent (0-100)
|
|
183
|
+
- `execute`: Sign and send immediately. **Not supported for cross-chain.** Default: false
|
|
184
|
+
- `derivationIndex`: Account derivation index (default: 0)
|
|
185
|
+
- `quoteApiUrl`: Phantom-compatible API override. Leave unset for normal use.
|
|
186
|
+
|
|
187
|
+
**Example (Solana — sell SOL, buy USDC):**
|
|
188
|
+
|
|
189
|
+
```json
|
|
190
|
+
{
|
|
191
|
+
"sellChainId": "solana:mainnet",
|
|
192
|
+
"sellTokenIsNative": true,
|
|
193
|
+
"buyTokenMint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
|
|
194
|
+
"amount": "0.5",
|
|
195
|
+
"amountUnit": "ui",
|
|
196
|
+
"slippageTolerance": 1,
|
|
197
|
+
"execute": true
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
**Example (EVM — sell ETH, buy USDC on Base):**
|
|
202
|
+
|
|
203
|
+
```json
|
|
204
|
+
{
|
|
205
|
+
"sellChainId": "eip155:8453",
|
|
206
|
+
"sellTokenIsNative": true,
|
|
207
|
+
"buyTokenMint": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
208
|
+
"amount": "1000000000000000000",
|
|
209
|
+
"slippageTolerance": 1,
|
|
210
|
+
"execute": true
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
**Example (Cross-chain quote — SOL → ETH, returns steps only):**
|
|
215
|
+
|
|
216
|
+
```json
|
|
217
|
+
{
|
|
218
|
+
"sellChainId": "solana:mainnet",
|
|
219
|
+
"buyChainId": "eip155:1",
|
|
220
|
+
"sellTokenIsNative": true,
|
|
221
|
+
"buyTokenIsNative": true,
|
|
222
|
+
"amount": "1000000000"
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
**Important Notes:**
|
|
227
|
+
|
|
228
|
+
- `execute: false` — returns quote only (safe, no transaction sent)
|
|
229
|
+
- `execute: true` — immediately signs and broadcasts (irreversible); not available for cross-chain
|
|
230
|
+
- Cross-chain: the response contains `steps` for the agent to execute individually
|
|
231
|
+
- Always display expected output, fees, and price impact before executing
|
|
232
|
+
- Get explicit user confirmation before setting `execute: true`
|
|
233
|
+
|
|
234
|
+
## Workflow
|
|
235
|
+
|
|
236
|
+
1. **Check connection** — call `get_connection_status` first; if not connected, call `get_wallet_addresses` to trigger authentication
|
|
237
|
+
2. **Understand the user's intent** — what do they want to do with their wallet?
|
|
238
|
+
3. **For financial operations (transfers/swaps)**:
|
|
239
|
+
- Call `get_token_balances` to verify the user has sufficient funds (including ~0.000005 SOL for fees)
|
|
240
|
+
- Fetch quotes or preview transaction details
|
|
241
|
+
- Display all details to user (recipient, amount, fees, expected outcome)
|
|
242
|
+
- **Get explicit confirmation from user before proceeding**
|
|
243
|
+
- Only then call the execution tool (`transfer_tokens`, or `buy_token` with `execute: true`)
|
|
244
|
+
4. **Execute the appropriate tool** — use `get_wallet_addresses`, `sign_solana_message`, `sign_evm_personal_message`, `send_solana_transaction`, `send_evm_transaction`, etc.
|
|
245
|
+
5. **Present results clearly** — explain the outcome in user-friendly language
|
|
246
|
+
|
|
247
|
+
## Safety Considerations
|
|
248
|
+
|
|
249
|
+
**Critical: Confirmation Before Execution**
|
|
250
|
+
|
|
251
|
+
For `transfer_tokens`, `buy_token` with `execute: true`, `send_solana_transaction`, and `send_evm_transaction`:
|
|
252
|
+
|
|
253
|
+
1. **NEVER call these tools without explicit user confirmation**
|
|
254
|
+
2. Present full transaction details to user first (recipient, amount, fees, slippage)
|
|
255
|
+
3. Wait for user to confirm with "yes", "confirm", "proceed", or similar explicit approval
|
|
256
|
+
4. If user says "no" or expresses uncertainty, do NOT proceed
|
|
257
|
+
5. These tools execute and broadcast immediately — there is no undo
|
|
258
|
+
|
|
259
|
+
**Address Validation:**
|
|
260
|
+
|
|
261
|
+
- Verify addresses are valid Solana base58 format before using
|
|
262
|
+
- Double-check addresses with user to prevent typos
|
|
263
|
+
- Consider showing the first and last 4 characters for user verification
|
|
264
|
+
|
|
265
|
+
**Amount Verification:**
|
|
266
|
+
|
|
267
|
+
- Check user has sufficient balance (amount + fees)
|
|
268
|
+
- Explain the difference between `"ui"` units (user-friendly) and `"base"` units (atomic)
|
|
269
|
+
- For Solana: 1 SOL = 1,000,000,000 lamports
|
|
270
|
+
|
|
271
|
+
**Transaction Explanation:**
|
|
272
|
+
|
|
273
|
+
- Explain what signing a transaction or message means
|
|
274
|
+
- Be transparent about network fees, DEX fees, and any other costs
|
|
275
|
+
- Show expected transaction time (Solana: 1-2 seconds typically)
|
|
276
|
+
|
|
277
|
+
**Error Handling:**
|
|
278
|
+
|
|
279
|
+
- If a transaction fails, explain why and suggest solutions
|
|
280
|
+
- For swap failures, explain price movement and suggest retrying with higher slippage
|
|
281
|
+
- Always provide transaction signatures so users can check on block explorers
|