@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.
Files changed (264) hide show
  1. package/CHANGELOG.md +8 -4
  2. package/dist/commands/daemon/{call.d.mts → call.d.ts} +2 -2
  3. package/dist/commands/daemon/call.d.ts.map +1 -0
  4. package/dist/commands/daemon/{call.mjs → call.js} +30 -31
  5. package/dist/commands/daemon/call.js.map +1 -0
  6. package/dist/commands/daemon/{list.d.cts → list.d.ts} +2 -2
  7. package/dist/commands/daemon/list.d.ts.map +1 -0
  8. package/dist/commands/daemon/{list.mjs → list.js} +9 -10
  9. package/dist/commands/daemon/list.js.map +1 -0
  10. package/dist/commands/daemon/{purge.d.cts → purge.d.ts} +2 -2
  11. package/dist/commands/daemon/purge.d.ts.map +1 -0
  12. package/dist/commands/daemon/{purge.mjs → purge.js} +19 -20
  13. package/dist/commands/daemon/purge.js.map +1 -0
  14. package/dist/commands/daemon/{start.d.cts → start.d.ts} +2 -2
  15. package/dist/commands/daemon/start.d.ts.map +1 -0
  16. package/dist/commands/daemon/start.js +49 -0
  17. package/dist/commands/daemon/{start.cjs.map → start.js.map} +1 -1
  18. package/dist/commands/daemon/{status.d.cts → status.d.ts} +2 -2
  19. package/dist/commands/daemon/status.d.ts.map +1 -0
  20. package/dist/commands/daemon/{status.mjs → status.js} +10 -11
  21. package/dist/commands/daemon/status.js.map +1 -0
  22. package/dist/commands/daemon/{stop.d.cts → stop.d.ts} +2 -2
  23. package/dist/commands/daemon/stop.d.ts.map +1 -0
  24. package/dist/commands/daemon/{stop.mjs → stop.js} +9 -10
  25. package/dist/commands/daemon/stop.js.map +1 -0
  26. package/dist/commands/wallet/{send.d.cts → send.d.ts} +3 -3
  27. package/dist/commands/wallet/send.d.ts.map +1 -0
  28. package/dist/commands/wallet/{send.mjs → send.js} +111 -123
  29. package/dist/commands/wallet/send.js.map +1 -0
  30. package/dist/commands/wallet/{unlock.d.cts → unlock.d.ts} +2 -2
  31. package/dist/commands/wallet/unlock.d.ts.map +1 -0
  32. package/dist/commands/wallet/{unlock.mjs → unlock.js} +29 -30
  33. package/dist/commands/wallet/unlock.js.map +1 -0
  34. package/dist/daemon/{auto-approval.d.mts → auto-approval.d.ts} +3 -3
  35. package/dist/daemon/auto-approval.d.ts.map +1 -0
  36. package/dist/daemon/{auto-approval.mjs → auto-approval.js} +1 -1
  37. package/dist/daemon/auto-approval.js.map +1 -0
  38. package/dist/daemon/{daemon-client.d.mts → daemon-client.d.ts} +2 -2
  39. package/dist/daemon/daemon-client.d.ts.map +1 -0
  40. package/dist/daemon/{daemon-client.mjs → daemon-client.js} +8 -8
  41. package/dist/daemon/daemon-client.js.map +1 -0
  42. package/dist/daemon/daemon-entry.d.ts +2 -0
  43. package/dist/daemon/daemon-entry.d.ts.map +1 -0
  44. package/dist/daemon/{daemon-entry.mjs → daemon-entry.js} +12 -12
  45. package/dist/daemon/daemon-entry.js.map +1 -0
  46. package/dist/daemon/{daemon-spawn.d.mts → daemon-spawn.d.ts} +2 -2
  47. package/dist/daemon/daemon-spawn.d.ts.map +1 -0
  48. package/dist/daemon/{daemon-spawn.mjs → daemon-spawn.js} +7 -7
  49. package/dist/daemon/daemon-spawn.js.map +1 -0
  50. package/dist/daemon/{data-dir.d.cts → data-dir.d.ts} +1 -1
  51. package/dist/daemon/data-dir.d.ts.map +1 -0
  52. package/dist/daemon/{data-dir.mjs → data-dir.js} +3 -3
  53. package/dist/daemon/data-dir.js.map +1 -0
  54. package/dist/daemon/{paths.d.mts → paths.d.ts} +2 -2
  55. package/dist/daemon/paths.d.ts.map +1 -0
  56. package/dist/daemon/{paths.mjs → paths.js} +2 -2
  57. package/dist/daemon/paths.js.map +1 -0
  58. package/dist/daemon/{prompts.d.cts → prompts.d.ts} +1 -1
  59. package/dist/daemon/prompts.d.ts.map +1 -0
  60. package/dist/daemon/{prompts.mjs → prompts.js} +4 -4
  61. package/dist/daemon/prompts.js.map +1 -0
  62. package/dist/daemon/{rpc-socket-server.d.cts → rpc-socket-server.d.ts} +2 -2
  63. package/dist/daemon/rpc-socket-server.d.ts.map +1 -0
  64. package/dist/daemon/{rpc-socket-server.mjs → rpc-socket-server.js} +8 -8
  65. package/dist/daemon/rpc-socket-server.js.map +1 -0
  66. package/dist/daemon/{secrets.d.cts → secrets.d.ts} +1 -1
  67. package/dist/daemon/secrets.d.ts.map +1 -0
  68. package/dist/daemon/{secrets.mjs → secrets.js} +11 -23
  69. package/dist/daemon/secrets.js.map +1 -0
  70. package/dist/daemon/{send-transaction.d.cts → send-transaction.d.ts} +9 -9
  71. package/dist/daemon/send-transaction.d.ts.map +1 -0
  72. package/dist/daemon/{send-transaction.mjs → send-transaction.js} +3 -3
  73. package/dist/daemon/send-transaction.js.map +1 -0
  74. package/dist/daemon/{socket-line.d.cts → socket-line.d.ts} +2 -5
  75. package/dist/daemon/socket-line.d.ts.map +1 -0
  76. package/dist/daemon/{socket-line.mjs → socket-line.js} +1 -1
  77. package/dist/daemon/socket-line.js.map +1 -0
  78. package/dist/daemon/{stop-daemon.d.cts → stop-daemon.d.ts} +1 -1
  79. package/dist/daemon/stop-daemon.d.ts.map +1 -0
  80. package/dist/daemon/{stop-daemon.mjs → stop-daemon.js} +7 -7
  81. package/dist/daemon/stop-daemon.js.map +1 -0
  82. package/dist/daemon/{types.d.cts → types.d.ts} +4 -4
  83. package/dist/daemon/types.d.ts.map +1 -0
  84. package/dist/daemon/{types.mjs → types.js} +1 -1
  85. package/dist/daemon/types.js.map +1 -0
  86. package/dist/daemon/{utils.d.cts → utils.d.ts} +2 -3
  87. package/dist/daemon/utils.d.ts.map +1 -0
  88. package/dist/daemon/{utils.mjs → utils.js} +3 -3
  89. package/dist/daemon/utils.js.map +1 -0
  90. package/dist/daemon/{wallet-factory.d.cts → wallet-factory.d.ts} +4 -4
  91. package/dist/daemon/wallet-factory.d.ts.map +1 -0
  92. package/dist/daemon/{wallet-factory.mjs → wallet-factory.js} +12 -12
  93. package/dist/daemon/wallet-factory.js.map +1 -0
  94. package/dist/persistence/{KeyValueStore.d.cts → KeyValueStore.d.ts} +2 -2
  95. package/dist/persistence/KeyValueStore.d.ts.map +1 -0
  96. package/dist/persistence/KeyValueStore.js +59 -0
  97. package/dist/persistence/KeyValueStore.js.map +1 -0
  98. package/dist/persistence/{persistence.d.cts → persistence.d.ts} +5 -5
  99. package/dist/persistence/persistence.d.ts.map +1 -0
  100. package/dist/persistence/{persistence.mjs → persistence.js} +2 -2
  101. package/dist/persistence/persistence.js.map +1 -0
  102. package/dist/test/{run-command.d.cts → run-command.d.ts} +4 -4
  103. package/dist/test/run-command.d.ts.map +1 -0
  104. package/dist/test/{run-command.mjs → run-command.js} +3 -3
  105. package/dist/test/run-command.js.map +1 -0
  106. package/package.json +19 -15
  107. package/dist/commands/daemon/call.cjs +0 -79
  108. package/dist/commands/daemon/call.cjs.map +0 -1
  109. package/dist/commands/daemon/call.d.cts +0 -14
  110. package/dist/commands/daemon/call.d.cts.map +0 -1
  111. package/dist/commands/daemon/call.d.mts.map +0 -1
  112. package/dist/commands/daemon/call.mjs.map +0 -1
  113. package/dist/commands/daemon/list.cjs +0 -48
  114. package/dist/commands/daemon/list.cjs.map +0 -1
  115. package/dist/commands/daemon/list.d.cts.map +0 -1
  116. package/dist/commands/daemon/list.d.mts +0 -7
  117. package/dist/commands/daemon/list.d.mts.map +0 -1
  118. package/dist/commands/daemon/list.mjs.map +0 -1
  119. package/dist/commands/daemon/purge.cjs +0 -58
  120. package/dist/commands/daemon/purge.cjs.map +0 -1
  121. package/dist/commands/daemon/purge.d.cts.map +0 -1
  122. package/dist/commands/daemon/purge.d.mts +0 -10
  123. package/dist/commands/daemon/purge.d.mts.map +0 -1
  124. package/dist/commands/daemon/purge.mjs.map +0 -1
  125. package/dist/commands/daemon/start.cjs +0 -52
  126. package/dist/commands/daemon/start.d.cts.map +0 -1
  127. package/dist/commands/daemon/start.d.mts +0 -12
  128. package/dist/commands/daemon/start.d.mts.map +0 -1
  129. package/dist/commands/daemon/start.mjs +0 -50
  130. package/dist/commands/daemon/start.mjs.map +0 -1
  131. package/dist/commands/daemon/status.cjs +0 -59
  132. package/dist/commands/daemon/status.cjs.map +0 -1
  133. package/dist/commands/daemon/status.d.cts.map +0 -1
  134. package/dist/commands/daemon/status.d.mts +0 -7
  135. package/dist/commands/daemon/status.d.mts.map +0 -1
  136. package/dist/commands/daemon/status.mjs.map +0 -1
  137. package/dist/commands/daemon/stop.cjs +0 -26
  138. package/dist/commands/daemon/stop.cjs.map +0 -1
  139. package/dist/commands/daemon/stop.d.cts.map +0 -1
  140. package/dist/commands/daemon/stop.d.mts +0 -7
  141. package/dist/commands/daemon/stop.d.mts.map +0 -1
  142. package/dist/commands/daemon/stop.mjs.map +0 -1
  143. package/dist/commands/wallet/send.cjs +0 -332
  144. package/dist/commands/wallet/send.cjs.map +0 -1
  145. package/dist/commands/wallet/send.d.cts.map +0 -1
  146. package/dist/commands/wallet/send.d.mts +0 -42
  147. package/dist/commands/wallet/send.d.mts.map +0 -1
  148. package/dist/commands/wallet/send.mjs.map +0 -1
  149. package/dist/commands/wallet/unlock.cjs +0 -75
  150. package/dist/commands/wallet/unlock.cjs.map +0 -1
  151. package/dist/commands/wallet/unlock.d.cts.map +0 -1
  152. package/dist/commands/wallet/unlock.d.mts +0 -11
  153. package/dist/commands/wallet/unlock.d.mts.map +0 -1
  154. package/dist/commands/wallet/unlock.mjs.map +0 -1
  155. package/dist/daemon/auto-approval.cjs +0 -86
  156. package/dist/daemon/auto-approval.cjs.map +0 -1
  157. package/dist/daemon/auto-approval.d.cts +0 -22
  158. package/dist/daemon/auto-approval.d.cts.map +0 -1
  159. package/dist/daemon/auto-approval.d.mts.map +0 -1
  160. package/dist/daemon/auto-approval.mjs.map +0 -1
  161. package/dist/daemon/daemon-client.cjs +0 -149
  162. package/dist/daemon/daemon-client.cjs.map +0 -1
  163. package/dist/daemon/daemon-client.d.cts +0 -84
  164. package/dist/daemon/daemon-client.d.cts.map +0 -1
  165. package/dist/daemon/daemon-client.d.mts.map +0 -1
  166. package/dist/daemon/daemon-client.mjs.map +0 -1
  167. package/dist/daemon/daemon-entry.cjs +0 -278
  168. package/dist/daemon/daemon-entry.cjs.map +0 -1
  169. package/dist/daemon/daemon-entry.d.cts +0 -2
  170. package/dist/daemon/daemon-entry.d.cts.map +0 -1
  171. package/dist/daemon/daemon-entry.d.mts +0 -2
  172. package/dist/daemon/daemon-entry.d.mts.map +0 -1
  173. package/dist/daemon/daemon-entry.mjs.map +0 -1
  174. package/dist/daemon/daemon-spawn.cjs +0 -138
  175. package/dist/daemon/daemon-spawn.cjs.map +0 -1
  176. package/dist/daemon/daemon-spawn.d.cts +0 -28
  177. package/dist/daemon/daemon-spawn.d.cts.map +0 -1
  178. package/dist/daemon/daemon-spawn.d.mts.map +0 -1
  179. package/dist/daemon/daemon-spawn.mjs.map +0 -1
  180. package/dist/daemon/data-dir.cjs +0 -23
  181. package/dist/daemon/data-dir.cjs.map +0 -1
  182. package/dist/daemon/data-dir.d.cts.map +0 -1
  183. package/dist/daemon/data-dir.d.mts +0 -14
  184. package/dist/daemon/data-dir.d.mts.map +0 -1
  185. package/dist/daemon/data-dir.mjs.map +0 -1
  186. package/dist/daemon/paths.cjs +0 -20
  187. package/dist/daemon/paths.cjs.map +0 -1
  188. package/dist/daemon/paths.d.cts +0 -9
  189. package/dist/daemon/paths.d.cts.map +0 -1
  190. package/dist/daemon/paths.d.mts.map +0 -1
  191. package/dist/daemon/paths.mjs.map +0 -1
  192. package/dist/daemon/prompts.cjs +0 -55
  193. package/dist/daemon/prompts.cjs.map +0 -1
  194. package/dist/daemon/prompts.d.cts.map +0 -1
  195. package/dist/daemon/prompts.d.mts +0 -31
  196. package/dist/daemon/prompts.d.mts.map +0 -1
  197. package/dist/daemon/prompts.mjs.map +0 -1
  198. package/dist/daemon/rpc-socket-server.cjs +0 -284
  199. package/dist/daemon/rpc-socket-server.cjs.map +0 -1
  200. package/dist/daemon/rpc-socket-server.d.cts.map +0 -1
  201. package/dist/daemon/rpc-socket-server.d.mts +0 -44
  202. package/dist/daemon/rpc-socket-server.d.mts.map +0 -1
  203. package/dist/daemon/rpc-socket-server.mjs.map +0 -1
  204. package/dist/daemon/secrets.cjs +0 -137
  205. package/dist/daemon/secrets.cjs.map +0 -1
  206. package/dist/daemon/secrets.d.cts.map +0 -1
  207. package/dist/daemon/secrets.d.mts +0 -72
  208. package/dist/daemon/secrets.d.mts.map +0 -1
  209. package/dist/daemon/secrets.mjs.map +0 -1
  210. package/dist/daemon/send-transaction.cjs +0 -147
  211. package/dist/daemon/send-transaction.cjs.map +0 -1
  212. package/dist/daemon/send-transaction.d.cts.map +0 -1
  213. package/dist/daemon/send-transaction.d.mts +0 -102
  214. package/dist/daemon/send-transaction.d.mts.map +0 -1
  215. package/dist/daemon/send-transaction.mjs.map +0 -1
  216. package/dist/daemon/socket-line.cjs +0 -93
  217. package/dist/daemon/socket-line.cjs.map +0 -1
  218. package/dist/daemon/socket-line.d.cts.map +0 -1
  219. package/dist/daemon/socket-line.d.mts +0 -21
  220. package/dist/daemon/socket-line.d.mts.map +0 -1
  221. package/dist/daemon/socket-line.mjs.map +0 -1
  222. package/dist/daemon/stop-daemon.cjs +0 -117
  223. package/dist/daemon/stop-daemon.cjs.map +0 -1
  224. package/dist/daemon/stop-daemon.d.cts.map +0 -1
  225. package/dist/daemon/stop-daemon.d.mts +0 -28
  226. package/dist/daemon/stop-daemon.d.mts.map +0 -1
  227. package/dist/daemon/stop-daemon.mjs.map +0 -1
  228. package/dist/daemon/types.cjs +0 -20
  229. package/dist/daemon/types.cjs.map +0 -1
  230. package/dist/daemon/types.d.cts.map +0 -1
  231. package/dist/daemon/types.d.mts +0 -94
  232. package/dist/daemon/types.d.mts.map +0 -1
  233. package/dist/daemon/types.mjs.map +0 -1
  234. package/dist/daemon/utils.cjs +0 -172
  235. package/dist/daemon/utils.cjs.map +0 -1
  236. package/dist/daemon/utils.d.cts.map +0 -1
  237. package/dist/daemon/utils.d.mts +0 -87
  238. package/dist/daemon/utils.d.mts.map +0 -1
  239. package/dist/daemon/utils.mjs.map +0 -1
  240. package/dist/daemon/wallet-factory.cjs +0 -341
  241. package/dist/daemon/wallet-factory.cjs.map +0 -1
  242. package/dist/daemon/wallet-factory.d.cts.map +0 -1
  243. package/dist/daemon/wallet-factory.d.mts +0 -64
  244. package/dist/daemon/wallet-factory.d.mts.map +0 -1
  245. package/dist/daemon/wallet-factory.mjs.map +0 -1
  246. package/dist/persistence/KeyValueStore.cjs +0 -79
  247. package/dist/persistence/KeyValueStore.cjs.map +0 -1
  248. package/dist/persistence/KeyValueStore.d.cts.map +0 -1
  249. package/dist/persistence/KeyValueStore.d.mts +0 -18
  250. package/dist/persistence/KeyValueStore.d.mts.map +0 -1
  251. package/dist/persistence/KeyValueStore.mjs +0 -79
  252. package/dist/persistence/KeyValueStore.mjs.map +0 -1
  253. package/dist/persistence/persistence.cjs +0 -204
  254. package/dist/persistence/persistence.cjs.map +0 -1
  255. package/dist/persistence/persistence.d.cts.map +0 -1
  256. package/dist/persistence/persistence.d.mts +0 -45
  257. package/dist/persistence/persistence.d.mts.map +0 -1
  258. package/dist/persistence/persistence.mjs.map +0 -1
  259. package/dist/test/run-command.cjs +0 -73
  260. package/dist/test/run-command.cjs.map +0 -1
  261. package/dist/test/run-command.d.cts.map +0 -1
  262. package/dist/test/run-command.d.mts +0 -27
  263. package/dist/test/run-command.d.mts.map +0 -1
  264. package/dist/test/run-command.mjs.map +0 -1
@@ -1,17 +1,11 @@
1
- var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
2
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
3
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
4
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
5
- };
6
- var _WalletSend_instances, _WalletSend_dispatchSend;
7
- import { is } from "@metamask/superstruct";
8
- import { bigIntToHex, isJsonRpcFailure, toWei } from "@metamask/utils";
9
- import { Command, Flags } from "@oclif/core";
10
- import { sendCommand } from "../../daemon/daemon-client.mjs";
11
- import { getDaemonPaths } from "../../daemon/paths.mjs";
12
- import { confirmSend } from "../../daemon/prompts.mjs";
13
- import { SendTransactionBroadcastResultStruct, SendTransactionDryRunResultStruct } from "../../daemon/send-transaction.mjs";
14
- import { emptyToUndefined, formatJsonRpcError, makeDaemonConnectionError } from "../../daemon/utils.mjs";
1
+ import { is } from '@metamask/superstruct';
2
+ import { bigIntToHex, isJsonRpcFailure, toWei } from '@metamask/utils';
3
+ import { Command, Flags } from '@oclif/core';
4
+ import { sendCommand } from '../../daemon/daemon-client.js';
5
+ import { getDaemonPaths } from '../../daemon/paths.js';
6
+ import { confirmSend } from '../../daemon/prompts.js';
7
+ import { SendTransactionBroadcastResultStruct, SendTransactionDryRunResultStruct, } from '../../daemon/send-transaction.js';
8
+ import { emptyToUndefined, formatJsonRpcError, makeDaemonConnectionError, } from '../../daemon/utils.js';
15
9
  const ETHER_DECIMALS = 18;
16
10
  /**
17
11
  * Fallback response timeout (ms) for the broadcast call. Broadcasting waits for
@@ -20,7 +14,7 @@ const ETHER_DECIMALS = 18;
20
14
  * successful send look like a failure and tempt a duplicate re-send.
21
15
  * `--timeout` overrides it.
22
16
  */
23
- const BROADCAST_TIMEOUT_MS = 120000;
17
+ const BROADCAST_TIMEOUT_MS = 120_000;
24
18
  /**
25
19
  * Convert a decimal ether amount to a `0x`-prefixed wei quantity.
26
20
  *
@@ -48,11 +42,61 @@ export function parseEtherToWeiHex(amount) {
48
42
  }
49
43
  return bigIntToHex(toWei(trimmed, 'ether'));
50
44
  }
51
- class WalletSend extends Command {
52
- constructor() {
53
- super(...arguments);
54
- _WalletSend_instances.add(this);
55
- }
45
+ export default class WalletSend extends Command {
46
+ static description = 'Send a transaction through the daemon-hosted TransactionController. ' +
47
+ 'Estimates gas automatically unless overridden, signs, broadcasts, and ' +
48
+ 'prints the resulting transaction hash. The daemon auto-approves, so the ' +
49
+ 'confirmation boundary is this command.';
50
+ static examples = [
51
+ '<%= config.bin %> wallet send --to 0xRecipient --value 0.01 --chain-id 0x1',
52
+ '<%= config.bin %> wallet send --to 0xRecipient --value 0.01 --network-client-id mainnet --yes',
53
+ '<%= config.bin %> wallet send --to 0xContract --data 0xabcdef --value 0 --chain-id 0x1 --dry-run',
54
+ ];
55
+ static flags = {
56
+ to: Flags.string({
57
+ description: 'Recipient address (0x-prefixed)',
58
+ required: true,
59
+ }),
60
+ value: Flags.string({
61
+ description: 'Amount to send, in ether (e.g. 0.01). Defaults to 0.',
62
+ default: '0',
63
+ }),
64
+ from: Flags.string({
65
+ description: 'Sender address (0x-prefixed). Defaults to the selected account.',
66
+ }),
67
+ data: Flags.string({
68
+ description: 'Calldata as a 0x-prefixed hex string (for contract calls)',
69
+ }),
70
+ 'network-client-id': Flags.string({
71
+ description: 'Network client to send on. Provide this or --chain-id, not both.',
72
+ }),
73
+ 'chain-id': Flags.string({
74
+ description: 'Chain ID (0x-prefixed hex) to resolve to a network client. Provide this or --network-client-id, not both.',
75
+ }),
76
+ gas: Flags.string({
77
+ description: 'Gas limit override, as a 0x-prefixed hex quantity',
78
+ }),
79
+ 'max-fee-per-gas': Flags.string({
80
+ description: 'maxFeePerGas override, as a 0x-prefixed hex wei quantity',
81
+ }),
82
+ 'max-priority-fee-per-gas': Flags.string({
83
+ description: 'maxPriorityFeePerGas override, as a 0x-prefixed hex wei quantity',
84
+ }),
85
+ 'gas-price': Flags.string({
86
+ description: 'Legacy gasPrice override, as a 0x-prefixed hex wei quantity',
87
+ }),
88
+ 'dry-run': Flags.boolean({
89
+ description: 'Resolve the network client and sender and validate params, but do not broadcast.',
90
+ }),
91
+ yes: Flags.boolean({
92
+ char: 'y',
93
+ description: 'Skip the confirmation prompt and broadcast immediately.',
94
+ }),
95
+ timeout: Flags.integer({
96
+ char: 't',
97
+ description: 'Response timeout in milliseconds',
98
+ }),
99
+ };
56
100
  async run() {
57
101
  const { flags } = await this.parse(WalletSend);
58
102
  const networkClientId = emptyToUndefined(flags['network-client-id']);
@@ -106,7 +150,7 @@ class WalletSend extends Command {
106
150
  // previews first so the confirmation shows (and then pins) the resolved
107
151
  // sender/network; `--yes` skips straight to the broadcast.
108
152
  if (flags['dry-run']) {
109
- const preview = await __classPrivateFieldGet(this, _WalletSend_instances, "m", _WalletSend_dispatchSend).call(this, {
153
+ const preview = await this.#dispatchSend({
110
154
  socketPath,
111
155
  params: { ...params, dryRun: true },
112
156
  timeoutMs,
@@ -118,7 +162,7 @@ class WalletSend extends Command {
118
162
  }
119
163
  let resolved;
120
164
  if (!flags.yes) {
121
- const preview = await __classPrivateFieldGet(this, _WalletSend_instances, "m", _WalletSend_dispatchSend).call(this, {
165
+ const preview = await this.#dispatchSend({
122
166
  socketPath,
123
167
  params: { ...params, dryRun: true },
124
168
  timeoutMs,
@@ -154,7 +198,7 @@ class WalletSend extends Command {
154
198
  networkClientId: resolved.networkClientId,
155
199
  }
156
200
  : params;
157
- const result = await __classPrivateFieldGet(this, _WalletSend_instances, "m", _WalletSend_dispatchSend).call(this, {
201
+ const result = await this.#dispatchSend({
158
202
  socketPath,
159
203
  params: broadcastParams,
160
204
  timeoutMs: timeoutMs ?? BROADCAST_TIMEOUT_MS,
@@ -166,107 +210,51 @@ class WalletSend extends Command {
166
210
  this.log(`Id: ${result.transactionId}`);
167
211
  this.log(`Status: ${result.status}`);
168
212
  }
169
- }
170
- _WalletSend_instances = new WeakSet(), _WalletSend_dispatchSend =
171
- /**
172
- * Send a `sendTransaction` RPC to the daemon and return its validated result,
173
- * translating connection errors, broadcast timeouts, JSON-RPC failures, and
174
- * unexpected payloads into command errors.
175
- *
176
- * @param options - Dispatch options.
177
- * @param options.socketPath - The daemon Unix socket path.
178
- * @param options.params - The `sendTransaction` params (with or without
179
- * `dryRun`).
180
- * @param options.timeoutMs - Optional response timeout in milliseconds.
181
- * @param options.struct - Struct the `result` payload must satisfy; the
182
- * return type is inferred from it.
183
- * @param options.broadcast - Whether this is the real (fund-moving) broadcast.
184
- * When true, a read timeout is reported with guidance that the send may
185
- * already be in flight, so the user does not blindly re-send.
186
- * @returns The validated `result` payload.
187
- */
188
- async function _WalletSend_dispatchSend(options) {
189
- const { socketPath, params, timeoutMs, struct, broadcast } = options;
190
- let response;
191
- try {
192
- response = await sendCommand({
193
- socketPath,
194
- method: 'sendTransaction',
195
- params,
196
- ...(timeoutMs === undefined ? {} : { timeoutMs }),
197
- });
198
- }
199
- catch (error) {
200
- if (broadcast && isReadTimeout(error)) {
201
- this.error(broadcastTimeoutMessage());
213
+ /**
214
+ * Send a `sendTransaction` RPC to the daemon and return its validated result,
215
+ * translating connection errors, broadcast timeouts, JSON-RPC failures, and
216
+ * unexpected payloads into command errors.
217
+ *
218
+ * @param options - Dispatch options.
219
+ * @param options.socketPath - The daemon Unix socket path.
220
+ * @param options.params - The `sendTransaction` params (with or without
221
+ * `dryRun`).
222
+ * @param options.timeoutMs - Optional response timeout in milliseconds.
223
+ * @param options.struct - Struct the `result` payload must satisfy; the
224
+ * return type is inferred from it.
225
+ * @param options.broadcast - Whether this is the real (fund-moving) broadcast.
226
+ * When true, a read timeout is reported with guidance that the send may
227
+ * already be in flight, so the user does not blindly re-send.
228
+ * @returns The validated `result` payload.
229
+ */
230
+ async #dispatchSend(options) {
231
+ const { socketPath, params, timeoutMs, struct, broadcast } = options;
232
+ let response;
233
+ try {
234
+ response = await sendCommand({
235
+ socketPath,
236
+ method: 'sendTransaction',
237
+ params,
238
+ ...(timeoutMs === undefined ? {} : { timeoutMs }),
239
+ });
202
240
  }
203
- this.error(makeDaemonConnectionError(error));
204
- }
205
- if (isJsonRpcFailure(response)) {
206
- this.error(formatJsonRpcError(response.error));
207
- }
208
- const { result } = response;
209
- if (!is(result, struct)) {
210
- this.error(`The daemon returned an unexpected ${broadcast ? 'send' : 'dry-run'} ` +
211
- 'result. It may be running an incompatible version.');
241
+ catch (error) {
242
+ if (broadcast && isReadTimeout(error)) {
243
+ this.error(broadcastTimeoutMessage());
244
+ }
245
+ this.error(makeDaemonConnectionError(error));
246
+ }
247
+ if (isJsonRpcFailure(response)) {
248
+ this.error(formatJsonRpcError(response.error));
249
+ }
250
+ const { result } = response;
251
+ if (!is(result, struct)) {
252
+ this.error(`The daemon returned an unexpected ${broadcast ? 'send' : 'dry-run'} ` +
253
+ 'result. It may be running an incompatible version.');
254
+ }
255
+ return result;
212
256
  }
213
- return result;
214
- };
215
- WalletSend.description = 'Send a transaction through the daemon-hosted TransactionController. ' +
216
- 'Estimates gas automatically unless overridden, signs, broadcasts, and ' +
217
- 'prints the resulting transaction hash. The daemon auto-approves, so the ' +
218
- 'confirmation boundary is this command.';
219
- WalletSend.examples = [
220
- '<%= config.bin %> wallet send --to 0xRecipient --value 0.01 --chain-id 0x1',
221
- '<%= config.bin %> wallet send --to 0xRecipient --value 0.01 --network-client-id mainnet --yes',
222
- '<%= config.bin %> wallet send --to 0xContract --data 0xabcdef --value 0 --chain-id 0x1 --dry-run',
223
- ];
224
- WalletSend.flags = {
225
- to: Flags.string({
226
- description: 'Recipient address (0x-prefixed)',
227
- required: true,
228
- }),
229
- value: Flags.string({
230
- description: 'Amount to send, in ether (e.g. 0.01). Defaults to 0.',
231
- default: '0',
232
- }),
233
- from: Flags.string({
234
- description: 'Sender address (0x-prefixed). Defaults to the selected account.',
235
- }),
236
- data: Flags.string({
237
- description: 'Calldata as a 0x-prefixed hex string (for contract calls)',
238
- }),
239
- 'network-client-id': Flags.string({
240
- description: 'Network client to send on. Provide this or --chain-id, not both.',
241
- }),
242
- 'chain-id': Flags.string({
243
- description: 'Chain ID (0x-prefixed hex) to resolve to a network client. Provide this or --network-client-id, not both.',
244
- }),
245
- gas: Flags.string({
246
- description: 'Gas limit override, as a 0x-prefixed hex quantity',
247
- }),
248
- 'max-fee-per-gas': Flags.string({
249
- description: 'maxFeePerGas override, as a 0x-prefixed hex wei quantity',
250
- }),
251
- 'max-priority-fee-per-gas': Flags.string({
252
- description: 'maxPriorityFeePerGas override, as a 0x-prefixed hex wei quantity',
253
- }),
254
- 'gas-price': Flags.string({
255
- description: 'Legacy gasPrice override, as a 0x-prefixed hex wei quantity',
256
- }),
257
- 'dry-run': Flags.boolean({
258
- description: 'Resolve the network client and sender and validate params, but do not broadcast.',
259
- }),
260
- yes: Flags.boolean({
261
- char: 'y',
262
- description: 'Skip the confirmation prompt and broadcast immediately.',
263
- }),
264
- timeout: Flags.integer({
265
- char: 't',
266
- description: 'Response timeout in milliseconds',
267
- }),
268
- };
269
- export default WalletSend;
257
+ }
270
258
  /**
271
259
  * Whether an error is the daemon-client socket read timeout. It carries no
272
260
  * errno code, so its message is the only signal.
@@ -325,4 +313,4 @@ function formatPlan(plan, etherAmount, extras) {
325
313
  }
326
314
  return lines.join('\n');
327
315
  }
328
- //# sourceMappingURL=send.mjs.map
316
+ //# sourceMappingURL=send.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"send.js","sourceRoot":"","sources":["../../../src/commands/wallet/send.ts"],"names":[],"mappings":"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","sourcesContent":["import { is } from '@metamask/superstruct';\nimport type { Struct } from '@metamask/superstruct';\nimport { bigIntToHex, isJsonRpcFailure, toWei } from '@metamask/utils';\nimport type { Hex, Json, JsonRpcParams } from '@metamask/utils';\nimport { Command, Flags } from '@oclif/core';\n\nimport { sendCommand } from '../../daemon/daemon-client.js';\nimport { getDaemonPaths } from '../../daemon/paths.js';\nimport { confirmSend } from '../../daemon/prompts.js';\nimport {\n SendTransactionBroadcastResultStruct,\n SendTransactionDryRunResultStruct,\n} from '../../daemon/send-transaction.js';\nimport type { SendTransactionDryRunResult } from '../../daemon/send-transaction.js';\nimport {\n emptyToUndefined,\n formatJsonRpcError,\n makeDaemonConnectionError,\n} from '../../daemon/utils.js';\n\nconst ETHER_DECIMALS = 18;\n\n/**\n * Fallback response timeout (ms) for the broadcast call. Broadcasting waits for\n * signing and `eth_sendRawTransaction` server-side, which can far outlast the\n * 30s default used for cheap RPCs; too short a timeout would make a slow but\n * successful send look like a failure and tempt a duplicate re-send.\n * `--timeout` overrides it.\n */\nconst BROADCAST_TIMEOUT_MS = 120_000;\n\n/**\n * The transaction fields shown in the confirmation preview that the daemon\n * does not echo back (they are the raw `--data` / gas overrides the user\n * passed, so the CLI supplies them for display).\n */\ntype PlanExtras = {\n data?: string | undefined;\n gas?: string | undefined;\n maxFeePerGas?: string | undefined;\n maxPriorityFeePerGas?: string | undefined;\n gasPrice?: string | undefined;\n};\n\n/**\n * Convert a decimal ether amount to a `0x`-prefixed wei quantity.\n *\n * The fixed-point conversion is delegated to `@metamask/utils`' `toWei` rather\n * than re-deriving the wei math here. The daemon's `sendTransaction` boundary\n * expects canonical hex wei; this is where the human-friendly `--value` (ether)\n * is turned into it.\n *\n * `toWei` silently accepts negatives and throws opaque messages on other\n * malformed input, so the value is guarded up front for a clear error and a\n * strictly non-negative amount.\n *\n * @param amount - A non-negative decimal ether amount (e.g. `\"0.1\"`, `\"1\"`).\n * @returns The equivalent wei as a `0x`-prefixed hex string.\n * @throws If `amount` is not a non-negative decimal or has more than 18\n * fractional digits.\n */\nexport function parseEtherToWeiHex(amount: string): Hex {\n const trimmed = amount.trim();\n if (!/^\\d+(?:\\.\\d+)?$/u.test(trimmed)) {\n throw new Error(\n `Invalid value \"${amount}\": expected a non-negative decimal amount of ether (e.g. 0.1).`,\n );\n }\n\n if ((trimmed.split('.')[1] ?? '').length > ETHER_DECIMALS) {\n throw new Error(\n `Invalid value \"${amount}\": ether has at most ${ETHER_DECIMALS} decimal places.`,\n );\n }\n\n return bigIntToHex(toWei(trimmed, 'ether'));\n}\n\nexport default class WalletSend extends Command {\n static override description =\n 'Send a transaction through the daemon-hosted TransactionController. ' +\n 'Estimates gas automatically unless overridden, signs, broadcasts, and ' +\n 'prints the resulting transaction hash. The daemon auto-approves, so the ' +\n 'confirmation boundary is this command.';\n\n static override examples = [\n '<%= config.bin %> wallet send --to 0xRecipient --value 0.01 --chain-id 0x1',\n '<%= config.bin %> wallet send --to 0xRecipient --value 0.01 --network-client-id mainnet --yes',\n '<%= config.bin %> wallet send --to 0xContract --data 0xabcdef --value 0 --chain-id 0x1 --dry-run',\n ];\n\n static override flags = {\n to: Flags.string({\n description: 'Recipient address (0x-prefixed)',\n required: true,\n }),\n value: Flags.string({\n description: 'Amount to send, in ether (e.g. 0.01). Defaults to 0.',\n default: '0',\n }),\n from: Flags.string({\n description:\n 'Sender address (0x-prefixed). Defaults to the selected account.',\n }),\n data: Flags.string({\n description: 'Calldata as a 0x-prefixed hex string (for contract calls)',\n }),\n 'network-client-id': Flags.string({\n description:\n 'Network client to send on. Provide this or --chain-id, not both.',\n }),\n 'chain-id': Flags.string({\n description:\n 'Chain ID (0x-prefixed hex) to resolve to a network client. Provide this or --network-client-id, not both.',\n }),\n gas: Flags.string({\n description: 'Gas limit override, as a 0x-prefixed hex quantity',\n }),\n 'max-fee-per-gas': Flags.string({\n description: 'maxFeePerGas override, as a 0x-prefixed hex wei quantity',\n }),\n 'max-priority-fee-per-gas': Flags.string({\n description:\n 'maxPriorityFeePerGas override, as a 0x-prefixed hex wei quantity',\n }),\n 'gas-price': Flags.string({\n description:\n 'Legacy gasPrice override, as a 0x-prefixed hex wei quantity',\n }),\n 'dry-run': Flags.boolean({\n description:\n 'Resolve the network client and sender and validate params, but do not broadcast.',\n }),\n yes: Flags.boolean({\n char: 'y',\n description: 'Skip the confirmation prompt and broadcast immediately.',\n }),\n timeout: Flags.integer({\n char: 't',\n description: 'Response timeout in milliseconds',\n }),\n };\n\n public async run(): Promise<void> {\n const { flags } = await this.parse(WalletSend);\n\n const networkClientId = emptyToUndefined(flags['network-client-id']);\n const chainId = emptyToUndefined(flags['chain-id']);\n if ((networkClientId === undefined) === (chainId === undefined)) {\n this.error('Provide exactly one of --network-client-id or --chain-id.');\n }\n\n let value: string;\n try {\n value = parseEtherToWeiHex(flags.value);\n } catch (error) {\n // `parseEtherToWeiHex` only ever throws `Error`.\n this.error((error as Error).message);\n }\n\n // Everything except the network selector. The selector is added per call:\n // a confirmed broadcast pins the `networkClientId` the preview resolved\n // rather than re-sending `--chain-id` and re-resolving it.\n const baseParams: Record<string, Json> = {\n to: flags.to,\n value,\n ...(flags.from ? { from: flags.from } : {}),\n ...(flags.data ? { data: flags.data } : {}),\n ...(flags.gas ? { gas: flags.gas } : {}),\n ...(flags['max-fee-per-gas']\n ? { maxFeePerGas: flags['max-fee-per-gas'] }\n : {}),\n ...(flags['max-priority-fee-per-gas']\n ? { maxPriorityFeePerGas: flags['max-priority-fee-per-gas'] }\n : {}),\n ...(flags['gas-price'] ? { gasPrice: flags['gas-price'] } : {}),\n };\n // Exactly one selector is defined (guarded above); guard each spread by its\n // own `undefined` check so the object never carries an `undefined` value.\n const params: Record<string, Json> = {\n ...baseParams,\n ...(networkClientId === undefined ? {} : { networkClientId }),\n ...(chainId === undefined ? {} : { chainId }),\n };\n const planExtras: PlanExtras = {\n data: flags.data,\n gas: flags.gas,\n maxFeePerGas: flags['max-fee-per-gas'],\n maxPriorityFeePerGas: flags['max-priority-fee-per-gas'],\n gasPrice: flags['gas-price'],\n };\n\n const { socketPath } = getDaemonPaths(this.config.dataDir);\n const timeoutMs = flags.timeout;\n\n // A `dryRun` resolves the sender and network client server-side without\n // broadcasting. `--dry-run` stops after previewing; an interactive run\n // previews first so the confirmation shows (and then pins) the resolved\n // sender/network; `--yes` skips straight to the broadcast.\n if (flags['dry-run']) {\n const preview = await this.#dispatchSend({\n socketPath,\n params: { ...params, dryRun: true },\n timeoutMs,\n struct: SendTransactionDryRunResultStruct,\n broadcast: false,\n });\n this.log(formatPlan(preview, flags.value, planExtras));\n return;\n }\n\n let resolved: SendTransactionDryRunResult | undefined;\n if (!flags.yes) {\n const preview = await this.#dispatchSend({\n socketPath,\n params: { ...params, dryRun: true },\n timeoutMs,\n struct: SendTransactionDryRunResultStruct,\n broadcast: false,\n });\n\n let confirmed: boolean;\n try {\n confirmed = await confirmSend(\n formatPlan(preview, flags.value, planExtras),\n );\n } catch (error) {\n // Ctrl+C at the prompt (@inquirer/core's ExitPromptError) is a clean\n // abort, not a failure; anything else should surface.\n if (error instanceof Error && error.name === 'ExitPromptError') {\n this.log('Aborted.');\n return;\n }\n throw error;\n }\n if (!confirmed) {\n this.log('Aborted.');\n return;\n }\n resolved = preview;\n }\n\n // Broadcast the exact sender/network the user reviewed (when they confirmed\n // a preview), so what is signed matches what was shown. `--yes` skips the\n // preview, so there it re-resolves server-side from `params`.\n const broadcastParams: Record<string, Json> = resolved\n ? {\n ...baseParams,\n from: resolved.from,\n networkClientId: resolved.networkClientId,\n }\n : params;\n\n const result = await this.#dispatchSend({\n socketPath,\n params: broadcastParams,\n timeoutMs: timeoutMs ?? BROADCAST_TIMEOUT_MS,\n struct: SendTransactionBroadcastResultStruct,\n broadcast: true,\n });\n this.log('Transaction broadcast.');\n this.log(`Hash: ${result.transactionHash}`);\n this.log(`Id: ${result.transactionId}`);\n this.log(`Status: ${result.status}`);\n }\n\n /**\n * Send a `sendTransaction` RPC to the daemon and return its validated result,\n * translating connection errors, broadcast timeouts, JSON-RPC failures, and\n * unexpected payloads into command errors.\n *\n * @param options - Dispatch options.\n * @param options.socketPath - The daemon Unix socket path.\n * @param options.params - The `sendTransaction` params (with or without\n * `dryRun`).\n * @param options.timeoutMs - Optional response timeout in milliseconds.\n * @param options.struct - Struct the `result` payload must satisfy; the\n * return type is inferred from it.\n * @param options.broadcast - Whether this is the real (fund-moving) broadcast.\n * When true, a read timeout is reported with guidance that the send may\n * already be in flight, so the user does not blindly re-send.\n * @returns The validated `result` payload.\n */\n async #dispatchSend<Value>(options: {\n socketPath: string;\n params: JsonRpcParams;\n timeoutMs: number | undefined;\n struct: Struct<Value>;\n broadcast: boolean;\n }): Promise<Value> {\n const { socketPath, params, timeoutMs, struct, broadcast } = options;\n let response;\n try {\n response = await sendCommand({\n socketPath,\n method: 'sendTransaction',\n params,\n ...(timeoutMs === undefined ? {} : { timeoutMs }),\n });\n } catch (error) {\n if (broadcast && isReadTimeout(error)) {\n this.error(broadcastTimeoutMessage());\n }\n this.error(makeDaemonConnectionError(error));\n }\n\n if (isJsonRpcFailure(response)) {\n this.error(formatJsonRpcError(response.error));\n }\n\n const { result } = response;\n if (!is(result, struct)) {\n this.error(\n `The daemon returned an unexpected ${broadcast ? 'send' : 'dry-run'} ` +\n 'result. It may be running an incompatible version.',\n );\n }\n return result;\n }\n}\n\n/**\n * Whether an error is the daemon-client socket read timeout. It carries no\n * errno code, so its message is the only signal.\n *\n * @param error - The caught value.\n * @returns True if it is the read timeout.\n */\nfunction isReadTimeout(error: unknown): boolean {\n return error instanceof Error && error.message === 'Socket read timed out';\n}\n\n/**\n * The message shown when the broadcast call times out. A send is not\n * idempotent, and the daemon may still be broadcasting after the client gives\n * up waiting, so this warns against a blind re-run rather than reading as a\n * plain connection failure.\n *\n * @returns The user-facing guidance.\n */\nfunction broadcastTimeoutMessage(): string {\n return (\n 'The daemon did not respond in time, but your transaction may still be ' +\n 'broadcasting. Do NOT re-run this command — you could send it twice. ' +\n 'Check `mm daemon status`, the daemon log, or your account on-chain to ' +\n 'confirm, then use --timeout to wait longer if needed.'\n );\n}\n\n/**\n * Format a dry-run plan for display (and as the confirmation prompt body).\n *\n * @param plan - The dry-run result returned by the daemon.\n * @param etherAmount - The original `--value` (ether), shown alongside the\n * resolved wei so the user sees the human amount they typed.\n * @param extras - The `--data` / gas overrides the daemon does not echo back,\n * shown so the user confirms exactly what will be sent.\n * @returns A multi-line summary of the transaction to be sent.\n */\nfunction formatPlan(\n plan: SendTransactionDryRunResult,\n etherAmount: string,\n extras: PlanExtras,\n): string {\n const lines = [\n 'About to send:',\n ` To: ${plan.to}`,\n ` From: ${plan.from}`,\n ` Value: ${etherAmount} ETH (${plan.value} wei)`,\n ` Network: ${plan.networkClientId}`,\n ];\n if (extras.data) {\n lines.push(` Data: ${extras.data}`);\n }\n const gasParts = [\n extras.gas ? `gas=${extras.gas}` : undefined,\n extras.maxFeePerGas ? `maxFeePerGas=${extras.maxFeePerGas}` : undefined,\n extras.maxPriorityFeePerGas\n ? `maxPriorityFeePerGas=${extras.maxPriorityFeePerGas}`\n : undefined,\n extras.gasPrice ? `gasPrice=${extras.gasPrice}` : undefined,\n ].filter((part): part is string => part !== undefined);\n if (gasParts.length > 0) {\n lines.push(` Gas: ${gasParts.join(', ')}`);\n }\n return lines.join('\\n');\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { Command } from "@oclif/core";
1
+ import { Command } from '@oclif/core';
2
2
  export default class WalletUnlock extends Command {
3
3
  static description: string;
4
4
  static examples: string[];
@@ -8,4 +8,4 @@ export default class WalletUnlock extends Command {
8
8
  };
9
9
  run(): Promise<void>;
10
10
  }
11
- //# sourceMappingURL=unlock.d.cts.map
11
+ //# sourceMappingURL=unlock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unlock.d.ts","sourceRoot":"","sources":["../../../src/commands/wallet/unlock.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAS,MAAM,aAAa,CAAC;AAU7C,MAAM,CAAC,OAAO,OAAO,YAAa,SAAQ,OAAO;IAC/C,OAAgB,WAAW,SAGyC;IAEpE,OAAgB,QAAQ,WAItB;IAEF,OAAgB,KAAK;QACnB,QAAQ;QAOR,OAAO;MAKP;IAEW,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,CA+ChC;CACF"}
@@ -1,10 +1,31 @@
1
- import { isJsonRpcFailure } from "@metamask/utils";
2
- import { Command, Flags } from "@oclif/core";
3
- import { sendCommand } from "../../daemon/daemon-client.mjs";
4
- import { getDaemonPaths } from "../../daemon/paths.mjs";
5
- import { promptPassword } from "../../daemon/prompts.mjs";
6
- import { emptyToUndefined, makeDaemonConnectionError } from "../../daemon/utils.mjs";
7
- class WalletUnlock extends Command {
1
+ import { isJsonRpcFailure } from '@metamask/utils';
2
+ import { Command, Flags } from '@oclif/core';
3
+ import { sendCommand } from '../../daemon/daemon-client.js';
4
+ import { getDaemonPaths } from '../../daemon/paths.js';
5
+ import { promptPassword } from '../../daemon/prompts.js';
6
+ import { emptyToUndefined, makeDaemonConnectionError, } from '../../daemon/utils.js';
7
+ export default class WalletUnlock extends Command {
8
+ static description = 'Unlock the wallet (submits the password to KeyringController). ' +
9
+ 'Use this after `mm daemon start` was run without `--password`, or ' +
10
+ 'after the keyring was locked via `KeyringController:setLocked`.';
11
+ static examples = [
12
+ '<%= config.bin %> wallet unlock --password <pw>',
13
+ 'MM_WALLET_PASSWORD=<pw> <%= config.bin %> wallet unlock',
14
+ '<%= config.bin %> wallet unlock # prompts interactively',
15
+ ];
16
+ static flags = {
17
+ password: Flags.string({
18
+ description: 'Wallet password (testing only — use MM_WALLET_PASSWORD env var in production). ' +
19
+ 'When omitted, the command prompts interactively.',
20
+ env: 'MM_WALLET_PASSWORD',
21
+ required: false,
22
+ }),
23
+ timeout: Flags.integer({
24
+ char: 't',
25
+ description: 'Response timeout in milliseconds',
26
+ required: false,
27
+ }),
28
+ };
8
29
  async run() {
9
30
  const { flags } = await this.parse(WalletUnlock);
10
31
  const { timeout: timeoutMs } = flags;
@@ -48,26 +69,4 @@ class WalletUnlock extends Command {
48
69
  this.log('Wallet unlocked.');
49
70
  }
50
71
  }
51
- WalletUnlock.description = 'Unlock the wallet (submits the password to KeyringController). ' +
52
- 'Use this after `mm daemon start` was run without `--password`, or ' +
53
- 'after the keyring was locked via `KeyringController:setLocked`.';
54
- WalletUnlock.examples = [
55
- '<%= config.bin %> wallet unlock --password <pw>',
56
- 'MM_WALLET_PASSWORD=<pw> <%= config.bin %> wallet unlock',
57
- '<%= config.bin %> wallet unlock # prompts interactively',
58
- ];
59
- WalletUnlock.flags = {
60
- password: Flags.string({
61
- description: 'Wallet password (testing only — use MM_WALLET_PASSWORD env var in production). ' +
62
- 'When omitted, the command prompts interactively.',
63
- env: 'MM_WALLET_PASSWORD',
64
- required: false,
65
- }),
66
- timeout: Flags.integer({
67
- char: 't',
68
- description: 'Response timeout in milliseconds',
69
- required: false,
70
- }),
71
- };
72
- export default WalletUnlock;
73
- //# sourceMappingURL=unlock.mjs.map
72
+ //# sourceMappingURL=unlock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unlock.js","sourceRoot":"","sources":["../../../src/commands/wallet/unlock.ts"],"names":[],"mappings":"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","sourcesContent":["import { isJsonRpcFailure } from '@metamask/utils';\nimport { Command, Flags } from '@oclif/core';\n\nimport { sendCommand } from '../../daemon/daemon-client.js';\nimport { getDaemonPaths } from '../../daemon/paths.js';\nimport { promptPassword } from '../../daemon/prompts.js';\nimport {\n emptyToUndefined,\n makeDaemonConnectionError,\n} from '../../daemon/utils.js';\n\nexport default class WalletUnlock extends Command {\n static override description =\n 'Unlock the wallet (submits the password to KeyringController). ' +\n 'Use this after `mm daemon start` was run without `--password`, or ' +\n 'after the keyring was locked via `KeyringController:setLocked`.';\n\n static override examples = [\n '<%= config.bin %> wallet unlock --password <pw>',\n 'MM_WALLET_PASSWORD=<pw> <%= config.bin %> wallet unlock',\n '<%= config.bin %> wallet unlock # prompts interactively',\n ];\n\n static override flags = {\n password: Flags.string({\n description:\n 'Wallet password (testing only — use MM_WALLET_PASSWORD env var in production). ' +\n 'When omitted, the command prompts interactively.',\n env: 'MM_WALLET_PASSWORD',\n required: false,\n }),\n timeout: Flags.integer({\n char: 't',\n description: 'Response timeout in milliseconds',\n required: false,\n }),\n };\n\n public async run(): Promise<void> {\n const { flags } = await this.parse(WalletUnlock);\n const { timeout: timeoutMs } = flags;\n\n // `emptyToUndefined` collapses `--password ''` and `MM_WALLET_PASSWORD=''`\n // to undefined so the prompt fires instead of sending an empty string.\n const flagPassword = emptyToUndefined(flags.password);\n let password: string;\n try {\n password = flagPassword ?? (await promptPassword());\n } catch (error) {\n // Only swallow ExitPromptError (@inquirer/core's Ctrl+C signal); any\n // other rejection (import failure, internal prompt crash) should surface.\n if (error instanceof Error && error.name === 'ExitPromptError') {\n return;\n }\n throw error;\n }\n\n const { socketPath } = getDaemonPaths(this.config.dataDir);\n\n let response;\n try {\n response = await sendCommand({\n socketPath,\n method: 'call',\n params: ['KeyringController:submitPassword', password],\n ...(timeoutMs === undefined ? {} : { timeoutMs }),\n });\n } catch (error) {\n this.error(makeDaemonConnectionError(error));\n }\n\n if (isJsonRpcFailure(response)) {\n const { code, message, data } = response.error;\n // `isJsonRpcFailure` already validates that `data` is JSON, so\n // `JSON.stringify` cannot throw here.\n const dataSuffix =\n data === undefined || data === null\n ? ''\n : ` data=${JSON.stringify(data)}`;\n this.error(\n `Failed to unlock: ${message} (code ${String(code)})${dataSuffix}`,\n );\n }\n\n this.log('Wallet unlocked.');\n }\n}\n"]}
@@ -1,5 +1,5 @@
1
- import type { DefaultActions, DefaultEvents, RootMessenger } from "@metamask/wallet";
2
- import type { Logger } from "./types.mjs";
1
+ import type { DefaultActions, DefaultEvents, RootMessenger } from '@metamask/wallet';
2
+ import type { Logger } from './types.js';
3
3
  /**
4
4
  * Subscribe the daemon to auto-accept every pending approval request.
5
5
  *
@@ -19,4 +19,4 @@ import type { Logger } from "./types.mjs";
19
19
  * @returns A function that unsubscribes the auto-approval handler.
20
20
  */
21
21
  export declare function subscribeToAutoApproval(messenger: Readonly<RootMessenger<DefaultActions, DefaultEvents>>, log?: Logger): () => void;
22
- //# sourceMappingURL=auto-approval.d.mts.map
22
+ //# sourceMappingURL=auto-approval.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto-approval.d.ts","sourceRoot":"","sources":["../../src/daemon/auto-approval.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EACb,aAAa,EACd,MAAM,kBAAkB,CAAC;AAE1B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAqBzC;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,QAAQ,CAAC,aAAa,CAAC,cAAc,EAAE,aAAa,CAAC,CAAC,EACjE,GAAG,CAAC,EAAE,MAAM,GACX,MAAM,IAAI,CAyCZ"}
@@ -79,4 +79,4 @@ function subscribeToApprovalStateChanged(messenger, handler) {
79
79
  subscriber.unsubscribe('ApprovalController:stateChanged', handler);
80
80
  };
81
81
  }
82
- //# sourceMappingURL=auto-approval.mjs.map
82
+ //# sourceMappingURL=auto-approval.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto-approval.js","sourceRoot":"","sources":["../../src/daemon/auto-approval.ts"],"names":[],"mappings":"AA2BA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,uBAAuB,CACrC,SAAiE,EACjE,GAAY;IAEZ,MAAM,KAAK,GACT,GAAG;QACH,CAAC,CAAC,OAAe,EAAQ,EAAE;YACzB,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACzB,CAAC,CAAC,CAAC;IAEL,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;IAEnC,MAAM,UAAU,GAAG,CAAC,EAAU,EAAE,KAAc,EAAQ,EAAE;QACtD,KAAK,CAAC,0CAA0C,EAAE,KAAK,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC1E,CAAC,CAAC;IAEF,MAAM,aAAa,GAAG,CAAC,EAAU,EAAQ,EAAE;QACzC,IAAI,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;YACrB,OAAO;QACT,CAAC;QACD,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAEjB,IAAI,CAAC;YACH,SAAS;iBACN,IAAI,CAAC,kCAAkC,EAAE,EAAE,CAAC;iBAC5C,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE,CAAC,UAAU,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;iBAChD,OAAO,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;QACxC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,kEAAkE;YAClE,uEAAuE;YACvE,uEAAuE;YACvE,8DAA8D;YAC9D,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACpB,UAAU,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;QACxB,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,OAAO,GAA+B,CAAC,KAAK,EAAE,EAAE;QACpD,KAAK,MAAM,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,EAAE,CAAC;YACrD,aAAa,CAAC,EAAE,CAAC,CAAC;QACpB,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,+BAA+B,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;AAC7D,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,SAAS,+BAA+B,CACtC,SAAiE,EACjE,OAAmC;IAEnC,MAAM,UAAU,GAAG,SAMlB,CAAC;IACF,UAAU,CAAC,SAAS,CAAC,iCAAiC,EAAE,OAAO,CAAC,CAAC;IACjE,OAAO,GAAG,EAAE;QACV,UAAU,CAAC,WAAW,CAAC,iCAAiC,EAAE,OAAO,CAAC,CAAC;IACrE,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import type {\n DefaultActions,\n DefaultEvents,\n RootMessenger,\n} from '@metamask/wallet';\n\nimport type { Logger } from './types.js';\n\n/**\n * The slice of `ApprovalController` state this module reads. The full\n * state-change payload is the controller's `ApprovalControllerState`; auto\n * approval only needs the ids of the pending requests, so it looks at\n * `pendingApprovals` alone (the request bodies are irrelevant to accepting\n * them).\n */\ntype PendingApprovalsState = {\n pendingApprovals: Record<string, unknown>;\n};\n\n/**\n * Handler for `ApprovalController`'s state-change event, narrowed to the slice\n * auto approval reads. The `Patch[]` second argument from the raw event is\n * intentionally absent — auto approval re-accepts on every state change and\n * does not filter by patch.\n */\ntype ApprovalStateChangeHandler = (state: PendingApprovalsState) => void;\n\n/**\n * Subscribe the daemon to auto-accept every pending approval request.\n *\n * Without this, any `ApprovalController:addRequest` call hangs forever on a\n * headless daemon. **Everything is approved without a prompt** — trust boundary\n * is the `0600` same-user socket. A scoped policy is tracked in\n * {@link https://github.com/MetaMask/core/issues/9513}.\n *\n * The `inFlight` guard makes accepting each id idempotent: `acceptRequest`\n * deletes the request on resolve, which itself re-emits `stateChanged`. Without\n * it the same id would be accepted twice and the second accept would reject.\n * Both sync throws and async rejections are logged and swallowed so one bad\n * request cannot crash the daemon or wedge the subscription.\n *\n * @param messenger - The wallet root messenger.\n * @param log - Optional logger for accept failures. Defaults to `console.error`.\n * @returns A function that unsubscribes the auto-approval handler.\n */\nexport function subscribeToAutoApproval(\n messenger: Readonly<RootMessenger<DefaultActions, DefaultEvents>>,\n log?: Logger,\n): () => void {\n const logFn =\n log ??\n ((message: string): void => {\n console.error(message);\n });\n\n const inFlight = new Set<string>();\n\n const logFailure = (id: string, error: unknown): void => {\n logFn(`Failed to auto-accept approval request ${id}: ${String(error)}`);\n };\n\n const acceptRequest = (id: string): void => {\n if (inFlight.has(id)) {\n return;\n }\n inFlight.add(id);\n\n try {\n messenger\n .call('ApprovalController:acceptRequest', id)\n .catch((error: unknown) => logFailure(id, error))\n .finally(() => inFlight.delete(id));\n } catch (error) {\n // Synchronous throw means the Promise chain above was never built\n // (no .catch/.finally attached), so clean up the in-flight guard here.\n // The error is intentionally suppressed — a race-condition reject must\n // not crash the daemon or permanently wedge the subscription.\n inFlight.delete(id);\n logFailure(id, error);\n }\n };\n\n const handler: ApprovalStateChangeHandler = (state) => {\n for (const id of Object.keys(state.pendingApprovals)) {\n acceptRequest(id);\n }\n };\n\n return subscribeToApprovalStateChanged(messenger, handler);\n}\n\n/**\n * Subscribe a handler to `ApprovalController:stateChanged`.\n *\n * `ApprovalControllerEvents` only declares `ApprovalController:stateChange`\n * (via `ControllerStateChangeEvent`), not the non-deprecated\n * `ApprovalController:stateChanged` variant that `BaseController` publishes at\n * runtime. This helper localizes the unavoidable cast — using the same\n * technique as `subscribeToStateChanged` in the persistence layer — behind a\n * typed {@link ApprovalStateChangeHandler}, keeping the `state` payload\n * compile-checked at the call site instead of erased by a statement-level\n * `@ts-expect-error`.\n *\n * TODO: Remove this cast once `ApprovalControllerEvents` includes\n * `ControllerStateChangedEvent` (`:stateChanged`), matching the union already\n * exported by `BaseController`.\n *\n * @param messenger - The wallet root messenger.\n * @param handler - The state-change handler to register.\n * @returns A function that unsubscribes the handler.\n */\nfunction subscribeToApprovalStateChanged(\n messenger: Readonly<RootMessenger<DefaultActions, DefaultEvents>>,\n handler: ApprovalStateChangeHandler,\n): () => void {\n const subscriber = messenger as unknown as {\n subscribe: (eventType: string, handler: ApprovalStateChangeHandler) => void;\n unsubscribe: (\n eventType: string,\n handler: ApprovalStateChangeHandler,\n ) => void;\n };\n subscriber.subscribe('ApprovalController:stateChanged', handler);\n return () => {\n subscriber.unsubscribe('ApprovalController:stateChanged', handler);\n };\n}\n"]}
@@ -1,4 +1,4 @@
1
- import type { JsonRpcParams, JsonRpcResponse } from "@metamask/utils";
1
+ import type { JsonRpcParams, JsonRpcResponse } from '@metamask/utils';
2
2
  /**
3
3
  * Options for {@link sendCommand}.
4
4
  */
@@ -81,4 +81,4 @@ export type PingResult = {
81
81
  */
82
82
  export declare function pingDaemon(socketPath: string): Promise<PingResult>;
83
83
  export {};
84
- //# sourceMappingURL=daemon-client.d.mts.map
84
+ //# sourceMappingURL=daemon-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon-client.d.ts","sourceRoot":"","sources":["../../src/daemon/daemon-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAWtE;;GAEG;AACH,KAAK,kBAAkB,GAAG;IACxB,4BAA4B;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,2BAA2B;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,MAAM,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IACnC,+DAA+D;IAC/D,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC,CAAC;AAiBF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,WAAW,CAAC,EAChC,UAAU,EACV,MAAM,EACN,MAAM,EACN,SAAS,GACV,EAAE,kBAAkB,GAAG,OAAO,CAAC,eAAe,CAAC,CA4C/C;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,qBAAqB,GAC7B,SAAS,GACT,SAAS,GACT,YAAY,GACZ,UAAU,GACV,OAAO,CAAC;AAEZ;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,UAAU,GAClB;IAAE,MAAM,EAAE,YAAY,CAAA;CAAE,GACxB;IAAE,MAAM,EAAE,QAAQ,CAAA;CAAE,GACpB;IAAE,MAAM,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,qBAAqB,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,CAAC;AA4C3E;;;;;;;;GAQG;AACH,wBAAsB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAcxE"}
@@ -1,9 +1,9 @@
1
- import { assertIsJsonRpcResponse } from "@metamask/utils";
2
- import { randomUUID } from "node:crypto";
3
- import { createConnection } from "node:net";
4
- import { readLine, writeLine } from "./socket-line.mjs";
5
- import { isErrorWithCode } from "./utils.mjs";
6
- const DEFAULT_TIMEOUT_MS = 30000;
1
+ import { assertIsJsonRpcResponse } from '@metamask/utils';
2
+ import { randomUUID } from 'node:crypto';
3
+ import { createConnection } from 'node:net';
4
+ import { readLine, writeLine } from './socket-line.js';
5
+ import { isErrorWithCode } from './utils.js';
6
+ const DEFAULT_TIMEOUT_MS = 30_000;
7
7
  async function connectSocket(socketPath) {
8
8
  return new Promise((resolve, reject) => {
9
9
  const socket = createConnection(socketPath, () => {
@@ -127,7 +127,7 @@ function classifyUnreachable(error) {
127
127
  */
128
128
  export async function pingDaemon(socketPath) {
129
129
  try {
130
- await sendCommand({ socketPath, method: 'getStatus', timeoutMs: 3000 });
130
+ await sendCommand({ socketPath, method: 'getStatus', timeoutMs: 3_000 });
131
131
  return { status: 'responsive' };
132
132
  }
133
133
  catch (error) {
@@ -141,4 +141,4 @@ export async function pingDaemon(socketPath) {
141
141
  };
142
142
  }
143
143
  }
144
- //# sourceMappingURL=daemon-client.mjs.map
144
+ //# sourceMappingURL=daemon-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon-client.js","sourceRoot":"","sources":["../../src/daemon/daemon-client.ts"],"names":[],"mappings":"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","sourcesContent":["import type { JsonRpcParams, JsonRpcResponse } from '@metamask/utils';\nimport { assertIsJsonRpcResponse } from '@metamask/utils';\nimport { randomUUID } from 'node:crypto';\nimport { createConnection } from 'node:net';\nimport type { Socket } from 'node:net';\n\nimport { readLine, writeLine } from './socket-line.js';\nimport { isErrorWithCode } from './utils.js';\n\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\n/**\n * Options for {@link sendCommand}.\n */\ntype SendCommandOptions = {\n /** The Unix socket path. */\n socketPath: string;\n /** The RPC method name. */\n method: string;\n /** Optional method parameters (object or positional array). */\n params?: JsonRpcParams | undefined;\n /** Response read timeout in milliseconds (default: 30 000). */\n timeoutMs?: number | undefined;\n};\n\nasync function connectSocket(socketPath: string): Promise<Socket> {\n return new Promise((resolve, reject) => {\n const socket = createConnection(socketPath, () => {\n socket.removeAllListeners('error');\n resolve(socket);\n });\n socket.on('error', (error) => {\n // A failed connect never reaches the caller, so destroy the socket here\n // to avoid leaking its file descriptor.\n socket.destroy();\n reject(error);\n });\n });\n}\n\n/**\n * Send a JSON-RPC request to the daemon over a Unix socket and return the\n * response.\n *\n * Opens a connection, writes one JSON-RPC request line, reads one JSON-RPC\n * response line, then closes the connection. Retries once after a short delay\n * only on `ECONNREFUSED` — the connection was never established, so the daemon\n * provably never received the request and re-sending is safe. Does not retry\n * on `ECONNRESET`, which can drop after the daemon has already received and\n * acted on the request: blindly re-sending could execute a non-idempotent\n * action (e.g. a transaction broadcast) twice, so it is surfaced to the caller\n * instead. Verifies that the response `id` matches the outgoing request `id`.\n *\n * @param options - Command options.\n * @param options.socketPath - The Unix socket path.\n * @param options.method - The RPC method name.\n * @param options.params - Optional method parameters.\n * @param options.timeoutMs - Read timeout in milliseconds.\n * @returns The parsed JSON-RPC response.\n */\nexport async function sendCommand({\n socketPath,\n method,\n params,\n timeoutMs,\n}: SendCommandOptions): Promise<JsonRpcResponse> {\n const id = randomUUID();\n const request = {\n jsonrpc: '2.0',\n id,\n method,\n ...(params === undefined ? {} : { params }),\n };\n\n const effectiveTimeout = timeoutMs ?? DEFAULT_TIMEOUT_MS;\n\n const attempt = async (): Promise<JsonRpcResponse> => {\n const socket = await connectSocket(socketPath);\n try {\n await writeLine(socket, JSON.stringify(request));\n const responseLine = await readLine(socket, effectiveTimeout);\n const parsed: unknown = JSON.parse(responseLine);\n assertIsJsonRpcResponse(parsed);\n if (parsed.id !== id) {\n throw new Error(\n `JSON-RPC response id ${JSON.stringify(parsed.id)} does not match request id ${JSON.stringify(id)}`,\n );\n }\n return parsed;\n } finally {\n socket.destroy();\n }\n };\n\n try {\n return await attempt();\n } catch (error: unknown) {\n // Only retry on ECONNREFUSED: the connection was never established, so the\n // daemon provably never received the request and re-sending is safe.\n // ECONNRESET can drop *after* the daemon received and began (or finished)\n // processing the request, so blindly re-sending a non-idempotent request\n // (e.g. a transaction broadcast) could execute it twice. Surface it to the\n // caller instead of retrying.\n if (!isErrorWithCode(error, 'ECONNREFUSED')) {\n throw error;\n }\n await new Promise((resolve) => setTimeout(resolve, 100));\n return attempt();\n }\n}\n\n/**\n * Why an unreachable daemon cannot be queried.\n *\n * - `'refused'`: the connection could not be completed — `ECONNREFUSED`\n * (retried once) or `ECONNRESET` (a mid-request drop, not retried). Typical\n * of a daemon that has crashed or is mid-restart.\n * - `'timeout'`: the daemon accepted the connection but did not respond within\n * the read timeout — most likely wedged on a long-running operation.\n * - `'permission'`: the socket exists but cannot be opened (`EACCES` / `EPERM`).\n * The daemon almost certainly belongs to another user.\n * - `'protocol'`: the daemon responded but the response did not parse as a\n * valid JSON-RPC response, or the response id did not match.\n * - `'other'`: anything else.\n */\nexport type PingUnreachableReason =\n | 'refused'\n | 'timeout'\n | 'permission'\n | 'protocol'\n | 'other';\n\n/**\n * Outcome of a daemon health check.\n *\n * - `'responsive'`: the daemon answered a `getStatus` RPC.\n * - `'absent'`: the socket connect attempt failed with `ENOENT`, i.e. no\n * socket file exists at the path. No daemon present.\n * - `'unreachable'`: any other non-success outcome. The daemon may still be\n * alive but is not responding. Callers should not silently take over the\n * slot or assume the daemon is dead. The `reason` field categorises the\n * failure so callers can distinguish a wedged sibling daemon from a\n * foreign-user daemon from a transient crash. User-initiated stop / purge\n * flows may still escalate to signals against the recorded PID.\n */\nexport type PingResult =\n | { status: 'responsive' }\n | { status: 'absent' }\n | { status: 'unreachable'; reason: PingUnreachableReason; error: Error };\n\n/**\n * Normalize an unknown throw into a real Error instance so that downstream\n * consumers (which read `.message`) cannot crash on string/object throws.\n *\n * @param error - The caught value.\n * @returns An Error mirroring the caught value.\n */\nfunction toError(error: unknown): Error {\n return error instanceof Error ? error : new Error(String(error));\n}\n\n/**\n * Categorise an unreachable error by Node errno / message shape so callers can\n * make decisions per failure mode rather than parsing message strings.\n *\n * @param error - The caught value.\n * @returns A {@link PingUnreachableReason} label.\n */\nfunction classifyUnreachable(error: unknown): PingUnreachableReason {\n if (\n isErrorWithCode(error, 'ECONNREFUSED') ||\n isErrorWithCode(error, 'ECONNRESET')\n ) {\n return 'refused';\n }\n if (isErrorWithCode(error, 'EACCES') || isErrorWithCode(error, 'EPERM')) {\n return 'permission';\n }\n if (error instanceof Error && error.message === 'Socket read timed out') {\n return 'timeout';\n }\n if (\n error instanceof Error &&\n (error.message.includes('JSON-RPC response id') ||\n /Expected .* JSON-RPC/u.test(error.message) ||\n error.name === 'SyntaxError')\n ) {\n return 'protocol';\n }\n return 'other';\n}\n\n/**\n * Check whether the daemon is running by sending a lightweight `getStatus`\n * RPC call. Distinguishes \"no daemon present\" (socket file missing) from\n * \"daemon present but unreachable\" (socket file exists but the daemon is\n * wedged, mid-shutdown, or owned by a different user).\n *\n * @param socketPath - The Unix socket path.\n * @returns A {@link PingResult} describing the daemon's reachability.\n */\nexport async function pingDaemon(socketPath: string): Promise<PingResult> {\n try {\n await sendCommand({ socketPath, method: 'getStatus', timeoutMs: 3_000 });\n return { status: 'responsive' };\n } catch (error: unknown) {\n if (isErrorWithCode(error, 'ENOENT')) {\n return { status: 'absent' };\n }\n return {\n status: 'unreachable',\n reason: classifyUnreachable(error),\n error: toError(error),\n };\n }\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=daemon-entry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon-entry.d.ts","sourceRoot":"","sources":["../../src/daemon/daemon-entry.ts"],"names":[],"mappings":""}
@@ -1,14 +1,14 @@
1
- import { define, literal } from "@metamask/superstruct";
2
- import { appendFile, readFile, rm, writeFile } from "node:fs/promises";
3
- import { pingDaemon } from "./daemon-client.mjs";
4
- import { ensureOwnerOnlyDirectory } from "./data-dir.mjs";
5
- import { getDaemonPaths } from "./paths.mjs";
6
- import { startRpcSocketServer } from "./rpc-socket-server.mjs";
7
- import { Password, Srp } from "./secrets.mjs";
8
- import { runSendTransaction, SendTransactionParamsStruct } from "./send-transaction.mjs";
9
- import { defineHandler } from "./types.mjs";
10
- import { isErrorWithCode, isProcessAlive, readPidFile } from "./utils.mjs";
11
- import { createWallet } from "./wallet-factory.mjs";
1
+ import { define, literal } from '@metamask/superstruct';
2
+ import { appendFile, readFile, rm, writeFile } from 'node:fs/promises';
3
+ import { pingDaemon } from './daemon-client.js';
4
+ import { ensureOwnerOnlyDirectory } from './data-dir.js';
5
+ import { getDaemonPaths } from './paths.js';
6
+ import { startRpcSocketServer } from './rpc-socket-server.js';
7
+ import { Password, Srp } from './secrets.js';
8
+ import { runSendTransaction, SendTransactionParamsStruct, } from './send-transaction.js';
9
+ import { defineHandler } from './types.js';
10
+ import { isErrorWithCode, isProcessAlive, readPidFile } from './utils.js';
11
+ import { createWallet } from './wallet-factory.js';
12
12
  /**
13
13
  * Params struct for the `call` RPC method. `params` must be a non-empty array
14
14
  * whose first element is the messenger action name; remaining elements are
@@ -273,4 +273,4 @@ function makeLogger(logPath) {
273
273
  });
274
274
  };
275
275
  }
276
- //# sourceMappingURL=daemon-entry.mjs.map
276
+ //# sourceMappingURL=daemon-entry.js.map