@cogcoin/client 1.1.9 → 1.1.11
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 +1 -1
- package/dist/bitcoind/client/managed-client.d.ts +2 -0
- package/dist/bitcoind/client/managed-client.js +6 -0
- package/dist/bitcoind/indexer-daemon/background-follow.d.ts +23 -0
- package/dist/bitcoind/indexer-daemon/background-follow.js +132 -0
- package/dist/bitcoind/indexer-daemon/client.d.ts +12 -0
- package/dist/bitcoind/indexer-daemon/client.js +137 -0
- package/dist/bitcoind/indexer-daemon/lifecycle.d.ts +30 -0
- package/dist/bitcoind/indexer-daemon/lifecycle.js +153 -0
- package/dist/bitcoind/indexer-daemon/process.d.ts +35 -0
- package/dist/bitcoind/indexer-daemon/process.js +140 -0
- package/dist/bitcoind/indexer-daemon/runtime.d.ts +23 -0
- package/dist/bitcoind/indexer-daemon/runtime.js +204 -0
- package/dist/bitcoind/indexer-daemon/server.d.ts +12 -0
- package/dist/bitcoind/indexer-daemon/server.js +87 -0
- package/dist/bitcoind/indexer-daemon/snapshot-leases.d.ts +23 -0
- package/dist/bitcoind/indexer-daemon/snapshot-leases.js +139 -0
- package/dist/bitcoind/indexer-daemon/status.d.ts +23 -0
- package/dist/bitcoind/indexer-daemon/status.js +282 -0
- package/dist/bitcoind/indexer-daemon/types.d.ts +141 -0
- package/dist/bitcoind/indexer-daemon/types.js +1 -0
- package/dist/bitcoind/indexer-daemon-main.js +14 -665
- package/dist/bitcoind/indexer-daemon.d.ts +4 -132
- package/dist/bitcoind/indexer-daemon.js +2 -417
- package/dist/bitcoind/managed-bitcoind-service-config.d.ts +30 -0
- package/dist/bitcoind/managed-bitcoind-service-config.js +202 -0
- package/dist/bitcoind/managed-bitcoind-service-lifecycle.d.ts +28 -0
- package/dist/bitcoind/managed-bitcoind-service-lifecycle.js +296 -0
- package/dist/bitcoind/managed-bitcoind-service-process.d.ts +8 -0
- package/dist/bitcoind/managed-bitcoind-service-process.js +48 -0
- package/dist/bitcoind/managed-bitcoind-service-replica.d.ts +8 -0
- package/dist/bitcoind/managed-bitcoind-service-replica.js +142 -0
- package/dist/bitcoind/managed-bitcoind-service-status.d.ts +42 -0
- package/dist/bitcoind/managed-bitcoind-service-status.js +170 -0
- package/dist/bitcoind/managed-bitcoind-service-types.d.ts +36 -0
- package/dist/bitcoind/managed-bitcoind-service-types.js +1 -0
- package/dist/bitcoind/service.d.ts +7 -63
- package/dist/bitcoind/service.js +7 -797
- package/dist/cli/mining-format.js +6 -1
- package/dist/cli/wallet-format/balance.js +1 -1
- package/dist/client/default-client.d.ts +3 -1
- package/dist/client/default-client.js +22 -0
- package/dist/types.d.ts +13 -1
- package/dist/wallet/fs/atomic.d.ts +11 -2
- package/dist/wallet/fs/atomic.js +45 -5
- package/dist/wallet/mining/cycle.js +4 -4
- package/dist/wallet/mining/engine-types.d.ts +1 -0
- package/dist/wallet/mining/engine-types.js +9 -1
- package/dist/wallet/mining/projection.d.ts +1 -0
- package/dist/wallet/mining/projection.js +15 -1
- package/dist/wallet/mining/publish.js +3 -6
- package/dist/wallet/mining/runner.js +30 -18
- package/dist/wallet/mining/visualizer-sync.js +7 -9
- package/dist/wallet/mining/visualizer.js +9 -7
- package/dist/wallet/read/context.d.ts +4 -10
- package/dist/wallet/read/context.js +6 -228
- package/dist/wallet/read/local-state.d.ts +36 -0
- package/dist/wallet/read/local-state.js +259 -0
- package/dist/wallet/read/managed-bitcoind.d.ts +30 -0
- package/dist/wallet/read/managed-bitcoind.js +138 -0
- package/dist/wallet/read/managed-indexer.d.ts +23 -0
- package/dist/wallet/read/managed-indexer.js +87 -0
- package/dist/wallet/read/managed-services.d.ts +6 -21
- package/dist/wallet/read/managed-services.js +23 -196
- package/dist/wallet/read/types.d.ts +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
import { access, constants, readFile } from "node:fs/promises";
|
|
2
|
+
import { openClient } from "../../client.js";
|
|
3
|
+
import { openSqliteStore } from "../../sqlite/index.js";
|
|
4
|
+
import { writeRuntimeStatusFile } from "../../wallet/fs/status-file.js";
|
|
5
|
+
import { DEFAULT_SNAPSHOT_METADATA } from "../bootstrap.js";
|
|
6
|
+
import { createRpcClient } from "../node.js";
|
|
7
|
+
import { createBootstrapProgress } from "../progress/formatting.js";
|
|
8
|
+
import { resolveManagedServicePaths } from "../service-paths.js";
|
|
9
|
+
export async function readJsonFile(filePath) {
|
|
10
|
+
try {
|
|
11
|
+
return JSON.parse(await readFile(filePath, "utf8"));
|
|
12
|
+
}
|
|
13
|
+
catch (error) {
|
|
14
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
throw error;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export async function readManagedBitcoindStatus(paths) {
|
|
21
|
+
return readJsonFile(paths.bitcoindStatusPath);
|
|
22
|
+
}
|
|
23
|
+
export function createIndexerSnapshotKey(appliedTip) {
|
|
24
|
+
return appliedTip === null
|
|
25
|
+
? "__null__"
|
|
26
|
+
: [
|
|
27
|
+
appliedTip.height,
|
|
28
|
+
appliedTip.blockHashHex,
|
|
29
|
+
appliedTip.stateHashHex ?? "",
|
|
30
|
+
].join(":");
|
|
31
|
+
}
|
|
32
|
+
export function createManagedBitcoindCookieUnavailableMessage(cookieFile) {
|
|
33
|
+
return `The managed Bitcoin RPC cookie file is unavailable at ${cookieFile} while preparing getblockchaininfo. The managed node is not running or is shutting down.`;
|
|
34
|
+
}
|
|
35
|
+
export async function readCoreTipStatus(paths) {
|
|
36
|
+
const runtimeConfig = await readJsonFile(paths.bitcoindRuntimeConfigPath).catch(() => null);
|
|
37
|
+
if (runtimeConfig?.rpc === undefined || runtimeConfig.rpc === null) {
|
|
38
|
+
return {
|
|
39
|
+
rpcReachable: false,
|
|
40
|
+
coreBestHeight: null,
|
|
41
|
+
coreBestHash: null,
|
|
42
|
+
error: "managed_bitcoind_runtime_config_unavailable",
|
|
43
|
+
prerequisiteUnavailable: true,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
await access(runtimeConfig.rpc.cookieFile, constants.R_OK);
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return {
|
|
51
|
+
rpcReachable: false,
|
|
52
|
+
coreBestHeight: null,
|
|
53
|
+
coreBestHash: null,
|
|
54
|
+
error: createManagedBitcoindCookieUnavailableMessage(runtimeConfig.rpc.cookieFile),
|
|
55
|
+
prerequisiteUnavailable: true,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
try {
|
|
59
|
+
const rpc = createRpcClient(runtimeConfig.rpc);
|
|
60
|
+
const info = await rpc.getBlockchainInfo();
|
|
61
|
+
return {
|
|
62
|
+
rpcReachable: true,
|
|
63
|
+
coreBestHeight: info.blocks,
|
|
64
|
+
coreBestHash: info.bestblockhash,
|
|
65
|
+
error: null,
|
|
66
|
+
prerequisiteUnavailable: false,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
return {
|
|
71
|
+
rpcReachable: false,
|
|
72
|
+
coreBestHeight: null,
|
|
73
|
+
coreBestHash: null,
|
|
74
|
+
error: error instanceof Error ? error.message : String(error),
|
|
75
|
+
prerequisiteUnavailable: false,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
export async function readAppliedTipStatus(databasePath) {
|
|
80
|
+
try {
|
|
81
|
+
const store = await openSqliteStore({ filename: databasePath });
|
|
82
|
+
try {
|
|
83
|
+
const client = await openClient({ store });
|
|
84
|
+
try {
|
|
85
|
+
return {
|
|
86
|
+
appliedTip: await client.getTip(),
|
|
87
|
+
error: null,
|
|
88
|
+
schemaMismatch: false,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
finally {
|
|
92
|
+
await client.close();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
finally {
|
|
96
|
+
await store.close().catch(() => undefined);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
101
|
+
return {
|
|
102
|
+
appliedTip: null,
|
|
103
|
+
error: message,
|
|
104
|
+
schemaMismatch: message === "sqlite_store_schema_version_unsupported",
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
export function observeIndexerAppliedTip(state, appliedTip, nowUnixMs) {
|
|
109
|
+
state.appliedTipHeight = appliedTip?.height ?? null;
|
|
110
|
+
state.appliedTipHash = appliedTip?.blockHashHex ?? null;
|
|
111
|
+
const snapshotKey = createIndexerSnapshotKey(appliedTip);
|
|
112
|
+
if (state.lastSnapshotKey !== snapshotKey) {
|
|
113
|
+
state.snapshotSeqCounter += 1;
|
|
114
|
+
state.snapshotSeq = String(state.snapshotSeqCounter);
|
|
115
|
+
state.lastSnapshotKey = snapshotKey;
|
|
116
|
+
state.lastAppliedAtUnixMs = nowUnixMs;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
export function deriveIndexerDaemonLeaseState(options) {
|
|
120
|
+
if (options.coreStatus.error !== null) {
|
|
121
|
+
return {
|
|
122
|
+
state: options.coreStatus.prerequisiteUnavailable && !options.hasSuccessfulCoreTipRefresh ? "starting" : "failed",
|
|
123
|
+
lastError: options.coreStatus.error,
|
|
124
|
+
hasSuccessfulCoreTipRefresh: options.hasSuccessfulCoreTipRefresh,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
const nextHasSuccessfulCoreTipRefresh = true;
|
|
128
|
+
if (options.coreStatus.coreBestHeight !== null
|
|
129
|
+
&& options.appliedTip?.height !== undefined
|
|
130
|
+
&& options.coreStatus.coreBestHash !== null
|
|
131
|
+
&& options.appliedTip?.blockHashHex !== undefined) {
|
|
132
|
+
return {
|
|
133
|
+
state: options.coreStatus.coreBestHeight === options.appliedTip.height
|
|
134
|
+
&& options.coreStatus.coreBestHash === options.appliedTip.blockHashHex
|
|
135
|
+
? "synced"
|
|
136
|
+
: "catching-up",
|
|
137
|
+
lastError: null,
|
|
138
|
+
hasSuccessfulCoreTipRefresh: nextHasSuccessfulCoreTipRefresh,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
return {
|
|
142
|
+
state: "starting",
|
|
143
|
+
lastError: null,
|
|
144
|
+
hasSuccessfulCoreTipRefresh: nextHasSuccessfulCoreTipRefresh,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
export function buildIndexerDaemonStatus(state) {
|
|
148
|
+
return {
|
|
149
|
+
serviceApiVersion: "cogcoin/indexer-ipc/v1",
|
|
150
|
+
binaryVersion: state.binaryVersion,
|
|
151
|
+
buildId: null,
|
|
152
|
+
updatedAtUnixMs: state.updatedAtUnixMs,
|
|
153
|
+
walletRootId: state.walletRootId,
|
|
154
|
+
daemonInstanceId: state.daemonInstanceId,
|
|
155
|
+
schemaVersion: "cogcoin/indexer-db/v1",
|
|
156
|
+
state: state.state,
|
|
157
|
+
processId: process.pid ?? null,
|
|
158
|
+
startedAtUnixMs: state.startedAtUnixMs,
|
|
159
|
+
heartbeatAtUnixMs: state.heartbeatAtUnixMs,
|
|
160
|
+
ipcReady: true,
|
|
161
|
+
rpcReachable: state.rpcReachable,
|
|
162
|
+
coreBestHeight: state.coreBestHeight,
|
|
163
|
+
coreBestHash: state.coreBestHash,
|
|
164
|
+
appliedTipHeight: state.appliedTipHeight,
|
|
165
|
+
appliedTipHash: state.appliedTipHash,
|
|
166
|
+
snapshotSeq: state.snapshotSeq,
|
|
167
|
+
backlogBlocks: state.coreBestHeight === null || state.appliedTipHeight === null
|
|
168
|
+
? null
|
|
169
|
+
: Math.max(state.coreBestHeight - state.appliedTipHeight, 0),
|
|
170
|
+
reorgDepth: null,
|
|
171
|
+
lastAppliedAtUnixMs: state.lastAppliedAtUnixMs,
|
|
172
|
+
activeSnapshotCount: state.snapshots.size,
|
|
173
|
+
lastError: state.lastError,
|
|
174
|
+
backgroundFollowActive: state.backgroundFollowActive,
|
|
175
|
+
bootstrapPhase: state.bootstrapPhase,
|
|
176
|
+
bootstrapProgress: { ...state.bootstrapProgress },
|
|
177
|
+
cogcoinSyncHeight: state.cogcoinSyncHeight,
|
|
178
|
+
cogcoinSyncTargetHeight: state.cogcoinSyncTargetHeight,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
export async function writeIndexerDaemonStatus(paths, state) {
|
|
182
|
+
const status = buildIndexerDaemonStatus(state);
|
|
183
|
+
await writeRuntimeStatusFile(paths.indexerDaemonStatusPath, status);
|
|
184
|
+
return status;
|
|
185
|
+
}
|
|
186
|
+
export async function refreshIndexerDaemonStatus(options) {
|
|
187
|
+
const now = Date.now();
|
|
188
|
+
options.state.heartbeatAtUnixMs = now;
|
|
189
|
+
options.state.updatedAtUnixMs = now;
|
|
190
|
+
const [coreStatus, indexedStatus] = await Promise.all([
|
|
191
|
+
readCoreTipStatus(options.paths),
|
|
192
|
+
readAppliedTipStatus(options.databasePath),
|
|
193
|
+
]);
|
|
194
|
+
const backgroundStatus = await options.state.backgroundClient?.getNodeStatus().catch(() => null) ?? null;
|
|
195
|
+
if (backgroundStatus?.following === true) {
|
|
196
|
+
options.state.backgroundFollowError = null;
|
|
197
|
+
}
|
|
198
|
+
options.state.rpcReachable = coreStatus.rpcReachable;
|
|
199
|
+
options.state.coreBestHeight = coreStatus.coreBestHeight;
|
|
200
|
+
options.state.coreBestHash = coreStatus.coreBestHash;
|
|
201
|
+
observeIndexerAppliedTip(options.state, indexedStatus.appliedTip, now);
|
|
202
|
+
options.state.backgroundFollowActive = backgroundStatus?.following ?? (options.state.backgroundClient !== null);
|
|
203
|
+
options.state.bootstrapPhase = backgroundStatus?.bootstrapPhase ?? (options.state.backgroundFollowActive ? "follow_tip" : "paused");
|
|
204
|
+
options.state.bootstrapProgress = backgroundStatus?.bootstrapProgress ?? createBootstrapProgress(options.state.bootstrapPhase, DEFAULT_SNAPSHOT_METADATA);
|
|
205
|
+
options.state.cogcoinSyncHeight = backgroundStatus?.cogcoinSyncHeight ?? indexedStatus.appliedTip?.height ?? null;
|
|
206
|
+
options.state.cogcoinSyncTargetHeight = backgroundStatus?.cogcoinSyncTargetHeight ?? coreStatus.coreBestHeight;
|
|
207
|
+
if (backgroundStatus === null && options.state.backgroundFollowError !== null) {
|
|
208
|
+
options.state.state = "failed";
|
|
209
|
+
options.state.lastError = options.state.backgroundFollowError;
|
|
210
|
+
options.state.backgroundFollowActive = false;
|
|
211
|
+
options.state.bootstrapPhase = "error";
|
|
212
|
+
options.state.bootstrapProgress = {
|
|
213
|
+
...createBootstrapProgress("error", DEFAULT_SNAPSHOT_METADATA),
|
|
214
|
+
blocks: coreStatus.coreBestHeight,
|
|
215
|
+
headers: coreStatus.coreBestHeight,
|
|
216
|
+
targetHeight: coreStatus.coreBestHeight,
|
|
217
|
+
message: options.state.backgroundFollowError,
|
|
218
|
+
lastError: options.state.backgroundFollowError,
|
|
219
|
+
updatedAt: now,
|
|
220
|
+
};
|
|
221
|
+
options.state.cogcoinSyncHeight = indexedStatus.appliedTip?.height ?? null;
|
|
222
|
+
options.state.cogcoinSyncTargetHeight = coreStatus.coreBestHeight;
|
|
223
|
+
return writeIndexerDaemonStatus(options.paths, options.state);
|
|
224
|
+
}
|
|
225
|
+
if (indexedStatus.schemaMismatch) {
|
|
226
|
+
options.state.state = "schema-mismatch";
|
|
227
|
+
options.state.lastError = indexedStatus.error;
|
|
228
|
+
options.state.bootstrapPhase = "error";
|
|
229
|
+
options.state.bootstrapProgress = {
|
|
230
|
+
...options.state.bootstrapProgress,
|
|
231
|
+
phase: "error",
|
|
232
|
+
message: indexedStatus.error ?? "Indexer schema mismatch.",
|
|
233
|
+
lastError: indexedStatus.error,
|
|
234
|
+
updatedAt: now,
|
|
235
|
+
};
|
|
236
|
+
return writeIndexerDaemonStatus(options.paths, options.state);
|
|
237
|
+
}
|
|
238
|
+
if (indexedStatus.error !== null) {
|
|
239
|
+
options.state.state = "failed";
|
|
240
|
+
options.state.lastError = indexedStatus.error;
|
|
241
|
+
options.state.bootstrapPhase = "error";
|
|
242
|
+
options.state.bootstrapProgress = {
|
|
243
|
+
...options.state.bootstrapProgress,
|
|
244
|
+
phase: "error",
|
|
245
|
+
message: indexedStatus.error,
|
|
246
|
+
lastError: indexedStatus.error,
|
|
247
|
+
updatedAt: now,
|
|
248
|
+
};
|
|
249
|
+
return writeIndexerDaemonStatus(options.paths, options.state);
|
|
250
|
+
}
|
|
251
|
+
const leaseState = deriveIndexerDaemonLeaseState({
|
|
252
|
+
coreStatus,
|
|
253
|
+
appliedTip: indexedStatus.appliedTip,
|
|
254
|
+
hasSuccessfulCoreTipRefresh: options.state.hasSuccessfulCoreTipRefresh,
|
|
255
|
+
});
|
|
256
|
+
options.state.hasSuccessfulCoreTipRefresh = leaseState.hasSuccessfulCoreTipRefresh;
|
|
257
|
+
options.state.state = leaseState.state;
|
|
258
|
+
options.state.lastError = leaseState.lastError;
|
|
259
|
+
if (options.state.lastError !== null) {
|
|
260
|
+
options.state.bootstrapPhase = leaseState.state === "starting" ? "paused" : "error";
|
|
261
|
+
options.state.bootstrapProgress = {
|
|
262
|
+
...options.state.bootstrapProgress,
|
|
263
|
+
phase: options.state.bootstrapPhase,
|
|
264
|
+
message: options.state.lastError,
|
|
265
|
+
lastError: options.state.lastError,
|
|
266
|
+
updatedAt: now,
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
else if (backgroundStatus === null) {
|
|
270
|
+
options.state.bootstrapPhase = leaseState.state === "synced" ? "follow_tip" : "paused";
|
|
271
|
+
options.state.bootstrapProgress = {
|
|
272
|
+
...createBootstrapProgress(options.state.bootstrapPhase, DEFAULT_SNAPSHOT_METADATA),
|
|
273
|
+
blocks: coreStatus.coreBestHeight,
|
|
274
|
+
headers: coreStatus.coreBestHeight,
|
|
275
|
+
targetHeight: coreStatus.coreBestHeight,
|
|
276
|
+
updatedAt: now,
|
|
277
|
+
};
|
|
278
|
+
options.state.cogcoinSyncHeight = indexedStatus.appliedTip?.height ?? null;
|
|
279
|
+
options.state.cogcoinSyncTargetHeight = coreStatus.coreBestHeight;
|
|
280
|
+
}
|
|
281
|
+
return writeIndexerDaemonStatus(options.paths, options.state);
|
|
282
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import type { openSqliteStore } from "../../sqlite/index.js";
|
|
2
|
+
import type { ClientTip } from "../../types.js";
|
|
3
|
+
import type { BootstrapPhase, BootstrapProgress, ManagedBitcoindClient, ManagedIndexerDaemonObservedStatus, ManagedIndexerDaemonState, ManagedIndexerDaemonStatus, ManagedIndexerSnapshotIdentity } from "../types.js";
|
|
4
|
+
export interface DaemonRequest {
|
|
5
|
+
id: string;
|
|
6
|
+
method: "GetStatus" | "OpenSnapshot" | "ReadSnapshot" | "CloseSnapshot" | "ResumeBackgroundFollow";
|
|
7
|
+
token?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface DaemonResponse {
|
|
10
|
+
id: string;
|
|
11
|
+
ok: boolean;
|
|
12
|
+
result?: unknown;
|
|
13
|
+
error?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface IndexerSnapshotHandle {
|
|
16
|
+
token: string;
|
|
17
|
+
expiresAtUnixMs: number;
|
|
18
|
+
serviceApiVersion: string;
|
|
19
|
+
binaryVersion: string;
|
|
20
|
+
buildId: string | null;
|
|
21
|
+
walletRootId: string;
|
|
22
|
+
daemonInstanceId: string;
|
|
23
|
+
schemaVersion: string;
|
|
24
|
+
processId: number | null;
|
|
25
|
+
startedAtUnixMs: number;
|
|
26
|
+
state: ManagedIndexerDaemonStatus["state"];
|
|
27
|
+
heartbeatAtUnixMs: number;
|
|
28
|
+
rpcReachable: boolean;
|
|
29
|
+
coreBestHeight: number | null;
|
|
30
|
+
coreBestHash: string | null;
|
|
31
|
+
appliedTipHeight: number | null;
|
|
32
|
+
appliedTipHash: string | null;
|
|
33
|
+
snapshotSeq: string | null;
|
|
34
|
+
backlogBlocks: number | null;
|
|
35
|
+
reorgDepth: number | null;
|
|
36
|
+
lastAppliedAtUnixMs: number | null;
|
|
37
|
+
activeSnapshotCount: number;
|
|
38
|
+
lastError: string | null;
|
|
39
|
+
backgroundFollowActive: boolean;
|
|
40
|
+
bootstrapPhase: BootstrapPhase | null;
|
|
41
|
+
bootstrapProgress: BootstrapProgress | null;
|
|
42
|
+
cogcoinSyncHeight: number | null;
|
|
43
|
+
cogcoinSyncTargetHeight: number | null;
|
|
44
|
+
tipHeight: number | null;
|
|
45
|
+
tipHash: string | null;
|
|
46
|
+
openedAtUnixMs: number;
|
|
47
|
+
}
|
|
48
|
+
export interface IndexerSnapshotPayload {
|
|
49
|
+
token: string;
|
|
50
|
+
stateBase64: string;
|
|
51
|
+
serviceApiVersion: string;
|
|
52
|
+
schemaVersion: string;
|
|
53
|
+
walletRootId: string;
|
|
54
|
+
daemonInstanceId: string;
|
|
55
|
+
processId: number | null;
|
|
56
|
+
startedAtUnixMs: number;
|
|
57
|
+
snapshotSeq: string | null;
|
|
58
|
+
tipHeight: number | null;
|
|
59
|
+
tipHash: string | null;
|
|
60
|
+
openedAtUnixMs: number;
|
|
61
|
+
tip: {
|
|
62
|
+
height: number;
|
|
63
|
+
blockHashHex: string;
|
|
64
|
+
previousHashHex: string | null;
|
|
65
|
+
stateHashHex: string | null;
|
|
66
|
+
} | null;
|
|
67
|
+
expiresAtUnixMs: number;
|
|
68
|
+
}
|
|
69
|
+
export interface IndexerDaemonClient {
|
|
70
|
+
getStatus(): Promise<ManagedIndexerDaemonObservedStatus>;
|
|
71
|
+
openSnapshot(): Promise<IndexerSnapshotHandle>;
|
|
72
|
+
readSnapshot(token: string): Promise<IndexerSnapshotPayload>;
|
|
73
|
+
closeSnapshot(token: string): Promise<void>;
|
|
74
|
+
resumeBackgroundFollow(): Promise<void>;
|
|
75
|
+
close(): Promise<void>;
|
|
76
|
+
}
|
|
77
|
+
export interface IndexerDaemonStopResult {
|
|
78
|
+
status: "stopped" | "not-running";
|
|
79
|
+
walletRootId: string;
|
|
80
|
+
}
|
|
81
|
+
export interface CoherentIndexerSnapshotLease {
|
|
82
|
+
payload: IndexerSnapshotPayload;
|
|
83
|
+
status: ManagedIndexerDaemonStatus;
|
|
84
|
+
}
|
|
85
|
+
export type ManagedIndexerDaemonServiceLifetime = "persistent" | "ephemeral";
|
|
86
|
+
export type ManagedIndexerDaemonOwnership = "attached" | "started";
|
|
87
|
+
export interface LoadedSnapshotMaterial {
|
|
88
|
+
token: string;
|
|
89
|
+
stateBase64: string;
|
|
90
|
+
tip: ClientTip | null;
|
|
91
|
+
expiresAtUnixMs: number;
|
|
92
|
+
}
|
|
93
|
+
export interface LoadedSnapshot extends LoadedSnapshotMaterial, ManagedIndexerSnapshotIdentity {
|
|
94
|
+
}
|
|
95
|
+
export interface CoreTipStatus {
|
|
96
|
+
rpcReachable: boolean;
|
|
97
|
+
coreBestHeight: number | null;
|
|
98
|
+
coreBestHash: string | null;
|
|
99
|
+
error: string | null;
|
|
100
|
+
prerequisiteUnavailable: boolean;
|
|
101
|
+
}
|
|
102
|
+
export interface IndexedTipStatus {
|
|
103
|
+
appliedTip: ClientTip | null;
|
|
104
|
+
error: string | null;
|
|
105
|
+
schemaMismatch: boolean;
|
|
106
|
+
}
|
|
107
|
+
export interface IndexerDaemonLeaseStateResult {
|
|
108
|
+
state: ManagedIndexerDaemonState;
|
|
109
|
+
lastError: string | null;
|
|
110
|
+
hasSuccessfulCoreTipRefresh: boolean;
|
|
111
|
+
}
|
|
112
|
+
export interface IndexerDaemonRuntimeState {
|
|
113
|
+
readonly daemonInstanceId: string;
|
|
114
|
+
readonly binaryVersion: string;
|
|
115
|
+
readonly startedAtUnixMs: number;
|
|
116
|
+
readonly walletRootId: string;
|
|
117
|
+
readonly snapshots: Map<string, LoadedSnapshot>;
|
|
118
|
+
state: ManagedIndexerDaemonState;
|
|
119
|
+
heartbeatAtUnixMs: number;
|
|
120
|
+
updatedAtUnixMs: number;
|
|
121
|
+
rpcReachable: boolean;
|
|
122
|
+
coreBestHeight: number | null;
|
|
123
|
+
coreBestHash: string | null;
|
|
124
|
+
appliedTipHeight: number | null;
|
|
125
|
+
appliedTipHash: string | null;
|
|
126
|
+
snapshotSeqCounter: number;
|
|
127
|
+
snapshotSeq: string | null;
|
|
128
|
+
lastSnapshotKey: string | undefined;
|
|
129
|
+
lastAppliedAtUnixMs: number | null;
|
|
130
|
+
lastError: string | null;
|
|
131
|
+
hasSuccessfulCoreTipRefresh: boolean;
|
|
132
|
+
backgroundStore: Awaited<ReturnType<typeof openSqliteStore>> | null;
|
|
133
|
+
backgroundClient: ManagedBitcoindClient | null;
|
|
134
|
+
backgroundResumePromise: Promise<void> | null;
|
|
135
|
+
backgroundFollowError: string | null;
|
|
136
|
+
backgroundFollowActive: boolean;
|
|
137
|
+
bootstrapPhase: BootstrapPhase;
|
|
138
|
+
bootstrapProgress: BootstrapProgress;
|
|
139
|
+
cogcoinSyncHeight: number | null;
|
|
140
|
+
cogcoinSyncTargetHeight: number | null;
|
|
141
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|