@cogcoin/client 0.5.15 → 1.0.1

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 (174) hide show
  1. package/README.md +80 -25
  2. package/dist/app-paths.d.ts +5 -6
  3. package/dist/app-paths.js +8 -16
  4. package/dist/art/balance.txt +10 -0
  5. package/dist/art/welcome.txt +16 -0
  6. package/dist/bitcoind/bootstrap/controller.d.ts +1 -0
  7. package/dist/bitcoind/bootstrap/controller.js +53 -1
  8. package/dist/bitcoind/client/follow-block-times.d.ts +1 -0
  9. package/dist/bitcoind/client/follow-block-times.js +1 -1
  10. package/dist/bitcoind/client/internal-types.d.ts +7 -3
  11. package/dist/bitcoind/client/managed-client.d.ts +4 -2
  12. package/dist/bitcoind/client/managed-client.js +14 -0
  13. package/dist/bitcoind/client/sync-engine.js +72 -11
  14. package/dist/bitcoind/hash-order.d.ts +4 -0
  15. package/dist/bitcoind/hash-order.js +13 -0
  16. package/dist/bitcoind/indexer-daemon-main.js +11 -3
  17. package/dist/bitcoind/normalize.js +3 -2
  18. package/dist/bitcoind/processing-start-height.d.ts +5 -0
  19. package/dist/bitcoind/processing-start-height.js +7 -0
  20. package/dist/bitcoind/progress/constants.d.ts +4 -0
  21. package/dist/bitcoind/progress/constants.js +4 -0
  22. package/dist/bitcoind/progress/controller.d.ts +2 -1
  23. package/dist/bitcoind/progress/controller.js +3 -3
  24. package/dist/bitcoind/progress/follow-scene.d.ts +6 -2
  25. package/dist/bitcoind/progress/follow-scene.js +29 -6
  26. package/dist/bitcoind/progress/formatting.d.ts +1 -0
  27. package/dist/bitcoind/progress/formatting.js +6 -0
  28. package/dist/bitcoind/progress/train-scene.js +37 -18
  29. package/dist/bitcoind/progress/tty-renderer.d.ts +6 -1
  30. package/dist/bitcoind/progress/tty-renderer.js +8 -4
  31. package/dist/bitcoind/rpc.d.ts +2 -1
  32. package/dist/bitcoind/rpc.js +3 -0
  33. package/dist/bitcoind/types.d.ts +6 -0
  34. package/dist/bytes.d.ts +1 -0
  35. package/dist/bytes.js +3 -0
  36. package/dist/cli/art.d.ts +2 -0
  37. package/dist/cli/art.js +37 -0
  38. package/dist/cli/commands/client-admin.d.ts +2 -0
  39. package/dist/cli/commands/client-admin.js +91 -0
  40. package/dist/cli/commands/follow.js +0 -2
  41. package/dist/cli/commands/mining-admin.js +6 -47
  42. package/dist/cli/commands/mining-read.js +11 -50
  43. package/dist/cli/commands/mining-runtime.js +142 -5
  44. package/dist/cli/commands/service-runtime.js +0 -2
  45. package/dist/cli/commands/status.js +8 -2
  46. package/dist/cli/commands/sync.js +49 -92
  47. package/dist/cli/commands/wallet-admin.js +142 -136
  48. package/dist/cli/commands/wallet-mutation.js +91 -79
  49. package/dist/cli/commands/wallet-read.js +15 -18
  50. package/dist/cli/context.js +5 -14
  51. package/dist/cli/mining-format.d.ts +0 -1
  52. package/dist/cli/mining-format.js +5 -37
  53. package/dist/cli/mining-json.d.ts +0 -18
  54. package/dist/cli/mining-json.js +0 -35
  55. package/dist/cli/mutation-command-groups.d.ts +1 -2
  56. package/dist/cli/mutation-command-groups.js +0 -5
  57. package/dist/cli/mutation-json.d.ts +24 -145
  58. package/dist/cli/mutation-json.js +30 -136
  59. package/dist/cli/mutation-resolved-json.d.ts +0 -7
  60. package/dist/cli/mutation-resolved-json.js +4 -10
  61. package/dist/cli/mutation-success.d.ts +2 -0
  62. package/dist/cli/mutation-success.js +11 -1
  63. package/dist/cli/mutation-text-format.js +1 -3
  64. package/dist/cli/output.d.ts +1 -1
  65. package/dist/cli/output.js +254 -231
  66. package/dist/cli/parse.d.ts +1 -1
  67. package/dist/cli/parse.js +93 -122
  68. package/dist/cli/preview-json.d.ts +17 -120
  69. package/dist/cli/preview-json.js +14 -97
  70. package/dist/cli/prompt.js +8 -13
  71. package/dist/cli/read-json.d.ts +15 -37
  72. package/dist/cli/read-json.js +44 -140
  73. package/dist/cli/runner.js +10 -13
  74. package/dist/cli/sync-progress.d.ts +6 -0
  75. package/dist/cli/sync-progress.js +91 -0
  76. package/dist/cli/types.d.ts +9 -17
  77. package/dist/cli/types.js +0 -2
  78. package/dist/cli/wallet-format.d.ts +1 -0
  79. package/dist/cli/wallet-format.js +208 -144
  80. package/dist/cli/workflow-hints.d.ts +3 -3
  81. package/dist/cli/workflow-hints.js +11 -8
  82. package/dist/client/default-client.d.ts +3 -1
  83. package/dist/client/default-client.js +45 -2
  84. package/dist/client/factory.js +1 -1
  85. package/dist/client/initialization.js +23 -0
  86. package/dist/client/persistence.js +5 -5
  87. package/dist/client/store-adapter.js +1 -0
  88. package/dist/sqlite/checkpoints.d.ts +1 -0
  89. package/dist/sqlite/checkpoints.js +7 -0
  90. package/dist/sqlite/store.js +14 -1
  91. package/dist/types.d.ts +1 -0
  92. package/dist/wallet/coin-control.d.ts +41 -12
  93. package/dist/wallet/coin-control.js +100 -428
  94. package/dist/wallet/descriptor-normalization.d.ts +1 -3
  95. package/dist/wallet/descriptor-normalization.js +0 -16
  96. package/dist/wallet/lifecycle.d.ts +7 -99
  97. package/dist/wallet/lifecycle.js +513 -968
  98. package/dist/wallet/managed-core-wallet.d.ts +13 -0
  99. package/dist/wallet/managed-core-wallet.js +20 -0
  100. package/dist/wallet/mining/constants.d.ts +5 -12
  101. package/dist/wallet/mining/constants.js +5 -12
  102. package/dist/wallet/mining/control.d.ts +1 -13
  103. package/dist/wallet/mining/control.js +45 -349
  104. package/dist/wallet/mining/index.d.ts +4 -5
  105. package/dist/wallet/mining/index.js +2 -3
  106. package/dist/wallet/mining/runner.d.ts +123 -13
  107. package/dist/wallet/mining/runner.js +899 -511
  108. package/dist/wallet/mining/runtime-artifacts.js +23 -3
  109. package/dist/wallet/mining/sentence-protocol.d.ts +44 -0
  110. package/dist/wallet/mining/sentence-protocol.js +123 -0
  111. package/dist/wallet/mining/sentences.d.ts +4 -8
  112. package/dist/wallet/mining/sentences.js +3 -52
  113. package/dist/wallet/mining/state.d.ts +11 -6
  114. package/dist/wallet/mining/state.js +7 -6
  115. package/dist/wallet/mining/types.d.ts +2 -30
  116. package/dist/wallet/mining/visualizer.d.ts +31 -3
  117. package/dist/wallet/mining/visualizer.js +135 -13
  118. package/dist/wallet/read/context.d.ts +0 -2
  119. package/dist/wallet/read/context.js +119 -140
  120. package/dist/wallet/read/filter.js +2 -11
  121. package/dist/wallet/read/index.d.ts +1 -1
  122. package/dist/wallet/read/project.js +24 -77
  123. package/dist/wallet/read/types.d.ts +10 -25
  124. package/dist/wallet/reset.d.ts +0 -1
  125. package/dist/wallet/reset.js +60 -138
  126. package/dist/wallet/root-resolution.d.ts +1 -5
  127. package/dist/wallet/root-resolution.js +0 -18
  128. package/dist/wallet/runtime.d.ts +0 -6
  129. package/dist/wallet/runtime.js +0 -8
  130. package/dist/wallet/state/client-password-agent.js +208 -0
  131. package/dist/wallet/state/client-password.d.ts +65 -0
  132. package/dist/wallet/state/client-password.js +952 -0
  133. package/dist/wallet/state/crypto.d.ts +1 -20
  134. package/dist/wallet/state/crypto.js +0 -63
  135. package/dist/wallet/state/provider.d.ts +23 -11
  136. package/dist/wallet/state/provider.js +248 -290
  137. package/dist/wallet/state/storage.d.ts +2 -2
  138. package/dist/wallet/state/storage.js +48 -16
  139. package/dist/wallet/tx/anchor.d.ts +3 -28
  140. package/dist/wallet/tx/anchor.js +349 -1250
  141. package/dist/wallet/tx/bitcoin-transfer.d.ts +35 -0
  142. package/dist/wallet/tx/bitcoin-transfer.js +200 -0
  143. package/dist/wallet/tx/cog.d.ts +5 -1
  144. package/dist/wallet/tx/cog.js +149 -185
  145. package/dist/wallet/tx/common.d.ts +61 -8
  146. package/dist/wallet/tx/common.js +266 -146
  147. package/dist/wallet/tx/domain-admin.d.ts +3 -1
  148. package/dist/wallet/tx/domain-admin.js +61 -99
  149. package/dist/wallet/tx/domain-market.d.ts +5 -1
  150. package/dist/wallet/tx/domain-market.js +221 -228
  151. package/dist/wallet/tx/field.d.ts +4 -10
  152. package/dist/wallet/tx/field.js +83 -924
  153. package/dist/wallet/tx/identity-selector.d.ts +9 -3
  154. package/dist/wallet/tx/identity-selector.js +17 -35
  155. package/dist/wallet/tx/index.d.ts +3 -1
  156. package/dist/wallet/tx/index.js +2 -1
  157. package/dist/wallet/tx/register.d.ts +3 -1
  158. package/dist/wallet/tx/register.js +62 -220
  159. package/dist/wallet/tx/reputation.d.ts +3 -1
  160. package/dist/wallet/tx/reputation.js +58 -95
  161. package/dist/wallet/types.d.ts +8 -122
  162. package/package.json +5 -5
  163. package/dist/wallet/archive.d.ts +0 -4
  164. package/dist/wallet/archive.js +0 -41
  165. package/dist/wallet/mining/hook-protocol.d.ts +0 -47
  166. package/dist/wallet/mining/hook-protocol.js +0 -161
  167. package/dist/wallet/mining/hook-runner.js +0 -52
  168. package/dist/wallet/mining/hooks.d.ts +0 -38
  169. package/dist/wallet/mining/hooks.js +0 -520
  170. package/dist/wallet/state/explicit-lock.d.ts +0 -4
  171. package/dist/wallet/state/explicit-lock.js +0 -19
  172. package/dist/wallet/state/session.d.ts +0 -12
  173. package/dist/wallet/state/session.js +0 -23
  174. /package/dist/wallet/{mining/hook-runner.d.ts → state/client-password-agent.d.ts} +0 -0
@@ -0,0 +1,13 @@
1
+ export declare const MANAGED_CORE_WALLET_UNLOCK_TIMEOUT_SECONDS = 10;
2
+ export interface ManagedCoreWalletUnlockingRpc {
3
+ walletPassphrase(walletName: string, passphrase: string, timeoutSeconds: number): Promise<null>;
4
+ walletLock(walletName: string): Promise<null>;
5
+ }
6
+ export declare function withUnlockedManagedCoreWallet<T>(options: {
7
+ rpc: ManagedCoreWalletUnlockingRpc;
8
+ walletName: string;
9
+ internalPassphrase: string;
10
+ timeoutSeconds?: number;
11
+ run: () => Promise<T>;
12
+ }): Promise<T>;
13
+ export declare function clearLegacyWalletLockArtifacts(walletRuntimeRoot: string): Promise<void>;
@@ -0,0 +1,20 @@
1
+ import { rm } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ export const MANAGED_CORE_WALLET_UNLOCK_TIMEOUT_SECONDS = 10;
4
+ const LEGACY_UNLOCK_SESSION_FILENAME = "wallet-unlock-session.enc";
5
+ const LEGACY_EXPLICIT_LOCK_FILENAME = "wallet-explicit-lock.json";
6
+ export async function withUnlockedManagedCoreWallet(options) {
7
+ await options.rpc.walletPassphrase(options.walletName, options.internalPassphrase, options.timeoutSeconds ?? MANAGED_CORE_WALLET_UNLOCK_TIMEOUT_SECONDS);
8
+ try {
9
+ return await options.run();
10
+ }
11
+ finally {
12
+ await options.rpc.walletLock(options.walletName).catch(() => undefined);
13
+ }
14
+ }
15
+ export async function clearLegacyWalletLockArtifacts(walletRuntimeRoot) {
16
+ await Promise.all([
17
+ rm(join(walletRuntimeRoot, LEGACY_UNLOCK_SESSION_FILENAME), { force: true }).catch(() => undefined),
18
+ rm(join(walletRuntimeRoot, LEGACY_EXPLICIT_LOCK_FILENAME), { force: true }).catch(() => undefined),
19
+ ]);
20
+ }
@@ -8,17 +8,10 @@ export declare const MINING_PROVIDER_BACKOFF_BASE_MS = 30000;
8
8
  export declare const MINING_PROVIDER_BACKOFF_MAX_MS = 900000;
9
9
  export declare const MINING_LOOP_INTERVAL_MS = 2000;
10
10
  export declare const MINING_BUILTIN_TIMEOUT_MS = 30000;
11
- export declare const MINING_HOOK_SCHEMA_VERSION: 1;
12
- export declare const MINING_HOOK_MAX_CANDIDATE_SENTENCE_UTF8_BYTES = 512;
13
- export declare const MINING_HOOK_MAX_CANDIDATES_PER_ROOT_DOMAIN = 8;
14
- export declare const MINING_HOOK_MAX_CANDIDATES_TOTAL = 64;
15
- export declare const MINING_HOOK_TIMEOUT_MS = 30000;
16
- export declare const MINING_CUSTOM_HOOK_TIMEOUT_MS = 30000;
17
- export declare const MINING_HOOK_STDOUT_MAX_BYTES = 262144;
18
- export declare const MINING_HOOK_STDERR_MAX_BYTES = 65536;
19
- export declare const MINING_HOOK_VALIDATION_TIMEOUT_MS = 10000;
20
- export declare const MINING_HOOK_TERMINATE_GRACE_MS = 2000;
21
- export declare const MINING_HOOK_FAILURE_THRESHOLD = 3;
22
- export declare const MINING_HOOK_COOLDOWN_MS = 300000;
11
+ export declare const MINING_SENTENCE_SCHEMA_VERSION: 1;
12
+ export declare const MINING_SENTENCE_MAX_CANDIDATE_SENTENCE_UTF8_BYTES = 512;
13
+ export declare const MINING_SENTENCE_MAX_CANDIDATES_PER_ROOT_DOMAIN = 8;
14
+ export declare const MINING_SENTENCE_MAX_CANDIDATES_TOTAL = 64;
15
+ export declare const MINING_SENTENCE_TIMEOUT_MS = 30000;
23
16
  export declare const MINING_SHUTDOWN_GRACE_MS = 15000;
24
17
  export declare const MINING_SETTLEMENT_DUMMY_REWARD = 100n;
@@ -8,17 +8,10 @@ export const MINING_PROVIDER_BACKOFF_BASE_MS = 30_000;
8
8
  export const MINING_PROVIDER_BACKOFF_MAX_MS = 900_000;
9
9
  export const MINING_LOOP_INTERVAL_MS = 2_000;
10
10
  export const MINING_BUILTIN_TIMEOUT_MS = 30_000;
11
- export const MINING_HOOK_SCHEMA_VERSION = 1;
12
- export const MINING_HOOK_MAX_CANDIDATE_SENTENCE_UTF8_BYTES = 512;
13
- export const MINING_HOOK_MAX_CANDIDATES_PER_ROOT_DOMAIN = 8;
14
- export const MINING_HOOK_MAX_CANDIDATES_TOTAL = 64;
15
- export const MINING_HOOK_TIMEOUT_MS = 30_000;
16
- export const MINING_CUSTOM_HOOK_TIMEOUT_MS = MINING_HOOK_TIMEOUT_MS;
17
- export const MINING_HOOK_STDOUT_MAX_BYTES = 262_144;
18
- export const MINING_HOOK_STDERR_MAX_BYTES = 65_536;
19
- export const MINING_HOOK_VALIDATION_TIMEOUT_MS = 10_000;
20
- export const MINING_HOOK_TERMINATE_GRACE_MS = 2_000;
21
- export const MINING_HOOK_FAILURE_THRESHOLD = 3;
22
- export const MINING_HOOK_COOLDOWN_MS = 300_000;
11
+ export const MINING_SENTENCE_SCHEMA_VERSION = 1;
12
+ export const MINING_SENTENCE_MAX_CANDIDATE_SENTENCE_UTF8_BYTES = 512;
13
+ export const MINING_SENTENCE_MAX_CANDIDATES_PER_ROOT_DOMAIN = 8;
14
+ export const MINING_SENTENCE_MAX_CANDIDATES_TOTAL = 64;
15
+ export const MINING_SENTENCE_TIMEOUT_MS = 30_000;
23
16
  export const MINING_SHUTDOWN_GRACE_MS = 15_000;
24
17
  export const MINING_SETTLEMENT_DUMMY_REWARD = 100n;
@@ -1,4 +1,4 @@
1
- import { type WalletPrompter } from "../lifecycle.js";
1
+ import type { WalletPrompter } from "../lifecycle.js";
2
2
  import { type WalletRuntimePaths } from "../runtime.js";
3
3
  import { type WalletSecretProvider } from "../state/provider.js";
4
4
  import type { WalletBitcoindStatus, WalletIndexerStatus, WalletLocalStateStatus, WalletNodeStatus } from "../read/types.js";
@@ -10,7 +10,6 @@ export declare function inspectMiningControlPlane(options: {
10
10
  nodeStatus: WalletNodeStatus | null;
11
11
  nodeHealth: MiningRuntimeStatusV1["nodeHealth"];
12
12
  indexer: WalletIndexerStatus;
13
- verify?: boolean;
14
13
  nowUnixMs?: number;
15
14
  paths?: WalletRuntimePaths;
16
15
  }): Promise<MiningControlPlaneView>;
@@ -24,17 +23,6 @@ export declare function refreshMiningRuntimeStatus(options: {
24
23
  nowUnixMs?: number;
25
24
  paths?: WalletRuntimePaths;
26
25
  }): Promise<MiningControlPlaneView>;
27
- export declare function enableMiningHooks(options: {
28
- provider?: WalletSecretProvider;
29
- prompter: WalletPrompter;
30
- nowUnixMs?: number;
31
- paths?: WalletRuntimePaths;
32
- }): Promise<MiningControlPlaneView>;
33
- export declare function disableMiningHooks(options: {
34
- provider?: WalletSecretProvider;
35
- nowUnixMs?: number;
36
- paths?: WalletRuntimePaths;
37
- }): Promise<MiningControlPlaneView>;
38
26
  export declare function setupBuiltInMining(options: {
39
27
  provider?: WalletSecretProvider;
40
28
  prompter: WalletPrompter;
@@ -1,32 +1,12 @@
1
- import { randomBytes } from "node:crypto";
2
1
  import { acquireFileLock } from "../fs/lock.js";
3
- import { loadOrAutoUnlockWalletState } from "../lifecycle.js";
4
2
  import { resolveWalletRuntimePathsForTesting } from "../runtime.js";
5
- import { saveWalletState } from "../state/storage.js";
6
3
  import { createDefaultWalletSecretProvider, createWalletSecretReference, } from "../state/provider.js";
7
- import { appendMiningEvent, getLastMiningEventTimestamp, loadMiningRuntimeStatus, readMiningEvents, saveMiningRuntimeStatus, followMiningEvents } from "./runtime-artifacts.js";
4
+ import { loadWalletState } from "../state/storage.js";
5
+ import { appendMiningEvent, getLastMiningEventTimestamp, loadMiningRuntimeStatus, readMiningEvents, saveMiningRuntimeStatus, followMiningEvents, } from "./runtime-artifacts.js";
8
6
  import { requestMiningGenerationPreemption } from "./coordination.js";
9
- import { ensureMiningHookTemplate, inspectMiningHookState, shouldEnterHookCooldown, validateCustomMiningHook, } from "./hooks.js";
10
7
  import { normalizeMiningPublishState, normalizeMiningStateRecord } from "./state.js";
11
8
  import { loadClientConfig, saveBuiltInMiningProviderConfig } from "./config.js";
12
- import { MINING_WORKER_API_VERSION } from "./constants.js";
13
- const WORKER_HEARTBEAT_STALE_MS = 15_000;
14
- function normalizeHookMode(mode) {
15
- return mode === "custom" ? "custom" : "builtin";
16
- }
17
- function createDefaultHookState() {
18
- return {
19
- mode: "builtin",
20
- validationState: "never",
21
- lastValidationAtUnixMs: null,
22
- lastValidationError: null,
23
- validatedLaunchFingerprint: null,
24
- validatedFullFingerprint: null,
25
- fullTrustWarningAcknowledgedAtUnixMs: null,
26
- consecutiveFailureCount: 0,
27
- cooldownUntilUnixMs: null,
28
- };
29
- }
9
+ import { MINING_WORKER_API_VERSION, MINING_WORKER_HEARTBEAT_STALE_MS, } from "./constants.js";
30
10
  function createMiningEvent(kind, message, options = {}) {
31
11
  return {
32
12
  schemaVersion: 1,
@@ -81,19 +61,10 @@ async function isProcessAlive(pid) {
81
61
  return true;
82
62
  }
83
63
  }
84
- function mapProviderState(provider, hookMode, localState, nowUnixMs) {
64
+ function mapProviderState(provider, localState) {
85
65
  const miningState = localState.state?.miningState === undefined
86
66
  ? null
87
67
  : normalizeMiningStateRecord(localState.state.miningState);
88
- const hookState = localState.state?.hookClientState.mining ?? null;
89
- const hookCooldownUntilUnixMs = hookState?.cooldownUntilUnixMs ?? null;
90
- const hookCooldownActive = hookCooldownUntilUnixMs !== null
91
- && hookCooldownUntilUnixMs > nowUnixMs;
92
- if (hookMode === "custom") {
93
- return hookState?.validationState === "failed" || hookCooldownActive
94
- ? "hook-error"
95
- : "n/a";
96
- }
97
68
  if (miningState?.state === "paused" && miningState.pauseReason?.includes("rate-limit")) {
98
69
  return "rate-limited";
99
70
  }
@@ -106,9 +77,6 @@ function mapProviderState(provider, hookMode, localState, nowUnixMs) {
106
77
  if (provider.status === "ready") {
107
78
  return "ready";
108
79
  }
109
- if (provider.status === "error") {
110
- return "unavailable";
111
- }
112
80
  return "unavailable";
113
81
  }
114
82
  function mapIndexerDaemonState(indexer) {
@@ -185,7 +153,7 @@ async function deriveBackgroundWorkerHealth(options) {
185
153
  return "stale-pid";
186
154
  }
187
155
  if (runtime.backgroundWorkerHeartbeatAtUnixMs === null
188
- || (options.nowUnixMs - runtime.backgroundWorkerHeartbeatAtUnixMs) > WORKER_HEARTBEAT_STALE_MS) {
156
+ || (options.nowUnixMs - runtime.backgroundWorkerHeartbeatAtUnixMs) > MINING_WORKER_HEARTBEAT_STALE_MS) {
189
157
  return "stale-heartbeat";
190
158
  }
191
159
  return "healthy";
@@ -199,7 +167,7 @@ async function buildMiningRuntimeSnapshot(options) {
199
167
  localState: options.localState,
200
168
  nowUnixMs: options.nowUnixMs,
201
169
  });
202
- const providerState = mapProviderState(options.provider, options.hookMode, options.localState, options.nowUnixMs);
170
+ const providerState = mapProviderState(options.provider, options.localState);
203
171
  const indexerDaemonState = mapIndexerDaemonState(options.indexer);
204
172
  const corePublishState = mapCorePublishState(options.nodeHealth, options.nodeStatus);
205
173
  const existing = options.existingRuntime;
@@ -243,7 +211,7 @@ async function buildMiningRuntimeSnapshot(options) {
243
211
  currentCanonicalBlend: state?.currentScore ?? existing?.currentCanonicalBlend ?? null,
244
212
  currentTxid: state?.currentTxid ?? existing?.currentTxid ?? null,
245
213
  currentWtxid: state?.currentWtxid ?? existing?.currentWtxid ?? null,
246
- liveMiningFamilyInMempool: state?.liveMiningFamilyInMempool ?? existing?.liveMiningFamilyInMempool ?? null,
214
+ livePublishInMempool: state?.livePublishInMempool ?? existing?.livePublishInMempool ?? null,
247
215
  currentFeeRateSatVb: state?.currentFeeRateSatVb ?? existing?.currentFeeRateSatVb ?? null,
248
216
  currentAbsoluteFeeSats: state?.currentAbsoluteFeeSats ?? existing?.currentAbsoluteFeeSats ?? null,
249
217
  currentBlockFeeSpentSats: state?.currentBlockFeeSpentSats ?? existing?.currentBlockFeeSpentSats ?? "0",
@@ -258,7 +226,6 @@ async function buildMiningRuntimeSnapshot(options) {
258
226
  lastMempoolSequence: existing?.lastMempoolSequence ?? null,
259
227
  lastCompetitivenessGateAtUnixMs: existing?.lastCompetitivenessGateAtUnixMs ?? null,
260
228
  pauseReason: state?.pauseReason ?? options.existingRuntime?.pauseReason ?? null,
261
- hookMode: options.hookMode,
262
229
  providerConfigured: options.provider.configured,
263
230
  providerKind: options.provider.provider,
264
231
  bitcoindHealth: options.bitcoind.health,
@@ -267,51 +234,35 @@ async function buildMiningRuntimeSnapshot(options) {
267
234
  nodeHealth: options.nodeHealth,
268
235
  indexerHealth: options.indexer.health,
269
236
  tipsAligned: options.tipsAligned,
270
- lastValidationState: options.hookValidationState,
271
- lastOperatorValidationState: options.hookOperatorValidationState,
272
- lastValidationAtUnixMs: options.hookValidationAtUnixMs,
273
237
  lastEventAtUnixMs: options.lastEventAtUnixMs,
274
238
  lastError: existing?.lastError ?? options.provider.message ?? options.indexer.message ?? null,
275
- note: options.hookMode === "custom" && options.hookCooldownActive
276
- ? "Custom mining hook launch is paused during the post-failure cooldown window."
277
- : options.hookMode === "custom" && options.hookOperatorValidationState !== "current"
278
- ? "Custom mining hook is selected, but it must be revalidated before it can launch."
279
- : state?.pauseReason === "zero-reward"
280
- ? "Mining is disabled because the target block reward is zero."
281
- : existing?.currentPhase === "resuming"
282
- ? "Mining discarded stale in-flight work after a large local runtime gap and is rechecking health."
283
- : existing?.currentPhase === "waiting-provider"
284
- ? "Mining is waiting for the sentence provider to recover."
285
- : existing?.currentPhase === "waiting-indexer"
286
- ? "Mining is waiting for Bitcoin Core and the indexer to align."
287
- : existing?.currentPhase === "waiting-bitcoin-network"
288
- ? "Mining is waiting for the local Bitcoin node to become publishable."
289
- : state?.state === "repair-required"
290
- ? "Mining is blocked until the current mining family is reconciled or `cogcoin repair` completes."
291
- : state?.state === "paused-stale" && state.liveMiningFamilyInMempool
292
- ? "A previously broadcast mining family is still in mempool for an older tip context. Wait for confirmation or rerun mining to replace it."
293
- : state?.state === "paused" && state.liveMiningFamilyInMempool
294
- ? "Mining is paused, but the last mining transaction may still confirm from mempool without further fee bumps."
295
- : state?.state === "paused"
296
- ? "Mining is paused by another wallet command or local policy."
297
- : options.provider.status === "missing"
298
- ? "Run `cogcoin mine setup` to configure the built-in mining provider."
299
- : options.indexer.health === "reorging"
300
- ? "Mining remains stopped while the indexer replays a reorg and refreshes the coherent snapshot."
301
- : options.indexer.health !== "synced" || options.nodeHealth !== "synced"
302
- ? "Mining remains stopped until Bitcoin Core and the indexer are both healthy and aligned."
303
- : null,
239
+ note: state?.pauseReason === "zero-reward"
240
+ ? "Mining is disabled because the target block reward is zero."
241
+ : existing?.currentPhase === "resuming"
242
+ ? "Mining discarded stale in-flight work after a large local runtime gap and is rechecking health."
243
+ : existing?.currentPhase === "waiting-provider"
244
+ ? "Mining is waiting for the sentence provider to recover."
245
+ : existing?.currentPhase === "waiting-indexer"
246
+ ? "Mining is waiting for Bitcoin Core and the indexer to align."
247
+ : existing?.currentPhase === "waiting-bitcoin-network"
248
+ ? "Mining is waiting for the local Bitcoin node to become publishable."
249
+ : state?.state === "repair-required"
250
+ ? "Mining is blocked until the current mining publish is reconciled or `cogcoin repair` completes."
251
+ : state?.state === "paused-stale" && state.livePublishInMempool
252
+ ? "A previously broadcast mining transaction is still in mempool for an older tip context. Wait for confirmation or rerun mining to replace it."
253
+ : state?.state === "paused" && state.livePublishInMempool
254
+ ? "Mining is paused, but the last mining transaction may still confirm from mempool without further fee bumps."
255
+ : state?.state === "paused"
256
+ ? "Mining is paused by another wallet command or local policy."
257
+ : options.provider.status === "missing"
258
+ ? "Run `cogcoin mine setup` to configure the built-in mining provider."
259
+ : options.indexer.health === "reorging"
260
+ ? "Mining remains stopped while the indexer replays a reorg and refreshes the coherent snapshot."
261
+ : options.indexer.health !== "synced" || options.nodeHealth !== "synced"
262
+ ? "Mining remains stopped until Bitcoin Core and the indexer are both healthy and aligned."
263
+ : null,
304
264
  };
305
265
  }
306
- async function persistWalletMiningHookState(options) {
307
- await saveWalletState({
308
- primaryPath: options.paths.walletStatePath,
309
- backupPath: options.paths.walletStateBackupPath,
310
- }, options.state, {
311
- provider: options.provider,
312
- secretReference: createWalletSecretReference(options.state.walletRootId),
313
- });
314
- }
315
266
  async function loadMiningProviderConfig(options) {
316
267
  try {
317
268
  const config = await loadClientConfig({
@@ -338,14 +289,6 @@ export async function inspectMiningControlPlane(options) {
338
289
  paths,
339
290
  provider,
340
291
  });
341
- const hookState = options.localState.state?.hookClientState.mining ?? null;
342
- const hook = await inspectMiningHookState({
343
- hookRootPath: paths.hooksMiningDir,
344
- entrypointPath: paths.hooksMiningEntrypointPath,
345
- packagePath: paths.hooksMiningPackageJsonPath,
346
- localState: hookState,
347
- verify: options.verify ?? false,
348
- });
349
292
  const providerInspection = buildProviderInspection(providerConfig);
350
293
  const existingRuntime = await loadMiningRuntimeStatus(paths.miningStatusPath).catch(() => null);
351
294
  const lastEventAtUnixMs = await getLastMiningEventTimestamp(paths.miningEventsPath).catch(() => null);
@@ -357,11 +300,6 @@ export async function inspectMiningControlPlane(options) {
357
300
  localState: options.localState,
358
301
  bitcoind: options.bitcoind,
359
302
  nodeStatus: options.nodeStatus,
360
- hookMode: normalizeHookMode(hook.mode === "unavailable" ? null : hook.mode),
361
- hookValidationState: hook.validationState === "unavailable" ? null : hook.validationState,
362
- hookOperatorValidationState: hook.operatorValidationState,
363
- hookValidationAtUnixMs: hook.validatedAtUnixMs,
364
- hookCooldownActive: hook.cooldownActive,
365
303
  provider: providerInspection,
366
304
  nodeHealth: options.nodeHealth,
367
305
  indexer: options.indexer,
@@ -371,7 +309,6 @@ export async function inspectMiningControlPlane(options) {
371
309
  });
372
310
  return {
373
311
  runtime,
374
- hook,
375
312
  provider: providerInspection,
376
313
  lastEventAtUnixMs,
377
314
  };
@@ -382,246 +319,13 @@ export async function refreshMiningRuntimeStatus(options) {
382
319
  await saveMiningRuntimeStatus(paths.miningStatusPath, view.runtime);
383
320
  return view;
384
321
  }
385
- export async function enableMiningHooks(options) {
386
- if (!options.prompter.isInteractive) {
387
- throw new Error("mining_hooks_enable_requires_tty");
388
- }
389
- const provider = options.provider ?? createDefaultWalletSecretProvider();
390
- const nowUnixMs = options.nowUnixMs ?? Date.now();
391
- const paths = options.paths ?? resolveWalletRuntimePathsForTesting();
392
- const controlLock = await acquireFileLock(paths.miningControlLockPath, {
393
- purpose: "hooks-enable-mining",
394
- });
395
- try {
396
- const preemption = await requestMiningGenerationPreemption({
397
- paths,
398
- reason: "hooks-enable-mining",
399
- });
400
- const unlocked = await loadOrAutoUnlockWalletState({
401
- provider,
402
- nowUnixMs,
403
- paths,
404
- });
405
- try {
406
- if (unlocked === null) {
407
- throw new Error("wallet_locked");
408
- }
409
- const state = unlocked.state;
410
- state.hookClientState.mining ??= createDefaultHookState();
411
- if (state.hookClientState.mining.fullTrustWarningAcknowledgedAtUnixMs === null) {
412
- options.prompter.writeLine("Enabling a custom mining hook gives local JavaScript code full access to your user account.");
413
- const confirmation = await options.prompter.prompt("Type TRUST CUSTOM MINING HOOKS to continue: ");
414
- if (confirmation.trim() !== "TRUST CUSTOM MINING HOOKS") {
415
- throw new Error("mining_hooks_enable_trust_acknowledgement_required");
416
- }
417
- state.hookClientState.mining.fullTrustWarningAcknowledgedAtUnixMs = nowUnixMs;
418
- }
419
- const createdTemplate = await ensureMiningHookTemplate({
420
- hookRootPath: paths.hooksMiningDir,
421
- entrypointPath: paths.hooksMiningEntrypointPath,
422
- packagePath: paths.hooksMiningPackageJsonPath,
423
- });
424
- if (createdTemplate) {
425
- await persistWalletMiningHookState({ state, provider, paths });
426
- await appendMiningEvent(paths.miningEventsPath, createMiningEvent("custom-hook-template-created", "Created the default mining hook template. Edit it, then rerun `cogcoin hooks enable mining`.", { timestampUnixMs: nowUnixMs }));
427
- await refreshMiningRuntimeStatus({
428
- provider,
429
- localState: {
430
- availability: "ready",
431
- walletRootId: state.walletRootId,
432
- state,
433
- source: unlocked.source,
434
- unlockUntilUnixMs: unlocked.session.unlockUntilUnixMs,
435
- hasPrimaryStateFile: true,
436
- hasBackupStateFile: true,
437
- hasUnlockSessionFile: true,
438
- message: null,
439
- },
440
- bitcoind: {
441
- health: "unavailable",
442
- status: null,
443
- message: "Managed bitcoind status unavailable during hook setup.",
444
- },
445
- nodeStatus: null,
446
- nodeHealth: "unavailable",
447
- indexer: {
448
- health: "unavailable",
449
- status: null,
450
- message: "Indexer status unavailable during hook setup.",
451
- snapshotTip: null,
452
- source: "none",
453
- daemonInstanceId: null,
454
- snapshotSeq: null,
455
- openedAtUnixMs: null,
456
- },
457
- nowUnixMs,
458
- paths,
459
- });
460
- throw new Error(`mining_hooks_enable_template_created:${paths.hooksMiningDir}`);
461
- }
462
- try {
463
- const validation = await validateCustomMiningHook({
464
- hookRootPath: paths.hooksMiningDir,
465
- entrypointPath: paths.hooksMiningEntrypointPath,
466
- packagePath: paths.hooksMiningPackageJsonPath,
467
- });
468
- state.hookClientState.mining = {
469
- ...state.hookClientState.mining,
470
- mode: "custom",
471
- validationState: "current",
472
- lastValidationAtUnixMs: nowUnixMs,
473
- lastValidationError: null,
474
- validatedLaunchFingerprint: validation.launchFingerprint,
475
- validatedFullFingerprint: validation.fullFingerprint,
476
- consecutiveFailureCount: 0,
477
- cooldownUntilUnixMs: null,
478
- };
479
- await persistWalletMiningHookState({ state, provider, paths });
480
- await appendMiningEvent(paths.miningEventsPath, createMiningEvent("custom-hook-enabled", "Custom mining hook enabled after validation.", { timestampUnixMs: nowUnixMs }));
481
- }
482
- catch (error) {
483
- const validationError = error instanceof Error ? error.message : String(error);
484
- const consecutiveFailureCount = (state.hookClientState.mining.consecutiveFailureCount ?? 0) + 1;
485
- state.hookClientState.mining = {
486
- ...state.hookClientState.mining,
487
- validationState: "failed",
488
- lastValidationAtUnixMs: nowUnixMs,
489
- lastValidationError: validationError,
490
- validatedLaunchFingerprint: null,
491
- validatedFullFingerprint: null,
492
- consecutiveFailureCount,
493
- cooldownUntilUnixMs: shouldEnterHookCooldown({
494
- consecutiveFailureCount,
495
- nowUnixMs,
496
- }),
497
- };
498
- await persistWalletMiningHookState({ state, provider, paths });
499
- await appendMiningEvent(paths.miningEventsPath, createMiningEvent("custom-hook-validation-failed", state.hookClientState.mining.lastValidationError ?? "Custom mining hook validation failed.", {
500
- level: "error",
501
- timestampUnixMs: nowUnixMs,
502
- }));
503
- throw new Error(`mining_hooks_enable_validation_failed:${validationError}`);
504
- }
505
- return refreshMiningRuntimeStatus({
506
- provider,
507
- localState: {
508
- availability: "ready",
509
- walletRootId: state.walletRootId,
510
- state,
511
- source: unlocked.source,
512
- unlockUntilUnixMs: unlocked.session.unlockUntilUnixMs,
513
- hasPrimaryStateFile: true,
514
- hasBackupStateFile: true,
515
- hasUnlockSessionFile: true,
516
- message: null,
517
- },
518
- bitcoind: {
519
- health: "unavailable",
520
- status: null,
521
- message: "Managed bitcoind status unavailable during hook setup.",
522
- },
523
- nodeStatus: null,
524
- nodeHealth: "unavailable",
525
- indexer: {
526
- health: "unavailable",
527
- status: null,
528
- message: "Indexer status unavailable during hook setup.",
529
- snapshotTip: null,
530
- source: "none",
531
- daemonInstanceId: null,
532
- snapshotSeq: null,
533
- openedAtUnixMs: null,
534
- },
535
- nowUnixMs,
536
- paths,
537
- });
538
- }
539
- finally {
540
- await preemption.release();
541
- }
542
- }
543
- finally {
544
- await controlLock.release();
545
- }
546
- }
547
- export async function disableMiningHooks(options) {
548
- const provider = options.provider ?? createDefaultWalletSecretProvider();
549
- const nowUnixMs = options.nowUnixMs ?? Date.now();
550
- const paths = options.paths ?? resolveWalletRuntimePathsForTesting();
551
- const controlLock = await acquireFileLock(paths.miningControlLockPath, {
552
- purpose: "hooks-disable-mining",
553
- });
554
- try {
555
- const preemption = await requestMiningGenerationPreemption({
556
- paths,
557
- reason: "hooks-disable-mining",
558
- });
559
- const unlocked = await loadOrAutoUnlockWalletState({
560
- provider,
561
- nowUnixMs,
562
- paths,
563
- });
564
- try {
565
- if (unlocked === null) {
566
- throw new Error("wallet_locked");
567
- }
568
- const state = unlocked.state;
569
- state.hookClientState.mining = {
570
- ...createDefaultHookState(),
571
- mode: "builtin",
572
- fullTrustWarningAcknowledgedAtUnixMs: state.hookClientState.mining?.fullTrustWarningAcknowledgedAtUnixMs ?? null,
573
- };
574
- await persistWalletMiningHookState({ state, provider, paths });
575
- await appendMiningEvent(paths.miningEventsPath, createMiningEvent("custom-hook-disabled", "Custom mining hook disabled. Built-in mining mode is active again.", { timestampUnixMs: nowUnixMs }));
576
- return refreshMiningRuntimeStatus({
577
- provider,
578
- localState: {
579
- availability: "ready",
580
- walletRootId: state.walletRootId,
581
- state,
582
- source: unlocked.source,
583
- unlockUntilUnixMs: unlocked.session.unlockUntilUnixMs,
584
- hasPrimaryStateFile: true,
585
- hasBackupStateFile: true,
586
- hasUnlockSessionFile: true,
587
- message: null,
588
- },
589
- bitcoind: {
590
- health: "unavailable",
591
- status: null,
592
- message: "Managed bitcoind status unavailable during hook setup.",
593
- },
594
- nodeStatus: null,
595
- nodeHealth: "unavailable",
596
- indexer: {
597
- health: "unavailable",
598
- status: null,
599
- message: "Indexer status unavailable during hook setup.",
600
- snapshotTip: null,
601
- source: "none",
602
- daemonInstanceId: null,
603
- snapshotSeq: null,
604
- openedAtUnixMs: null,
605
- },
606
- nowUnixMs,
607
- paths,
608
- });
609
- }
610
- finally {
611
- await preemption.release();
612
- }
613
- }
614
- finally {
615
- await controlLock.release();
616
- }
617
- }
618
322
  function normalizeProviderChoice(raw) {
619
323
  const value = raw.trim().toLowerCase();
620
324
  return value === "openai" || value === "anthropic" ? value : null;
621
325
  }
622
326
  function writeBuiltInMiningProviderDisclosure(prompter) {
623
327
  prompter.writeLine("Built-in mining provider disclosure:");
624
- prompter.writeLine("The built-in mining hook will send the following to the selected provider:");
328
+ prompter.writeLine("The built-in mining provider will send the following to the selected provider:");
625
329
  prompter.writeLine("- eligible anchored root domain names");
626
330
  prompter.writeLine("- the required five words for each root domain");
627
331
  prompter.writeLine("- target block height");
@@ -664,16 +368,13 @@ export async function setupBuiltInMining(options) {
664
368
  paths,
665
369
  reason: "mine-setup",
666
370
  });
667
- const unlocked = await loadOrAutoUnlockWalletState({
668
- provider,
669
- nowUnixMs,
670
- paths,
671
- });
672
371
  try {
673
- if (unlocked === null) {
674
- throw new Error("wallet_locked");
675
- }
676
- const state = unlocked.state;
372
+ const loaded = await loadWalletState({
373
+ primaryPath: paths.walletStatePath,
374
+ backupPath: paths.walletStateBackupPath,
375
+ }, {
376
+ provider,
377
+ });
677
378
  await appendMiningEvent(paths.miningEventsPath, createMiningEvent("mine-setup-started", "Started built-in mining provider setup.", { timestampUnixMs: nowUnixMs }));
678
379
  try {
679
380
  const config = await promptForMiningProviderConfig(options.prompter);
@@ -681,26 +382,21 @@ export async function setupBuiltInMining(options) {
681
382
  await saveBuiltInMiningProviderConfig({
682
383
  path: paths.clientConfigPath,
683
384
  provider,
684
- secretReference: createWalletSecretReference(state.walletRootId),
385
+ secretReference: createWalletSecretReference(loaded.state.walletRootId),
685
386
  config,
686
387
  });
687
- state.hookClientState.mining ??= createDefaultHookState();
688
- if (state.hookClientState.mining.mode === "disabled") {
689
- state.hookClientState.mining.mode = "builtin";
690
- }
691
- await persistWalletMiningHookState({ state, provider, paths });
692
388
  await appendMiningEvent(paths.miningEventsPath, createMiningEvent("mine-setup-completed", `Configured the built-in ${config.provider} mining provider.`, { timestampUnixMs: nowUnixMs }));
693
389
  return refreshMiningRuntimeStatus({
694
390
  provider,
695
391
  localState: {
696
392
  availability: "ready",
697
- walletRootId: state.walletRootId,
698
- state,
699
- source: unlocked.source,
700
- unlockUntilUnixMs: unlocked.session.unlockUntilUnixMs,
393
+ clientPasswordReadiness: "ready",
394
+ unlockRequired: false,
395
+ walletRootId: loaded.state.walletRootId,
396
+ state: loaded.state,
397
+ source: loaded.source,
701
398
  hasPrimaryStateFile: true,
702
399
  hasBackupStateFile: true,
703
- hasUnlockSessionFile: true,
704
400
  message: null,
705
401
  },
706
402
  bitcoind: {
@@ -1,8 +1,7 @@
1
1
  export { isMiningGenerationAbortRequested, markMiningGenerationActive, markMiningGenerationInactive, readMiningGenerationActivity, readMiningPreemptionRequest, requestMiningGenerationPreemption, } from "./coordination.js";
2
- export { disableMiningHooks, enableMiningHooks, followMiningLog, inspectMiningControlPlane, readMiningLog, refreshMiningRuntimeStatus, setupBuiltInMining, } from "./control.js";
3
- export { runBackgroundMiningWorker, runForegroundMining, startBackgroundMining, stopBackgroundMining, type MiningStartResult, } from "./runner.js";
2
+ export { followMiningLog, inspectMiningControlPlane, readMiningLog, refreshMiningRuntimeStatus, setupBuiltInMining, } from "./control.js";
3
+ export { ensureBuiltInMiningSetupIfNeeded, runBackgroundMiningWorker, runForegroundMining, startBackgroundMining, stopBackgroundMining, type MiningStartResult, } from "./runner.js";
4
4
  export { appendMiningEvent, loadMiningRuntimeStatus, readMiningEvents, resolveRotatedMiningEventsPath, saveMiningRuntimeStatus, } from "./runtime-artifacts.js";
5
- export { ensureMiningHookTemplate, inspectMiningHookState, runGenerateSentencesHookRequest, validateCustomMiningHook, } from "./hooks.js";
6
- export type { GenerateSentencesHookCandidateV1, GenerateSentencesHookRequestV1, GenerateSentencesHookResponseV1, MiningHookOperatorValidationState, } from "./hook-protocol.js";
5
+ export type { MiningSentenceCandidateV1, MiningSentenceGenerationRequestV1, MiningSentenceGenerationResponseV1, } from "./sentence-protocol.js";
7
6
  export { loadClientConfig, saveBuiltInMiningProviderConfig, saveClientConfig, } from "./config.js";
8
- export type { ClientConfigV1, MiningControlPlaneView, MiningEventRecord, MiningHookInspection, MiningProviderConfigRecord, MiningProviderInspection, MiningRuntimeStatusV1, MiningServiceHealth, } from "./types.js";
7
+ export type { ClientConfigV1, MiningControlPlaneView, MiningEventRecord, MiningProviderConfigRecord, MiningProviderInspection, MiningRuntimeStatusV1, MiningServiceHealth, } from "./types.js";