@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
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
import { access, constants } from "node:fs/promises";
|
|
2
|
-
import { deserializeIndexerState, loadBundledGenesisParameters } from "@cogcoin/indexer";
|
|
3
2
|
import { readPackageVersionFromDisk } from "../../package-version.js";
|
|
4
|
-
import {
|
|
3
|
+
import { readSnapshotWithRetry, } from "../../bitcoind/indexer-daemon.js";
|
|
5
4
|
import { createRpcClient } from "../../bitcoind/node.js";
|
|
6
5
|
import { UNINITIALIZED_WALLET_ROOT_ID } from "../../bitcoind/service-paths.js";
|
|
7
|
-
import { attachOrStartManagedBitcoindService
|
|
8
|
-
import { resolveCogcoinProcessingStartHeight } from "../../bitcoind/processing-start-height.js";
|
|
6
|
+
import { attachOrStartManagedBitcoindService } from "../../bitcoind/service.js";
|
|
9
7
|
import {} from "../../bitcoind/types.js";
|
|
10
|
-
import { verifyManagedCoreWalletReplica, } from "../lifecycle.js";
|
|
11
8
|
import { normalizeWalletStateRecord, persistWalletCoinControlStateIfNeeded } from "../coin-control.js";
|
|
12
9
|
import { persistNormalizedWalletDescriptorStateIfNeeded } from "../descriptor-normalization.js";
|
|
13
10
|
import { inspectMiningControlPlane } from "../mining/index.js";
|
|
@@ -17,12 +14,9 @@ import { resolveWalletRuntimePathsForTesting } from "../runtime.js";
|
|
|
17
14
|
import { extractWalletRootIdHintFromWalletStateEnvelope, loadRawWalletStateEnvelope, loadWalletState, } from "../state/storage.js";
|
|
18
15
|
import { createDefaultWalletSecretProvider, createWalletSecretReference, inspectClientPasswordSetupReadiness, } from "../state/provider.js";
|
|
19
16
|
import { describeClientPasswordLockedMessage, describeClientPasswordMigrationMessage, describeClientPasswordSetupMessage, } from "../state/client-password.js";
|
|
17
|
+
import { openManagedWalletReadServiceBundle } from "./managed-services.js";
|
|
20
18
|
import { createWalletReadModel } from "./project.js";
|
|
21
19
|
const DEFAULT_SERVICE_START_TIMEOUT_MS = 10_000;
|
|
22
|
-
const STALE_HEARTBEAT_THRESHOLD_MS = 15_000;
|
|
23
|
-
const TOLERATED_NODE_HEADER_LEAD_BLOCKS = 2;
|
|
24
|
-
const TOLERATED_NODE_HEADER_LEAD_MESSAGE = "Bitcoin headers can briefly lead validated blocks; a short 1-2 block lead is normal and is being tolerated.";
|
|
25
|
-
const NODE_CATCHING_UP_MESSAGE = "Bitcoin Core is still catching up to headers.";
|
|
26
20
|
function btcAmountToSats(value) {
|
|
27
21
|
return BigInt(Math.round(value * 100_000_000));
|
|
28
22
|
}
|
|
@@ -222,279 +216,6 @@ async function inspectWalletLocalState(options = {}) {
|
|
|
222
216
|
};
|
|
223
217
|
}
|
|
224
218
|
}
|
|
225
|
-
function mapIndexerStartupError(message) {
|
|
226
|
-
switch (message) {
|
|
227
|
-
case "indexer_daemon_start_timeout":
|
|
228
|
-
return {
|
|
229
|
-
health: "starting",
|
|
230
|
-
message: "Indexer daemon is still starting.",
|
|
231
|
-
};
|
|
232
|
-
case "indexer_daemon_service_version_mismatch":
|
|
233
|
-
return {
|
|
234
|
-
health: "service-version-mismatch",
|
|
235
|
-
message: "The live indexer daemon is running an incompatible service API version.",
|
|
236
|
-
};
|
|
237
|
-
case "indexer_daemon_schema_mismatch":
|
|
238
|
-
return {
|
|
239
|
-
health: "schema-mismatch",
|
|
240
|
-
message: "The live indexer daemon is using an incompatible sqlite schema.",
|
|
241
|
-
};
|
|
242
|
-
case "indexer_daemon_wallet_root_mismatch":
|
|
243
|
-
return {
|
|
244
|
-
health: "wallet-root-mismatch",
|
|
245
|
-
message: "The live indexer daemon belongs to a different wallet root.",
|
|
246
|
-
};
|
|
247
|
-
case "indexer_daemon_protocol_error":
|
|
248
|
-
return {
|
|
249
|
-
health: "unavailable",
|
|
250
|
-
message: "The live indexer daemon socket responded with an invalid or incomplete protocol exchange.",
|
|
251
|
-
};
|
|
252
|
-
case INDEXER_DAEMON_BACKGROUND_FOLLOW_RECOVERY_FAILED:
|
|
253
|
-
return {
|
|
254
|
-
health: "failed",
|
|
255
|
-
message: "The managed indexer daemon could not recover automatic background follow.",
|
|
256
|
-
};
|
|
257
|
-
default:
|
|
258
|
-
return {
|
|
259
|
-
health: "unavailable",
|
|
260
|
-
message,
|
|
261
|
-
};
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
function mapBitcoindStartupError(message) {
|
|
265
|
-
switch (message) {
|
|
266
|
-
case "managed_bitcoind_service_start_timeout":
|
|
267
|
-
return {
|
|
268
|
-
health: "starting",
|
|
269
|
-
status: null,
|
|
270
|
-
message: "Managed bitcoind service is still starting.",
|
|
271
|
-
};
|
|
272
|
-
case "managed_bitcoind_service_version_mismatch":
|
|
273
|
-
return {
|
|
274
|
-
health: "service-version-mismatch",
|
|
275
|
-
status: null,
|
|
276
|
-
message: "The live managed bitcoind service is running an incompatible service version.",
|
|
277
|
-
};
|
|
278
|
-
case "managed_bitcoind_wallet_root_mismatch":
|
|
279
|
-
return {
|
|
280
|
-
health: "wallet-root-mismatch",
|
|
281
|
-
status: null,
|
|
282
|
-
message: "The live managed bitcoind service belongs to a different wallet root.",
|
|
283
|
-
};
|
|
284
|
-
case "managed_bitcoind_runtime_mismatch":
|
|
285
|
-
return {
|
|
286
|
-
health: "runtime-mismatch",
|
|
287
|
-
status: null,
|
|
288
|
-
message: "The live managed bitcoind service runtime does not match this wallet's expected data directory or chain.",
|
|
289
|
-
};
|
|
290
|
-
case "managed_bitcoind_protocol_error":
|
|
291
|
-
return {
|
|
292
|
-
health: "unavailable",
|
|
293
|
-
status: null,
|
|
294
|
-
message: "The managed bitcoind runtime artifacts are invalid or incomplete.",
|
|
295
|
-
};
|
|
296
|
-
default:
|
|
297
|
-
return {
|
|
298
|
-
health: "unavailable",
|
|
299
|
-
status: null,
|
|
300
|
-
message,
|
|
301
|
-
};
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
function deriveBitcoindHealth(options) {
|
|
305
|
-
if (options.startupError !== null) {
|
|
306
|
-
const mapped = mapBitcoindStartupError(options.startupError);
|
|
307
|
-
return {
|
|
308
|
-
...mapped,
|
|
309
|
-
status: options.status,
|
|
310
|
-
};
|
|
311
|
-
}
|
|
312
|
-
if (options.status === null) {
|
|
313
|
-
return {
|
|
314
|
-
health: "unavailable",
|
|
315
|
-
status: null,
|
|
316
|
-
message: "Managed bitcoind service is unavailable.",
|
|
317
|
-
};
|
|
318
|
-
}
|
|
319
|
-
if (options.status.state === "starting") {
|
|
320
|
-
return {
|
|
321
|
-
health: "starting",
|
|
322
|
-
status: options.status,
|
|
323
|
-
message: options.status.lastError ?? "Managed bitcoind service is still starting.",
|
|
324
|
-
};
|
|
325
|
-
}
|
|
326
|
-
if (options.status.state === "failed") {
|
|
327
|
-
return {
|
|
328
|
-
health: "failed",
|
|
329
|
-
status: options.status,
|
|
330
|
-
message: options.status.lastError ?? "Managed bitcoind service refresh failed.",
|
|
331
|
-
};
|
|
332
|
-
}
|
|
333
|
-
const proofStatus = options.nodeStatus?.walletReplica?.proofStatus;
|
|
334
|
-
if (proofStatus === "missing") {
|
|
335
|
-
return {
|
|
336
|
-
health: "replica-missing",
|
|
337
|
-
status: options.status,
|
|
338
|
-
message: options.nodeStatus?.walletReplicaMessage ?? "Managed Core wallet replica is missing.",
|
|
339
|
-
};
|
|
340
|
-
}
|
|
341
|
-
if (proofStatus === "mismatch") {
|
|
342
|
-
return {
|
|
343
|
-
health: "replica-mismatch",
|
|
344
|
-
status: options.status,
|
|
345
|
-
message: options.nodeStatus?.walletReplicaMessage ?? "Managed Core wallet replica does not match trusted wallet state.",
|
|
346
|
-
};
|
|
347
|
-
}
|
|
348
|
-
return {
|
|
349
|
-
health: "ready",
|
|
350
|
-
status: options.status,
|
|
351
|
-
message: options.nodeStatus?.walletReplicaMessage ?? options.status.lastError,
|
|
352
|
-
};
|
|
353
|
-
}
|
|
354
|
-
function deriveNodeHealth(status, bitcoindHealth) {
|
|
355
|
-
if (bitcoindHealth !== "ready" || status === null || !status.ready) {
|
|
356
|
-
return {
|
|
357
|
-
health: "catching-up",
|
|
358
|
-
message: NODE_CATCHING_UP_MESSAGE,
|
|
359
|
-
};
|
|
360
|
-
}
|
|
361
|
-
const headerLead = status.nodeBestHeight !== null && status.nodeHeaderHeight !== null
|
|
362
|
-
? status.nodeHeaderHeight - status.nodeBestHeight
|
|
363
|
-
: null;
|
|
364
|
-
if (headerLead !== null && headerLead > 0) {
|
|
365
|
-
if (headerLead <= TOLERATED_NODE_HEADER_LEAD_BLOCKS) {
|
|
366
|
-
return {
|
|
367
|
-
health: "synced",
|
|
368
|
-
message: TOLERATED_NODE_HEADER_LEAD_MESSAGE,
|
|
369
|
-
};
|
|
370
|
-
}
|
|
371
|
-
return {
|
|
372
|
-
health: "catching-up",
|
|
373
|
-
message: NODE_CATCHING_UP_MESSAGE,
|
|
374
|
-
};
|
|
375
|
-
}
|
|
376
|
-
return {
|
|
377
|
-
health: "synced",
|
|
378
|
-
message: null,
|
|
379
|
-
};
|
|
380
|
-
}
|
|
381
|
-
export function deriveNodeHealthForTesting(status, bitcoindHealth) {
|
|
382
|
-
return deriveNodeHealth(status, bitcoindHealth);
|
|
383
|
-
}
|
|
384
|
-
function deriveIndexerHealth(options) {
|
|
385
|
-
const daemonStatus = options.source === "lease"
|
|
386
|
-
? options.daemonStatus
|
|
387
|
-
: options.observedStatus ?? options.daemonStatus;
|
|
388
|
-
const snapshotTip = options.snapshot?.tip ?? null;
|
|
389
|
-
const daemonInstanceId = options.snapshot?.daemonInstanceId ?? daemonStatus?.daemonInstanceId ?? null;
|
|
390
|
-
const snapshotSeq = options.snapshot?.snapshotSeq ?? daemonStatus?.snapshotSeq ?? null;
|
|
391
|
-
const openedAtUnixMs = options.snapshot?.openedAtUnixMs ?? null;
|
|
392
|
-
const source = daemonStatus === null && options.snapshot === null ? "none" : options.source;
|
|
393
|
-
const createResult = (health, message) => ({
|
|
394
|
-
health,
|
|
395
|
-
status: daemonStatus,
|
|
396
|
-
message,
|
|
397
|
-
snapshotTip,
|
|
398
|
-
source,
|
|
399
|
-
daemonInstanceId,
|
|
400
|
-
snapshotSeq,
|
|
401
|
-
openedAtUnixMs,
|
|
402
|
-
});
|
|
403
|
-
if (options.startupError !== null) {
|
|
404
|
-
const mapped = mapIndexerStartupError(options.startupError);
|
|
405
|
-
return createResult(mapped.health, mapped.message);
|
|
406
|
-
}
|
|
407
|
-
if (daemonStatus === null) {
|
|
408
|
-
return createResult("unavailable", "Indexer daemon is unavailable.");
|
|
409
|
-
}
|
|
410
|
-
if ((options.now - daemonStatus.heartbeatAtUnixMs) > STALE_HEARTBEAT_THRESHOLD_MS) {
|
|
411
|
-
return createResult("stale-heartbeat", "Indexer daemon heartbeat is stale.");
|
|
412
|
-
}
|
|
413
|
-
if (daemonStatus.state === "schema-mismatch") {
|
|
414
|
-
return createResult("schema-mismatch", daemonStatus.lastError ?? "Indexer daemon sqlite schema is incompatible.");
|
|
415
|
-
}
|
|
416
|
-
if (daemonStatus.state === "failed") {
|
|
417
|
-
return createResult("failed", daemonStatus.lastError ?? "Indexer daemon refresh failed.");
|
|
418
|
-
}
|
|
419
|
-
if (daemonStatus.state === "service-version-mismatch") {
|
|
420
|
-
return createResult("service-version-mismatch", "Indexer daemon service API is incompatible.");
|
|
421
|
-
}
|
|
422
|
-
if (options.snapshot === null) {
|
|
423
|
-
if (daemonStatus.state === "reorging") {
|
|
424
|
-
return createResult("reorging", "Indexer daemon is replaying a reorg and refreshing the coherent snapshot.");
|
|
425
|
-
}
|
|
426
|
-
return createResult(daemonStatus.state === "catching-up" ? "catching-up" : "starting", "Indexer snapshot is not ready yet.");
|
|
427
|
-
}
|
|
428
|
-
if (daemonStatus.state === "catching-up") {
|
|
429
|
-
return createResult("catching-up", "Indexer daemon is still catching up to the managed Bitcoin tip.");
|
|
430
|
-
}
|
|
431
|
-
if (daemonStatus.state === "reorging") {
|
|
432
|
-
return createResult("reorging", "Indexer daemon is replaying a reorg and refreshing the coherent snapshot.");
|
|
433
|
-
}
|
|
434
|
-
return createResult("synced", null);
|
|
435
|
-
}
|
|
436
|
-
async function attachNodeStatus(options) {
|
|
437
|
-
try {
|
|
438
|
-
const probe = await probeManagedBitcoindService({
|
|
439
|
-
dataDir: options.dataDir,
|
|
440
|
-
chain: "main",
|
|
441
|
-
startHeight: 0,
|
|
442
|
-
walletRootId: options.walletRootId,
|
|
443
|
-
startupTimeoutMs: options.startupTimeoutMs,
|
|
444
|
-
});
|
|
445
|
-
if (probe.compatibility !== "compatible" && probe.compatibility !== "unreachable") {
|
|
446
|
-
return {
|
|
447
|
-
handle: null,
|
|
448
|
-
rpc: null,
|
|
449
|
-
status: null,
|
|
450
|
-
observedStatus: probe.status,
|
|
451
|
-
error: probe.error,
|
|
452
|
-
};
|
|
453
|
-
}
|
|
454
|
-
const genesis = await loadBundledGenesisParameters();
|
|
455
|
-
const handle = await attachOrStartManagedBitcoindService({
|
|
456
|
-
dataDir: options.dataDir,
|
|
457
|
-
chain: "main",
|
|
458
|
-
startHeight: resolveCogcoinProcessingStartHeight(genesis),
|
|
459
|
-
walletRootId: options.walletRootId,
|
|
460
|
-
startupTimeoutMs: options.startupTimeoutMs,
|
|
461
|
-
});
|
|
462
|
-
const rpc = createRpcClient(handle.rpc);
|
|
463
|
-
const [chainInfo, serviceStatus] = await Promise.all([
|
|
464
|
-
rpc.getBlockchainInfo(),
|
|
465
|
-
handle.refreshServiceStatus?.(),
|
|
466
|
-
]);
|
|
467
|
-
const status = {
|
|
468
|
-
ready: true,
|
|
469
|
-
chain: chainInfo.chain,
|
|
470
|
-
pid: handle.pid,
|
|
471
|
-
walletRootId: handle.walletRootId ?? null,
|
|
472
|
-
nodeBestHeight: chainInfo.blocks,
|
|
473
|
-
nodeBestHashHex: chainInfo.bestblockhash,
|
|
474
|
-
nodeHeaderHeight: chainInfo.headers,
|
|
475
|
-
serviceUpdatedAtUnixMs: serviceStatus?.updatedAtUnixMs ?? null,
|
|
476
|
-
serviceStatus: serviceStatus ?? null,
|
|
477
|
-
walletReplica: serviceStatus?.walletReplica ?? null,
|
|
478
|
-
walletReplicaMessage: serviceStatus?.walletReplica?.message ?? null,
|
|
479
|
-
};
|
|
480
|
-
return {
|
|
481
|
-
handle,
|
|
482
|
-
rpc,
|
|
483
|
-
status,
|
|
484
|
-
observedStatus: serviceStatus ?? null,
|
|
485
|
-
error: null,
|
|
486
|
-
};
|
|
487
|
-
}
|
|
488
|
-
catch (error) {
|
|
489
|
-
return {
|
|
490
|
-
handle: null,
|
|
491
|
-
rpc: null,
|
|
492
|
-
status: null,
|
|
493
|
-
observedStatus: null,
|
|
494
|
-
error: error instanceof Error ? error.message : String(error),
|
|
495
|
-
};
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
219
|
async function readFundingSpendableSats(options) {
|
|
499
220
|
if (options.state === null || options.rpc === null) {
|
|
500
221
|
return null;
|
|
@@ -524,105 +245,26 @@ export async function openWalletReadContext(options) {
|
|
|
524
245
|
paths: options.paths,
|
|
525
246
|
});
|
|
526
247
|
const walletRootId = localState.walletRootId ?? UNINITIALIZED_WALLET_ROOT_ID;
|
|
527
|
-
const
|
|
248
|
+
const managedServices = await openManagedWalletReadServiceBundle({
|
|
528
249
|
dataDir: options.dataDir,
|
|
250
|
+
databasePath: options.databasePath,
|
|
529
251
|
walletRootId,
|
|
252
|
+
localState,
|
|
530
253
|
startupTimeoutMs,
|
|
531
|
-
|
|
532
|
-
if (localState.state !== null && node.status !== null) {
|
|
533
|
-
const verifiedReplica = await verifyManagedCoreWalletReplica(localState.state, options.dataDir, {
|
|
534
|
-
nodeHandle: node.handle ?? undefined,
|
|
535
|
-
});
|
|
536
|
-
node.status = {
|
|
537
|
-
...node.status,
|
|
538
|
-
walletReplica: verifiedReplica,
|
|
539
|
-
walletReplicaMessage: verifiedReplica.message ?? null,
|
|
540
|
-
};
|
|
541
|
-
}
|
|
542
|
-
const bitcoind = deriveBitcoindHealth({
|
|
543
|
-
status: node.observedStatus,
|
|
544
|
-
nodeStatus: node.status,
|
|
545
|
-
startupError: node.error,
|
|
546
|
-
});
|
|
547
|
-
const nodeDerived = deriveNodeHealth(node.status, bitcoind.health);
|
|
548
|
-
let daemonClient = null;
|
|
549
|
-
let daemonStatus = null;
|
|
550
|
-
let observedDaemonStatus = null;
|
|
551
|
-
let snapshot = null;
|
|
552
|
-
let indexerSource = "none";
|
|
553
|
-
let daemonError = null;
|
|
554
|
-
try {
|
|
555
|
-
const probe = await probeIndexerDaemon({
|
|
556
|
-
dataDir: options.dataDir,
|
|
557
|
-
walletRootId,
|
|
558
|
-
});
|
|
559
|
-
if (probe.compatibility === "compatible" || probe.compatibility === "unreachable") {
|
|
560
|
-
await probe.client?.close().catch(() => undefined);
|
|
561
|
-
daemonClient = await attachOrStartIndexerDaemon({
|
|
562
|
-
dataDir: options.dataDir,
|
|
563
|
-
databasePath: options.databasePath,
|
|
564
|
-
walletRootId,
|
|
565
|
-
startupTimeoutMs,
|
|
566
|
-
ensureBackgroundFollow: true,
|
|
567
|
-
expectedBinaryVersion: expectedIndexerBinaryVersion,
|
|
568
|
-
});
|
|
569
|
-
}
|
|
570
|
-
else {
|
|
571
|
-
observedDaemonStatus = probe.status;
|
|
572
|
-
indexerSource = probe.status === null ? "none" : "probe";
|
|
573
|
-
daemonError = probe.error;
|
|
574
|
-
}
|
|
575
|
-
if (daemonClient !== null) {
|
|
576
|
-
const lease = await readSnapshotWithRetry(daemonClient, walletRootId);
|
|
577
|
-
daemonStatus = lease.status;
|
|
578
|
-
observedDaemonStatus = lease.status;
|
|
579
|
-
snapshot = {
|
|
580
|
-
tip: lease.payload.tip,
|
|
581
|
-
state: deserializeIndexerState(Buffer.from(lease.payload.stateBase64, "base64")),
|
|
582
|
-
source: "lease",
|
|
583
|
-
daemonInstanceId: lease.payload.daemonInstanceId,
|
|
584
|
-
snapshotSeq: lease.payload.snapshotSeq,
|
|
585
|
-
openedAtUnixMs: lease.payload.openedAtUnixMs,
|
|
586
|
-
};
|
|
587
|
-
indexerSource = "lease";
|
|
588
|
-
}
|
|
589
|
-
}
|
|
590
|
-
catch (error) {
|
|
591
|
-
daemonError = error instanceof Error ? error.message : String(error);
|
|
592
|
-
if (daemonError === INDEXER_DAEMON_BACKGROUND_FOLLOW_RECOVERY_FAILED) {
|
|
593
|
-
await daemonClient?.close().catch(() => undefined);
|
|
594
|
-
await node.handle?.stop().catch(() => undefined);
|
|
595
|
-
throw error;
|
|
596
|
-
}
|
|
597
|
-
if (observedDaemonStatus === null) {
|
|
598
|
-
observedDaemonStatus = await readObservedIndexerDaemonStatus({
|
|
599
|
-
dataDir: options.dataDir,
|
|
600
|
-
walletRootId,
|
|
601
|
-
}).catch(() => null);
|
|
602
|
-
if (observedDaemonStatus !== null) {
|
|
603
|
-
indexerSource = "status-file";
|
|
604
|
-
}
|
|
605
|
-
}
|
|
606
|
-
}
|
|
607
|
-
const indexer = deriveIndexerHealth({
|
|
608
|
-
daemonStatus,
|
|
609
|
-
observedStatus: observedDaemonStatus,
|
|
610
|
-
snapshot,
|
|
611
|
-
source: indexerSource,
|
|
254
|
+
expectedIndexerBinaryVersion,
|
|
612
255
|
now,
|
|
613
|
-
startupError: daemonError,
|
|
614
256
|
});
|
|
615
257
|
const fundingSpendableSats = await readFundingSpendableSats({
|
|
616
258
|
state: localState.state,
|
|
617
|
-
rpc: node.rpc,
|
|
259
|
+
rpc: managedServices.node.rpc,
|
|
618
260
|
});
|
|
619
261
|
const mining = await inspectMiningControlPlane({
|
|
620
262
|
provider: options.secretProvider,
|
|
621
263
|
localState,
|
|
622
|
-
bitcoind,
|
|
623
|
-
nodeStatus: node.status,
|
|
624
|
-
nodeHealth:
|
|
625
|
-
indexer,
|
|
264
|
+
bitcoind: managedServices.bitcoind,
|
|
265
|
+
nodeStatus: managedServices.node.status,
|
|
266
|
+
nodeHealth: managedServices.nodeHealth,
|
|
267
|
+
indexer: managedServices.indexer,
|
|
626
268
|
nowUnixMs: now,
|
|
627
269
|
paths: options.paths,
|
|
628
270
|
});
|
|
@@ -630,20 +272,19 @@ export async function openWalletReadContext(options) {
|
|
|
630
272
|
dataDir: options.dataDir,
|
|
631
273
|
databasePath: options.databasePath,
|
|
632
274
|
localState,
|
|
633
|
-
bitcoind,
|
|
634
|
-
nodeStatus: node.status,
|
|
635
|
-
nodeHealth:
|
|
636
|
-
nodeMessage:
|
|
637
|
-
indexer,
|
|
638
|
-
snapshot,
|
|
275
|
+
bitcoind: managedServices.bitcoind,
|
|
276
|
+
nodeStatus: managedServices.node.status,
|
|
277
|
+
nodeHealth: managedServices.nodeHealth,
|
|
278
|
+
nodeMessage: managedServices.nodeMessage,
|
|
279
|
+
indexer: managedServices.indexer,
|
|
280
|
+
snapshot: managedServices.snapshot,
|
|
639
281
|
model: localState.state === null
|
|
640
282
|
? null
|
|
641
|
-
: createWalletReadModel(localState.state, snapshot),
|
|
283
|
+
: createWalletReadModel(localState.state, managedServices.snapshot),
|
|
642
284
|
fundingSpendableSats,
|
|
643
285
|
mining,
|
|
644
286
|
async close() {
|
|
645
|
-
await
|
|
646
|
-
await node.handle?.stop().catch(() => undefined);
|
|
287
|
+
await managedServices.close();
|
|
647
288
|
},
|
|
648
289
|
};
|
|
649
290
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { loadBundledGenesisParameters } from "@cogcoin/indexer";
|
|
2
|
+
import { attachOrStartIndexerDaemon, probeIndexerDaemon, readObservedIndexerDaemonStatus, readSnapshotWithRetry, type IndexerDaemonClient } from "../../bitcoind/indexer-daemon.js";
|
|
3
|
+
import type { ManagedWalletReadServiceBundle } from "../../bitcoind/managed-runtime/types.js";
|
|
4
|
+
import { createRpcClient } from "../../bitcoind/node.js";
|
|
5
|
+
import { attachOrStartManagedBitcoindService, probeManagedBitcoindService } from "../../bitcoind/service.js";
|
|
6
|
+
import type { ManagedBitcoindNodeHandle } from "../../bitcoind/types.js";
|
|
7
|
+
import { verifyManagedCoreWalletReplica } from "../lifecycle.js";
|
|
8
|
+
import type { WalletBitcoindStatus, WalletLocalStateStatus, WalletNodeStatus, WalletServiceHealth } from "./types.js";
|
|
9
|
+
type ManagedWalletReadServiceDeps = {
|
|
10
|
+
loadBundledGenesisParameters: typeof loadBundledGenesisParameters;
|
|
11
|
+
probeManagedBitcoindService: typeof probeManagedBitcoindService;
|
|
12
|
+
attachOrStartManagedBitcoindService: typeof attachOrStartManagedBitcoindService;
|
|
13
|
+
createRpcClient: typeof createRpcClient;
|
|
14
|
+
verifyManagedCoreWalletReplica: typeof verifyManagedCoreWalletReplica;
|
|
15
|
+
probeIndexerDaemon: typeof probeIndexerDaemon;
|
|
16
|
+
attachOrStartIndexerDaemon: typeof attachOrStartIndexerDaemon;
|
|
17
|
+
readSnapshotWithRetry: typeof readSnapshotWithRetry;
|
|
18
|
+
readObservedIndexerDaemonStatus: typeof readObservedIndexerDaemonStatus;
|
|
19
|
+
};
|
|
20
|
+
export declare function deriveNodeHealthForTesting(status: WalletNodeStatus | null, bitcoindHealth: WalletBitcoindStatus["health"]): {
|
|
21
|
+
health: WalletServiceHealth;
|
|
22
|
+
message: string | null;
|
|
23
|
+
};
|
|
24
|
+
export declare function openManagedWalletReadServiceBundle(options: {
|
|
25
|
+
dataDir: string;
|
|
26
|
+
databasePath: string;
|
|
27
|
+
walletRootId: string;
|
|
28
|
+
localState: WalletLocalStateStatus;
|
|
29
|
+
startupTimeoutMs: number;
|
|
30
|
+
expectedIndexerBinaryVersion: string | null;
|
|
31
|
+
now: number;
|
|
32
|
+
}, dependencies?: ManagedWalletReadServiceDeps): Promise<ManagedWalletReadServiceBundle<ManagedBitcoindNodeHandle, ReturnType<typeof createRpcClient>, IndexerDaemonClient>>;
|
|
33
|
+
export {};
|