@metamask-previews/wallet-cli 0.0.0-preview-6316943cb → 0.0.0-preview-6cd1bb2f5

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.
@@ -1,328 +0,0 @@
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";
15
- const ETHER_DECIMALS = 18;
16
- /**
17
- * Fallback response timeout (ms) for the broadcast call. Broadcasting waits for
18
- * signing and `eth_sendRawTransaction` server-side, which can far outlast the
19
- * 30s default used for cheap RPCs; too short a timeout would make a slow but
20
- * successful send look like a failure and tempt a duplicate re-send.
21
- * `--timeout` overrides it.
22
- */
23
- const BROADCAST_TIMEOUT_MS = 120000;
24
- /**
25
- * Convert a decimal ether amount to a `0x`-prefixed wei quantity.
26
- *
27
- * The fixed-point conversion is delegated to `@metamask/utils`' `toWei` rather
28
- * than re-deriving the wei math here. The daemon's `sendTransaction` boundary
29
- * expects canonical hex wei; this is where the human-friendly `--value` (ether)
30
- * is turned into it.
31
- *
32
- * `toWei` silently accepts negatives and throws opaque messages on other
33
- * malformed input, so the value is guarded up front for a clear error and a
34
- * strictly non-negative amount.
35
- *
36
- * @param amount - A non-negative decimal ether amount (e.g. `"0.1"`, `"1"`).
37
- * @returns The equivalent wei as a `0x`-prefixed hex string.
38
- * @throws If `amount` is not a non-negative decimal or has more than 18
39
- * fractional digits.
40
- */
41
- export function parseEtherToWeiHex(amount) {
42
- const trimmed = amount.trim();
43
- if (!/^\d+(?:\.\d+)?$/u.test(trimmed)) {
44
- throw new Error(`Invalid value "${amount}": expected a non-negative decimal amount of ether (e.g. 0.1).`);
45
- }
46
- if ((trimmed.split('.')[1] ?? '').length > ETHER_DECIMALS) {
47
- throw new Error(`Invalid value "${amount}": ether has at most ${ETHER_DECIMALS} decimal places.`);
48
- }
49
- return bigIntToHex(toWei(trimmed, 'ether'));
50
- }
51
- class WalletSend extends Command {
52
- constructor() {
53
- super(...arguments);
54
- _WalletSend_instances.add(this);
55
- }
56
- async run() {
57
- const { flags } = await this.parse(WalletSend);
58
- const networkClientId = emptyToUndefined(flags['network-client-id']);
59
- const chainId = emptyToUndefined(flags['chain-id']);
60
- if ((networkClientId === undefined) === (chainId === undefined)) {
61
- this.error('Provide exactly one of --network-client-id or --chain-id.');
62
- }
63
- let value;
64
- try {
65
- value = parseEtherToWeiHex(flags.value);
66
- }
67
- catch (error) {
68
- // `parseEtherToWeiHex` only ever throws `Error`.
69
- this.error(error.message);
70
- }
71
- // Everything except the network selector. The selector is added per call:
72
- // a confirmed broadcast pins the `networkClientId` the preview resolved
73
- // rather than re-sending `--chain-id` and re-resolving it.
74
- const baseParams = {
75
- to: flags.to,
76
- value,
77
- ...(flags.from ? { from: flags.from } : {}),
78
- ...(flags.data ? { data: flags.data } : {}),
79
- ...(flags.gas ? { gas: flags.gas } : {}),
80
- ...(flags['max-fee-per-gas']
81
- ? { maxFeePerGas: flags['max-fee-per-gas'] }
82
- : {}),
83
- ...(flags['max-priority-fee-per-gas']
84
- ? { maxPriorityFeePerGas: flags['max-priority-fee-per-gas'] }
85
- : {}),
86
- ...(flags['gas-price'] ? { gasPrice: flags['gas-price'] } : {}),
87
- };
88
- // Exactly one selector is defined (guarded above); guard each spread by its
89
- // own `undefined` check so the object never carries an `undefined` value.
90
- const params = {
91
- ...baseParams,
92
- ...(networkClientId === undefined ? {} : { networkClientId }),
93
- ...(chainId === undefined ? {} : { chainId }),
94
- };
95
- const planExtras = {
96
- data: flags.data,
97
- gas: flags.gas,
98
- maxFeePerGas: flags['max-fee-per-gas'],
99
- maxPriorityFeePerGas: flags['max-priority-fee-per-gas'],
100
- gasPrice: flags['gas-price'],
101
- };
102
- const { socketPath } = getDaemonPaths(this.config.dataDir);
103
- const timeoutMs = flags.timeout;
104
- // A `dryRun` resolves the sender and network client server-side without
105
- // broadcasting. `--dry-run` stops after previewing; an interactive run
106
- // previews first so the confirmation shows (and then pins) the resolved
107
- // sender/network; `--yes` skips straight to the broadcast.
108
- if (flags['dry-run']) {
109
- const preview = await __classPrivateFieldGet(this, _WalletSend_instances, "m", _WalletSend_dispatchSend).call(this, {
110
- socketPath,
111
- params: { ...params, dryRun: true },
112
- timeoutMs,
113
- struct: SendTransactionDryRunResultStruct,
114
- broadcast: false,
115
- });
116
- this.log(formatPlan(preview, flags.value, planExtras));
117
- return;
118
- }
119
- let resolved;
120
- if (!flags.yes) {
121
- const preview = await __classPrivateFieldGet(this, _WalletSend_instances, "m", _WalletSend_dispatchSend).call(this, {
122
- socketPath,
123
- params: { ...params, dryRun: true },
124
- timeoutMs,
125
- struct: SendTransactionDryRunResultStruct,
126
- broadcast: false,
127
- });
128
- let confirmed;
129
- try {
130
- confirmed = await confirmSend(formatPlan(preview, flags.value, planExtras));
131
- }
132
- catch (error) {
133
- // Ctrl+C at the prompt (@inquirer/core's ExitPromptError) is a clean
134
- // abort, not a failure; anything else should surface.
135
- if (error instanceof Error && error.name === 'ExitPromptError') {
136
- this.log('Aborted.');
137
- return;
138
- }
139
- throw error;
140
- }
141
- if (!confirmed) {
142
- this.log('Aborted.');
143
- return;
144
- }
145
- resolved = preview;
146
- }
147
- // Broadcast the exact sender/network the user reviewed (when they confirmed
148
- // a preview), so what is signed matches what was shown. `--yes` skips the
149
- // preview, so there it re-resolves server-side from `params`.
150
- const broadcastParams = resolved
151
- ? {
152
- ...baseParams,
153
- from: resolved.from,
154
- networkClientId: resolved.networkClientId,
155
- }
156
- : params;
157
- const result = await __classPrivateFieldGet(this, _WalletSend_instances, "m", _WalletSend_dispatchSend).call(this, {
158
- socketPath,
159
- params: broadcastParams,
160
- timeoutMs: timeoutMs ?? BROADCAST_TIMEOUT_MS,
161
- struct: SendTransactionBroadcastResultStruct,
162
- broadcast: true,
163
- });
164
- this.log('Transaction broadcast.');
165
- this.log(`Hash: ${result.transactionHash}`);
166
- this.log(`Id: ${result.transactionId}`);
167
- this.log(`Status: ${result.status}`);
168
- }
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());
202
- }
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.');
212
- }
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;
270
- /**
271
- * Whether an error is the daemon-client socket read timeout. It carries no
272
- * errno code, so its message is the only signal.
273
- *
274
- * @param error - The caught value.
275
- * @returns True if it is the read timeout.
276
- */
277
- function isReadTimeout(error) {
278
- return error instanceof Error && error.message === 'Socket read timed out';
279
- }
280
- /**
281
- * The message shown when the broadcast call times out. A send is not
282
- * idempotent, and the daemon may still be broadcasting after the client gives
283
- * up waiting, so this warns against a blind re-run rather than reading as a
284
- * plain connection failure.
285
- *
286
- * @returns The user-facing guidance.
287
- */
288
- function broadcastTimeoutMessage() {
289
- return ('The daemon did not respond in time, but your transaction may still be ' +
290
- 'broadcasting. Do NOT re-run this command — you could send it twice. ' +
291
- 'Check `mm daemon status`, the daemon log, or your account on-chain to ' +
292
- 'confirm, then use --timeout to wait longer if needed.');
293
- }
294
- /**
295
- * Format a dry-run plan for display (and as the confirmation prompt body).
296
- *
297
- * @param plan - The dry-run result returned by the daemon.
298
- * @param etherAmount - The original `--value` (ether), shown alongside the
299
- * resolved wei so the user sees the human amount they typed.
300
- * @param extras - The `--data` / gas overrides the daemon does not echo back,
301
- * shown so the user confirms exactly what will be sent.
302
- * @returns A multi-line summary of the transaction to be sent.
303
- */
304
- function formatPlan(plan, etherAmount, extras) {
305
- const lines = [
306
- 'About to send:',
307
- ` To: ${plan.to}`,
308
- ` From: ${plan.from}`,
309
- ` Value: ${etherAmount} ETH (${plan.value} wei)`,
310
- ` Network: ${plan.networkClientId}`,
311
- ];
312
- if (extras.data) {
313
- lines.push(` Data: ${extras.data}`);
314
- }
315
- const gasParts = [
316
- extras.gas ? `gas=${extras.gas}` : undefined,
317
- extras.maxFeePerGas ? `maxFeePerGas=${extras.maxFeePerGas}` : undefined,
318
- extras.maxPriorityFeePerGas
319
- ? `maxPriorityFeePerGas=${extras.maxPriorityFeePerGas}`
320
- : undefined,
321
- extras.gasPrice ? `gasPrice=${extras.gasPrice}` : undefined,
322
- ].filter((part) => part !== undefined);
323
- if (gasParts.length > 0) {
324
- lines.push(` Gas: ${gasParts.join(', ')}`);
325
- }
326
- return lines.join('\n');
327
- }
328
- //# sourceMappingURL=send.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"send.mjs","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,147 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.runSendTransaction = exports.SendTransactionBroadcastResultStruct = exports.SendTransactionDryRunResultStruct = exports.SendTransactionParamsStruct = void 0;
4
- const superstruct_1 = require("@metamask/superstruct");
5
- const utils_1 = require("@metamask/utils");
6
- /**
7
- * Origin recorded on daemon-initiated transactions. Mirrors
8
- * `ORIGIN_METAMASK` from `@metamask/controller-utils` (a single string
9
- * constant, inlined here to avoid pulling that whole package in as a
10
- * dependency for one value).
11
- */
12
- const INTERNAL_ORIGIN = 'metamask';
13
- /**
14
- * Struct for a `0x`-prefixed 20-byte hex address. `isValidHexAddress` accepts
15
- * an all-lowercase address or a valid EIP-55 checksummed one, so a plain
16
- * lowercase paste works while a mistyped mixed-case address is rejected.
17
- */
18
- const AddressStruct = (0, superstruct_1.define)('Address', (value) => typeof value === 'string' && (0, utils_1.isValidHexAddress)(value)
19
- ? true
20
- : 'Expected a 0x-prefixed 20-byte hex address');
21
- /**
22
- * Params struct for the `sendTransaction` RPC method.
23
- *
24
- * The transaction fields (`to`, `value`, `data`, gas overrides) are canonical
25
- * `0x`-prefixed hex — any unit conversion (e.g. ether → wei) is the CLI
26
- * command's job, so the daemon boundary stays unambiguous. Exactly one of
27
- * `networkClientId` / `chainId` selects the network client; the refinement
28
- * below rejects supplying both or neither. `dryRun` short-circuits before
29
- * broadcast (see {@link runSendTransaction}).
30
- */
31
- exports.SendTransactionParamsStruct = (0, superstruct_1.refine)((0, superstruct_1.object)({
32
- to: AddressStruct,
33
- from: (0, superstruct_1.optional)(AddressStruct),
34
- value: (0, superstruct_1.optional)(utils_1.StrictHexStruct),
35
- data: (0, superstruct_1.optional)(utils_1.StrictHexStruct),
36
- gas: (0, superstruct_1.optional)(utils_1.StrictHexStruct),
37
- maxFeePerGas: (0, superstruct_1.optional)(utils_1.StrictHexStruct),
38
- maxPriorityFeePerGas: (0, superstruct_1.optional)(utils_1.StrictHexStruct),
39
- gasPrice: (0, superstruct_1.optional)(utils_1.StrictHexStruct),
40
- networkClientId: (0, superstruct_1.optional)((0, superstruct_1.nonempty)((0, superstruct_1.string)())),
41
- chainId: (0, superstruct_1.optional)(utils_1.StrictHexStruct),
42
- dryRun: (0, superstruct_1.optional)((0, superstruct_1.boolean)()),
43
- }), 'SendTransactionParams', (value) => {
44
- if ((value.networkClientId === undefined) ===
45
- (value.chainId === undefined)) {
46
- return 'Exactly one of `networkClientId` or `chainId` must be provided';
47
- }
48
- // `gasPrice` (legacy) and the EIP-1559 fields are mutually exclusive:
49
- // `TransactionController` rejects the combination at broadcast, so reject
50
- // it here at the boundary instead — otherwise a dry-run and the
51
- // confirmation preview would show a plan that always fails at send.
52
- if (value.gasPrice !== undefined &&
53
- (value.maxFeePerGas !== undefined ||
54
- value.maxPriorityFeePerGas !== undefined)) {
55
- return '`gasPrice` cannot be combined with `maxFeePerGas` or `maxPriorityFeePerGas`';
56
- }
57
- return true;
58
- });
59
- /**
60
- * The resolved plan a `dryRun` returns: the network client and sender the
61
- * daemon would use, without adding or broadcasting anything. Exported as a
62
- * struct so the CLI can validate the payload it reads back over JSON-RPC
63
- * (which erases types on the wire) rather than trusting its shape.
64
- */
65
- exports.SendTransactionDryRunResultStruct = (0, superstruct_1.object)({
66
- dryRun: (0, superstruct_1.literal)(true),
67
- from: utils_1.StrictHexStruct,
68
- to: utils_1.StrictHexStruct,
69
- value: utils_1.StrictHexStruct,
70
- networkClientId: (0, superstruct_1.string)(),
71
- });
72
- /**
73
- * The outcome of a broadcast send: the on-chain hash plus the id/status the
74
- * daemon tracks the transaction under. Exported as a struct for the same
75
- * client-side validation reason as {@link SendTransactionDryRunResultStruct}.
76
- */
77
- exports.SendTransactionBroadcastResultStruct = (0, superstruct_1.object)({
78
- transactionHash: (0, superstruct_1.string)(),
79
- transactionId: (0, superstruct_1.string)(),
80
- status: (0, superstruct_1.string)(),
81
- });
82
- /**
83
- * Add and broadcast a transaction through the daemon-hosted
84
- * `TransactionController`, returning a serializable result.
85
- *
86
- * `TransactionController:addTransaction` returns `{ transactionMeta, result }`
87
- * where `result` is a `Promise<hash>` that resolves once the transaction is
88
- * signed and broadcast. That promise is not JSON-serializable, so it cannot
89
- * travel back over the daemon's JSON-RPC socket via the generic `call`
90
- * dispatch — hence this dedicated handler, which awaits the broadcast
91
- * server-side and returns only the resolved hash (and id/status).
92
- *
93
- * The network client is resolved from `chainId` (via `NetworkController`) when
94
- * `networkClientId` is not given directly, and `from` defaults to the selected
95
- * account. The transaction is submitted as `isInternal` (the daemon is driven
96
- * only by its owner over the `0600` same-user socket), which skips
97
- * origin/permitted-account validation; its approval request is auto-accepted
98
- * by the daemon's auto-approval subscription.
99
- *
100
- * When `dryRun` is set, the network client and sender are resolved and the
101
- * params validated, but nothing is added or broadcast — the resolved plan is
102
- * returned so the CLI can preview it before the user confirms.
103
- *
104
- * @param messenger - The wallet root messenger.
105
- * @param params - Validated `sendTransaction` params.
106
- * @returns The dry-run plan, or the broadcast hash with its id and status.
107
- */
108
- async function runSendTransaction(messenger, params) {
109
- const { to, value = '0x0', data, gas, maxFeePerGas, maxPriorityFeePerGas, gasPrice, networkClientId: networkClientIdParam, chainId, dryRun, } = params;
110
- // The struct guarantees exactly one of `networkClientId` / `chainId`, so
111
- // `chainId` is defined whenever `networkClientId` is not.
112
- const networkClientId = networkClientIdParam ??
113
- messenger.call('NetworkController:findNetworkClientIdByChainId', chainId);
114
- const from = params.from ??
115
- messenger.call('AccountsController:getSelectedAccount').address;
116
- if (dryRun) {
117
- return { dryRun: true, from, to, value, networkClientId };
118
- }
119
- const txParams = {
120
- from,
121
- to,
122
- value,
123
- ...(data === undefined ? {} : { data }),
124
- ...(gas === undefined ? {} : { gas }),
125
- ...(maxFeePerGas === undefined ? {} : { maxFeePerGas }),
126
- ...(maxPriorityFeePerGas === undefined ? {} : { maxPriorityFeePerGas }),
127
- ...(gasPrice === undefined ? {} : { gasPrice }),
128
- };
129
- const { result, transactionMeta } = await messenger.call('TransactionController:addTransaction', txParams, { networkClientId, origin: INTERNAL_ORIGIN, isInternal: true });
130
- // `result` resolves only once the transaction is signed and broadcast (see
131
- // the function JSDoc); awaiting it here is what this handler exists for.
132
- const transactionHash = await result;
133
- // Re-read the live record for the current status: `transactionMeta` is the
134
- // creation snapshot (still `unapproved`). If the record is already gone,
135
- // fall back to `submitted` — reaching this point means `result` resolved, so
136
- // the transaction was broadcast, never merely `unapproved`.
137
- const [current] = messenger.call('TransactionController:getTransactions', {
138
- searchCriteria: { id: transactionMeta.id },
139
- });
140
- return {
141
- transactionHash,
142
- transactionId: transactionMeta.id,
143
- status: current?.status ?? 'submitted',
144
- };
145
- }
146
- exports.runSendTransaction = runSendTransaction;
147
- //# sourceMappingURL=send-transaction.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"send-transaction.cjs","sourceRoot":"","sources":["../../src/daemon/send-transaction.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n boolean,\n define,\n literal,\n nonempty,\n object,\n optional,\n refine,\n string,\n} from '@metamask/superstruct';\nimport type { Infer } from '@metamask/superstruct';\nimport { isValidHexAddress, StrictHexStruct } from '@metamask/utils';\nimport type { Hex } from '@metamask/utils';\nimport type {\n DefaultActions,\n DefaultEvents,\n RootMessenger,\n} from '@metamask/wallet';\n\n/**\n * Origin recorded on daemon-initiated transactions. Mirrors\n * `ORIGIN_METAMASK` from `@metamask/controller-utils` (a single string\n * constant, inlined here to avoid pulling that whole package in as a\n * dependency for one value).\n */\nconst INTERNAL_ORIGIN = 'metamask';\n\n/**\n * Struct for a `0x`-prefixed 20-byte hex address. `isValidHexAddress` accepts\n * an all-lowercase address or a valid EIP-55 checksummed one, so a plain\n * lowercase paste works while a mistyped mixed-case address is rejected.\n */\nconst AddressStruct = define<Hex>('Address', (value) =>\n typeof value === 'string' && isValidHexAddress(value as Hex)\n ? true\n : 'Expected a 0x-prefixed 20-byte hex address',\n);\n\n/**\n * Params struct for the `sendTransaction` RPC method.\n *\n * The transaction fields (`to`, `value`, `data`, gas overrides) are canonical\n * `0x`-prefixed hex — any unit conversion (e.g. ether → wei) is the CLI\n * command's job, so the daemon boundary stays unambiguous. Exactly one of\n * `networkClientId` / `chainId` selects the network client; the refinement\n * below rejects supplying both or neither. `dryRun` short-circuits before\n * broadcast (see {@link runSendTransaction}).\n */\nexport const SendTransactionParamsStruct = refine(\n object({\n to: AddressStruct,\n from: optional(AddressStruct),\n value: optional(StrictHexStruct),\n data: optional(StrictHexStruct),\n gas: optional(StrictHexStruct),\n maxFeePerGas: optional(StrictHexStruct),\n maxPriorityFeePerGas: optional(StrictHexStruct),\n gasPrice: optional(StrictHexStruct),\n networkClientId: optional(nonempty(string())),\n chainId: optional(StrictHexStruct),\n dryRun: optional(boolean()),\n }),\n 'SendTransactionParams',\n (value) => {\n if (\n (value.networkClientId === undefined) ===\n (value.chainId === undefined)\n ) {\n return 'Exactly one of `networkClientId` or `chainId` must be provided';\n }\n // `gasPrice` (legacy) and the EIP-1559 fields are mutually exclusive:\n // `TransactionController` rejects the combination at broadcast, so reject\n // it here at the boundary instead — otherwise a dry-run and the\n // confirmation preview would show a plan that always fails at send.\n if (\n value.gasPrice !== undefined &&\n (value.maxFeePerGas !== undefined ||\n value.maxPriorityFeePerGas !== undefined)\n ) {\n return '`gasPrice` cannot be combined with `maxFeePerGas` or `maxPriorityFeePerGas`';\n }\n return true;\n },\n);\n\nexport type SendTransactionParams = Infer<typeof SendTransactionParamsStruct>;\n\n/**\n * The resolved plan a `dryRun` returns: the network client and sender the\n * daemon would use, without adding or broadcasting anything. Exported as a\n * struct so the CLI can validate the payload it reads back over JSON-RPC\n * (which erases types on the wire) rather than trusting its shape.\n */\nexport const SendTransactionDryRunResultStruct = object({\n dryRun: literal(true),\n from: StrictHexStruct,\n to: StrictHexStruct,\n value: StrictHexStruct,\n networkClientId: string(),\n});\n\n/**\n * The outcome of a broadcast send: the on-chain hash plus the id/status the\n * daemon tracks the transaction under. Exported as a struct for the same\n * client-side validation reason as {@link SendTransactionDryRunResultStruct}.\n */\nexport const SendTransactionBroadcastResultStruct = object({\n transactionHash: string(),\n transactionId: string(),\n status: string(),\n});\n\nexport type SendTransactionDryRunResult = Infer<\n typeof SendTransactionDryRunResultStruct\n>;\n\nexport type SendTransactionBroadcastResult = Infer<\n typeof SendTransactionBroadcastResultStruct\n>;\n\nexport type SendTransactionResult =\n | SendTransactionDryRunResult\n | SendTransactionBroadcastResult;\n\n/**\n * Add and broadcast a transaction through the daemon-hosted\n * `TransactionController`, returning a serializable result.\n *\n * `TransactionController:addTransaction` returns `{ transactionMeta, result }`\n * where `result` is a `Promise<hash>` that resolves once the transaction is\n * signed and broadcast. That promise is not JSON-serializable, so it cannot\n * travel back over the daemon's JSON-RPC socket via the generic `call`\n * dispatch — hence this dedicated handler, which awaits the broadcast\n * server-side and returns only the resolved hash (and id/status).\n *\n * The network client is resolved from `chainId` (via `NetworkController`) when\n * `networkClientId` is not given directly, and `from` defaults to the selected\n * account. The transaction is submitted as `isInternal` (the daemon is driven\n * only by its owner over the `0600` same-user socket), which skips\n * origin/permitted-account validation; its approval request is auto-accepted\n * by the daemon's auto-approval subscription.\n *\n * When `dryRun` is set, the network client and sender are resolved and the\n * params validated, but nothing is added or broadcast — the resolved plan is\n * returned so the CLI can preview it before the user confirms.\n *\n * @param messenger - The wallet root messenger.\n * @param params - Validated `sendTransaction` params.\n * @returns The dry-run plan, or the broadcast hash with its id and status.\n */\nexport async function runSendTransaction(\n messenger: Readonly<RootMessenger<DefaultActions, DefaultEvents>>,\n params: SendTransactionParams,\n): Promise<SendTransactionResult> {\n const {\n to,\n value = '0x0',\n data,\n gas,\n maxFeePerGas,\n maxPriorityFeePerGas,\n gasPrice,\n networkClientId: networkClientIdParam,\n chainId,\n dryRun,\n } = params;\n\n // The struct guarantees exactly one of `networkClientId` / `chainId`, so\n // `chainId` is defined whenever `networkClientId` is not.\n const networkClientId =\n networkClientIdParam ??\n messenger.call(\n 'NetworkController:findNetworkClientIdByChainId',\n chainId as Hex,\n );\n\n const from =\n params.from ??\n (messenger.call('AccountsController:getSelectedAccount').address as Hex);\n\n if (dryRun) {\n return { dryRun: true, from, to, value, networkClientId };\n }\n\n const txParams = {\n from,\n to,\n value,\n ...(data === undefined ? {} : { data }),\n ...(gas === undefined ? {} : { gas }),\n ...(maxFeePerGas === undefined ? {} : { maxFeePerGas }),\n ...(maxPriorityFeePerGas === undefined ? {} : { maxPriorityFeePerGas }),\n ...(gasPrice === undefined ? {} : { gasPrice }),\n };\n\n const { result, transactionMeta } = await messenger.call(\n 'TransactionController:addTransaction',\n txParams,\n { networkClientId, origin: INTERNAL_ORIGIN, isInternal: true },\n );\n\n // `result` resolves only once the transaction is signed and broadcast (see\n // the function JSDoc); awaiting it here is what this handler exists for.\n const transactionHash = await result;\n\n // Re-read the live record for the current status: `transactionMeta` is the\n // creation snapshot (still `unapproved`). If the record is already gone,\n // fall back to `submitted` — reaching this point means `result` resolved, so\n // the transaction was broadcast, never merely `unapproved`.\n const [current] = messenger.call('TransactionController:getTransactions', {\n searchCriteria: { id: transactionMeta.id },\n });\n\n return {\n transactionHash,\n transactionId: transactionMeta.id,\n status: current?.status ?? 'submitted',\n };\n}\n"]}
@@ -1,102 +0,0 @@
1
- import type { Infer } from "@metamask/superstruct";
2
- import type { DefaultActions, DefaultEvents, RootMessenger } from "@metamask/wallet";
3
- /**
4
- * Params struct for the `sendTransaction` RPC method.
5
- *
6
- * The transaction fields (`to`, `value`, `data`, gas overrides) are canonical
7
- * `0x`-prefixed hex — any unit conversion (e.g. ether → wei) is the CLI
8
- * command's job, so the daemon boundary stays unambiguous. Exactly one of
9
- * `networkClientId` / `chainId` selects the network client; the refinement
10
- * below rejects supplying both or neither. `dryRun` short-circuits before
11
- * broadcast (see {@link runSendTransaction}).
12
- */
13
- export declare const SendTransactionParamsStruct: import("@metamask/superstruct").Struct<{
14
- to: `0x${string}`;
15
- data?: `0x${string}` | undefined;
16
- value?: `0x${string}` | undefined;
17
- from?: `0x${string}` | undefined;
18
- gas?: `0x${string}` | undefined;
19
- maxFeePerGas?: `0x${string}` | undefined;
20
- maxPriorityFeePerGas?: `0x${string}` | undefined;
21
- gasPrice?: `0x${string}` | undefined;
22
- networkClientId?: string | undefined;
23
- chainId?: `0x${string}` | undefined;
24
- dryRun?: boolean | undefined;
25
- }, {
26
- to: import("@metamask/superstruct").Struct<`0x${string}`, null>;
27
- from: import("@metamask/superstruct").Struct<`0x${string}` | undefined, null>;
28
- value: import("@metamask/superstruct").Struct<`0x${string}` | undefined, null>;
29
- data: import("@metamask/superstruct").Struct<`0x${string}` | undefined, null>;
30
- gas: import("@metamask/superstruct").Struct<`0x${string}` | undefined, null>;
31
- maxFeePerGas: import("@metamask/superstruct").Struct<`0x${string}` | undefined, null>;
32
- maxPriorityFeePerGas: import("@metamask/superstruct").Struct<`0x${string}` | undefined, null>;
33
- gasPrice: import("@metamask/superstruct").Struct<`0x${string}` | undefined, null>;
34
- networkClientId: import("@metamask/superstruct").Struct<string | undefined, null>;
35
- chainId: import("@metamask/superstruct").Struct<`0x${string}` | undefined, null>;
36
- dryRun: import("@metamask/superstruct").Struct<boolean | undefined, null>;
37
- }>;
38
- export type SendTransactionParams = Infer<typeof SendTransactionParamsStruct>;
39
- /**
40
- * The resolved plan a `dryRun` returns: the network client and sender the
41
- * daemon would use, without adding or broadcasting anything. Exported as a
42
- * struct so the CLI can validate the payload it reads back over JSON-RPC
43
- * (which erases types on the wire) rather than trusting its shape.
44
- */
45
- export declare const SendTransactionDryRunResultStruct: import("@metamask/superstruct").Struct<{
46
- value: `0x${string}`;
47
- to: `0x${string}`;
48
- from: `0x${string}`;
49
- networkClientId: string;
50
- dryRun: true;
51
- }, {
52
- dryRun: import("@metamask/superstruct").Struct<true, true>;
53
- from: import("@metamask/superstruct").Struct<`0x${string}`, null>;
54
- to: import("@metamask/superstruct").Struct<`0x${string}`, null>;
55
- value: import("@metamask/superstruct").Struct<`0x${string}`, null>;
56
- networkClientId: import("@metamask/superstruct").Struct<string, null>;
57
- }>;
58
- /**
59
- * The outcome of a broadcast send: the on-chain hash plus the id/status the
60
- * daemon tracks the transaction under. Exported as a struct for the same
61
- * client-side validation reason as {@link SendTransactionDryRunResultStruct}.
62
- */
63
- export declare const SendTransactionBroadcastResultStruct: import("@metamask/superstruct").Struct<{
64
- status: string;
65
- transactionHash: string;
66
- transactionId: string;
67
- }, {
68
- transactionHash: import("@metamask/superstruct").Struct<string, null>;
69
- transactionId: import("@metamask/superstruct").Struct<string, null>;
70
- status: import("@metamask/superstruct").Struct<string, null>;
71
- }>;
72
- export type SendTransactionDryRunResult = Infer<typeof SendTransactionDryRunResultStruct>;
73
- export type SendTransactionBroadcastResult = Infer<typeof SendTransactionBroadcastResultStruct>;
74
- export type SendTransactionResult = SendTransactionDryRunResult | SendTransactionBroadcastResult;
75
- /**
76
- * Add and broadcast a transaction through the daemon-hosted
77
- * `TransactionController`, returning a serializable result.
78
- *
79
- * `TransactionController:addTransaction` returns `{ transactionMeta, result }`
80
- * where `result` is a `Promise<hash>` that resolves once the transaction is
81
- * signed and broadcast. That promise is not JSON-serializable, so it cannot
82
- * travel back over the daemon's JSON-RPC socket via the generic `call`
83
- * dispatch — hence this dedicated handler, which awaits the broadcast
84
- * server-side and returns only the resolved hash (and id/status).
85
- *
86
- * The network client is resolved from `chainId` (via `NetworkController`) when
87
- * `networkClientId` is not given directly, and `from` defaults to the selected
88
- * account. The transaction is submitted as `isInternal` (the daemon is driven
89
- * only by its owner over the `0600` same-user socket), which skips
90
- * origin/permitted-account validation; its approval request is auto-accepted
91
- * by the daemon's auto-approval subscription.
92
- *
93
- * When `dryRun` is set, the network client and sender are resolved and the
94
- * params validated, but nothing is added or broadcast — the resolved plan is
95
- * returned so the CLI can preview it before the user confirms.
96
- *
97
- * @param messenger - The wallet root messenger.
98
- * @param params - Validated `sendTransaction` params.
99
- * @returns The dry-run plan, or the broadcast hash with its id and status.
100
- */
101
- export declare function runSendTransaction(messenger: Readonly<RootMessenger<DefaultActions, DefaultEvents>>, params: SendTransactionParams): Promise<SendTransactionResult>;
102
- //# sourceMappingURL=send-transaction.d.cts.map