@phantom/openclaw-plugin 0.1.0 → 0.1.1
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 +92 -6
- package/dist/index.d.ts +34 -0
- package/dist/index.js +170 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +147 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -6,6 +6,55 @@ Direct integration with Phantom wallet for OpenClaw agents. This plugin wraps th
|
|
|
6
6
|
|
|
7
7
|
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.
|
|
8
8
|
|
|
9
|
+
## Quick Start
|
|
10
|
+
|
|
11
|
+
Get up and running in under 5 minutes:
|
|
12
|
+
|
|
13
|
+
### Installation Checklist
|
|
14
|
+
|
|
15
|
+
- [ ] **Step 1:** Get your App ID from [phantom.com/portal](https://phantom.com/portal)
|
|
16
|
+
- Sign in with Gmail or Apple
|
|
17
|
+
- Click "Create App"
|
|
18
|
+
- Go to Dashboard → View App → Redirect URLs
|
|
19
|
+
- Add `http://localhost:8080/callback` as a redirect URL
|
|
20
|
+
- Navigate to "Phantom Connect" tab
|
|
21
|
+
- Copy your App ID
|
|
22
|
+
|
|
23
|
+
- [ ] **Step 2:** Install the plugin
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
openclaw plugins install @phantom/openclaw-plugin
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
- [ ] **Step 3:** Configure in `~/.openclaw/openclaw.json`
|
|
30
|
+
|
|
31
|
+
```json
|
|
32
|
+
{
|
|
33
|
+
"plugins": {
|
|
34
|
+
"enabled": true,
|
|
35
|
+
"entries": {
|
|
36
|
+
"phantom-openclaw-plugin": {
|
|
37
|
+
"enabled": true,
|
|
38
|
+
"config": {
|
|
39
|
+
"PHANTOM_APP_ID": "your_app_id_from_portal"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
- [ ] **Step 4:** Restart OpenClaw
|
|
48
|
+
|
|
49
|
+
- [ ] **Step 5:** Test with your agent
|
|
50
|
+
```text
|
|
51
|
+
Ask: "What are my Phantom wallet addresses?"
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**⚠️ Important:** Use the same email address for both the Phantom Portal and OpenClaw authentication!
|
|
55
|
+
|
|
56
|
+
See [Prerequisites](#prerequisites) below for detailed setup instructions.
|
|
57
|
+
|
|
9
58
|
## Features
|
|
10
59
|
|
|
11
60
|
- **Direct Integration**: Built on top of `@phantom/mcp-server` for reliable wallet operations
|
|
@@ -20,7 +69,11 @@ Before using this plugin, you **must** obtain an App ID from the Phantom Portal:
|
|
|
20
69
|
1. **Visit the Phantom Portal**: Go to [phantom.com/portal](https://phantom.com/portal)
|
|
21
70
|
2. **Sign in**: Use your Gmail or Apple account to sign in
|
|
22
71
|
3. **Create an App**: Click "Create App" and fill in the required details
|
|
23
|
-
4. **
|
|
72
|
+
4. **Configure Redirect URL**:
|
|
73
|
+
- Navigate to Dashboard → View App → Redirect URLs
|
|
74
|
+
- Add `http://localhost:8080/callback` as a redirect URL
|
|
75
|
+
- This allows the OAuth callback to work correctly
|
|
76
|
+
5. **Get Your App ID**: Navigate to the "Phantom Connect" tab to find your App ID
|
|
24
77
|
- Your app is automatically approved for development use
|
|
25
78
|
- Copy the App ID for the configuration below
|
|
26
79
|
|
|
@@ -88,6 +141,7 @@ Sign an arbitrary message with the Phantom wallet.
|
|
|
88
141
|
**Parameters:**
|
|
89
142
|
|
|
90
143
|
- `message` (string, required): The message to sign
|
|
144
|
+
- `networkId` (string, required): Network identifier (e.g., "solana:mainnet", "eip155:1")
|
|
91
145
|
- `derivationIndex` (number, optional): Derivation index for the wallet (default: 0)
|
|
92
146
|
|
|
93
147
|
**Example:**
|
|
@@ -95,6 +149,7 @@ Sign an arbitrary message with the Phantom wallet.
|
|
|
95
149
|
```json
|
|
96
150
|
{
|
|
97
151
|
"message": "Hello, Phantom!",
|
|
152
|
+
"networkId": "solana:mainnet",
|
|
98
153
|
"derivationIndex": 0
|
|
99
154
|
}
|
|
100
155
|
```
|
|
@@ -105,17 +160,18 @@ Sign a blockchain transaction.
|
|
|
105
160
|
|
|
106
161
|
**Parameters:**
|
|
107
162
|
|
|
108
|
-
- `transaction` (string, required):
|
|
163
|
+
- `transaction` (string, required): The transaction to sign (format depends on chain: base64url for Solana, RLP-encoded hex for Ethereum)
|
|
164
|
+
- `networkId` (string, required): Network identifier (e.g., "solana:mainnet", "eip155:1" for Ethereum mainnet)
|
|
109
165
|
- `derivationIndex` (number, optional): Derivation index for the wallet (default: 0)
|
|
110
|
-
- `
|
|
166
|
+
- `account` (string, optional): Specific account address to use for simulation/signing
|
|
111
167
|
|
|
112
168
|
**Example:**
|
|
113
169
|
|
|
114
170
|
```json
|
|
115
171
|
{
|
|
116
|
-
"transaction": "
|
|
117
|
-
"
|
|
118
|
-
"
|
|
172
|
+
"transaction": "base64url-encoded-transaction-data",
|
|
173
|
+
"networkId": "solana:mainnet",
|
|
174
|
+
"derivationIndex": 0
|
|
119
175
|
}
|
|
120
176
|
```
|
|
121
177
|
|
|
@@ -192,6 +248,36 @@ Fetch a Solana swap quote from Phantom's quotes API. Optionally execute the swap
|
|
|
192
248
|
|
|
193
249
|
**⚠️ Warning:** When `execute: true`, this tool submits transactions immediately and irreversibly.
|
|
194
250
|
|
|
251
|
+
## Network IDs Reference
|
|
252
|
+
|
|
253
|
+
Network identifiers follow the CAIP-2/CAIP-10 format. Here are the supported networks:
|
|
254
|
+
|
|
255
|
+
### Solana
|
|
256
|
+
|
|
257
|
+
- Mainnet: `solana:mainnet`
|
|
258
|
+
- Devnet: `solana:devnet`
|
|
259
|
+
- Testnet: `solana:testnet`
|
|
260
|
+
|
|
261
|
+
### Ethereum / EVM Chains
|
|
262
|
+
|
|
263
|
+
- Ethereum Mainnet: `eip155:1`
|
|
264
|
+
- Ethereum Sepolia: `eip155:11155111`
|
|
265
|
+
- Polygon Mainnet: `eip155:137`
|
|
266
|
+
- Polygon Amoy: `eip155:80002`
|
|
267
|
+
- Base Mainnet: `eip155:8453`
|
|
268
|
+
- Base Sepolia: `eip155:84532`
|
|
269
|
+
- Arbitrum One: `eip155:42161`
|
|
270
|
+
- Arbitrum Sepolia: `eip155:421614`
|
|
271
|
+
|
|
272
|
+
### Bitcoin
|
|
273
|
+
|
|
274
|
+
- Mainnet: `bip122:000000000019d6689c085ae165831e93`
|
|
275
|
+
|
|
276
|
+
### Sui
|
|
277
|
+
|
|
278
|
+
- Mainnet: `sui:mainnet`
|
|
279
|
+
- Testnet: `sui:testnet`
|
|
280
|
+
|
|
195
281
|
## Authentication
|
|
196
282
|
|
|
197
283
|
On first use, the plugin will automatically initiate the Phantom OAuth flow:
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenClaw Plugin API types
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* OpenClaw Plugin API interface
|
|
6
|
+
*/
|
|
7
|
+
type OpenClawApi = {
|
|
8
|
+
/** Plugin configuration provided by OpenClaw */
|
|
9
|
+
config?: Record<string, unknown>;
|
|
10
|
+
/** Register a tool with OpenClaw */
|
|
11
|
+
registerTool: (definition: {
|
|
12
|
+
name: string;
|
|
13
|
+
description: string;
|
|
14
|
+
parameters: unknown;
|
|
15
|
+
execute: (id: string, params: Record<string, unknown>) => Promise<{
|
|
16
|
+
content: unknown;
|
|
17
|
+
isError?: boolean;
|
|
18
|
+
}>;
|
|
19
|
+
}) => void;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Phantom OpenClaw Plugin
|
|
24
|
+
*
|
|
25
|
+
* Integrates Phantom wallet operations directly with OpenClaw agents
|
|
26
|
+
* by wrapping the Phantom MCP Server tools.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Plugin registration function
|
|
31
|
+
*/
|
|
32
|
+
declare function register(api: OpenClawApi): Promise<void>;
|
|
33
|
+
|
|
34
|
+
export { register as default };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var src_exports = {};
|
|
22
|
+
__export(src_exports, {
|
|
23
|
+
default: () => register
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(src_exports);
|
|
26
|
+
|
|
27
|
+
// src/session.ts
|
|
28
|
+
var import_mcp_server = require("@phantom/mcp-server");
|
|
29
|
+
var PluginSession = class {
|
|
30
|
+
constructor(options = {}) {
|
|
31
|
+
this.initialized = false;
|
|
32
|
+
this.initializingPromise = null;
|
|
33
|
+
this.sessionManager = new import_mcp_server.SessionManager({
|
|
34
|
+
appId: options.appId ?? "phantom-openclaw",
|
|
35
|
+
callbackPort: options.callbackPort,
|
|
36
|
+
sessionDir: options.sessionDir
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Initialize the session (authenticate if needed)
|
|
41
|
+
* Thread-safe: concurrent calls will await the same initialization promise
|
|
42
|
+
*/
|
|
43
|
+
async initialize() {
|
|
44
|
+
if (this.initialized) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (this.initializingPromise) {
|
|
48
|
+
return this.initializingPromise;
|
|
49
|
+
}
|
|
50
|
+
this.initializingPromise = this.sessionManager.initialize().then(() => {
|
|
51
|
+
this.initialized = true;
|
|
52
|
+
}).catch((error) => {
|
|
53
|
+
this.initializingPromise = null;
|
|
54
|
+
throw error;
|
|
55
|
+
});
|
|
56
|
+
return this.initializingPromise;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Get the authenticated PhantomClient
|
|
60
|
+
*/
|
|
61
|
+
getClient() {
|
|
62
|
+
if (!this.initialized) {
|
|
63
|
+
throw new Error("Session not initialized. Call initialize() first.");
|
|
64
|
+
}
|
|
65
|
+
return this.sessionManager.getClient();
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Get the current session data
|
|
69
|
+
*/
|
|
70
|
+
getSession() {
|
|
71
|
+
if (!this.initialized) {
|
|
72
|
+
throw new Error("Session not initialized. Call initialize() first.");
|
|
73
|
+
}
|
|
74
|
+
return this.sessionManager.getSession();
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
// src/tools/register-tools.ts
|
|
79
|
+
var import_typebox = require("@sinclair/typebox");
|
|
80
|
+
var import_mcp_server2 = require("@phantom/mcp-server");
|
|
81
|
+
function convertSchema(mcpSchema) {
|
|
82
|
+
return import_typebox.Type.Object(
|
|
83
|
+
Object.fromEntries(Object.entries(mcpSchema.properties || {}).map(([key, _value]) => [key, import_typebox.Type.Unknown()]))
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
function registerPhantomTools(api, session) {
|
|
87
|
+
for (const mcpTool of import_mcp_server2.tools) {
|
|
88
|
+
api.registerTool({
|
|
89
|
+
name: mcpTool.name,
|
|
90
|
+
description: mcpTool.description,
|
|
91
|
+
parameters: convertSchema(mcpTool.inputSchema),
|
|
92
|
+
async execute(_id, params) {
|
|
93
|
+
const createLogger = (prefix) => ({
|
|
94
|
+
info: (msg) => console.info(`[${prefix}] ${msg}`),
|
|
95
|
+
// eslint-disable-line no-console
|
|
96
|
+
error: (msg) => console.error(`[${prefix}] ${msg}`),
|
|
97
|
+
// eslint-disable-line no-console
|
|
98
|
+
debug: (msg) => console.debug(`[${prefix}] ${msg}`),
|
|
99
|
+
// eslint-disable-line no-console
|
|
100
|
+
child: (name) => createLogger(`${prefix}:${name}`)
|
|
101
|
+
});
|
|
102
|
+
const context = {
|
|
103
|
+
client: session.getClient(),
|
|
104
|
+
session: session.getSession(),
|
|
105
|
+
logger: createLogger(mcpTool.name)
|
|
106
|
+
};
|
|
107
|
+
try {
|
|
108
|
+
const result = await mcpTool.handler(params, context);
|
|
109
|
+
const normalized = result ?? null;
|
|
110
|
+
return {
|
|
111
|
+
content: [
|
|
112
|
+
{
|
|
113
|
+
type: "text",
|
|
114
|
+
text: typeof normalized === "string" ? normalized : JSON.stringify(normalized, null, 2)
|
|
115
|
+
}
|
|
116
|
+
]
|
|
117
|
+
};
|
|
118
|
+
} catch (error) {
|
|
119
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
120
|
+
return {
|
|
121
|
+
content: [
|
|
122
|
+
{
|
|
123
|
+
type: "text",
|
|
124
|
+
text: JSON.stringify({ error: errorMessage }, null, 2)
|
|
125
|
+
}
|
|
126
|
+
],
|
|
127
|
+
isError: true
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// src/index.ts
|
|
136
|
+
var sessionInstance = null;
|
|
137
|
+
function getSession(config) {
|
|
138
|
+
if (!sessionInstance) {
|
|
139
|
+
const appId = typeof config?.PHANTOM_APP_ID === "string" ? config.PHANTOM_APP_ID : void 0;
|
|
140
|
+
let callbackPort;
|
|
141
|
+
if (typeof config?.PHANTOM_CALLBACK_PORT === "number") {
|
|
142
|
+
callbackPort = config.PHANTOM_CALLBACK_PORT;
|
|
143
|
+
} else if (typeof config?.PHANTOM_CALLBACK_PORT === "string") {
|
|
144
|
+
const parsed = parseInt(config.PHANTOM_CALLBACK_PORT, 10);
|
|
145
|
+
if (!isNaN(parsed) && parsed > 0 && parsed <= 65535) {
|
|
146
|
+
callbackPort = parsed;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
sessionInstance = new PluginSession({
|
|
150
|
+
appId,
|
|
151
|
+
callbackPort
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
return sessionInstance;
|
|
155
|
+
}
|
|
156
|
+
function resetSession() {
|
|
157
|
+
sessionInstance = null;
|
|
158
|
+
}
|
|
159
|
+
async function register(api) {
|
|
160
|
+
try {
|
|
161
|
+
const session = getSession(api.config);
|
|
162
|
+
await session.initialize();
|
|
163
|
+
registerPhantomTools(api, session);
|
|
164
|
+
} catch (error) {
|
|
165
|
+
console.error("Failed to initialize Phantom OpenClaw plugin:", error);
|
|
166
|
+
resetSession();
|
|
167
|
+
throw error;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/session.ts","../src/tools/register-tools.ts"],"sourcesContent":["/**\n * Phantom OpenClaw Plugin\n *\n * Integrates Phantom wallet operations directly with OpenClaw agents\n * by wrapping the Phantom MCP Server tools.\n */\n\nimport type { OpenClawApi } from \"./client/types.js\";\nimport { PluginSession } from \"./session.js\";\nimport { registerPhantomTools } from \"./tools/register-tools.js\";\n\n// Singleton session instance\nlet sessionInstance: PluginSession | null = null;\n\n/**\n * Get or create the plugin session with configuration\n */\nfunction getSession(config?: Record<string, unknown>): PluginSession {\n if (!sessionInstance) {\n // Extract configuration from OpenClaw API config\n const appId = typeof config?.PHANTOM_APP_ID === \"string\" ? config.PHANTOM_APP_ID : undefined;\n\n // Parse callback port - accept both number and numeric string\n let callbackPort: number | undefined;\n if (typeof config?.PHANTOM_CALLBACK_PORT === \"number\") {\n callbackPort = config.PHANTOM_CALLBACK_PORT;\n } else if (typeof config?.PHANTOM_CALLBACK_PORT === \"string\") {\n const parsed = parseInt(config.PHANTOM_CALLBACK_PORT, 10);\n if (!isNaN(parsed) && parsed > 0 && parsed <= 65535) {\n callbackPort = parsed;\n }\n }\n\n sessionInstance = new PluginSession({\n appId,\n callbackPort,\n });\n }\n return sessionInstance;\n}\n\n/**\n * Reset the session singleton (used for cleanup on initialization failure)\n */\nfunction resetSession(): void {\n sessionInstance = null;\n}\n\n/**\n * Plugin registration function\n */\nexport default async function register(api: OpenClawApi) {\n try {\n // Initialize session (authenticate if needed)\n const session = getSession(api.config);\n await session.initialize();\n\n // Register all Phantom MCP tools\n registerPhantomTools(api, session);\n } catch (error) {\n console.error(\"Failed to initialize Phantom OpenClaw plugin:\", error); // eslint-disable-line no-console\n // Reset singleton so next attempt gets a fresh instance\n resetSession();\n throw error;\n }\n}\n","/**\n * Session management for Phantom OpenClaw plugin\n * Wraps the SessionManager from @phantom/mcp-server\n */\n\nimport { SessionManager } from \"@phantom/mcp-server\";\nimport type { PhantomClient, SessionData } from \"@phantom/mcp-server\";\n\n/**\n * Configuration options for PluginSession\n */\nexport interface PluginSessionOptions {\n /** Application identifier from Phantom Portal */\n appId?: string;\n /** OAuth callback port (default: 8080) */\n callbackPort?: number;\n /** Directory to store session data (default: ~/.phantom-mcp) */\n sessionDir?: string;\n}\n\n/**\n * Plugin session manager\n * Handles authentication and provides access to PhantomClient\n */\nexport class PluginSession {\n private sessionManager: SessionManager;\n private initialized = false;\n private initializingPromise: Promise<void> | null = null;\n\n constructor(options: PluginSessionOptions = {}) {\n // Initialize SessionManager with configuration\n this.sessionManager = new SessionManager({\n appId: options.appId ?? \"phantom-openclaw\",\n callbackPort: options.callbackPort,\n sessionDir: options.sessionDir,\n });\n }\n\n /**\n * Initialize the session (authenticate if needed)\n * Thread-safe: concurrent calls will await the same initialization promise\n */\n async initialize(): Promise<void> {\n if (this.initialized) {\n return;\n }\n\n // If already initializing, return the existing promise\n if (this.initializingPromise) {\n return this.initializingPromise;\n }\n\n // Create and store the initialization promise\n this.initializingPromise = this.sessionManager\n .initialize()\n .then(() => {\n this.initialized = true;\n })\n .catch(error => {\n // Clear promise on error so subsequent calls can retry\n this.initializingPromise = null;\n throw error;\n });\n\n return this.initializingPromise;\n }\n\n /**\n * Get the authenticated PhantomClient\n */\n getClient(): PhantomClient {\n if (!this.initialized) {\n throw new Error(\"Session not initialized. Call initialize() first.\");\n }\n return this.sessionManager.getClient();\n }\n\n /**\n * Get the current session data\n */\n getSession(): SessionData {\n if (!this.initialized) {\n throw new Error(\"Session not initialized. Call initialize() first.\");\n }\n return this.sessionManager.getSession();\n }\n}\n","/**\n * Register Phantom MCP tools as OpenClaw tools\n */\n\nimport { Type } from \"@sinclair/typebox\";\nimport { tools } from \"@phantom/mcp-server\";\nimport type { OpenClawApi } from \"../client/types.js\";\nimport type { PluginSession } from \"../session.js\";\n\n/**\n * Convert MCP tool JSON schema to TypeBox schema\n */\nfunction convertSchema(mcpSchema: any): any {\n // For now, use Type.Unknown() - we could do more sophisticated conversion\n return Type.Object(\n Object.fromEntries(Object.entries(mcpSchema.properties || {}).map(([key, _value]) => [key, Type.Unknown()])),\n );\n}\n\n/**\n * Register all Phantom MCP tools with OpenClaw\n */\nexport function registerPhantomTools(api: OpenClawApi, session: PluginSession): void {\n for (const mcpTool of tools) {\n api.registerTool({\n name: mcpTool.name,\n description: mcpTool.description,\n parameters: convertSchema(mcpTool.inputSchema),\n async execute(_id: string, params: Record<string, unknown>) {\n // Create tool context for MCP tool with recursive logger\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const createLogger = (prefix: string): any => ({\n info: (msg: string) => console.info(`[${prefix}] ${msg}`), // eslint-disable-line no-console\n error: (msg: string) => console.error(`[${prefix}] ${msg}`), // eslint-disable-line no-console\n debug: (msg: string) => console.debug(`[${prefix}] ${msg}`), // eslint-disable-line no-console\n child: (name: string) => createLogger(`${prefix}:${name}`),\n });\n\n const context = {\n client: session.getClient(),\n session: session.getSession(),\n logger: createLogger(mcpTool.name),\n };\n\n try {\n // Execute the MCP tool handler\n const result = await mcpTool.handler(params, context);\n\n // Return in OpenClaw format with defensive handling for undefined\n const normalized = result ?? null;\n return {\n content: [\n {\n type: \"text\" as const,\n text: typeof normalized === \"string\" ? normalized : JSON.stringify(normalized, null, 2),\n },\n ],\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({ error: errorMessage }, null, 2),\n },\n ],\n isError: true,\n };\n }\n },\n });\n }\n}\n"],"mappings":"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","names":["import_mcp_server"]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
// src/session.ts
|
|
2
|
+
import { SessionManager } from "@phantom/mcp-server";
|
|
3
|
+
var PluginSession = class {
|
|
4
|
+
constructor(options = {}) {
|
|
5
|
+
this.initialized = false;
|
|
6
|
+
this.initializingPromise = null;
|
|
7
|
+
this.sessionManager = new SessionManager({
|
|
8
|
+
appId: options.appId ?? "phantom-openclaw",
|
|
9
|
+
callbackPort: options.callbackPort,
|
|
10
|
+
sessionDir: options.sessionDir
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Initialize the session (authenticate if needed)
|
|
15
|
+
* Thread-safe: concurrent calls will await the same initialization promise
|
|
16
|
+
*/
|
|
17
|
+
async initialize() {
|
|
18
|
+
if (this.initialized) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
if (this.initializingPromise) {
|
|
22
|
+
return this.initializingPromise;
|
|
23
|
+
}
|
|
24
|
+
this.initializingPromise = this.sessionManager.initialize().then(() => {
|
|
25
|
+
this.initialized = true;
|
|
26
|
+
}).catch((error) => {
|
|
27
|
+
this.initializingPromise = null;
|
|
28
|
+
throw error;
|
|
29
|
+
});
|
|
30
|
+
return this.initializingPromise;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Get the authenticated PhantomClient
|
|
34
|
+
*/
|
|
35
|
+
getClient() {
|
|
36
|
+
if (!this.initialized) {
|
|
37
|
+
throw new Error("Session not initialized. Call initialize() first.");
|
|
38
|
+
}
|
|
39
|
+
return this.sessionManager.getClient();
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Get the current session data
|
|
43
|
+
*/
|
|
44
|
+
getSession() {
|
|
45
|
+
if (!this.initialized) {
|
|
46
|
+
throw new Error("Session not initialized. Call initialize() first.");
|
|
47
|
+
}
|
|
48
|
+
return this.sessionManager.getSession();
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// src/tools/register-tools.ts
|
|
53
|
+
import { Type } from "@sinclair/typebox";
|
|
54
|
+
import { tools } from "@phantom/mcp-server";
|
|
55
|
+
function convertSchema(mcpSchema) {
|
|
56
|
+
return Type.Object(
|
|
57
|
+
Object.fromEntries(Object.entries(mcpSchema.properties || {}).map(([key, _value]) => [key, Type.Unknown()]))
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
function registerPhantomTools(api, session) {
|
|
61
|
+
for (const mcpTool of tools) {
|
|
62
|
+
api.registerTool({
|
|
63
|
+
name: mcpTool.name,
|
|
64
|
+
description: mcpTool.description,
|
|
65
|
+
parameters: convertSchema(mcpTool.inputSchema),
|
|
66
|
+
async execute(_id, params) {
|
|
67
|
+
const createLogger = (prefix) => ({
|
|
68
|
+
info: (msg) => console.info(`[${prefix}] ${msg}`),
|
|
69
|
+
// eslint-disable-line no-console
|
|
70
|
+
error: (msg) => console.error(`[${prefix}] ${msg}`),
|
|
71
|
+
// eslint-disable-line no-console
|
|
72
|
+
debug: (msg) => console.debug(`[${prefix}] ${msg}`),
|
|
73
|
+
// eslint-disable-line no-console
|
|
74
|
+
child: (name) => createLogger(`${prefix}:${name}`)
|
|
75
|
+
});
|
|
76
|
+
const context = {
|
|
77
|
+
client: session.getClient(),
|
|
78
|
+
session: session.getSession(),
|
|
79
|
+
logger: createLogger(mcpTool.name)
|
|
80
|
+
};
|
|
81
|
+
try {
|
|
82
|
+
const result = await mcpTool.handler(params, context);
|
|
83
|
+
const normalized = result ?? null;
|
|
84
|
+
return {
|
|
85
|
+
content: [
|
|
86
|
+
{
|
|
87
|
+
type: "text",
|
|
88
|
+
text: typeof normalized === "string" ? normalized : JSON.stringify(normalized, null, 2)
|
|
89
|
+
}
|
|
90
|
+
]
|
|
91
|
+
};
|
|
92
|
+
} catch (error) {
|
|
93
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
94
|
+
return {
|
|
95
|
+
content: [
|
|
96
|
+
{
|
|
97
|
+
type: "text",
|
|
98
|
+
text: JSON.stringify({ error: errorMessage }, null, 2)
|
|
99
|
+
}
|
|
100
|
+
],
|
|
101
|
+
isError: true
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// src/index.ts
|
|
110
|
+
var sessionInstance = null;
|
|
111
|
+
function getSession(config) {
|
|
112
|
+
if (!sessionInstance) {
|
|
113
|
+
const appId = typeof config?.PHANTOM_APP_ID === "string" ? config.PHANTOM_APP_ID : void 0;
|
|
114
|
+
let callbackPort;
|
|
115
|
+
if (typeof config?.PHANTOM_CALLBACK_PORT === "number") {
|
|
116
|
+
callbackPort = config.PHANTOM_CALLBACK_PORT;
|
|
117
|
+
} else if (typeof config?.PHANTOM_CALLBACK_PORT === "string") {
|
|
118
|
+
const parsed = parseInt(config.PHANTOM_CALLBACK_PORT, 10);
|
|
119
|
+
if (!isNaN(parsed) && parsed > 0 && parsed <= 65535) {
|
|
120
|
+
callbackPort = parsed;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
sessionInstance = new PluginSession({
|
|
124
|
+
appId,
|
|
125
|
+
callbackPort
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
return sessionInstance;
|
|
129
|
+
}
|
|
130
|
+
function resetSession() {
|
|
131
|
+
sessionInstance = null;
|
|
132
|
+
}
|
|
133
|
+
async function register(api) {
|
|
134
|
+
try {
|
|
135
|
+
const session = getSession(api.config);
|
|
136
|
+
await session.initialize();
|
|
137
|
+
registerPhantomTools(api, session);
|
|
138
|
+
} catch (error) {
|
|
139
|
+
console.error("Failed to initialize Phantom OpenClaw plugin:", error);
|
|
140
|
+
resetSession();
|
|
141
|
+
throw error;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
export {
|
|
145
|
+
register as default
|
|
146
|
+
};
|
|
147
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/session.ts","../src/tools/register-tools.ts","../src/index.ts"],"sourcesContent":["/**\n * Session management for Phantom OpenClaw plugin\n * Wraps the SessionManager from @phantom/mcp-server\n */\n\nimport { SessionManager } from \"@phantom/mcp-server\";\nimport type { PhantomClient, SessionData } from \"@phantom/mcp-server\";\n\n/**\n * Configuration options for PluginSession\n */\nexport interface PluginSessionOptions {\n /** Application identifier from Phantom Portal */\n appId?: string;\n /** OAuth callback port (default: 8080) */\n callbackPort?: number;\n /** Directory to store session data (default: ~/.phantom-mcp) */\n sessionDir?: string;\n}\n\n/**\n * Plugin session manager\n * Handles authentication and provides access to PhantomClient\n */\nexport class PluginSession {\n private sessionManager: SessionManager;\n private initialized = false;\n private initializingPromise: Promise<void> | null = null;\n\n constructor(options: PluginSessionOptions = {}) {\n // Initialize SessionManager with configuration\n this.sessionManager = new SessionManager({\n appId: options.appId ?? \"phantom-openclaw\",\n callbackPort: options.callbackPort,\n sessionDir: options.sessionDir,\n });\n }\n\n /**\n * Initialize the session (authenticate if needed)\n * Thread-safe: concurrent calls will await the same initialization promise\n */\n async initialize(): Promise<void> {\n if (this.initialized) {\n return;\n }\n\n // If already initializing, return the existing promise\n if (this.initializingPromise) {\n return this.initializingPromise;\n }\n\n // Create and store the initialization promise\n this.initializingPromise = this.sessionManager\n .initialize()\n .then(() => {\n this.initialized = true;\n })\n .catch(error => {\n // Clear promise on error so subsequent calls can retry\n this.initializingPromise = null;\n throw error;\n });\n\n return this.initializingPromise;\n }\n\n /**\n * Get the authenticated PhantomClient\n */\n getClient(): PhantomClient {\n if (!this.initialized) {\n throw new Error(\"Session not initialized. Call initialize() first.\");\n }\n return this.sessionManager.getClient();\n }\n\n /**\n * Get the current session data\n */\n getSession(): SessionData {\n if (!this.initialized) {\n throw new Error(\"Session not initialized. Call initialize() first.\");\n }\n return this.sessionManager.getSession();\n }\n}\n","/**\n * Register Phantom MCP tools as OpenClaw tools\n */\n\nimport { Type } from \"@sinclair/typebox\";\nimport { tools } from \"@phantom/mcp-server\";\nimport type { OpenClawApi } from \"../client/types.js\";\nimport type { PluginSession } from \"../session.js\";\n\n/**\n * Convert MCP tool JSON schema to TypeBox schema\n */\nfunction convertSchema(mcpSchema: any): any {\n // For now, use Type.Unknown() - we could do more sophisticated conversion\n return Type.Object(\n Object.fromEntries(Object.entries(mcpSchema.properties || {}).map(([key, _value]) => [key, Type.Unknown()])),\n );\n}\n\n/**\n * Register all Phantom MCP tools with OpenClaw\n */\nexport function registerPhantomTools(api: OpenClawApi, session: PluginSession): void {\n for (const mcpTool of tools) {\n api.registerTool({\n name: mcpTool.name,\n description: mcpTool.description,\n parameters: convertSchema(mcpTool.inputSchema),\n async execute(_id: string, params: Record<string, unknown>) {\n // Create tool context for MCP tool with recursive logger\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const createLogger = (prefix: string): any => ({\n info: (msg: string) => console.info(`[${prefix}] ${msg}`), // eslint-disable-line no-console\n error: (msg: string) => console.error(`[${prefix}] ${msg}`), // eslint-disable-line no-console\n debug: (msg: string) => console.debug(`[${prefix}] ${msg}`), // eslint-disable-line no-console\n child: (name: string) => createLogger(`${prefix}:${name}`),\n });\n\n const context = {\n client: session.getClient(),\n session: session.getSession(),\n logger: createLogger(mcpTool.name),\n };\n\n try {\n // Execute the MCP tool handler\n const result = await mcpTool.handler(params, context);\n\n // Return in OpenClaw format with defensive handling for undefined\n const normalized = result ?? null;\n return {\n content: [\n {\n type: \"text\" as const,\n text: typeof normalized === \"string\" ? normalized : JSON.stringify(normalized, null, 2),\n },\n ],\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({ error: errorMessage }, null, 2),\n },\n ],\n isError: true,\n };\n }\n },\n });\n }\n}\n","/**\n * Phantom OpenClaw Plugin\n *\n * Integrates Phantom wallet operations directly with OpenClaw agents\n * by wrapping the Phantom MCP Server tools.\n */\n\nimport type { OpenClawApi } from \"./client/types.js\";\nimport { PluginSession } from \"./session.js\";\nimport { registerPhantomTools } from \"./tools/register-tools.js\";\n\n// Singleton session instance\nlet sessionInstance: PluginSession | null = null;\n\n/**\n * Get or create the plugin session with configuration\n */\nfunction getSession(config?: Record<string, unknown>): PluginSession {\n if (!sessionInstance) {\n // Extract configuration from OpenClaw API config\n const appId = typeof config?.PHANTOM_APP_ID === \"string\" ? config.PHANTOM_APP_ID : undefined;\n\n // Parse callback port - accept both number and numeric string\n let callbackPort: number | undefined;\n if (typeof config?.PHANTOM_CALLBACK_PORT === \"number\") {\n callbackPort = config.PHANTOM_CALLBACK_PORT;\n } else if (typeof config?.PHANTOM_CALLBACK_PORT === \"string\") {\n const parsed = parseInt(config.PHANTOM_CALLBACK_PORT, 10);\n if (!isNaN(parsed) && parsed > 0 && parsed <= 65535) {\n callbackPort = parsed;\n }\n }\n\n sessionInstance = new PluginSession({\n appId,\n callbackPort,\n });\n }\n return sessionInstance;\n}\n\n/**\n * Reset the session singleton (used for cleanup on initialization failure)\n */\nfunction resetSession(): void {\n sessionInstance = null;\n}\n\n/**\n * Plugin registration function\n */\nexport default async function register(api: OpenClawApi) {\n try {\n // Initialize session (authenticate if needed)\n const session = getSession(api.config);\n await session.initialize();\n\n // Register all Phantom MCP tools\n registerPhantomTools(api, session);\n } catch (error) {\n console.error(\"Failed to initialize Phantom OpenClaw plugin:\", error); // eslint-disable-line no-console\n // Reset singleton so next attempt gets a fresh instance\n resetSession();\n throw error;\n }\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@phantom/openclaw-plugin",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "OpenClaw plugin that bridges tool calls to Phantom's MCP server for wallet operations.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"typescript": "^5.0.4"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@phantom/mcp-server": "
|
|
44
|
+
"@phantom/mcp-server": "^0.1.2",
|
|
45
45
|
"@sinclair/typebox": "^0.32.0"
|
|
46
46
|
},
|
|
47
47
|
"files": [
|
|
@@ -52,4 +52,4 @@
|
|
|
52
52
|
"publishConfig": {
|
|
53
53
|
"directory": "_release/package"
|
|
54
54
|
}
|
|
55
|
-
}
|
|
55
|
+
}
|