@cogcoin/client 0.5.3 → 0.5.5
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 +11 -3
- package/dist/app-paths.d.ts +2 -0
- package/dist/app-paths.js +4 -0
- package/dist/art/wallet.txt +10 -0
- package/dist/bitcoind/bootstrap/chunk-manifest.d.ts +14 -0
- package/dist/bitcoind/bootstrap/chunk-manifest.js +85 -0
- package/dist/bitcoind/bootstrap/chunk-recovery.d.ts +4 -0
- package/dist/bitcoind/bootstrap/chunk-recovery.js +122 -0
- package/dist/bitcoind/bootstrap/constants.d.ts +3 -1
- package/dist/bitcoind/bootstrap/constants.js +3 -1
- package/dist/bitcoind/bootstrap/controller.d.ts +6 -1
- package/dist/bitcoind/bootstrap/controller.js +14 -7
- package/dist/bitcoind/bootstrap/default-snapshot-chunk-manifest.d.ts +2 -0
- package/dist/bitcoind/bootstrap/default-snapshot-chunk-manifest.js +2309 -0
- package/dist/bitcoind/bootstrap/download.js +177 -83
- package/dist/bitcoind/bootstrap/headers.d.ts +4 -2
- package/dist/bitcoind/bootstrap/headers.js +29 -4
- package/dist/bitcoind/bootstrap/state.d.ts +11 -1
- package/dist/bitcoind/bootstrap/state.js +50 -23
- package/dist/bitcoind/bootstrap/types.d.ts +12 -1
- package/dist/bitcoind/client/internal-types.d.ts +1 -0
- package/dist/bitcoind/client/managed-client.js +27 -13
- package/dist/bitcoind/client/sync-engine.js +42 -5
- package/dist/bitcoind/errors.js +9 -0
- package/dist/bitcoind/indexer-daemon.d.ts +9 -0
- package/dist/bitcoind/indexer-daemon.js +51 -14
- package/dist/bitcoind/service.d.ts +9 -0
- package/dist/bitcoind/service.js +65 -24
- package/dist/bitcoind/testing.d.ts +2 -2
- package/dist/bitcoind/testing.js +2 -2
- package/dist/bitcoind/types.d.ts +9 -0
- package/dist/cli/commands/service-runtime.d.ts +2 -0
- package/dist/cli/commands/service-runtime.js +432 -0
- package/dist/cli/commands/wallet-admin.js +227 -132
- package/dist/cli/commands/wallet-mutation.js +597 -580
- package/dist/cli/context.js +23 -1
- package/dist/cli/mutation-json.d.ts +17 -1
- package/dist/cli/mutation-json.js +42 -0
- package/dist/cli/output.js +113 -2
- package/dist/cli/parse.d.ts +1 -1
- package/dist/cli/parse.js +65 -0
- package/dist/cli/preview-json.d.ts +19 -1
- package/dist/cli/preview-json.js +31 -0
- package/dist/cli/prompt.js +40 -12
- package/dist/cli/runner.js +12 -0
- package/dist/cli/signals.d.ts +1 -0
- package/dist/cli/signals.js +44 -0
- package/dist/cli/types.d.ts +24 -2
- package/dist/cli/types.js +6 -0
- package/dist/cli/wallet-format.js +3 -0
- package/dist/cli/workflow-hints.d.ts +1 -0
- package/dist/cli/workflow-hints.js +3 -0
- package/dist/wallet/fs/lock.d.ts +2 -0
- package/dist/wallet/fs/lock.js +32 -0
- package/dist/wallet/lifecycle.d.ts +19 -1
- package/dist/wallet/lifecycle.js +315 -8
- package/dist/wallet/material.d.ts +2 -0
- package/dist/wallet/material.js +8 -1
- package/dist/wallet/mnemonic-art.d.ts +2 -0
- package/dist/wallet/mnemonic-art.js +54 -0
- package/dist/wallet/reset.d.ts +61 -0
- package/dist/wallet/reset.js +781 -0
- package/dist/wallet/runtime.d.ts +2 -0
- package/dist/wallet/runtime.js +2 -0
- package/dist/wallet/state/pending-init.d.ts +24 -0
- package/dist/wallet/state/pending-init.js +59 -0
- package/dist/wallet/state/provider.d.ts +1 -0
- package/dist/wallet/state/provider.js +7 -1
- package/dist/wallet/types.d.ts +8 -0
- package/package.json +6 -4
|
@@ -2,9 +2,39 @@ import { formatManagedSyncErrorMessage } from "../errors.js";
|
|
|
2
2
|
import { normalizeRpcBlock } from "../normalize.js";
|
|
3
3
|
import { estimateEtaSeconds } from "./rate-tracker.js";
|
|
4
4
|
const DEFAULT_SYNC_CATCH_UP_POLL_MS = 2_000;
|
|
5
|
-
function
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
function createAbortError(signal) {
|
|
6
|
+
const reason = signal?.reason;
|
|
7
|
+
if (reason instanceof Error) {
|
|
8
|
+
return reason;
|
|
9
|
+
}
|
|
10
|
+
const error = new Error("managed_sync_aborted");
|
|
11
|
+
error.name = "AbortError";
|
|
12
|
+
return error;
|
|
13
|
+
}
|
|
14
|
+
function isAbortError(error, signal) {
|
|
15
|
+
if (signal?.aborted) {
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
return error instanceof Error
|
|
19
|
+
&& (error.name === "AbortError" || error.message === "managed_sync_aborted");
|
|
20
|
+
}
|
|
21
|
+
function throwIfAborted(signal) {
|
|
22
|
+
if (signal?.aborted) {
|
|
23
|
+
throw createAbortError(signal);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function sleep(ms, signal) {
|
|
27
|
+
return new Promise((resolve, reject) => {
|
|
28
|
+
const timer = setTimeout(() => {
|
|
29
|
+
signal?.removeEventListener("abort", onAbort);
|
|
30
|
+
resolve();
|
|
31
|
+
}, ms);
|
|
32
|
+
const onAbort = () => {
|
|
33
|
+
clearTimeout(timer);
|
|
34
|
+
signal?.removeEventListener("abort", onAbort);
|
|
35
|
+
reject(createAbortError(signal));
|
|
36
|
+
};
|
|
37
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
8
38
|
});
|
|
9
39
|
}
|
|
10
40
|
async function setBitcoinSyncProgress(dependencies, info) {
|
|
@@ -81,9 +111,12 @@ async function syncAgainstBestHeight(dependencies, bestHeight) {
|
|
|
81
111
|
}
|
|
82
112
|
export async function syncToTip(dependencies) {
|
|
83
113
|
try {
|
|
114
|
+
throwIfAborted(dependencies.abortSignal);
|
|
84
115
|
await dependencies.node.validate();
|
|
85
116
|
const indexedTipBeforeBootstrap = await dependencies.client.getTip();
|
|
86
|
-
await dependencies.bootstrap.ensureReady(indexedTipBeforeBootstrap, dependencies.node.expectedChain
|
|
117
|
+
await dependencies.bootstrap.ensureReady(indexedTipBeforeBootstrap, dependencies.node.expectedChain, {
|
|
118
|
+
signal: dependencies.abortSignal,
|
|
119
|
+
});
|
|
87
120
|
const startTip = await dependencies.client.getTip();
|
|
88
121
|
const aggregate = {
|
|
89
122
|
appliedBlocks: 0,
|
|
@@ -95,6 +128,7 @@ export async function syncToTip(dependencies) {
|
|
|
95
128
|
bestHashHex: "",
|
|
96
129
|
};
|
|
97
130
|
while (true) {
|
|
131
|
+
throwIfAborted(dependencies.abortSignal);
|
|
98
132
|
const startInfo = await dependencies.rpc.getBlockchainInfo();
|
|
99
133
|
await setBitcoinSyncProgress(dependencies, startInfo);
|
|
100
134
|
const pass = await syncAgainstBestHeight(dependencies, startInfo.blocks);
|
|
@@ -129,10 +163,13 @@ export async function syncToTip(dependencies) {
|
|
|
129
163
|
if (endInfo.blocks >= dependencies.startHeight && finalTip?.height !== endInfo.blocks) {
|
|
130
164
|
continue;
|
|
131
165
|
}
|
|
132
|
-
await sleep(DEFAULT_SYNC_CATCH_UP_POLL_MS);
|
|
166
|
+
await sleep(DEFAULT_SYNC_CATCH_UP_POLL_MS, dependencies.abortSignal);
|
|
133
167
|
}
|
|
134
168
|
}
|
|
135
169
|
catch (error) {
|
|
170
|
+
if (isAbortError(error, dependencies.abortSignal)) {
|
|
171
|
+
throw createAbortError(dependencies.abortSignal);
|
|
172
|
+
}
|
|
136
173
|
const message = formatManagedSyncErrorMessage(error instanceof Error ? error.message : String(error));
|
|
137
174
|
await dependencies.progress.setPhase("error", {
|
|
138
175
|
lastError: message,
|
package/dist/bitcoind/errors.js
CHANGED
|
@@ -18,6 +18,15 @@ export function formatManagedSyncErrorMessage(message) {
|
|
|
18
18
|
if (message === "snapshot_response_body_missing") {
|
|
19
19
|
return appendNextStep("Snapshot server returned an empty response body.", "Wait a moment, confirm the snapshot host is reachable, then rerun sync.");
|
|
20
20
|
}
|
|
21
|
+
if (message === "snapshot_resume_requires_partial_content") {
|
|
22
|
+
return appendNextStep("Snapshot server ignored the resume request for a partial download.", "Wait a moment and rerun sync. If this keeps happening, confirm the snapshot host supports HTTP range requests.");
|
|
23
|
+
}
|
|
24
|
+
if (message.startsWith("snapshot_chunk_sha256_mismatch_")) {
|
|
25
|
+
return appendNextStep("A downloaded snapshot chunk was corrupted and was rolled back to the last verified checkpoint.", "Wait a moment and rerun sync. If this keeps happening, check local disk health and the stability of the snapshot connection.");
|
|
26
|
+
}
|
|
27
|
+
if (message.startsWith("snapshot_download_incomplete_")) {
|
|
28
|
+
return appendNextStep("Snapshot download ended before the expected file size was reached.", "Wait a moment and rerun sync. The downloader will resume from the last verified checkpoint.");
|
|
29
|
+
}
|
|
21
30
|
if (message === "bitcoind_cookie_timeout") {
|
|
22
31
|
return appendNextStep("The managed Bitcoin node did not finish starting in time.", "Check the node logs and local permissions for the Bitcoin data directory, then rerun sync.");
|
|
23
32
|
}
|
|
@@ -73,6 +73,10 @@ export interface IndexerDaemonProbeResult {
|
|
|
73
73
|
client: IndexerDaemonClient | null;
|
|
74
74
|
error: string | null;
|
|
75
75
|
}
|
|
76
|
+
export interface IndexerDaemonStopResult {
|
|
77
|
+
status: "stopped" | "not-running";
|
|
78
|
+
walletRootId: string;
|
|
79
|
+
}
|
|
76
80
|
export interface CoherentIndexerSnapshotLease {
|
|
77
81
|
payload: IndexerSnapshotPayload;
|
|
78
82
|
status: ManagedIndexerDaemonStatus;
|
|
@@ -92,6 +96,11 @@ export declare function attachOrStartIndexerDaemon(options: {
|
|
|
92
96
|
walletRootId?: string;
|
|
93
97
|
startupTimeoutMs?: number;
|
|
94
98
|
}): Promise<IndexerDaemonClient>;
|
|
99
|
+
export declare function stopIndexerDaemonService(options: {
|
|
100
|
+
dataDir: string;
|
|
101
|
+
walletRootId?: string;
|
|
102
|
+
shutdownTimeoutMs?: number;
|
|
103
|
+
}): Promise<IndexerDaemonStopResult>;
|
|
95
104
|
export declare function shutdownIndexerDaemonForTesting(options: {
|
|
96
105
|
dataDir: string;
|
|
97
106
|
walletRootId?: string;
|
|
@@ -39,6 +39,20 @@ function sleep(ms) {
|
|
|
39
39
|
setTimeout(resolve, ms);
|
|
40
40
|
});
|
|
41
41
|
}
|
|
42
|
+
async function waitForProcessExit(pid, timeoutMs, errorCode) {
|
|
43
|
+
const deadline = Date.now() + timeoutMs;
|
|
44
|
+
while (Date.now() < deadline) {
|
|
45
|
+
if (!await isProcessAlive(pid)) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
await sleep(50);
|
|
49
|
+
}
|
|
50
|
+
throw new Error(errorCode);
|
|
51
|
+
}
|
|
52
|
+
async function clearIndexerDaemonRuntimeArtifacts(paths) {
|
|
53
|
+
await rm(paths.indexerDaemonStatusPath, { force: true }).catch(() => undefined);
|
|
54
|
+
await rm(paths.indexerDaemonSocketPath, { force: true }).catch(() => undefined);
|
|
55
|
+
}
|
|
42
56
|
function createIndexerDaemonClient(socketPath) {
|
|
43
57
|
async function sendRequest(request) {
|
|
44
58
|
return new Promise((resolve, reject) => {
|
|
@@ -357,26 +371,49 @@ export async function attachOrStartIndexerDaemon(options) {
|
|
|
357
371
|
throw error;
|
|
358
372
|
}
|
|
359
373
|
}
|
|
360
|
-
export async function
|
|
374
|
+
export async function stopIndexerDaemonService(options) {
|
|
361
375
|
const walletRootId = options.walletRootId ?? UNINITIALIZED_WALLET_ROOT_ID;
|
|
362
376
|
const paths = resolveManagedServicePaths(options.dataDir, walletRootId);
|
|
363
|
-
const
|
|
364
|
-
|
|
377
|
+
const lock = await acquireFileLock(paths.indexerDaemonLockPath, {
|
|
378
|
+
purpose: "indexer-daemon-stop",
|
|
379
|
+
walletRootId,
|
|
380
|
+
dataDir: options.dataDir,
|
|
381
|
+
});
|
|
382
|
+
try {
|
|
383
|
+
const status = await readJsonFile(paths.indexerDaemonStatusPath);
|
|
384
|
+
const processId = status?.processId ?? null;
|
|
385
|
+
if (status === null || processId === null || !await isProcessAlive(processId)) {
|
|
386
|
+
await clearIndexerDaemonRuntimeArtifacts(paths);
|
|
387
|
+
return {
|
|
388
|
+
status: "not-running",
|
|
389
|
+
walletRootId,
|
|
390
|
+
};
|
|
391
|
+
}
|
|
365
392
|
try {
|
|
366
|
-
process.kill(
|
|
367
|
-
const deadline = Date.now() + 5_000;
|
|
368
|
-
while (Date.now() < deadline) {
|
|
369
|
-
if (!await isProcessAlive(status.processId)) {
|
|
370
|
-
break;
|
|
371
|
-
}
|
|
372
|
-
await sleep(50);
|
|
373
|
-
}
|
|
393
|
+
process.kill(processId, "SIGTERM");
|
|
374
394
|
}
|
|
375
|
-
catch {
|
|
376
|
-
|
|
395
|
+
catch (error) {
|
|
396
|
+
if (!(error instanceof Error && "code" in error && error.code === "ESRCH")) {
|
|
397
|
+
throw error;
|
|
398
|
+
}
|
|
377
399
|
}
|
|
400
|
+
await waitForProcessExit(processId, options.shutdownTimeoutMs ?? 5_000, "indexer_daemon_stop_timeout");
|
|
401
|
+
await clearIndexerDaemonRuntimeArtifacts(paths);
|
|
402
|
+
return {
|
|
403
|
+
status: "stopped",
|
|
404
|
+
walletRootId,
|
|
405
|
+
};
|
|
378
406
|
}
|
|
379
|
-
|
|
407
|
+
finally {
|
|
408
|
+
await lock.release();
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
export async function shutdownIndexerDaemonForTesting(options) {
|
|
412
|
+
await stopIndexerDaemonService(options).catch(async () => {
|
|
413
|
+
const walletRootId = options.walletRootId ?? UNINITIALIZED_WALLET_ROOT_ID;
|
|
414
|
+
const paths = resolveManagedServicePaths(options.dataDir, walletRootId);
|
|
415
|
+
await rm(paths.indexerDaemonSocketPath, { force: true }).catch(() => undefined);
|
|
416
|
+
});
|
|
380
417
|
}
|
|
381
418
|
export async function readIndexerDaemonStatusForTesting(options) {
|
|
382
419
|
const walletRootId = options.walletRootId ?? UNINITIALIZED_WALLET_ROOT_ID;
|
|
@@ -25,11 +25,20 @@ export interface ManagedBitcoindServiceProbeResult {
|
|
|
25
25
|
status: ManagedBitcoindObservedStatus | null;
|
|
26
26
|
error: string | null;
|
|
27
27
|
}
|
|
28
|
+
export interface ManagedBitcoindServiceStopResult {
|
|
29
|
+
status: "stopped" | "not-running";
|
|
30
|
+
walletRootId: string;
|
|
31
|
+
}
|
|
28
32
|
export declare function createManagedWalletReplica(rpc: ManagedWalletReplicaRpc, walletRootId: string, options?: {
|
|
29
33
|
managedWalletPassphrase?: string;
|
|
30
34
|
}): Promise<ManagedCoreWalletReplicaStatus>;
|
|
31
35
|
export declare function probeManagedBitcoindService(options: ManagedBitcoindServiceOptions): Promise<ManagedBitcoindServiceProbeResult>;
|
|
32
36
|
export declare function attachOrStartManagedBitcoindService(options: ManagedBitcoindServiceOptions): Promise<ManagedBitcoindNodeHandle>;
|
|
37
|
+
export declare function stopManagedBitcoindService(options: {
|
|
38
|
+
dataDir: string;
|
|
39
|
+
walletRootId?: string;
|
|
40
|
+
shutdownTimeoutMs?: number;
|
|
41
|
+
}): Promise<ManagedBitcoindServiceStopResult>;
|
|
33
42
|
export declare function readManagedBitcoindServiceStatusForTesting(dataDir: string, walletRootId?: string): Promise<ManagedBitcoindObservedStatus | null>;
|
|
34
43
|
export declare function shutdownManagedBitcoindServiceForTesting(options: {
|
|
35
44
|
dataDir: string;
|
package/dist/bitcoind/service.js
CHANGED
|
@@ -21,6 +21,16 @@ function sleep(ms) {
|
|
|
21
21
|
setTimeout(resolve, ms);
|
|
22
22
|
});
|
|
23
23
|
}
|
|
24
|
+
async function waitForProcessExit(pid, timeoutMs, errorCode) {
|
|
25
|
+
const deadline = Date.now() + timeoutMs;
|
|
26
|
+
while (Date.now() < deadline) {
|
|
27
|
+
if (!await isProcessAlive(pid)) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
await sleep(250);
|
|
31
|
+
}
|
|
32
|
+
throw new Error(errorCode);
|
|
33
|
+
}
|
|
24
34
|
function getWalletReplicaName(walletRootId) {
|
|
25
35
|
return `cogcoin-${walletRootId}`.replace(/[^a-zA-Z0-9._-]+/g, "-").slice(0, 63);
|
|
26
36
|
}
|
|
@@ -488,6 +498,12 @@ async function writeBitcoindStatus(paths, status) {
|
|
|
488
498
|
p2pPort: status.p2pPort,
|
|
489
499
|
});
|
|
490
500
|
}
|
|
501
|
+
async function clearManagedBitcoindRuntimeArtifacts(paths) {
|
|
502
|
+
await rm(paths.bitcoindStatusPath, { force: true }).catch(() => undefined);
|
|
503
|
+
await rm(paths.bitcoindPidPath, { force: true }).catch(() => undefined);
|
|
504
|
+
await rm(paths.bitcoindReadyPath, { force: true }).catch(() => undefined);
|
|
505
|
+
await rm(paths.bitcoindWalletStatusPath, { force: true }).catch(() => undefined);
|
|
506
|
+
}
|
|
491
507
|
async function refreshManagedBitcoindStatus(status, paths, options) {
|
|
492
508
|
const nowUnixMs = Date.now();
|
|
493
509
|
const rpc = createRpcClient(status.rpc);
|
|
@@ -699,37 +715,62 @@ export async function attachOrStartManagedBitcoindService(options) {
|
|
|
699
715
|
throw error;
|
|
700
716
|
}
|
|
701
717
|
}
|
|
702
|
-
export async function
|
|
703
|
-
const paths = resolveManagedServicePaths(dataDir, walletRootId);
|
|
704
|
-
return readJsonFile(paths.bitcoindStatusPath);
|
|
705
|
-
}
|
|
706
|
-
export async function shutdownManagedBitcoindServiceForTesting(options) {
|
|
718
|
+
export async function stopManagedBitcoindService(options) {
|
|
707
719
|
const walletRootId = options.walletRootId ?? UNINITIALIZED_WALLET_ROOT_ID;
|
|
708
720
|
const paths = resolveManagedServicePaths(options.dataDir, walletRootId);
|
|
709
|
-
const
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
721
|
+
const lock = await acquireFileLock(paths.bitcoindLockPath, {
|
|
722
|
+
purpose: "managed-bitcoind-stop",
|
|
723
|
+
walletRootId,
|
|
724
|
+
dataDir: options.dataDir,
|
|
725
|
+
});
|
|
714
726
|
try {
|
|
715
|
-
await
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
727
|
+
const status = await readJsonFile(paths.bitcoindStatusPath);
|
|
728
|
+
const processId = status?.processId ?? null;
|
|
729
|
+
if (status === null || processId === null || !await isProcessAlive(processId)) {
|
|
730
|
+
await clearManagedBitcoindRuntimeArtifacts(paths);
|
|
731
|
+
return {
|
|
732
|
+
status: "not-running",
|
|
733
|
+
walletRootId,
|
|
734
|
+
};
|
|
735
|
+
}
|
|
736
|
+
const rpc = createRpcClient(status.rpc);
|
|
737
|
+
try {
|
|
738
|
+
await rpc.stop();
|
|
739
|
+
}
|
|
740
|
+
catch {
|
|
719
741
|
try {
|
|
720
|
-
process.kill(
|
|
742
|
+
process.kill(processId, "SIGTERM");
|
|
721
743
|
}
|
|
722
|
-
catch {
|
|
723
|
-
|
|
744
|
+
catch (error) {
|
|
745
|
+
if (!(error instanceof Error && "code" in error && error.code === "ESRCH")) {
|
|
746
|
+
throw error;
|
|
747
|
+
}
|
|
724
748
|
}
|
|
725
749
|
}
|
|
750
|
+
await waitForProcessExit(processId, options.shutdownTimeoutMs ?? DEFAULT_SHUTDOWN_TIMEOUT_MS, "managed_bitcoind_service_stop_timeout");
|
|
751
|
+
await clearManagedBitcoindRuntimeArtifacts(paths);
|
|
752
|
+
return {
|
|
753
|
+
status: "stopped",
|
|
754
|
+
walletRootId,
|
|
755
|
+
};
|
|
726
756
|
}
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
if (!await isProcessAlive(status.processId)) {
|
|
730
|
-
break;
|
|
731
|
-
}
|
|
732
|
-
await sleep(250);
|
|
757
|
+
finally {
|
|
758
|
+
await lock.release();
|
|
733
759
|
}
|
|
734
|
-
|
|
760
|
+
}
|
|
761
|
+
export async function readManagedBitcoindServiceStatusForTesting(dataDir, walletRootId = UNINITIALIZED_WALLET_ROOT_ID) {
|
|
762
|
+
const paths = resolveManagedServicePaths(dataDir, walletRootId);
|
|
763
|
+
return readJsonFile(paths.bitcoindStatusPath);
|
|
764
|
+
}
|
|
765
|
+
export async function shutdownManagedBitcoindServiceForTesting(options) {
|
|
766
|
+
await stopManagedBitcoindService({
|
|
767
|
+
dataDir: options.dataDir,
|
|
768
|
+
walletRootId: options.walletRootId,
|
|
769
|
+
shutdownTimeoutMs: options.shutdownTimeoutMs,
|
|
770
|
+
}).catch(async (error) => {
|
|
771
|
+
const walletRootId = options.walletRootId ?? UNINITIALIZED_WALLET_ROOT_ID;
|
|
772
|
+
const paths = resolveManagedServicePaths(options.dataDir, walletRootId);
|
|
773
|
+
await rm(paths.bitcoindReadyPath, { force: true }).catch(() => undefined);
|
|
774
|
+
throw error;
|
|
775
|
+
});
|
|
735
776
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export { openManagedBitcoindClientInternal } from "./client.js";
|
|
2
|
-
export { attachOrStartIndexerDaemon, readIndexerDaemonStatusForTesting, shutdownIndexerDaemonForTesting, } from "./indexer-daemon.js";
|
|
2
|
+
export { attachOrStartIndexerDaemon, readIndexerDaemonStatusForTesting, stopIndexerDaemonService, shutdownIndexerDaemonForTesting, } from "./indexer-daemon.js";
|
|
3
3
|
export { normalizeRpcBlock } from "./normalize.js";
|
|
4
4
|
export { BitcoinRpcClient } from "./rpc.js";
|
|
5
|
-
export { attachOrStartManagedBitcoindService, readManagedBitcoindServiceStatusForTesting, shutdownManagedBitcoindServiceForTesting, } from "./service.js";
|
|
5
|
+
export { attachOrStartManagedBitcoindService, readManagedBitcoindServiceStatusForTesting, stopManagedBitcoindService, shutdownManagedBitcoindServiceForTesting, } from "./service.js";
|
|
6
6
|
export { AssumeUtxoBootstrapController, DEFAULT_SNAPSHOT_METADATA, createBootstrapStateForTesting, downloadSnapshotFileForTesting, loadBootstrapStateForTesting, resolveBootstrapPathsForTesting, saveBootstrapStateForTesting, validateSnapshotFileForTesting, waitForHeadersForTesting, } from "./bootstrap.js";
|
|
7
7
|
export { buildBitcoindArgsForTesting, createRpcClient, launchManagedBitcoindNode, resolveDefaultBitcoindDataDirForTesting, validateNodeConfigForTesting, } from "./node.js";
|
|
8
8
|
export { ManagedProgressController, TtyProgressRenderer, advanceFollowSceneStateForTesting, createFollowSceneStateForTesting, createBootstrapProgressForTesting, formatCompactFollowAgeLabelForTesting, loadBannerArtForTesting, loadScrollArtForTesting, loadTrainCarArtForTesting, loadTrainArtForTesting, loadTrainSmokeArtForTesting, formatProgressLineForTesting, formatQuoteLineForTesting, renderArtFrameForTesting, renderCompletionFrameForTesting, renderFollowFrameForTesting, renderIntroFrameForTesting, resolveCompletionMessageForTesting, resolveIntroMessageForTesting, resolveStatusFieldTextForTesting, setFollowBlockTimeForTesting, setFollowBlockTimesForTesting, syncFollowSceneStateForTesting, } from "./progress.js";
|
package/dist/bitcoind/testing.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export { openManagedBitcoindClientInternal } from "./client.js";
|
|
2
|
-
export { attachOrStartIndexerDaemon, readIndexerDaemonStatusForTesting, shutdownIndexerDaemonForTesting, } from "./indexer-daemon.js";
|
|
2
|
+
export { attachOrStartIndexerDaemon, readIndexerDaemonStatusForTesting, stopIndexerDaemonService, shutdownIndexerDaemonForTesting, } from "./indexer-daemon.js";
|
|
3
3
|
export { normalizeRpcBlock } from "./normalize.js";
|
|
4
4
|
export { BitcoinRpcClient } from "./rpc.js";
|
|
5
|
-
export { attachOrStartManagedBitcoindService, readManagedBitcoindServiceStatusForTesting, shutdownManagedBitcoindServiceForTesting, } from "./service.js";
|
|
5
|
+
export { attachOrStartManagedBitcoindService, readManagedBitcoindServiceStatusForTesting, stopManagedBitcoindService, shutdownManagedBitcoindServiceForTesting, } from "./service.js";
|
|
6
6
|
export { AssumeUtxoBootstrapController, DEFAULT_SNAPSHOT_METADATA, createBootstrapStateForTesting, downloadSnapshotFileForTesting, loadBootstrapStateForTesting, resolveBootstrapPathsForTesting, saveBootstrapStateForTesting, validateSnapshotFileForTesting, waitForHeadersForTesting, } from "./bootstrap.js";
|
|
7
7
|
export { buildBitcoindArgsForTesting, createRpcClient, launchManagedBitcoindNode, resolveDefaultBitcoindDataDirForTesting, validateNodeConfigForTesting, } from "./node.js";
|
|
8
8
|
export { ManagedProgressController, TtyProgressRenderer, advanceFollowSceneStateForTesting, createFollowSceneStateForTesting, createBootstrapProgressForTesting, formatCompactFollowAgeLabelForTesting, loadBannerArtForTesting, loadScrollArtForTesting, loadTrainCarArtForTesting, loadTrainArtForTesting, loadTrainSmokeArtForTesting, formatProgressLineForTesting, formatQuoteLineForTesting, renderArtFrameForTesting, renderCompletionFrameForTesting, renderFollowFrameForTesting, renderIntroFrameForTesting, resolveCompletionMessageForTesting, resolveIntroMessageForTesting, resolveStatusFieldTextForTesting, setFollowBlockTimeForTesting, setFollowBlockTimesForTesting, syncFollowSceneStateForTesting, } from "./progress.js";
|
package/dist/bitcoind/types.d.ts
CHANGED
|
@@ -8,6 +8,15 @@ export interface SnapshotMetadata {
|
|
|
8
8
|
sha256: string;
|
|
9
9
|
sizeBytes: number;
|
|
10
10
|
}
|
|
11
|
+
export interface SnapshotChunkManifest {
|
|
12
|
+
formatVersion: number;
|
|
13
|
+
chunkSizeBytes: number;
|
|
14
|
+
snapshotFilename: string;
|
|
15
|
+
snapshotHeight: number;
|
|
16
|
+
snapshotSizeBytes: number;
|
|
17
|
+
snapshotSha256: string;
|
|
18
|
+
chunkSha256s: string[];
|
|
19
|
+
}
|
|
11
20
|
export interface WritingQuote {
|
|
12
21
|
quote: string;
|
|
13
22
|
author: string;
|