@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.
Files changed (66) hide show
  1. package/README.md +1 -1
  2. package/dist/bitcoind/client/managed-client.d.ts +2 -0
  3. package/dist/bitcoind/client/managed-client.js +6 -0
  4. package/dist/bitcoind/indexer-daemon/background-follow.d.ts +23 -0
  5. package/dist/bitcoind/indexer-daemon/background-follow.js +132 -0
  6. package/dist/bitcoind/indexer-daemon/client.d.ts +12 -0
  7. package/dist/bitcoind/indexer-daemon/client.js +137 -0
  8. package/dist/bitcoind/indexer-daemon/lifecycle.d.ts +30 -0
  9. package/dist/bitcoind/indexer-daemon/lifecycle.js +153 -0
  10. package/dist/bitcoind/indexer-daemon/process.d.ts +35 -0
  11. package/dist/bitcoind/indexer-daemon/process.js +140 -0
  12. package/dist/bitcoind/indexer-daemon/runtime.d.ts +23 -0
  13. package/dist/bitcoind/indexer-daemon/runtime.js +204 -0
  14. package/dist/bitcoind/indexer-daemon/server.d.ts +12 -0
  15. package/dist/bitcoind/indexer-daemon/server.js +87 -0
  16. package/dist/bitcoind/indexer-daemon/snapshot-leases.d.ts +23 -0
  17. package/dist/bitcoind/indexer-daemon/snapshot-leases.js +139 -0
  18. package/dist/bitcoind/indexer-daemon/status.d.ts +23 -0
  19. package/dist/bitcoind/indexer-daemon/status.js +282 -0
  20. package/dist/bitcoind/indexer-daemon/types.d.ts +141 -0
  21. package/dist/bitcoind/indexer-daemon/types.js +1 -0
  22. package/dist/bitcoind/indexer-daemon-main.js +14 -665
  23. package/dist/bitcoind/indexer-daemon.d.ts +4 -132
  24. package/dist/bitcoind/indexer-daemon.js +2 -417
  25. package/dist/bitcoind/managed-bitcoind-service-config.d.ts +30 -0
  26. package/dist/bitcoind/managed-bitcoind-service-config.js +202 -0
  27. package/dist/bitcoind/managed-bitcoind-service-lifecycle.d.ts +28 -0
  28. package/dist/bitcoind/managed-bitcoind-service-lifecycle.js +296 -0
  29. package/dist/bitcoind/managed-bitcoind-service-process.d.ts +8 -0
  30. package/dist/bitcoind/managed-bitcoind-service-process.js +48 -0
  31. package/dist/bitcoind/managed-bitcoind-service-replica.d.ts +8 -0
  32. package/dist/bitcoind/managed-bitcoind-service-replica.js +142 -0
  33. package/dist/bitcoind/managed-bitcoind-service-status.d.ts +42 -0
  34. package/dist/bitcoind/managed-bitcoind-service-status.js +170 -0
  35. package/dist/bitcoind/managed-bitcoind-service-types.d.ts +36 -0
  36. package/dist/bitcoind/managed-bitcoind-service-types.js +1 -0
  37. package/dist/bitcoind/service.d.ts +7 -63
  38. package/dist/bitcoind/service.js +7 -797
  39. package/dist/cli/mining-format.js +6 -1
  40. package/dist/cli/wallet-format/balance.js +1 -1
  41. package/dist/client/default-client.d.ts +3 -1
  42. package/dist/client/default-client.js +22 -0
  43. package/dist/types.d.ts +13 -1
  44. package/dist/wallet/fs/atomic.d.ts +11 -2
  45. package/dist/wallet/fs/atomic.js +45 -5
  46. package/dist/wallet/mining/cycle.js +4 -4
  47. package/dist/wallet/mining/engine-types.d.ts +1 -0
  48. package/dist/wallet/mining/engine-types.js +9 -1
  49. package/dist/wallet/mining/projection.d.ts +1 -0
  50. package/dist/wallet/mining/projection.js +15 -1
  51. package/dist/wallet/mining/publish.js +3 -6
  52. package/dist/wallet/mining/runner.js +30 -18
  53. package/dist/wallet/mining/visualizer-sync.js +7 -9
  54. package/dist/wallet/mining/visualizer.js +9 -7
  55. package/dist/wallet/read/context.d.ts +4 -10
  56. package/dist/wallet/read/context.js +6 -228
  57. package/dist/wallet/read/local-state.d.ts +36 -0
  58. package/dist/wallet/read/local-state.js +259 -0
  59. package/dist/wallet/read/managed-bitcoind.d.ts +30 -0
  60. package/dist/wallet/read/managed-bitcoind.js +138 -0
  61. package/dist/wallet/read/managed-indexer.d.ts +23 -0
  62. package/dist/wallet/read/managed-indexer.js +87 -0
  63. package/dist/wallet/read/managed-services.d.ts +6 -21
  64. package/dist/wallet/read/managed-services.js +23 -196
  65. package/dist/wallet/read/types.d.ts +1 -0
  66. 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 {};