@jaw.id/cli 0.0.7 → 0.1.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 +24 -24
- package/dist/base-command.js +28 -8
- package/dist/base-command.js.map +1 -1
- package/dist/commands/config/set.js +28 -38
- package/dist/commands/config/set.js.map +1 -1
- package/dist/commands/config/show.js +29 -12
- package/dist/commands/config/show.js.map +1 -1
- package/dist/commands/config/write.js +288 -0
- package/dist/commands/config/write.js.map +1 -0
- package/dist/commands/disconnect.js +42 -54
- package/dist/commands/disconnect.js.map +1 -1
- package/dist/commands/mcp/index.js +62 -102
- package/dist/commands/mcp/index.js.map +1 -1
- package/dist/commands/rpc/call.js +218 -92
- package/dist/commands/rpc/call.js.map +1 -1
- package/dist/commands/session/revoke.js +727 -0
- package/dist/commands/session/revoke.js.map +1 -0
- package/dist/commands/session/setup.js +960 -0
- package/dist/commands/session/setup.js.map +1 -0
- package/dist/commands/session/status.js +206 -0
- package/dist/commands/session/status.js.map +1 -0
- package/dist/commands/version.js +28 -8
- package/dist/commands/version.js.map +1 -1
- package/dist/index.js +42 -67
- package/dist/index.js.map +1 -1
- package/dist/lib/bridge-singleton.js +47 -61
- package/dist/lib/bridge-singleton.js.map +1 -1
- package/dist/lib/config.js +17 -13
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/crypto.js +3 -15
- package/dist/lib/crypto.js.map +1 -1
- package/dist/lib/keystore.js +64 -0
- package/dist/lib/keystore.js.map +1 -0
- package/dist/lib/output.js +1 -16
- package/dist/lib/output.js.map +1 -1
- package/dist/lib/paths.js +3 -1
- package/dist/lib/paths.js.map +1 -1
- package/dist/lib/session-bridge.js +168 -0
- package/dist/lib/session-bridge.js.map +1 -0
- package/dist/lib/session-config.js +52 -0
- package/dist/lib/session-config.js.map +1 -0
- package/dist/lib/validation.js +62 -27
- package/dist/lib/validation.js.map +1 -1
- package/dist/lib/ws-bridge.js +15 -46
- package/dist/lib/ws-bridge.js.map +1 -1
- package/dist/mcp/handlers/config.js +28 -29
- package/dist/mcp/handlers/config.js.map +1 -1
- package/dist/mcp/handlers/daemon.js +41 -51
- package/dist/mcp/handlers/daemon.js.map +1 -1
- package/dist/mcp/handlers/resources.js +1 -3
- package/dist/mcp/handlers/resources.js.map +1 -1
- package/dist/mcp/handlers/rpc.js +63 -79
- package/dist/mcp/handlers/rpc.js.map +1 -1
- package/dist/mcp/helpers.js.map +1 -1
- package/dist/mcp/server.js +61 -99
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tools.js +2 -4
- package/dist/mcp/tools.js.map +1 -1
- package/oclif.manifest.json +304 -4
- package/package.json +19 -1
- package/dist/lib/session-store.js +0 -80
- package/dist/lib/session-store.js.map +0 -1
package/dist/mcp/server.js
CHANGED
|
@@ -15,12 +15,10 @@ var rpcMethodSchema = {
|
|
|
15
15
|
params: z.any().optional().describe(
|
|
16
16
|
"Method parameters \u2014 structure varies by method. Read the jaw://api-reference/{method} resource for the expected format."
|
|
17
17
|
),
|
|
18
|
-
chainId: z.number().optional().describe(
|
|
19
|
-
"Target chain ID (overrides default). E.g., 1 for Ethereum, 8453 for Base, 84532 for Base Sepolia"
|
|
20
|
-
)
|
|
18
|
+
chainId: z.number().optional().describe("Target chain ID (overrides default). E.g., 1 for Ethereum, 8453 for Base, 84532 for Base Sepolia")
|
|
21
19
|
};
|
|
22
20
|
var configSetSchema = {
|
|
23
|
-
key: z.enum(["apiKey", "defaultChain", "keysUrl", "
|
|
21
|
+
key: z.enum(["apiKey", "defaultChain", "keysUrl", "ens", "relayUrl"]).describe("Config key"),
|
|
24
22
|
value: z.string().describe("Config value")
|
|
25
23
|
};
|
|
26
24
|
|
|
@@ -51,7 +49,9 @@ var PATHS = {
|
|
|
51
49
|
root: JAW_DIR,
|
|
52
50
|
config: path.join(JAW_DIR, "config.json"),
|
|
53
51
|
session: path.join(JAW_DIR, "session.json"),
|
|
54
|
-
relay: path.join(JAW_DIR, "relay.json")
|
|
52
|
+
relay: path.join(JAW_DIR, "relay.json"),
|
|
53
|
+
keystore: path.join(JAW_DIR, "keystore.json"),
|
|
54
|
+
sessionConfig: path.join(JAW_DIR, "session-config.json")
|
|
55
55
|
};
|
|
56
56
|
|
|
57
57
|
// src/lib/validation.ts
|
|
@@ -82,13 +82,23 @@ function ensureDir(dir) {
|
|
|
82
82
|
fs2.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
83
83
|
fs2.chmodSync(dir, 448);
|
|
84
84
|
}
|
|
85
|
+
function migrateConfig(config) {
|
|
86
|
+
if (config.paymasterUrl && !config.paymasters) {
|
|
87
|
+
const chainId = config.defaultChain ?? 1;
|
|
88
|
+
config.paymasters = { [chainId]: { url: config.paymasterUrl } };
|
|
89
|
+
delete config.paymasterUrl;
|
|
90
|
+
saveConfig(config);
|
|
91
|
+
}
|
|
92
|
+
return config;
|
|
93
|
+
}
|
|
85
94
|
function loadConfig() {
|
|
86
95
|
if (!fs2.existsSync(PATHS.config)) {
|
|
87
96
|
return {};
|
|
88
97
|
}
|
|
89
98
|
const raw = fs2.readFileSync(PATHS.config, "utf-8");
|
|
90
99
|
try {
|
|
91
|
-
|
|
100
|
+
const config = JSON.parse(raw);
|
|
101
|
+
return migrateConfig(config);
|
|
92
102
|
} catch {
|
|
93
103
|
throw new Error(
|
|
94
104
|
`Config file at ${PATHS.config} is not valid JSON. Run \`jaw config set apiKey=<key>\` to reset it.`
|
|
@@ -110,14 +120,10 @@ function redactConfig(config) {
|
|
|
110
120
|
}
|
|
111
121
|
function setConfigValue(key, value) {
|
|
112
122
|
if (key === "keysUrl" && typeof value === "string" && !isValidKeysUrl(value)) {
|
|
113
|
-
throw new Error(
|
|
114
|
-
`Untrusted keysUrl: ${value}. Must be a *.jaw.id domain (HTTPS) or localhost.`
|
|
115
|
-
);
|
|
123
|
+
throw new Error(`Untrusted keysUrl: ${value}. Must be a *.jaw.id domain (HTTPS) or localhost.`);
|
|
116
124
|
}
|
|
117
125
|
if (key === "relayUrl" && typeof value === "string" && !isValidRelayUrl(value)) {
|
|
118
|
-
throw new Error(
|
|
119
|
-
`Untrusted relayUrl: ${value}. Must be wss://*.jaw.id or ws://localhost.`
|
|
120
|
-
);
|
|
126
|
+
throw new Error(`Untrusted relayUrl: ${value}. Must be wss://*.jaw.id or ws://localhost.`);
|
|
121
127
|
}
|
|
122
128
|
const config = loadConfig();
|
|
123
129
|
const updated = { ...config, [key]: value };
|
|
@@ -127,11 +133,7 @@ function setConfigValue(key, value) {
|
|
|
127
133
|
// src/lib/crypto.ts
|
|
128
134
|
var subtle = globalThis.crypto.subtle;
|
|
129
135
|
async function generateKeyPair() {
|
|
130
|
-
return subtle.generateKey(
|
|
131
|
-
{ name: "ECDH", namedCurve: "P-256" },
|
|
132
|
-
true,
|
|
133
|
-
["deriveKey"]
|
|
134
|
-
);
|
|
136
|
+
return subtle.generateKey({ name: "ECDH", namedCurve: "P-256" }, true, ["deriveKey"]);
|
|
135
137
|
}
|
|
136
138
|
async function deriveSharedSecret(privateKey, peerPublicKey) {
|
|
137
139
|
return subtle.deriveKey(
|
|
@@ -145,11 +147,7 @@ async function deriveSharedSecret(privateKey, peerPublicKey) {
|
|
|
145
147
|
async function encryptMessage(sharedSecret, payload) {
|
|
146
148
|
const iv = globalThis.crypto.getRandomValues(new Uint8Array(12));
|
|
147
149
|
const plaintext = new TextEncoder().encode(JSON.stringify(payload));
|
|
148
|
-
const cipherBuf = await subtle.encrypt(
|
|
149
|
-
{ name: "AES-GCM", iv },
|
|
150
|
-
sharedSecret,
|
|
151
|
-
plaintext
|
|
152
|
-
);
|
|
150
|
+
const cipherBuf = await subtle.encrypt({ name: "AES-GCM", iv }, sharedSecret, plaintext);
|
|
153
151
|
return {
|
|
154
152
|
iv: bufferToBase64(iv),
|
|
155
153
|
ciphertext: bufferToBase64(new Uint8Array(cipherBuf))
|
|
@@ -158,11 +156,7 @@ async function encryptMessage(sharedSecret, payload) {
|
|
|
158
156
|
async function decryptMessage(sharedSecret, envelope) {
|
|
159
157
|
const iv = Buffer.from(envelope.iv, "base64");
|
|
160
158
|
const ciphertext = Buffer.from(envelope.ciphertext, "base64");
|
|
161
|
-
const plainBuf = await subtle.decrypt(
|
|
162
|
-
{ name: "AES-GCM", iv },
|
|
163
|
-
sharedSecret,
|
|
164
|
-
ciphertext
|
|
165
|
-
);
|
|
159
|
+
const plainBuf = await subtle.decrypt({ name: "AES-GCM", iv }, sharedSecret, ciphertext);
|
|
166
160
|
return JSON.parse(new TextDecoder().decode(plainBuf));
|
|
167
161
|
}
|
|
168
162
|
async function exportKeyToHex(type, key) {
|
|
@@ -254,11 +248,7 @@ var WSBridge = class {
|
|
|
254
248
|
let expectingKeyExchange = !this.peerPublicKeyHex;
|
|
255
249
|
const timer = setTimeout(() => {
|
|
256
250
|
ws.close();
|
|
257
|
-
reject(
|
|
258
|
-
new Error(
|
|
259
|
-
"Browser did not connect in time.\nRun `jaw disconnect` then try again."
|
|
260
|
-
)
|
|
261
|
-
);
|
|
251
|
+
reject(new Error("Browser did not connect in time.\nRun `jaw disconnect` then try again."));
|
|
262
252
|
}, 3e4);
|
|
263
253
|
const sendEncryptedInit = async () => {
|
|
264
254
|
if (!this.sharedSecret) return;
|
|
@@ -281,10 +271,7 @@ var WSBridge = class {
|
|
|
281
271
|
if (!msg) return;
|
|
282
272
|
if (msg.type === "encrypted" && this.sharedSecret) {
|
|
283
273
|
try {
|
|
284
|
-
const inner = await decryptMessage(
|
|
285
|
-
this.sharedSecret,
|
|
286
|
-
msg
|
|
287
|
-
);
|
|
274
|
+
const inner = await decryptMessage(this.sharedSecret, msg);
|
|
288
275
|
if (inner.type === "ready") {
|
|
289
276
|
clearTimeout(readyTimer);
|
|
290
277
|
ws.off("message", onMsg);
|
|
@@ -322,6 +309,10 @@ var WSBridge = class {
|
|
|
322
309
|
expectingKeyExchange = true;
|
|
323
310
|
onBrowserNeeded().catch(() => {
|
|
324
311
|
});
|
|
312
|
+
} else if (!onBrowserNeeded) {
|
|
313
|
+
clearTimeout(timer);
|
|
314
|
+
ws.close();
|
|
315
|
+
reject(new Error("Browser not connected \u2014 relay session is stale."));
|
|
325
316
|
}
|
|
326
317
|
} else if (msg.type === "browser_connected") {
|
|
327
318
|
expectingKeyExchange = true;
|
|
@@ -371,9 +362,7 @@ var WSBridge = class {
|
|
|
371
362
|
return new Promise((resolve, reject) => {
|
|
372
363
|
const timer = setTimeout(() => {
|
|
373
364
|
reject(
|
|
374
|
-
new Error(
|
|
375
|
-
`Request timed out after ${this.timeout / 1e3}s. Did you complete the action in the browser?`
|
|
376
|
-
)
|
|
365
|
+
new Error(`Request timed out after ${this.timeout / 1e3}s. Did you complete the action in the browser?`)
|
|
377
366
|
);
|
|
378
367
|
this.close();
|
|
379
368
|
}, this.timeout);
|
|
@@ -381,10 +370,7 @@ var WSBridge = class {
|
|
|
381
370
|
const msg = safeParse(data);
|
|
382
371
|
if (!msg || msg.type !== "encrypted" || !this.sharedSecret) return;
|
|
383
372
|
try {
|
|
384
|
-
const inner = await decryptMessage(
|
|
385
|
-
this.sharedSecret,
|
|
386
|
-
msg
|
|
387
|
-
);
|
|
373
|
+
const inner = await decryptMessage(this.sharedSecret, msg);
|
|
388
374
|
if (inner.type === "rpc_response" && inner.id === id) {
|
|
389
375
|
clearTimeout(timer);
|
|
390
376
|
ws.off("message", onMessage);
|
|
@@ -392,11 +378,7 @@ var WSBridge = class {
|
|
|
392
378
|
resolve(inner.data);
|
|
393
379
|
} else {
|
|
394
380
|
const err = inner.error;
|
|
395
|
-
reject(
|
|
396
|
-
new Error(
|
|
397
|
-
err ? `[${err.code}] ${err.message}` : "Request failed"
|
|
398
|
-
)
|
|
399
|
-
);
|
|
381
|
+
reject(new Error(err ? `[${err.code}] ${err.message}` : "Request failed"));
|
|
400
382
|
}
|
|
401
383
|
}
|
|
402
384
|
} catch {
|
|
@@ -406,9 +388,6 @@ var WSBridge = class {
|
|
|
406
388
|
this.sendRaw(ws, serialized);
|
|
407
389
|
});
|
|
408
390
|
}
|
|
409
|
-
isOpen() {
|
|
410
|
-
return this.ws?.readyState === WebSocket.OPEN;
|
|
411
|
-
}
|
|
412
391
|
async shutdown() {
|
|
413
392
|
this.disposed = true;
|
|
414
393
|
if (this.ws?.readyState === WebSocket.OPEN && this.sharedSecret) {
|
|
@@ -416,10 +395,7 @@ var WSBridge = class {
|
|
|
416
395
|
const envelope = await encryptMessage(this.sharedSecret, {
|
|
417
396
|
type: "shutdown"
|
|
418
397
|
});
|
|
419
|
-
this.sendRaw(
|
|
420
|
-
this.ws,
|
|
421
|
-
JSON.stringify({ type: "encrypted", ...envelope })
|
|
422
|
-
);
|
|
398
|
+
this.sendRaw(this.ws, JSON.stringify({ type: "encrypted", ...envelope }));
|
|
423
399
|
} catch {
|
|
424
400
|
}
|
|
425
401
|
}
|
|
@@ -497,10 +473,8 @@ var WSBridge = class {
|
|
|
497
473
|
this.reconnectAttempts++;
|
|
498
474
|
setTimeout(() => {
|
|
499
475
|
if (this.disposed) return;
|
|
500
|
-
this.connectInternal(this.onBrowserNeeded, this.onPeerKeyChanged).catch(
|
|
501
|
-
|
|
502
|
-
}
|
|
503
|
-
);
|
|
476
|
+
this.connectInternal(this.onBrowserNeeded, this.onPeerKeyChanged).catch(() => {
|
|
477
|
+
});
|
|
504
478
|
}, delay);
|
|
505
479
|
}
|
|
506
480
|
/** Send a raw string over the WebSocket, enforcing message size limits. */
|
|
@@ -510,10 +484,7 @@ var WSBridge = class {
|
|
|
510
484
|
async deriveSecret() {
|
|
511
485
|
if (!this.peerPublicKeyHex) return;
|
|
512
486
|
const privateKey = await importKeyFromHex("private", this.privateKeyHex);
|
|
513
|
-
const peerPublicKey = await importKeyFromHex(
|
|
514
|
-
"public",
|
|
515
|
-
this.peerPublicKeyHex
|
|
516
|
-
);
|
|
487
|
+
const peerPublicKey = await importKeyFromHex("public", this.peerPublicKeyHex);
|
|
517
488
|
this.sharedSecret = await deriveSharedSecret(privateKey, peerPublicKey);
|
|
518
489
|
}
|
|
519
490
|
};
|
|
@@ -575,17 +546,19 @@ async function getBridge(options) {
|
|
|
575
546
|
throw new Error(`Untrusted relayUrl: ${relayUrl}. Must be wss://*.jaw.id or ws://localhost.`);
|
|
576
547
|
}
|
|
577
548
|
let relaySession = loadRelaySession();
|
|
578
|
-
if (relaySession && relaySession.relayUrl === relayUrl) {
|
|
549
|
+
if (relaySession && relaySession.relayUrl === relayUrl && relaySession.peerPublicKey) {
|
|
579
550
|
try {
|
|
580
|
-
return await connectBridge(relaySession, options, chainId, keysUrl, relayUrl);
|
|
551
|
+
return await connectBridge(relaySession, options, chainId, keysUrl, relayUrl, false);
|
|
581
552
|
} catch {
|
|
582
553
|
deleteRelaySession();
|
|
583
554
|
relaySession = null;
|
|
584
555
|
}
|
|
556
|
+
} else if (relaySession) {
|
|
557
|
+
deleteRelaySession();
|
|
585
558
|
}
|
|
586
559
|
const session = await createNewSession(relayUrl);
|
|
587
560
|
saveRelaySession(session);
|
|
588
|
-
return await connectBridge(session, options, chainId, keysUrl, relayUrl);
|
|
561
|
+
return await connectBridge(session, options, chainId, keysUrl, relayUrl, true);
|
|
589
562
|
}
|
|
590
563
|
async function createNewSession(relayUrl) {
|
|
591
564
|
const kp = await generateKeyPair();
|
|
@@ -600,7 +573,7 @@ async function createNewSession(relayUrl) {
|
|
|
600
573
|
startedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
601
574
|
};
|
|
602
575
|
}
|
|
603
|
-
async function connectBridge(relaySession, options, chainId, keysUrl, relayUrl) {
|
|
576
|
+
async function connectBridge(relaySession, options, chainId, keysUrl, relayUrl, openBrowser) {
|
|
604
577
|
const config = loadConfig();
|
|
605
578
|
const bridge = new WSBridge({
|
|
606
579
|
relayUrl,
|
|
@@ -610,19 +583,19 @@ async function connectBridge(relaySession, options, chainId, keysUrl, relayUrl)
|
|
|
610
583
|
apiKey: options.apiKey,
|
|
611
584
|
chainId,
|
|
612
585
|
ens: options.ens ?? config.ens,
|
|
613
|
-
paymasterUrl: options.paymasterUrl ?? config.
|
|
586
|
+
paymasterUrl: options.paymasterUrl ?? config.paymasters?.[chainId]?.url
|
|
614
587
|
},
|
|
615
588
|
privateKeyHex: relaySession.privateKey,
|
|
616
589
|
publicKeyHex: relaySession.publicKey,
|
|
617
590
|
peerPublicKeyHex: relaySession.peerPublicKey
|
|
618
591
|
});
|
|
619
592
|
await bridge.connect(
|
|
620
|
-
// onBrowserNeeded
|
|
621
|
-
async () => {
|
|
593
|
+
// onBrowserNeeded — only open a browser for new sessions
|
|
594
|
+
openBrowser ? async () => {
|
|
622
595
|
const bridgeUrl = buildBridgeUrl(keysUrl, relaySession.session, relayUrl, relaySession.publicKey);
|
|
623
596
|
const { default: open } = await import('open');
|
|
624
597
|
await open(bridgeUrl);
|
|
625
|
-
},
|
|
598
|
+
} : void 0,
|
|
626
599
|
// onPeerKeyChanged
|
|
627
600
|
(newPeerKey) => {
|
|
628
601
|
relaySession.peerPublicKey = newPeerKey;
|
|
@@ -682,9 +655,7 @@ async function shutdownDaemon() {
|
|
|
682
655
|
function resolveApiKey() {
|
|
683
656
|
const apiKey = process.env["JAW_API_KEY"] ?? loadConfig().apiKey;
|
|
684
657
|
if (!apiKey) {
|
|
685
|
-
throw new Error(
|
|
686
|
-
"API key required. Set JAW_API_KEY env var or run: jaw config set apiKey <key>"
|
|
687
|
-
);
|
|
658
|
+
throw new Error("API key required. Set JAW_API_KEY env var or run: jaw config set apiKey <key>");
|
|
688
659
|
}
|
|
689
660
|
return apiKey;
|
|
690
661
|
}
|
|
@@ -696,12 +667,14 @@ function registerRpcTool(server) {
|
|
|
696
667
|
async (params) => {
|
|
697
668
|
const config = loadConfig();
|
|
698
669
|
const apiKey = resolveApiKey();
|
|
670
|
+
const chainId = params.chainId ?? config.defaultChain ?? 1;
|
|
671
|
+
const pm = config.paymasters?.[chainId];
|
|
699
672
|
const bridge = await getBridge({
|
|
700
673
|
keysUrl: config.keysUrl,
|
|
701
674
|
apiKey,
|
|
702
|
-
chainId
|
|
675
|
+
chainId,
|
|
703
676
|
ens: config.ens,
|
|
704
|
-
paymasterUrl:
|
|
677
|
+
paymasterUrl: pm?.url
|
|
705
678
|
});
|
|
706
679
|
try {
|
|
707
680
|
const result = await bridge.request(params.method, params.params);
|
|
@@ -717,26 +690,19 @@ function registerRpcTool(server) {
|
|
|
717
690
|
|
|
718
691
|
// src/mcp/handlers/config.ts
|
|
719
692
|
function registerConfigTools(server) {
|
|
720
|
-
server.tool(
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
content: [
|
|
729
|
-
{ type: "text", text: JSON.stringify(config) }
|
|
730
|
-
]
|
|
731
|
-
};
|
|
732
|
-
} catch (err) {
|
|
733
|
-
return mcpError(err);
|
|
734
|
-
}
|
|
693
|
+
server.tool("jaw_config_show", "Show current CLI configuration (API key redacted).", {}, async () => {
|
|
694
|
+
try {
|
|
695
|
+
const config = redactConfig(loadConfig());
|
|
696
|
+
return {
|
|
697
|
+
content: [{ type: "text", text: JSON.stringify(config) }]
|
|
698
|
+
};
|
|
699
|
+
} catch (err) {
|
|
700
|
+
return mcpError(err);
|
|
735
701
|
}
|
|
736
|
-
);
|
|
702
|
+
});
|
|
737
703
|
server.tool(
|
|
738
704
|
"jaw_config_set",
|
|
739
|
-
"Set a CLI configuration value (apiKey, defaultChain, keysUrl,
|
|
705
|
+
"Set a CLI configuration value (apiKey, defaultChain, keysUrl, ens, relayUrl).",
|
|
740
706
|
configSetSchema,
|
|
741
707
|
async (params) => {
|
|
742
708
|
try {
|
|
@@ -786,9 +752,7 @@ function registerDaemonTools(server) {
|
|
|
786
752
|
config
|
|
787
753
|
};
|
|
788
754
|
return {
|
|
789
|
-
content: [
|
|
790
|
-
{ type: "text", text: JSON.stringify(status, null, 2) }
|
|
791
|
-
]
|
|
755
|
+
content: [{ type: "text", text: JSON.stringify(status, null, 2) }]
|
|
792
756
|
};
|
|
793
757
|
} catch (err) {
|
|
794
758
|
return mcpError(err);
|
|
@@ -853,9 +817,7 @@ function registerResources(server) {
|
|
|
853
817
|
async (uri, variables) => {
|
|
854
818
|
const method = String(variables.method);
|
|
855
819
|
if (!/^[\w_]+$/.test(method)) {
|
|
856
|
-
throw new Error(
|
|
857
|
-
`Invalid method name: "${method}". Expected an RPC method like wallet_sendCalls.`
|
|
858
|
-
);
|
|
820
|
+
throw new Error(`Invalid method name: "${method}". Expected an RPC method like wallet_sendCalls.`);
|
|
859
821
|
}
|
|
860
822
|
return {
|
|
861
823
|
contents: [
|