@cogcoin/client 0.5.6 → 0.5.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 +11 -2
- package/dist/bitcoind/bootstrap/getblock-archive.d.ts +39 -0
- package/dist/bitcoind/bootstrap/getblock-archive.js +548 -0
- package/dist/bitcoind/bootstrap.d.ts +1 -0
- package/dist/bitcoind/bootstrap.js +1 -0
- package/dist/bitcoind/client/factory.js +84 -30
- package/dist/bitcoind/client/managed-client.js +2 -1
- package/dist/bitcoind/client/sync-engine.js +7 -0
- package/dist/bitcoind/errors.js +18 -0
- package/dist/bitcoind/indexer-daemon-main.js +78 -0
- package/dist/bitcoind/indexer-daemon.d.ts +3 -1
- package/dist/bitcoind/indexer-daemon.js +13 -6
- package/dist/bitcoind/node.js +2 -0
- package/dist/bitcoind/progress/constants.d.ts +1 -0
- package/dist/bitcoind/progress/constants.js +1 -0
- package/dist/bitcoind/progress/controller.d.ts +22 -0
- package/dist/bitcoind/progress/controller.js +48 -23
- package/dist/bitcoind/progress/formatting.js +25 -0
- package/dist/bitcoind/progress/render-policy.d.ts +35 -0
- package/dist/bitcoind/progress/render-policy.js +81 -0
- package/dist/bitcoind/service-paths.js +2 -6
- package/dist/bitcoind/service.d.ts +5 -1
- package/dist/bitcoind/service.js +93 -54
- package/dist/bitcoind/testing.d.ts +1 -1
- package/dist/bitcoind/testing.js +1 -1
- package/dist/bitcoind/types.d.ts +35 -1
- package/dist/cli/commands/follow.js +2 -0
- package/dist/cli/commands/getblock-archive-restart.d.ts +5 -0
- package/dist/cli/commands/getblock-archive-restart.js +15 -0
- package/dist/cli/commands/mining-admin.js +4 -0
- package/dist/cli/commands/mining-read.js +8 -5
- package/dist/cli/commands/mining-runtime.js +4 -0
- package/dist/cli/commands/status.js +2 -0
- package/dist/cli/commands/sync.js +2 -0
- package/dist/cli/commands/wallet-admin.js +29 -3
- package/dist/cli/commands/wallet-mutation.js +57 -4
- package/dist/cli/commands/wallet-read.js +2 -0
- package/dist/cli/context.js +5 -3
- package/dist/cli/mutation-command-groups.d.ts +2 -1
- package/dist/cli/mutation-command-groups.js +5 -0
- package/dist/cli/mutation-json.d.ts +18 -2
- package/dist/cli/mutation-json.js +47 -0
- package/dist/cli/mutation-success.d.ts +1 -0
- package/dist/cli/mutation-success.js +2 -2
- package/dist/cli/output.js +84 -1
- package/dist/cli/parse.d.ts +1 -1
- package/dist/cli/parse.js +127 -3
- package/dist/cli/preview-json.d.ts +10 -1
- package/dist/cli/preview-json.js +30 -0
- package/dist/cli/prompt.js +1 -1
- package/dist/cli/runner.js +3 -0
- package/dist/cli/types.d.ts +11 -4
- package/dist/cli/wallet-format.js +6 -0
- package/dist/wallet/lifecycle.d.ts +15 -1
- package/dist/wallet/lifecycle.js +147 -83
- package/dist/wallet/mining/visualizer.d.ts +11 -6
- package/dist/wallet/mining/visualizer.js +32 -15
- package/dist/wallet/reset.js +39 -27
- package/dist/wallet/runtime.d.ts +12 -1
- package/dist/wallet/runtime.js +53 -11
- package/dist/wallet/state/provider.d.ts +1 -0
- package/dist/wallet/state/provider.js +119 -3
- package/dist/wallet/state/seed-index.d.ts +43 -0
- package/dist/wallet/state/seed-index.js +151 -0
- package/dist/wallet/tx/anchor.d.ts +22 -0
- package/dist/wallet/tx/anchor.js +215 -8
- package/dist/wallet/tx/index.d.ts +1 -1
- package/dist/wallet/tx/index.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { HEADLESS_PROGRESS_TICK_MS, PROGRESS_TICK_MS } from "./constants.js";
|
|
2
|
+
export const DEFAULT_RENDER_CLOCK = {
|
|
3
|
+
now: () => Date.now(),
|
|
4
|
+
setTimeout,
|
|
5
|
+
clearTimeout,
|
|
6
|
+
setInterval,
|
|
7
|
+
clearInterval,
|
|
8
|
+
};
|
|
9
|
+
export function resolveTtyRenderPolicy(progressOutput, stream, options = {}) {
|
|
10
|
+
const ttyActive = stream.isTTY === true;
|
|
11
|
+
const enabled = progressOutput === "none"
|
|
12
|
+
? false
|
|
13
|
+
: progressOutput === "tty"
|
|
14
|
+
? true
|
|
15
|
+
: ttyActive;
|
|
16
|
+
const env = options.env ?? process.env;
|
|
17
|
+
const linuxHeadlessThrottle = enabled
|
|
18
|
+
&& ttyActive
|
|
19
|
+
&& (options.platform ?? process.platform) === "linux"
|
|
20
|
+
&& (env.DISPLAY?.trim() ?? "").length === 0
|
|
21
|
+
&& (env.WAYLAND_DISPLAY?.trim() ?? "").length === 0;
|
|
22
|
+
return {
|
|
23
|
+
enabled,
|
|
24
|
+
linuxHeadlessThrottle,
|
|
25
|
+
repaintIntervalMs: linuxHeadlessThrottle ? HEADLESS_PROGRESS_TICK_MS : PROGRESS_TICK_MS,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export class TtyRenderThrottle {
|
|
29
|
+
#clock;
|
|
30
|
+
#intervalMs;
|
|
31
|
+
#onRender;
|
|
32
|
+
#throttled;
|
|
33
|
+
#lastRenderAt = null;
|
|
34
|
+
#pendingTimer = null;
|
|
35
|
+
constructor(options) {
|
|
36
|
+
this.#clock = options.clock ?? DEFAULT_RENDER_CLOCK;
|
|
37
|
+
this.#intervalMs = options.intervalMs;
|
|
38
|
+
this.#onRender = options.onRender;
|
|
39
|
+
this.#throttled = options.throttled;
|
|
40
|
+
}
|
|
41
|
+
request() {
|
|
42
|
+
if (!this.#throttled) {
|
|
43
|
+
this.cancel();
|
|
44
|
+
this.#renderNow();
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const now = this.#clock.now();
|
|
48
|
+
if (this.#lastRenderAt === null || (now - this.#lastRenderAt) >= this.#intervalMs) {
|
|
49
|
+
this.cancel();
|
|
50
|
+
this.#renderNow();
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (this.#pendingTimer !== null) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const delayMs = Math.max(0, this.#intervalMs - (now - this.#lastRenderAt));
|
|
57
|
+
this.#pendingTimer = this.#clock.setTimeout(() => {
|
|
58
|
+
this.#pendingTimer = null;
|
|
59
|
+
this.#renderNow();
|
|
60
|
+
}, delayMs);
|
|
61
|
+
}
|
|
62
|
+
flush() {
|
|
63
|
+
if (this.#pendingTimer === null) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
this.#clock.clearTimeout(this.#pendingTimer);
|
|
67
|
+
this.#pendingTimer = null;
|
|
68
|
+
this.#renderNow();
|
|
69
|
+
}
|
|
70
|
+
cancel() {
|
|
71
|
+
if (this.#pendingTimer === null) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
this.#clock.clearTimeout(this.#pendingTimer);
|
|
75
|
+
this.#pendingTimer = null;
|
|
76
|
+
}
|
|
77
|
+
#renderNow() {
|
|
78
|
+
this.#lastRenderAt = this.#clock.now();
|
|
79
|
+
this.#onRender();
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -3,9 +3,6 @@ import { tmpdir } from "node:os";
|
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
4
|
import { resolveCogcoinPathsForTesting, resolveDefaultBitcoindDataDirForTesting } from "../app-paths.js";
|
|
5
5
|
export const UNINITIALIZED_WALLET_ROOT_ID = "wallet-root-uninitialized";
|
|
6
|
-
function sanitizeWalletRootId(walletRootId) {
|
|
7
|
-
return walletRootId.replace(/[^a-zA-Z0-9._-]+/g, "-");
|
|
8
|
-
}
|
|
9
6
|
function createDataDirSuffix(dataDir) {
|
|
10
7
|
return createHash("sha256").update(dataDir).digest("hex").slice(0, 12);
|
|
11
8
|
}
|
|
@@ -17,7 +14,6 @@ function resolveIndexerDaemonSocketPath(serviceRootId) {
|
|
|
17
14
|
return join(tmpdir(), `cogcoin-indexer-${socketId}.sock`);
|
|
18
15
|
}
|
|
19
16
|
export function resolveManagedServicePaths(dataDir, walletRootId = UNINITIALIZED_WALLET_ROOT_ID) {
|
|
20
|
-
const normalizedWalletRootId = sanitizeWalletRootId(walletRootId);
|
|
21
17
|
const defaultPaths = resolveCogcoinPathsForTesting();
|
|
22
18
|
const defaultBitcoindDataDir = resolveDefaultBitcoindDataDirForTesting();
|
|
23
19
|
const useDefaultRoots = dataDir === defaultBitcoindDataDir;
|
|
@@ -25,8 +21,8 @@ export function resolveManagedServicePaths(dataDir, walletRootId = UNINITIALIZED
|
|
|
25
21
|
const runtimeRoot = useDefaultRoots ? defaultPaths.runtimeRoot : join(dataRoot, "runtime");
|
|
26
22
|
const indexerRoot = useDefaultRoots ? defaultPaths.indexerRoot : join(dataRoot, "indexer");
|
|
27
23
|
const serviceRootId = useDefaultRoots
|
|
28
|
-
?
|
|
29
|
-
:
|
|
24
|
+
? "managed"
|
|
25
|
+
: `managed-${createDataDirSuffix(dataDir)}`;
|
|
30
26
|
const walletRuntimeRoot = join(runtimeRoot, serviceRootId);
|
|
31
27
|
const indexerServiceRoot = join(indexerRoot, serviceRootId);
|
|
32
28
|
return {
|
|
@@ -20,7 +20,11 @@ interface ManagedWalletReplicaRpc {
|
|
|
20
20
|
}>;
|
|
21
21
|
walletLock(walletName: string): Promise<null>;
|
|
22
22
|
}
|
|
23
|
-
type ManagedBitcoindServiceOptions = Pick<InternalManagedBitcoindOptions, "dataDir" | "chain" | "startHeight" | "walletRootId" | "rpcPort" | "zmqPort" | "p2pPort" | "pollIntervalMs" | "startupTimeoutMs" | "shutdownTimeoutMs" | "managedWalletPassphrase"
|
|
23
|
+
type ManagedBitcoindServiceOptions = Pick<InternalManagedBitcoindOptions, "dataDir" | "chain" | "startHeight" | "walletRootId" | "rpcPort" | "zmqPort" | "p2pPort" | "pollIntervalMs" | "startupTimeoutMs" | "shutdownTimeoutMs" | "managedWalletPassphrase"> & {
|
|
24
|
+
getblockArchivePath?: string | null;
|
|
25
|
+
getblockArchiveEndHeight?: number | null;
|
|
26
|
+
getblockArchiveSha256?: string | null;
|
|
27
|
+
};
|
|
24
28
|
export type ManagedBitcoindServiceCompatibility = "compatible" | "service-version-mismatch" | "wallet-root-mismatch" | "runtime-mismatch" | "unreachable" | "protocol-error";
|
|
25
29
|
export interface ManagedBitcoindServiceProbeResult {
|
|
26
30
|
compatibility: ManagedBitcoindServiceCompatibility;
|
package/dist/bitcoind/service.js
CHANGED
|
@@ -226,15 +226,14 @@ async function waitForRpcReady(rpc, cookieFile, expectedChain, timeoutMs) {
|
|
|
226
226
|
throw lastError instanceof Error ? lastError : new Error("bitcoind_rpc_timeout");
|
|
227
227
|
}
|
|
228
228
|
function validateManagedBitcoindStatus(status, options, runtimeRoot) {
|
|
229
|
+
const walletRootId = options.walletRootId ?? UNINITIALIZED_WALLET_ROOT_ID;
|
|
230
|
+
const legacyRuntimeRoot = join(resolveManagedServicePaths(options.dataDir ?? "", walletRootId).runtimeRoot, walletRootId);
|
|
229
231
|
if (status.serviceApiVersion !== MANAGED_BITCOIND_SERVICE_API_VERSION_VALUE) {
|
|
230
232
|
throw new Error("managed_bitcoind_service_version_mismatch");
|
|
231
233
|
}
|
|
232
|
-
if (status.walletRootId !== (options.walletRootId ?? UNINITIALIZED_WALLET_ROOT_ID)) {
|
|
233
|
-
throw new Error("managed_bitcoind_wallet_root_mismatch");
|
|
234
|
-
}
|
|
235
234
|
if (status.chain !== options.chain
|
|
236
235
|
|| status.dataDir !== (options.dataDir ?? "")
|
|
237
|
-
|| status.runtimeRoot !== runtimeRoot) {
|
|
236
|
+
|| (status.runtimeRoot !== runtimeRoot && status.runtimeRoot !== legacyRuntimeRoot)) {
|
|
238
237
|
throw new Error("managed_bitcoind_runtime_mismatch");
|
|
239
238
|
}
|
|
240
239
|
}
|
|
@@ -275,6 +274,8 @@ function createBitcoindServiceStatus(options) {
|
|
|
275
274
|
rpc: options.rpc,
|
|
276
275
|
zmq: options.zmq,
|
|
277
276
|
p2pPort: options.p2pPort,
|
|
277
|
+
getblockArchiveEndHeight: options.getblockArchiveEndHeight,
|
|
278
|
+
getblockArchiveSha256: options.getblockArchiveSha256,
|
|
278
279
|
walletReplica: options.walletReplica,
|
|
279
280
|
startedAtUnixMs: options.startedAtUnixMs,
|
|
280
281
|
heartbeatAtUnixMs: options.heartbeatAtUnixMs,
|
|
@@ -287,9 +288,7 @@ function mapManagedBitcoindValidationError(error) {
|
|
|
287
288
|
compatibility: error instanceof Error
|
|
288
289
|
? error.message === "managed_bitcoind_service_version_mismatch"
|
|
289
290
|
? "service-version-mismatch"
|
|
290
|
-
:
|
|
291
|
-
? "wallet-root-mismatch"
|
|
292
|
-
: "runtime-mismatch"
|
|
291
|
+
: "runtime-mismatch"
|
|
293
292
|
: "protocol-error",
|
|
294
293
|
status: null,
|
|
295
294
|
error: error instanceof Error ? error.message : "managed_bitcoind_protocol_error",
|
|
@@ -366,6 +365,8 @@ async function resolveRuntimeConfig(statusPath, configPath, options) {
|
|
|
366
365
|
zmqPort,
|
|
367
366
|
p2pPort,
|
|
368
367
|
dbcacheMiB: detectManagedBitcoindDbcacheMiB(),
|
|
368
|
+
getblockArchiveEndHeight: options.getblockArchiveEndHeight ?? null,
|
|
369
|
+
getblockArchiveSha256: options.getblockArchiveSha256 ?? null,
|
|
369
370
|
};
|
|
370
371
|
}
|
|
371
372
|
async function writeBitcoinConf(filePath, options, runtimeConfig) {
|
|
@@ -407,6 +408,9 @@ function buildManagedServiceArgs(options, runtimeConfig) {
|
|
|
407
408
|
if (options.chain === "regtest") {
|
|
408
409
|
args.push("-chain=regtest");
|
|
409
410
|
}
|
|
411
|
+
if (options.getblockArchivePath !== undefined && options.getblockArchivePath !== null) {
|
|
412
|
+
args.push(`-loadblock=${options.getblockArchivePath}`);
|
|
413
|
+
}
|
|
410
414
|
return args;
|
|
411
415
|
}
|
|
412
416
|
export async function writeBitcoinConfForTesting(filePath, options, runtimeConfig) {
|
|
@@ -547,6 +551,8 @@ async function writeBitcoindStatus(paths, status) {
|
|
|
547
551
|
rpc: status.rpc,
|
|
548
552
|
zmqPort: status.zmq.port,
|
|
549
553
|
p2pPort: status.p2pPort,
|
|
554
|
+
getblockArchiveEndHeight: status.getblockArchiveEndHeight,
|
|
555
|
+
getblockArchiveSha256: status.getblockArchiveSha256,
|
|
550
556
|
});
|
|
551
557
|
}
|
|
552
558
|
async function clearManagedBitcoindRuntimeArtifacts(paths) {
|
|
@@ -590,6 +596,11 @@ export async function stopManagedBitcoindServiceWithLockHeld(options) {
|
|
|
590
596
|
}
|
|
591
597
|
export async function withClaimedUninitializedManagedRuntime(options, callback) {
|
|
592
598
|
const targetWalletRootId = options.walletRootId ?? UNINITIALIZED_WALLET_ROOT_ID;
|
|
599
|
+
const targetPaths = resolveManagedServicePaths(options.dataDir, targetWalletRootId);
|
|
600
|
+
const uninitializedPaths = resolveManagedServicePaths(options.dataDir, UNINITIALIZED_WALLET_ROOT_ID);
|
|
601
|
+
if (targetPaths.walletRuntimeRoot === uninitializedPaths.walletRuntimeRoot) {
|
|
602
|
+
return callback();
|
|
603
|
+
}
|
|
593
604
|
if (targetWalletRootId === UNINITIALIZED_WALLET_ROOT_ID) {
|
|
594
605
|
return callback();
|
|
595
606
|
}
|
|
@@ -598,7 +609,6 @@ export async function withClaimedUninitializedManagedRuntime(options, callback)
|
|
|
598
609
|
return callback();
|
|
599
610
|
}
|
|
600
611
|
claimedUninitializedRuntimeKeys.add(claimKey);
|
|
601
|
-
const uninitializedPaths = resolveManagedServicePaths(options.dataDir, UNINITIALIZED_WALLET_ROOT_ID);
|
|
602
612
|
const lockTimeoutMs = options.shutdownTimeoutMs ?? DEFAULT_STARTUP_TIMEOUT_MS;
|
|
603
613
|
const bitcoindLock = await acquireFileLockWithRetry(uninitializedPaths.bitcoindLockPath, {
|
|
604
614
|
purpose: "managed-bitcoind-claim-uninitialized",
|
|
@@ -638,12 +648,15 @@ export async function withClaimedUninitializedManagedRuntime(options, callback)
|
|
|
638
648
|
async function refreshManagedBitcoindStatus(status, paths, options) {
|
|
639
649
|
const nowUnixMs = Date.now();
|
|
640
650
|
const rpc = createRpcClient(status.rpc);
|
|
651
|
+
const targetWalletRootId = options.walletRootId ?? status.walletRootId;
|
|
641
652
|
try {
|
|
642
653
|
await waitForRpcReady(rpc, status.rpc.cookieFile, status.chain, options.startupTimeoutMs ?? DEFAULT_STARTUP_TIMEOUT_MS);
|
|
643
654
|
await validateNodeConfigForTesting(rpc, status.chain, status.zmq.endpoint);
|
|
644
|
-
const walletReplica = await loadManagedWalletReplicaIfPresent(rpc,
|
|
655
|
+
const walletReplica = await loadManagedWalletReplicaIfPresent(rpc, targetWalletRootId, status.dataDir);
|
|
645
656
|
const nextStatus = {
|
|
646
657
|
...status,
|
|
658
|
+
walletRootId: targetWalletRootId,
|
|
659
|
+
runtimeRoot: paths.walletRuntimeRoot,
|
|
647
660
|
state: "ready",
|
|
648
661
|
processId: await isProcessAlive(status.processId) ? status.processId : null,
|
|
649
662
|
walletReplica,
|
|
@@ -657,6 +670,8 @@ async function refreshManagedBitcoindStatus(status, paths, options) {
|
|
|
657
670
|
catch (error) {
|
|
658
671
|
const nextStatus = {
|
|
659
672
|
...status,
|
|
673
|
+
walletRootId: targetWalletRootId,
|
|
674
|
+
runtimeRoot: paths.walletRuntimeRoot,
|
|
660
675
|
state: "failed",
|
|
661
676
|
processId: await isProcessAlive(status.processId) ? status.processId : null,
|
|
662
677
|
heartbeatAtUnixMs: nowUnixMs,
|
|
@@ -677,6 +692,8 @@ function createNodeHandle(status, paths, options) {
|
|
|
677
692
|
expectedChain: currentStatus.chain,
|
|
678
693
|
startHeight: currentStatus.startHeight,
|
|
679
694
|
dataDir: currentStatus.dataDir,
|
|
695
|
+
getblockArchiveEndHeight: currentStatus.getblockArchiveEndHeight ?? null,
|
|
696
|
+
getblockArchiveSha256: currentStatus.getblockArchiveSha256 ?? null,
|
|
680
697
|
walletRootId: currentStatus.walletRootId,
|
|
681
698
|
runtimeRoot: paths.walletRuntimeRoot,
|
|
682
699
|
async validate() {
|
|
@@ -684,6 +701,9 @@ function createNodeHandle(status, paths, options) {
|
|
|
684
701
|
},
|
|
685
702
|
async refreshServiceStatus() {
|
|
686
703
|
currentStatus = await refreshManagedBitcoindStatus(currentStatus, paths, options);
|
|
704
|
+
this.getblockArchiveEndHeight = currentStatus.getblockArchiveEndHeight ?? null;
|
|
705
|
+
this.getblockArchiveSha256 = currentStatus.getblockArchiveSha256 ?? null;
|
|
706
|
+
this.walletRootId = currentStatus.walletRootId;
|
|
687
707
|
return currentStatus;
|
|
688
708
|
},
|
|
689
709
|
async stop() {
|
|
@@ -786,57 +806,76 @@ export async function attachOrStartManagedBitcoindService(options) {
|
|
|
786
806
|
await verifyBitcoindVersion(bitcoindPath);
|
|
787
807
|
const binaryVersion = SUPPORTED_BITCOIND_VERSION;
|
|
788
808
|
await mkdir(resolvedOptions.dataDir ?? "", { recursive: true });
|
|
789
|
-
const
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
809
|
+
const startManagedProcess = async (startOptions) => {
|
|
810
|
+
const runtimeConfig = await resolveRuntimeConfig(paths.bitcoindStatusPath, paths.bitcoindRuntimeConfigPath, startOptions);
|
|
811
|
+
await writeBitcoinConf(paths.bitcoinConfPath, startOptions, runtimeConfig);
|
|
812
|
+
const rpcConfig = runtimeConfig.rpc;
|
|
813
|
+
const zmqConfig = {
|
|
814
|
+
endpoint: `tcp://${LOCAL_HOST}:${runtimeConfig.zmqPort}`,
|
|
815
|
+
topic: "hashblock",
|
|
816
|
+
port: runtimeConfig.zmqPort,
|
|
817
|
+
pollIntervalMs: startOptions.pollIntervalMs ?? 15_000,
|
|
818
|
+
};
|
|
819
|
+
const child = spawn(bitcoindPath, buildManagedServiceArgs(startOptions, runtimeConfig), {
|
|
820
|
+
detached: true,
|
|
821
|
+
stdio: "ignore",
|
|
822
|
+
});
|
|
823
|
+
child.unref();
|
|
824
|
+
const rpc = createRpcClient(rpcConfig);
|
|
825
|
+
try {
|
|
826
|
+
await waitForRpcReady(rpc, rpcConfig.cookieFile, startOptions.chain, startupTimeoutMs);
|
|
827
|
+
await validateNodeConfigForTesting(rpc, startOptions.chain, zmqConfig.endpoint);
|
|
828
|
+
}
|
|
829
|
+
catch (error) {
|
|
830
|
+
if (child.pid !== undefined) {
|
|
831
|
+
try {
|
|
832
|
+
process.kill(child.pid, "SIGTERM");
|
|
833
|
+
}
|
|
834
|
+
catch {
|
|
835
|
+
// ignore kill failures during startup cleanup
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
throw error;
|
|
839
|
+
}
|
|
840
|
+
const nowUnixMs = Date.now();
|
|
841
|
+
const walletRootId = startOptions.walletRootId ?? UNINITIALIZED_WALLET_ROOT_ID;
|
|
842
|
+
const walletReplica = await loadManagedWalletReplicaIfPresent(rpc, walletRootId, startOptions.dataDir ?? "");
|
|
843
|
+
return createBitcoindServiceStatus({
|
|
844
|
+
binaryVersion,
|
|
845
|
+
serviceInstanceId: randomBytes(16).toString("hex"),
|
|
846
|
+
state: "ready",
|
|
847
|
+
processId: child.pid ?? null,
|
|
848
|
+
walletRootId,
|
|
849
|
+
chain: startOptions.chain,
|
|
850
|
+
dataDir: startOptions.dataDir ?? "",
|
|
851
|
+
runtimeRoot: paths.walletRuntimeRoot,
|
|
852
|
+
startHeight: startOptions.startHeight,
|
|
853
|
+
rpc: rpcConfig,
|
|
854
|
+
zmq: zmqConfig,
|
|
855
|
+
p2pPort: runtimeConfig.p2pPort,
|
|
856
|
+
getblockArchiveEndHeight: runtimeConfig.getblockArchiveEndHeight ?? null,
|
|
857
|
+
getblockArchiveSha256: runtimeConfig.getblockArchiveSha256 ?? null,
|
|
858
|
+
walletReplica,
|
|
859
|
+
startedAtUnixMs: nowUnixMs,
|
|
860
|
+
heartbeatAtUnixMs: nowUnixMs,
|
|
861
|
+
lastError: walletReplica.message ?? null,
|
|
862
|
+
});
|
|
797
863
|
};
|
|
798
|
-
|
|
799
|
-
detached: true,
|
|
800
|
-
stdio: "ignore",
|
|
801
|
-
});
|
|
802
|
-
child.unref();
|
|
803
|
-
const rpc = createRpcClient(rpcConfig);
|
|
864
|
+
let status;
|
|
804
865
|
try {
|
|
805
|
-
await
|
|
806
|
-
await validateNodeConfigForTesting(rpc, resolvedOptions.chain, zmqConfig.endpoint);
|
|
866
|
+
status = await startManagedProcess(resolvedOptions);
|
|
807
867
|
}
|
|
808
868
|
catch (error) {
|
|
809
|
-
if (
|
|
810
|
-
|
|
811
|
-
process.kill(child.pid, "SIGTERM");
|
|
812
|
-
}
|
|
813
|
-
catch {
|
|
814
|
-
// ignore kill failures during startup cleanup
|
|
815
|
-
}
|
|
869
|
+
if (resolvedOptions.getblockArchivePath === undefined || resolvedOptions.getblockArchivePath === null) {
|
|
870
|
+
throw error;
|
|
816
871
|
}
|
|
817
|
-
|
|
872
|
+
status = await startManagedProcess({
|
|
873
|
+
...resolvedOptions,
|
|
874
|
+
getblockArchivePath: null,
|
|
875
|
+
getblockArchiveEndHeight: null,
|
|
876
|
+
getblockArchiveSha256: null,
|
|
877
|
+
});
|
|
818
878
|
}
|
|
819
|
-
const nowUnixMs = Date.now();
|
|
820
|
-
const walletRootId = resolvedOptions.walletRootId ?? UNINITIALIZED_WALLET_ROOT_ID;
|
|
821
|
-
const walletReplica = await loadManagedWalletReplicaIfPresent(rpc, walletRootId, resolvedOptions.dataDir ?? "");
|
|
822
|
-
const status = createBitcoindServiceStatus({
|
|
823
|
-
binaryVersion,
|
|
824
|
-
serviceInstanceId: randomBytes(16).toString("hex"),
|
|
825
|
-
state: "ready",
|
|
826
|
-
processId: child.pid ?? null,
|
|
827
|
-
walletRootId,
|
|
828
|
-
chain: resolvedOptions.chain,
|
|
829
|
-
dataDir: resolvedOptions.dataDir ?? "",
|
|
830
|
-
runtimeRoot: paths.walletRuntimeRoot,
|
|
831
|
-
startHeight: resolvedOptions.startHeight,
|
|
832
|
-
rpc: rpcConfig,
|
|
833
|
-
zmq: zmqConfig,
|
|
834
|
-
p2pPort: runtimeConfig.p2pPort,
|
|
835
|
-
walletReplica,
|
|
836
|
-
startedAtUnixMs: nowUnixMs,
|
|
837
|
-
heartbeatAtUnixMs: nowUnixMs,
|
|
838
|
-
lastError: walletReplica.message ?? null,
|
|
839
|
-
});
|
|
840
879
|
await writeBitcoindStatus(paths, status);
|
|
841
880
|
return createNodeHandle(status, paths, resolvedOptions);
|
|
842
881
|
}
|
|
@@ -3,7 +3,7 @@ export { attachOrStartIndexerDaemon, readIndexerDaemonStatusForTesting, stopInde
|
|
|
3
3
|
export { normalizeRpcBlock } from "./normalize.js";
|
|
4
4
|
export { BitcoinRpcClient } from "./rpc.js";
|
|
5
5
|
export { attachOrStartManagedBitcoindService, buildManagedServiceArgsForTesting, readManagedBitcoindServiceStatusForTesting, resolveManagedBitcoindDbcacheMiB, stopManagedBitcoindService, shutdownManagedBitcoindServiceForTesting, writeBitcoinConfForTesting, } from "./service.js";
|
|
6
|
-
export { AssumeUtxoBootstrapController, DEFAULT_SNAPSHOT_METADATA, createBootstrapStateForTesting, downloadSnapshotFileForTesting, loadBootstrapStateForTesting, resolveBootstrapPathsForTesting, saveBootstrapStateForTesting, validateSnapshotFileForTesting, waitForHeadersForTesting, } from "./bootstrap.js";
|
|
6
|
+
export { AssumeUtxoBootstrapController, DEFAULT_SNAPSHOT_METADATA, createBootstrapStateForTesting, downloadSnapshotFileForTesting, loadBootstrapStateForTesting, prepareLatestGetblockArchiveForTesting, resolveBootstrapPathsForTesting, resolveGetblockArchivePathsForTesting, resolveReadyGetblockArchiveForTesting, saveBootstrapStateForTesting, validateSnapshotFileForTesting, waitForGetblockArchiveImportForTesting, 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";
|
|
9
9
|
export { WritingQuoteRotator, loadWritingQuotesForTesting, shuffleIndicesForTesting, } from "./quotes.js";
|
package/dist/bitcoind/testing.js
CHANGED
|
@@ -3,7 +3,7 @@ export { attachOrStartIndexerDaemon, readIndexerDaemonStatusForTesting, stopInde
|
|
|
3
3
|
export { normalizeRpcBlock } from "./normalize.js";
|
|
4
4
|
export { BitcoinRpcClient } from "./rpc.js";
|
|
5
5
|
export { attachOrStartManagedBitcoindService, buildManagedServiceArgsForTesting, readManagedBitcoindServiceStatusForTesting, resolveManagedBitcoindDbcacheMiB, stopManagedBitcoindService, shutdownManagedBitcoindServiceForTesting, writeBitcoinConfForTesting, } from "./service.js";
|
|
6
|
-
export { AssumeUtxoBootstrapController, DEFAULT_SNAPSHOT_METADATA, createBootstrapStateForTesting, downloadSnapshotFileForTesting, loadBootstrapStateForTesting, resolveBootstrapPathsForTesting, saveBootstrapStateForTesting, validateSnapshotFileForTesting, waitForHeadersForTesting, } from "./bootstrap.js";
|
|
6
|
+
export { AssumeUtxoBootstrapController, DEFAULT_SNAPSHOT_METADATA, createBootstrapStateForTesting, downloadSnapshotFileForTesting, loadBootstrapStateForTesting, prepareLatestGetblockArchiveForTesting, resolveBootstrapPathsForTesting, resolveGetblockArchivePathsForTesting, resolveReadyGetblockArchiveForTesting, saveBootstrapStateForTesting, validateSnapshotFileForTesting, waitForGetblockArchiveImportForTesting, 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";
|
|
9
9
|
export { WritingQuoteRotator, loadWritingQuotesForTesting, shuffleIndicesForTesting, } from "./quotes.js";
|
package/dist/bitcoind/types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { BitcoinBlock, Client, ClientOptions, ClientTip } from "../types.js";
|
|
2
|
-
export type BootstrapPhase = "snapshot_download" | "wait_headers_for_snapshot" | "load_snapshot" | "bitcoin_sync" | "cogcoin_sync" | "follow_tip" | "paused" | "error" | "complete";
|
|
2
|
+
export type BootstrapPhase = "getblock_archive_download" | "getblock_archive_import" | "snapshot_download" | "wait_headers_for_snapshot" | "load_snapshot" | "bitcoin_sync" | "cogcoin_sync" | "follow_tip" | "paused" | "error" | "complete";
|
|
3
3
|
export type ProgressOutputMode = "auto" | "tty" | "none";
|
|
4
4
|
export interface SnapshotMetadata {
|
|
5
5
|
url: string;
|
|
@@ -17,6 +17,28 @@ export interface SnapshotChunkManifest {
|
|
|
17
17
|
snapshotSha256: string;
|
|
18
18
|
chunkSha256s: string[];
|
|
19
19
|
}
|
|
20
|
+
export interface GetblockArchiveManifestBlockRecord {
|
|
21
|
+
height: number;
|
|
22
|
+
blockHash: string;
|
|
23
|
+
previousBlockHash: string;
|
|
24
|
+
recordOffset: number;
|
|
25
|
+
recordLength: number;
|
|
26
|
+
rawBlockSizeBytes: number;
|
|
27
|
+
}
|
|
28
|
+
export interface GetblockArchiveManifest {
|
|
29
|
+
formatVersion: number;
|
|
30
|
+
chain: "main";
|
|
31
|
+
baseSnapshotHeight: number;
|
|
32
|
+
firstBlockHeight: number;
|
|
33
|
+
endHeight: number;
|
|
34
|
+
blockCount: number;
|
|
35
|
+
artifactFilename: string;
|
|
36
|
+
artifactSizeBytes: number;
|
|
37
|
+
artifactSha256: string;
|
|
38
|
+
chunkSizeBytes: number;
|
|
39
|
+
chunkSha256s: string[];
|
|
40
|
+
blocks: GetblockArchiveManifestBlockRecord[];
|
|
41
|
+
}
|
|
20
42
|
export interface WritingQuote {
|
|
21
43
|
quote: string;
|
|
22
44
|
author: string;
|
|
@@ -63,6 +85,8 @@ export interface ManagedBitcoindRuntimeConfig {
|
|
|
63
85
|
zmqPort: number;
|
|
64
86
|
p2pPort: number;
|
|
65
87
|
dbcacheMiB: number;
|
|
88
|
+
getblockArchiveEndHeight?: number | null;
|
|
89
|
+
getblockArchiveSha256?: string | null;
|
|
66
90
|
}
|
|
67
91
|
export declare const MANAGED_BITCOIND_SERVICE_API_VERSION = "cogcoin/bitcoind-service/v1";
|
|
68
92
|
export type ManagedBitcoindServiceState = "starting" | "ready" | "stopping" | "failed";
|
|
@@ -81,6 +105,8 @@ export interface ManagedBitcoindServiceStatus {
|
|
|
81
105
|
rpc: BitcoindRpcConfig;
|
|
82
106
|
zmq: BitcoindZmqConfig;
|
|
83
107
|
p2pPort: number;
|
|
108
|
+
getblockArchiveEndHeight: number | null;
|
|
109
|
+
getblockArchiveSha256: string | null;
|
|
84
110
|
walletReplica: ManagedCoreWalletReplicaStatus | null;
|
|
85
111
|
startedAtUnixMs: number;
|
|
86
112
|
heartbeatAtUnixMs: number;
|
|
@@ -123,6 +149,10 @@ export interface ManagedBitcoindStatus {
|
|
|
123
149
|
serviceStatus?: ManagedBitcoindObservedStatus | null;
|
|
124
150
|
indexerDaemon?: ManagedIndexerDaemonObservedStatus | null;
|
|
125
151
|
}
|
|
152
|
+
export interface ManagedGetblockArchiveRestartRequest {
|
|
153
|
+
currentArchiveEndHeight: number | null;
|
|
154
|
+
nextArchiveEndHeight: number;
|
|
155
|
+
}
|
|
126
156
|
export interface ManagedBitcoindOptions extends ClientOptions {
|
|
127
157
|
dataDir?: string;
|
|
128
158
|
databasePath?: string;
|
|
@@ -137,6 +167,8 @@ export interface ManagedBitcoindOptions extends ClientOptions {
|
|
|
137
167
|
managedWalletPassphrase?: string;
|
|
138
168
|
onProgress?: (event: ManagedBitcoindProgressEvent) => void;
|
|
139
169
|
progressOutput?: ProgressOutputMode;
|
|
170
|
+
fetchImpl?: typeof fetch;
|
|
171
|
+
confirmGetblockArchiveRestart?: (request: ManagedGetblockArchiveRestartRequest) => Promise<boolean>;
|
|
140
172
|
}
|
|
141
173
|
export interface ManagedBitcoindClient extends Client {
|
|
142
174
|
syncToTip(): Promise<SyncResult>;
|
|
@@ -397,6 +429,8 @@ export interface ManagedBitcoindNodeHandle {
|
|
|
397
429
|
expectedChain: "main" | "regtest";
|
|
398
430
|
startHeight: number;
|
|
399
431
|
dataDir: string;
|
|
432
|
+
getblockArchiveEndHeight: number | null;
|
|
433
|
+
getblockArchiveSha256: string | null;
|
|
400
434
|
walletRootId?: string;
|
|
401
435
|
runtimeRoot?: string;
|
|
402
436
|
validate(): Promise<void>;
|
|
@@ -3,6 +3,7 @@ import { resolveWalletRootIdFromLocalArtifacts } from "../../wallet/root-resolut
|
|
|
3
3
|
import { usesTtyProgress, writeLine } from "../io.js";
|
|
4
4
|
import { classifyCliError } from "../output.js";
|
|
5
5
|
import { createStopSignalWatcher } from "../signals.js";
|
|
6
|
+
import { confirmGetblockArchiveRestart } from "./getblock-archive-restart.js";
|
|
6
7
|
export async function runFollowCommand(parsed, context) {
|
|
7
8
|
const dbPath = parsed.dbPath ?? context.resolveDefaultClientDatabasePath();
|
|
8
9
|
const dataDir = parsed.dataDir ?? context.resolveDefaultBitcoindDataDir();
|
|
@@ -23,6 +24,7 @@ export async function runFollowCommand(parsed, context) {
|
|
|
23
24
|
dataDir,
|
|
24
25
|
walletRootId: walletRoot.walletRootId,
|
|
25
26
|
progressOutput: parsed.progressOutput,
|
|
27
|
+
confirmGetblockArchiveRestart: async (options) => confirmGetblockArchiveRestart(parsed, context, options),
|
|
26
28
|
});
|
|
27
29
|
storeOwned = false;
|
|
28
30
|
const stopWatcher = createStopSignalWatcher(context.signalSource, context.stderr, client, context.forceExit);
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ParsedCliArgs, RequiredCliRunnerContext } from "../types.js";
|
|
2
|
+
export declare function confirmGetblockArchiveRestart(parsed: ParsedCliArgs, context: RequiredCliRunnerContext, options: {
|
|
3
|
+
currentArchiveEndHeight: number | null;
|
|
4
|
+
nextArchiveEndHeight: number;
|
|
5
|
+
}): Promise<boolean>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export async function confirmGetblockArchiveRestart(parsed, context, options) {
|
|
2
|
+
if (parsed.assumeYes) {
|
|
3
|
+
return true;
|
|
4
|
+
}
|
|
5
|
+
const prompter = context.createPrompter();
|
|
6
|
+
if (!prompter.isInteractive) {
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
const currentLabel = options.currentArchiveEndHeight === null
|
|
10
|
+
? "without a getblock archive"
|
|
11
|
+
: `with a getblock archive through height ${options.currentArchiveEndHeight.toLocaleString()}`;
|
|
12
|
+
prompter.writeLine(`Managed bitcoind is already running ${currentLabel}. A newer getblock archive through height ${options.nextArchiveEndHeight.toLocaleString()} is available.`);
|
|
13
|
+
const answer = (await prompter.prompt(`Restart managed bitcoind to load the getblock archive through height ${options.nextArchiveEndHeight.toLocaleString()}? [y/N]: `)).trim().toLowerCase();
|
|
14
|
+
return answer === "y" || answer === "yes";
|
|
15
|
+
}
|
|
@@ -12,11 +12,13 @@ function createCommandPrompter(parsed, context) {
|
|
|
12
12
|
export async function runMiningAdminCommand(parsed, context) {
|
|
13
13
|
try {
|
|
14
14
|
const provider = context.walletSecretProvider;
|
|
15
|
+
const runtimePaths = context.resolveWalletRuntimePaths(parsed.seedName);
|
|
15
16
|
if (parsed.command === "hooks-mining-enable") {
|
|
16
17
|
const prompter = createCommandPrompter(parsed, context);
|
|
17
18
|
const view = await context.enableMiningHooks({
|
|
18
19
|
provider,
|
|
19
20
|
prompter,
|
|
21
|
+
paths: runtimePaths,
|
|
20
22
|
});
|
|
21
23
|
const nextSteps = getHooksEnableMiningNextSteps();
|
|
22
24
|
if (parsed.outputMode === "preview-json") {
|
|
@@ -40,6 +42,7 @@ export async function runMiningAdminCommand(parsed, context) {
|
|
|
40
42
|
if (parsed.command === "hooks-mining-disable") {
|
|
41
43
|
const view = await context.disableMiningHooks({
|
|
42
44
|
provider,
|
|
45
|
+
paths: runtimePaths,
|
|
43
46
|
});
|
|
44
47
|
if (parsed.outputMode === "preview-json") {
|
|
45
48
|
writeJsonValue(context.stdout, createPreviewSuccessEnvelope(resolvePreviewJsonSchema(parsed), describeCanonicalCommand(parsed), "disabled", buildHooksPreviewData("hooks-disable-mining", view)));
|
|
@@ -57,6 +60,7 @@ export async function runMiningAdminCommand(parsed, context) {
|
|
|
57
60
|
const view = await context.setupBuiltInMining({
|
|
58
61
|
provider,
|
|
59
62
|
prompter,
|
|
63
|
+
paths: runtimePaths,
|
|
60
64
|
});
|
|
61
65
|
const nextSteps = getMineSetupNextSteps();
|
|
62
66
|
if (parsed.outputMode === "preview-json") {
|
|
@@ -5,9 +5,7 @@ import { writeLine } from "../io.js";
|
|
|
5
5
|
import { inspectWalletLocalState } from "../../wallet/read/index.js";
|
|
6
6
|
import { createErrorEnvelope, createSuccessEnvelope, describeCanonicalCommand, normalizeListPage, writeJsonValue, } from "../output.js";
|
|
7
7
|
import { buildHooksStatusJson, buildMineLogJson, buildMineStatusJson } from "../read-json.js";
|
|
8
|
-
|
|
9
|
-
async function readRotationIndices() {
|
|
10
|
-
const paths = resolveWalletRuntimePathsForTesting();
|
|
8
|
+
async function readRotationIndices(paths) {
|
|
11
9
|
const rotation = [];
|
|
12
10
|
for (let index = 1; index <= 4; index += 1) {
|
|
13
11
|
try {
|
|
@@ -26,10 +24,12 @@ export async function runMiningReadCommand(parsed, context) {
|
|
|
26
24
|
try {
|
|
27
25
|
const dbPath = parsed.dbPath ?? context.resolveDefaultClientDatabasePath();
|
|
28
26
|
const dataDir = parsed.dataDir ?? context.resolveDefaultBitcoindDataDir();
|
|
27
|
+
const runtimePaths = context.resolveWalletRuntimePaths(parsed.seedName);
|
|
29
28
|
await context.ensureDirectory(dirname(dbPath));
|
|
30
29
|
if (parsed.command === "hooks-mining-status") {
|
|
31
30
|
const localState = await inspectWalletLocalState({
|
|
32
31
|
secretProvider: context.walletSecretProvider,
|
|
32
|
+
paths: runtimePaths,
|
|
33
33
|
});
|
|
34
34
|
const view = await context.inspectMiningControlPlane({
|
|
35
35
|
provider: context.walletSecretProvider,
|
|
@@ -52,6 +52,7 @@ export async function runMiningReadCommand(parsed, context) {
|
|
|
52
52
|
openedAtUnixMs: null,
|
|
53
53
|
},
|
|
54
54
|
verify: parsed.verify,
|
|
55
|
+
paths: runtimePaths,
|
|
55
56
|
});
|
|
56
57
|
if (parsed.outputMode === "json") {
|
|
57
58
|
const result = buildHooksStatusJson(view);
|
|
@@ -79,7 +80,7 @@ export async function runMiningReadCommand(parsed, context) {
|
|
|
79
80
|
const events = normalized.items.slice().reverse();
|
|
80
81
|
if (events.length === 0) {
|
|
81
82
|
if (parsed.outputMode === "json") {
|
|
82
|
-
const result = buildMineLogJson(events, normalized.page, await readRotationIndices());
|
|
83
|
+
const result = buildMineLogJson(events, normalized.page, await readRotationIndices(runtimePaths));
|
|
83
84
|
writeJsonValue(context.stdout, createSuccessEnvelope("cogcoin/mine-log/v1", describeCanonicalCommand(parsed), result.data, {
|
|
84
85
|
warnings: result.warnings,
|
|
85
86
|
explanations: result.explanations,
|
|
@@ -91,7 +92,7 @@ export async function runMiningReadCommand(parsed, context) {
|
|
|
91
92
|
return 0;
|
|
92
93
|
}
|
|
93
94
|
if (parsed.outputMode === "json") {
|
|
94
|
-
const result = buildMineLogJson(events, normalized.page, await readRotationIndices());
|
|
95
|
+
const result = buildMineLogJson(events, normalized.page, await readRotationIndices(runtimePaths));
|
|
95
96
|
writeJsonValue(context.stdout, createSuccessEnvelope("cogcoin/mine-log/v1", describeCanonicalCommand(parsed), result.data, {
|
|
96
97
|
warnings: result.warnings,
|
|
97
98
|
explanations: result.explanations,
|
|
@@ -131,6 +132,7 @@ export async function runMiningReadCommand(parsed, context) {
|
|
|
131
132
|
dataDir,
|
|
132
133
|
databasePath: dbPath,
|
|
133
134
|
secretProvider: context.walletSecretProvider,
|
|
135
|
+
paths: runtimePaths,
|
|
134
136
|
});
|
|
135
137
|
try {
|
|
136
138
|
const mining = readContext.mining ?? await context.inspectMiningControlPlane({
|
|
@@ -140,6 +142,7 @@ export async function runMiningReadCommand(parsed, context) {
|
|
|
140
142
|
nodeStatus: readContext.nodeStatus,
|
|
141
143
|
nodeHealth: readContext.nodeHealth,
|
|
142
144
|
indexer: readContext.indexer,
|
|
145
|
+
paths: runtimePaths,
|
|
143
146
|
});
|
|
144
147
|
if (parsed.outputMode === "json") {
|
|
145
148
|
const result = buildMineStatusJson(mining);
|
|
@@ -15,6 +15,7 @@ export async function runMiningRuntimeCommand(parsed, context) {
|
|
|
15
15
|
const dbPath = parsed.dbPath ?? context.resolveDefaultClientDatabasePath();
|
|
16
16
|
const dataDir = parsed.dataDir ?? context.resolveDefaultBitcoindDataDir();
|
|
17
17
|
const provider = context.walletSecretProvider;
|
|
18
|
+
const runtimePaths = context.resolveWalletRuntimePaths(parsed.seedName);
|
|
18
19
|
await context.ensureDirectory(dirname(dbPath));
|
|
19
20
|
if (parsed.command === "mine") {
|
|
20
21
|
const abortController = new AbortController();
|
|
@@ -33,6 +34,7 @@ export async function runMiningRuntimeCommand(parsed, context) {
|
|
|
33
34
|
stdout: context.stdout,
|
|
34
35
|
stderr: context.stderr,
|
|
35
36
|
progressOutput: parsed.progressOutput,
|
|
37
|
+
paths: runtimePaths,
|
|
36
38
|
});
|
|
37
39
|
}
|
|
38
40
|
finally {
|
|
@@ -47,6 +49,7 @@ export async function runMiningRuntimeCommand(parsed, context) {
|
|
|
47
49
|
databasePath: dbPath,
|
|
48
50
|
provider,
|
|
49
51
|
prompter: createCommandPrompter(parsed, context),
|
|
52
|
+
paths: runtimePaths,
|
|
50
53
|
});
|
|
51
54
|
if (parsed.outputMode === "preview-json") {
|
|
52
55
|
writeJsonValue(context.stdout, createPreviewSuccessEnvelope(resolvePreviewJsonSchema(parsed), describeCanonicalCommand(parsed), result.started ? "started" : "already-active", buildMineStartPreviewData(result)));
|
|
@@ -74,6 +77,7 @@ export async function runMiningRuntimeCommand(parsed, context) {
|
|
|
74
77
|
dataDir,
|
|
75
78
|
databasePath: dbPath,
|
|
76
79
|
provider,
|
|
80
|
+
paths: runtimePaths,
|
|
77
81
|
});
|
|
78
82
|
const nextSteps = getMineStopNextSteps();
|
|
79
83
|
if (parsed.outputMode === "preview-json") {
|