@metamask-previews/wallet-cli 0.0.0-preview-2a8139a3e → 0.0.0-preview-b8d04f274
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 -5
- package/README.md +1 -13
- package/dist/commands/daemon/start.cjs +3 -7
- package/dist/commands/daemon/start.cjs.map +1 -1
- package/dist/commands/daemon/start.d.cts +1 -1
- package/dist/commands/daemon/start.d.cts.map +1 -1
- package/dist/commands/daemon/start.d.mts +1 -1
- package/dist/commands/daemon/start.d.mts.map +1 -1
- package/dist/commands/daemon/start.mjs +3 -7
- package/dist/commands/daemon/start.mjs.map +1 -1
- package/dist/daemon/daemon-entry.cjs +27 -52
- package/dist/daemon/daemon-entry.cjs.map +1 -1
- package/dist/daemon/daemon-entry.mjs +27 -52
- package/dist/daemon/daemon-entry.mjs.map +1 -1
- package/dist/daemon/daemon-spawn.cjs +8 -19
- package/dist/daemon/daemon-spawn.cjs.map +1 -1
- package/dist/daemon/daemon-spawn.d.cts.map +1 -1
- package/dist/daemon/daemon-spawn.d.mts.map +1 -1
- package/dist/daemon/daemon-spawn.mjs +8 -19
- package/dist/daemon/daemon-spawn.mjs.map +1 -1
- package/dist/daemon/prompts.cjs +1 -17
- package/dist/daemon/prompts.cjs.map +1 -1
- package/dist/daemon/prompts.d.cts +0 -9
- package/dist/daemon/prompts.d.cts.map +1 -1
- package/dist/daemon/prompts.d.mts +0 -9
- package/dist/daemon/prompts.d.mts.map +1 -1
- package/dist/daemon/prompts.mjs +0 -15
- package/dist/daemon/prompts.mjs.map +1 -1
- package/dist/daemon/rpc-socket-server.cjs +1 -14
- package/dist/daemon/rpc-socket-server.cjs.map +1 -1
- package/dist/daemon/rpc-socket-server.d.cts.map +1 -1
- package/dist/daemon/rpc-socket-server.d.mts.map +1 -1
- package/dist/daemon/rpc-socket-server.mjs +1 -14
- package/dist/daemon/rpc-socket-server.mjs.map +1 -1
- package/dist/daemon/types.cjs +0 -17
- package/dist/daemon/types.cjs.map +1 -1
- package/dist/daemon/types.d.cts +7 -58
- package/dist/daemon/types.d.cts.map +1 -1
- package/dist/daemon/types.d.mts +7 -58
- package/dist/daemon/types.d.mts.map +1 -1
- package/dist/daemon/types.mjs +1 -15
- package/dist/daemon/types.mjs.map +1 -1
- package/dist/daemon/utils.cjs +2 -14
- package/dist/daemon/utils.cjs.map +1 -1
- package/dist/daemon/utils.d.cts +0 -9
- package/dist/daemon/utils.d.cts.map +1 -1
- package/dist/daemon/utils.d.mts +0 -9
- package/dist/daemon/utils.d.mts.map +1 -1
- package/dist/daemon/utils.mjs +1 -12
- package/dist/daemon/utils.mjs.map +1 -1
- package/dist/daemon/wallet-factory.cjs +8 -50
- package/dist/daemon/wallet-factory.cjs.map +1 -1
- package/dist/daemon/wallet-factory.d.cts +8 -17
- package/dist/daemon/wallet-factory.d.cts.map +1 -1
- package/dist/daemon/wallet-factory.d.mts +8 -17
- package/dist/daemon/wallet-factory.d.mts.map +1 -1
- package/dist/daemon/wallet-factory.mjs +8 -50
- package/dist/daemon/wallet-factory.mjs.map +1 -1
- package/package.json +2 -5
- package/dist/commands/wallet/unlock.cjs +0 -75
- package/dist/commands/wallet/unlock.cjs.map +0 -1
- package/dist/commands/wallet/unlock.d.cts +0 -11
- 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 +0 -73
- package/dist/commands/wallet/unlock.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 +0 -72
- 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 +0 -132
- package/dist/daemon/secrets.mjs.map +0 -1
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { Command } from "@oclif/core";
|
|
2
|
-
export default class WalletUnlock extends Command {
|
|
3
|
-
static description: string;
|
|
4
|
-
static examples: string[];
|
|
5
|
-
static flags: {
|
|
6
|
-
password: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
|
-
timeout: import("@oclif/core/interfaces").OptionFlag<number | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
|
-
};
|
|
9
|
-
run(): Promise<void>;
|
|
10
|
-
}
|
|
11
|
-
//# sourceMappingURL=unlock.d.mts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"unlock.d.mts","sourceRoot":"","sources":["../../../src/commands/wallet/unlock.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAS,oBAAoB;AAU7C,MAAM,CAAC,OAAO,OAAO,YAAa,SAAQ,OAAO;IAC/C,OAAgB,WAAW,SAGyC;IAEpE,OAAgB,QAAQ,WAItB;IAEF,OAAgB,KAAK;;;MAanB;IAEW,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAgDlC"}
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import { isJsonRpcFailure } from "@metamask/utils";
|
|
2
|
-
import { Command, Flags } from "@oclif/core";
|
|
3
|
-
import { sendCommand } from "../../daemon/daemon-client.mjs";
|
|
4
|
-
import { getDaemonPaths } from "../../daemon/paths.mjs";
|
|
5
|
-
import { promptPassword } from "../../daemon/prompts.mjs";
|
|
6
|
-
import { emptyToUndefined, makeDaemonConnectionError } from "../../daemon/utils.mjs";
|
|
7
|
-
class WalletUnlock extends Command {
|
|
8
|
-
async run() {
|
|
9
|
-
const { flags } = await this.parse(WalletUnlock);
|
|
10
|
-
const { timeout: timeoutMs } = flags;
|
|
11
|
-
// `emptyToUndefined` collapses `--password ''` and `MM_WALLET_PASSWORD=''`
|
|
12
|
-
// to undefined so the prompt fires instead of sending an empty string.
|
|
13
|
-
const flagPassword = emptyToUndefined(flags.password);
|
|
14
|
-
let password;
|
|
15
|
-
try {
|
|
16
|
-
password = flagPassword ?? (await promptPassword());
|
|
17
|
-
}
|
|
18
|
-
catch (error) {
|
|
19
|
-
// Only swallow ExitPromptError (@inquirer/core's Ctrl+C signal); any
|
|
20
|
-
// other rejection (import failure, internal prompt crash) should surface.
|
|
21
|
-
if (error instanceof Error && error.name === 'ExitPromptError') {
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
throw error;
|
|
25
|
-
}
|
|
26
|
-
const { socketPath } = getDaemonPaths(this.config.dataDir);
|
|
27
|
-
let response;
|
|
28
|
-
try {
|
|
29
|
-
response = await sendCommand({
|
|
30
|
-
socketPath,
|
|
31
|
-
method: 'call',
|
|
32
|
-
params: ['KeyringController:submitPassword', password],
|
|
33
|
-
...(timeoutMs === undefined ? {} : { timeoutMs }),
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
catch (error) {
|
|
37
|
-
this.error(makeDaemonConnectionError(error));
|
|
38
|
-
}
|
|
39
|
-
if (isJsonRpcFailure(response)) {
|
|
40
|
-
const { code, message, data } = response.error;
|
|
41
|
-
// `isJsonRpcFailure` already validates that `data` is JSON, so
|
|
42
|
-
// `JSON.stringify` cannot throw here.
|
|
43
|
-
const dataSuffix = data === undefined || data === null
|
|
44
|
-
? ''
|
|
45
|
-
: ` data=${JSON.stringify(data)}`;
|
|
46
|
-
this.error(`Failed to unlock: ${message} (code ${String(code)})${dataSuffix}`);
|
|
47
|
-
}
|
|
48
|
-
this.log('Wallet unlocked.');
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
WalletUnlock.description = 'Unlock the wallet (submits the password to KeyringController). ' +
|
|
52
|
-
'Use this after `mm daemon start` was run without `--password`, or ' +
|
|
53
|
-
'after the keyring was locked via `KeyringController:setLocked`.';
|
|
54
|
-
WalletUnlock.examples = [
|
|
55
|
-
'<%= config.bin %> wallet unlock --password <pw>',
|
|
56
|
-
'MM_WALLET_PASSWORD=<pw> <%= config.bin %> wallet unlock',
|
|
57
|
-
'<%= config.bin %> wallet unlock # prompts interactively',
|
|
58
|
-
];
|
|
59
|
-
WalletUnlock.flags = {
|
|
60
|
-
password: Flags.string({
|
|
61
|
-
description: 'Wallet password (testing only — use MM_WALLET_PASSWORD env var in production). ' +
|
|
62
|
-
'When omitted, the command prompts interactively.',
|
|
63
|
-
env: 'MM_WALLET_PASSWORD',
|
|
64
|
-
required: false,
|
|
65
|
-
}),
|
|
66
|
-
timeout: Flags.integer({
|
|
67
|
-
char: 't',
|
|
68
|
-
description: 'Response timeout in milliseconds',
|
|
69
|
-
required: false,
|
|
70
|
-
}),
|
|
71
|
-
};
|
|
72
|
-
export default WalletUnlock;
|
|
73
|
-
//# sourceMappingURL=unlock.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"unlock.mjs","sourceRoot":"","sources":["../../../src/commands/wallet/unlock.ts"],"names":[],"mappings":"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","sourcesContent":["import { isJsonRpcFailure } from '@metamask/utils';\nimport { Command, Flags } from '@oclif/core';\n\nimport { sendCommand } from '../../daemon/daemon-client';\nimport { getDaemonPaths } from '../../daemon/paths';\nimport { promptPassword } from '../../daemon/prompts';\nimport {\n emptyToUndefined,\n makeDaemonConnectionError,\n} from '../../daemon/utils';\n\nexport default class WalletUnlock extends Command {\n static override description =\n 'Unlock the wallet (submits the password to KeyringController). ' +\n 'Use this after `mm daemon start` was run without `--password`, or ' +\n 'after the keyring was locked via `KeyringController:setLocked`.';\n\n static override examples = [\n '<%= config.bin %> wallet unlock --password <pw>',\n 'MM_WALLET_PASSWORD=<pw> <%= config.bin %> wallet unlock',\n '<%= config.bin %> wallet unlock # prompts interactively',\n ];\n\n static override flags = {\n password: Flags.string({\n description:\n 'Wallet password (testing only — use MM_WALLET_PASSWORD env var in production). ' +\n 'When omitted, the command prompts interactively.',\n env: 'MM_WALLET_PASSWORD',\n required: false,\n }),\n timeout: Flags.integer({\n char: 't',\n description: 'Response timeout in milliseconds',\n required: false,\n }),\n };\n\n public async run(): Promise<void> {\n const { flags } = await this.parse(WalletUnlock);\n const { timeout: timeoutMs } = flags;\n\n // `emptyToUndefined` collapses `--password ''` and `MM_WALLET_PASSWORD=''`\n // to undefined so the prompt fires instead of sending an empty string.\n const flagPassword = emptyToUndefined(flags.password);\n let password: string;\n try {\n password = flagPassword ?? (await promptPassword());\n } catch (error) {\n // Only swallow ExitPromptError (@inquirer/core's Ctrl+C signal); any\n // other rejection (import failure, internal prompt crash) should surface.\n if (error instanceof Error && error.name === 'ExitPromptError') {\n return;\n }\n throw error;\n }\n\n const { socketPath } = getDaemonPaths(this.config.dataDir);\n\n let response;\n try {\n response = await sendCommand({\n socketPath,\n method: 'call',\n params: ['KeyringController:submitPassword', password],\n ...(timeoutMs === undefined ? {} : { timeoutMs }),\n });\n } catch (error) {\n this.error(makeDaemonConnectionError(error));\n }\n\n if (isJsonRpcFailure(response)) {\n const { code, message, data } = response.error;\n // `isJsonRpcFailure` already validates that `data` is JSON, so\n // `JSON.stringify` cannot throw here.\n const dataSuffix =\n data === undefined || data === null\n ? ''\n : ` data=${JSON.stringify(data)}`;\n this.error(\n `Failed to unlock: ${message} (code ${String(code)})${dataSuffix}`,\n );\n }\n\n this.log('Wallet unlocked.');\n }\n}\n"]}
|
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,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.cts.map
|
|
@@ -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"}
|
package/dist/daemon/secrets.mjs
DELETED
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
2
|
-
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
3
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
4
|
-
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");
|
|
5
|
-
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
6
|
-
};
|
|
7
|
-
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
8
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
9
|
-
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");
|
|
10
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
|
-
};
|
|
12
|
-
var _Password_value, _Srp_value;
|
|
13
|
-
import { validateMnemonic } from "@metamask/scure-bip39";
|
|
14
|
-
import { wordlist } from "@metamask/scure-bip39/dist/wordlists/english.js";
|
|
15
|
-
const REDACTED = '[redacted]';
|
|
16
|
-
const VALID_SRP_WORD_COUNTS = [12, 15, 18, 21, 24];
|
|
17
|
-
const INSPECT_CUSTOM = Symbol.for('nodejs.util.inspect.custom');
|
|
18
|
-
const WORDLIST_SET = new Set(wordlist);
|
|
19
|
-
/**
|
|
20
|
-
* Opaque wrapper around a wallet password.
|
|
21
|
-
*
|
|
22
|
-
* Constructed via {@link Password.from}, which validates the input. The
|
|
23
|
-
* underlying string is only reachable through {@link Password.unwrap}; every
|
|
24
|
-
* other path (`toString`, `JSON.stringify`, `util.inspect`, template-literal
|
|
25
|
-
* interpolation) yields `[redacted]`. This makes accidental logging produce a
|
|
26
|
-
* harmless placeholder instead of leaking the secret.
|
|
27
|
-
*/
|
|
28
|
-
export class Password {
|
|
29
|
-
// See .from() for why this is private.
|
|
30
|
-
// eslint-disable-next-line no-restricted-syntax
|
|
31
|
-
constructor(value) {
|
|
32
|
-
_Password_value.set(this, void 0);
|
|
33
|
-
__classPrivateFieldSet(this, _Password_value, value, "f");
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Wrap a non-empty string as a {@link Password}.
|
|
37
|
-
*
|
|
38
|
-
* Matches the `@metamask/keyring-controller` convention: any non-empty
|
|
39
|
-
* string is acceptable; minimum-length policy is left to the keyring.
|
|
40
|
-
*
|
|
41
|
-
* @param value - The raw password string.
|
|
42
|
-
* @returns A redacting {@link Password} wrapper.
|
|
43
|
-
* @throws If `value` is empty.
|
|
44
|
-
*/
|
|
45
|
-
static from(value) {
|
|
46
|
-
if (value.length === 0) {
|
|
47
|
-
throw new Error('Password must be a non-empty string');
|
|
48
|
-
}
|
|
49
|
-
return new Password(value);
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Reveal the underlying password string. Call this only at trust boundaries
|
|
53
|
-
* (e.g. handing the value to the keyring or to a child-process env var).
|
|
54
|
-
*
|
|
55
|
-
* @returns The original password string.
|
|
56
|
-
*/
|
|
57
|
-
unwrap() {
|
|
58
|
-
return __classPrivateFieldGet(this, _Password_value, "f");
|
|
59
|
-
}
|
|
60
|
-
toString() {
|
|
61
|
-
return REDACTED;
|
|
62
|
-
}
|
|
63
|
-
toJSON() {
|
|
64
|
-
return REDACTED;
|
|
65
|
-
}
|
|
66
|
-
[(_Password_value = new WeakMap(), INSPECT_CUSTOM)]() {
|
|
67
|
-
return REDACTED;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Opaque wrapper around a BIP-39 secret recovery phrase.
|
|
72
|
-
*
|
|
73
|
-
* Constructed via {@link Srp.from}, which validates the word count
|
|
74
|
-
* (12/15/18/21/24) and that every word is present in the BIP-39 English
|
|
75
|
-
* wordlist. The underlying string is only reachable through {@link Srp.unwrap};
|
|
76
|
-
* every other path yields `[redacted]`.
|
|
77
|
-
*/
|
|
78
|
-
export class Srp {
|
|
79
|
-
// See .from() for why this is private.
|
|
80
|
-
// eslint-disable-next-line no-restricted-syntax
|
|
81
|
-
constructor(value) {
|
|
82
|
-
_Srp_value.set(this, void 0);
|
|
83
|
-
__classPrivateFieldSet(this, _Srp_value, value, "f");
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* Validate and wrap a BIP-39 mnemonic phrase.
|
|
87
|
-
*
|
|
88
|
-
* Whitespace is normalized (trimmed and collapsed) before validation so that
|
|
89
|
-
* copy-pasted phrases with accidental leading/trailing/extra spaces are
|
|
90
|
-
* accepted. Catching malformed input here (rather than letting it reach
|
|
91
|
-
* `KeyringController:createNewVaultAndRestore`) produces a clearer error.
|
|
92
|
-
*
|
|
93
|
-
* @param value - The raw mnemonic string.
|
|
94
|
-
* @returns A redacting {@link Srp} wrapper containing the normalized phrase.
|
|
95
|
-
* @throws If the word count is not one of 12/15/18/21/24, if any word is
|
|
96
|
-
* not present in the BIP-39 English wordlist, or if the checksum is invalid.
|
|
97
|
-
*/
|
|
98
|
-
static from(value) {
|
|
99
|
-
const words = value.trim().split(/\s+/u);
|
|
100
|
-
if (!VALID_SRP_WORD_COUNTS.includes(words.length)) {
|
|
101
|
-
throw new Error(`Secret recovery phrase must be 12, 15, 18, 21, or 24 words (got ${words.length})`);
|
|
102
|
-
}
|
|
103
|
-
for (const word of words) {
|
|
104
|
-
if (!WORDLIST_SET.has(word)) {
|
|
105
|
-
throw new Error('Secret recovery phrase contains a word not in the BIP-39 English wordlist');
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
const normalized = words.join(' ');
|
|
109
|
-
if (!validateMnemonic(normalized, wordlist)) {
|
|
110
|
-
throw new Error('Secret recovery phrase has an invalid checksum');
|
|
111
|
-
}
|
|
112
|
-
return new Srp(normalized);
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* Reveal the underlying mnemonic string. Call this only at trust boundaries.
|
|
116
|
-
*
|
|
117
|
-
* @returns The original mnemonic string.
|
|
118
|
-
*/
|
|
119
|
-
unwrap() {
|
|
120
|
-
return __classPrivateFieldGet(this, _Srp_value, "f");
|
|
121
|
-
}
|
|
122
|
-
toString() {
|
|
123
|
-
return REDACTED;
|
|
124
|
-
}
|
|
125
|
-
toJSON() {
|
|
126
|
-
return REDACTED;
|
|
127
|
-
}
|
|
128
|
-
[(_Srp_value = new WeakMap(), INSPECT_CUSTOM)]() {
|
|
129
|
-
return REDACTED;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
//# sourceMappingURL=secrets.mjs.map
|
|
@@ -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"]}
|