@cogcoin/client 1.2.3 → 1.2.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 +12 -2
- package/dist/bitcoind/managed-bitcoind-service-config.d.ts +5 -1
- package/dist/bitcoind/managed-bitcoind-service-config.js +27 -18
- package/dist/bitcoind/managed-bitcoind-service-lifecycle.js +46 -3
- package/dist/bitcoind/managed-bitcoind-service-status.d.ts +9 -2
- package/dist/bitcoind/managed-bitcoind-service-status.js +65 -9
- package/dist/bitcoind/managed-bitcoind-service-types.d.ts +8 -0
- package/dist/bitcoind/managed-runtime/bitcoind-policy.js +27 -0
- package/dist/bitcoind/managed-runtime/bitcoind-runtime.js +6 -0
- package/dist/bitcoind/managed-runtime/types.d.ts +2 -2
- package/dist/bitcoind/retryable-rpc.d.ts +1 -0
- package/dist/bitcoind/retryable-rpc.js +19 -2
- package/dist/cli/command-registry.js +2 -2
- package/dist/cli/commands/service-runtime.js +22 -2
- package/dist/cli/commands/status.js +7 -1
- package/dist/cli/commands/wallet-admin.js +8 -2
- package/dist/cli/context.js +2 -0
- package/dist/cli/output/rules/cli-surface.js +7 -0
- package/dist/cli/output/rules/services.js +7 -0
- package/dist/cli/parse.js +9 -0
- package/dist/cli/status-format.d.ts +2 -2
- package/dist/cli/status-format.js +167 -28
- package/dist/cli/types.d.ts +3 -0
- package/dist/passive-status.d.ts +49 -1
- package/dist/passive-status.js +208 -2
- package/dist/wallet/lifecycle/context.js +1 -0
- package/dist/wallet/lifecycle/repair-bitcoind.js +44 -1
- package/dist/wallet/lifecycle/repair-runtime.d.ts +3 -1
- package/dist/wallet/lifecycle/repair-runtime.js +12 -0
- package/dist/wallet/lifecycle/repair.js +31 -9
- package/dist/wallet/lifecycle/types.d.ts +7 -0
- package/dist/wallet/mining/competitiveness.js +2 -2
- package/dist/wallet/mining/lifecycle.js +4 -0
- package/dist/wallet/mining/mempool-index.js +29 -3
- package/dist/wallet/read/managed-bitcoind.js +9 -0
- package/package.json +1 -1
|
@@ -38,7 +38,10 @@ function getResetNextSteps(result) {
|
|
|
38
38
|
? ["Run `cogcoin init` to create or restore a wallet."]
|
|
39
39
|
: ["Run `cogcoin sync` to bootstrap assumeutxo and the managed Bitcoin/indexer state."];
|
|
40
40
|
}
|
|
41
|
-
function getRepairNextSteps() {
|
|
41
|
+
function getRepairNextSteps(result) {
|
|
42
|
+
if (result.bitcoindPostRepairHealth === "starting") {
|
|
43
|
+
return ["Wait for Bitcoin Core to finish loading, then run `cogcoin status` or rerun `cogcoin mine`."];
|
|
44
|
+
}
|
|
42
45
|
return ["Run `cogcoin status` to review the repaired local state."];
|
|
43
46
|
}
|
|
44
47
|
function formatResetBitcoinDataDirStatus(result) {
|
|
@@ -116,7 +119,7 @@ function buildRepairWarningEntries(result) {
|
|
|
116
119
|
return entries;
|
|
117
120
|
}
|
|
118
121
|
function formatRepairResultText(result) {
|
|
119
|
-
const nextStep = getRepairNextSteps()[0] ?? null;
|
|
122
|
+
const nextStep = getRepairNextSteps(result)[0] ?? null;
|
|
120
123
|
const warningEntries = buildRepairWarningEntries(result);
|
|
121
124
|
const sections = [
|
|
122
125
|
formatAdminSection("Wallet", [
|
|
@@ -244,6 +247,9 @@ export async function runWalletAdminCommand(parsed, context) {
|
|
|
244
247
|
provider: repairProvider,
|
|
245
248
|
assumeYes: parsed.assumeYes,
|
|
246
249
|
paths: runtimePaths,
|
|
250
|
+
progress: async (event) => {
|
|
251
|
+
writeLine(context.stdout, event.message);
|
|
252
|
+
},
|
|
247
253
|
});
|
|
248
254
|
writeLine(context.stdout, formatRepairResultText(result));
|
|
249
255
|
return 0;
|
package/dist/cli/context.js
CHANGED
|
@@ -3,6 +3,7 @@ import { mkdir } from "node:fs/promises";
|
|
|
3
3
|
import { attachOrStartIndexerDaemon, probeIndexerDaemon, readObservedIndexerDaemonStatus, stopIndexerDaemonService, } from "../bitcoind/indexer-daemon.js";
|
|
4
4
|
import { createRpcClient } from "../bitcoind/node.js";
|
|
5
5
|
import { attachOrStartManagedBitcoindService, probeManagedBitcoindService, stopManagedBitcoindService, } from "../bitcoind/service.js";
|
|
6
|
+
import { refreshManagedBitcoindStatus } from "../bitcoind/managed-bitcoind-service-status.js";
|
|
6
7
|
import { resolveDefaultBitcoindDataDirForTesting, resolveDefaultClientDatabasePathForTesting, resolveDefaultUpdateCheckStatePathForTesting, } from "../app-paths.js";
|
|
7
8
|
import { openManagedBitcoindClient } from "../bitcoind/index.js";
|
|
8
9
|
import { openManagedIndexerMonitor } from "../bitcoind/indexer-monitor.js";
|
|
@@ -106,6 +107,7 @@ export function createDefaultContext(overrides = {}) {
|
|
|
106
107
|
}),
|
|
107
108
|
attachManagedBitcoindService: overrides.attachManagedBitcoindService ?? attachOrStartManagedBitcoindService,
|
|
108
109
|
probeManagedBitcoindService: overrides.probeManagedBitcoindService ?? probeManagedBitcoindService,
|
|
110
|
+
refreshManagedBitcoindServiceStatus: overrides.refreshManagedBitcoindServiceStatus ?? refreshManagedBitcoindStatus,
|
|
109
111
|
stopManagedBitcoindService: overrides.stopManagedBitcoindService ?? stopManagedBitcoindService,
|
|
110
112
|
createBitcoinRpcClient: overrides.createBitcoinRpcClient ?? createRpcClient,
|
|
111
113
|
attachIndexerDaemon: overrides.attachIndexerDaemon ?? attachOrStartIndexerDaemon,
|
|
@@ -77,6 +77,13 @@ export const cliSurfaceErrorRules = [
|
|
|
77
77
|
next: "Drop `--satvb` for this command, or use it with a wallet mutation command like `cogcoin register` or `cogcoin send`.",
|
|
78
78
|
};
|
|
79
79
|
}
|
|
80
|
+
if (errorCode === "cli_live_not_supported_for_command") {
|
|
81
|
+
return {
|
|
82
|
+
what: "This command does not support `--live`.",
|
|
83
|
+
why: "`--live` only applies to `cogcoin status`, where it opts into RPC-backed wallet and service checks.",
|
|
84
|
+
next: "Drop `--live`, or run `cogcoin status --live`.",
|
|
85
|
+
};
|
|
86
|
+
}
|
|
80
87
|
if (errorCode === "cli_anchor_clear_removed") {
|
|
81
88
|
return {
|
|
82
89
|
what: "`anchor clear` is no longer available.",
|
|
@@ -21,6 +21,13 @@ export const serviceErrorRules = [
|
|
|
21
21
|
next: "Rerun the command in an interactive terminal.",
|
|
22
22
|
};
|
|
23
23
|
}
|
|
24
|
+
if (errorCode === "managed_bitcoind_service_starting" || /^bitcoind_rpc_[^_]+_-28(?:_|$)/.test(errorCode)) {
|
|
25
|
+
return {
|
|
26
|
+
what: "Bitcoin Core is still loading.",
|
|
27
|
+
why: "The managed Bitcoin RPC service is alive, but Bitcoin Core is still warming up and returned its normal startup -28 response.",
|
|
28
|
+
next: "Wait for the node to finish loading, then rerun the command. Use `cogcoin status` to check readiness.",
|
|
29
|
+
};
|
|
30
|
+
}
|
|
24
31
|
if (errorCode.includes("tip_mismatch") || errorCode.includes("stale") || errorCode.includes("catching_up") || errorCode.includes("starting")) {
|
|
25
32
|
return {
|
|
26
33
|
what: "Trusted service state is not ready.",
|
package/dist/cli/parse.js
CHANGED
|
@@ -37,6 +37,7 @@ export function parseCliArgs(argv) {
|
|
|
37
37
|
let listLimit = null;
|
|
38
38
|
let listAll = false;
|
|
39
39
|
let follow = false;
|
|
40
|
+
let statusLive = false;
|
|
40
41
|
for (let index = 0; index < argv.length; index += 1) {
|
|
41
42
|
const token = argv[index];
|
|
42
43
|
if (token === "--help") {
|
|
@@ -238,6 +239,10 @@ export function parseCliArgs(argv) {
|
|
|
238
239
|
follow = true;
|
|
239
240
|
continue;
|
|
240
241
|
}
|
|
242
|
+
if (token === "--live") {
|
|
243
|
+
statusLive = true;
|
|
244
|
+
continue;
|
|
245
|
+
}
|
|
241
246
|
if (token === "--yes") {
|
|
242
247
|
assumeYes = true;
|
|
243
248
|
continue;
|
|
@@ -448,6 +453,9 @@ export function parseCliArgs(argv) {
|
|
|
448
453
|
if (follow && command !== "mine-log") {
|
|
449
454
|
throw new Error("cli_follow_not_supported_for_command");
|
|
450
455
|
}
|
|
456
|
+
if (statusLive && command !== "status") {
|
|
457
|
+
throw new Error("cli_live_not_supported_for_command");
|
|
458
|
+
}
|
|
451
459
|
if (command === "mine-log" && follow && (listAll || listLimit !== null)) {
|
|
452
460
|
throw new Error("cli_follow_limit_not_supported");
|
|
453
461
|
}
|
|
@@ -502,5 +510,6 @@ export function parseCliArgs(argv) {
|
|
|
502
510
|
listLimit,
|
|
503
511
|
listAll,
|
|
504
512
|
follow,
|
|
513
|
+
statusLive,
|
|
505
514
|
};
|
|
506
515
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare function formatStatusReport(status:
|
|
1
|
+
import type { PassiveClientStatus } from "../passive-status.js";
|
|
2
|
+
export declare function formatStatusReport(status: PassiveClientStatus, version: string): string;
|
|
@@ -1,48 +1,187 @@
|
|
|
1
|
+
function row(ok, text) {
|
|
2
|
+
return { ok, text };
|
|
3
|
+
}
|
|
4
|
+
function formatMarker(ok) {
|
|
5
|
+
return ok ? "✓" : "✗";
|
|
6
|
+
}
|
|
7
|
+
function formatValue(value) {
|
|
8
|
+
return value === null || value === undefined || value === "" ? "none" : String(value);
|
|
9
|
+
}
|
|
10
|
+
function formatYesNo(value) {
|
|
11
|
+
return value ? "yes" : "no";
|
|
12
|
+
}
|
|
1
13
|
function formatBootstrapPercent(current, total) {
|
|
2
14
|
if (total <= 0) {
|
|
3
15
|
return "0.00";
|
|
4
16
|
}
|
|
5
17
|
return ((current / total) * 100).toFixed(2);
|
|
6
18
|
}
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
19
|
+
function formatSignedDelta(value) {
|
|
20
|
+
if (value > 0) {
|
|
21
|
+
return `+${value}`;
|
|
22
|
+
}
|
|
23
|
+
return String(value);
|
|
24
|
+
}
|
|
25
|
+
function formatSection(title, rows) {
|
|
26
|
+
return [
|
|
27
|
+
title,
|
|
28
|
+
...rows.map((entry) => `${formatMarker(entry.ok)} ${entry.text}`),
|
|
29
|
+
].join("\n");
|
|
30
|
+
}
|
|
31
|
+
function buildPathsRows(status) {
|
|
32
|
+
return [
|
|
33
|
+
row(true, `DB path: ${status.dbPath}`),
|
|
34
|
+
row(true, `Bitcoin datadir: ${status.bitcoinDataDir}`),
|
|
35
|
+
];
|
|
36
|
+
}
|
|
37
|
+
function buildWalletRows(status) {
|
|
38
|
+
const rows = [
|
|
39
|
+
row(status.wallet.walletRootId !== null && status.wallet.error === null, `Wallet root: ${status.wallet.walletRootId ?? "unknown"} (${status.wallet.source})`),
|
|
40
|
+
];
|
|
41
|
+
if (status.wallet.error !== null) {
|
|
42
|
+
rows.push(row(false, `Wallet root error: ${status.wallet.error}`));
|
|
43
|
+
}
|
|
44
|
+
return rows;
|
|
45
|
+
}
|
|
46
|
+
function buildLocalStoreRows(status) {
|
|
47
|
+
const rows = [
|
|
48
|
+
row(status.storeExists, `Store exists: ${formatYesNo(status.storeExists)}`),
|
|
49
|
+
row(status.storeInitialized, `Store initialized: ${formatYesNo(status.storeInitialized)}`),
|
|
14
50
|
];
|
|
15
51
|
if (status.storeError !== null) {
|
|
16
|
-
|
|
52
|
+
rows.push(row(false, `Store error: ${status.storeError}`));
|
|
17
53
|
}
|
|
18
54
|
if (status.indexedTip === null) {
|
|
19
|
-
|
|
55
|
+
rows.push(row(false, "Indexed tip: none"));
|
|
20
56
|
}
|
|
21
57
|
else {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
58
|
+
rows.push(row(true, `Indexed tip height: ${status.indexedTip.height}`));
|
|
59
|
+
rows.push(row(true, `Indexed tip hash: ${status.indexedTip.blockHashHex}`));
|
|
60
|
+
rows.push(row(status.indexedTip.stateHashHex !== null, `Indexed tip state hash: ${formatValue(status.indexedTip.stateHashHex)}`));
|
|
25
61
|
}
|
|
26
62
|
if (status.latestCheckpoint === null) {
|
|
27
|
-
|
|
63
|
+
rows.push(row(false, "Latest checkpoint: none"));
|
|
28
64
|
}
|
|
29
65
|
else {
|
|
30
|
-
|
|
31
|
-
|
|
66
|
+
rows.push(row(true, `Latest checkpoint height: ${status.latestCheckpoint.height}`));
|
|
67
|
+
rows.push(row(true, `Latest checkpoint hash: ${status.latestCheckpoint.blockHashHex}`));
|
|
68
|
+
}
|
|
69
|
+
if (status.indexedTip !== null && status.indexer.appliedTipHeight !== null) {
|
|
70
|
+
const delta = status.indexedTip.height - status.indexer.appliedTipHeight;
|
|
71
|
+
rows.push(row(Math.abs(delta) <= 1, `Store/indexer height delta: ${formatSignedDelta(delta)}`));
|
|
32
72
|
}
|
|
73
|
+
return rows;
|
|
74
|
+
}
|
|
75
|
+
function buildBootstrapRows(status) {
|
|
33
76
|
if (status.bootstrap === null) {
|
|
34
|
-
|
|
77
|
+
return [row(false, "Bootstrap state: none")];
|
|
35
78
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
79
|
+
return [
|
|
80
|
+
row(status.bootstrap.lastError === null, `Bootstrap phase: ${status.bootstrap.phase}`),
|
|
81
|
+
row(status.bootstrap.lastError === null, `Bootstrap download: ${status.bootstrap.downloadedBytes} / ${status.bootstrap.totalBytes} bytes (${formatBootstrapPercent(status.bootstrap.downloadedBytes, status.bootstrap.totalBytes)}%)`),
|
|
82
|
+
row(status.bootstrap.validated, `Bootstrap validated: ${formatYesNo(status.bootstrap.validated)}`),
|
|
83
|
+
row(status.bootstrap.loadTxOutSetComplete, `Bootstrap loaded: ${formatYesNo(status.bootstrap.loadTxOutSetComplete)}`),
|
|
84
|
+
row(status.bootstrap.baseHeight !== null, `Bootstrap base height: ${formatValue(status.bootstrap.baseHeight)}`),
|
|
85
|
+
row(status.bootstrap.tipHashHex !== null, `Bootstrap tip hash: ${formatValue(status.bootstrap.tipHashHex)}`),
|
|
86
|
+
row(status.bootstrap.snapshotHeight !== null, `Bootstrap snapshot height: ${formatValue(status.bootstrap.snapshotHeight)}`),
|
|
87
|
+
row(status.bootstrap.lastError === null, `Bootstrap last error: ${formatValue(status.bootstrap.lastError)}`),
|
|
88
|
+
];
|
|
89
|
+
}
|
|
90
|
+
function buildManagedBitcoindRows(status) {
|
|
91
|
+
if (status.managedBitcoind.error !== null) {
|
|
92
|
+
return [
|
|
93
|
+
row(false, "Managed bitcoind: corrupt"),
|
|
94
|
+
row(false, `Managed bitcoind status path: ${formatValue(status.managedBitcoind.statusPath)}`),
|
|
95
|
+
row(false, `Managed bitcoind status error: ${status.managedBitcoind.error}`),
|
|
96
|
+
];
|
|
97
|
+
}
|
|
98
|
+
if (!status.managedBitcoind.present) {
|
|
99
|
+
return [row(false, "Managed bitcoind: unavailable")];
|
|
100
|
+
}
|
|
101
|
+
return [
|
|
102
|
+
row(status.managedBitcoind.state === "ready", `Managed bitcoind: ${formatValue(status.managedBitcoind.state)}`),
|
|
103
|
+
row(status.managedBitcoind.processId !== null, `Managed bitcoind pid: ${formatValue(status.managedBitcoind.processId)}`),
|
|
104
|
+
row(status.managedBitcoind.walletRootId !== null, `Managed bitcoind wallet root: ${formatValue(status.managedBitcoind.walletRootId)}`),
|
|
105
|
+
row(status.managedBitcoind.heartbeatAtUnixMs !== null, `Managed bitcoind heartbeat: ${formatValue(status.managedBitcoind.heartbeatAtUnixMs)}`),
|
|
106
|
+
row(status.managedBitcoind.updatedAtUnixMs !== null, `Managed bitcoind updated: ${formatValue(status.managedBitcoind.updatedAtUnixMs)}`),
|
|
107
|
+
row(status.managedBitcoind.lastError === null, `Managed bitcoind last error: ${formatValue(status.managedBitcoind.lastError)}`),
|
|
108
|
+
];
|
|
109
|
+
}
|
|
110
|
+
function buildIndexerRows(status) {
|
|
111
|
+
if (status.indexer.error !== null) {
|
|
112
|
+
return [
|
|
113
|
+
row(false, "Indexer: corrupt"),
|
|
114
|
+
row(false, `Indexer status path: ${formatValue(status.indexer.statusPath)}`),
|
|
115
|
+
row(false, `Indexer status error: ${status.indexer.error}`),
|
|
116
|
+
];
|
|
117
|
+
}
|
|
118
|
+
if (!status.indexer.present) {
|
|
119
|
+
return [row(false, "Indexer: unavailable")];
|
|
120
|
+
}
|
|
121
|
+
const rows = [
|
|
122
|
+
row(status.indexer.state === "synced", `Indexer: ${formatValue(status.indexer.state)}`),
|
|
123
|
+
row(status.indexer.processId !== null, `Indexer pid: ${formatValue(status.indexer.processId)}`),
|
|
124
|
+
row(status.indexer.walletRootId !== null, `Indexer wallet root: ${formatValue(status.indexer.walletRootId)}`),
|
|
125
|
+
row(status.indexer.coreBestHeight !== null, `Indexer core best height: ${formatValue(status.indexer.coreBestHeight)}`),
|
|
126
|
+
row(status.indexer.appliedTipHeight !== null, `Indexer applied tip height: ${formatValue(status.indexer.appliedTipHeight)}`),
|
|
127
|
+
row(status.indexer.appliedTipHash !== null, `Indexer applied tip hash: ${formatValue(status.indexer.appliedTipHash)}`),
|
|
128
|
+
row(status.indexer.heartbeatAtUnixMs !== null, `Indexer heartbeat: ${formatValue(status.indexer.heartbeatAtUnixMs)}`),
|
|
129
|
+
row(status.indexer.updatedAtUnixMs !== null, `Indexer updated: ${formatValue(status.indexer.updatedAtUnixMs)}`),
|
|
130
|
+
row(status.indexer.lastError === null, `Indexer last error: ${formatValue(status.indexer.lastError)}`),
|
|
131
|
+
];
|
|
132
|
+
if (status.indexer.coreBestHeight !== null && status.indexer.appliedTipHeight !== null) {
|
|
133
|
+
const lag = Math.max(0, status.indexer.coreBestHeight - status.indexer.appliedTipHeight);
|
|
134
|
+
rows.push(row(lag === 0, `Indexer lag: ${lag} blocks`));
|
|
135
|
+
}
|
|
136
|
+
return rows;
|
|
137
|
+
}
|
|
138
|
+
function buildManagedServicesRows(status) {
|
|
139
|
+
return [
|
|
140
|
+
...buildManagedBitcoindRows(status),
|
|
141
|
+
...buildIndexerRows(status),
|
|
142
|
+
];
|
|
143
|
+
}
|
|
144
|
+
function buildMiningRows(status) {
|
|
145
|
+
if (status.mining.error !== null) {
|
|
146
|
+
return [
|
|
147
|
+
row(false, "Mining state: corrupt"),
|
|
148
|
+
row(false, `Mining status path: ${formatValue(status.mining.statusPath)}`),
|
|
149
|
+
row(false, `Mining status error: ${status.mining.error}`),
|
|
150
|
+
];
|
|
151
|
+
}
|
|
152
|
+
if (!status.mining.present) {
|
|
153
|
+
return [row(false, "Mining state: unavailable")];
|
|
154
|
+
}
|
|
155
|
+
const miningHasError = status.mining.lastError !== null;
|
|
156
|
+
const needsBackgroundWorker = status.mining.runMode === "background";
|
|
157
|
+
return [
|
|
158
|
+
row(!miningHasError, `Mining run mode: ${formatValue(status.mining.runMode)}`),
|
|
159
|
+
row(!miningHasError, `Mining state: ${formatValue(status.mining.miningState)}`),
|
|
160
|
+
row(!miningHasError, `Mining phase: ${formatValue(status.mining.currentPhase)}`),
|
|
161
|
+
row(!needsBackgroundWorker || status.mining.backgroundWorkerPid !== null, `Mining background worker pid: ${formatValue(status.mining.backgroundWorkerPid)}`),
|
|
162
|
+
row(!needsBackgroundWorker || status.mining.backgroundWorkerHealth !== null, `Mining background worker health: ${formatValue(status.mining.backgroundWorkerHealth)}`),
|
|
163
|
+
row(status.mining.updatedAtUnixMs !== null, `Mining updated: ${formatValue(status.mining.updatedAtUnixMs)}`),
|
|
164
|
+
row(!miningHasError, `Mining last error: ${formatValue(status.mining.lastError)}`),
|
|
165
|
+
row(status.mining.note === null, `Mining note: ${formatValue(status.mining.note)}`),
|
|
166
|
+
];
|
|
167
|
+
}
|
|
168
|
+
function buildPassiveModeRows() {
|
|
169
|
+
return [
|
|
170
|
+
row(true, "Live node: not checked"),
|
|
171
|
+
row(true, "Password prompt: not required"),
|
|
172
|
+
row(true, "RPC-backed balance: not checked"),
|
|
173
|
+
];
|
|
174
|
+
}
|
|
175
|
+
export function formatStatusReport(status, version) {
|
|
176
|
+
return [
|
|
177
|
+
`⛭ Cogcoin Status v${version} (passive) ⛭`,
|
|
178
|
+
formatSection("Paths", buildPathsRows(status)),
|
|
179
|
+
formatSection("Wallet", buildWalletRows(status)),
|
|
180
|
+
formatSection("Local Store", buildLocalStoreRows(status)),
|
|
181
|
+
formatSection("Bootstrap", buildBootstrapRows(status)),
|
|
182
|
+
formatSection("Managed Services", buildManagedServicesRows(status)),
|
|
183
|
+
formatSection("Mining", buildMiningRows(status)),
|
|
184
|
+
formatSection("Passive Mode", buildPassiveModeRows()),
|
|
185
|
+
"Run cogcoin status --live for RPC-backed balance and full service verification.",
|
|
186
|
+
].join("\n\n");
|
|
48
187
|
}
|
package/dist/cli/types.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { createRpcClient } from "../bitcoind/node.js";
|
|
|
4
4
|
import type { ManagedBitcoindProgressEvent } from "../bitcoind/types.js";
|
|
5
5
|
import { attachOrStartIndexerDaemon, probeIndexerDaemon, readObservedIndexerDaemonStatus, stopIndexerDaemonService } from "../bitcoind/indexer-daemon.js";
|
|
6
6
|
import { attachOrStartManagedBitcoindService, probeManagedBitcoindService, stopManagedBitcoindService } from "../bitcoind/service.js";
|
|
7
|
+
import type { refreshManagedBitcoindStatus } from "../bitcoind/managed-bitcoind-service-status.js";
|
|
7
8
|
import { openSqliteStore } from "../sqlite/index.js";
|
|
8
9
|
import type { ClientStoreAdapter } from "../types.js";
|
|
9
10
|
import type { WalletRuntimePaths } from "../wallet/runtime.js";
|
|
@@ -64,6 +65,7 @@ export interface ParsedCliArgs {
|
|
|
64
65
|
listLimit: number | null;
|
|
65
66
|
listAll: boolean;
|
|
66
67
|
follow: boolean;
|
|
68
|
+
statusLive: boolean;
|
|
67
69
|
}
|
|
68
70
|
export interface ManagedClientLike {
|
|
69
71
|
syncToTip(): Promise<{
|
|
@@ -115,6 +117,7 @@ export interface CliRunnerContext {
|
|
|
115
117
|
openManagedIndexerMonitor?: typeof openManagedIndexerMonitor;
|
|
116
118
|
attachManagedBitcoindService?: typeof attachOrStartManagedBitcoindService;
|
|
117
119
|
probeManagedBitcoindService?: typeof probeManagedBitcoindService;
|
|
120
|
+
refreshManagedBitcoindServiceStatus?: typeof refreshManagedBitcoindStatus;
|
|
118
121
|
stopManagedBitcoindService?: typeof stopManagedBitcoindService;
|
|
119
122
|
createBitcoinRpcClient?: typeof createRpcClient;
|
|
120
123
|
attachIndexerDaemon?: typeof attachOrStartIndexerDaemon;
|
package/dist/passive-status.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { WalletRuntimePaths } from "./wallet/runtime.js";
|
|
1
2
|
interface PassiveTipStatus {
|
|
2
3
|
height: number;
|
|
3
4
|
blockHashHex: string;
|
|
@@ -22,15 +23,62 @@ interface PassiveBootstrapStatus {
|
|
|
22
23
|
snapshotHeight: number | null;
|
|
23
24
|
updatedAt: number | null;
|
|
24
25
|
}
|
|
26
|
+
export interface PassiveWalletStatus {
|
|
27
|
+
walletRootId: string | null;
|
|
28
|
+
source: "wallet-state" | "none" | "unreadable";
|
|
29
|
+
error: string | null;
|
|
30
|
+
}
|
|
31
|
+
export interface PassiveManagedBitcoindStatus {
|
|
32
|
+
statusPath: string | null;
|
|
33
|
+
present: boolean;
|
|
34
|
+
state: string | null;
|
|
35
|
+
processId: number | null;
|
|
36
|
+
walletRootId: string | null;
|
|
37
|
+
heartbeatAtUnixMs: number | null;
|
|
38
|
+
updatedAtUnixMs: number | null;
|
|
39
|
+
lastError: string | null;
|
|
40
|
+
error: string | null;
|
|
41
|
+
}
|
|
42
|
+
export interface PassiveIndexerStatus {
|
|
43
|
+
statusPath: string | null;
|
|
44
|
+
present: boolean;
|
|
45
|
+
state: string | null;
|
|
46
|
+
processId: number | null;
|
|
47
|
+
walletRootId: string | null;
|
|
48
|
+
coreBestHeight: number | null;
|
|
49
|
+
appliedTipHeight: number | null;
|
|
50
|
+
appliedTipHash: string | null;
|
|
51
|
+
heartbeatAtUnixMs: number | null;
|
|
52
|
+
updatedAtUnixMs: number | null;
|
|
53
|
+
lastError: string | null;
|
|
54
|
+
error: string | null;
|
|
55
|
+
}
|
|
56
|
+
export interface PassiveMiningStatus {
|
|
57
|
+
statusPath: string | null;
|
|
58
|
+
present: boolean;
|
|
59
|
+
runMode: string | null;
|
|
60
|
+
miningState: string | null;
|
|
61
|
+
currentPhase: string | null;
|
|
62
|
+
backgroundWorkerPid: number | null;
|
|
63
|
+
backgroundWorkerHealth: string | null;
|
|
64
|
+
updatedAtUnixMs: number | null;
|
|
65
|
+
lastError: string | null;
|
|
66
|
+
note: string | null;
|
|
67
|
+
error: string | null;
|
|
68
|
+
}
|
|
25
69
|
export interface PassiveClientStatus {
|
|
26
70
|
dbPath: string;
|
|
27
71
|
bitcoinDataDir: string;
|
|
72
|
+
wallet: PassiveWalletStatus;
|
|
28
73
|
storeInitialized: boolean;
|
|
29
74
|
storeExists: boolean;
|
|
30
75
|
indexedTip: PassiveTipStatus | null;
|
|
31
76
|
latestCheckpoint: PassiveCheckpointStatus | null;
|
|
32
77
|
bootstrap: PassiveBootstrapStatus | null;
|
|
78
|
+
managedBitcoind: PassiveManagedBitcoindStatus;
|
|
79
|
+
indexer: PassiveIndexerStatus;
|
|
80
|
+
mining: PassiveMiningStatus;
|
|
33
81
|
storeError: string | null;
|
|
34
82
|
}
|
|
35
|
-
export declare function inspectPassiveClientStatus(dbPath: string, bitcoinDataDir: string): Promise<PassiveClientStatus>;
|
|
83
|
+
export declare function inspectPassiveClientStatus(dbPath: string, bitcoinDataDir: string, runtimePaths?: WalletRuntimePaths): Promise<PassiveClientStatus>;
|
|
36
84
|
export {};
|