@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
@@ -1,6 +1,7 @@
1
+ import { getBalance } from "@cogcoin/indexer/queries";
1
2
  import { findDomainField, findWalletDomain, listDomainFields, listWalletLocks, } from "../wallet/read/index.js";
2
3
  import { getAddressNextSteps, getBootstrapSyncNextStep, getFundingQuickstartGuidance, getIdsNextSteps, getLocksNextSteps, } from "./workflow-hints.js";
3
- import { getMutationRecommendation, getRepairRecommendation } from "./wallet-format.js";
4
+ import { getClientUnlockRecommendation, getMutationRecommendation, getRepairRecommendation, } from "./wallet-format.js";
4
5
  function decimalOrNull(value) {
5
6
  return value === null || value === undefined ? null : value.toString();
6
7
  }
@@ -30,7 +31,13 @@ function createBaseMessages(context) {
30
31
  if (repairRecommendation !== null) {
31
32
  nextSteps.push(repairRecommendation);
32
33
  }
33
- if (repairRecommendation === null) {
34
+ const clientUnlockRecommendation = repairRecommendation === null
35
+ ? getClientUnlockRecommendation(context)
36
+ : null;
37
+ if (clientUnlockRecommendation !== null) {
38
+ nextSteps.push(clientUnlockRecommendation);
39
+ }
40
+ if (repairRecommendation === null && clientUnlockRecommendation === null) {
34
41
  const bootstrapSync = getBootstrapSyncNextStep(context);
35
42
  if (bootstrapSync !== null) {
36
43
  nextSteps.push(bootstrapSync);
@@ -135,14 +142,6 @@ export function buildAvailability(context) {
135
142
  },
136
143
  };
137
144
  if (context.mining !== undefined) {
138
- availability.hooks = {
139
- available: context.mining.hook.mode !== "unavailable",
140
- stale: context.mining.hook.operatorValidationState === "stale",
141
- reason: context.mining.hook.validationError ?? context.mining.hook.trustMessage,
142
- state: context.mining.hook.validationState,
143
- operatorValidationState: context.mining.hook.operatorValidationState,
144
- cooldownActive: context.mining.hook.cooldownActive,
145
- };
146
145
  availability.backgroundWorker = {
147
146
  available: context.mining.runtime.backgroundWorkerPid !== null,
148
147
  stale: context.mining.runtime.backgroundWorkerHealth === "stale-heartbeat"
@@ -154,21 +153,24 @@ export function buildAvailability(context) {
154
153
  }
155
154
  return availability;
156
155
  }
157
- function mapIdentity(identity) {
156
+ function walletCogBalance(context) {
157
+ if (context.snapshot === null || context.model === null) {
158
+ return null;
159
+ }
160
+ return getBalance(context.snapshot.state, new Uint8Array(Buffer.from(context.model.walletScriptPubKeyHex, "hex")));
161
+ }
162
+ function mapWalletAddress(context) {
163
+ const localDomains = context.model === null
164
+ ? []
165
+ : context.model.domains
166
+ .filter((domain) => domain.localRelationship === "local")
167
+ .map((domain) => domain.name)
168
+ .sort((left, right) => left.localeCompare(right));
158
169
  return {
159
- index: identity.index,
160
- scriptPubKeyHex: identity.scriptPubKeyHex,
161
- address: identity.address,
162
- selectors: identity.selectors,
163
- assignedDomainNames: identity.assignedDomainNames,
164
- ownedDomainNames: identity.ownedDomainNames,
165
- anchoredOwnedDomainNames: identity.anchoredOwnedDomainNames,
166
- localStatus: identity.localStatus,
167
- effectiveStatus: identity.effectiveStatus,
168
- canonicalDomainId: identity.canonicalDomainId,
169
- canonicalDomainName: identity.canonicalDomainName,
170
- observedCogBalance: decimalOrNull(identity.observedCogBalance),
171
- readOnly: identity.readOnly,
170
+ address: context.model?.walletAddress ?? null,
171
+ scriptPubKeyHex: context.model?.walletScriptPubKeyHex ?? null,
172
+ localDomains,
173
+ observedCogBalance: decimalOrNull(walletCogBalance(context)),
172
174
  };
173
175
  }
174
176
  function mapDomain(domain) {
@@ -177,11 +179,9 @@ function mapDomain(domain) {
177
179
  domainId: domain.domainId,
178
180
  anchored: domain.anchored,
179
181
  ownerScriptPubKeyHex: domain.ownerScriptPubKeyHex,
180
- ownerLocalIndex: domain.ownerLocalIndex,
181
182
  ownerAddress: domain.ownerAddress,
182
183
  localRelationship: domain.localRelationship,
183
184
  chainStatus: domain.chainStatus,
184
- localAnchorIntent: domain.localAnchorIntent,
185
185
  foundingMessageText: domain.foundingMessageText,
186
186
  endpointText: domain.endpointText,
187
187
  delegateScriptPubKeyHex: domain.delegateScriptPubKeyHex,
@@ -270,7 +270,7 @@ function buildMiningStatusData(mining) {
270
270
  domainId: mining.runtime.currentDomainId,
271
271
  name: mining.runtime.currentDomainName,
272
272
  },
273
- liveMiningFamilyInMempool: mining.runtime.liveMiningFamilyInMempool,
273
+ livePublishInMempool: mining.runtime.livePublishInMempool,
274
274
  publishDecision: mining.runtime.currentPublishDecision,
275
275
  fees: {
276
276
  currentFeeRateSatVb: mining.runtime.currentFeeRateSatVb,
@@ -288,10 +288,6 @@ function buildMiningStatusData(mining) {
288
288
  phase: mining.runtime.currentPhase,
289
289
  lastSuspendDetectedAtUnixMs: mining.runtime.lastSuspendDetectedAtUnixMs,
290
290
  pauseReason: mining.runtime.pauseReason,
291
- hookMode: mining.runtime.hookMode,
292
- hookValidationState: mining.runtime.lastValidationState,
293
- hookOperatorValidationState: mining.runtime.lastOperatorValidationState,
294
- hookCooldownActive: mining.hook.cooldownActive,
295
291
  providerState: mining.runtime.providerState,
296
292
  tipsAligned: mining.runtime.tipsAligned,
297
293
  sameDomainCompetitorSuppressed: mining.runtime.sameDomainCompetitorSuppressed,
@@ -310,7 +306,6 @@ export function buildStatusJson(context) {
310
306
  wallet: {
311
307
  availability: context.localState.availability,
312
308
  walletRootId: context.model?.walletRootId ?? context.localState.walletRootId ?? context.nodeStatus?.walletRootId ?? null,
313
- unlockUntilUnixMs: context.localState.unlockUntilUnixMs,
314
309
  managedCoreReplicaStatus: context.nodeStatus?.walletReplica?.proofStatus ?? null,
315
310
  },
316
311
  btc: {
@@ -335,56 +330,45 @@ export function buildStatusJson(context) {
335
330
  },
336
331
  domains: {
337
332
  relatedCount: context.model?.domains.length ?? null,
338
- readOnlyIdentityCount: context.model?.readOnlyIdentityCount ?? null,
333
+ readOnlyIdentityCount: 0,
339
334
  pendingMutationCount: (context.localState.state?.pendingMutations ?? []).filter((mutation) => mutation.status !== "confirmed" && mutation.status !== "canceled").length ?? null,
340
- pendingFamilyCount: context.localState.state?.proactiveFamilies.filter((family) => family.status !== "confirmed" && family.status !== "canceled").length ?? null,
335
+ pendingFamilyCount: 0,
341
336
  },
342
337
  mining: context.mining === undefined ? null : buildMiningStatusData(context.mining),
343
- hooks: context.mining === undefined
344
- ? null
345
- : {
346
- mode: context.mining.hook.mode,
347
- validationState: context.mining.hook.validationState,
348
- operatorValidationState: context.mining.hook.operatorValidationState,
349
- trustStatus: context.mining.hook.trustStatus,
350
- providerConfigured: context.mining.provider.configured,
351
- cooldownActive: context.mining.hook.cooldownActive,
352
- },
353
338
  availability: buildAvailability(context),
354
339
  },
355
340
  };
356
341
  }
357
342
  export function buildAddressJson(context) {
358
343
  const messages = createBaseMessages(context);
359
- const fundingIdentity = context.model?.fundingIdentity ?? null;
360
344
  return {
361
345
  ...messages,
362
346
  explanations: dedupeStrings([
363
347
  ...messages.explanations,
364
- ...(fundingIdentity?.address == null ? [] : [getFundingQuickstartGuidance()]),
348
+ ...(context.model?.walletAddress == null ? [] : [getFundingQuickstartGuidance()]),
365
349
  ]),
366
350
  nextSteps: dedupeStrings([
367
351
  ...messages.nextSteps,
368
- ...getAddressNextSteps(context, fundingIdentity?.address),
352
+ ...getAddressNextSteps(context, context.model?.walletAddress ?? null),
369
353
  ]),
370
354
  data: {
371
- address: fundingIdentity?.address ?? null,
372
- scriptPubKeyHex: fundingIdentity?.scriptPubKeyHex ?? null,
355
+ address: context.model?.walletAddress ?? null,
356
+ scriptPubKeyHex: context.model?.walletScriptPubKeyHex ?? null,
373
357
  network: context.localState.state?.network ?? context.nodeStatus?.chain ?? null,
374
358
  availability: buildAvailability(context),
375
359
  },
376
360
  };
377
361
  }
378
- export function buildIdsJson(context, page, identities) {
362
+ export function buildIdsJson(context, page) {
379
363
  const messages = createBaseMessages(context);
380
364
  return {
381
365
  ...messages,
382
366
  nextSteps: dedupeStrings([
383
367
  ...messages.nextSteps,
384
- ...getIdsNextSteps(context.model === null ? null : identities),
368
+ ...getIdsNextSteps(context.model?.walletAddress ?? null),
385
369
  ]),
386
370
  data: {
387
- identities: context.model === null ? null : identities.map(mapIdentity),
371
+ addresses: context.model === null ? null : [mapWalletAddress(context)],
388
372
  page,
389
373
  availability: buildAvailability(context),
390
374
  },
@@ -392,73 +376,13 @@ export function buildIdsJson(context, page, identities) {
392
376
  }
393
377
  export function buildWalletStatusJson(context) {
394
378
  const messages = createBaseMessages(context);
395
- const fundingIdentity = context.model?.fundingIdentity ?? null;
396
- const lockState = context.localState.availability === "ready" && context.localState.unlockUntilUnixMs !== null
397
- ? "unlocked"
398
- : context.localState.availability;
399
379
  return {
400
380
  ...messages,
401
381
  data: {
402
- lockState,
403
- unlockUntilUnixMs: context.localState.unlockUntilUnixMs,
404
- fundingAddress: fundingIdentity?.address ?? null,
405
- fundingScriptPubKeyHex: fundingIdentity?.scriptPubKeyHex ?? null,
406
- availability: buildAvailability(context),
407
- },
408
- };
409
- }
410
- export function buildHooksStatusJson(mining) {
411
- const warnings = [];
412
- const explanations = [];
413
- const nextSteps = [];
414
- if (mining.hook.operatorValidationState === "failed" || mining.hook.operatorValidationState === "stale") {
415
- warnings.push(`Mining hook validation is ${mining.hook.operatorValidationState}.`);
416
- }
417
- if (mining.hook.cooldownActive) {
418
- warnings.push("Mining hook launch is paused during the cooldown window.");
419
- }
420
- if (mining.hook.validationError !== null) {
421
- explanations.push(mining.hook.validationError);
422
- }
423
- if (mining.hook.trustMessage !== null) {
424
- explanations.push(mining.hook.trustMessage);
425
- }
426
- const launchFingerprintState = mining.hook.currentLaunchFingerprint === null
427
- ? "unavailable"
428
- : mining.hook.validatedLaunchFingerprint === null
429
- ? "not-validated"
430
- : mining.hook.currentLaunchFingerprint === mining.hook.validatedLaunchFingerprint
431
- ? "matched"
432
- : "stale";
433
- const fullFingerprintState = mining.hook.currentFullFingerprint === null
434
- ? (mining.hook.verifyUsed ? "unavailable" : "not-verified")
435
- : mining.hook.validatedFullFingerprint === null
436
- ? "not-validated"
437
- : mining.hook.currentFullFingerprint === mining.hook.validatedFullFingerprint
438
- ? "matched"
439
- : "stale";
440
- return {
441
- warnings: dedupeStrings(warnings),
442
- explanations: dedupeStrings(explanations),
443
- nextSteps: dedupeStrings(nextSteps),
444
- data: {
445
- mode: mining.hook.mode,
446
- validationState: mining.hook.validationState,
447
- operatorValidationState: mining.hook.operatorValidationState,
448
- launchFingerprintState,
449
- fullFingerprintState,
450
- lastValidationAtUnixMs: mining.hook.validatedAtUnixMs,
451
- lastValidationError: mining.hook.validationError,
452
- trustChecks: {
453
- trustStatus: mining.hook.trustStatus,
454
- trustMessage: mining.hook.trustMessage,
455
- entrypointExists: mining.hook.entrypointExists,
456
- packageStatus: mining.hook.packageStatus,
457
- packageMessage: mining.hook.packageMessage,
458
- cooldownUntilUnixMs: mining.hook.cooldownUntilUnixMs,
459
- cooldownActive: mining.hook.cooldownActive,
460
- consecutiveFailureCount: mining.hook.consecutiveFailureCount,
461
- },
382
+ availability: context.localState.availability,
383
+ walletAddress: context.model?.walletAddress ?? null,
384
+ walletScriptPubKeyHex: context.model?.walletScriptPubKeyHex ?? null,
385
+ services: buildAvailability(context),
462
386
  },
463
387
  };
464
388
  }
@@ -476,7 +400,7 @@ export function buildMineStatusJson(mining) {
476
400
  nextSteps.push("Wait for mining to finish rechecking health after the local runtime resumed.");
477
401
  }
478
402
  else if (mining.runtime.miningState === "paused-stale" || mining.runtime.miningState === "paused") {
479
- nextSteps.push("Wait for the live mempool family to settle, or rerun mining when you want replacements to resume.");
403
+ nextSteps.push("Wait for the live mining publish to settle, or rerun mining when you want replacements to resume.");
480
404
  }
481
405
  if (mining.runtime.note !== null) {
482
406
  explanations.push(mining.runtime.note);
@@ -491,14 +415,6 @@ export function buildMineStatusJson(mining) {
491
415
  data: {
492
416
  ...buildMiningStatusData(mining),
493
417
  availability: {
494
- hooks: {
495
- available: mining.hook.mode !== "unavailable",
496
- stale: mining.hook.operatorValidationState === "stale",
497
- reason: mining.hook.validationError,
498
- state: mining.hook.validationState,
499
- operatorValidationState: mining.hook.operatorValidationState,
500
- cooldownActive: mining.hook.cooldownActive,
501
- },
502
418
  bitcoind: {
503
419
  available: mining.runtime.bitcoindHealth === "ready" || mining.runtime.bitcoindHealth === "starting",
504
420
  stale: mining.runtime.bitcoindHealth === "starting",
@@ -558,15 +474,14 @@ export function buildMineLogJson(events, page, rotation) {
558
474
  }
559
475
  export function buildBalanceJson(context) {
560
476
  const messages = createBaseMessages(context);
561
- const total = context.model === null || context.snapshot === null
562
- ? null
563
- : context.model.identities.reduce((sum, identity) => identity.readOnly || identity.observedCogBalance === null ? sum : sum + identity.observedCogBalance, 0n);
477
+ const total = walletCogBalance(context);
564
478
  return {
565
479
  ...messages,
566
480
  data: {
567
481
  assetLabel: "COG",
568
482
  totalCogtoshi: decimalOrNull(total),
569
- identities: context.model?.identities.map(mapIdentity) ?? null,
483
+ walletAddress: context.model?.walletAddress ?? null,
484
+ walletScriptPubKeyHex: context.model?.walletScriptPubKeyHex ?? null,
570
485
  pending: (context.localState.state?.pendingMutations ?? [])
571
486
  .filter((mutation) => (mutation.kind === "send" || mutation.kind === "lock" || mutation.kind === "claim")
572
487
  && mutation.status !== "confirmed"
@@ -619,17 +534,6 @@ export function buildShowJson(context, domainName) {
619
534
  : {
620
535
  ...mapDomain(found.domain),
621
536
  pendingMutations: listPendingMutationsForDomain(context, domainName).map(mapPendingMutation),
622
- pendingFamilies: (context.localState.state?.proactiveFamilies ?? [])
623
- .filter((family) => family.domainName === domainName
624
- && family.status !== "confirmed"
625
- && family.status !== "canceled")
626
- .map((family) => ({
627
- type: family.type,
628
- status: family.status,
629
- step: family.currentStep ?? null,
630
- reservedDedicatedIndex: family.reservedDedicatedIndex ?? null,
631
- fieldName: family.fieldName ?? null,
632
- })),
633
537
  },
634
538
  availability: buildAvailability(context),
635
539
  },
@@ -3,6 +3,7 @@ import { writeLine } from "./io.js";
3
3
  import { classifyCliError, createCommandJsonErrorEnvelope, createErrorEnvelope, formatCliTextError, inferOutputMode, isStructuredOutputMode, writeJsonValue, } from "./output.js";
4
4
  import { HELP_TEXT, parseCliArgs } from "./parse.js";
5
5
  import { runFollowCommand } from "./commands/follow.js";
6
+ import { runClientAdminCommand } from "./commands/client-admin.js";
6
7
  import { runMiningAdminCommand } from "./commands/mining-admin.js";
7
8
  import { runMiningReadCommand } from "./commands/mining-read.js";
8
9
  import { runMiningRuntimeCommand } from "./commands/mining-runtime.js";
@@ -69,6 +70,11 @@ export async function runCli(argv, contextOverrides = {}) {
69
70
  if (parsed.command === "status") {
70
71
  return runStatusCommand(parsed, context);
71
72
  }
73
+ if (parsed.command === "client-lock"
74
+ || parsed.command === "client-unlock"
75
+ || parsed.command === "client-change-password") {
76
+ return runClientAdminCommand(parsed, context);
77
+ }
72
78
  if (parsed.command === "bitcoin-start"
73
79
  || parsed.command === "bitcoin-stop"
74
80
  || parsed.command === "bitcoin-status"
@@ -82,30 +88,21 @@ export async function runCli(argv, contextOverrides = {}) {
82
88
  || parsed.command === "mine-stop") {
83
89
  return runMiningRuntimeCommand(parsed, context);
84
90
  }
85
- if (parsed.command === "hooks-mining-enable"
86
- || parsed.command === "hooks-mining-disable"
87
- || parsed.command === "mine-setup") {
91
+ if (parsed.command === "mine-setup") {
88
92
  return runMiningAdminCommand(parsed, context);
89
93
  }
90
94
  if (parsed.command === "init"
91
95
  || parsed.command === "restore"
92
96
  || parsed.command === "reset"
93
97
  || parsed.command === "repair"
94
- || parsed.command === "unlock"
95
- || parsed.command === "wallet-export"
96
- || parsed.command === "wallet-import"
97
98
  || parsed.command === "wallet-init"
98
99
  || parsed.command === "wallet-delete"
99
100
  || parsed.command === "wallet-restore"
100
- || parsed.command === "wallet-show-mnemonic"
101
- || parsed.command === "wallet-unlock"
102
- || parsed.command === "wallet-lock") {
101
+ || parsed.command === "wallet-show-mnemonic") {
103
102
  return runWalletAdminCommand(parsed, context);
104
103
  }
105
104
  if (parsed.command === "anchor"
106
- || parsed.command === "anchor-clear"
107
105
  || parsed.command === "domain-anchor"
108
- || parsed.command === "domain-anchor-clear"
109
106
  || parsed.command === "register"
110
107
  || parsed.command === "domain-register"
111
108
  || parsed.command === "transfer"
@@ -126,6 +123,7 @@ export async function runCli(argv, contextOverrides = {}) {
126
123
  || parsed.command === "field-create"
127
124
  || parsed.command === "field-set"
128
125
  || parsed.command === "field-clear"
126
+ || parsed.command === "bitcoin-transfer"
129
127
  || parsed.command === "send"
130
128
  || parsed.command === "claim"
131
129
  || parsed.command === "reclaim"
@@ -137,8 +135,7 @@ export async function runCli(argv, contextOverrides = {}) {
137
135
  || parsed.command === "rep-revoke") {
138
136
  return runWalletMutationCommand(parsed, context);
139
137
  }
140
- if (parsed.command === "hooks-mining-status"
141
- || parsed.command === "mine-status"
138
+ if (parsed.command === "mine-status"
142
139
  || parsed.command === "mine-log") {
143
140
  return runMiningReadCommand(parsed, context);
144
141
  }
@@ -0,0 +1,6 @@
1
+ import type { ManagedBitcoindProgressEvent } from "../bitcoind/types.js";
2
+ import type { ParsedCliArgs } from "./types.js";
3
+ export declare function createSyncProgressReporter(options: {
4
+ progressOutput: ParsedCliArgs["progressOutput"];
5
+ write: (line: string) => void;
6
+ }): (event: ManagedBitcoindProgressEvent) => void;
@@ -0,0 +1,91 @@
1
+ import { formatBytes, formatDuration } from "../bitcoind/progress/formatting.js";
2
+ const SYNC_PROGRESS_LOG_INTERVAL_MS = 5_000;
3
+ export function createSyncProgressReporter(options) {
4
+ let lastPhase = null;
5
+ let lastMessage = "";
6
+ let lastDownloadPrintedAt = 0;
7
+ let lastDownloadBytes = null;
8
+ let lastImportPrintedAt = 0;
9
+ let lastImportBlocks = null;
10
+ const infoEnabled = options.progressOutput !== "none";
11
+ function shouldPrintEntryMessage(message, phase) {
12
+ if (message === "Waiting to start managed sync." || message === "Sync complete.") {
13
+ return false;
14
+ }
15
+ if (message.startsWith("Warning:")) {
16
+ return true;
17
+ }
18
+ if (!infoEnabled) {
19
+ return false;
20
+ }
21
+ if (phase === "getblock_archive_download" || phase === "getblock_archive_import") {
22
+ return true;
23
+ }
24
+ return phase === "snapshot_download"
25
+ || phase === "wait_headers_for_snapshot"
26
+ || phase === "load_snapshot"
27
+ || phase === "bitcoin_sync"
28
+ || phase === "cogcoin_sync"
29
+ || message.includes("Getblock manifest")
30
+ || message.startsWith("Fetching Getblock manifest.")
31
+ || message.startsWith("Refreshing Getblock manifest.")
32
+ || message.startsWith("Using Getblock range ");
33
+ }
34
+ function formatDownloadLine(label, event) {
35
+ const current = event.progress.downloadedBytes ?? 0;
36
+ const total = event.progress.totalBytes ?? 0;
37
+ const percent = event.progress.percent ?? (total > 0 ? (current / total) * 100 : 0);
38
+ const speed = event.progress.bytesPerSecond === null ? "--" : `${formatBytes(event.progress.bytesPerSecond)}/s`;
39
+ return `${label}: ${percent.toFixed(2)}% (${formatBytes(current)} / ${formatBytes(total)}, ${speed}, ETA ${formatDuration(event.progress.etaSeconds)})`;
40
+ }
41
+ return (event) => {
42
+ const message = event.progress.message.trim();
43
+ const phaseChanged = event.phase !== lastPhase;
44
+ const messageChanged = message !== lastMessage;
45
+ if ((phaseChanged || messageChanged) && shouldPrintEntryMessage(message, event.phase)) {
46
+ options.write(message);
47
+ }
48
+ if (infoEnabled && event.phase === "getblock_archive_download") {
49
+ const now = Date.now();
50
+ const currentBytes = event.progress.downloadedBytes ?? 0;
51
+ const isComplete = (event.progress.percent ?? 0) >= 100;
52
+ const shouldPrintMilestone = phaseChanged
53
+ || lastDownloadBytes !== currentBytes && (isComplete
54
+ || now - lastDownloadPrintedAt >= SYNC_PROGRESS_LOG_INTERVAL_MS);
55
+ if (shouldPrintMilestone) {
56
+ options.write(formatDownloadLine("Getblock download", event));
57
+ lastDownloadPrintedAt = now;
58
+ lastDownloadBytes = currentBytes;
59
+ }
60
+ }
61
+ else if (infoEnabled && event.phase === "snapshot_download") {
62
+ const now = Date.now();
63
+ const currentBytes = event.progress.downloadedBytes ?? 0;
64
+ const isComplete = (event.progress.percent ?? 0) >= 100;
65
+ const shouldPrintMilestone = phaseChanged
66
+ || lastDownloadBytes !== currentBytes && (isComplete
67
+ || now - lastDownloadPrintedAt >= SYNC_PROGRESS_LOG_INTERVAL_MS);
68
+ if (shouldPrintMilestone) {
69
+ options.write(formatDownloadLine("Snapshot download", event));
70
+ lastDownloadPrintedAt = now;
71
+ lastDownloadBytes = currentBytes;
72
+ }
73
+ }
74
+ else if (infoEnabled && event.phase === "getblock_archive_import") {
75
+ const now = Date.now();
76
+ const currentBlocks = event.progress.blocks ?? 0;
77
+ const targetBlocks = event.progress.targetHeight ?? currentBlocks;
78
+ const isComplete = currentBlocks >= targetBlocks;
79
+ const shouldPrintMilestone = phaseChanged
80
+ || lastImportBlocks !== currentBlocks && (isComplete
81
+ || now - lastImportPrintedAt >= SYNC_PROGRESS_LOG_INTERVAL_MS);
82
+ if (shouldPrintMilestone) {
83
+ options.write(`Getblock import: Bitcoin ${currentBlocks.toLocaleString()} / ${targetBlocks.toLocaleString()}`);
84
+ lastImportPrintedAt = now;
85
+ lastImportBlocks = currentBlocks;
86
+ }
87
+ }
88
+ lastPhase = event.phase;
89
+ lastMessage = message;
90
+ };
91
+ }
@@ -6,17 +6,15 @@ import { attachOrStartManagedBitcoindService, probeManagedBitcoindService, stopM
6
6
  import { openSqliteStore } from "../sqlite/index.js";
7
7
  import type { ClientStoreAdapter } from "../types.js";
8
8
  import type { WalletRuntimePaths } from "../wallet/runtime.js";
9
- import type { exportWallet, WalletPrompter, importWallet, initializeWallet, deleteImportedWalletSeed, lockWallet, previewResetWallet, repairWallet, resetWallet, restoreWalletFromMnemonic, showWalletMnemonic, unlockWallet } from "../wallet/lifecycle.js";
9
+ import type { WalletPrompter, initializeWallet, deleteImportedWalletSeed, previewResetWallet, repairWallet, resetWallet, restoreWalletFromMnemonic, showWalletMnemonic } from "../wallet/lifecycle.js";
10
10
  import type { openWalletReadContext } from "../wallet/read/index.js";
11
- import { loadWalletExplicitLock } from "../wallet/state/explicit-lock.js";
12
- import { loadUnlockSession } from "../wallet/state/session.js";
13
11
  import { loadRawWalletStateEnvelope, loadWalletState } from "../wallet/state/storage.js";
14
12
  import type { WalletSecretProvider } from "../wallet/state/provider.js";
15
- import type { disableMiningHooks, enableMiningHooks, followMiningLog, inspectMiningControlPlane, readMiningLog, runForegroundMining, setupBuiltInMining, startBackgroundMining, stopBackgroundMining } from "../wallet/mining/index.js";
16
- import type { anchorDomain, clearPendingAnchor, buyDomain, claimCogLock, clearDomainDelegate, clearDomainEndpoint, clearDomainMiner, clearField, createField, giveReputation, lockCogToDomain, registerDomain, reclaimCogLock, revokeReputation, sendCog, setField, setDomainCanonical, setDomainDelegate, setDomainEndpoint, setDomainMiner, sellDomain, transferDomain } from "../wallet/tx/index.js";
13
+ import type { ensureBuiltInMiningSetupIfNeeded, followMiningLog, inspectMiningControlPlane, readMiningLog, runForegroundMining, setupBuiltInMining, startBackgroundMining, stopBackgroundMining } from "../wallet/mining/index.js";
14
+ import type { anchorDomain, transferBitcoin, buyDomain, claimCogLock, clearDomainDelegate, clearDomainEndpoint, clearDomainMiner, clearField, createField, giveReputation, lockCogToDomain, registerDomain, reclaimCogLock, revokeReputation, sendCog, setField, setDomainCanonical, setDomainDelegate, setDomainEndpoint, setDomainMiner, sellDomain, transferDomain } from "../wallet/tx/index.js";
17
15
  export type ProgressOutput = "auto" | "tty" | "none";
18
16
  export type OutputMode = "text" | "json" | "preview-json";
19
- export type CommandName = "init" | "restore" | "reset" | "repair" | "sync" | "status" | "follow" | "bitcoin-start" | "bitcoin-stop" | "bitcoin-status" | "indexer-start" | "indexer-stop" | "indexer-status" | "unlock" | "anchor" | "anchor-clear" | "domain-anchor" | "domain-anchor-clear" | "register" | "domain-register" | "transfer" | "domain-transfer" | "sell" | "domain-sell" | "unsell" | "domain-unsell" | "buy" | "domain-buy" | "domain-endpoint-set" | "domain-endpoint-clear" | "domain-delegate-set" | "domain-delegate-clear" | "domain-miner-set" | "domain-miner-clear" | "domain-canonical" | "field-list" | "field-show" | "field-create" | "field-set" | "field-clear" | "send" | "claim" | "reclaim" | "cog-send" | "cog-claim" | "cog-reclaim" | "cog-lock" | "rep-give" | "rep-revoke" | "cog-balance" | "cog-locks" | "hooks-mining-enable" | "hooks-mining-disable" | "hooks-mining-status" | "mine" | "mine-start" | "mine-stop" | "mine-setup" | "mine-status" | "mine-log" | "wallet-export" | "wallet-import" | "wallet-init" | "wallet-delete" | "wallet-restore" | "wallet-show-mnemonic" | "wallet-lock" | "wallet-unlock" | "wallet-status" | "wallet-address" | "wallet-ids" | "address" | "ids" | "balance" | "locks" | "domain-list" | "domains" | "domain-show" | "show" | "fields" | "field";
17
+ export type CommandName = "init" | "restore" | "reset" | "repair" | "sync" | "status" | "client-lock" | "client-change-password" | "client-unlock" | "follow" | "bitcoin-start" | "bitcoin-stop" | "bitcoin-status" | "bitcoin-transfer" | "indexer-start" | "indexer-stop" | "indexer-status" | "anchor" | "domain-anchor" | "register" | "domain-register" | "transfer" | "domain-transfer" | "sell" | "domain-sell" | "unsell" | "domain-unsell" | "buy" | "domain-buy" | "domain-endpoint-set" | "domain-endpoint-clear" | "domain-delegate-set" | "domain-delegate-clear" | "domain-miner-set" | "domain-miner-clear" | "domain-canonical" | "field-list" | "field-show" | "field-create" | "field-set" | "field-clear" | "send" | "claim" | "reclaim" | "cog-send" | "cog-claim" | "cog-reclaim" | "cog-lock" | "rep-give" | "rep-revoke" | "cog-balance" | "cog-locks" | "mine" | "mine-start" | "mine-stop" | "mine-setup" | "mine-status" | "mine-log" | "wallet-init" | "wallet-delete" | "wallet-restore" | "wallet-show-mnemonic" | "wallet-status" | "wallet-address" | "wallet-ids" | "address" | "ids" | "balance" | "locks" | "domain-list" | "domains" | "domain-show" | "show" | "fields" | "field";
20
18
  export interface WritableLike {
21
19
  isTTY?: boolean;
22
20
  write(chunk: string): void;
@@ -40,6 +38,7 @@ export interface ParsedCliArgs {
40
38
  seedName: string | null;
41
39
  unlockFor: string | null;
42
40
  assumeYes: boolean;
41
+ force: boolean;
43
42
  forceRace: boolean;
44
43
  anchorMessage: string | null;
45
44
  transferTarget: string | null;
@@ -49,12 +48,12 @@ export interface ParsedCliArgs {
49
48
  fieldPermanent: boolean;
50
49
  fieldFormat: string | null;
51
50
  fieldValue: string | null;
52
- fromIdentity: string | null;
53
51
  lockRecipientDomain: string | null;
54
52
  conditionHex: string | null;
55
53
  untilHeight: string | null;
56
54
  preimageHex: string | null;
57
55
  reviewText: string | null;
56
+ satvb: number | null;
58
57
  locksClaimableOnly: boolean;
59
58
  locksReclaimableOnly: boolean;
60
59
  domainsAnchoredOnly: boolean;
@@ -62,7 +61,6 @@ export interface ParsedCliArgs {
62
61
  domainsMineableOnly: boolean;
63
62
  listLimit: number | null;
64
63
  listAll: boolean;
65
- verify: boolean;
66
64
  follow: boolean;
67
65
  }
68
66
  export interface ManagedClientLike {
@@ -73,6 +71,7 @@ export interface ManagedClientLike {
73
71
  bestHeight: number;
74
72
  }>;
75
73
  playSyncCompletionScene?(): Promise<void>;
74
+ detachToBackgroundFollow?(): Promise<void>;
76
75
  startFollowingTip(): Promise<void>;
77
76
  getNodeStatus(): Promise<{
78
77
  indexedTip: {
@@ -118,20 +117,14 @@ export interface CliRunnerContext {
118
117
  openWalletReadContext?: typeof openWalletReadContext;
119
118
  loadWalletState?: typeof loadWalletState;
120
119
  loadRawWalletStateEnvelope?: typeof loadRawWalletStateEnvelope;
121
- loadUnlockSession?: typeof loadUnlockSession;
122
- loadWalletExplicitLock?: typeof loadWalletExplicitLock;
123
120
  initializeWallet?: typeof initializeWallet;
124
121
  restoreWalletFromMnemonic?: typeof restoreWalletFromMnemonic;
125
122
  previewResetWallet?: typeof previewResetWallet;
126
- exportWallet?: typeof exportWallet;
127
- importWallet?: typeof importWallet;
128
123
  deleteImportedWalletSeed?: typeof deleteImportedWalletSeed;
129
124
  showWalletMnemonic?: typeof showWalletMnemonic;
130
- unlockWallet?: typeof unlockWallet;
131
- lockWallet?: typeof lockWallet;
132
125
  registerDomain?: typeof registerDomain;
133
126
  anchorDomain?: typeof anchorDomain;
134
- clearPendingAnchor?: typeof clearPendingAnchor;
127
+ transferBitcoin?: typeof transferBitcoin;
135
128
  transferDomain?: typeof transferDomain;
136
129
  sellDomain?: typeof sellDomain;
137
130
  buyDomain?: typeof buyDomain;
@@ -151,9 +144,8 @@ export interface CliRunnerContext {
151
144
  clearField?: typeof clearField;
152
145
  giveReputation?: typeof giveReputation;
153
146
  revokeReputation?: typeof revokeReputation;
154
- enableMiningHooks?: typeof enableMiningHooks;
155
- disableMiningHooks?: typeof disableMiningHooks;
156
147
  inspectMiningControlPlane?: typeof inspectMiningControlPlane;
148
+ ensureBuiltInMiningSetupIfNeeded?: typeof ensureBuiltInMiningSetupIfNeeded;
157
149
  runForegroundMining?: typeof runForegroundMining;
158
150
  startBackgroundMining?: typeof startBackgroundMining;
159
151
  stopBackgroundMining?: typeof stopBackgroundMining;
package/dist/cli/types.js CHANGED
@@ -3,6 +3,4 @@ import { createRpcClient } from "../bitcoind/node.js";
3
3
  import { attachOrStartIndexerDaemon, probeIndexerDaemon, readObservedIndexerDaemonStatus, stopIndexerDaemonService, } from "../bitcoind/indexer-daemon.js";
4
4
  import { attachOrStartManagedBitcoindService, probeManagedBitcoindService, stopManagedBitcoindService, } from "../bitcoind/service.js";
5
5
  import { openSqliteStore } from "../sqlite/index.js";
6
- import { loadWalletExplicitLock } from "../wallet/state/explicit-lock.js";
7
- import { loadUnlockSession } from "../wallet/state/session.js";
8
6
  import { loadRawWalletStateEnvelope, loadWalletState } from "../wallet/state/storage.js";
@@ -1,5 +1,6 @@
1
1
  import type { WalletDomainView, WalletReadContext } from "../wallet/read/index.js";
2
2
  export declare function getRepairRecommendation(context: WalletReadContext): string | null;
3
+ export declare function getClientUnlockRecommendation(context: WalletReadContext): string | null;
3
4
  export declare function getMutationRecommendation(context: WalletReadContext): string | null;
4
5
  export declare function formatWalletOverviewReport(context: WalletReadContext, version: string): string;
5
6
  export declare function formatDetailedWalletStatusReport(context: WalletReadContext): string;