@cogcoin/client 1.1.5 → 1.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/README.md +1 -1
  2. package/dist/bitcoind/indexer-daemon.d.ts +3 -7
  3. package/dist/bitcoind/indexer-daemon.js +43 -158
  4. package/dist/bitcoind/managed-runtime/bitcoind-policy.d.ts +16 -0
  5. package/dist/bitcoind/managed-runtime/bitcoind-policy.js +177 -0
  6. package/dist/bitcoind/managed-runtime/indexer-policy.d.ts +34 -0
  7. package/dist/bitcoind/managed-runtime/indexer-policy.js +200 -0
  8. package/dist/bitcoind/managed-runtime/status.d.ts +11 -0
  9. package/dist/bitcoind/managed-runtime/status.js +59 -0
  10. package/dist/bitcoind/managed-runtime/types.d.ts +37 -0
  11. package/dist/bitcoind/managed-runtime/types.js +1 -0
  12. package/dist/bitcoind/service.d.ts +2 -7
  13. package/dist/bitcoind/service.js +46 -94
  14. package/dist/wallet/lifecycle/access.d.ts +5 -0
  15. package/dist/wallet/lifecycle/access.js +79 -0
  16. package/dist/wallet/lifecycle/context.d.ts +26 -0
  17. package/dist/wallet/lifecycle/context.js +58 -0
  18. package/dist/wallet/lifecycle/managed-core.d.ts +1 -9
  19. package/dist/wallet/lifecycle/managed-core.js +3 -63
  20. package/dist/wallet/lifecycle/repair-bitcoind.d.ts +10 -0
  21. package/dist/wallet/lifecycle/repair-bitcoind.js +142 -0
  22. package/dist/wallet/lifecycle/repair-indexer.d.ts +8 -0
  23. package/dist/wallet/lifecycle/repair-indexer.js +117 -0
  24. package/dist/wallet/lifecycle/repair.d.ts +2 -4
  25. package/dist/wallet/lifecycle/repair.js +77 -318
  26. package/dist/wallet/lifecycle/setup-prompts.d.ts +7 -0
  27. package/dist/wallet/lifecycle/setup-prompts.js +88 -0
  28. package/dist/wallet/lifecycle/setup-state.d.ts +26 -0
  29. package/dist/wallet/lifecycle/setup-state.js +159 -0
  30. package/dist/wallet/lifecycle/setup.d.ts +3 -4
  31. package/dist/wallet/lifecycle/setup.js +45 -351
  32. package/dist/wallet/lifecycle/types.d.ts +33 -2
  33. package/dist/wallet/read/context.js +13 -188
  34. package/package.json +1 -1
@@ -0,0 +1,159 @@
1
+ import { randomBytes } from "node:crypto";
2
+ import { withClaimedUninitializedManagedRuntime } from "../../bitcoind/service.js";
3
+ import { createInternalCoreWalletPassphrase, deriveWalletMaterialFromMnemonic, generateWalletMaterial, } from "../material.js";
4
+ import { clearLegacyWalletLockArtifacts } from "../managed-core-wallet.js";
5
+ import { clearWalletPendingInitializationState, loadWalletPendingInitializationStateOrNull, saveWalletPendingInitializationState, } from "../state/pending-init.js";
6
+ import { createWalletPendingInitSecretReference, createWalletRootId, createWalletSecretReference, } from "../state/provider.js";
7
+ import { saveWalletState } from "../state/storage.js";
8
+ import { importDescriptorIntoManagedCoreWallet, sanitizeWalletName } from "./managed-core.js";
9
+ function resolvePendingInitializationStoragePaths(paths) {
10
+ return {
11
+ primaryPath: paths.walletInitPendingPath,
12
+ backupPath: paths.walletInitPendingBackupPath,
13
+ };
14
+ }
15
+ export async function clearPendingInitialization(paths, provider) {
16
+ await clearWalletPendingInitializationState(resolvePendingInitializationStoragePaths(paths), {
17
+ provider,
18
+ secretReference: createWalletPendingInitSecretReference(paths.walletStateRoot),
19
+ });
20
+ }
21
+ export async function loadOrCreatePendingInitializationMaterial(options) {
22
+ try {
23
+ const loaded = await loadWalletPendingInitializationStateOrNull(resolvePendingInitializationStoragePaths(options.paths), {
24
+ provider: options.provider,
25
+ });
26
+ if (loaded !== null) {
27
+ return deriveWalletMaterialFromMnemonic(loaded.state.mnemonic.phrase);
28
+ }
29
+ }
30
+ catch {
31
+ await clearPendingInitialization(options.paths, options.provider);
32
+ }
33
+ const material = generateWalletMaterial();
34
+ const secretReference = createWalletPendingInitSecretReference(options.paths.walletStateRoot);
35
+ const pendingState = {
36
+ schemaVersion: 1,
37
+ createdAtUnixMs: options.nowUnixMs,
38
+ mnemonic: {
39
+ phrase: material.mnemonic.phrase,
40
+ language: material.mnemonic.language,
41
+ },
42
+ };
43
+ await options.provider.storeSecret(secretReference.keyId, randomBytes(32));
44
+ try {
45
+ await saveWalletPendingInitializationState(resolvePendingInitializationStoragePaths(options.paths), pendingState, {
46
+ provider: options.provider,
47
+ secretReference,
48
+ });
49
+ }
50
+ catch (error) {
51
+ await options.provider.deleteSecret(secretReference.keyId).catch(() => undefined);
52
+ throw error;
53
+ }
54
+ return material;
55
+ }
56
+ export function createInitialWalletState(options) {
57
+ return {
58
+ schemaVersion: 5,
59
+ stateRevision: 1,
60
+ lastWrittenAtUnixMs: options.nowUnixMs,
61
+ walletRootId: options.walletRootId,
62
+ network: "mainnet",
63
+ localScriptPubKeyHexes: [options.material.funding.scriptPubKeyHex],
64
+ mnemonic: {
65
+ phrase: options.material.mnemonic.phrase,
66
+ language: options.material.mnemonic.language,
67
+ },
68
+ keys: {
69
+ masterFingerprintHex: options.material.keys.masterFingerprintHex,
70
+ accountPath: options.material.keys.accountPath,
71
+ accountXprv: options.material.keys.accountXprv,
72
+ accountXpub: options.material.keys.accountXpub,
73
+ },
74
+ descriptor: {
75
+ privateExternal: options.material.descriptor.privateExternal,
76
+ publicExternal: options.material.descriptor.publicExternal,
77
+ checksum: options.material.descriptor.checksum,
78
+ rangeEnd: options.material.descriptor.rangeEnd,
79
+ safetyMargin: options.material.descriptor.safetyMargin,
80
+ },
81
+ funding: {
82
+ address: options.material.funding.address,
83
+ scriptPubKeyHex: options.material.funding.scriptPubKeyHex,
84
+ },
85
+ walletBirthTime: Math.floor(options.nowUnixMs / 1000),
86
+ managedCoreWallet: {
87
+ walletName: sanitizeWalletName(options.walletRootId),
88
+ internalPassphrase: options.internalCoreWalletPassphrase,
89
+ descriptorChecksum: null,
90
+ walletAddress: null,
91
+ walletScriptPubKeyHex: null,
92
+ proofStatus: "not-proven",
93
+ lastImportedAtUnixMs: null,
94
+ lastVerifiedAtUnixMs: null,
95
+ },
96
+ domains: [],
97
+ miningState: {
98
+ runMode: "stopped",
99
+ state: "idle",
100
+ pauseReason: null,
101
+ currentPublishState: "none",
102
+ currentDomain: null,
103
+ currentDomainId: null,
104
+ currentDomainIndex: null,
105
+ currentSenderScriptPubKeyHex: null,
106
+ currentTxid: null,
107
+ currentWtxid: null,
108
+ currentFeeRateSatVb: null,
109
+ currentAbsoluteFeeSats: null,
110
+ currentScore: null,
111
+ currentSentence: null,
112
+ currentEncodedSentenceBytesHex: null,
113
+ currentBip39WordIndices: null,
114
+ currentBlendSeedHex: null,
115
+ currentBlockTargetHeight: null,
116
+ currentReferencedBlockHashDisplay: null,
117
+ currentIntentFingerprintHex: null,
118
+ livePublishInMempool: null,
119
+ currentPublishDecision: null,
120
+ replacementCount: 0,
121
+ currentBlockFeeSpentSats: "0",
122
+ sessionFeeSpentSats: "0",
123
+ lifetimeFeeSpentSats: "0",
124
+ sharedMiningConflictOutpoint: null,
125
+ },
126
+ pendingMutations: [],
127
+ };
128
+ }
129
+ export async function persistInitializedWallet(options) {
130
+ const walletRootId = createWalletRootId();
131
+ const internalCoreWalletPassphrase = createInternalCoreWalletPassphrase();
132
+ const secretReference = createWalletSecretReference(walletRootId);
133
+ await options.provider.storeSecret(secretReference.keyId, randomBytes(32));
134
+ const initialState = createInitialWalletState({
135
+ walletRootId,
136
+ nowUnixMs: options.context.nowUnixMs,
137
+ material: options.material,
138
+ internalCoreWalletPassphrase,
139
+ });
140
+ const verifiedState = await withClaimedUninitializedManagedRuntime({
141
+ dataDir: options.context.dataDir,
142
+ walletRootId,
143
+ }, async () => {
144
+ await saveWalletState({
145
+ primaryPath: options.context.paths.walletStatePath,
146
+ backupPath: options.context.paths.walletStateBackupPath,
147
+ }, initialState, {
148
+ provider: options.provider,
149
+ secretReference,
150
+ });
151
+ return await importDescriptorIntoManagedCoreWallet(initialState, options.provider, options.context.paths, options.context.dataDir, options.context.nowUnixMs, options.context.attachService, options.context.rpcFactory);
152
+ });
153
+ await clearLegacyWalletLockArtifacts(options.context.paths.walletRuntimeRoot);
154
+ await clearPendingInitialization(options.context.paths, options.provider);
155
+ return {
156
+ walletRootId,
157
+ state: verifiedState,
158
+ };
159
+ }
@@ -1,4 +1,3 @@
1
- import { type WalletRuntimePaths } from "../runtime.js";
2
1
  import { type WalletSecretProvider } from "../state/provider.js";
3
2
  import type { WalletInitializationResult, WalletPrompter, WalletSetupDependencies } from "./types.js";
4
3
  export declare function initializeWallet(options: {
@@ -6,11 +5,11 @@ export declare function initializeWallet(options: {
6
5
  provider?: WalletSecretProvider;
7
6
  prompter: WalletPrompter;
8
7
  nowUnixMs?: number;
9
- paths?: WalletRuntimePaths;
8
+ paths?: import("../runtime.js").WalletRuntimePaths;
10
9
  } & WalletSetupDependencies): Promise<WalletInitializationResult>;
11
10
  export declare function showWalletMnemonic(options: {
12
11
  provider?: WalletSecretProvider;
13
12
  prompter: WalletPrompter;
14
13
  nowUnixMs?: number;
15
- paths?: WalletRuntimePaths;
16
- }): Promise<void>;
14
+ paths?: import("../runtime.js").WalletRuntimePaths;
15
+ } & WalletSetupDependencies): Promise<void>;
@@ -1,306 +1,24 @@
1
- import { randomBytes } from "node:crypto";
2
- import { access, constants } from "node:fs/promises";
3
- import { withClaimedUninitializedManagedRuntime } from "../../bitcoind/service.js";
4
- import { acquireFileLock } from "../fs/lock.js";
5
- import { createInternalCoreWalletPassphrase, createMnemonicConfirmationChallenge, deriveWalletMaterialFromMnemonic, generateWalletMaterial, isEnglishMnemonicWord, validateEnglishMnemonic, } from "../material.js";
6
- import { renderWalletMnemonicRevealArt } from "../mnemonic-art.js";
7
- import { resolveWalletRuntimePathsForTesting } from "../runtime.js";
8
- import { clearWalletPendingInitializationState, loadWalletPendingInitializationStateOrNull, saveWalletPendingInitializationState, } from "../state/pending-init.js";
9
- import { createDefaultWalletSecretProvider, createWalletPendingInitSecretReference, createWalletRootId, createWalletSecretReference, ensureClientPasswordConfigured, withInteractiveWalletSecretProvider, } from "../state/provider.js";
10
- import { clearLegacyWalletLockArtifacts, } from "../managed-core-wallet.js";
11
- import { loadWalletState, saveWalletState } from "../state/storage.js";
12
- import { importDescriptorIntoManagedCoreWallet, normalizeLoadedWalletStateIfNeeded, sanitizeWalletName, } from "./managed-core.js";
13
- function resolvePendingInitializationStoragePaths(paths) {
14
- return {
15
- primaryPath: paths.walletInitPendingPath,
16
- backupPath: paths.walletInitPendingBackupPath,
17
- };
18
- }
19
- async function pathExists(path) {
20
- try {
21
- await access(path, constants.F_OK);
22
- return true;
23
- }
24
- catch {
25
- return false;
26
- }
27
- }
28
- async function clearPendingInitialization(paths, provider) {
29
- await clearWalletPendingInitializationState(resolvePendingInitializationStoragePaths(paths), {
30
- provider,
31
- secretReference: createWalletPendingInitSecretReference(paths.walletStateRoot),
32
- });
33
- }
34
- async function loadOrCreatePendingInitializationMaterial(options) {
35
- try {
36
- const loaded = await loadWalletPendingInitializationStateOrNull(resolvePendingInitializationStoragePaths(options.paths), {
37
- provider: options.provider,
38
- });
39
- if (loaded !== null) {
40
- return deriveWalletMaterialFromMnemonic(loaded.state.mnemonic.phrase);
41
- }
42
- }
43
- catch {
44
- await clearPendingInitialization(options.paths, options.provider);
45
- }
46
- const material = generateWalletMaterial();
47
- const secretReference = createWalletPendingInitSecretReference(options.paths.walletStateRoot);
48
- const pendingState = {
49
- schemaVersion: 1,
50
- createdAtUnixMs: options.nowUnixMs,
51
- mnemonic: {
52
- phrase: material.mnemonic.phrase,
53
- language: material.mnemonic.language,
54
- },
55
- };
56
- await options.provider.storeSecret(secretReference.keyId, randomBytes(32));
57
- try {
58
- await saveWalletPendingInitializationState(resolvePendingInitializationStoragePaths(options.paths), pendingState, {
59
- provider: options.provider,
60
- secretReference,
61
- });
62
- }
63
- catch (error) {
64
- await options.provider.deleteSecret(secretReference.keyId).catch(() => undefined);
65
- throw error;
66
- }
67
- return material;
68
- }
69
- function createInitialWalletState(options) {
70
- return {
71
- schemaVersion: 5,
72
- stateRevision: 1,
73
- lastWrittenAtUnixMs: options.nowUnixMs,
74
- walletRootId: options.walletRootId,
75
- network: "mainnet",
76
- localScriptPubKeyHexes: [options.material.funding.scriptPubKeyHex],
77
- mnemonic: {
78
- phrase: options.material.mnemonic.phrase,
79
- language: options.material.mnemonic.language,
80
- },
81
- keys: {
82
- masterFingerprintHex: options.material.keys.masterFingerprintHex,
83
- accountPath: options.material.keys.accountPath,
84
- accountXprv: options.material.keys.accountXprv,
85
- accountXpub: options.material.keys.accountXpub,
86
- },
87
- descriptor: {
88
- privateExternal: options.material.descriptor.privateExternal,
89
- publicExternal: options.material.descriptor.publicExternal,
90
- checksum: options.material.descriptor.checksum,
91
- rangeEnd: options.material.descriptor.rangeEnd,
92
- safetyMargin: options.material.descriptor.safetyMargin,
93
- },
94
- funding: {
95
- address: options.material.funding.address,
96
- scriptPubKeyHex: options.material.funding.scriptPubKeyHex,
97
- },
98
- walletBirthTime: Math.floor(options.nowUnixMs / 1000),
99
- managedCoreWallet: {
100
- walletName: sanitizeWalletName(options.walletRootId),
101
- internalPassphrase: options.internalCoreWalletPassphrase,
102
- descriptorChecksum: null,
103
- walletAddress: null,
104
- walletScriptPubKeyHex: null,
105
- proofStatus: "not-proven",
106
- lastImportedAtUnixMs: null,
107
- lastVerifiedAtUnixMs: null,
108
- },
109
- domains: [],
110
- miningState: {
111
- runMode: "stopped",
112
- state: "idle",
113
- pauseReason: null,
114
- currentPublishState: "none",
115
- currentDomain: null,
116
- currentDomainId: null,
117
- currentDomainIndex: null,
118
- currentSenderScriptPubKeyHex: null,
119
- currentTxid: null,
120
- currentWtxid: null,
121
- currentFeeRateSatVb: null,
122
- currentAbsoluteFeeSats: null,
123
- currentScore: null,
124
- currentSentence: null,
125
- currentEncodedSentenceBytesHex: null,
126
- currentBip39WordIndices: null,
127
- currentBlendSeedHex: null,
128
- currentBlockTargetHeight: null,
129
- currentReferencedBlockHashDisplay: null,
130
- currentIntentFingerprintHex: null,
131
- livePublishInMempool: null,
132
- currentPublishDecision: null,
133
- replacementCount: 0,
134
- currentBlockFeeSpentSats: "0",
135
- sessionFeeSpentSats: "0",
136
- lifetimeFeeSpentSats: "0",
137
- sharedMiningConflictOutpoint: null,
138
- },
139
- pendingMutations: [],
140
- };
141
- }
142
- async function promptRequiredValue(prompter, message) {
143
- const value = (await prompter.prompt(message)).trim();
144
- if (value === "") {
145
- throw new Error("wallet_prompt_value_required");
146
- }
147
- return value;
148
- }
149
- async function promptForRestoreMnemonic(prompter) {
150
- const words = [];
151
- for (let index = 0; index < 24; index += 1) {
152
- const word = (await promptRequiredValue(prompter, `Word ${index + 1} of 24: `)).toLowerCase();
153
- if (!isEnglishMnemonicWord(word)) {
154
- throw new Error("wallet_restore_mnemonic_invalid");
155
- }
156
- words.push(word);
157
- }
158
- const phrase = words.join(" ");
159
- if (!validateEnglishMnemonic(phrase)) {
160
- throw new Error("wallet_restore_mnemonic_invalid");
161
- }
162
- return phrase;
163
- }
164
- async function promptForInitializationMode(prompter) {
165
- if (prompter.selectOption != null) {
166
- return await prompter.selectOption({
167
- message: "How should Cogcoin set up this wallet?",
168
- options: [
169
- {
170
- label: "Create new wallet",
171
- description: "Generate a fresh 24-word recovery phrase.",
172
- value: "generated",
173
- },
174
- {
175
- label: "Restore existing wallet",
176
- description: "Enter an existing 24-word recovery phrase.",
177
- value: "restored",
178
- },
179
- ],
180
- initialValue: "generated",
181
- });
182
- }
183
- prompter.writeLine("How should Cogcoin set up this wallet?");
184
- prompter.writeLine("1. Create new wallet");
185
- prompter.writeLine("2. Restore existing wallet");
186
- while (true) {
187
- const answer = (await prompter.prompt("Choice [1-2]: ")).trim();
188
- if (answer === "1") {
189
- return "generated";
190
- }
191
- if (answer === "2") {
192
- return "restored";
193
- }
194
- prompter.writeLine("Enter 1 or 2.");
195
- }
196
- }
197
- async function confirmTypedAcknowledgement(prompter, expected, message, errorCode = "wallet_typed_confirmation_rejected") {
198
- const answer = (await prompter.prompt(message)).trim();
199
- if (answer !== expected) {
200
- throw new Error(errorCode);
201
- }
202
- }
203
- function isWalletSecretAccessError(error) {
204
- const message = error instanceof Error ? error.message : String(error);
205
- return message.startsWith("wallet_secret_missing_")
206
- || message.startsWith("wallet_secret_provider_");
207
- }
208
- async function persistInitializedWallet(options) {
209
- const walletRootId = createWalletRootId();
210
- const internalCoreWalletPassphrase = createInternalCoreWalletPassphrase();
211
- const secretReference = createWalletSecretReference(walletRootId);
212
- await options.provider.storeSecret(secretReference.keyId, randomBytes(32));
213
- const initialState = createInitialWalletState({
214
- walletRootId,
215
- nowUnixMs: options.nowUnixMs,
216
- material: options.material,
217
- internalCoreWalletPassphrase,
218
- });
219
- const verifiedState = await withClaimedUninitializedManagedRuntime({
220
- dataDir: options.dataDir,
221
- walletRootId,
222
- }, async () => {
223
- await saveWalletState({
224
- primaryPath: options.paths.walletStatePath,
225
- backupPath: options.paths.walletStateBackupPath,
226
- }, initialState, {
227
- provider: options.provider,
228
- secretReference,
229
- });
230
- return importDescriptorIntoManagedCoreWallet(initialState, options.provider, options.paths, options.dataDir, options.nowUnixMs, options.attachService, options.rpcFactory);
231
- });
232
- await clearLegacyWalletLockArtifacts(options.paths.walletRuntimeRoot);
233
- await clearPendingInitialization(options.paths, options.provider);
234
- return {
235
- walletRootId,
236
- state: verifiedState,
237
- };
238
- }
239
- function writeMnemonicReveal(prompter, phrase, introLines) {
240
- const words = phrase.trim().split(/\s+/);
241
- for (const line of introLines) {
242
- prompter.writeLine(line);
243
- }
244
- for (const line of renderWalletMnemonicRevealArt(words)) {
245
- prompter.writeLine(line);
246
- }
247
- prompter.writeLine("Single-line copy:");
248
- prompter.writeLine(phrase);
249
- }
250
- async function confirmMnemonic(prompter, words) {
251
- const challenge = createMnemonicConfirmationChallenge(words);
252
- for (const entry of challenge) {
253
- const answer = (await prompter.prompt(`Confirm word #${entry.index + 1}: `)).trim().toLowerCase();
254
- if (answer !== entry.word) {
255
- throw new Error(`wallet_init_confirmation_failed_word_${entry.index + 1}`);
256
- }
257
- }
258
- }
259
- async function loadWalletStateForAccess(options = {}) {
260
- const provider = options.provider ?? createDefaultWalletSecretProvider();
261
- const nowUnixMs = options.nowUnixMs ?? Date.now();
262
- const paths = options.paths ?? resolveWalletRuntimePathsForTesting();
263
- const loaded = await loadWalletState({
264
- primaryPath: paths.walletStatePath,
265
- backupPath: paths.walletStateBackupPath,
266
- }, {
267
- provider,
268
- });
269
- return normalizeLoadedWalletStateIfNeeded({
270
- provider,
271
- state: loaded.state,
272
- source: loaded.source,
273
- nowUnixMs,
274
- paths,
275
- dataDir: options.dataDir,
276
- attachService: options.attachService,
277
- rpcFactory: options.rpcFactory,
278
- });
279
- }
1
+ import { deriveWalletMaterialFromMnemonic } from "../material.js";
2
+ import { ensureClientPasswordConfigured, withInteractiveWalletSecretProvider, } from "../state/provider.js";
3
+ import { loadWalletStateForAccess, mapWalletReadAccessError } from "./access.js";
4
+ import { acquireWalletControlLock, resolveWalletManagedCoreContext, resolveWalletSetupContext, walletStateExists, } from "./context.js";
5
+ import { clearSensitiveDisplay, confirmMnemonic, confirmTypedAcknowledgement, promptForInitializationMode, promptForRestoreMnemonic, writeMnemonicReveal, } from "./setup-prompts.js";
6
+ import { clearPendingInitialization, loadOrCreatePendingInitializationMaterial, persistInitializedWallet, } from "./setup-state.js";
280
7
  export async function initializeWallet(options) {
281
- if (!options.prompter.isInteractive) {
8
+ const context = resolveWalletSetupContext(options);
9
+ if (!context.prompter.isInteractive) {
282
10
  throw new Error("wallet_init_requires_tty");
283
11
  }
284
- const provider = options.provider ?? createDefaultWalletSecretProvider();
285
- const interactiveProvider = withInteractiveWalletSecretProvider(provider, options.prompter);
286
- const nowUnixMs = options.nowUnixMs ?? Date.now();
287
- const paths = options.paths ?? resolveWalletRuntimePathsForTesting();
288
- const controlLock = await acquireFileLock(paths.walletControlLockPath, {
289
- purpose: "wallet-init",
290
- walletRootId: null,
291
- });
12
+ const interactiveProvider = withInteractiveWalletSecretProvider(context.provider, context.prompter);
13
+ const controlLock = await acquireWalletControlLock(context.paths, "wallet-init");
292
14
  try {
293
- const passwordAction = await ensureClientPasswordConfigured(provider, options.prompter);
294
- const hasWalletState = await pathExists(paths.walletStatePath) || await pathExists(paths.walletStateBackupPath);
295
- if (hasWalletState) {
296
- await clearPendingInitialization(paths, interactiveProvider);
15
+ const passwordAction = await ensureClientPasswordConfigured(context.provider, context.prompter);
16
+ if (await walletStateExists(context.paths)) {
17
+ await clearPendingInitialization(context.paths, interactiveProvider);
297
18
  const loaded = await loadWalletStateForAccess({
19
+ ...context,
298
20
  provider: interactiveProvider,
299
- nowUnixMs,
300
- paths,
301
- dataDir: options.dataDir,
302
- attachService: options.attachService,
303
- rpcFactory: options.rpcFactory,
21
+ dataDir: context.dataDir,
304
22
  });
305
23
  return {
306
24
  setupMode: "existing",
@@ -311,56 +29,42 @@ export async function initializeWallet(options) {
311
29
  state: loaded.state,
312
30
  };
313
31
  }
314
- const setupMode = await promptForInitializationMode(options.prompter);
32
+ const setupMode = await promptForInitializationMode(context.prompter);
315
33
  let material;
316
34
  if (setupMode === "generated") {
317
35
  material = await loadOrCreatePendingInitializationMaterial({
318
36
  provider: interactiveProvider,
319
- paths,
320
- nowUnixMs,
37
+ paths: context.paths,
38
+ nowUnixMs: context.nowUnixMs,
321
39
  });
322
- let mnemonicRevealed = false;
323
- writeMnemonicReveal(options.prompter, material.mnemonic.phrase, [
40
+ writeMnemonicReveal(context.prompter, material.mnemonic.phrase, [
324
41
  "Cogcoin Wallet Initialization",
325
42
  "Write down this 24-word recovery phrase.",
326
43
  "The same phrase will be shown again until confirmation succeeds:",
327
44
  "",
328
45
  ]);
329
- mnemonicRevealed = true;
330
46
  try {
331
- await confirmMnemonic(options.prompter, material.mnemonic.words);
47
+ await confirmMnemonic(context.prompter, material.mnemonic.words);
332
48
  }
333
49
  finally {
334
- if (mnemonicRevealed) {
335
- await Promise.resolve()
336
- .then(() => options.prompter.clearSensitiveDisplay?.("mnemonic-reveal"))
337
- .catch(() => undefined);
338
- }
50
+ await clearSensitiveDisplay(context.prompter, "mnemonic-reveal");
339
51
  }
340
52
  }
341
53
  else {
342
- let promptPhaseStarted = false;
343
54
  let mnemonicPhrase;
344
55
  try {
345
- promptPhaseStarted = true;
346
- mnemonicPhrase = await promptForRestoreMnemonic(options.prompter);
56
+ mnemonicPhrase = await promptForRestoreMnemonic(context.prompter);
347
57
  }
348
58
  finally {
349
- if (promptPhaseStarted) {
350
- await options.prompter.clearSensitiveDisplay?.("restore-mnemonic-entry");
351
- }
59
+ await clearSensitiveDisplay(context.prompter, "restore-mnemonic-entry");
352
60
  }
353
- await clearPendingInitialization(paths, interactiveProvider);
61
+ await clearPendingInitialization(context.paths, interactiveProvider);
354
62
  material = deriveWalletMaterialFromMnemonic(mnemonicPhrase);
355
63
  }
356
64
  const initialized = await persistInitializedWallet({
357
- dataDir: options.dataDir,
65
+ context,
358
66
  provider: interactiveProvider,
359
67
  material,
360
- nowUnixMs,
361
- paths,
362
- attachService: options.attachService,
363
- rpcFactory: options.rpcFactory,
364
68
  });
365
69
  return {
366
70
  setupMode,
@@ -376,52 +80,42 @@ export async function initializeWallet(options) {
376
80
  }
377
81
  }
378
82
  export async function showWalletMnemonic(options) {
379
- if (!options.prompter.isInteractive) {
83
+ const context = {
84
+ ...resolveWalletManagedCoreContext({
85
+ provider: options.provider,
86
+ nowUnixMs: options.nowUnixMs,
87
+ paths: options.paths,
88
+ attachService: options.attachService,
89
+ rpcFactory: options.rpcFactory,
90
+ }),
91
+ prompter: options.prompter,
92
+ };
93
+ if (!context.prompter.isInteractive) {
380
94
  throw new Error("wallet_show_mnemonic_requires_tty");
381
95
  }
382
- const provider = options.provider ?? createDefaultWalletSecretProvider();
383
- const interactiveProvider = withInteractiveWalletSecretProvider(provider, options.prompter);
384
- const nowUnixMs = options.nowUnixMs ?? Date.now();
385
- const paths = options.paths ?? resolveWalletRuntimePathsForTesting();
386
- const controlLock = await acquireFileLock(paths.walletControlLockPath, {
387
- purpose: "wallet-show-mnemonic",
388
- walletRootId: null,
389
- });
96
+ const interactiveProvider = withInteractiveWalletSecretProvider(context.provider, context.prompter);
97
+ const controlLock = await acquireWalletControlLock(context.paths, "wallet-show-mnemonic");
390
98
  try {
391
- const [hasPrimaryStateFile, hasBackupStateFile] = await Promise.all([
392
- pathExists(paths.walletStatePath),
393
- pathExists(paths.walletStateBackupPath),
394
- ]);
395
- if (!hasPrimaryStateFile && !hasBackupStateFile) {
99
+ if (!await walletStateExists(context.paths)) {
396
100
  throw new Error("wallet_uninitialized");
397
101
  }
398
102
  const loaded = await loadWalletStateForAccess({
103
+ ...context,
399
104
  provider: interactiveProvider,
400
- nowUnixMs,
401
- paths,
402
105
  }).catch((error) => {
403
- if (isWalletSecretAccessError(error)) {
404
- throw new Error("wallet_secret_provider_unavailable");
405
- }
406
- throw new Error("local-state-corrupt");
106
+ throw mapWalletReadAccessError(error);
407
107
  });
408
- await confirmTypedAcknowledgement(options.prompter, "show mnemonic", "Type \"show mnemonic\" to continue: ", "wallet_show_mnemonic_typed_ack_required");
409
- let mnemonicRevealed = false;
410
- writeMnemonicReveal(options.prompter, loaded.state.mnemonic.phrase, [
108
+ await confirmTypedAcknowledgement(context.prompter, "show mnemonic", "Type \"show mnemonic\" to continue: ", "wallet_show_mnemonic_typed_ack_required");
109
+ writeMnemonicReveal(context.prompter, loaded.state.mnemonic.phrase, [
411
110
  "Cogcoin Wallet Recovery Phrase",
412
111
  "This 24-word recovery phrase controls the wallet.",
413
112
  "",
414
113
  ]);
415
- mnemonicRevealed = true;
416
114
  try {
417
- await options.prompter.prompt("Press Enter to clear the recovery phrase from the screen: ");
115
+ await context.prompter.prompt("Press Enter to clear the recovery phrase from the screen: ");
418
116
  }
419
117
  finally {
420
- if (mnemonicRevealed) {
421
- await Promise.resolve()
422
- .then(() => options.prompter.clearSensitiveDisplay?.("mnemonic-reveal"))
423
- .catch(() => undefined);
424
- }
118
+ await clearSensitiveDisplay(context.prompter, "mnemonic-reveal");
425
119
  }
426
120
  }
427
121
  finally {