@cogcoin/client 1.1.5 → 1.1.7
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/README.md +2 -2
- package/dist/bitcoind/indexer-daemon.d.ts +3 -7
- package/dist/bitcoind/indexer-daemon.js +39 -204
- package/dist/bitcoind/managed-runtime/bitcoind-policy.d.ts +16 -0
- package/dist/bitcoind/managed-runtime/bitcoind-policy.js +177 -0
- package/dist/bitcoind/managed-runtime/bitcoind-runtime.d.ts +20 -0
- package/dist/bitcoind/managed-runtime/bitcoind-runtime.js +74 -0
- package/dist/bitcoind/managed-runtime/bitcoind-status.d.ts +11 -0
- package/dist/bitcoind/managed-runtime/bitcoind-status.js +44 -0
- package/dist/bitcoind/managed-runtime/indexer-policy.d.ts +34 -0
- package/dist/bitcoind/managed-runtime/indexer-policy.js +200 -0
- package/dist/bitcoind/managed-runtime/indexer-runtime.d.ts +15 -0
- package/dist/bitcoind/managed-runtime/indexer-runtime.js +82 -0
- package/dist/bitcoind/managed-runtime/status.d.ts +11 -0
- package/dist/bitcoind/managed-runtime/status.js +59 -0
- package/dist/bitcoind/managed-runtime/types.d.ts +77 -0
- package/dist/bitcoind/node.d.ts +2 -2
- package/dist/bitcoind/node.js +2 -2
- package/dist/bitcoind/rpc.d.ts +2 -1
- package/dist/bitcoind/rpc.js +53 -3
- package/dist/bitcoind/service.d.ts +2 -7
- package/dist/bitcoind/service.js +79 -207
- package/dist/cli/command-registry.d.ts +1 -1
- package/dist/cli/command-registry.js +2 -64
- package/dist/cli/commands/client-admin.js +3 -18
- package/dist/cli/commands/mining-runtime.js +4 -60
- package/dist/cli/commands/wallet-admin.js +6 -6
- package/dist/cli/context.js +1 -3
- package/dist/cli/mining-json.d.ts +1 -22
- package/dist/cli/mining-json.js +0 -23
- package/dist/cli/output.js +16 -2
- package/dist/cli/parse.js +0 -2
- package/dist/cli/preview-json.d.ts +1 -22
- package/dist/cli/preview-json.js +0 -19
- package/dist/cli/types.d.ts +1 -3
- package/dist/cli/wallet-format.js +1 -1
- package/dist/cli/workflow-hints.d.ts +1 -2
- package/dist/cli/workflow-hints.js +5 -8
- package/dist/wallet/lifecycle/access.d.ts +5 -0
- package/dist/wallet/lifecycle/access.js +79 -0
- package/dist/wallet/lifecycle/context.d.ts +26 -0
- package/dist/wallet/lifecycle/context.js +57 -0
- package/dist/wallet/lifecycle/managed-core.d.ts +1 -9
- package/dist/wallet/lifecycle/managed-core.js +3 -63
- package/dist/wallet/lifecycle/repair-bitcoind.d.ts +10 -0
- package/dist/wallet/lifecycle/repair-bitcoind.js +142 -0
- package/dist/wallet/lifecycle/repair-indexer.d.ts +8 -0
- package/dist/wallet/lifecycle/repair-indexer.js +117 -0
- package/dist/wallet/lifecycle/repair-mining.d.ts +1 -5
- package/dist/wallet/lifecycle/repair-mining.js +5 -39
- package/dist/wallet/lifecycle/repair.d.ts +2 -4
- package/dist/wallet/lifecycle/repair.js +74 -318
- package/dist/wallet/lifecycle/setup-prompts.d.ts +7 -0
- package/dist/wallet/lifecycle/setup-prompts.js +88 -0
- package/dist/wallet/lifecycle/setup-state.d.ts +26 -0
- package/dist/wallet/lifecycle/setup-state.js +159 -0
- package/dist/wallet/lifecycle/setup.d.ts +3 -4
- package/dist/wallet/lifecycle/setup.js +47 -351
- package/dist/wallet/lifecycle/types.d.ts +33 -5
- package/dist/wallet/managed-core-wallet.d.ts +2 -0
- package/dist/wallet/managed-core-wallet.js +27 -1
- package/dist/wallet/mining/candidate.d.ts +1 -0
- package/dist/wallet/mining/candidate.js +38 -6
- package/dist/wallet/mining/competitiveness.d.ts +1 -0
- package/dist/wallet/mining/competitiveness.js +6 -0
- package/dist/wallet/mining/cycle.d.ts +2 -0
- package/dist/wallet/mining/cycle.js +14 -4
- package/dist/wallet/mining/engine-types.d.ts +1 -0
- package/dist/wallet/mining/index.d.ts +1 -1
- package/dist/wallet/mining/index.js +1 -1
- package/dist/wallet/mining/publish.d.ts +3 -0
- package/dist/wallet/mining/publish.js +78 -6
- package/dist/wallet/mining/runner.d.ts +0 -32
- package/dist/wallet/mining/runner.js +59 -104
- package/dist/wallet/mining/stop.d.ts +7 -0
- package/dist/wallet/mining/stop.js +23 -0
- package/dist/wallet/mining/supervisor.d.ts +2 -36
- package/dist/wallet/mining/supervisor.js +139 -246
- package/dist/wallet/read/context.d.ts +1 -5
- package/dist/wallet/read/context.js +20 -379
- package/dist/wallet/read/managed-services.d.ts +33 -0
- package/dist/wallet/read/managed-services.js +222 -0
- package/dist/wallet/state/client-password/bootstrap.d.ts +2 -0
- package/dist/wallet/state/client-password/bootstrap.js +3 -0
- package/dist/wallet/state/client-password/context.d.ts +10 -0
- package/dist/wallet/state/client-password/context.js +46 -0
- package/dist/wallet/state/client-password/crypto.d.ts +34 -0
- package/dist/wallet/state/client-password/crypto.js +117 -0
- package/dist/wallet/state/client-password/files.d.ts +10 -0
- package/dist/wallet/state/client-password/files.js +109 -0
- package/dist/wallet/state/client-password/legacy-cleanup.d.ts +11 -0
- package/dist/wallet/state/client-password/legacy-cleanup.js +338 -0
- package/dist/wallet/state/client-password/messages.d.ts +3 -0
- package/dist/wallet/state/client-password/messages.js +9 -0
- package/dist/wallet/state/client-password/migration.d.ts +4 -0
- package/dist/wallet/state/client-password/migration.js +32 -0
- package/dist/wallet/state/client-password/prompts.d.ts +12 -0
- package/dist/wallet/state/client-password/prompts.js +79 -0
- package/dist/wallet/state/client-password/protected-secrets.d.ts +13 -0
- package/dist/wallet/state/client-password/protected-secrets.js +90 -0
- package/dist/wallet/state/client-password/readiness.d.ts +4 -0
- package/dist/wallet/state/client-password/readiness.js +48 -0
- package/dist/wallet/state/client-password/references.d.ts +1 -0
- package/dist/wallet/state/client-password/references.js +56 -0
- package/dist/wallet/state/client-password/rotation.d.ts +6 -0
- package/dist/wallet/state/client-password/rotation.js +98 -0
- package/dist/wallet/state/client-password/session-policy.d.ts +6 -0
- package/dist/wallet/state/client-password/session-policy.js +28 -0
- package/dist/wallet/state/client-password/session.d.ts +19 -0
- package/dist/wallet/state/client-password/session.js +170 -0
- package/dist/wallet/state/client-password/setup.d.ts +8 -0
- package/dist/wallet/state/client-password/setup.js +49 -0
- package/dist/wallet/state/client-password/types.d.ts +82 -0
- package/dist/wallet/state/client-password/types.js +5 -0
- package/dist/wallet/state/client-password.d.ts +7 -38
- package/dist/wallet/state/client-password.js +52 -937
- package/dist/wallet/tx/anchor.js +123 -216
- package/dist/wallet/tx/cog.js +294 -489
- package/dist/wallet/tx/common.d.ts +2 -0
- package/dist/wallet/tx/common.js +2 -0
- package/dist/wallet/tx/domain-admin.js +111 -220
- package/dist/wallet/tx/domain-market.js +401 -681
- package/dist/wallet/tx/executor.d.ts +176 -0
- package/dist/wallet/tx/executor.js +302 -0
- package/dist/wallet/tx/field.js +109 -215
- package/dist/wallet/tx/register.js +158 -269
- package/dist/wallet/tx/reputation.js +120 -227
- package/package.json +1 -1
- package/dist/wallet/mining/worker-main.js +0 -17
- package/dist/wallet/state/client-password-agent.d.ts +0 -1
- package/dist/wallet/state/client-password-agent.js +0 -211
- /package/dist/{wallet/mining/worker-main.d.ts → bitcoind/managed-runtime/types.js} +0 -0
|
@@ -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,26 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
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 { bindClientPasswordPromptSessionPolicy } from "../state/client-password/session-policy.js";
|
|
4
|
+
import { loadWalletStateForAccess, mapWalletReadAccessError } from "./access.js";
|
|
5
|
+
import { acquireWalletControlLock, resolveWalletManagedCoreContext, resolveWalletSetupContext, walletStateExists, } from "./context.js";
|
|
6
|
+
import { clearSensitiveDisplay, confirmMnemonic, confirmTypedAcknowledgement, promptForInitializationMode, promptForRestoreMnemonic, writeMnemonicReveal, } from "./setup-prompts.js";
|
|
7
|
+
import { clearPendingInitialization, loadOrCreatePendingInitializationMaterial, persistInitializedWallet, } from "./setup-state.js";
|
|
280
8
|
export async function initializeWallet(options) {
|
|
281
|
-
|
|
9
|
+
const context = resolveWalletSetupContext(options);
|
|
10
|
+
if (!context.prompter.isInteractive) {
|
|
282
11
|
throw new Error("wallet_init_requires_tty");
|
|
283
12
|
}
|
|
284
|
-
const
|
|
285
|
-
const interactiveProvider = withInteractiveWalletSecretProvider(provider,
|
|
286
|
-
const
|
|
287
|
-
const paths = options.paths ?? resolveWalletRuntimePathsForTesting();
|
|
288
|
-
const controlLock = await acquireFileLock(paths.walletControlLockPath, {
|
|
289
|
-
purpose: "wallet-init",
|
|
290
|
-
walletRootId: null,
|
|
291
|
-
});
|
|
13
|
+
const initPrompter = bindClientPasswordPromptSessionPolicy(context.prompter, "init-24h");
|
|
14
|
+
const interactiveProvider = withInteractiveWalletSecretProvider(context.provider, initPrompter);
|
|
15
|
+
const controlLock = await acquireWalletControlLock(context.paths, "wallet-init");
|
|
292
16
|
try {
|
|
293
|
-
const passwordAction = await ensureClientPasswordConfigured(provider,
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
await clearPendingInitialization(paths, interactiveProvider);
|
|
17
|
+
const passwordAction = await ensureClientPasswordConfigured(context.provider, initPrompter);
|
|
18
|
+
if (await walletStateExists(context.paths)) {
|
|
19
|
+
await clearPendingInitialization(context.paths, interactiveProvider);
|
|
297
20
|
const loaded = await loadWalletStateForAccess({
|
|
21
|
+
...context,
|
|
298
22
|
provider: interactiveProvider,
|
|
299
|
-
|
|
300
|
-
paths,
|
|
301
|
-
dataDir: options.dataDir,
|
|
302
|
-
attachService: options.attachService,
|
|
303
|
-
rpcFactory: options.rpcFactory,
|
|
23
|
+
dataDir: context.dataDir,
|
|
304
24
|
});
|
|
305
25
|
return {
|
|
306
26
|
setupMode: "existing",
|
|
@@ -311,56 +31,42 @@ export async function initializeWallet(options) {
|
|
|
311
31
|
state: loaded.state,
|
|
312
32
|
};
|
|
313
33
|
}
|
|
314
|
-
const setupMode = await promptForInitializationMode(
|
|
34
|
+
const setupMode = await promptForInitializationMode(initPrompter);
|
|
315
35
|
let material;
|
|
316
36
|
if (setupMode === "generated") {
|
|
317
37
|
material = await loadOrCreatePendingInitializationMaterial({
|
|
318
38
|
provider: interactiveProvider,
|
|
319
|
-
paths,
|
|
320
|
-
nowUnixMs,
|
|
39
|
+
paths: context.paths,
|
|
40
|
+
nowUnixMs: context.nowUnixMs,
|
|
321
41
|
});
|
|
322
|
-
|
|
323
|
-
writeMnemonicReveal(options.prompter, material.mnemonic.phrase, [
|
|
42
|
+
writeMnemonicReveal(initPrompter, material.mnemonic.phrase, [
|
|
324
43
|
"Cogcoin Wallet Initialization",
|
|
325
44
|
"Write down this 24-word recovery phrase.",
|
|
326
45
|
"The same phrase will be shown again until confirmation succeeds:",
|
|
327
46
|
"",
|
|
328
47
|
]);
|
|
329
|
-
mnemonicRevealed = true;
|
|
330
48
|
try {
|
|
331
|
-
await confirmMnemonic(
|
|
49
|
+
await confirmMnemonic(initPrompter, material.mnemonic.words);
|
|
332
50
|
}
|
|
333
51
|
finally {
|
|
334
|
-
|
|
335
|
-
await Promise.resolve()
|
|
336
|
-
.then(() => options.prompter.clearSensitiveDisplay?.("mnemonic-reveal"))
|
|
337
|
-
.catch(() => undefined);
|
|
338
|
-
}
|
|
52
|
+
await clearSensitiveDisplay(initPrompter, "mnemonic-reveal");
|
|
339
53
|
}
|
|
340
54
|
}
|
|
341
55
|
else {
|
|
342
|
-
let promptPhaseStarted = false;
|
|
343
56
|
let mnemonicPhrase;
|
|
344
57
|
try {
|
|
345
|
-
|
|
346
|
-
mnemonicPhrase = await promptForRestoreMnemonic(options.prompter);
|
|
58
|
+
mnemonicPhrase = await promptForRestoreMnemonic(initPrompter);
|
|
347
59
|
}
|
|
348
60
|
finally {
|
|
349
|
-
|
|
350
|
-
await options.prompter.clearSensitiveDisplay?.("restore-mnemonic-entry");
|
|
351
|
-
}
|
|
61
|
+
await clearSensitiveDisplay(initPrompter, "restore-mnemonic-entry");
|
|
352
62
|
}
|
|
353
|
-
await clearPendingInitialization(paths, interactiveProvider);
|
|
63
|
+
await clearPendingInitialization(context.paths, interactiveProvider);
|
|
354
64
|
material = deriveWalletMaterialFromMnemonic(mnemonicPhrase);
|
|
355
65
|
}
|
|
356
66
|
const initialized = await persistInitializedWallet({
|
|
357
|
-
|
|
67
|
+
context,
|
|
358
68
|
provider: interactiveProvider,
|
|
359
69
|
material,
|
|
360
|
-
nowUnixMs,
|
|
361
|
-
paths,
|
|
362
|
-
attachService: options.attachService,
|
|
363
|
-
rpcFactory: options.rpcFactory,
|
|
364
70
|
});
|
|
365
71
|
return {
|
|
366
72
|
setupMode,
|
|
@@ -376,52 +82,42 @@ export async function initializeWallet(options) {
|
|
|
376
82
|
}
|
|
377
83
|
}
|
|
378
84
|
export async function showWalletMnemonic(options) {
|
|
379
|
-
|
|
85
|
+
const context = {
|
|
86
|
+
...resolveWalletManagedCoreContext({
|
|
87
|
+
provider: options.provider,
|
|
88
|
+
nowUnixMs: options.nowUnixMs,
|
|
89
|
+
paths: options.paths,
|
|
90
|
+
attachService: options.attachService,
|
|
91
|
+
rpcFactory: options.rpcFactory,
|
|
92
|
+
}),
|
|
93
|
+
prompter: options.prompter,
|
|
94
|
+
};
|
|
95
|
+
if (!context.prompter.isInteractive) {
|
|
380
96
|
throw new Error("wallet_show_mnemonic_requires_tty");
|
|
381
97
|
}
|
|
382
|
-
const
|
|
383
|
-
const
|
|
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
|
-
});
|
|
98
|
+
const interactiveProvider = withInteractiveWalletSecretProvider(context.provider, context.prompter);
|
|
99
|
+
const controlLock = await acquireWalletControlLock(context.paths, "wallet-show-mnemonic");
|
|
390
100
|
try {
|
|
391
|
-
|
|
392
|
-
pathExists(paths.walletStatePath),
|
|
393
|
-
pathExists(paths.walletStateBackupPath),
|
|
394
|
-
]);
|
|
395
|
-
if (!hasPrimaryStateFile && !hasBackupStateFile) {
|
|
101
|
+
if (!await walletStateExists(context.paths)) {
|
|
396
102
|
throw new Error("wallet_uninitialized");
|
|
397
103
|
}
|
|
398
104
|
const loaded = await loadWalletStateForAccess({
|
|
105
|
+
...context,
|
|
399
106
|
provider: interactiveProvider,
|
|
400
|
-
nowUnixMs,
|
|
401
|
-
paths,
|
|
402
107
|
}).catch((error) => {
|
|
403
|
-
|
|
404
|
-
throw new Error("wallet_secret_provider_unavailable");
|
|
405
|
-
}
|
|
406
|
-
throw new Error("local-state-corrupt");
|
|
108
|
+
throw mapWalletReadAccessError(error);
|
|
407
109
|
});
|
|
408
|
-
await confirmTypedAcknowledgement(
|
|
409
|
-
|
|
410
|
-
writeMnemonicReveal(options.prompter, loaded.state.mnemonic.phrase, [
|
|
110
|
+
await confirmTypedAcknowledgement(context.prompter, "show mnemonic", "Type \"show mnemonic\" to continue: ", "wallet_show_mnemonic_typed_ack_required");
|
|
111
|
+
writeMnemonicReveal(context.prompter, loaded.state.mnemonic.phrase, [
|
|
411
112
|
"Cogcoin Wallet Recovery Phrase",
|
|
412
113
|
"This 24-word recovery phrase controls the wallet.",
|
|
413
114
|
"",
|
|
414
115
|
]);
|
|
415
|
-
mnemonicRevealed = true;
|
|
416
116
|
try {
|
|
417
|
-
await
|
|
117
|
+
await context.prompter.prompt("Press Enter to clear the recovery phrase from the screen: ");
|
|
418
118
|
}
|
|
419
119
|
finally {
|
|
420
|
-
|
|
421
|
-
await Promise.resolve()
|
|
422
|
-
.then(() => options.prompter.clearSensitiveDisplay?.("mnemonic-reveal"))
|
|
423
|
-
.catch(() => undefined);
|
|
424
|
-
}
|
|
120
|
+
await clearSensitiveDisplay(context.prompter, "mnemonic-reveal");
|
|
425
121
|
}
|
|
426
122
|
}
|
|
427
123
|
finally {
|