@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.
- package/CHANGELOG.md +0 -3
- package/README.md +1 -11
- package/dist/daemon/daemon-entry.cjs +0 -4
- package/dist/daemon/daemon-entry.cjs.map +1 -1
- package/dist/daemon/daemon-entry.mjs +0 -4
- package/dist/daemon/daemon-entry.mjs.map +1 -1
- package/dist/daemon/prompts.cjs +1 -19
- package/dist/daemon/prompts.cjs.map +1 -1
- package/dist/daemon/prompts.d.cts +0 -11
- package/dist/daemon/prompts.d.cts.map +1 -1
- package/dist/daemon/prompts.d.mts +0 -11
- package/dist/daemon/prompts.d.mts.map +1 -1
- package/dist/daemon/prompts.mjs +0 -17
- package/dist/daemon/prompts.mjs.map +1 -1
- package/package.json +1 -4
- package/dist/commands/wallet/send.cjs +0 -332
- package/dist/commands/wallet/send.cjs.map +0 -1
- package/dist/commands/wallet/send.d.cts +0 -42
- package/dist/commands/wallet/send.d.cts.map +0 -1
- package/dist/commands/wallet/send.d.mts +0 -42
- package/dist/commands/wallet/send.d.mts.map +0 -1
- package/dist/commands/wallet/send.mjs +0 -328
- package/dist/commands/wallet/send.mjs.map +0 -1
- package/dist/daemon/send-transaction.cjs +0 -147
- package/dist/daemon/send-transaction.cjs.map +0 -1
- package/dist/daemon/send-transaction.d.cts +0 -102
- package/dist/daemon/send-transaction.d.cts.map +0 -1
- package/dist/daemon/send-transaction.d.mts +0 -102
- package/dist/daemon/send-transaction.d.mts.map +0 -1
- package/dist/daemon/send-transaction.mjs +0 -143
- package/dist/daemon/send-transaction.mjs.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"send-transaction.d.cts","sourceRoot":"","sources":["../../src/daemon/send-transaction.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,KAAK,EAAE,8BAA8B;AAGnD,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EACb,aAAa,EACd,yBAAyB;AAqB1B;;;;;;;;;GASG;AACH,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;EAmCvC,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAE9E;;;;;GAKG;AACH,eAAO,MAAM,iCAAiC;;;;;;;;;;;;EAM5C,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,oCAAoC;;;;;;;;EAI/C,CAAC;AAEH,MAAM,MAAM,2BAA2B,GAAG,KAAK,CAC7C,OAAO,iCAAiC,CACzC,CAAC;AAEF,MAAM,MAAM,8BAA8B,GAAG,KAAK,CAChD,OAAO,oCAAoC,CAC5C,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAC7B,2BAA2B,GAC3B,8BAA8B,CAAC;AAEnC;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,QAAQ,CAAC,aAAa,CAAC,cAAc,EAAE,aAAa,CAAC,CAAC,EACjE,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,qBAAqB,CAAC,CAiEhC"}
|
|
@@ -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.mts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"send-transaction.d.mts","sourceRoot":"","sources":["../../src/daemon/send-transaction.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,KAAK,EAAE,8BAA8B;AAGnD,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EACb,aAAa,EACd,yBAAyB;AAqB1B;;;;;;;;;GASG;AACH,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;EAmCvC,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAE9E;;;;;GAKG;AACH,eAAO,MAAM,iCAAiC;;;;;;;;;;;;EAM5C,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,oCAAoC;;;;;;;;EAI/C,CAAC;AAEH,MAAM,MAAM,2BAA2B,GAAG,KAAK,CAC7C,OAAO,iCAAiC,CACzC,CAAC;AAEF,MAAM,MAAM,8BAA8B,GAAG,KAAK,CAChD,OAAO,oCAAoC,CAC5C,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAC7B,2BAA2B,GAC3B,8BAA8B,CAAC;AAEnC;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,QAAQ,CAAC,aAAa,CAAC,cAAc,EAAE,aAAa,CAAC,CAAC,EACjE,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,qBAAqB,CAAC,CAiEhC"}
|
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
import { boolean, define, literal, nonempty, object, optional, refine, string } from "@metamask/superstruct";
|
|
2
|
-
import { isValidHexAddress, StrictHexStruct } from "@metamask/utils";
|
|
3
|
-
/**
|
|
4
|
-
* Origin recorded on daemon-initiated transactions. Mirrors
|
|
5
|
-
* `ORIGIN_METAMASK` from `@metamask/controller-utils` (a single string
|
|
6
|
-
* constant, inlined here to avoid pulling that whole package in as a
|
|
7
|
-
* dependency for one value).
|
|
8
|
-
*/
|
|
9
|
-
const INTERNAL_ORIGIN = 'metamask';
|
|
10
|
-
/**
|
|
11
|
-
* Struct for a `0x`-prefixed 20-byte hex address. `isValidHexAddress` accepts
|
|
12
|
-
* an all-lowercase address or a valid EIP-55 checksummed one, so a plain
|
|
13
|
-
* lowercase paste works while a mistyped mixed-case address is rejected.
|
|
14
|
-
*/
|
|
15
|
-
const AddressStruct = define('Address', (value) => typeof value === 'string' && isValidHexAddress(value)
|
|
16
|
-
? true
|
|
17
|
-
: 'Expected a 0x-prefixed 20-byte hex address');
|
|
18
|
-
/**
|
|
19
|
-
* Params struct for the `sendTransaction` RPC method.
|
|
20
|
-
*
|
|
21
|
-
* The transaction fields (`to`, `value`, `data`, gas overrides) are canonical
|
|
22
|
-
* `0x`-prefixed hex — any unit conversion (e.g. ether → wei) is the CLI
|
|
23
|
-
* command's job, so the daemon boundary stays unambiguous. Exactly one of
|
|
24
|
-
* `networkClientId` / `chainId` selects the network client; the refinement
|
|
25
|
-
* below rejects supplying both or neither. `dryRun` short-circuits before
|
|
26
|
-
* broadcast (see {@link runSendTransaction}).
|
|
27
|
-
*/
|
|
28
|
-
export const SendTransactionParamsStruct = refine(object({
|
|
29
|
-
to: AddressStruct,
|
|
30
|
-
from: optional(AddressStruct),
|
|
31
|
-
value: optional(StrictHexStruct),
|
|
32
|
-
data: optional(StrictHexStruct),
|
|
33
|
-
gas: optional(StrictHexStruct),
|
|
34
|
-
maxFeePerGas: optional(StrictHexStruct),
|
|
35
|
-
maxPriorityFeePerGas: optional(StrictHexStruct),
|
|
36
|
-
gasPrice: optional(StrictHexStruct),
|
|
37
|
-
networkClientId: optional(nonempty(string())),
|
|
38
|
-
chainId: optional(StrictHexStruct),
|
|
39
|
-
dryRun: optional(boolean()),
|
|
40
|
-
}), 'SendTransactionParams', (value) => {
|
|
41
|
-
if ((value.networkClientId === undefined) ===
|
|
42
|
-
(value.chainId === undefined)) {
|
|
43
|
-
return 'Exactly one of `networkClientId` or `chainId` must be provided';
|
|
44
|
-
}
|
|
45
|
-
// `gasPrice` (legacy) and the EIP-1559 fields are mutually exclusive:
|
|
46
|
-
// `TransactionController` rejects the combination at broadcast, so reject
|
|
47
|
-
// it here at the boundary instead — otherwise a dry-run and the
|
|
48
|
-
// confirmation preview would show a plan that always fails at send.
|
|
49
|
-
if (value.gasPrice !== undefined &&
|
|
50
|
-
(value.maxFeePerGas !== undefined ||
|
|
51
|
-
value.maxPriorityFeePerGas !== undefined)) {
|
|
52
|
-
return '`gasPrice` cannot be combined with `maxFeePerGas` or `maxPriorityFeePerGas`';
|
|
53
|
-
}
|
|
54
|
-
return true;
|
|
55
|
-
});
|
|
56
|
-
/**
|
|
57
|
-
* The resolved plan a `dryRun` returns: the network client and sender the
|
|
58
|
-
* daemon would use, without adding or broadcasting anything. Exported as a
|
|
59
|
-
* struct so the CLI can validate the payload it reads back over JSON-RPC
|
|
60
|
-
* (which erases types on the wire) rather than trusting its shape.
|
|
61
|
-
*/
|
|
62
|
-
export const SendTransactionDryRunResultStruct = object({
|
|
63
|
-
dryRun: literal(true),
|
|
64
|
-
from: StrictHexStruct,
|
|
65
|
-
to: StrictHexStruct,
|
|
66
|
-
value: StrictHexStruct,
|
|
67
|
-
networkClientId: string(),
|
|
68
|
-
});
|
|
69
|
-
/**
|
|
70
|
-
* The outcome of a broadcast send: the on-chain hash plus the id/status the
|
|
71
|
-
* daemon tracks the transaction under. Exported as a struct for the same
|
|
72
|
-
* client-side validation reason as {@link SendTransactionDryRunResultStruct}.
|
|
73
|
-
*/
|
|
74
|
-
export const SendTransactionBroadcastResultStruct = object({
|
|
75
|
-
transactionHash: string(),
|
|
76
|
-
transactionId: string(),
|
|
77
|
-
status: string(),
|
|
78
|
-
});
|
|
79
|
-
/**
|
|
80
|
-
* Add and broadcast a transaction through the daemon-hosted
|
|
81
|
-
* `TransactionController`, returning a serializable result.
|
|
82
|
-
*
|
|
83
|
-
* `TransactionController:addTransaction` returns `{ transactionMeta, result }`
|
|
84
|
-
* where `result` is a `Promise<hash>` that resolves once the transaction is
|
|
85
|
-
* signed and broadcast. That promise is not JSON-serializable, so it cannot
|
|
86
|
-
* travel back over the daemon's JSON-RPC socket via the generic `call`
|
|
87
|
-
* dispatch — hence this dedicated handler, which awaits the broadcast
|
|
88
|
-
* server-side and returns only the resolved hash (and id/status).
|
|
89
|
-
*
|
|
90
|
-
* The network client is resolved from `chainId` (via `NetworkController`) when
|
|
91
|
-
* `networkClientId` is not given directly, and `from` defaults to the selected
|
|
92
|
-
* account. The transaction is submitted as `isInternal` (the daemon is driven
|
|
93
|
-
* only by its owner over the `0600` same-user socket), which skips
|
|
94
|
-
* origin/permitted-account validation; its approval request is auto-accepted
|
|
95
|
-
* by the daemon's auto-approval subscription.
|
|
96
|
-
*
|
|
97
|
-
* When `dryRun` is set, the network client and sender are resolved and the
|
|
98
|
-
* params validated, but nothing is added or broadcast — the resolved plan is
|
|
99
|
-
* returned so the CLI can preview it before the user confirms.
|
|
100
|
-
*
|
|
101
|
-
* @param messenger - The wallet root messenger.
|
|
102
|
-
* @param params - Validated `sendTransaction` params.
|
|
103
|
-
* @returns The dry-run plan, or the broadcast hash with its id and status.
|
|
104
|
-
*/
|
|
105
|
-
export async function runSendTransaction(messenger, params) {
|
|
106
|
-
const { to, value = '0x0', data, gas, maxFeePerGas, maxPriorityFeePerGas, gasPrice, networkClientId: networkClientIdParam, chainId, dryRun, } = params;
|
|
107
|
-
// The struct guarantees exactly one of `networkClientId` / `chainId`, so
|
|
108
|
-
// `chainId` is defined whenever `networkClientId` is not.
|
|
109
|
-
const networkClientId = networkClientIdParam ??
|
|
110
|
-
messenger.call('NetworkController:findNetworkClientIdByChainId', chainId);
|
|
111
|
-
const from = params.from ??
|
|
112
|
-
messenger.call('AccountsController:getSelectedAccount').address;
|
|
113
|
-
if (dryRun) {
|
|
114
|
-
return { dryRun: true, from, to, value, networkClientId };
|
|
115
|
-
}
|
|
116
|
-
const txParams = {
|
|
117
|
-
from,
|
|
118
|
-
to,
|
|
119
|
-
value,
|
|
120
|
-
...(data === undefined ? {} : { data }),
|
|
121
|
-
...(gas === undefined ? {} : { gas }),
|
|
122
|
-
...(maxFeePerGas === undefined ? {} : { maxFeePerGas }),
|
|
123
|
-
...(maxPriorityFeePerGas === undefined ? {} : { maxPriorityFeePerGas }),
|
|
124
|
-
...(gasPrice === undefined ? {} : { gasPrice }),
|
|
125
|
-
};
|
|
126
|
-
const { result, transactionMeta } = await messenger.call('TransactionController:addTransaction', txParams, { networkClientId, origin: INTERNAL_ORIGIN, isInternal: true });
|
|
127
|
-
// `result` resolves only once the transaction is signed and broadcast (see
|
|
128
|
-
// the function JSDoc); awaiting it here is what this handler exists for.
|
|
129
|
-
const transactionHash = await result;
|
|
130
|
-
// Re-read the live record for the current status: `transactionMeta` is the
|
|
131
|
-
// creation snapshot (still `unapproved`). If the record is already gone,
|
|
132
|
-
// fall back to `submitted` — reaching this point means `result` resolved, so
|
|
133
|
-
// the transaction was broadcast, never merely `unapproved`.
|
|
134
|
-
const [current] = messenger.call('TransactionController:getTransactions', {
|
|
135
|
-
searchCriteria: { id: transactionMeta.id },
|
|
136
|
-
});
|
|
137
|
-
return {
|
|
138
|
-
transactionHash,
|
|
139
|
-
transactionId: transactionMeta.id,
|
|
140
|
-
status: current?.status ?? 'submitted',
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
//# sourceMappingURL=send-transaction.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"send-transaction.mjs","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"]}
|