@metamask-previews/wallet-cli 0.0.0-preview-8bfa290fb → 0.0.0-preview-e8a256c39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -4
- package/dist/commands/daemon/{call.d.mts → call.d.ts} +2 -2
- package/dist/commands/daemon/call.d.ts.map +1 -0
- package/dist/commands/daemon/{call.mjs → call.js} +30 -31
- package/dist/commands/daemon/call.js.map +1 -0
- package/dist/commands/daemon/{list.d.cts → list.d.ts} +2 -2
- package/dist/commands/daemon/list.d.ts.map +1 -0
- package/dist/commands/daemon/{list.mjs → list.js} +9 -10
- package/dist/commands/daemon/list.js.map +1 -0
- package/dist/commands/daemon/{purge.d.cts → purge.d.ts} +2 -2
- package/dist/commands/daemon/purge.d.ts.map +1 -0
- package/dist/commands/daemon/{purge.mjs → purge.js} +19 -20
- package/dist/commands/daemon/purge.js.map +1 -0
- package/dist/commands/daemon/{start.d.cts → start.d.ts} +2 -2
- package/dist/commands/daemon/start.d.ts.map +1 -0
- package/dist/commands/daemon/start.js +49 -0
- package/dist/commands/daemon/{start.cjs.map → start.js.map} +1 -1
- package/dist/commands/daemon/{status.d.cts → status.d.ts} +2 -2
- package/dist/commands/daemon/status.d.ts.map +1 -0
- package/dist/commands/daemon/{status.mjs → status.js} +10 -11
- package/dist/commands/daemon/status.js.map +1 -0
- package/dist/commands/daemon/{stop.d.cts → stop.d.ts} +2 -2
- package/dist/commands/daemon/stop.d.ts.map +1 -0
- package/dist/commands/daemon/{stop.mjs → stop.js} +9 -10
- package/dist/commands/daemon/stop.js.map +1 -0
- package/dist/commands/wallet/{send.d.cts → send.d.ts} +3 -3
- package/dist/commands/wallet/send.d.ts.map +1 -0
- package/dist/commands/wallet/{send.mjs → send.js} +111 -123
- package/dist/commands/wallet/send.js.map +1 -0
- package/dist/commands/wallet/{unlock.d.cts → unlock.d.ts} +2 -2
- package/dist/commands/wallet/unlock.d.ts.map +1 -0
- package/dist/commands/wallet/{unlock.mjs → unlock.js} +29 -30
- package/dist/commands/wallet/unlock.js.map +1 -0
- package/dist/daemon/{auto-approval.d.mts → auto-approval.d.ts} +3 -3
- package/dist/daemon/auto-approval.d.ts.map +1 -0
- package/dist/daemon/{auto-approval.mjs → auto-approval.js} +1 -1
- package/dist/daemon/auto-approval.js.map +1 -0
- package/dist/daemon/{daemon-client.d.mts → daemon-client.d.ts} +2 -2
- package/dist/daemon/daemon-client.d.ts.map +1 -0
- package/dist/daemon/{daemon-client.mjs → daemon-client.js} +8 -8
- package/dist/daemon/daemon-client.js.map +1 -0
- package/dist/daemon/daemon-entry.d.ts +2 -0
- package/dist/daemon/daemon-entry.d.ts.map +1 -0
- package/dist/daemon/{daemon-entry.mjs → daemon-entry.js} +12 -12
- package/dist/daemon/daemon-entry.js.map +1 -0
- package/dist/daemon/{daemon-spawn.d.mts → daemon-spawn.d.ts} +2 -2
- package/dist/daemon/daemon-spawn.d.ts.map +1 -0
- package/dist/daemon/{daemon-spawn.mjs → daemon-spawn.js} +7 -7
- package/dist/daemon/daemon-spawn.js.map +1 -0
- package/dist/daemon/{data-dir.d.cts → data-dir.d.ts} +1 -1
- package/dist/daemon/data-dir.d.ts.map +1 -0
- package/dist/daemon/{data-dir.mjs → data-dir.js} +3 -3
- package/dist/daemon/data-dir.js.map +1 -0
- package/dist/daemon/{paths.d.mts → paths.d.ts} +2 -2
- package/dist/daemon/paths.d.ts.map +1 -0
- package/dist/daemon/{paths.mjs → paths.js} +2 -2
- package/dist/daemon/paths.js.map +1 -0
- package/dist/daemon/{prompts.d.cts → prompts.d.ts} +1 -1
- package/dist/daemon/prompts.d.ts.map +1 -0
- package/dist/daemon/{prompts.mjs → prompts.js} +4 -4
- package/dist/daemon/prompts.js.map +1 -0
- package/dist/daemon/{rpc-socket-server.d.cts → rpc-socket-server.d.ts} +2 -2
- package/dist/daemon/rpc-socket-server.d.ts.map +1 -0
- package/dist/daemon/{rpc-socket-server.mjs → rpc-socket-server.js} +8 -8
- package/dist/daemon/rpc-socket-server.js.map +1 -0
- package/dist/daemon/{secrets.d.cts → secrets.d.ts} +1 -1
- package/dist/daemon/secrets.d.ts.map +1 -0
- package/dist/daemon/{secrets.mjs → secrets.js} +11 -23
- package/dist/daemon/secrets.js.map +1 -0
- package/dist/daemon/{send-transaction.d.cts → send-transaction.d.ts} +9 -9
- package/dist/daemon/send-transaction.d.ts.map +1 -0
- package/dist/daemon/{send-transaction.mjs → send-transaction.js} +3 -3
- package/dist/daemon/send-transaction.js.map +1 -0
- package/dist/daemon/{socket-line.d.cts → socket-line.d.ts} +2 -5
- package/dist/daemon/socket-line.d.ts.map +1 -0
- package/dist/daemon/{socket-line.mjs → socket-line.js} +1 -1
- package/dist/daemon/socket-line.js.map +1 -0
- package/dist/daemon/{stop-daemon.d.cts → stop-daemon.d.ts} +1 -1
- package/dist/daemon/stop-daemon.d.ts.map +1 -0
- package/dist/daemon/{stop-daemon.mjs → stop-daemon.js} +7 -7
- package/dist/daemon/stop-daemon.js.map +1 -0
- package/dist/daemon/{types.d.cts → types.d.ts} +4 -4
- package/dist/daemon/types.d.ts.map +1 -0
- package/dist/daemon/{types.mjs → types.js} +1 -1
- package/dist/daemon/types.js.map +1 -0
- package/dist/daemon/{utils.d.cts → utils.d.ts} +2 -3
- package/dist/daemon/utils.d.ts.map +1 -0
- package/dist/daemon/{utils.mjs → utils.js} +3 -3
- package/dist/daemon/utils.js.map +1 -0
- package/dist/daemon/{wallet-factory.d.cts → wallet-factory.d.ts} +4 -4
- package/dist/daemon/wallet-factory.d.ts.map +1 -0
- package/dist/daemon/{wallet-factory.mjs → wallet-factory.js} +12 -12
- package/dist/daemon/wallet-factory.js.map +1 -0
- package/dist/persistence/{KeyValueStore.d.cts → KeyValueStore.d.ts} +2 -2
- package/dist/persistence/KeyValueStore.d.ts.map +1 -0
- package/dist/persistence/KeyValueStore.js +59 -0
- package/dist/persistence/KeyValueStore.js.map +1 -0
- package/dist/persistence/{persistence.d.cts → persistence.d.ts} +5 -5
- package/dist/persistence/persistence.d.ts.map +1 -0
- package/dist/persistence/{persistence.mjs → persistence.js} +2 -2
- package/dist/persistence/persistence.js.map +1 -0
- package/dist/test/{run-command.d.cts → run-command.d.ts} +4 -4
- package/dist/test/run-command.d.ts.map +1 -0
- package/dist/test/{run-command.mjs → run-command.js} +3 -3
- package/dist/test/run-command.js.map +1 -0
- package/package.json +19 -15
- package/dist/commands/daemon/call.cjs +0 -79
- package/dist/commands/daemon/call.cjs.map +0 -1
- package/dist/commands/daemon/call.d.cts +0 -14
- package/dist/commands/daemon/call.d.cts.map +0 -1
- package/dist/commands/daemon/call.d.mts.map +0 -1
- package/dist/commands/daemon/call.mjs.map +0 -1
- package/dist/commands/daemon/list.cjs +0 -48
- package/dist/commands/daemon/list.cjs.map +0 -1
- package/dist/commands/daemon/list.d.cts.map +0 -1
- package/dist/commands/daemon/list.d.mts +0 -7
- package/dist/commands/daemon/list.d.mts.map +0 -1
- package/dist/commands/daemon/list.mjs.map +0 -1
- package/dist/commands/daemon/purge.cjs +0 -58
- package/dist/commands/daemon/purge.cjs.map +0 -1
- package/dist/commands/daemon/purge.d.cts.map +0 -1
- package/dist/commands/daemon/purge.d.mts +0 -10
- package/dist/commands/daemon/purge.d.mts.map +0 -1
- package/dist/commands/daemon/purge.mjs.map +0 -1
- package/dist/commands/daemon/start.cjs +0 -52
- package/dist/commands/daemon/start.d.cts.map +0 -1
- package/dist/commands/daemon/start.d.mts +0 -12
- package/dist/commands/daemon/start.d.mts.map +0 -1
- package/dist/commands/daemon/start.mjs +0 -50
- package/dist/commands/daemon/start.mjs.map +0 -1
- package/dist/commands/daemon/status.cjs +0 -59
- package/dist/commands/daemon/status.cjs.map +0 -1
- package/dist/commands/daemon/status.d.cts.map +0 -1
- package/dist/commands/daemon/status.d.mts +0 -7
- package/dist/commands/daemon/status.d.mts.map +0 -1
- package/dist/commands/daemon/status.mjs.map +0 -1
- package/dist/commands/daemon/stop.cjs +0 -26
- package/dist/commands/daemon/stop.cjs.map +0 -1
- package/dist/commands/daemon/stop.d.cts.map +0 -1
- package/dist/commands/daemon/stop.d.mts +0 -7
- package/dist/commands/daemon/stop.d.mts.map +0 -1
- package/dist/commands/daemon/stop.mjs.map +0 -1
- package/dist/commands/wallet/send.cjs +0 -332
- package/dist/commands/wallet/send.cjs.map +0 -1
- package/dist/commands/wallet/send.d.cts.map +0 -1
- package/dist/commands/wallet/send.d.mts +0 -42
- package/dist/commands/wallet/send.d.mts.map +0 -1
- package/dist/commands/wallet/send.mjs.map +0 -1
- package/dist/commands/wallet/unlock.cjs +0 -75
- package/dist/commands/wallet/unlock.cjs.map +0 -1
- package/dist/commands/wallet/unlock.d.cts.map +0 -1
- package/dist/commands/wallet/unlock.d.mts +0 -11
- package/dist/commands/wallet/unlock.d.mts.map +0 -1
- package/dist/commands/wallet/unlock.mjs.map +0 -1
- package/dist/daemon/auto-approval.cjs +0 -86
- package/dist/daemon/auto-approval.cjs.map +0 -1
- package/dist/daemon/auto-approval.d.cts +0 -22
- package/dist/daemon/auto-approval.d.cts.map +0 -1
- package/dist/daemon/auto-approval.d.mts.map +0 -1
- package/dist/daemon/auto-approval.mjs.map +0 -1
- package/dist/daemon/daemon-client.cjs +0 -149
- package/dist/daemon/daemon-client.cjs.map +0 -1
- package/dist/daemon/daemon-client.d.cts +0 -84
- package/dist/daemon/daemon-client.d.cts.map +0 -1
- package/dist/daemon/daemon-client.d.mts.map +0 -1
- package/dist/daemon/daemon-client.mjs.map +0 -1
- package/dist/daemon/daemon-entry.cjs +0 -278
- package/dist/daemon/daemon-entry.cjs.map +0 -1
- package/dist/daemon/daemon-entry.d.cts +0 -2
- package/dist/daemon/daemon-entry.d.cts.map +0 -1
- package/dist/daemon/daemon-entry.d.mts +0 -2
- package/dist/daemon/daemon-entry.d.mts.map +0 -1
- package/dist/daemon/daemon-entry.mjs.map +0 -1
- package/dist/daemon/daemon-spawn.cjs +0 -138
- package/dist/daemon/daemon-spawn.cjs.map +0 -1
- package/dist/daemon/daemon-spawn.d.cts +0 -28
- package/dist/daemon/daemon-spawn.d.cts.map +0 -1
- package/dist/daemon/daemon-spawn.d.mts.map +0 -1
- package/dist/daemon/daemon-spawn.mjs.map +0 -1
- package/dist/daemon/data-dir.cjs +0 -23
- package/dist/daemon/data-dir.cjs.map +0 -1
- package/dist/daemon/data-dir.d.cts.map +0 -1
- package/dist/daemon/data-dir.d.mts +0 -14
- package/dist/daemon/data-dir.d.mts.map +0 -1
- package/dist/daemon/data-dir.mjs.map +0 -1
- package/dist/daemon/paths.cjs +0 -20
- package/dist/daemon/paths.cjs.map +0 -1
- package/dist/daemon/paths.d.cts +0 -9
- package/dist/daemon/paths.d.cts.map +0 -1
- package/dist/daemon/paths.d.mts.map +0 -1
- package/dist/daemon/paths.mjs.map +0 -1
- package/dist/daemon/prompts.cjs +0 -55
- package/dist/daemon/prompts.cjs.map +0 -1
- package/dist/daemon/prompts.d.cts.map +0 -1
- package/dist/daemon/prompts.d.mts +0 -31
- package/dist/daemon/prompts.d.mts.map +0 -1
- package/dist/daemon/prompts.mjs.map +0 -1
- package/dist/daemon/rpc-socket-server.cjs +0 -284
- package/dist/daemon/rpc-socket-server.cjs.map +0 -1
- package/dist/daemon/rpc-socket-server.d.cts.map +0 -1
- package/dist/daemon/rpc-socket-server.d.mts +0 -44
- package/dist/daemon/rpc-socket-server.d.mts.map +0 -1
- package/dist/daemon/rpc-socket-server.mjs.map +0 -1
- package/dist/daemon/secrets.cjs +0 -137
- package/dist/daemon/secrets.cjs.map +0 -1
- package/dist/daemon/secrets.d.cts.map +0 -1
- package/dist/daemon/secrets.d.mts +0 -72
- package/dist/daemon/secrets.d.mts.map +0 -1
- package/dist/daemon/secrets.mjs.map +0 -1
- package/dist/daemon/send-transaction.cjs +0 -147
- package/dist/daemon/send-transaction.cjs.map +0 -1
- package/dist/daemon/send-transaction.d.cts.map +0 -1
- package/dist/daemon/send-transaction.d.mts +0 -102
- package/dist/daemon/send-transaction.d.mts.map +0 -1
- package/dist/daemon/send-transaction.mjs.map +0 -1
- package/dist/daemon/socket-line.cjs +0 -93
- package/dist/daemon/socket-line.cjs.map +0 -1
- package/dist/daemon/socket-line.d.cts.map +0 -1
- package/dist/daemon/socket-line.d.mts +0 -21
- package/dist/daemon/socket-line.d.mts.map +0 -1
- package/dist/daemon/socket-line.mjs.map +0 -1
- package/dist/daemon/stop-daemon.cjs +0 -117
- package/dist/daemon/stop-daemon.cjs.map +0 -1
- package/dist/daemon/stop-daemon.d.cts.map +0 -1
- package/dist/daemon/stop-daemon.d.mts +0 -28
- package/dist/daemon/stop-daemon.d.mts.map +0 -1
- package/dist/daemon/stop-daemon.mjs.map +0 -1
- package/dist/daemon/types.cjs +0 -20
- package/dist/daemon/types.cjs.map +0 -1
- package/dist/daemon/types.d.cts.map +0 -1
- package/dist/daemon/types.d.mts +0 -94
- package/dist/daemon/types.d.mts.map +0 -1
- package/dist/daemon/types.mjs.map +0 -1
- package/dist/daemon/utils.cjs +0 -172
- package/dist/daemon/utils.cjs.map +0 -1
- package/dist/daemon/utils.d.cts.map +0 -1
- package/dist/daemon/utils.d.mts +0 -87
- package/dist/daemon/utils.d.mts.map +0 -1
- package/dist/daemon/utils.mjs.map +0 -1
- package/dist/daemon/wallet-factory.cjs +0 -341
- package/dist/daemon/wallet-factory.cjs.map +0 -1
- package/dist/daemon/wallet-factory.d.cts.map +0 -1
- package/dist/daemon/wallet-factory.d.mts +0 -64
- package/dist/daemon/wallet-factory.d.mts.map +0 -1
- package/dist/daemon/wallet-factory.mjs.map +0 -1
- package/dist/persistence/KeyValueStore.cjs +0 -79
- package/dist/persistence/KeyValueStore.cjs.map +0 -1
- package/dist/persistence/KeyValueStore.d.cts.map +0 -1
- package/dist/persistence/KeyValueStore.d.mts +0 -18
- package/dist/persistence/KeyValueStore.d.mts.map +0 -1
- package/dist/persistence/KeyValueStore.mjs +0 -79
- package/dist/persistence/KeyValueStore.mjs.map +0 -1
- package/dist/persistence/persistence.cjs +0 -204
- package/dist/persistence/persistence.cjs.map +0 -1
- package/dist/persistence/persistence.d.cts.map +0 -1
- package/dist/persistence/persistence.d.mts +0 -45
- package/dist/persistence/persistence.d.mts.map +0 -1
- package/dist/persistence/persistence.mjs.map +0 -1
- package/dist/test/run-command.cjs +0 -73
- package/dist/test/run-command.cjs.map +0 -1
- package/dist/test/run-command.d.cts.map +0 -1
- package/dist/test/run-command.d.mts +0 -27
- package/dist/test/run-command.d.mts.map +0 -1
- package/dist/test/run-command.mjs.map +0 -1
package/dist/daemon/secrets.cjs
DELETED
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
3
|
-
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
4
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
5
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
6
|
-
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
7
|
-
};
|
|
8
|
-
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
9
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
10
|
-
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");
|
|
11
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
12
|
-
};
|
|
13
|
-
var _Password_value, _Srp_value;
|
|
14
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.Srp = exports.Password = void 0;
|
|
16
|
-
const scure_bip39_1 = require("@metamask/scure-bip39");
|
|
17
|
-
const english_1 = require("@metamask/scure-bip39/dist/wordlists/english.js");
|
|
18
|
-
const REDACTED = '[redacted]';
|
|
19
|
-
const VALID_SRP_WORD_COUNTS = [12, 15, 18, 21, 24];
|
|
20
|
-
const INSPECT_CUSTOM = Symbol.for('nodejs.util.inspect.custom');
|
|
21
|
-
const WORDLIST_SET = new Set(english_1.wordlist);
|
|
22
|
-
/**
|
|
23
|
-
* Opaque wrapper around a wallet password.
|
|
24
|
-
*
|
|
25
|
-
* Constructed via {@link Password.from}, which validates the input. The
|
|
26
|
-
* underlying string is only reachable through {@link Password.unwrap}; every
|
|
27
|
-
* other path (`toString`, `JSON.stringify`, `util.inspect`, template-literal
|
|
28
|
-
* interpolation) yields `[redacted]`. This makes accidental logging produce a
|
|
29
|
-
* harmless placeholder instead of leaking the secret.
|
|
30
|
-
*/
|
|
31
|
-
class Password {
|
|
32
|
-
// See .from() for why this is private.
|
|
33
|
-
// eslint-disable-next-line no-restricted-syntax
|
|
34
|
-
constructor(value) {
|
|
35
|
-
_Password_value.set(this, void 0);
|
|
36
|
-
__classPrivateFieldSet(this, _Password_value, value, "f");
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Wrap a non-empty string as a {@link Password}.
|
|
40
|
-
*
|
|
41
|
-
* Matches the `@metamask/keyring-controller` convention: any non-empty
|
|
42
|
-
* string is acceptable; minimum-length policy is left to the keyring.
|
|
43
|
-
*
|
|
44
|
-
* @param value - The raw password string.
|
|
45
|
-
* @returns A redacting {@link Password} wrapper.
|
|
46
|
-
* @throws If `value` is empty.
|
|
47
|
-
*/
|
|
48
|
-
static from(value) {
|
|
49
|
-
if (value.length === 0) {
|
|
50
|
-
throw new Error('Password must be a non-empty string');
|
|
51
|
-
}
|
|
52
|
-
return new Password(value);
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Reveal the underlying password string. Call this only at trust boundaries
|
|
56
|
-
* (e.g. handing the value to the keyring or to a child-process env var).
|
|
57
|
-
*
|
|
58
|
-
* @returns The original password string.
|
|
59
|
-
*/
|
|
60
|
-
unwrap() {
|
|
61
|
-
return __classPrivateFieldGet(this, _Password_value, "f");
|
|
62
|
-
}
|
|
63
|
-
toString() {
|
|
64
|
-
return REDACTED;
|
|
65
|
-
}
|
|
66
|
-
toJSON() {
|
|
67
|
-
return REDACTED;
|
|
68
|
-
}
|
|
69
|
-
[(_Password_value = new WeakMap(), INSPECT_CUSTOM)]() {
|
|
70
|
-
return REDACTED;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
exports.Password = Password;
|
|
74
|
-
/**
|
|
75
|
-
* Opaque wrapper around a BIP-39 secret recovery phrase.
|
|
76
|
-
*
|
|
77
|
-
* Constructed via {@link Srp.from}, which validates the word count
|
|
78
|
-
* (12/15/18/21/24) and that every word is present in the BIP-39 English
|
|
79
|
-
* wordlist. The underlying string is only reachable through {@link Srp.unwrap};
|
|
80
|
-
* every other path yields `[redacted]`.
|
|
81
|
-
*/
|
|
82
|
-
class Srp {
|
|
83
|
-
// See .from() for why this is private.
|
|
84
|
-
// eslint-disable-next-line no-restricted-syntax
|
|
85
|
-
constructor(value) {
|
|
86
|
-
_Srp_value.set(this, void 0);
|
|
87
|
-
__classPrivateFieldSet(this, _Srp_value, value, "f");
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* Validate and wrap a BIP-39 mnemonic phrase.
|
|
91
|
-
*
|
|
92
|
-
* Whitespace is normalized (trimmed and collapsed) before validation so that
|
|
93
|
-
* copy-pasted phrases with accidental leading/trailing/extra spaces are
|
|
94
|
-
* accepted. Catching malformed input here (rather than letting it reach
|
|
95
|
-
* `KeyringController:createNewVaultAndRestore`) produces a clearer error.
|
|
96
|
-
*
|
|
97
|
-
* @param value - The raw mnemonic string.
|
|
98
|
-
* @returns A redacting {@link Srp} wrapper containing the normalized phrase.
|
|
99
|
-
* @throws If the word count is not one of 12/15/18/21/24, if any word is
|
|
100
|
-
* not present in the BIP-39 English wordlist, or if the checksum is invalid.
|
|
101
|
-
*/
|
|
102
|
-
static from(value) {
|
|
103
|
-
const words = value.trim().split(/\s+/u);
|
|
104
|
-
if (!VALID_SRP_WORD_COUNTS.includes(words.length)) {
|
|
105
|
-
throw new Error(`Secret recovery phrase must be 12, 15, 18, 21, or 24 words (got ${words.length})`);
|
|
106
|
-
}
|
|
107
|
-
for (const word of words) {
|
|
108
|
-
if (!WORDLIST_SET.has(word)) {
|
|
109
|
-
throw new Error('Secret recovery phrase contains a word not in the BIP-39 English wordlist');
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
const normalized = words.join(' ');
|
|
113
|
-
if (!(0, scure_bip39_1.validateMnemonic)(normalized, english_1.wordlist)) {
|
|
114
|
-
throw new Error('Secret recovery phrase has an invalid checksum');
|
|
115
|
-
}
|
|
116
|
-
return new Srp(normalized);
|
|
117
|
-
}
|
|
118
|
-
/**
|
|
119
|
-
* Reveal the underlying mnemonic string. Call this only at trust boundaries.
|
|
120
|
-
*
|
|
121
|
-
* @returns The original mnemonic string.
|
|
122
|
-
*/
|
|
123
|
-
unwrap() {
|
|
124
|
-
return __classPrivateFieldGet(this, _Srp_value, "f");
|
|
125
|
-
}
|
|
126
|
-
toString() {
|
|
127
|
-
return REDACTED;
|
|
128
|
-
}
|
|
129
|
-
toJSON() {
|
|
130
|
-
return REDACTED;
|
|
131
|
-
}
|
|
132
|
-
[(_Srp_value = new WeakMap(), INSPECT_CUSTOM)]() {
|
|
133
|
-
return REDACTED;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
exports.Srp = Srp;
|
|
137
|
-
//# sourceMappingURL=secrets.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"secrets.cjs","sourceRoot":"","sources":["../../src/daemon/secrets.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,uDAAyD;AACzD,6EAAwE;AAExE,MAAM,QAAQ,GAAG,YAAY,CAAC;AAE9B,MAAM,qBAAqB,GAAsB,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;AAEtE,MAAM,cAAc,GAAG,MAAM,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;AAEhE,MAAM,YAAY,GAAwB,IAAI,GAAG,CAAC,kBAAQ,CAAC,CAAC;AAE5D;;;;;;;;GAQG;AACH,MAAa,QAAQ;IAGnB,uCAAuC;IACvC,gDAAgD;IAChD,YAAoB,KAAa;QAJxB,kCAAe;QAKtB,uBAAA,IAAI,mBAAU,KAAK,MAAA,CAAC;IACtB,CAAC;IAED;;;;;;;;;OASG;IACH,MAAM,CAAC,IAAI,CAAC,KAAa;QACvB,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;QACzD,CAAC;QACD,OAAO,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC;IAED;;;;;OAKG;IACH,MAAM;QACJ,OAAO,uBAAA,IAAI,uBAAO,CAAC;IACrB,CAAC;IAED,QAAQ;QACN,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,MAAM;QACJ,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,mCAAC,cAAc,EAAC;QACd,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF;AA/CD,4BA+CC;AAED;;;;;;;GAOG;AACH,MAAa,GAAG;IAGd,uCAAuC;IACvC,gDAAgD;IAChD,YAAoB,KAAa;QAJxB,6BAAe;QAKtB,uBAAA,IAAI,cAAU,KAAK,MAAA,CAAC;IACtB,CAAC;IAED;;;;;;;;;;;;OAYG;IACH,MAAM,CAAC,IAAI,CAAC,KAAa;QACvB,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACzC,IAAI,CAAC,qBAAqB,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;YAClD,MAAM,IAAI,KAAK,CACb,mEAAmE,KAAK,CAAC,MAAM,GAAG,CACnF,CAAC;QACJ,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC5B,MAAM,IAAI,KAAK,CACb,2EAA2E,CAC5E,CAAC;YACJ,CAAC;QACH,CAAC;QAED,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,CAAC,IAAA,8BAAgB,EAAC,UAAU,EAAE,kBAAQ,CAAC,EAAE,CAAC;YAC5C,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;QACpE,CAAC;QACD,OAAO,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC;IAC7B,CAAC;IAED;;;;OAIG;IACH,MAAM;QACJ,OAAO,uBAAA,IAAI,kBAAO,CAAC;IACrB,CAAC;IAED,QAAQ;QACN,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,MAAM;QACJ,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,8BAAC,cAAc,EAAC;QACd,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF;AAhED,kBAgEC","sourcesContent":["import { validateMnemonic } from '@metamask/scure-bip39';\nimport { wordlist } from '@metamask/scure-bip39/dist/wordlists/english';\n\nconst REDACTED = '[redacted]';\n\nconst VALID_SRP_WORD_COUNTS: readonly number[] = [12, 15, 18, 21, 24];\n\nconst INSPECT_CUSTOM = Symbol.for('nodejs.util.inspect.custom');\n\nconst WORDLIST_SET: ReadonlySet<string> = new Set(wordlist);\n\n/**\n * Opaque wrapper around a wallet password.\n *\n * Constructed via {@link Password.from}, which validates the input. The\n * underlying string is only reachable through {@link Password.unwrap}; every\n * other path (`toString`, `JSON.stringify`, `util.inspect`, template-literal\n * interpolation) yields `[redacted]`. This makes accidental logging produce a\n * harmless placeholder instead of leaking the secret.\n */\nexport class Password {\n readonly #value: string;\n\n // See .from() for why this is private.\n // eslint-disable-next-line no-restricted-syntax\n private constructor(value: string) {\n this.#value = value;\n }\n\n /**\n * Wrap a non-empty string as a {@link Password}.\n *\n * Matches the `@metamask/keyring-controller` convention: any non-empty\n * string is acceptable; minimum-length policy is left to the keyring.\n *\n * @param value - The raw password string.\n * @returns A redacting {@link Password} wrapper.\n * @throws If `value` is empty.\n */\n static from(value: string): Password {\n if (value.length === 0) {\n throw new Error('Password must be a non-empty string');\n }\n return new Password(value);\n }\n\n /**\n * Reveal the underlying password string. Call this only at trust boundaries\n * (e.g. handing the value to the keyring or to a child-process env var).\n *\n * @returns The original password string.\n */\n unwrap(): string {\n return this.#value;\n }\n\n toString(): string {\n return REDACTED;\n }\n\n toJSON(): string {\n return REDACTED;\n }\n\n [INSPECT_CUSTOM](): string {\n return REDACTED;\n }\n}\n\n/**\n * Opaque wrapper around a BIP-39 secret recovery phrase.\n *\n * Constructed via {@link Srp.from}, which validates the word count\n * (12/15/18/21/24) and that every word is present in the BIP-39 English\n * wordlist. The underlying string is only reachable through {@link Srp.unwrap};\n * every other path yields `[redacted]`.\n */\nexport class Srp {\n readonly #value: string;\n\n // See .from() for why this is private.\n // eslint-disable-next-line no-restricted-syntax\n private constructor(value: string) {\n this.#value = value;\n }\n\n /**\n * Validate and wrap a BIP-39 mnemonic phrase.\n *\n * Whitespace is normalized (trimmed and collapsed) before validation so that\n * copy-pasted phrases with accidental leading/trailing/extra spaces are\n * accepted. Catching malformed input here (rather than letting it reach\n * `KeyringController:createNewVaultAndRestore`) produces a clearer error.\n *\n * @param value - The raw mnemonic string.\n * @returns A redacting {@link Srp} wrapper containing the normalized phrase.\n * @throws If the word count is not one of 12/15/18/21/24, if any word is\n * not present in the BIP-39 English wordlist, or if the checksum is invalid.\n */\n static from(value: string): Srp {\n const words = value.trim().split(/\\s+/u);\n if (!VALID_SRP_WORD_COUNTS.includes(words.length)) {\n throw new Error(\n `Secret recovery phrase must be 12, 15, 18, 21, or 24 words (got ${words.length})`,\n );\n }\n for (const word of words) {\n if (!WORDLIST_SET.has(word)) {\n throw new Error(\n 'Secret recovery phrase contains a word not in the BIP-39 English wordlist',\n );\n }\n }\n\n const normalized = words.join(' ');\n if (!validateMnemonic(normalized, wordlist)) {\n throw new Error('Secret recovery phrase has an invalid checksum');\n }\n return new Srp(normalized);\n }\n\n /**\n * Reveal the underlying mnemonic string. Call this only at trust boundaries.\n *\n * @returns The original mnemonic string.\n */\n unwrap(): string {\n return this.#value;\n }\n\n toString(): string {\n return REDACTED;\n }\n\n toJSON(): string {\n return REDACTED;\n }\n\n [INSPECT_CUSTOM](): string {\n return REDACTED;\n }\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"secrets.d.cts","sourceRoot":"","sources":["../../src/daemon/secrets.ts"],"names":[],"mappings":"AAOA,QAAA,MAAM,cAAc,eAA2C,CAAC;AAIhE;;;;;;;;GAQG;AACH,qBAAa,QAAQ;;IAKnB,OAAO;IAIP;;;;;;;;;OASG;IACH,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ;IAOpC;;;;;OAKG;IACH,MAAM,IAAI,MAAM;IAIhB,QAAQ,IAAI,MAAM;IAIlB,MAAM,IAAI,MAAM;IAIhB,CAAC,cAAc,CAAC,IAAI,MAAM;CAG3B;AAED;;;;;;;GAOG;AACH,qBAAa,GAAG;;IAKd,OAAO;IAIP;;;;;;;;;;;;OAYG;IACH,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG;IAsB/B;;;;OAIG;IACH,MAAM,IAAI,MAAM;IAIhB,QAAQ,IAAI,MAAM;IAIlB,MAAM,IAAI,MAAM;IAIhB,CAAC,cAAc,CAAC,IAAI,MAAM;CAG3B"}
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
declare const INSPECT_CUSTOM: unique symbol;
|
|
2
|
-
/**
|
|
3
|
-
* Opaque wrapper around a wallet password.
|
|
4
|
-
*
|
|
5
|
-
* Constructed via {@link Password.from}, which validates the input. The
|
|
6
|
-
* underlying string is only reachable through {@link Password.unwrap}; every
|
|
7
|
-
* other path (`toString`, `JSON.stringify`, `util.inspect`, template-literal
|
|
8
|
-
* interpolation) yields `[redacted]`. This makes accidental logging produce a
|
|
9
|
-
* harmless placeholder instead of leaking the secret.
|
|
10
|
-
*/
|
|
11
|
-
export declare class Password {
|
|
12
|
-
#private;
|
|
13
|
-
private constructor();
|
|
14
|
-
/**
|
|
15
|
-
* Wrap a non-empty string as a {@link Password}.
|
|
16
|
-
*
|
|
17
|
-
* Matches the `@metamask/keyring-controller` convention: any non-empty
|
|
18
|
-
* string is acceptable; minimum-length policy is left to the keyring.
|
|
19
|
-
*
|
|
20
|
-
* @param value - The raw password string.
|
|
21
|
-
* @returns A redacting {@link Password} wrapper.
|
|
22
|
-
* @throws If `value` is empty.
|
|
23
|
-
*/
|
|
24
|
-
static from(value: string): Password;
|
|
25
|
-
/**
|
|
26
|
-
* Reveal the underlying password string. Call this only at trust boundaries
|
|
27
|
-
* (e.g. handing the value to the keyring or to a child-process env var).
|
|
28
|
-
*
|
|
29
|
-
* @returns The original password string.
|
|
30
|
-
*/
|
|
31
|
-
unwrap(): string;
|
|
32
|
-
toString(): string;
|
|
33
|
-
toJSON(): string;
|
|
34
|
-
[INSPECT_CUSTOM](): string;
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Opaque wrapper around a BIP-39 secret recovery phrase.
|
|
38
|
-
*
|
|
39
|
-
* Constructed via {@link Srp.from}, which validates the word count
|
|
40
|
-
* (12/15/18/21/24) and that every word is present in the BIP-39 English
|
|
41
|
-
* wordlist. The underlying string is only reachable through {@link Srp.unwrap};
|
|
42
|
-
* every other path yields `[redacted]`.
|
|
43
|
-
*/
|
|
44
|
-
export declare class Srp {
|
|
45
|
-
#private;
|
|
46
|
-
private constructor();
|
|
47
|
-
/**
|
|
48
|
-
* Validate and wrap a BIP-39 mnemonic phrase.
|
|
49
|
-
*
|
|
50
|
-
* Whitespace is normalized (trimmed and collapsed) before validation so that
|
|
51
|
-
* copy-pasted phrases with accidental leading/trailing/extra spaces are
|
|
52
|
-
* accepted. Catching malformed input here (rather than letting it reach
|
|
53
|
-
* `KeyringController:createNewVaultAndRestore`) produces a clearer error.
|
|
54
|
-
*
|
|
55
|
-
* @param value - The raw mnemonic string.
|
|
56
|
-
* @returns A redacting {@link Srp} wrapper containing the normalized phrase.
|
|
57
|
-
* @throws If the word count is not one of 12/15/18/21/24, if any word is
|
|
58
|
-
* not present in the BIP-39 English wordlist, or if the checksum is invalid.
|
|
59
|
-
*/
|
|
60
|
-
static from(value: string): Srp;
|
|
61
|
-
/**
|
|
62
|
-
* Reveal the underlying mnemonic string. Call this only at trust boundaries.
|
|
63
|
-
*
|
|
64
|
-
* @returns The original mnemonic string.
|
|
65
|
-
*/
|
|
66
|
-
unwrap(): string;
|
|
67
|
-
toString(): string;
|
|
68
|
-
toJSON(): string;
|
|
69
|
-
[INSPECT_CUSTOM](): string;
|
|
70
|
-
}
|
|
71
|
-
export {};
|
|
72
|
-
//# sourceMappingURL=secrets.d.mts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"secrets.d.mts","sourceRoot":"","sources":["../../src/daemon/secrets.ts"],"names":[],"mappings":"AAOA,QAAA,MAAM,cAAc,eAA2C,CAAC;AAIhE;;;;;;;;GAQG;AACH,qBAAa,QAAQ;;IAKnB,OAAO;IAIP;;;;;;;;;OASG;IACH,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ;IAOpC;;;;;OAKG;IACH,MAAM,IAAI,MAAM;IAIhB,QAAQ,IAAI,MAAM;IAIlB,MAAM,IAAI,MAAM;IAIhB,CAAC,cAAc,CAAC,IAAI,MAAM;CAG3B;AAED;;;;;;;GAOG;AACH,qBAAa,GAAG;;IAKd,OAAO;IAIP;;;;;;;;;;;;OAYG;IACH,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG;IAsB/B;;;;OAIG;IACH,MAAM,IAAI,MAAM;IAIhB,QAAQ,IAAI,MAAM;IAIlB,MAAM,IAAI,MAAM;IAIhB,CAAC,cAAc,CAAC,IAAI,MAAM;CAG3B"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"secrets.mjs","sourceRoot":"","sources":["../../src/daemon/secrets.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,OAAO,EAAE,gBAAgB,EAAE,8BAA8B;AACzD,OAAO,EAAE,QAAQ,EAAE,wDAAqD;AAExE,MAAM,QAAQ,GAAG,YAAY,CAAC;AAE9B,MAAM,qBAAqB,GAAsB,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;AAEtE,MAAM,cAAc,GAAG,MAAM,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;AAEhE,MAAM,YAAY,GAAwB,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;AAE5D;;;;;;;;GAQG;AACH,MAAM,OAAO,QAAQ;IAGnB,uCAAuC;IACvC,gDAAgD;IAChD,YAAoB,KAAa;QAJxB,kCAAe;QAKtB,uBAAA,IAAI,mBAAU,KAAK,MAAA,CAAC;IACtB,CAAC;IAED;;;;;;;;;OASG;IACH,MAAM,CAAC,IAAI,CAAC,KAAa;QACvB,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;QACzD,CAAC;QACD,OAAO,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC;IAED;;;;;OAKG;IACH,MAAM;QACJ,OAAO,uBAAA,IAAI,uBAAO,CAAC;IACrB,CAAC;IAED,QAAQ;QACN,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,MAAM;QACJ,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,mCAAC,cAAc,EAAC;QACd,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF;AAED;;;;;;;GAOG;AACH,MAAM,OAAO,GAAG;IAGd,uCAAuC;IACvC,gDAAgD;IAChD,YAAoB,KAAa;QAJxB,6BAAe;QAKtB,uBAAA,IAAI,cAAU,KAAK,MAAA,CAAC;IACtB,CAAC;IAED;;;;;;;;;;;;OAYG;IACH,MAAM,CAAC,IAAI,CAAC,KAAa;QACvB,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACzC,IAAI,CAAC,qBAAqB,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;YAClD,MAAM,IAAI,KAAK,CACb,mEAAmE,KAAK,CAAC,MAAM,GAAG,CACnF,CAAC;QACJ,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC5B,MAAM,IAAI,KAAK,CACb,2EAA2E,CAC5E,CAAC;YACJ,CAAC;QACH,CAAC;QAED,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,CAAC,gBAAgB,CAAC,UAAU,EAAE,QAAQ,CAAC,EAAE,CAAC;YAC5C,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;QACpE,CAAC;QACD,OAAO,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC;IAC7B,CAAC;IAED;;;;OAIG;IACH,MAAM;QACJ,OAAO,uBAAA,IAAI,kBAAO,CAAC;IACrB,CAAC;IAED,QAAQ;QACN,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,MAAM;QACJ,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,8BAAC,cAAc,EAAC;QACd,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF","sourcesContent":["import { validateMnemonic } from '@metamask/scure-bip39';\nimport { wordlist } from '@metamask/scure-bip39/dist/wordlists/english';\n\nconst REDACTED = '[redacted]';\n\nconst VALID_SRP_WORD_COUNTS: readonly number[] = [12, 15, 18, 21, 24];\n\nconst INSPECT_CUSTOM = Symbol.for('nodejs.util.inspect.custom');\n\nconst WORDLIST_SET: ReadonlySet<string> = new Set(wordlist);\n\n/**\n * Opaque wrapper around a wallet password.\n *\n * Constructed via {@link Password.from}, which validates the input. The\n * underlying string is only reachable through {@link Password.unwrap}; every\n * other path (`toString`, `JSON.stringify`, `util.inspect`, template-literal\n * interpolation) yields `[redacted]`. This makes accidental logging produce a\n * harmless placeholder instead of leaking the secret.\n */\nexport class Password {\n readonly #value: string;\n\n // See .from() for why this is private.\n // eslint-disable-next-line no-restricted-syntax\n private constructor(value: string) {\n this.#value = value;\n }\n\n /**\n * Wrap a non-empty string as a {@link Password}.\n *\n * Matches the `@metamask/keyring-controller` convention: any non-empty\n * string is acceptable; minimum-length policy is left to the keyring.\n *\n * @param value - The raw password string.\n * @returns A redacting {@link Password} wrapper.\n * @throws If `value` is empty.\n */\n static from(value: string): Password {\n if (value.length === 0) {\n throw new Error('Password must be a non-empty string');\n }\n return new Password(value);\n }\n\n /**\n * Reveal the underlying password string. Call this only at trust boundaries\n * (e.g. handing the value to the keyring or to a child-process env var).\n *\n * @returns The original password string.\n */\n unwrap(): string {\n return this.#value;\n }\n\n toString(): string {\n return REDACTED;\n }\n\n toJSON(): string {\n return REDACTED;\n }\n\n [INSPECT_CUSTOM](): string {\n return REDACTED;\n }\n}\n\n/**\n * Opaque wrapper around a BIP-39 secret recovery phrase.\n *\n * Constructed via {@link Srp.from}, which validates the word count\n * (12/15/18/21/24) and that every word is present in the BIP-39 English\n * wordlist. The underlying string is only reachable through {@link Srp.unwrap};\n * every other path yields `[redacted]`.\n */\nexport class Srp {\n readonly #value: string;\n\n // See .from() for why this is private.\n // eslint-disable-next-line no-restricted-syntax\n private constructor(value: string) {\n this.#value = value;\n }\n\n /**\n * Validate and wrap a BIP-39 mnemonic phrase.\n *\n * Whitespace is normalized (trimmed and collapsed) before validation so that\n * copy-pasted phrases with accidental leading/trailing/extra spaces are\n * accepted. Catching malformed input here (rather than letting it reach\n * `KeyringController:createNewVaultAndRestore`) produces a clearer error.\n *\n * @param value - The raw mnemonic string.\n * @returns A redacting {@link Srp} wrapper containing the normalized phrase.\n * @throws If the word count is not one of 12/15/18/21/24, if any word is\n * not present in the BIP-39 English wordlist, or if the checksum is invalid.\n */\n static from(value: string): Srp {\n const words = value.trim().split(/\\s+/u);\n if (!VALID_SRP_WORD_COUNTS.includes(words.length)) {\n throw new Error(\n `Secret recovery phrase must be 12, 15, 18, 21, or 24 words (got ${words.length})`,\n );\n }\n for (const word of words) {\n if (!WORDLIST_SET.has(word)) {\n throw new Error(\n 'Secret recovery phrase contains a word not in the BIP-39 English wordlist',\n );\n }\n }\n\n const normalized = words.join(' ');\n if (!validateMnemonic(normalized, wordlist)) {\n throw new Error('Secret recovery phrase has an invalid checksum');\n }\n return new Srp(normalized);\n }\n\n /**\n * Reveal the underlying mnemonic string. Call this only at trust boundaries.\n *\n * @returns The original mnemonic string.\n */\n unwrap(): string {\n return this.#value;\n }\n\n toString(): string {\n return REDACTED;\n }\n\n toJSON(): string {\n return REDACTED;\n }\n\n [INSPECT_CUSTOM](): string {\n return REDACTED;\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 +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 +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"]}
|