@metamask-previews/wallet-cli 0.0.0-preview-8bfa290fb → 0.0.0-preview-e8a256c39
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/CHANGELOG.md +8 -4
- package/dist/commands/daemon/{call.d.mts → call.d.ts} +2 -2
- package/dist/commands/daemon/call.d.ts.map +1 -0
- package/dist/commands/daemon/{call.mjs → call.js} +30 -31
- package/dist/commands/daemon/call.js.map +1 -0
- package/dist/commands/daemon/{list.d.cts → list.d.ts} +2 -2
- package/dist/commands/daemon/list.d.ts.map +1 -0
- package/dist/commands/daemon/{list.mjs → list.js} +9 -10
- package/dist/commands/daemon/list.js.map +1 -0
- package/dist/commands/daemon/{purge.d.cts → purge.d.ts} +2 -2
- package/dist/commands/daemon/purge.d.ts.map +1 -0
- package/dist/commands/daemon/{purge.mjs → purge.js} +19 -20
- package/dist/commands/daemon/purge.js.map +1 -0
- package/dist/commands/daemon/{start.d.cts → start.d.ts} +2 -2
- package/dist/commands/daemon/start.d.ts.map +1 -0
- package/dist/commands/daemon/start.js +49 -0
- package/dist/commands/daemon/{start.cjs.map → start.js.map} +1 -1
- package/dist/commands/daemon/{status.d.cts → status.d.ts} +2 -2
- package/dist/commands/daemon/status.d.ts.map +1 -0
- package/dist/commands/daemon/{status.mjs → status.js} +10 -11
- package/dist/commands/daemon/status.js.map +1 -0
- package/dist/commands/daemon/{stop.d.cts → stop.d.ts} +2 -2
- package/dist/commands/daemon/stop.d.ts.map +1 -0
- package/dist/commands/daemon/{stop.mjs → stop.js} +9 -10
- package/dist/commands/daemon/stop.js.map +1 -0
- package/dist/commands/wallet/{send.d.cts → send.d.ts} +3 -3
- package/dist/commands/wallet/send.d.ts.map +1 -0
- package/dist/commands/wallet/{send.mjs → send.js} +111 -123
- package/dist/commands/wallet/send.js.map +1 -0
- package/dist/commands/wallet/{unlock.d.cts → unlock.d.ts} +2 -2
- package/dist/commands/wallet/unlock.d.ts.map +1 -0
- package/dist/commands/wallet/{unlock.mjs → unlock.js} +29 -30
- package/dist/commands/wallet/unlock.js.map +1 -0
- package/dist/daemon/{auto-approval.d.mts → auto-approval.d.ts} +3 -3
- package/dist/daemon/auto-approval.d.ts.map +1 -0
- package/dist/daemon/{auto-approval.mjs → auto-approval.js} +1 -1
- package/dist/daemon/auto-approval.js.map +1 -0
- package/dist/daemon/{daemon-client.d.mts → daemon-client.d.ts} +2 -2
- package/dist/daemon/daemon-client.d.ts.map +1 -0
- package/dist/daemon/{daemon-client.mjs → daemon-client.js} +8 -8
- package/dist/daemon/daemon-client.js.map +1 -0
- package/dist/daemon/daemon-entry.d.ts +2 -0
- package/dist/daemon/daemon-entry.d.ts.map +1 -0
- package/dist/daemon/{daemon-entry.mjs → daemon-entry.js} +12 -12
- package/dist/daemon/daemon-entry.js.map +1 -0
- package/dist/daemon/{daemon-spawn.d.mts → daemon-spawn.d.ts} +2 -2
- package/dist/daemon/daemon-spawn.d.ts.map +1 -0
- package/dist/daemon/{daemon-spawn.mjs → daemon-spawn.js} +7 -7
- package/dist/daemon/daemon-spawn.js.map +1 -0
- package/dist/daemon/{data-dir.d.cts → data-dir.d.ts} +1 -1
- package/dist/daemon/data-dir.d.ts.map +1 -0
- package/dist/daemon/{data-dir.mjs → data-dir.js} +3 -3
- package/dist/daemon/data-dir.js.map +1 -0
- package/dist/daemon/{paths.d.mts → paths.d.ts} +2 -2
- package/dist/daemon/paths.d.ts.map +1 -0
- package/dist/daemon/{paths.mjs → paths.js} +2 -2
- package/dist/daemon/paths.js.map +1 -0
- package/dist/daemon/{prompts.d.cts → prompts.d.ts} +1 -1
- package/dist/daemon/prompts.d.ts.map +1 -0
- package/dist/daemon/{prompts.mjs → prompts.js} +4 -4
- package/dist/daemon/prompts.js.map +1 -0
- package/dist/daemon/{rpc-socket-server.d.cts → rpc-socket-server.d.ts} +2 -2
- package/dist/daemon/rpc-socket-server.d.ts.map +1 -0
- package/dist/daemon/{rpc-socket-server.mjs → rpc-socket-server.js} +8 -8
- package/dist/daemon/rpc-socket-server.js.map +1 -0
- package/dist/daemon/{secrets.d.cts → secrets.d.ts} +1 -1
- package/dist/daemon/secrets.d.ts.map +1 -0
- package/dist/daemon/{secrets.mjs → secrets.js} +11 -23
- package/dist/daemon/secrets.js.map +1 -0
- package/dist/daemon/{send-transaction.d.cts → send-transaction.d.ts} +9 -9
- package/dist/daemon/send-transaction.d.ts.map +1 -0
- package/dist/daemon/{send-transaction.mjs → send-transaction.js} +3 -3
- package/dist/daemon/send-transaction.js.map +1 -0
- package/dist/daemon/{socket-line.d.cts → socket-line.d.ts} +2 -5
- package/dist/daemon/socket-line.d.ts.map +1 -0
- package/dist/daemon/{socket-line.mjs → socket-line.js} +1 -1
- package/dist/daemon/socket-line.js.map +1 -0
- package/dist/daemon/{stop-daemon.d.cts → stop-daemon.d.ts} +1 -1
- package/dist/daemon/stop-daemon.d.ts.map +1 -0
- package/dist/daemon/{stop-daemon.mjs → stop-daemon.js} +7 -7
- package/dist/daemon/stop-daemon.js.map +1 -0
- package/dist/daemon/{types.d.cts → types.d.ts} +4 -4
- package/dist/daemon/types.d.ts.map +1 -0
- package/dist/daemon/{types.mjs → types.js} +1 -1
- package/dist/daemon/types.js.map +1 -0
- package/dist/daemon/{utils.d.cts → utils.d.ts} +2 -3
- package/dist/daemon/utils.d.ts.map +1 -0
- package/dist/daemon/{utils.mjs → utils.js} +3 -3
- package/dist/daemon/utils.js.map +1 -0
- package/dist/daemon/{wallet-factory.d.cts → wallet-factory.d.ts} +4 -4
- package/dist/daemon/wallet-factory.d.ts.map +1 -0
- package/dist/daemon/{wallet-factory.mjs → wallet-factory.js} +12 -12
- package/dist/daemon/wallet-factory.js.map +1 -0
- package/dist/persistence/{KeyValueStore.d.cts → KeyValueStore.d.ts} +2 -2
- package/dist/persistence/KeyValueStore.d.ts.map +1 -0
- package/dist/persistence/KeyValueStore.js +59 -0
- package/dist/persistence/KeyValueStore.js.map +1 -0
- package/dist/persistence/{persistence.d.cts → persistence.d.ts} +5 -5
- package/dist/persistence/persistence.d.ts.map +1 -0
- package/dist/persistence/{persistence.mjs → persistence.js} +2 -2
- package/dist/persistence/persistence.js.map +1 -0
- package/dist/test/{run-command.d.cts → run-command.d.ts} +4 -4
- package/dist/test/run-command.d.ts.map +1 -0
- package/dist/test/{run-command.mjs → run-command.js} +3 -3
- package/dist/test/run-command.js.map +1 -0
- package/package.json +19 -15
- package/dist/commands/daemon/call.cjs +0 -79
- package/dist/commands/daemon/call.cjs.map +0 -1
- package/dist/commands/daemon/call.d.cts +0 -14
- package/dist/commands/daemon/call.d.cts.map +0 -1
- package/dist/commands/daemon/call.d.mts.map +0 -1
- package/dist/commands/daemon/call.mjs.map +0 -1
- package/dist/commands/daemon/list.cjs +0 -48
- package/dist/commands/daemon/list.cjs.map +0 -1
- package/dist/commands/daemon/list.d.cts.map +0 -1
- package/dist/commands/daemon/list.d.mts +0 -7
- package/dist/commands/daemon/list.d.mts.map +0 -1
- package/dist/commands/daemon/list.mjs.map +0 -1
- package/dist/commands/daemon/purge.cjs +0 -58
- package/dist/commands/daemon/purge.cjs.map +0 -1
- package/dist/commands/daemon/purge.d.cts.map +0 -1
- package/dist/commands/daemon/purge.d.mts +0 -10
- package/dist/commands/daemon/purge.d.mts.map +0 -1
- package/dist/commands/daemon/purge.mjs.map +0 -1
- package/dist/commands/daemon/start.cjs +0 -52
- package/dist/commands/daemon/start.d.cts.map +0 -1
- package/dist/commands/daemon/start.d.mts +0 -12
- package/dist/commands/daemon/start.d.mts.map +0 -1
- package/dist/commands/daemon/start.mjs +0 -50
- package/dist/commands/daemon/start.mjs.map +0 -1
- package/dist/commands/daemon/status.cjs +0 -59
- package/dist/commands/daemon/status.cjs.map +0 -1
- package/dist/commands/daemon/status.d.cts.map +0 -1
- package/dist/commands/daemon/status.d.mts +0 -7
- package/dist/commands/daemon/status.d.mts.map +0 -1
- package/dist/commands/daemon/status.mjs.map +0 -1
- package/dist/commands/daemon/stop.cjs +0 -26
- package/dist/commands/daemon/stop.cjs.map +0 -1
- package/dist/commands/daemon/stop.d.cts.map +0 -1
- package/dist/commands/daemon/stop.d.mts +0 -7
- package/dist/commands/daemon/stop.d.mts.map +0 -1
- package/dist/commands/daemon/stop.mjs.map +0 -1
- package/dist/commands/wallet/send.cjs +0 -332
- package/dist/commands/wallet/send.cjs.map +0 -1
- package/dist/commands/wallet/send.d.cts.map +0 -1
- package/dist/commands/wallet/send.d.mts +0 -42
- package/dist/commands/wallet/send.d.mts.map +0 -1
- package/dist/commands/wallet/send.mjs.map +0 -1
- package/dist/commands/wallet/unlock.cjs +0 -75
- package/dist/commands/wallet/unlock.cjs.map +0 -1
- package/dist/commands/wallet/unlock.d.cts.map +0 -1
- package/dist/commands/wallet/unlock.d.mts +0 -11
- package/dist/commands/wallet/unlock.d.mts.map +0 -1
- package/dist/commands/wallet/unlock.mjs.map +0 -1
- package/dist/daemon/auto-approval.cjs +0 -86
- package/dist/daemon/auto-approval.cjs.map +0 -1
- package/dist/daemon/auto-approval.d.cts +0 -22
- package/dist/daemon/auto-approval.d.cts.map +0 -1
- package/dist/daemon/auto-approval.d.mts.map +0 -1
- package/dist/daemon/auto-approval.mjs.map +0 -1
- package/dist/daemon/daemon-client.cjs +0 -149
- package/dist/daemon/daemon-client.cjs.map +0 -1
- package/dist/daemon/daemon-client.d.cts +0 -84
- package/dist/daemon/daemon-client.d.cts.map +0 -1
- package/dist/daemon/daemon-client.d.mts.map +0 -1
- package/dist/daemon/daemon-client.mjs.map +0 -1
- package/dist/daemon/daemon-entry.cjs +0 -278
- package/dist/daemon/daemon-entry.cjs.map +0 -1
- package/dist/daemon/daemon-entry.d.cts +0 -2
- package/dist/daemon/daemon-entry.d.cts.map +0 -1
- package/dist/daemon/daemon-entry.d.mts +0 -2
- package/dist/daemon/daemon-entry.d.mts.map +0 -1
- package/dist/daemon/daemon-entry.mjs.map +0 -1
- package/dist/daemon/daemon-spawn.cjs +0 -138
- package/dist/daemon/daemon-spawn.cjs.map +0 -1
- package/dist/daemon/daemon-spawn.d.cts +0 -28
- package/dist/daemon/daemon-spawn.d.cts.map +0 -1
- package/dist/daemon/daemon-spawn.d.mts.map +0 -1
- package/dist/daemon/daemon-spawn.mjs.map +0 -1
- package/dist/daemon/data-dir.cjs +0 -23
- package/dist/daemon/data-dir.cjs.map +0 -1
- package/dist/daemon/data-dir.d.cts.map +0 -1
- package/dist/daemon/data-dir.d.mts +0 -14
- package/dist/daemon/data-dir.d.mts.map +0 -1
- package/dist/daemon/data-dir.mjs.map +0 -1
- package/dist/daemon/paths.cjs +0 -20
- package/dist/daemon/paths.cjs.map +0 -1
- package/dist/daemon/paths.d.cts +0 -9
- package/dist/daemon/paths.d.cts.map +0 -1
- package/dist/daemon/paths.d.mts.map +0 -1
- package/dist/daemon/paths.mjs.map +0 -1
- package/dist/daemon/prompts.cjs +0 -55
- package/dist/daemon/prompts.cjs.map +0 -1
- package/dist/daemon/prompts.d.cts.map +0 -1
- package/dist/daemon/prompts.d.mts +0 -31
- package/dist/daemon/prompts.d.mts.map +0 -1
- package/dist/daemon/prompts.mjs.map +0 -1
- package/dist/daemon/rpc-socket-server.cjs +0 -284
- package/dist/daemon/rpc-socket-server.cjs.map +0 -1
- package/dist/daemon/rpc-socket-server.d.cts.map +0 -1
- package/dist/daemon/rpc-socket-server.d.mts +0 -44
- package/dist/daemon/rpc-socket-server.d.mts.map +0 -1
- package/dist/daemon/rpc-socket-server.mjs.map +0 -1
- package/dist/daemon/secrets.cjs +0 -137
- package/dist/daemon/secrets.cjs.map +0 -1
- package/dist/daemon/secrets.d.cts.map +0 -1
- package/dist/daemon/secrets.d.mts +0 -72
- package/dist/daemon/secrets.d.mts.map +0 -1
- package/dist/daemon/secrets.mjs.map +0 -1
- package/dist/daemon/send-transaction.cjs +0 -147
- package/dist/daemon/send-transaction.cjs.map +0 -1
- package/dist/daemon/send-transaction.d.cts.map +0 -1
- package/dist/daemon/send-transaction.d.mts +0 -102
- package/dist/daemon/send-transaction.d.mts.map +0 -1
- package/dist/daemon/send-transaction.mjs.map +0 -1
- package/dist/daemon/socket-line.cjs +0 -93
- package/dist/daemon/socket-line.cjs.map +0 -1
- package/dist/daemon/socket-line.d.cts.map +0 -1
- package/dist/daemon/socket-line.d.mts +0 -21
- package/dist/daemon/socket-line.d.mts.map +0 -1
- package/dist/daemon/socket-line.mjs.map +0 -1
- package/dist/daemon/stop-daemon.cjs +0 -117
- package/dist/daemon/stop-daemon.cjs.map +0 -1
- package/dist/daemon/stop-daemon.d.cts.map +0 -1
- package/dist/daemon/stop-daemon.d.mts +0 -28
- package/dist/daemon/stop-daemon.d.mts.map +0 -1
- package/dist/daemon/stop-daemon.mjs.map +0 -1
- package/dist/daemon/types.cjs +0 -20
- package/dist/daemon/types.cjs.map +0 -1
- package/dist/daemon/types.d.cts.map +0 -1
- package/dist/daemon/types.d.mts +0 -94
- package/dist/daemon/types.d.mts.map +0 -1
- package/dist/daemon/types.mjs.map +0 -1
- package/dist/daemon/utils.cjs +0 -172
- package/dist/daemon/utils.cjs.map +0 -1
- package/dist/daemon/utils.d.cts.map +0 -1
- package/dist/daemon/utils.d.mts +0 -87
- package/dist/daemon/utils.d.mts.map +0 -1
- package/dist/daemon/utils.mjs.map +0 -1
- package/dist/daemon/wallet-factory.cjs +0 -341
- package/dist/daemon/wallet-factory.cjs.map +0 -1
- package/dist/daemon/wallet-factory.d.cts.map +0 -1
- package/dist/daemon/wallet-factory.d.mts +0 -64
- package/dist/daemon/wallet-factory.d.mts.map +0 -1
- package/dist/daemon/wallet-factory.mjs.map +0 -1
- package/dist/persistence/KeyValueStore.cjs +0 -79
- package/dist/persistence/KeyValueStore.cjs.map +0 -1
- package/dist/persistence/KeyValueStore.d.cts.map +0 -1
- package/dist/persistence/KeyValueStore.d.mts +0 -18
- package/dist/persistence/KeyValueStore.d.mts.map +0 -1
- package/dist/persistence/KeyValueStore.mjs +0 -79
- package/dist/persistence/KeyValueStore.mjs.map +0 -1
- package/dist/persistence/persistence.cjs +0 -204
- package/dist/persistence/persistence.cjs.map +0 -1
- package/dist/persistence/persistence.d.cts.map +0 -1
- package/dist/persistence/persistence.d.mts +0 -45
- package/dist/persistence/persistence.d.mts.map +0 -1
- package/dist/persistence/persistence.mjs.map +0 -1
- package/dist/test/run-command.cjs +0 -73
- package/dist/test/run-command.cjs.map +0 -1
- package/dist/test/run-command.d.cts.map +0 -1
- package/dist/test/run-command.d.mts +0 -27
- package/dist/test/run-command.d.mts.map +0 -1
- package/dist/test/run-command.mjs.map +0 -1
package/dist/daemon/data-dir.cjs
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ensureOwnerOnlyDirectory = void 0;
|
|
4
|
-
const node_fs_1 = require("node:fs");
|
|
5
|
-
const promises_1 = require("node:fs/promises");
|
|
6
|
-
/**
|
|
7
|
-
* Create the daemon's data directory (if it does not exist) and restrict it to
|
|
8
|
-
* the owning user.
|
|
9
|
-
*
|
|
10
|
-
* The mode is `0o700` (owner-only). The daemon exposes the full wallet
|
|
11
|
-
* messenger over the socket inside this directory, so anyone who can traverse
|
|
12
|
-
* the dir can also `connect()` to the socket. Restricting to the owning user is
|
|
13
|
-
* the only access-control boundary. We `chmod` after `mkdir` because the `mode`
|
|
14
|
-
* option is ignored when the directory already exists.
|
|
15
|
-
*
|
|
16
|
-
* @param dataDir - The data directory to create and lock down.
|
|
17
|
-
*/
|
|
18
|
-
async function ensureOwnerOnlyDirectory(dataDir) {
|
|
19
|
-
(0, node_fs_1.mkdirSync)(dataDir, { recursive: true, mode: 0o700 });
|
|
20
|
-
await (0, promises_1.chmod)(dataDir, 0o700);
|
|
21
|
-
}
|
|
22
|
-
exports.ensureOwnerOnlyDirectory = ensureOwnerOnlyDirectory;
|
|
23
|
-
//# sourceMappingURL=data-dir.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"data-dir.cjs","sourceRoot":"","sources":["../../src/daemon/data-dir.ts"],"names":[],"mappings":";;;AAAA,qCAAoC;AACpC,+CAAyC;AAEzC;;;;;;;;;;;GAWG;AACI,KAAK,UAAU,wBAAwB,CAAC,OAAe;IAC5D,IAAA,mBAAS,EAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACrD,MAAM,IAAA,gBAAK,EAAC,OAAO,EAAE,KAAK,CAAC,CAAC;AAC9B,CAAC;AAHD,4DAGC","sourcesContent":["import { mkdirSync } from 'node:fs';\nimport { chmod } from 'node:fs/promises';\n\n/**\n * Create the daemon's data directory (if it does not exist) and restrict it to\n * the owning user.\n *\n * The mode is `0o700` (owner-only). The daemon exposes the full wallet\n * messenger over the socket inside this directory, so anyone who can traverse\n * the dir can also `connect()` to the socket. Restricting to the owning user is\n * the only access-control boundary. We `chmod` after `mkdir` because the `mode`\n * option is ignored when the directory already exists.\n *\n * @param dataDir - The data directory to create and lock down.\n */\nexport async function ensureOwnerOnlyDirectory(dataDir: string): Promise<void> {\n mkdirSync(dataDir, { recursive: true, mode: 0o700 });\n await chmod(dataDir, 0o700);\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"data-dir.d.cts","sourceRoot":"","sources":["../../src/daemon/data-dir.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;GAWG;AACH,wBAAsB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAG7E"}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Create the daemon's data directory (if it does not exist) and restrict it to
|
|
3
|
-
* the owning user.
|
|
4
|
-
*
|
|
5
|
-
* The mode is `0o700` (owner-only). The daemon exposes the full wallet
|
|
6
|
-
* messenger over the socket inside this directory, so anyone who can traverse
|
|
7
|
-
* the dir can also `connect()` to the socket. Restricting to the owning user is
|
|
8
|
-
* the only access-control boundary. We `chmod` after `mkdir` because the `mode`
|
|
9
|
-
* option is ignored when the directory already exists.
|
|
10
|
-
*
|
|
11
|
-
* @param dataDir - The data directory to create and lock down.
|
|
12
|
-
*/
|
|
13
|
-
export declare function ensureOwnerOnlyDirectory(dataDir: string): Promise<void>;
|
|
14
|
-
//# sourceMappingURL=data-dir.d.mts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"data-dir.d.mts","sourceRoot":"","sources":["../../src/daemon/data-dir.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;GAWG;AACH,wBAAsB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAG7E"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"data-dir.mjs","sourceRoot":"","sources":["../../src/daemon/data-dir.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,gBAAgB;AACpC,OAAO,EAAE,KAAK,EAAE,yBAAyB;AAEzC;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAAC,OAAe;IAC5D,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACrD,MAAM,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;AAC9B,CAAC","sourcesContent":["import { mkdirSync } from 'node:fs';\nimport { chmod } from 'node:fs/promises';\n\n/**\n * Create the daemon's data directory (if it does not exist) and restrict it to\n * the owning user.\n *\n * The mode is `0o700` (owner-only). The daemon exposes the full wallet\n * messenger over the socket inside this directory, so anyone who can traverse\n * the dir can also `connect()` to the socket. Restricting to the owning user is\n * the only access-control boundary. We `chmod` after `mkdir` because the `mode`\n * option is ignored when the directory already exists.\n *\n * @param dataDir - The data directory to create and lock down.\n */\nexport async function ensureOwnerOnlyDirectory(dataDir: string): Promise<void> {\n mkdirSync(dataDir, { recursive: true, mode: 0o700 });\n await chmod(dataDir, 0o700);\n}\n"]}
|
package/dist/daemon/paths.cjs
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getDaemonPaths = void 0;
|
|
4
|
-
const node_path_1 = require("node:path");
|
|
5
|
-
/**
|
|
6
|
-
* Resolve paths for daemon state files within the given data directory.
|
|
7
|
-
*
|
|
8
|
-
* @param dataDir - The base data directory (e.g. oclif config.dataDir).
|
|
9
|
-
* @returns Resolved paths for socket, PID file, log file, and database file.
|
|
10
|
-
*/
|
|
11
|
-
function getDaemonPaths(dataDir) {
|
|
12
|
-
return {
|
|
13
|
-
socketPath: (0, node_path_1.join)(dataDir, 'daemon.sock'),
|
|
14
|
-
pidPath: (0, node_path_1.join)(dataDir, 'daemon.pid'),
|
|
15
|
-
logPath: (0, node_path_1.join)(dataDir, 'daemon.log'),
|
|
16
|
-
dbPath: (0, node_path_1.join)(dataDir, 'wallet.db'),
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
exports.getDaemonPaths = getDaemonPaths;
|
|
20
|
-
//# sourceMappingURL=paths.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"paths.cjs","sourceRoot":"","sources":["../../src/daemon/paths.ts"],"names":[],"mappings":";;;AAAA,yCAAiC;AAIjC;;;;;GAKG;AACH,SAAgB,cAAc,CAAC,OAAe;IAC5C,OAAO;QACL,UAAU,EAAE,IAAA,gBAAI,EAAC,OAAO,EAAE,aAAa,CAAC;QACxC,OAAO,EAAE,IAAA,gBAAI,EAAC,OAAO,EAAE,YAAY,CAAC;QACpC,OAAO,EAAE,IAAA,gBAAI,EAAC,OAAO,EAAE,YAAY,CAAC;QACpC,MAAM,EAAE,IAAA,gBAAI,EAAC,OAAO,EAAE,WAAW,CAAC;KACnC,CAAC;AACJ,CAAC;AAPD,wCAOC","sourcesContent":["import { join } from 'node:path';\n\nimport type { DaemonPaths } from './types.js';\n\n/**\n * Resolve paths for daemon state files within the given data directory.\n *\n * @param dataDir - The base data directory (e.g. oclif config.dataDir).\n * @returns Resolved paths for socket, PID file, log file, and database file.\n */\nexport function getDaemonPaths(dataDir: string): DaemonPaths {\n return {\n socketPath: join(dataDir, 'daemon.sock'),\n pidPath: join(dataDir, 'daemon.pid'),\n logPath: join(dataDir, 'daemon.log'),\n dbPath: join(dataDir, 'wallet.db'),\n };\n}\n"]}
|
package/dist/daemon/paths.d.cts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { DaemonPaths } from "./types.cjs";
|
|
2
|
-
/**
|
|
3
|
-
* Resolve paths for daemon state files within the given data directory.
|
|
4
|
-
*
|
|
5
|
-
* @param dataDir - The base data directory (e.g. oclif config.dataDir).
|
|
6
|
-
* @returns Resolved paths for socket, PID file, log file, and database file.
|
|
7
|
-
*/
|
|
8
|
-
export declare function getDaemonPaths(dataDir: string): DaemonPaths;
|
|
9
|
-
//# sourceMappingURL=paths.d.cts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"paths.d.cts","sourceRoot":"","sources":["../../src/daemon/paths.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,oBAAmB;AAE9C;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,CAO3D"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"paths.d.mts","sourceRoot":"","sources":["../../src/daemon/paths.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,oBAAmB;AAE9C;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,CAO3D"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"paths.mjs","sourceRoot":"","sources":["../../src/daemon/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,kBAAkB;AAIjC;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,OAAe;IAC5C,OAAO;QACL,UAAU,EAAE,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC;QACxC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC;QACpC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC;QACpC,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC;KACnC,CAAC;AACJ,CAAC","sourcesContent":["import { join } from 'node:path';\n\nimport type { DaemonPaths } from './types.js';\n\n/**\n * Resolve paths for daemon state files within the given data directory.\n *\n * @param dataDir - The base data directory (e.g. oclif config.dataDir).\n * @returns Resolved paths for socket, PID file, log file, and database file.\n */\nexport function getDaemonPaths(dataDir: string): DaemonPaths {\n return {\n socketPath: join(dataDir, 'daemon.sock'),\n pidPath: join(dataDir, 'daemon.pid'),\n logPath: join(dataDir, 'daemon.log'),\n dbPath: join(dataDir, 'wallet.db'),\n };\n}\n"]}
|
package/dist/daemon/prompts.cjs
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.promptPassword = exports.confirmSend = exports.confirmPurge = void 0;
|
|
4
|
-
/**
|
|
5
|
-
* Ask the user to confirm the destructive `daemon purge` operation.
|
|
6
|
-
*
|
|
7
|
-
* Wraps `@inquirer/confirm` in a dynamic import so this CommonJS-compiled
|
|
8
|
-
* package can interop with that ESM-only dependency, and so tests can mock
|
|
9
|
-
* the prompt without going through jest's ESM mock machinery.
|
|
10
|
-
*
|
|
11
|
-
* @returns True if the user confirmed.
|
|
12
|
-
*/
|
|
13
|
-
async function confirmPurge() {
|
|
14
|
-
const { default: confirm } = await import("@inquirer/confirm");
|
|
15
|
-
return confirm({
|
|
16
|
-
message: 'This will stop the daemon and delete all state. Continue?',
|
|
17
|
-
default: false,
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
exports.confirmPurge = confirmPurge;
|
|
21
|
-
/**
|
|
22
|
-
* Ask the user to confirm broadcasting a transaction. Used by `mm wallet send`
|
|
23
|
-
* when neither `--yes` nor `--dry-run` was passed. Same dynamic-import +
|
|
24
|
-
* ESM-interop pattern as {@link confirmPurge}. Defaults to `false` so an
|
|
25
|
-
* accidental bare Enter never broadcasts.
|
|
26
|
-
*
|
|
27
|
-
* @param summary - A human-readable description of the transaction to send
|
|
28
|
-
* (recipient, amount, network), shown above the prompt.
|
|
29
|
-
* @returns True if the user confirmed.
|
|
30
|
-
*/
|
|
31
|
-
async function confirmSend(summary) {
|
|
32
|
-
const { default: confirm } = await import("@inquirer/confirm");
|
|
33
|
-
return confirm({
|
|
34
|
-
message: `${summary}\nBroadcast this transaction?`,
|
|
35
|
-
default: false,
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
exports.confirmSend = confirmSend;
|
|
39
|
-
/**
|
|
40
|
-
* Prompt the user for the wallet password, with input masked. Used by
|
|
41
|
-
* `mm wallet unlock` when the user did not pass `--password` or set the
|
|
42
|
-
* `MM_WALLET_PASSWORD` env var. Same dynamic-import + ESM-interop pattern
|
|
43
|
-
* as {@link confirmPurge}.
|
|
44
|
-
*
|
|
45
|
-
* @returns The password the user typed.
|
|
46
|
-
*/
|
|
47
|
-
async function promptPassword() {
|
|
48
|
-
const { default: password } = await import("@inquirer/password");
|
|
49
|
-
return password({
|
|
50
|
-
message: 'Wallet password:',
|
|
51
|
-
mask: true,
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
exports.promptPassword = promptPassword;
|
|
55
|
-
//# sourceMappingURL=prompts.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prompts.cjs","sourceRoot":"","sources":["../../src/daemon/prompts.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;GAQG;AACI,KAAK,UAAU,YAAY;IAChC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,qBAAqB,CAAC;IAC/D,OAAO,OAAO,CAAC;QACb,OAAO,EAAE,2DAA2D;QACpE,OAAO,EAAE,KAAK;KACf,CAAC,CAAC;AACL,CAAC;AAND,oCAMC;AAED;;;;;;;;;GASG;AACI,KAAK,UAAU,WAAW,CAAC,OAAe;IAC/C,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,qBAAqB,CAAC;IAC/D,OAAO,OAAO,CAAC;QACb,OAAO,EAAE,GAAG,OAAO,+BAA+B;QAClD,OAAO,EAAE,KAAK;KACf,CAAC,CAAC;AACL,CAAC;AAND,kCAMC;AAED;;;;;;;GAOG;AACI,KAAK,UAAU,cAAc;IAClC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,sBAAsB,CAAC;IACjE,OAAO,QAAQ,CAAC;QACd,OAAO,EAAE,kBAAkB;QAC3B,IAAI,EAAE,IAAI;KACX,CAAC,CAAC;AACL,CAAC;AAND,wCAMC","sourcesContent":["/**\n * Ask the user to confirm the destructive `daemon purge` operation.\n *\n * Wraps `@inquirer/confirm` in a dynamic import so this CommonJS-compiled\n * package can interop with that ESM-only dependency, and so tests can mock\n * the prompt without going through jest's ESM mock machinery.\n *\n * @returns True if the user confirmed.\n */\nexport async function confirmPurge(): Promise<boolean> {\n const { default: confirm } = await import('@inquirer/confirm');\n return confirm({\n message: 'This will stop the daemon and delete all state. Continue?',\n default: false,\n });\n}\n\n/**\n * Ask the user to confirm broadcasting a transaction. Used by `mm wallet send`\n * when neither `--yes` nor `--dry-run` was passed. Same dynamic-import +\n * ESM-interop pattern as {@link confirmPurge}. Defaults to `false` so an\n * accidental bare Enter never broadcasts.\n *\n * @param summary - A human-readable description of the transaction to send\n * (recipient, amount, network), shown above the prompt.\n * @returns True if the user confirmed.\n */\nexport async function confirmSend(summary: string): Promise<boolean> {\n const { default: confirm } = await import('@inquirer/confirm');\n return confirm({\n message: `${summary}\\nBroadcast this transaction?`,\n default: false,\n });\n}\n\n/**\n * Prompt the user for the wallet password, with input masked. Used by\n * `mm wallet unlock` when the user did not pass `--password` or set the\n * `MM_WALLET_PASSWORD` env var. Same dynamic-import + ESM-interop pattern\n * as {@link confirmPurge}.\n *\n * @returns The password the user typed.\n */\nexport async function promptPassword(): Promise<string> {\n const { default: password } = await import('@inquirer/password');\n return password({\n message: 'Wallet password:',\n mask: true,\n });\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prompts.d.cts","sourceRoot":"","sources":["../../src/daemon/prompts.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,OAAO,CAAC,CAMrD;AAED;;;;;;;;;GASG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAMnE;AAED;;;;;;;GAOG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,CAMtD"}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Ask the user to confirm the destructive `daemon purge` operation.
|
|
3
|
-
*
|
|
4
|
-
* Wraps `@inquirer/confirm` in a dynamic import so this CommonJS-compiled
|
|
5
|
-
* package can interop with that ESM-only dependency, and so tests can mock
|
|
6
|
-
* the prompt without going through jest's ESM mock machinery.
|
|
7
|
-
*
|
|
8
|
-
* @returns True if the user confirmed.
|
|
9
|
-
*/
|
|
10
|
-
export declare function confirmPurge(): Promise<boolean>;
|
|
11
|
-
/**
|
|
12
|
-
* Ask the user to confirm broadcasting a transaction. Used by `mm wallet send`
|
|
13
|
-
* when neither `--yes` nor `--dry-run` was passed. Same dynamic-import +
|
|
14
|
-
* ESM-interop pattern as {@link confirmPurge}. Defaults to `false` so an
|
|
15
|
-
* accidental bare Enter never broadcasts.
|
|
16
|
-
*
|
|
17
|
-
* @param summary - A human-readable description of the transaction to send
|
|
18
|
-
* (recipient, amount, network), shown above the prompt.
|
|
19
|
-
* @returns True if the user confirmed.
|
|
20
|
-
*/
|
|
21
|
-
export declare function confirmSend(summary: string): Promise<boolean>;
|
|
22
|
-
/**
|
|
23
|
-
* Prompt the user for the wallet password, with input masked. Used by
|
|
24
|
-
* `mm wallet unlock` when the user did not pass `--password` or set the
|
|
25
|
-
* `MM_WALLET_PASSWORD` env var. Same dynamic-import + ESM-interop pattern
|
|
26
|
-
* as {@link confirmPurge}.
|
|
27
|
-
*
|
|
28
|
-
* @returns The password the user typed.
|
|
29
|
-
*/
|
|
30
|
-
export declare function promptPassword(): Promise<string>;
|
|
31
|
-
//# sourceMappingURL=prompts.d.mts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prompts.d.mts","sourceRoot":"","sources":["../../src/daemon/prompts.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,OAAO,CAAC,CAMrD;AAED;;;;;;;;;GASG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAMnE;AAED;;;;;;;GAOG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,CAMtD"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prompts.mjs","sourceRoot":"","sources":["../../src/daemon/prompts.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,qBAAqB,CAAC;IAC/D,OAAO,OAAO,CAAC;QACb,OAAO,EAAE,2DAA2D;QACpE,OAAO,EAAE,KAAK;KACf,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAe;IAC/C,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,qBAAqB,CAAC;IAC/D,OAAO,OAAO,CAAC;QACb,OAAO,EAAE,GAAG,OAAO,+BAA+B;QAClD,OAAO,EAAE,KAAK;KACf,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,sBAAsB,CAAC;IACjE,OAAO,QAAQ,CAAC;QACd,OAAO,EAAE,kBAAkB;QAC3B,IAAI,EAAE,IAAI;KACX,CAAC,CAAC;AACL,CAAC","sourcesContent":["/**\n * Ask the user to confirm the destructive `daemon purge` operation.\n *\n * Wraps `@inquirer/confirm` in a dynamic import so this CommonJS-compiled\n * package can interop with that ESM-only dependency, and so tests can mock\n * the prompt without going through jest's ESM mock machinery.\n *\n * @returns True if the user confirmed.\n */\nexport async function confirmPurge(): Promise<boolean> {\n const { default: confirm } = await import('@inquirer/confirm');\n return confirm({\n message: 'This will stop the daemon and delete all state. Continue?',\n default: false,\n });\n}\n\n/**\n * Ask the user to confirm broadcasting a transaction. Used by `mm wallet send`\n * when neither `--yes` nor `--dry-run` was passed. Same dynamic-import +\n * ESM-interop pattern as {@link confirmPurge}. Defaults to `false` so an\n * accidental bare Enter never broadcasts.\n *\n * @param summary - A human-readable description of the transaction to send\n * (recipient, amount, network), shown above the prompt.\n * @returns True if the user confirmed.\n */\nexport async function confirmSend(summary: string): Promise<boolean> {\n const { default: confirm } = await import('@inquirer/confirm');\n return confirm({\n message: `${summary}\\nBroadcast this transaction?`,\n default: false,\n });\n}\n\n/**\n * Prompt the user for the wallet password, with input masked. Used by\n * `mm wallet unlock` when the user did not pass `--password` or set the\n * `MM_WALLET_PASSWORD` env var. Same dynamic-import + ESM-interop pattern\n * as {@link confirmPurge}.\n *\n * @returns The password the user typed.\n */\nexport async function promptPassword(): Promise<string> {\n const { default: password } = await import('@inquirer/password');\n return password({\n message: 'Wallet password:',\n mask: true,\n });\n}\n"]}
|
|
@@ -1,284 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.startRpcSocketServer = void 0;
|
|
4
|
-
const rpc_errors_1 = require("@metamask/rpc-errors");
|
|
5
|
-
const superstruct_1 = require("@metamask/superstruct");
|
|
6
|
-
const utils_1 = require("@metamask/utils");
|
|
7
|
-
const promises_1 = require("node:fs/promises");
|
|
8
|
-
const node_net_1 = require("node:net");
|
|
9
|
-
const utils_js_1 = require("./utils.cjs");
|
|
10
|
-
const CONNECTION_TIMEOUT_MS = 30000;
|
|
11
|
-
/**
|
|
12
|
-
* Start a Unix socket server that processes JSON-RPC requests.
|
|
13
|
-
*
|
|
14
|
-
* Each connection reads one newline-delimited JSON-RPC request, processes it
|
|
15
|
-
* via the provided handler map, writes a JSON-RPC response, and closes.
|
|
16
|
-
*
|
|
17
|
-
* The special `shutdown` method is intercepted before handler dispatch and
|
|
18
|
-
* triggers the provided {@link StartRpcSocketServerOptions.onShutdown} callback
|
|
19
|
-
* after responding.
|
|
20
|
-
*
|
|
21
|
-
* @param options - Server options.
|
|
22
|
-
* @param options.socketPath - The Unix socket path to listen on.
|
|
23
|
-
* @param options.handlers - Map of RPC method names to handler functions.
|
|
24
|
-
* @param options.onShutdown - Optional callback invoked when a `shutdown` RPC is received.
|
|
25
|
-
* @param options.log - Optional logger for server-side diagnostics.
|
|
26
|
-
* @returns A handle with a `close()` function for cleanup.
|
|
27
|
-
*/
|
|
28
|
-
async function startRpcSocketServer({ socketPath, handlers, onShutdown, log, }) {
|
|
29
|
-
const logFn = log ?? defaultLog;
|
|
30
|
-
const server = (0, node_net_1.createServer)((socket) => {
|
|
31
|
-
let buffer = '';
|
|
32
|
-
// Destroy connections that never send a complete request line. `unref` so
|
|
33
|
-
// the timer alone cannot keep the event loop alive at shutdown.
|
|
34
|
-
const timer = setTimeout(() => {
|
|
35
|
-
socket.destroy();
|
|
36
|
-
}, CONNECTION_TIMEOUT_MS);
|
|
37
|
-
timer.unref();
|
|
38
|
-
/**
|
|
39
|
-
* Clear the idle-connection timer. Called from data, close, and error
|
|
40
|
-
* paths so the timer never outlives the connection itself.
|
|
41
|
-
*/
|
|
42
|
-
const clearIdleTimer = () => {
|
|
43
|
-
clearTimeout(timer);
|
|
44
|
-
};
|
|
45
|
-
const onData = (data) => {
|
|
46
|
-
buffer += data.toString();
|
|
47
|
-
const idx = buffer.indexOf('\n');
|
|
48
|
-
if (idx === -1) {
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
clearIdleTimer();
|
|
52
|
-
// One request per connection.
|
|
53
|
-
socket.removeListener('data', onData);
|
|
54
|
-
const line = buffer.slice(0, idx);
|
|
55
|
-
const remaining = buffer.slice(idx + 1);
|
|
56
|
-
buffer = '';
|
|
57
|
-
if (remaining.length > 0) {
|
|
58
|
-
socket.end(`${JSON.stringify({
|
|
59
|
-
jsonrpc: '2.0',
|
|
60
|
-
error: rpc_errors_1.rpcErrors
|
|
61
|
-
.invalidRequest({
|
|
62
|
-
message: 'Only one request per connection is allowed',
|
|
63
|
-
})
|
|
64
|
-
.serialize(),
|
|
65
|
-
})}\n`);
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
handleRequest(handlers, line, onShutdown, logFn)
|
|
69
|
-
.then((response) => {
|
|
70
|
-
socket.end(`${JSON.stringify(response)}\n`);
|
|
71
|
-
return undefined;
|
|
72
|
-
})
|
|
73
|
-
.catch((dispatchError) => {
|
|
74
|
-
logFn(`Unhandled RPC dispatch error: ${String(dispatchError)}`);
|
|
75
|
-
socket.end(`${JSON.stringify({
|
|
76
|
-
jsonrpc: '2.0',
|
|
77
|
-
error: rpc_errors_1.rpcErrors
|
|
78
|
-
.internal({ message: 'Internal error' })
|
|
79
|
-
.serialize(),
|
|
80
|
-
})}\n`);
|
|
81
|
-
});
|
|
82
|
-
};
|
|
83
|
-
socket.on('data', onData);
|
|
84
|
-
socket.once('close', clearIdleTimer);
|
|
85
|
-
socket.on('error', (socketError) => {
|
|
86
|
-
clearIdleTimer();
|
|
87
|
-
const { code } = socketError;
|
|
88
|
-
if (code === 'EPIPE' || code === 'ECONNRESET') {
|
|
89
|
-
return; // Expected during probe/disconnect.
|
|
90
|
-
}
|
|
91
|
-
logFn(`Unexpected socket error: ${String(socketError)}`);
|
|
92
|
-
});
|
|
93
|
-
});
|
|
94
|
-
await listen(server, socketPath);
|
|
95
|
-
return {
|
|
96
|
-
close: async () => closeServer(server),
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
exports.startRpcSocketServer = startRpcSocketServer;
|
|
100
|
-
/**
|
|
101
|
-
* Default fallback logger: writes to stderr. Daemons spawned with
|
|
102
|
-
* `stdio: 'ignore'` should always pass an explicit `log`.
|
|
103
|
-
*
|
|
104
|
-
* @param message - The message to log.
|
|
105
|
-
*/
|
|
106
|
-
function defaultLog(message) {
|
|
107
|
-
process.stderr.write(`${message}\n`);
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* Handle a single JSON-RPC request line, intercepting the `shutdown` method.
|
|
111
|
-
*
|
|
112
|
-
* @param handlers - The RPC handler map.
|
|
113
|
-
* @param line - The raw JSON line from the socket.
|
|
114
|
-
* @param onShutdown - Optional shutdown callback.
|
|
115
|
-
* @param log - Logger for diagnostic messages.
|
|
116
|
-
* @returns A JSON-RPC response object.
|
|
117
|
-
*/
|
|
118
|
-
async function handleRequest(handlers, line, onShutdown, log) {
|
|
119
|
-
let parsed;
|
|
120
|
-
try {
|
|
121
|
-
parsed = JSON.parse(line);
|
|
122
|
-
}
|
|
123
|
-
catch {
|
|
124
|
-
return {
|
|
125
|
-
jsonrpc: '2.0',
|
|
126
|
-
id: null,
|
|
127
|
-
error: rpc_errors_1.rpcErrors.parse({ message: 'Parse error' }).serialize(),
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
if (!(0, utils_1.isJsonRpcRequest)(parsed)) {
|
|
131
|
-
const id = typeof parsed === 'object' &&
|
|
132
|
-
parsed !== null &&
|
|
133
|
-
(0, utils_1.hasProperty)(parsed, 'id') &&
|
|
134
|
-
isValidJsonRpcId(parsed.id)
|
|
135
|
-
? parsed.id
|
|
136
|
-
: null;
|
|
137
|
-
return {
|
|
138
|
-
jsonrpc: '2.0',
|
|
139
|
-
id,
|
|
140
|
-
error: rpc_errors_1.rpcErrors
|
|
141
|
-
.invalidRequest({ message: 'Invalid JSON-RPC request' })
|
|
142
|
-
.serialize(),
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
const { id, method, params } = parsed;
|
|
146
|
-
try {
|
|
147
|
-
if (method === 'shutdown') {
|
|
148
|
-
if (onShutdown) {
|
|
149
|
-
setTimeout(() => {
|
|
150
|
-
onShutdown().catch((error) => {
|
|
151
|
-
log(`onShutdown callback failed: ${String(error)}`);
|
|
152
|
-
});
|
|
153
|
-
}, 0);
|
|
154
|
-
}
|
|
155
|
-
return { jsonrpc: '2.0', id, result: { status: 'shutting down' } };
|
|
156
|
-
}
|
|
157
|
-
const handler = Object.prototype.hasOwnProperty.call(handlers, method)
|
|
158
|
-
? handlers[method]
|
|
159
|
-
: undefined;
|
|
160
|
-
if (!handler) {
|
|
161
|
-
return {
|
|
162
|
-
jsonrpc: '2.0',
|
|
163
|
-
id,
|
|
164
|
-
error: rpc_errors_1.rpcErrors
|
|
165
|
-
.methodNotFound({ message: `Method not found: ${method}` })
|
|
166
|
-
.serialize(),
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
const [structError, validatedParams] = (0, superstruct_1.validate)(coerceHandlerParams(params), handler.paramsStruct);
|
|
170
|
-
if (structError !== undefined) {
|
|
171
|
-
return {
|
|
172
|
-
jsonrpc: '2.0',
|
|
173
|
-
id,
|
|
174
|
-
error: rpc_errors_1.rpcErrors
|
|
175
|
-
.invalidParams({
|
|
176
|
-
message: `Invalid params for ${method}: ${structError.message}`,
|
|
177
|
-
})
|
|
178
|
-
.serialize(),
|
|
179
|
-
};
|
|
180
|
-
}
|
|
181
|
-
const result = await handler.run(validatedParams);
|
|
182
|
-
return { jsonrpc: '2.0', id, result: result ?? null };
|
|
183
|
-
}
|
|
184
|
-
catch (error) {
|
|
185
|
-
log(`RPC handler "${method}" failed: ${String(error)}`);
|
|
186
|
-
if (isRpcError(error)) {
|
|
187
|
-
return { jsonrpc: '2.0', id, error };
|
|
188
|
-
}
|
|
189
|
-
const message = error instanceof Error ? error.message : 'Internal error';
|
|
190
|
-
return {
|
|
191
|
-
jsonrpc: '2.0',
|
|
192
|
-
id,
|
|
193
|
-
error: rpc_errors_1.rpcErrors.internal({ message }).serialize(),
|
|
194
|
-
};
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
/**
|
|
198
|
-
* Narrow `params` to the shape handlers expect. JSON-RPC 2.0 requires
|
|
199
|
-
* `params`, when present, to be an array or object; both are valid `Json`.
|
|
200
|
-
*
|
|
201
|
-
* @param params - The validated `params` field from a JSON-RPC request.
|
|
202
|
-
* @returns The same value, or `null` when absent.
|
|
203
|
-
*/
|
|
204
|
-
function coerceHandlerParams(params) {
|
|
205
|
-
return params ?? null;
|
|
206
|
-
}
|
|
207
|
-
/**
|
|
208
|
-
* Per JSON-RPC 2.0, `id` must be a string, number, or null. Used when
|
|
209
|
-
* salvaging an `id` from a parse-success-but-not-valid-request payload.
|
|
210
|
-
*
|
|
211
|
-
* @param value - The candidate id.
|
|
212
|
-
* @returns True if the value is an acceptable JSON-RPC id.
|
|
213
|
-
*/
|
|
214
|
-
function isValidJsonRpcId(value) {
|
|
215
|
-
return (value === null || typeof value === 'string' || typeof value === 'number');
|
|
216
|
-
}
|
|
217
|
-
/**
|
|
218
|
-
* Check if an error is an RPC error with a numeric code.
|
|
219
|
-
*
|
|
220
|
-
* @param error - The error to check.
|
|
221
|
-
* @returns True if the error has a numeric code property.
|
|
222
|
-
*/
|
|
223
|
-
function isRpcError(error) {
|
|
224
|
-
return (typeof error === 'object' &&
|
|
225
|
-
error !== null &&
|
|
226
|
-
(0, utils_1.hasProperty)(error, 'code') &&
|
|
227
|
-
typeof error.code === 'number' &&
|
|
228
|
-
(0, utils_1.hasProperty)(error, 'message') &&
|
|
229
|
-
typeof error.message === 'string');
|
|
230
|
-
}
|
|
231
|
-
/**
|
|
232
|
-
* Start listening on a Unix socket path, removing any stale socket file.
|
|
233
|
-
*
|
|
234
|
-
* @param server - The net.Server instance.
|
|
235
|
-
* @param socketPath - The Unix socket path.
|
|
236
|
-
*/
|
|
237
|
-
async function listen(server, socketPath) {
|
|
238
|
-
try {
|
|
239
|
-
await (0, promises_1.unlink)(socketPath);
|
|
240
|
-
}
|
|
241
|
-
catch (error) {
|
|
242
|
-
if (!(0, utils_js_1.isErrorWithCode)(error, 'ENOENT')) {
|
|
243
|
-
throw error;
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
await new Promise((resolve, reject) => {
|
|
247
|
-
server.on('error', reject);
|
|
248
|
-
server.listen(socketPath, () => {
|
|
249
|
-
server.removeListener('error', reject);
|
|
250
|
-
resolve();
|
|
251
|
-
});
|
|
252
|
-
});
|
|
253
|
-
// Restrict the socket to its owner. The daemon hosts an unlocked wallet, so
|
|
254
|
-
// a world-connectable socket would let any local user drive it. listen()
|
|
255
|
-
// creates the socket with umask-derived (typically world-accessible) perms.
|
|
256
|
-
try {
|
|
257
|
-
await (0, promises_1.chmod)(socketPath, 0o600);
|
|
258
|
-
}
|
|
259
|
-
catch (error) {
|
|
260
|
-
// Never leave a possibly world-accessible socket listening with no handle
|
|
261
|
-
// to close it. Cleanup is best-effort so the chmod failure still surfaces.
|
|
262
|
-
await closeServer(server).catch(() => undefined);
|
|
263
|
-
await (0, promises_1.unlink)(socketPath).catch(() => undefined);
|
|
264
|
-
throw error;
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
/**
|
|
268
|
-
* Close a server, resolving once it stops accepting connections.
|
|
269
|
-
*
|
|
270
|
-
* @param server - The net.Server instance.
|
|
271
|
-
*/
|
|
272
|
-
async function closeServer(server) {
|
|
273
|
-
await new Promise((resolve, reject) => {
|
|
274
|
-
server.close((error) => {
|
|
275
|
-
if (error) {
|
|
276
|
-
reject(error);
|
|
277
|
-
}
|
|
278
|
-
else {
|
|
279
|
-
resolve();
|
|
280
|
-
}
|
|
281
|
-
});
|
|
282
|
-
});
|
|
283
|
-
}
|
|
284
|
-
//# sourceMappingURL=rpc-socket-server.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rpc-socket-server.cjs","sourceRoot":"","sources":["../../src/daemon/rpc-socket-server.ts"],"names":[],"mappings":"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","sourcesContent":["import { rpcErrors } from '@metamask/rpc-errors';\nimport { validate as validateStruct } from '@metamask/superstruct';\nimport type {\n JsonRpcId,\n JsonRpcParams,\n JsonRpcResponse,\n} from '@metamask/utils';\nimport { hasProperty, isJsonRpcRequest } from '@metamask/utils';\nimport { chmod, unlink } from 'node:fs/promises';\nimport { createServer } from 'node:net';\nimport type { Server } from 'node:net';\n\nimport type { RpcHandlerMap } from './types.js';\nimport { isErrorWithCode } from './utils.js';\n\nconst CONNECTION_TIMEOUT_MS = 30_000;\n\n/**\n * Handle returned by {@link startRpcSocketServer}.\n */\nexport type RpcSocketServerHandle = {\n close: () => Promise<void>;\n};\n\n/**\n * Options for {@link startRpcSocketServer}.\n */\nexport type StartRpcSocketServerOptions = {\n /** The Unix socket path to listen on. */\n socketPath: string;\n /** Map of RPC method names to handler functions. */\n handlers: RpcHandlerMap;\n /** Callback invoked when a `shutdown` RPC is received. */\n onShutdown?: (() => Promise<void>) | undefined;\n /**\n * Optional logger for server-side diagnostics (unexpected socket errors,\n * unhandled handler rejections, `onShutdown` callback failures). Without\n * this, failures fall back to `process.stderr.write`, which is discarded\n * when the daemon is spawned with `stdio: 'ignore'`.\n */\n log?: ((message: string) => void) | undefined;\n};\n\n/**\n * Start a Unix socket server that processes JSON-RPC requests.\n *\n * Each connection reads one newline-delimited JSON-RPC request, processes it\n * via the provided handler map, writes a JSON-RPC response, and closes.\n *\n * The special `shutdown` method is intercepted before handler dispatch and\n * triggers the provided {@link StartRpcSocketServerOptions.onShutdown} callback\n * after responding.\n *\n * @param options - Server options.\n * @param options.socketPath - The Unix socket path to listen on.\n * @param options.handlers - Map of RPC method names to handler functions.\n * @param options.onShutdown - Optional callback invoked when a `shutdown` RPC is received.\n * @param options.log - Optional logger for server-side diagnostics.\n * @returns A handle with a `close()` function for cleanup.\n */\nexport async function startRpcSocketServer({\n socketPath,\n handlers,\n onShutdown,\n log,\n}: StartRpcSocketServerOptions): Promise<RpcSocketServerHandle> {\n const logFn = log ?? defaultLog;\n\n const server = createServer((socket) => {\n let buffer = '';\n\n // Destroy connections that never send a complete request line. `unref` so\n // the timer alone cannot keep the event loop alive at shutdown.\n const timer = setTimeout(() => {\n socket.destroy();\n }, CONNECTION_TIMEOUT_MS);\n timer.unref();\n\n /**\n * Clear the idle-connection timer. Called from data, close, and error\n * paths so the timer never outlives the connection itself.\n */\n const clearIdleTimer = (): void => {\n clearTimeout(timer);\n };\n\n const onData = (data: Buffer): void => {\n buffer += data.toString();\n const idx = buffer.indexOf('\\n');\n if (idx === -1) {\n return;\n }\n\n clearIdleTimer();\n\n // One request per connection.\n socket.removeListener('data', onData);\n\n const line = buffer.slice(0, idx);\n const remaining = buffer.slice(idx + 1);\n buffer = '';\n\n if (remaining.length > 0) {\n socket.end(\n `${JSON.stringify({\n jsonrpc: '2.0',\n error: rpcErrors\n .invalidRequest({\n message: 'Only one request per connection is allowed',\n })\n .serialize(),\n })}\\n`,\n );\n return;\n }\n\n handleRequest(handlers, line, onShutdown, logFn)\n .then((response) => {\n socket.end(`${JSON.stringify(response)}\\n`);\n return undefined;\n })\n .catch((dispatchError: unknown) => {\n logFn(`Unhandled RPC dispatch error: ${String(dispatchError)}`);\n socket.end(\n `${JSON.stringify({\n jsonrpc: '2.0',\n error: rpcErrors\n .internal({ message: 'Internal error' })\n .serialize(),\n })}\\n`,\n );\n });\n };\n socket.on('data', onData);\n socket.once('close', clearIdleTimer);\n socket.on('error', (socketError: NodeJS.ErrnoException) => {\n clearIdleTimer();\n const { code } = socketError;\n if (code === 'EPIPE' || code === 'ECONNRESET') {\n return; // Expected during probe/disconnect.\n }\n logFn(`Unexpected socket error: ${String(socketError)}`);\n });\n });\n\n await listen(server, socketPath);\n\n return {\n close: async (): Promise<void> => closeServer(server),\n };\n}\n\n/**\n * Default fallback logger: writes to stderr. Daemons spawned with\n * `stdio: 'ignore'` should always pass an explicit `log`.\n *\n * @param message - The message to log.\n */\nfunction defaultLog(message: string): void {\n process.stderr.write(`${message}\\n`);\n}\n\n/**\n * Handle a single JSON-RPC request line, intercepting the `shutdown` method.\n *\n * @param handlers - The RPC handler map.\n * @param line - The raw JSON line from the socket.\n * @param onShutdown - Optional shutdown callback.\n * @param log - Logger for diagnostic messages.\n * @returns A JSON-RPC response object.\n */\nasync function handleRequest(\n handlers: RpcHandlerMap,\n line: string,\n onShutdown: (() => Promise<void>) | undefined,\n log: (message: string) => void,\n): Promise<JsonRpcResponse> {\n let parsed: unknown;\n try {\n parsed = JSON.parse(line);\n } catch {\n return {\n jsonrpc: '2.0',\n id: null,\n error: rpcErrors.parse({ message: 'Parse error' }).serialize(),\n };\n }\n\n if (!isJsonRpcRequest(parsed)) {\n const id: JsonRpcId =\n typeof parsed === 'object' &&\n parsed !== null &&\n hasProperty(parsed, 'id') &&\n isValidJsonRpcId(parsed.id)\n ? parsed.id\n : null;\n return {\n jsonrpc: '2.0',\n id,\n error: rpcErrors\n .invalidRequest({ message: 'Invalid JSON-RPC request' })\n .serialize(),\n };\n }\n\n const { id, method, params } = parsed;\n\n try {\n if (method === 'shutdown') {\n if (onShutdown) {\n setTimeout(() => {\n onShutdown().catch((error: unknown) => {\n log(`onShutdown callback failed: ${String(error)}`);\n });\n }, 0);\n }\n return { jsonrpc: '2.0', id, result: { status: 'shutting down' } };\n }\n\n const handler = Object.prototype.hasOwnProperty.call(handlers, method)\n ? handlers[method]\n : undefined;\n if (!handler) {\n return {\n jsonrpc: '2.0',\n id,\n error: rpcErrors\n .methodNotFound({ message: `Method not found: ${method}` })\n .serialize(),\n };\n }\n\n const [structError, validatedParams] = validateStruct(\n coerceHandlerParams(params),\n handler.paramsStruct,\n );\n if (structError !== undefined) {\n return {\n jsonrpc: '2.0',\n id,\n error: rpcErrors\n .invalidParams({\n message: `Invalid params for ${method}: ${structError.message}`,\n })\n .serialize(),\n };\n }\n\n const result = await handler.run(validatedParams);\n return { jsonrpc: '2.0', id, result: result ?? null };\n } catch (error) {\n log(`RPC handler \"${method}\" failed: ${String(error)}`);\n if (isRpcError(error)) {\n return { jsonrpc: '2.0', id, error };\n }\n const message = error instanceof Error ? error.message : 'Internal error';\n return {\n jsonrpc: '2.0',\n id,\n error: rpcErrors.internal({ message }).serialize(),\n };\n }\n}\n\n/**\n * Narrow `params` to the shape handlers expect. JSON-RPC 2.0 requires\n * `params`, when present, to be an array or object; both are valid `Json`.\n *\n * @param params - The validated `params` field from a JSON-RPC request.\n * @returns The same value, or `null` when absent.\n */\nfunction coerceHandlerParams(\n params: JsonRpcParams | undefined,\n): JsonRpcParams | null {\n return params ?? null;\n}\n\n/**\n * Per JSON-RPC 2.0, `id` must be a string, number, or null. Used when\n * salvaging an `id` from a parse-success-but-not-valid-request payload.\n *\n * @param value - The candidate id.\n * @returns True if the value is an acceptable JSON-RPC id.\n */\nfunction isValidJsonRpcId(value: unknown): value is JsonRpcId {\n return (\n value === null || typeof value === 'string' || typeof value === 'number'\n );\n}\n\n/**\n * Check if an error is an RPC error with a numeric code.\n *\n * @param error - The error to check.\n * @returns True if the error has a numeric code property.\n */\nfunction isRpcError(\n error: unknown,\n): error is { code: number; message: string } {\n return (\n typeof error === 'object' &&\n error !== null &&\n hasProperty(error, 'code') &&\n typeof error.code === 'number' &&\n hasProperty(error, 'message') &&\n typeof error.message === 'string'\n );\n}\n\n/**\n * Start listening on a Unix socket path, removing any stale socket file.\n *\n * @param server - The net.Server instance.\n * @param socketPath - The Unix socket path.\n */\nasync function listen(server: Server, socketPath: string): Promise<void> {\n try {\n await unlink(socketPath);\n } catch (error) {\n if (!isErrorWithCode(error, 'ENOENT')) {\n throw error;\n }\n }\n\n await new Promise<void>((resolve, reject) => {\n server.on('error', reject);\n server.listen(socketPath, () => {\n server.removeListener('error', reject);\n resolve();\n });\n });\n\n // Restrict the socket to its owner. The daemon hosts an unlocked wallet, so\n // a world-connectable socket would let any local user drive it. listen()\n // creates the socket with umask-derived (typically world-accessible) perms.\n try {\n await chmod(socketPath, 0o600);\n } catch (error) {\n // Never leave a possibly world-accessible socket listening with no handle\n // to close it. Cleanup is best-effort so the chmod failure still surfaces.\n await closeServer(server).catch(() => undefined);\n await unlink(socketPath).catch(() => undefined);\n throw error;\n }\n}\n\n/**\n * Close a server, resolving once it stops accepting connections.\n *\n * @param server - The net.Server instance.\n */\nasync function closeServer(server: Server): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n server.close((error) => {\n if (error) {\n reject(error);\n } else {\n resolve();\n }\n });\n });\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rpc-socket-server.d.cts","sourceRoot":"","sources":["../../src/daemon/rpc-socket-server.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAmB;AAKhD;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,2BAA2B,GAAG;IACxC,yCAAyC;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB,oDAAoD;IACpD,QAAQ,EAAE,aAAa,CAAC;IACxB,0DAA0D;IAC1D,UAAU,CAAC,EAAE,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC;IAC/C;;;;;OAKG;IACH,GAAG,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CAC/C,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,oBAAoB,CAAC,EACzC,UAAU,EACV,QAAQ,EACR,UAAU,EACV,GAAG,GACJ,EAAE,2BAA2B,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAqF9D"}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import type { RpcHandlerMap } from "./types.mjs";
|
|
2
|
-
/**
|
|
3
|
-
* Handle returned by {@link startRpcSocketServer}.
|
|
4
|
-
*/
|
|
5
|
-
export type RpcSocketServerHandle = {
|
|
6
|
-
close: () => Promise<void>;
|
|
7
|
-
};
|
|
8
|
-
/**
|
|
9
|
-
* Options for {@link startRpcSocketServer}.
|
|
10
|
-
*/
|
|
11
|
-
export type StartRpcSocketServerOptions = {
|
|
12
|
-
/** The Unix socket path to listen on. */
|
|
13
|
-
socketPath: string;
|
|
14
|
-
/** Map of RPC method names to handler functions. */
|
|
15
|
-
handlers: RpcHandlerMap;
|
|
16
|
-
/** Callback invoked when a `shutdown` RPC is received. */
|
|
17
|
-
onShutdown?: (() => Promise<void>) | undefined;
|
|
18
|
-
/**
|
|
19
|
-
* Optional logger for server-side diagnostics (unexpected socket errors,
|
|
20
|
-
* unhandled handler rejections, `onShutdown` callback failures). Without
|
|
21
|
-
* this, failures fall back to `process.stderr.write`, which is discarded
|
|
22
|
-
* when the daemon is spawned with `stdio: 'ignore'`.
|
|
23
|
-
*/
|
|
24
|
-
log?: ((message: string) => void) | undefined;
|
|
25
|
-
};
|
|
26
|
-
/**
|
|
27
|
-
* Start a Unix socket server that processes JSON-RPC requests.
|
|
28
|
-
*
|
|
29
|
-
* Each connection reads one newline-delimited JSON-RPC request, processes it
|
|
30
|
-
* via the provided handler map, writes a JSON-RPC response, and closes.
|
|
31
|
-
*
|
|
32
|
-
* The special `shutdown` method is intercepted before handler dispatch and
|
|
33
|
-
* triggers the provided {@link StartRpcSocketServerOptions.onShutdown} callback
|
|
34
|
-
* after responding.
|
|
35
|
-
*
|
|
36
|
-
* @param options - Server options.
|
|
37
|
-
* @param options.socketPath - The Unix socket path to listen on.
|
|
38
|
-
* @param options.handlers - Map of RPC method names to handler functions.
|
|
39
|
-
* @param options.onShutdown - Optional callback invoked when a `shutdown` RPC is received.
|
|
40
|
-
* @param options.log - Optional logger for server-side diagnostics.
|
|
41
|
-
* @returns A handle with a `close()` function for cleanup.
|
|
42
|
-
*/
|
|
43
|
-
export declare function startRpcSocketServer({ socketPath, handlers, onShutdown, log, }: StartRpcSocketServerOptions): Promise<RpcSocketServerHandle>;
|
|
44
|
-
//# sourceMappingURL=rpc-socket-server.d.mts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rpc-socket-server.d.mts","sourceRoot":"","sources":["../../src/daemon/rpc-socket-server.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAmB;AAKhD;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,2BAA2B,GAAG;IACxC,yCAAyC;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB,oDAAoD;IACpD,QAAQ,EAAE,aAAa,CAAC;IACxB,0DAA0D;IAC1D,UAAU,CAAC,EAAE,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC;IAC/C;;;;;OAKG;IACH,GAAG,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CAC/C,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,oBAAoB,CAAC,EACzC,UAAU,EACV,QAAQ,EACR,UAAU,EACV,GAAG,GACJ,EAAE,2BAA2B,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAqF9D"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rpc-socket-server.mjs","sourceRoot":"","sources":["../../src/daemon/rpc-socket-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,6BAA6B;AACjD,OAAO,EAAE,QAAQ,IAAI,cAAc,EAAE,8BAA8B;AAMnE,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,wBAAwB;AAChE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,yBAAyB;AACjD,OAAO,EAAE,YAAY,EAAE,iBAAiB;AAIxC,OAAO,EAAE,eAAe,EAAE,oBAAmB;AAE7C,MAAM,qBAAqB,GAAG,KAAM,CAAC;AA4BrC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,EACzC,UAAU,EACV,QAAQ,EACR,UAAU,EACV,GAAG,GACyB;IAC5B,MAAM,KAAK,GAAG,GAAG,IAAI,UAAU,CAAC;IAEhC,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,MAAM,EAAE,EAAE;QACrC,IAAI,MAAM,GAAG,EAAE,CAAC;QAEhB,0EAA0E;QAC1E,gEAAgE;QAChE,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,CAAC,EAAE,qBAAqB,CAAC,CAAC;QAC1B,KAAK,CAAC,KAAK,EAAE,CAAC;QAEd;;;WAGG;QACH,MAAM,cAAc,GAAG,GAAS,EAAE;YAChC,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC,CAAC;QAEF,MAAM,MAAM,GAAG,CAAC,IAAY,EAAQ,EAAE;YACpC,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC1B,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACjC,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC;gBACf,OAAO;YACT,CAAC;YAED,cAAc,EAAE,CAAC;YAEjB,8BAA8B;YAC9B,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YAEtC,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;YAClC,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;YACxC,MAAM,GAAG,EAAE,CAAC;YAEZ,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACzB,MAAM,CAAC,GAAG,CACR,GAAG,IAAI,CAAC,SAAS,CAAC;oBAChB,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,SAAS;yBACb,cAAc,CAAC;wBACd,OAAO,EAAE,4CAA4C;qBACtD,CAAC;yBACD,SAAS,EAAE;iBACf,CAAC,IAAI,CACP,CAAC;gBACF,OAAO;YACT,CAAC;YAED,aAAa,CAAC,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,CAAC;iBAC7C,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE;gBACjB,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;gBAC5C,OAAO,SAAS,CAAC;YACnB,CAAC,CAAC;iBACD,KAAK,CAAC,CAAC,aAAsB,EAAE,EAAE;gBAChC,KAAK,CAAC,iCAAiC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;gBAChE,MAAM,CAAC,GAAG,CACR,GAAG,IAAI,CAAC,SAAS,CAAC;oBAChB,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,SAAS;yBACb,QAAQ,CAAC,EAAE,OAAO,EAAE,gBAAgB,EAAE,CAAC;yBACvC,SAAS,EAAE;iBACf,CAAC,IAAI,CACP,CAAC;YACJ,CAAC,CAAC,CAAC;QACP,CAAC,CAAC;QACF,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC1B,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;QACrC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,WAAkC,EAAE,EAAE;YACxD,cAAc,EAAE,CAAC;YACjB,MAAM,EAAE,IAAI,EAAE,GAAG,WAAW,CAAC;YAC7B,IAAI,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,YAAY,EAAE,CAAC;gBAC9C,OAAO,CAAC,oCAAoC;YAC9C,CAAC;YACD,KAAK,CAAC,4BAA4B,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QAC3D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,MAAM,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAEjC,OAAO;QACL,KAAK,EAAE,KAAK,IAAmB,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC;KACtD,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAS,UAAU,CAAC,OAAe;IACjC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,IAAI,CAAC,CAAC;AACvC,CAAC;AAED;;;;;;;;GAQG;AACH,KAAK,UAAU,aAAa,CAC1B,QAAuB,EACvB,IAAY,EACZ,UAA6C,EAC7C,GAA8B;IAE9B,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;YACL,OAAO,EAAE,KAAK;YACd,EAAE,EAAE,IAAI;YACR,KAAK,EAAE,SAAS,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC,CAAC,SAAS,EAAE;SAC/D,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,EAAE,CAAC;QAC9B,MAAM,EAAE,GACN,OAAO,MAAM,KAAK,QAAQ;YAC1B,MAAM,KAAK,IAAI;YACf,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC;YACzB,gBAAgB,CAAC,MAAM,CAAC,EAAE,CAAC;YACzB,CAAC,CAAC,MAAM,CAAC,EAAE;YACX,CAAC,CAAC,IAAI,CAAC;QACX,OAAO;YACL,OAAO,EAAE,KAAK;YACd,EAAE;YACF,KAAK,EAAE,SAAS;iBACb,cAAc,CAAC,EAAE,OAAO,EAAE,0BAA0B,EAAE,CAAC;iBACvD,SAAS,EAAE;SACf,CAAC;IACJ,CAAC;IAED,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IAEtC,IAAI,CAAC;QACH,IAAI,MAAM,KAAK,UAAU,EAAE,CAAC;YAC1B,IAAI,UAAU,EAAE,CAAC;gBACf,UAAU,CAAC,GAAG,EAAE;oBACd,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;wBACpC,GAAG,CAAC,+BAA+B,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;oBACtD,CAAC,CAAC,CAAC;gBACL,CAAC,EAAE,CAAC,CAAC,CAAC;YACR,CAAC;YACD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,eAAe,EAAE,EAAE,CAAC;QACrE,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC;YACpE,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;YAClB,CAAC,CAAC,SAAS,CAAC;QACd,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,EAAE;gBACF,KAAK,EAAE,SAAS;qBACb,cAAc,CAAC,EAAE,OAAO,EAAE,qBAAqB,MAAM,EAAE,EAAE,CAAC;qBAC1D,SAAS,EAAE;aACf,CAAC;QACJ,CAAC;QAED,MAAM,CAAC,WAAW,EAAE,eAAe,CAAC,GAAG,cAAc,CACnD,mBAAmB,CAAC,MAAM,CAAC,EAC3B,OAAO,CAAC,YAAY,CACrB,CAAC;QACF,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YAC9B,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,EAAE;gBACF,KAAK,EAAE,SAAS;qBACb,aAAa,CAAC;oBACb,OAAO,EAAE,sBAAsB,MAAM,KAAK,WAAW,CAAC,OAAO,EAAE;iBAChE,CAAC;qBACD,SAAS,EAAE;aACf,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QAClD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,IAAI,IAAI,EAAE,CAAC;IACxD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,GAAG,CAAC,gBAAgB,MAAM,aAAa,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACxD,IAAI,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC;QACvC,CAAC;QACD,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC;QAC1E,OAAO;YACL,OAAO,EAAE,KAAK;YACd,EAAE;YACF,KAAK,EAAE,SAAS,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,SAAS,EAAE;SACnD,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,SAAS,mBAAmB,CAC1B,MAAiC;IAEjC,OAAO,MAAM,IAAI,IAAI,CAAC;AACxB,CAAC;AAED;;;;;;GAMG;AACH,SAAS,gBAAgB,CAAC,KAAc;IACtC,OAAO,CACL,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ,CACzE,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAS,UAAU,CACjB,KAAc;IAEd,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACd,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC;QAC1B,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ;QAC9B,WAAW,CAAC,KAAK,EAAE,SAAS,CAAC;QAC7B,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,CAClC,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,MAAM,CAAC,MAAc,EAAE,UAAkB;IACtD,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE,CAAC;YACtC,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC1C,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC3B,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,GAAG,EAAE;YAC7B,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YACvC,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,4EAA4E;IAC5E,yEAAyE;IACzE,4EAA4E;IAC5E,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IACjC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,0EAA0E;QAC1E,2EAA2E;QAC3E,MAAM,WAAW,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QACjD,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAChD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,WAAW,CAAC,MAAc;IACvC,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC1C,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;YACrB,IAAI,KAAK,EAAE,CAAC;gBACV,MAAM,CAAC,KAAK,CAAC,CAAC;YAChB,CAAC;iBAAM,CAAC;gBACN,OAAO,EAAE,CAAC;YACZ,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { rpcErrors } from '@metamask/rpc-errors';\nimport { validate as validateStruct } from '@metamask/superstruct';\nimport type {\n JsonRpcId,\n JsonRpcParams,\n JsonRpcResponse,\n} from '@metamask/utils';\nimport { hasProperty, isJsonRpcRequest } from '@metamask/utils';\nimport { chmod, unlink } from 'node:fs/promises';\nimport { createServer } from 'node:net';\nimport type { Server } from 'node:net';\n\nimport type { RpcHandlerMap } from './types.js';\nimport { isErrorWithCode } from './utils.js';\n\nconst CONNECTION_TIMEOUT_MS = 30_000;\n\n/**\n * Handle returned by {@link startRpcSocketServer}.\n */\nexport type RpcSocketServerHandle = {\n close: () => Promise<void>;\n};\n\n/**\n * Options for {@link startRpcSocketServer}.\n */\nexport type StartRpcSocketServerOptions = {\n /** The Unix socket path to listen on. */\n socketPath: string;\n /** Map of RPC method names to handler functions. */\n handlers: RpcHandlerMap;\n /** Callback invoked when a `shutdown` RPC is received. */\n onShutdown?: (() => Promise<void>) | undefined;\n /**\n * Optional logger for server-side diagnostics (unexpected socket errors,\n * unhandled handler rejections, `onShutdown` callback failures). Without\n * this, failures fall back to `process.stderr.write`, which is discarded\n * when the daemon is spawned with `stdio: 'ignore'`.\n */\n log?: ((message: string) => void) | undefined;\n};\n\n/**\n * Start a Unix socket server that processes JSON-RPC requests.\n *\n * Each connection reads one newline-delimited JSON-RPC request, processes it\n * via the provided handler map, writes a JSON-RPC response, and closes.\n *\n * The special `shutdown` method is intercepted before handler dispatch and\n * triggers the provided {@link StartRpcSocketServerOptions.onShutdown} callback\n * after responding.\n *\n * @param options - Server options.\n * @param options.socketPath - The Unix socket path to listen on.\n * @param options.handlers - Map of RPC method names to handler functions.\n * @param options.onShutdown - Optional callback invoked when a `shutdown` RPC is received.\n * @param options.log - Optional logger for server-side diagnostics.\n * @returns A handle with a `close()` function for cleanup.\n */\nexport async function startRpcSocketServer({\n socketPath,\n handlers,\n onShutdown,\n log,\n}: StartRpcSocketServerOptions): Promise<RpcSocketServerHandle> {\n const logFn = log ?? defaultLog;\n\n const server = createServer((socket) => {\n let buffer = '';\n\n // Destroy connections that never send a complete request line. `unref` so\n // the timer alone cannot keep the event loop alive at shutdown.\n const timer = setTimeout(() => {\n socket.destroy();\n }, CONNECTION_TIMEOUT_MS);\n timer.unref();\n\n /**\n * Clear the idle-connection timer. Called from data, close, and error\n * paths so the timer never outlives the connection itself.\n */\n const clearIdleTimer = (): void => {\n clearTimeout(timer);\n };\n\n const onData = (data: Buffer): void => {\n buffer += data.toString();\n const idx = buffer.indexOf('\\n');\n if (idx === -1) {\n return;\n }\n\n clearIdleTimer();\n\n // One request per connection.\n socket.removeListener('data', onData);\n\n const line = buffer.slice(0, idx);\n const remaining = buffer.slice(idx + 1);\n buffer = '';\n\n if (remaining.length > 0) {\n socket.end(\n `${JSON.stringify({\n jsonrpc: '2.0',\n error: rpcErrors\n .invalidRequest({\n message: 'Only one request per connection is allowed',\n })\n .serialize(),\n })}\\n`,\n );\n return;\n }\n\n handleRequest(handlers, line, onShutdown, logFn)\n .then((response) => {\n socket.end(`${JSON.stringify(response)}\\n`);\n return undefined;\n })\n .catch((dispatchError: unknown) => {\n logFn(`Unhandled RPC dispatch error: ${String(dispatchError)}`);\n socket.end(\n `${JSON.stringify({\n jsonrpc: '2.0',\n error: rpcErrors\n .internal({ message: 'Internal error' })\n .serialize(),\n })}\\n`,\n );\n });\n };\n socket.on('data', onData);\n socket.once('close', clearIdleTimer);\n socket.on('error', (socketError: NodeJS.ErrnoException) => {\n clearIdleTimer();\n const { code } = socketError;\n if (code === 'EPIPE' || code === 'ECONNRESET') {\n return; // Expected during probe/disconnect.\n }\n logFn(`Unexpected socket error: ${String(socketError)}`);\n });\n });\n\n await listen(server, socketPath);\n\n return {\n close: async (): Promise<void> => closeServer(server),\n };\n}\n\n/**\n * Default fallback logger: writes to stderr. Daemons spawned with\n * `stdio: 'ignore'` should always pass an explicit `log`.\n *\n * @param message - The message to log.\n */\nfunction defaultLog(message: string): void {\n process.stderr.write(`${message}\\n`);\n}\n\n/**\n * Handle a single JSON-RPC request line, intercepting the `shutdown` method.\n *\n * @param handlers - The RPC handler map.\n * @param line - The raw JSON line from the socket.\n * @param onShutdown - Optional shutdown callback.\n * @param log - Logger for diagnostic messages.\n * @returns A JSON-RPC response object.\n */\nasync function handleRequest(\n handlers: RpcHandlerMap,\n line: string,\n onShutdown: (() => Promise<void>) | undefined,\n log: (message: string) => void,\n): Promise<JsonRpcResponse> {\n let parsed: unknown;\n try {\n parsed = JSON.parse(line);\n } catch {\n return {\n jsonrpc: '2.0',\n id: null,\n error: rpcErrors.parse({ message: 'Parse error' }).serialize(),\n };\n }\n\n if (!isJsonRpcRequest(parsed)) {\n const id: JsonRpcId =\n typeof parsed === 'object' &&\n parsed !== null &&\n hasProperty(parsed, 'id') &&\n isValidJsonRpcId(parsed.id)\n ? parsed.id\n : null;\n return {\n jsonrpc: '2.0',\n id,\n error: rpcErrors\n .invalidRequest({ message: 'Invalid JSON-RPC request' })\n .serialize(),\n };\n }\n\n const { id, method, params } = parsed;\n\n try {\n if (method === 'shutdown') {\n if (onShutdown) {\n setTimeout(() => {\n onShutdown().catch((error: unknown) => {\n log(`onShutdown callback failed: ${String(error)}`);\n });\n }, 0);\n }\n return { jsonrpc: '2.0', id, result: { status: 'shutting down' } };\n }\n\n const handler = Object.prototype.hasOwnProperty.call(handlers, method)\n ? handlers[method]\n : undefined;\n if (!handler) {\n return {\n jsonrpc: '2.0',\n id,\n error: rpcErrors\n .methodNotFound({ message: `Method not found: ${method}` })\n .serialize(),\n };\n }\n\n const [structError, validatedParams] = validateStruct(\n coerceHandlerParams(params),\n handler.paramsStruct,\n );\n if (structError !== undefined) {\n return {\n jsonrpc: '2.0',\n id,\n error: rpcErrors\n .invalidParams({\n message: `Invalid params for ${method}: ${structError.message}`,\n })\n .serialize(),\n };\n }\n\n const result = await handler.run(validatedParams);\n return { jsonrpc: '2.0', id, result: result ?? null };\n } catch (error) {\n log(`RPC handler \"${method}\" failed: ${String(error)}`);\n if (isRpcError(error)) {\n return { jsonrpc: '2.0', id, error };\n }\n const message = error instanceof Error ? error.message : 'Internal error';\n return {\n jsonrpc: '2.0',\n id,\n error: rpcErrors.internal({ message }).serialize(),\n };\n }\n}\n\n/**\n * Narrow `params` to the shape handlers expect. JSON-RPC 2.0 requires\n * `params`, when present, to be an array or object; both are valid `Json`.\n *\n * @param params - The validated `params` field from a JSON-RPC request.\n * @returns The same value, or `null` when absent.\n */\nfunction coerceHandlerParams(\n params: JsonRpcParams | undefined,\n): JsonRpcParams | null {\n return params ?? null;\n}\n\n/**\n * Per JSON-RPC 2.0, `id` must be a string, number, or null. Used when\n * salvaging an `id` from a parse-success-but-not-valid-request payload.\n *\n * @param value - The candidate id.\n * @returns True if the value is an acceptable JSON-RPC id.\n */\nfunction isValidJsonRpcId(value: unknown): value is JsonRpcId {\n return (\n value === null || typeof value === 'string' || typeof value === 'number'\n );\n}\n\n/**\n * Check if an error is an RPC error with a numeric code.\n *\n * @param error - The error to check.\n * @returns True if the error has a numeric code property.\n */\nfunction isRpcError(\n error: unknown,\n): error is { code: number; message: string } {\n return (\n typeof error === 'object' &&\n error !== null &&\n hasProperty(error, 'code') &&\n typeof error.code === 'number' &&\n hasProperty(error, 'message') &&\n typeof error.message === 'string'\n );\n}\n\n/**\n * Start listening on a Unix socket path, removing any stale socket file.\n *\n * @param server - The net.Server instance.\n * @param socketPath - The Unix socket path.\n */\nasync function listen(server: Server, socketPath: string): Promise<void> {\n try {\n await unlink(socketPath);\n } catch (error) {\n if (!isErrorWithCode(error, 'ENOENT')) {\n throw error;\n }\n }\n\n await new Promise<void>((resolve, reject) => {\n server.on('error', reject);\n server.listen(socketPath, () => {\n server.removeListener('error', reject);\n resolve();\n });\n });\n\n // Restrict the socket to its owner. The daemon hosts an unlocked wallet, so\n // a world-connectable socket would let any local user drive it. listen()\n // creates the socket with umask-derived (typically world-accessible) perms.\n try {\n await chmod(socketPath, 0o600);\n } catch (error) {\n // Never leave a possibly world-accessible socket listening with no handle\n // to close it. Cleanup is best-effort so the chmod failure still surfaces.\n await closeServer(server).catch(() => undefined);\n await unlink(socketPath).catch(() => undefined);\n throw error;\n }\n}\n\n/**\n * Close a server, resolving once it stops accepting connections.\n *\n * @param server - The net.Server instance.\n */\nasync function closeServer(server: Server): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n server.close((error) => {\n if (error) {\n reject(error);\n } else {\n resolve();\n }\n });\n });\n}\n"]}
|