@cogcoin/client 1.0.1 → 1.1.0

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 (79) hide show
  1. package/README.md +4 -2
  2. package/dist/bitcoind/client/factory.d.ts +0 -8
  3. package/dist/bitcoind/client/factory.js +1 -59
  4. package/dist/bitcoind/client/managed-client.d.ts +1 -3
  5. package/dist/bitcoind/client/managed-client.js +3 -47
  6. package/dist/bitcoind/indexer-daemon-main.js +173 -28
  7. package/dist/bitcoind/indexer-daemon.d.ts +14 -3
  8. package/dist/bitcoind/indexer-daemon.js +145 -29
  9. package/dist/bitcoind/indexer-monitor.d.ts +12 -0
  10. package/dist/bitcoind/indexer-monitor.js +89 -0
  11. package/dist/bitcoind/progress/follow-scene.d.ts +7 -1
  12. package/dist/bitcoind/progress/follow-scene.js +87 -4
  13. package/dist/bitcoind/progress/tty-renderer.d.ts +2 -0
  14. package/dist/bitcoind/progress/tty-renderer.js +2 -0
  15. package/dist/bitcoind/retryable-rpc.js +3 -0
  16. package/dist/bitcoind/service.d.ts +1 -0
  17. package/dist/bitcoind/service.js +31 -9
  18. package/dist/bitcoind/testing.d.ts +0 -1
  19. package/dist/bitcoind/testing.js +0 -1
  20. package/dist/bitcoind/types.d.ts +5 -2
  21. package/dist/cli/commands/follow.js +44 -49
  22. package/dist/cli/commands/mining-admin.js +65 -2
  23. package/dist/cli/commands/mining-read.js +43 -3
  24. package/dist/cli/commands/mining-runtime.js +91 -73
  25. package/dist/cli/commands/service-runtime.js +42 -2
  26. package/dist/cli/commands/status.js +3 -1
  27. package/dist/cli/commands/sync.js +50 -90
  28. package/dist/cli/commands/update.d.ts +2 -0
  29. package/dist/cli/commands/update.js +101 -0
  30. package/dist/cli/commands/wallet-admin.js +21 -3
  31. package/dist/cli/commands/wallet-read.js +2 -0
  32. package/dist/cli/context.js +36 -1
  33. package/dist/cli/managed-indexer-observer.d.ts +33 -0
  34. package/dist/cli/managed-indexer-observer.js +163 -0
  35. package/dist/cli/mining-format.d.ts +3 -1
  36. package/dist/cli/mining-format.js +63 -0
  37. package/dist/cli/mining-json.d.ts +11 -1
  38. package/dist/cli/mining-json.js +15 -0
  39. package/dist/cli/output.js +74 -2
  40. package/dist/cli/parse.d.ts +1 -1
  41. package/dist/cli/parse.js +28 -0
  42. package/dist/cli/prompt.js +109 -0
  43. package/dist/cli/read-json.d.ts +26 -1
  44. package/dist/cli/read-json.js +48 -0
  45. package/dist/cli/runner.js +8 -2
  46. package/dist/cli/signals.d.ts +12 -0
  47. package/dist/cli/signals.js +31 -13
  48. package/dist/cli/types.d.ts +13 -4
  49. package/dist/cli/update-notifier.js +7 -222
  50. package/dist/cli/update-service.d.ts +34 -0
  51. package/dist/cli/update-service.js +152 -0
  52. package/dist/client/initialization.js +5 -0
  53. package/dist/semver.d.ts +12 -0
  54. package/dist/semver.js +68 -0
  55. package/dist/wallet/lifecycle.d.ts +10 -0
  56. package/dist/wallet/mining/config.js +64 -3
  57. package/dist/wallet/mining/control.d.ts +5 -1
  58. package/dist/wallet/mining/control.js +269 -26
  59. package/dist/wallet/mining/domain-prompts.d.ts +17 -0
  60. package/dist/wallet/mining/domain-prompts.js +130 -0
  61. package/dist/wallet/mining/index.d.ts +2 -1
  62. package/dist/wallet/mining/index.js +1 -0
  63. package/dist/wallet/mining/provider-model.d.ts +30 -0
  64. package/dist/wallet/mining/provider-model.js +134 -0
  65. package/dist/wallet/mining/runner.d.ts +156 -5
  66. package/dist/wallet/mining/runner.js +1019 -399
  67. package/dist/wallet/mining/runtime-artifacts.js +1 -0
  68. package/dist/wallet/mining/sentence-protocol.d.ts +1 -0
  69. package/dist/wallet/mining/sentences.d.ts +2 -2
  70. package/dist/wallet/mining/sentences.js +32 -6
  71. package/dist/wallet/mining/types.d.ts +35 -1
  72. package/dist/wallet/mining/visualizer.d.ts +3 -0
  73. package/dist/wallet/mining/visualizer.js +132 -15
  74. package/dist/wallet/read/context.d.ts +1 -0
  75. package/dist/wallet/read/context.js +15 -7
  76. package/dist/wallet/state/client-password-agent.js +4 -1
  77. package/dist/wallet/state/client-password.js +15 -8
  78. package/dist/wallet/tx/common.js +1 -1
  79. package/package.json +3 -2
@@ -0,0 +1,134 @@
1
+ const DEFAULT_BUILT_IN_PROVIDER_MODELS = {
2
+ openai: "gpt-5.4-mini",
3
+ anthropic: "claude-sonnet-4-20250514",
4
+ };
5
+ const RECOMMENDED_BUILT_IN_PROVIDER_MODELS = {
6
+ openai: "gpt-5.4-mini",
7
+ anthropic: "claude-sonnet-4-6",
8
+ };
9
+ const BUILT_IN_PROVIDER_MODEL_CATALOG = {
10
+ openai: [
11
+ {
12
+ label: "GPT-5.4",
13
+ modelId: "gpt-5.4",
14
+ inputUsdPerMillionTokens: 2.5,
15
+ outputUsdPerMillionTokens: 15,
16
+ },
17
+ {
18
+ label: "GPT-5.4 mini",
19
+ modelId: "gpt-5.4-mini",
20
+ inputUsdPerMillionTokens: 0.75,
21
+ outputUsdPerMillionTokens: 4.5,
22
+ },
23
+ {
24
+ label: "GPT-5.4 nano",
25
+ modelId: "gpt-5.4-nano",
26
+ inputUsdPerMillionTokens: 0.2,
27
+ outputUsdPerMillionTokens: 1.25,
28
+ },
29
+ ],
30
+ anthropic: [
31
+ {
32
+ label: "Claude Opus 4.7",
33
+ modelId: "claude-opus-4-7",
34
+ inputUsdPerMillionTokens: 5,
35
+ outputUsdPerMillionTokens: 25,
36
+ },
37
+ {
38
+ label: "Claude Sonnet 4.6",
39
+ modelId: "claude-sonnet-4-6",
40
+ inputUsdPerMillionTokens: 3,
41
+ outputUsdPerMillionTokens: 15,
42
+ },
43
+ {
44
+ label: "Claude Haiku 4.5",
45
+ modelId: "claude-haiku-4-5",
46
+ inputUsdPerMillionTokens: 1,
47
+ outputUsdPerMillionTokens: 5,
48
+ },
49
+ ],
50
+ };
51
+ const DAILY_COST_ESTIMATE_CALLS_PER_DAY = 144;
52
+ const DAILY_COST_ESTIMATE_BASE_INPUT_TOKENS = 340;
53
+ const DAILY_COST_ESTIMATE_PER_ROOT_INPUT_TOKENS = 85;
54
+ const DAILY_COST_ESTIMATE_BASE_OUTPUT_TOKENS = 120;
55
+ const DAILY_COST_ESTIMATE_PER_ROOT_OUTPUT_TOKENS = 105;
56
+ export const MINING_MODEL_DAILY_COST_ESTIMATE_ASSUMPTION = "Approximate daily cost assumes 144 sentence-generation calls/day using your current anchored root count, standard token pricing, no caching, and no extra prompt.";
57
+ function normalizeModelOverride(raw) {
58
+ if (typeof raw !== "string") {
59
+ return null;
60
+ }
61
+ const trimmed = raw.trim();
62
+ return trimmed.length === 0 ? null : trimmed;
63
+ }
64
+ export function getLegacyBuiltInProviderDefaultModel(provider) {
65
+ return DEFAULT_BUILT_IN_PROVIDER_MODELS[provider];
66
+ }
67
+ export function getRecommendedBuiltInProviderModel(provider) {
68
+ return RECOMMENDED_BUILT_IN_PROVIDER_MODELS[provider];
69
+ }
70
+ export function getBuiltInProviderModelCatalog(provider) {
71
+ return BUILT_IN_PROVIDER_MODEL_CATALOG[provider];
72
+ }
73
+ export function findBuiltInProviderModelCatalogEntry(provider, modelId) {
74
+ return BUILT_IN_PROVIDER_MODEL_CATALOG[provider].find((entry) => entry.modelId === modelId) ?? null;
75
+ }
76
+ export function normalizeMiningModelSelectionSource(raw, modelOverride) {
77
+ switch (raw) {
78
+ case "catalog":
79
+ case "custom":
80
+ case "legacy-default":
81
+ case "legacy-custom":
82
+ return raw;
83
+ default:
84
+ return modelOverride === null ? "legacy-default" : "legacy-custom";
85
+ }
86
+ }
87
+ export function normalizeMiningProviderConfigRecord(config) {
88
+ const modelOverride = normalizeModelOverride(config.modelOverride);
89
+ return {
90
+ ...config,
91
+ extraPrompt: typeof config.extraPrompt === "string" && config.extraPrompt.trim().length > 0
92
+ ? config.extraPrompt
93
+ : null,
94
+ modelOverride,
95
+ modelSelectionSource: normalizeMiningModelSelectionSource(config.modelSelectionSource, modelOverride),
96
+ };
97
+ }
98
+ export function resolveBuiltInProviderModel(provider, modelOverride) {
99
+ const normalizedModelOverride = normalizeModelOverride(modelOverride);
100
+ return {
101
+ effectiveModel: normalizedModelOverride ?? DEFAULT_BUILT_IN_PROVIDER_MODELS[provider],
102
+ usingDefaultModel: normalizedModelOverride === null,
103
+ };
104
+ }
105
+ export function resolveBuiltInProviderSelection(config) {
106
+ const modelOverride = normalizeModelOverride(config.modelOverride);
107
+ const modelSelectionSource = normalizeMiningModelSelectionSource(config.modelSelectionSource, modelOverride);
108
+ const { effectiveModel, usingDefaultModel } = resolveBuiltInProviderModel(config.provider, modelOverride);
109
+ return {
110
+ modelId: effectiveModel,
111
+ effectiveModel,
112
+ modelSelectionSource,
113
+ usingDefaultModel,
114
+ };
115
+ }
116
+ export function estimateBuiltInModelDailyCost(provider, modelId, eligibleRootCount) {
117
+ const model = findBuiltInProviderModelCatalogEntry(provider, modelId);
118
+ if (model === null) {
119
+ return null;
120
+ }
121
+ const rootCount = Math.max(0, Math.trunc(eligibleRootCount));
122
+ const estimatedInputTokens = DAILY_COST_ESTIMATE_BASE_INPUT_TOKENS
123
+ + (DAILY_COST_ESTIMATE_PER_ROOT_INPUT_TOKENS * rootCount);
124
+ const estimatedOutputTokens = DAILY_COST_ESTIMATE_BASE_OUTPUT_TOKENS
125
+ + (DAILY_COST_ESTIMATE_PER_ROOT_OUTPUT_TOKENS * rootCount);
126
+ const estimatedPerCallUsd = ((estimatedInputTokens / 1_000_000) * model.inputUsdPerMillionTokens) + ((estimatedOutputTokens / 1_000_000) * model.outputUsdPerMillionTokens);
127
+ const estimatedDailyCostUsd = Number((estimatedPerCallUsd * DAILY_COST_ESTIMATE_CALLS_PER_DAY).toFixed(6));
128
+ return {
129
+ estimatedDailyCostUsd,
130
+ estimatedDailyCostDisplay: estimatedDailyCostUsd < 0.005
131
+ ? "<$0.01/day"
132
+ : `$${estimatedDailyCostUsd.toFixed(2)}/day`,
133
+ };
134
+ }
@@ -1,14 +1,18 @@
1
- import { attachOrStartManagedBitcoindService } from "../../bitcoind/service.js";
1
+ import { spawn } from "node:child_process";
2
+ import { attachOrStartManagedBitcoindService, probeManagedBitcoindService, stopManagedBitcoindService } from "../../bitcoind/service.js";
2
3
  import { createRpcClient } from "../../bitcoind/node.js";
3
4
  import type { ProgressOutputMode } from "../../bitcoind/types.js";
4
5
  import { type FixedWalletInput, type MutationSender, type WalletMutationRpcClient } from "../tx/common.js";
6
+ import { readLockMetadata } from "../fs/lock.js";
5
7
  import type { WalletPrompter } from "../lifecycle.js";
6
8
  import { openWalletReadContext, type WalletReadContext } from "../read/index.js";
7
9
  import { type WalletRuntimePaths } from "../runtime.js";
8
10
  import { type WalletSecretProvider } from "../state/provider.js";
9
11
  import type { MiningStateRecord, OutpointRecord, WalletStateV1 } from "../types.js";
10
- import type { MiningEventRecord, MiningRuntimeStatusV1 } from "./types.js";
11
- import { type MiningFollowVisualizerState, type MiningSentenceBoardEntry } from "./visualizer.js";
12
+ import { requestMiningGenerationPreemption } from "./coordination.js";
13
+ import { type MiningSentenceGenerationRequest } from "./sentences.js";
14
+ import type { MiningControlPlaneView, MiningEventRecord, MiningRuntimeStatusV1 } from "./types.js";
15
+ import { type MiningFollowVisualizerState, type MiningSentenceBoardEntry, MiningFollowVisualizer } from "./visualizer.js";
12
16
  type MiningRpcClient = WalletMutationRpcClient & {
13
17
  getBlockchainInfo(): Promise<{
14
18
  blocks: number;
@@ -72,6 +76,41 @@ type MiningRpcClient = WalletMutationRpcClient & {
72
76
  sendRawTransaction(hex: string): Promise<string>;
73
77
  saveMempool?(): Promise<null>;
74
78
  };
79
+ interface MiningRunnerStatusOverrides {
80
+ runMode?: MiningRuntimeStatusV1["runMode"];
81
+ backgroundWorkerPid?: number | null;
82
+ backgroundWorkerRunId?: string | null;
83
+ backgroundWorkerHeartbeatAtUnixMs?: number | null;
84
+ currentPhase?: MiningRuntimeStatusV1["currentPhase"];
85
+ currentPublishState?: MiningRuntimeStatusV1["currentPublishState"];
86
+ targetBlockHeight?: number | null;
87
+ referencedBlockHashDisplay?: string | null;
88
+ currentDomainId?: number | null;
89
+ currentDomainName?: string | null;
90
+ currentSentenceDisplay?: string | null;
91
+ currentCanonicalBlend?: string | null;
92
+ currentTxid?: string | null;
93
+ currentWtxid?: string | null;
94
+ currentFeeRateSatVb?: number | null;
95
+ currentAbsoluteFeeSats?: number | null;
96
+ currentBlockFeeSpentSats?: string;
97
+ lastSuspendDetectedAtUnixMs?: number | null;
98
+ reconnectSettledUntilUnixMs?: number | null;
99
+ tipSettledUntilUnixMs?: number | null;
100
+ providerState?: MiningRuntimeStatusV1["providerState"];
101
+ corePublishState?: MiningRuntimeStatusV1["corePublishState"];
102
+ currentPublishDecision?: string | null;
103
+ sameDomainCompetitorSuppressed?: boolean | null;
104
+ higherRankedCompetitorDomainCount?: number | null;
105
+ dedupedCompetitorDomainCount?: number | null;
106
+ competitivenessGateIndeterminate?: boolean | null;
107
+ mempoolSequenceCacheStatus?: MiningRuntimeStatusV1["mempoolSequenceCacheStatus"];
108
+ lastMempoolSequence?: string | null;
109
+ lastCompetitivenessGateAtUnixMs?: number | null;
110
+ lastError?: string | null;
111
+ note?: string | null;
112
+ livePublishInMempool?: boolean | null;
113
+ }
75
114
  interface MiningCandidate {
76
115
  domainId: number;
77
116
  domainName: string;
@@ -97,8 +136,9 @@ type ReadyMiningReadContext = WalletReadContext & {
97
136
  interface MiningPublishSkipResult {
98
137
  state: WalletStateV1;
99
138
  txid: null;
100
- decision: "publish-skipped-stale-candidate";
139
+ decision: "publish-skipped-stale-candidate" | "publish-paused-insufficient-funds";
101
140
  note: string;
141
+ lastError?: string | null;
102
142
  skipped: true;
103
143
  retryable?: false;
104
144
  candidate: null;
@@ -123,6 +163,13 @@ interface RunnerDependencies {
123
163
  attachService?: typeof attachOrStartManagedBitcoindService;
124
164
  rpcFactory?: (config: Parameters<typeof createRpcClient>[0]) => MiningRpcClient;
125
165
  fetchImpl?: typeof fetch;
166
+ requestMiningPreemption?: typeof requestMiningGenerationPreemption;
167
+ runMiningLoopImpl?: typeof runMiningLoop;
168
+ saveStopSnapshotImpl?: typeof saveStopSnapshot;
169
+ spawnWorkerProcess?: typeof spawn;
170
+ waitForBackgroundHealthyImpl?: typeof waitForBackgroundHealthy;
171
+ shutdownGraceMs?: number;
172
+ sleepImpl?: typeof sleep;
126
173
  }
127
174
  interface MiningLoopState {
128
175
  attemptedTipKey: string | null;
@@ -131,10 +178,19 @@ interface MiningLoopState {
131
178
  selectedCandidate: MiningCandidate | null;
132
179
  ui: MiningFollowVisualizerState;
133
180
  waitingNote: string | null;
181
+ bitcoinRecoveryFirstFailureAtUnixMs: number | null;
182
+ bitcoinRecoveryFirstUnreachableAtUnixMs: number | null;
183
+ bitcoinRecoveryLastRestartAttemptAtUnixMs: number | null;
184
+ bitcoinRecoveryServiceInstanceId: string | null;
185
+ bitcoinRecoveryProcessId: number | null;
186
+ reconnectSettledUntilUnixMs: number | null;
187
+ tipSettledUntilUnixMs: number | null;
134
188
  }
135
189
  export interface RunForegroundMiningOptions extends RunnerDependencies {
136
190
  dataDir: string;
137
191
  databasePath: string;
192
+ clientVersion?: string | null;
193
+ updateAvailable?: boolean;
138
194
  provider?: WalletSecretProvider;
139
195
  prompter: WalletPrompter;
140
196
  builtInSetupEnsured?: boolean;
@@ -168,11 +224,19 @@ export interface MiningStartResult {
168
224
  started: boolean;
169
225
  snapshot: MiningRuntimeStatusV1 | null;
170
226
  }
227
+ interface MiningRuntimeTakeoverResult {
228
+ controlLockCleared: boolean;
229
+ replaced: boolean;
230
+ snapshot: MiningRuntimeStatusV1 | null;
231
+ terminatedPids: number[];
232
+ }
233
+ declare function sleep(ms: number, signal?: AbortSignal): Promise<void>;
171
234
  export declare function createMiningLoopStateForTesting(): MiningLoopState;
172
235
  export declare function resetMiningUiForTipForTesting(loopState: MiningLoopState, targetBlockHeight: number | null): void;
173
236
  export declare function resolveSettledBoardForTesting(options: {
174
237
  snapshotState: NonNullable<WalletReadContext["snapshot"]>["state"] | null | undefined;
175
238
  snapshotTipHeight: number | null;
239
+ snapshotTipPreviousHashHex?: string | null;
176
240
  nodeBestHeight: number | null;
177
241
  }): {
178
242
  settledBlockHeight: number | null;
@@ -222,7 +286,7 @@ export declare function createMiningPlanForTesting(options: {
222
286
  referencedBlockHashInternal: Uint8Array;
223
287
  targetBlockHeight: number;
224
288
  };
225
- conflictOutpoint: OutpointRecord;
289
+ conflictOutpoint: OutpointRecord | null;
226
290
  allUtxos: Awaited<ReturnType<MiningRpcClient["listUnspent"]>>;
227
291
  feeRateSatVb: number;
228
292
  }): {
@@ -243,6 +307,19 @@ export declare function resolveMiningConflictOutpointForTesting(options: {
243
307
  state: WalletStateV1;
244
308
  allUtxos: Awaited<ReturnType<MiningRpcClient["listUnspent"]>>;
245
309
  }): OutpointRecord | null;
310
+ export declare function buildMiningGenerationRequestForTesting(options: {
311
+ targetBlockHeight: number;
312
+ referencedBlockHashDisplay: string;
313
+ generatedAtUnixMs?: number;
314
+ requestId?: string;
315
+ domains: Array<{
316
+ domainId: number;
317
+ domainName: string;
318
+ requiredWords: [string, string, string, string, string];
319
+ }>;
320
+ domainExtraPrompts?: Record<string, string>;
321
+ extraPrompt?: string | null;
322
+ }): MiningSentenceGenerationRequest;
246
323
  declare function publishCandidateOnce(options: {
247
324
  readContext: WalletReadContext & {
248
325
  localState: {
@@ -283,6 +360,39 @@ export declare function ensureBuiltInMiningSetupIfNeeded(options: {
283
360
  prompter: WalletPrompter;
284
361
  paths: WalletRuntimePaths;
285
362
  }): Promise<boolean>;
363
+ declare function saveStopSnapshot(options: {
364
+ dataDir: string;
365
+ databasePath: string;
366
+ provider: WalletSecretProvider;
367
+ paths: WalletRuntimePaths;
368
+ runMode: "foreground" | "background";
369
+ backgroundWorkerPid: number | null;
370
+ backgroundWorkerRunId: string | null;
371
+ note: string | null;
372
+ }): Promise<void>;
373
+ declare function runMiningLoop(options: {
374
+ dataDir: string;
375
+ databasePath: string;
376
+ provider: WalletSecretProvider;
377
+ paths: WalletRuntimePaths;
378
+ runMode: "foreground" | "background";
379
+ backgroundWorkerPid: number | null;
380
+ backgroundWorkerRunId: string | null;
381
+ signal?: AbortSignal;
382
+ fetchImpl?: typeof fetch;
383
+ openReadContext: typeof openWalletReadContext;
384
+ attachService: typeof attachOrStartManagedBitcoindService;
385
+ probeService?: typeof probeManagedBitcoindService;
386
+ stopService?: typeof stopManagedBitcoindService;
387
+ rpcFactory: (config: Parameters<typeof createRpcClient>[0]) => MiningRpcClient;
388
+ stdout?: {
389
+ write(chunk: string): void;
390
+ };
391
+ visualizer?: MiningFollowVisualizer;
392
+ nowImpl?: () => number;
393
+ sleepImpl?: typeof sleep;
394
+ }): Promise<void>;
395
+ declare function waitForBackgroundHealthy(paths: WalletRuntimePaths): Promise<MiningRuntimeStatusV1 | null>;
286
396
  export declare function runForegroundMining(options: RunForegroundMiningOptions): Promise<void>;
287
397
  export declare function startBackgroundMining(options: StartBackgroundMiningOptions): Promise<MiningStartResult>;
288
398
  export declare function stopBackgroundMining(options: StopBackgroundMiningOptions): Promise<MiningRuntimeStatusV1 | null>;
@@ -303,7 +413,18 @@ export declare function handleDetectedMiningRuntimeResumeForTesting(options: {
303
413
  backgroundWorkerRunId: string | null;
304
414
  detectedAtUnixMs: number;
305
415
  openReadContext: typeof openWalletReadContext;
416
+ visualizer?: MiningFollowVisualizer;
417
+ loopState?: MiningLoopState;
306
418
  }): Promise<void>;
419
+ export declare function takeOverMiningRuntimeForTesting(options: {
420
+ paths: WalletRuntimePaths;
421
+ reason: string;
422
+ clearControlLockFile?: boolean;
423
+ controlLockMetadata?: Awaited<ReturnType<typeof readLockMetadata>>;
424
+ requestMiningPreemption?: typeof requestMiningGenerationPreemption;
425
+ shutdownGraceMs?: number;
426
+ sleepImpl?: typeof sleep;
427
+ }): Promise<MiningRuntimeTakeoverResult>;
307
428
  export declare function performMiningCycleForTesting(options: {
308
429
  dataDir: string;
309
430
  databasePath: string;
@@ -316,12 +437,42 @@ export declare function performMiningCycleForTesting(options: {
316
437
  fetchImpl?: typeof fetch;
317
438
  openReadContext: typeof openWalletReadContext;
318
439
  attachService: typeof attachOrStartManagedBitcoindService;
440
+ probeService?: typeof probeManagedBitcoindService;
441
+ stopService?: typeof stopManagedBitcoindService;
319
442
  rpcFactory: (config: Parameters<typeof createRpcClient>[0]) => MiningRpcClient;
320
443
  stdout?: {
321
444
  write(chunk: string): void;
322
445
  };
323
446
  loopState?: MiningLoopState;
447
+ nowImpl?: () => number;
448
+ }): Promise<void>;
449
+ export declare function runMiningLoopForTesting(options: {
450
+ dataDir: string;
451
+ databasePath: string;
452
+ provider: WalletSecretProvider;
453
+ paths: WalletRuntimePaths;
454
+ runMode: "foreground" | "background";
455
+ backgroundWorkerPid: number | null;
456
+ backgroundWorkerRunId: string | null;
457
+ signal?: AbortSignal;
458
+ fetchImpl?: typeof fetch;
459
+ openReadContext: typeof openWalletReadContext;
460
+ attachService: typeof attachOrStartManagedBitcoindService;
461
+ probeService?: typeof probeManagedBitcoindService;
462
+ stopService?: typeof stopManagedBitcoindService;
463
+ rpcFactory: (config: Parameters<typeof createRpcClient>[0]) => MiningRpcClient;
464
+ stdout?: {
465
+ write(chunk: string): void;
466
+ };
467
+ visualizer?: MiningFollowVisualizer;
468
+ nowImpl?: () => number;
469
+ sleepImpl?: typeof sleep;
324
470
  }): Promise<void>;
471
+ export declare function buildPrePublishStatusOverridesForTesting(options: {
472
+ state: WalletStateV1;
473
+ candidate: MiningCandidate;
474
+ }): MiningRunnerStatusOverrides;
475
+ export declare function buildStatusSnapshotForTesting(view: MiningControlPlaneView, overrides?: MiningRunnerStatusOverrides): MiningRuntimeStatusV1;
325
476
  export declare function shouldKeepCurrentTipLivePublishForTesting(options: {
326
477
  liveState: MiningStateRecord;
327
478
  candidate: {