@cogcoin/client 1.1.6 → 1.1.8

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 (125) hide show
  1. package/README.md +2 -2
  2. package/dist/bitcoind/indexer-daemon.js +29 -79
  3. package/dist/bitcoind/managed-runtime/bitcoind-runtime.d.ts +20 -0
  4. package/dist/bitcoind/managed-runtime/bitcoind-runtime.js +74 -0
  5. package/dist/bitcoind/managed-runtime/bitcoind-status.d.ts +11 -0
  6. package/dist/bitcoind/managed-runtime/bitcoind-status.js +44 -0
  7. package/dist/bitcoind/managed-runtime/indexer-runtime.d.ts +15 -0
  8. package/dist/bitcoind/managed-runtime/indexer-runtime.js +82 -0
  9. package/dist/bitcoind/managed-runtime/types.d.ts +40 -0
  10. package/dist/bitcoind/node.d.ts +2 -2
  11. package/dist/bitcoind/node.js +2 -2
  12. package/dist/bitcoind/rpc.d.ts +2 -1
  13. package/dist/bitcoind/rpc.js +53 -3
  14. package/dist/bitcoind/service.js +47 -127
  15. package/dist/cli/command-registry.d.ts +1 -1
  16. package/dist/cli/command-registry.js +2 -64
  17. package/dist/cli/commands/client-admin.js +3 -18
  18. package/dist/cli/commands/mining-runtime.js +4 -60
  19. package/dist/cli/commands/wallet-admin.js +6 -6
  20. package/dist/cli/context.js +1 -3
  21. package/dist/cli/mining-json.d.ts +1 -22
  22. package/dist/cli/mining-json.js +0 -23
  23. package/dist/cli/output.js +16 -2
  24. package/dist/cli/parse.js +0 -2
  25. package/dist/cli/preview-json.d.ts +1 -22
  26. package/dist/cli/preview-json.js +0 -19
  27. package/dist/cli/types.d.ts +1 -3
  28. package/dist/cli/wallet-format.js +1 -1
  29. package/dist/cli/workflow-hints.d.ts +1 -2
  30. package/dist/cli/workflow-hints.js +5 -8
  31. package/dist/wallet/lifecycle/context.js +0 -1
  32. package/dist/wallet/lifecycle/repair-mining.d.ts +1 -5
  33. package/dist/wallet/lifecycle/repair-mining.js +5 -39
  34. package/dist/wallet/lifecycle/repair.js +0 -3
  35. package/dist/wallet/lifecycle/setup.js +10 -8
  36. package/dist/wallet/lifecycle/types.d.ts +1 -4
  37. package/dist/wallet/managed-core-wallet.d.ts +2 -0
  38. package/dist/wallet/managed-core-wallet.js +27 -1
  39. package/dist/wallet/mining/candidate.d.ts +1 -0
  40. package/dist/wallet/mining/candidate.js +38 -6
  41. package/dist/wallet/mining/competitiveness.d.ts +1 -0
  42. package/dist/wallet/mining/competitiveness.js +6 -0
  43. package/dist/wallet/mining/cycle.d.ts +2 -0
  44. package/dist/wallet/mining/cycle.js +14 -4
  45. package/dist/wallet/mining/engine-state.js +10 -0
  46. package/dist/wallet/mining/engine-types.d.ts +1 -0
  47. package/dist/wallet/mining/index.d.ts +1 -1
  48. package/dist/wallet/mining/index.js +1 -1
  49. package/dist/wallet/mining/publish.d.ts +3 -0
  50. package/dist/wallet/mining/publish.js +78 -6
  51. package/dist/wallet/mining/runner.d.ts +0 -32
  52. package/dist/wallet/mining/runner.js +59 -104
  53. package/dist/wallet/mining/stop.d.ts +7 -0
  54. package/dist/wallet/mining/stop.js +23 -0
  55. package/dist/wallet/mining/supervisor.d.ts +2 -36
  56. package/dist/wallet/mining/supervisor.js +139 -246
  57. package/dist/wallet/mining/visualizer-sync.js +79 -15
  58. package/dist/wallet/read/context.d.ts +1 -5
  59. package/dist/wallet/read/context.js +21 -205
  60. package/dist/wallet/read/managed-services.d.ts +33 -0
  61. package/dist/wallet/read/managed-services.js +222 -0
  62. package/dist/wallet/reset/artifacts.d.ts +16 -0
  63. package/dist/wallet/reset/artifacts.js +141 -0
  64. package/dist/wallet/reset/execution.d.ts +38 -0
  65. package/dist/wallet/reset/execution.js +458 -0
  66. package/dist/wallet/reset/preflight.d.ts +7 -0
  67. package/dist/wallet/reset/preflight.js +116 -0
  68. package/dist/wallet/reset/preview.d.ts +2 -0
  69. package/dist/wallet/reset/preview.js +50 -0
  70. package/dist/wallet/reset/process-cleanup.d.ts +12 -0
  71. package/dist/wallet/reset/process-cleanup.js +179 -0
  72. package/dist/wallet/reset/types.d.ts +189 -0
  73. package/dist/wallet/reset/types.js +1 -0
  74. package/dist/wallet/reset.d.ts +4 -119
  75. package/dist/wallet/reset.js +4 -882
  76. package/dist/wallet/state/client-password/bootstrap.d.ts +2 -0
  77. package/dist/wallet/state/client-password/bootstrap.js +3 -0
  78. package/dist/wallet/state/client-password/context.d.ts +10 -0
  79. package/dist/wallet/state/client-password/context.js +46 -0
  80. package/dist/wallet/state/client-password/crypto.d.ts +34 -0
  81. package/dist/wallet/state/client-password/crypto.js +117 -0
  82. package/dist/wallet/state/client-password/files.d.ts +10 -0
  83. package/dist/wallet/state/client-password/files.js +109 -0
  84. package/dist/wallet/state/client-password/legacy-cleanup.d.ts +11 -0
  85. package/dist/wallet/state/client-password/legacy-cleanup.js +338 -0
  86. package/dist/wallet/state/client-password/messages.d.ts +3 -0
  87. package/dist/wallet/state/client-password/messages.js +9 -0
  88. package/dist/wallet/state/client-password/migration.d.ts +4 -0
  89. package/dist/wallet/state/client-password/migration.js +32 -0
  90. package/dist/wallet/state/client-password/prompts.d.ts +12 -0
  91. package/dist/wallet/state/client-password/prompts.js +79 -0
  92. package/dist/wallet/state/client-password/protected-secrets.d.ts +13 -0
  93. package/dist/wallet/state/client-password/protected-secrets.js +90 -0
  94. package/dist/wallet/state/client-password/readiness.d.ts +4 -0
  95. package/dist/wallet/state/client-password/readiness.js +48 -0
  96. package/dist/wallet/state/client-password/references.d.ts +1 -0
  97. package/dist/wallet/state/client-password/references.js +56 -0
  98. package/dist/wallet/state/client-password/rotation.d.ts +6 -0
  99. package/dist/wallet/state/client-password/rotation.js +98 -0
  100. package/dist/wallet/state/client-password/session-policy.d.ts +6 -0
  101. package/dist/wallet/state/client-password/session-policy.js +28 -0
  102. package/dist/wallet/state/client-password/session.d.ts +19 -0
  103. package/dist/wallet/state/client-password/session.js +170 -0
  104. package/dist/wallet/state/client-password/setup.d.ts +8 -0
  105. package/dist/wallet/state/client-password/setup.js +49 -0
  106. package/dist/wallet/state/client-password/types.d.ts +82 -0
  107. package/dist/wallet/state/client-password/types.js +5 -0
  108. package/dist/wallet/state/client-password.d.ts +7 -38
  109. package/dist/wallet/state/client-password.js +52 -937
  110. package/dist/wallet/tx/anchor.js +123 -216
  111. package/dist/wallet/tx/cog.js +294 -489
  112. package/dist/wallet/tx/common.d.ts +2 -0
  113. package/dist/wallet/tx/common.js +2 -0
  114. package/dist/wallet/tx/domain-admin.js +111 -220
  115. package/dist/wallet/tx/domain-market.js +401 -681
  116. package/dist/wallet/tx/executor.d.ts +176 -0
  117. package/dist/wallet/tx/executor.js +302 -0
  118. package/dist/wallet/tx/field.js +109 -215
  119. package/dist/wallet/tx/register.js +158 -269
  120. package/dist/wallet/tx/reputation.js +120 -227
  121. package/package.json +1 -1
  122. package/dist/wallet/mining/worker-main.d.ts +0 -1
  123. package/dist/wallet/mining/worker-main.js +0 -17
  124. package/dist/wallet/state/client-password-agent.d.ts +0 -1
  125. package/dist/wallet/state/client-password-agent.js +0 -211
@@ -1,6 +1,6 @@
1
1
  import { randomBytes } from "node:crypto";
2
2
  import { execFile, spawn } from "node:child_process";
3
- import { access, constants, mkdir, readFile, readdir, rm } from "node:fs/promises";
3
+ import { access, constants, mkdir, readFile, rm } from "node:fs/promises";
4
4
  import { totalmem } from "node:os";
5
5
  import { dirname, join } from "node:path";
6
6
  import { promisify } from "node:util";
@@ -10,7 +10,9 @@ import { acquireFileLock, FileLockBusyError } from "../wallet/fs/lock.js";
10
10
  import { writeFileAtomic } from "../wallet/fs/atomic.js";
11
11
  import { writeRuntimeStatusFile } from "../wallet/fs/status-file.js";
12
12
  import { stopIndexerDaemonServiceWithLockHeld } from "./indexer-daemon.js";
13
- import { mapManagedBitcoindRuntimeProbeFailure, mapManagedBitcoindValidationError, resolveManagedBitcoindProbeDecision, validateManagedBitcoindObservedStatus, } from "./managed-runtime/bitcoind-policy.js";
13
+ import { mapManagedBitcoindRuntimeProbeFailure, mapManagedBitcoindValidationError, validateManagedBitcoindObservedStatus, } from "./managed-runtime/bitcoind-policy.js";
14
+ import { listManagedBitcoindStatusCandidates, readManagedBitcoindObservedStatus, } from "./managed-runtime/bitcoind-status.js";
15
+ import { attachOrStartManagedBitcoindRuntime, probeManagedBitcoindRuntime, } from "./managed-runtime/bitcoind-runtime.js";
14
16
  import { readJsonFileIfPresent } from "./managed-runtime/status.js";
15
17
  import { createRpcClient, validateNodeConfigForTesting } from "./node.js";
16
18
  import { resolveManagedServicePaths, UNINITIALIZED_WALLET_ROOT_ID } from "./service-paths.js";
@@ -18,7 +20,7 @@ import { DEFAULT_MANAGED_BITCOIND_FOLLOW_POLL_INTERVAL_MS, MANAGED_BITCOIND_SERV
18
20
  const execFileAsync = promisify(execFile);
19
21
  const LOCAL_HOST = "127.0.0.1";
20
22
  const SUPPORTED_BITCOIND_VERSION = "30.2.0";
21
- const DEFAULT_STARTUP_TIMEOUT_MS = 30_000;
23
+ const DEFAULT_STARTUP_TIMEOUT_MS = 60_000;
22
24
  const DEFAULT_SHUTDOWN_TIMEOUT_MS = 15_000;
23
25
  const DEFAULT_DBCACHE_MIB = 450;
24
26
  const claimedUninitializedRuntimeKeys = new Set();
@@ -78,42 +80,6 @@ async function acquireFileLockWithRetry(lockPath, metadata, timeoutMs) {
78
80
  function getWalletReplicaName(walletRootId) {
79
81
  return `cogcoin-${walletRootId}`.replace(/[^a-zA-Z0-9._-]+/g, "-").slice(0, 63);
80
82
  }
81
- async function listManagedBitcoindStatusCandidates(options) {
82
- const candidates = new Map();
83
- const addCandidate = async (statusPath, allowDataDirMismatch = false) => {
84
- const status = await readJsonFileIfPresent(statusPath);
85
- if (status === null) {
86
- return;
87
- }
88
- if (!allowDataDirMismatch && status.dataDir !== options.dataDir) {
89
- return;
90
- }
91
- candidates.set(statusPath, status);
92
- };
93
- await addCandidate(options.expectedStatusPath, true);
94
- try {
95
- const entries = await readdir(options.runtimeRoot, {
96
- withFileTypes: true,
97
- });
98
- for (const entry of entries) {
99
- if (!entry.isDirectory()) {
100
- continue;
101
- }
102
- const statusPath = join(options.runtimeRoot, entry.name, "bitcoind-status.json");
103
- if (statusPath === options.expectedStatusPath) {
104
- continue;
105
- }
106
- await addCandidate(statusPath);
107
- }
108
- }
109
- catch {
110
- // Missing runtime roots are handled by returning no candidates.
111
- }
112
- return [...candidates.entries()].map(([statusPath, status]) => ({
113
- statusPath,
114
- status,
115
- }));
116
- }
117
83
  async function allocatePort() {
118
84
  return new Promise((resolve, reject) => {
119
85
  const server = net.createServer();
@@ -664,44 +630,19 @@ async function tryAttachExistingManagedBitcoindService(options) {
664
630
  const refreshed = await refreshManagedBitcoindStatus(probe.status, paths, options);
665
631
  return createNodeHandle(refreshed, paths, options, "attached");
666
632
  }
667
- async function waitForManagedBitcoindService(options, timeoutMs) {
668
- const deadline = Date.now() + timeoutMs;
669
- while (Date.now() < deadline) {
670
- const attached = await tryAttachExistingManagedBitcoindService(options).catch(() => null);
671
- if (attached !== null) {
672
- return attached;
673
- }
674
- await sleep(250);
675
- }
676
- throw new Error("managed_bitcoind_service_start_timeout");
677
- }
678
633
  export async function probeManagedBitcoindService(options) {
679
- const walletRootId = options.walletRootId ?? UNINITIALIZED_WALLET_ROOT_ID;
680
- const paths = resolveManagedServicePaths(options.dataDir ?? "", walletRootId);
681
- const candidates = await listManagedBitcoindStatusCandidates({
634
+ const resolvedOptions = {
635
+ ...options,
682
636
  dataDir: options.dataDir ?? "",
683
- runtimeRoot: paths.runtimeRoot,
684
- expectedStatusPath: paths.bitcoindStatusPath,
685
- });
686
- const expectedCandidate = candidates.find((candidate) => candidate.statusPath === paths.bitcoindStatusPath) ?? null;
687
- for (const candidate of candidates) {
688
- if (!await isProcessAlive(candidate.status.processId)) {
689
- continue;
690
- }
691
- return probeManagedBitcoindStatusCandidate(candidate.status, options, paths.walletRuntimeRoot);
692
- }
693
- if (expectedCandidate !== null) {
694
- return {
695
- compatibility: "unreachable",
696
- status: expectedCandidate.status,
697
- error: null,
698
- };
699
- }
700
- return {
701
- compatibility: "unreachable",
702
- status: candidates[0]?.status ?? null,
703
- error: null,
637
+ walletRootId: options.walletRootId ?? UNINITIALIZED_WALLET_ROOT_ID,
638
+ startupTimeoutMs: options.startupTimeoutMs ?? DEFAULT_STARTUP_TIMEOUT_MS,
704
639
  };
640
+ return probeManagedBitcoindRuntime(resolvedOptions, {
641
+ getPaths: (runtimeOptions) => resolveManagedServicePaths(runtimeOptions.dataDir, runtimeOptions.walletRootId),
642
+ listStatusCandidates: listManagedBitcoindStatusCandidates,
643
+ isProcessAlive,
644
+ probeStatusCandidate: probeManagedBitcoindStatusCandidate,
645
+ });
705
646
  }
706
647
  export async function attachOrStartManagedBitcoindService(options) {
707
648
  const resolvedOptions = {
@@ -716,42 +657,27 @@ export async function attachOrStartManagedBitcoindService(options) {
716
657
  walletRootId: resolvedOptions.walletRootId,
717
658
  shutdownTimeoutMs: resolvedOptions.shutdownTimeoutMs,
718
659
  }, async () => {
719
- const existingProbe = await probeManagedBitcoindService(resolvedOptions);
720
- const existingDecision = resolveManagedBitcoindProbeDecision(existingProbe);
721
- if (existingDecision.action === "attach") {
722
- const existing = await tryAttachExistingManagedBitcoindService(resolvedOptions);
723
- if (existing !== null) {
724
- return existing;
725
- }
726
- throw new Error("managed_bitcoind_protocol_error");
727
- }
728
- if (existingDecision.action === "reject") {
729
- throw new Error(existingDecision.error ?? "managed_bitcoind_protocol_error");
730
- }
731
- const paths = resolveManagedServicePaths(resolvedOptions.dataDir ?? "", resolvedOptions.walletRootId);
732
- try {
733
- const lock = await acquireFileLock(paths.bitcoindLockPath, {
660
+ return attachOrStartManagedBitcoindRuntime({
661
+ ...resolvedOptions,
662
+ dataDir: resolvedOptions.dataDir ?? "",
663
+ walletRootId: resolvedOptions.walletRootId ?? UNINITIALIZED_WALLET_ROOT_ID,
664
+ startupTimeoutMs,
665
+ }, {
666
+ getPaths: (runtimeOptions) => resolveManagedServicePaths(runtimeOptions.dataDir, runtimeOptions.walletRootId),
667
+ listStatusCandidates: listManagedBitcoindStatusCandidates,
668
+ isProcessAlive,
669
+ probeStatusCandidate: probeManagedBitcoindStatusCandidate,
670
+ attachExisting: tryAttachExistingManagedBitcoindService,
671
+ acquireStartLock: async (runtimeOptions, paths) => acquireFileLock(paths.bitcoindLockPath, {
734
672
  purpose: "managed-bitcoind-start",
735
- walletRootId: resolvedOptions.walletRootId,
736
- dataDir: resolvedOptions.dataDir,
737
- });
738
- try {
739
- const liveProbe = await probeManagedBitcoindService(resolvedOptions);
740
- const liveDecision = resolveManagedBitcoindProbeDecision(liveProbe);
741
- if (liveDecision.action === "attach") {
742
- const reattached = await tryAttachExistingManagedBitcoindService(resolvedOptions);
743
- if (reattached !== null) {
744
- return reattached;
745
- }
746
- throw new Error("managed_bitcoind_protocol_error");
747
- }
748
- if (liveDecision.action === "reject") {
749
- throw new Error(liveDecision.error ?? "managed_bitcoind_protocol_error");
750
- }
673
+ walletRootId: runtimeOptions.walletRootId,
674
+ dataDir: runtimeOptions.dataDir,
675
+ }),
676
+ startService: async (runtimeOptions, paths) => {
751
677
  const bitcoindPath = await getBitcoindPath();
752
678
  await verifyBitcoindVersion(bitcoindPath);
753
679
  const binaryVersion = SUPPORTED_BITCOIND_VERSION;
754
- await mkdir(resolvedOptions.dataDir ?? "", { recursive: true });
680
+ await mkdir(runtimeOptions.dataDir, { recursive: true });
755
681
  const startManagedProcess = async (startOptions) => {
756
682
  const runtimeConfig = await resolveRuntimeConfig(paths.bitcoindStatusPath, paths.bitcoindRuntimeConfigPath, startOptions);
757
683
  await writeBitcoinConf(paths.bitcoinConfPath, startOptions, runtimeConfig);
@@ -793,16 +719,15 @@ export async function attachOrStartManagedBitcoindService(options) {
793
719
  throw error;
794
720
  }
795
721
  const nowUnixMs = Date.now();
796
- const walletRootId = startOptions.walletRootId ?? UNINITIALIZED_WALLET_ROOT_ID;
797
- const walletReplica = await loadManagedWalletReplicaIfPresent(rpc, walletRootId, startOptions.dataDir ?? "");
722
+ const walletReplica = await loadManagedWalletReplicaIfPresent(rpc, startOptions.walletRootId, startOptions.dataDir);
798
723
  return createBitcoindServiceStatus({
799
724
  binaryVersion,
800
725
  serviceInstanceId: randomBytes(16).toString("hex"),
801
726
  state: "ready",
802
727
  processId: child.pid ?? null,
803
- walletRootId,
728
+ walletRootId: startOptions.walletRootId,
804
729
  chain: startOptions.chain,
805
- dataDir: startOptions.dataDir ?? "",
730
+ dataDir: startOptions.dataDir,
806
731
  runtimeRoot: paths.walletRuntimeRoot,
807
732
  startHeight: startOptions.startHeight,
808
733
  rpc: rpcConfig,
@@ -818,32 +743,25 @@ export async function attachOrStartManagedBitcoindService(options) {
818
743
  };
819
744
  let status;
820
745
  try {
821
- status = await startManagedProcess(resolvedOptions);
746
+ status = await startManagedProcess(runtimeOptions);
822
747
  }
823
748
  catch (error) {
824
- if (resolvedOptions.getblockArchivePath === undefined || resolvedOptions.getblockArchivePath === null) {
749
+ if (runtimeOptions.getblockArchivePath === undefined || runtimeOptions.getblockArchivePath === null) {
825
750
  throw error;
826
751
  }
827
752
  status = await startManagedProcess({
828
- ...resolvedOptions,
753
+ ...runtimeOptions,
829
754
  getblockArchivePath: null,
830
755
  getblockArchiveEndHeight: null,
831
756
  getblockArchiveSha256: null,
832
757
  });
833
758
  }
834
759
  await writeBitcoindStatus(paths, status);
835
- return createNodeHandle(status, paths, resolvedOptions, "started");
836
- }
837
- finally {
838
- await lock.release();
839
- }
840
- }
841
- catch (error) {
842
- if (error instanceof FileLockBusyError) {
843
- return waitForManagedBitcoindService(resolvedOptions, startupTimeoutMs);
844
- }
845
- throw error;
846
- }
760
+ return createNodeHandle(status, resolveManagedServicePaths(runtimeOptions.dataDir, runtimeOptions.walletRootId), runtimeOptions, "started");
761
+ },
762
+ isLockBusyError: (error) => error instanceof FileLockBusyError,
763
+ sleep,
764
+ });
847
765
  });
848
766
  }
849
767
  export async function stopManagedBitcoindService(options) {
@@ -866,8 +784,10 @@ export async function stopManagedBitcoindService(options) {
866
784
  }
867
785
  }
868
786
  export async function readManagedBitcoindServiceStatusForTesting(dataDir, walletRootId = UNINITIALIZED_WALLET_ROOT_ID) {
869
- const paths = resolveManagedServicePaths(dataDir, walletRootId);
870
- return readJsonFileIfPresent(paths.bitcoindStatusPath);
787
+ return readManagedBitcoindObservedStatus({
788
+ dataDir,
789
+ walletRootId,
790
+ });
871
791
  }
872
792
  export async function shutdownManagedBitcoindServiceForTesting(options) {
873
793
  await stopManagedBitcoindService({
@@ -1,5 +1,5 @@
1
1
  export type CommandHandlerFamily = "status" | "update" | "sync" | "follow" | "client-admin" | "service-runtime" | "wallet-admin" | "wallet-read" | "wallet-mutation" | "mining-admin" | "mining-runtime" | "mining-read";
2
- export type CommandName = "init" | "reset" | "repair" | "update" | "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" | "register" | "transfer" | "sell" | "unsell" | "buy" | "domain-endpoint-set" | "domain-endpoint-clear" | "domain-delegate-set" | "domain-delegate-clear" | "domain-miner-set" | "domain-miner-clear" | "domain-canonical" | "fields" | "field" | "field-create" | "field-set" | "field-clear" | "send" | "claim" | "reclaim" | "cog-lock" | "rep-give" | "rep-revoke" | "mine" | "mine-start" | "mine-stop" | "mine-setup" | "mine-prompt" | "mine-prompt-list" | "mine-status" | "mine-log" | "wallet-show-mnemonic" | "wallet-status" | "address" | "ids" | "balance" | "locks" | "domains" | "show";
2
+ export type CommandName = "init" | "reset" | "repair" | "update" | "sync" | "status" | "client-change-password" | "follow" | "bitcoin-start" | "bitcoin-stop" | "bitcoin-status" | "bitcoin-transfer" | "indexer-start" | "indexer-stop" | "indexer-status" | "anchor" | "register" | "transfer" | "sell" | "unsell" | "buy" | "domain-endpoint-set" | "domain-endpoint-clear" | "domain-delegate-set" | "domain-delegate-clear" | "domain-miner-set" | "domain-miner-clear" | "domain-canonical" | "fields" | "field" | "field-create" | "field-set" | "field-clear" | "send" | "claim" | "reclaim" | "cog-lock" | "rep-give" | "rep-revoke" | "mine" | "mine-setup" | "mine-prompt" | "mine-prompt-list" | "mine-status" | "mine-log" | "wallet-show-mnemonic" | "wallet-status" | "address" | "ids" | "balance" | "locks" | "domains" | "show";
3
3
  type AliasMatchMode = "always" | "requires-arg" | "end-or-flag";
4
4
  interface HelpEntry {
5
5
  usage: string;
@@ -31,38 +31,6 @@ const commandSpecs = [
31
31
  return "cogcoin update";
32
32
  },
33
33
  },
34
- {
35
- id: "client-unlock",
36
- handlerFamily: "client-admin",
37
- supportsYes: false,
38
- supportsSatvb: false,
39
- aliases: [{ tokens: ["client", "unlock"] }],
40
- helpEntries: [
41
- {
42
- usage: "client unlock",
43
- description: "Unlock password-protected local wallet secrets for a limited time",
44
- },
45
- ],
46
- describeCommand() {
47
- return "cogcoin client unlock";
48
- },
49
- },
50
- {
51
- id: "client-lock",
52
- handlerFamily: "client-admin",
53
- supportsYes: false,
54
- supportsSatvb: false,
55
- aliases: [{ tokens: ["client", "lock"] }],
56
- helpEntries: [
57
- {
58
- usage: "client lock",
59
- description: "Flush the cached client password unlock session",
60
- },
61
- ],
62
- describeCommand() {
63
- return "cogcoin client lock";
64
- },
65
- },
66
34
  {
67
35
  id: "client-change-password",
68
36
  handlerFamily: "client-admin",
@@ -308,38 +276,6 @@ const commandSpecs = [
308
276
  return "cogcoin mine";
309
277
  },
310
278
  },
311
- {
312
- id: "mine-start",
313
- handlerFamily: "mining-runtime",
314
- supportsYes: false,
315
- supportsSatvb: false,
316
- aliases: [{ tokens: ["mine", "start"] }],
317
- helpEntries: [
318
- {
319
- usage: "mine start",
320
- description: "Start the miner as a background worker",
321
- },
322
- ],
323
- describeCommand() {
324
- return "cogcoin mine start";
325
- },
326
- },
327
- {
328
- id: "mine-stop",
329
- handlerFamily: "mining-runtime",
330
- supportsYes: false,
331
- supportsSatvb: false,
332
- aliases: [{ tokens: ["mine", "stop"] }],
333
- helpEntries: [
334
- {
335
- usage: "mine stop",
336
- description: "Stop the active background miner",
337
- },
338
- ],
339
- describeCommand() {
340
- return "cogcoin mine stop";
341
- },
342
- },
343
279
  {
344
280
  id: "mine-setup",
345
281
  handlerFamily: "mining-admin",
@@ -949,6 +885,8 @@ const commandSpecs = [
949
885
  },
950
886
  ];
951
887
  const removedPathSpecs = [
888
+ { tokens: ["client", "unlock"], errorCode: "cli_client_unlock_removed" },
889
+ { tokens: ["client", "lock"], errorCode: "cli_client_lock_removed" },
952
890
  { tokens: ["restore"], errorCode: "cli_restore_removed" },
953
891
  { tokens: ["wallet", "delete"], errorCode: "cli_wallet_delete_removed" },
954
892
  { tokens: ["wallet", "restore"], errorCode: "cli_wallet_restore_removed" },
@@ -1,30 +1,15 @@
1
1
  import { writeLine } from "../io.js";
2
2
  import { writeHandledCliError } from "../output.js";
3
- import { changeClientPassword, lockClientPassword, unlockClientPassword, } from "../../wallet/state/provider.js";
3
+ import { changeClientPassword, } from "../../wallet/state/provider.js";
4
4
  function createCommandPrompter(context) {
5
5
  return context.createPrompter();
6
6
  }
7
7
  export async function runClientAdminCommand(parsed, context) {
8
8
  try {
9
- if (parsed.command === "client-lock") {
10
- await lockClientPassword(context.walletSecretProvider);
11
- writeLine(context.stdout, "Client locked.");
12
- return 0;
13
- }
14
- if (parsed.command === "client-unlock") {
15
- const prompter = createCommandPrompter(context);
16
- const status = await unlockClientPassword(context.walletSecretProvider, prompter);
17
- writeLine(context.stdout, status.unlockUntilUnixMs === null
18
- ? "Client unlocked."
19
- : `Client unlocked until ${new Date(status.unlockUntilUnixMs).toISOString()}.`);
20
- return 0;
21
- }
22
9
  if (parsed.command === "client-change-password") {
23
10
  const prompter = createCommandPrompter(context);
24
- const status = await changeClientPassword(context.walletSecretProvider, prompter);
25
- writeLine(context.stdout, status.unlockUntilUnixMs === null
26
- ? "Client password changed."
27
- : `Client password changed. Client unlocked until ${new Date(status.unlockUntilUnixMs).toISOString()}.`);
11
+ await changeClientPassword(context.walletSecretProvider, prompter);
12
+ writeLine(context.stdout, "Client password changed.");
28
13
  return 0;
29
14
  }
30
15
  writeLine(context.stderr, `client admin command not implemented: ${parsed.command}`);
@@ -1,12 +1,13 @@
1
1
  import { dirname } from "node:path";
2
2
  import { DEFAULT_SNAPSHOT_METADATA, resolveBootstrapPathsForTesting } from "../../bitcoind/bootstrap.js";
3
3
  import { createEmptyMiningFollowVisualizerState, MiningFollowVisualizer, } from "../../wallet/mining/visualizer.js";
4
+ import { createMiningStopRequestedError } from "../../wallet/mining/stop.js";
4
5
  import { resolveWalletRootIdFromLocalArtifacts } from "../../wallet/root-resolution.js";
5
6
  import { withInteractiveWalletSecretProvider } from "../../wallet/state/provider.js";
7
+ import { bindClientPasswordPromptSessionPolicy } from "../../wallet/state/client-password/session-policy.js";
6
8
  import { ManagedIndexerProgressObserver, assertManagedIndexerStatusRecoverable, isManagedIndexerCaughtUp, pollManagedIndexerUntilCaughtUp, } from "../managed-indexer-observer.js";
7
9
  import { usesTtyProgress, writeLine } from "../io.js";
8
10
  import { writeHandledCliError } from "../output.js";
9
- import { formatNextStepLines, getMineStopNextSteps, } from "../workflow-hints.js";
10
11
  import { createCloseSignalWatcher, waitForCompletionOrStop } from "../signals.js";
11
12
  import { createSyncProgressReporter } from "../sync-progress.js";
12
13
  import { PASSIVE_UPDATE_CHECK_TIMEOUT_MS, applyUpdateCheckResult, compareSemver, createEmptyUpdateCheckCache, fetchLatestPublishedVersion, isUpdateCheckDisabled, loadUpdateCheckCache, persistUpdateCheckCache, shouldRefreshUpdateCheck, } from "../update-service.js";
@@ -317,7 +318,7 @@ export async function runMiningRuntimeCommand(parsed, context) {
317
318
  const packageVersion = await context.readPackageVersion();
318
319
  const runtimePaths = context.resolveWalletRuntimePaths();
319
320
  if (parsed.command === "mine") {
320
- const prompter = context.createPrompter();
321
+ const prompter = bindClientPasswordPromptSessionPolicy(context.createPrompter(), "mining-indefinite");
321
322
  const provider = withInteractiveWalletSecretProvider(context.walletSecretProvider, prompter);
322
323
  const ttyProgressActive = usesTtyProgress(parsed.progressOutput, context.stderr);
323
324
  await ensureMiningProviderSetup({
@@ -368,7 +369,7 @@ export async function runMiningRuntimeCommand(parsed, context) {
368
369
  : false;
369
370
  abortController = new AbortController();
370
371
  onStop = () => {
371
- abortController?.abort();
372
+ abortController?.abort(createMiningStopRequestedError());
372
373
  };
373
374
  context.signalSource.on("SIGINT", onStop);
374
375
  context.signalSource.on("SIGTERM", onStop);
@@ -397,63 +398,6 @@ export async function runMiningRuntimeCommand(parsed, context) {
397
398
  }
398
399
  return 0;
399
400
  }
400
- if (parsed.command === "mine-start") {
401
- const prompter = createCommandPrompter(context);
402
- const provider = withInteractiveWalletSecretProvider(context.walletSecretProvider, prompter);
403
- await ensureMiningProviderSetup({
404
- context,
405
- provider,
406
- prompter,
407
- runtimePaths,
408
- });
409
- const preflightCode = await syncManagedMiningReadiness({
410
- parsed,
411
- context,
412
- dataDir,
413
- databasePath: dbPath,
414
- expectedBinaryVersion: packageVersion,
415
- provider,
416
- runtimePaths,
417
- });
418
- if (preflightCode !== null) {
419
- return preflightCode;
420
- }
421
- const result = await context.startBackgroundMining({
422
- dataDir,
423
- databasePath: dbPath,
424
- provider,
425
- prompter,
426
- builtInSetupEnsured: true,
427
- paths: runtimePaths,
428
- });
429
- if (!result.started) {
430
- writeLine(context.stdout, "Background mining is already active.");
431
- if (result.snapshot?.backgroundWorkerPid !== null && result.snapshot?.backgroundWorkerPid !== undefined) {
432
- writeLine(context.stdout, `Worker pid: ${result.snapshot.backgroundWorkerPid}`);
433
- }
434
- return 0;
435
- }
436
- writeLine(context.stdout, "Started background mining.");
437
- if (result.snapshot?.backgroundWorkerPid !== null && result.snapshot?.backgroundWorkerPid !== undefined) {
438
- writeLine(context.stdout, `Worker pid: ${result.snapshot.backgroundWorkerPid}`);
439
- }
440
- return 0;
441
- }
442
- if (parsed.command === "mine-stop") {
443
- const provider = withInteractiveWalletSecretProvider(context.walletSecretProvider, context.createPrompter());
444
- const snapshot = await context.stopBackgroundMining({
445
- dataDir,
446
- databasePath: dbPath,
447
- provider,
448
- paths: runtimePaths,
449
- });
450
- const nextSteps = getMineStopNextSteps();
451
- writeLine(context.stdout, snapshot?.note ?? "Background mining was not active.");
452
- for (const line of formatNextStepLines(nextSteps)) {
453
- writeLine(context.stdout, line);
454
- }
455
- return 0;
456
- }
457
401
  writeLine(context.stderr, `mining runtime command not implemented: ${parsed.command}`);
458
402
  return 1;
459
403
  }
@@ -1,17 +1,16 @@
1
1
  import { writeLine } from "../io.js";
2
2
  import { writeHandledCliError } from "../output.js";
3
3
  import { loadWelcomeArtText } from "../art.js";
4
- import { formatNextStepLines, getFundingQuickstartGuidance, getInitNextSteps, getSetupUnlockGuidanceLines, } from "../workflow-hints.js";
4
+ import { formatNextStepLines, getFundingQuickstartGuidance, getInitUnlockGuidanceLines, getInitNextSteps, } from "../workflow-hints.js";
5
5
  import { createOwnedLockCleanupSignalWatcher, waitForCompletionOrStop, } from "../signals.js";
6
6
  import { runSyncCommand } from "./sync.js";
7
- import { CLIENT_PASSWORD_SETUP_AUTO_UNLOCK_SECONDS } from "../../wallet/state/client-password.js";
8
7
  import { withInteractiveWalletSecretProvider } from "../../wallet/state/provider.js";
9
8
  function createCommandPrompter(context) {
10
9
  return context.createPrompter();
11
10
  }
12
11
  function getRepairWarnings(result) {
13
- return result.miningResumeAction === "resume-failed"
14
- ? [`Wallet repair succeeded, but background mining did not resume automatically: ${result.miningResumeError ?? "unknown error"}`]
12
+ return result.miningResumeAction === "skipped-background-mode-removed"
13
+ ? ["Background mining no longer resumes automatically after repair. Run `cogcoin mine` if you want mining resumed."]
15
14
  : [];
16
15
  }
17
16
  function getResetWarnings(result) {
@@ -20,7 +19,7 @@ function getResetWarnings(result) {
20
19
  : [];
21
20
  }
22
21
  function writeSetupUnlockGuidance(stdout) {
23
- for (const line of getSetupUnlockGuidanceLines(CLIENT_PASSWORD_SETUP_AUTO_UNLOCK_SECONDS)) {
22
+ for (const line of getInitUnlockGuidanceLines()) {
24
23
  writeLine(stdout, line);
25
24
  }
26
25
  }
@@ -100,7 +99,8 @@ function formatResetResultText(result) {
100
99
  function isRepairMiningResumeActionOk(action) {
101
100
  return action === "none"
102
101
  || action === "skipped-not-resumable"
103
- || action === "resumed-background";
102
+ || action === "skipped-post-repair-blocked"
103
+ || action === "skipped-background-mode-removed";
104
104
  }
105
105
  function buildRepairWarningEntries(result) {
106
106
  const entries = [];
@@ -13,7 +13,7 @@ import { initializeWallet, previewResetWallet, repairWallet, resetWallet, showWa
13
13
  import { resolveWalletRuntimePathsForTesting } from "../wallet/runtime.js";
14
14
  import { openWalletReadContext } from "../wallet/read/index.js";
15
15
  import { loadRawWalletStateEnvelope, loadWalletState } from "../wallet/state/storage.js";
16
- import { ensureBuiltInMiningSetupIfNeeded, followMiningLog, inspectMiningControlPlane, inspectMiningDomainPromptState, readMiningLog, runForegroundMining, setupBuiltInMining, startBackgroundMining, stopBackgroundMining, updateMiningDomainPrompt, } from "../wallet/mining/index.js";
16
+ import { ensureBuiltInMiningSetupIfNeeded, followMiningLog, inspectMiningControlPlane, inspectMiningDomainPromptState, readMiningLog, runForegroundMining, setupBuiltInMining, updateMiningDomainPrompt, } from "../wallet/mining/index.js";
17
17
  import { createLazyDefaultWalletSecretProvider } from "../wallet/state/provider.js";
18
18
  import { 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";
19
19
  import { createTerminalPrompter } from "./prompt.js";
@@ -93,8 +93,6 @@ export function createDefaultContext(overrides = {}) {
93
93
  inspectMiningDomainPromptState: overrides.inspectMiningDomainPromptState ?? inspectMiningDomainPromptState,
94
94
  ensureBuiltInMiningSetupIfNeeded: overrides.ensureBuiltInMiningSetupIfNeeded ?? ensureBuiltInMiningSetupIfNeeded,
95
95
  runForegroundMining: overrides.runForegroundMining ?? runForegroundMining,
96
- startBackgroundMining: overrides.startBackgroundMining ?? startBackgroundMining,
97
- stopBackgroundMining: overrides.stopBackgroundMining ?? stopBackgroundMining,
98
96
  setupBuiltInMining: overrides.setupBuiltInMining ?? setupBuiltInMining,
99
97
  updateMiningDomainPrompt: overrides.updateMiningDomainPrompt ?? updateMiningDomainPrompt,
100
98
  readMiningLog: overrides.readMiningLog ?? readMiningLog,
@@ -1,4 +1,4 @@
1
- import type { MiningControlPlaneView, MiningDomainPromptMutationResult, MiningRuntimeStatusV1 } from "../wallet/mining/index.js";
1
+ import type { MiningControlPlaneView, MiningDomainPromptMutationResult } from "../wallet/mining/index.js";
2
2
  export declare function buildMineSetupData(view: MiningControlPlaneView): {
3
3
  resultType: "state-change";
4
4
  stateChange: {
@@ -8,27 +8,6 @@ export declare function buildMineSetupData(view: MiningControlPlaneView): {
8
8
  };
9
9
  state: Record<string, unknown>;
10
10
  };
11
- export declare function buildMineStartData(result: {
12
- started: boolean;
13
- snapshot: MiningRuntimeStatusV1 | null;
14
- }): {
15
- resultType: "state-change";
16
- stateChange: {
17
- kind: string;
18
- before: Record<string, unknown> | null;
19
- after: Record<string, unknown> | null;
20
- };
21
- state: Record<string, unknown>;
22
- };
23
- export declare function buildMineStopData(snapshot: MiningRuntimeStatusV1 | null): {
24
- resultType: "state-change";
25
- stateChange: {
26
- kind: string;
27
- before: Record<string, unknown> | null;
28
- after: Record<string, unknown> | null;
29
- };
30
- state: Record<string, unknown>;
31
- };
32
11
  export declare function buildMinePromptData(result: MiningDomainPromptMutationResult): {
33
12
  domain: {
34
13
  name: string;
@@ -35,29 +35,6 @@ export function buildMineSetupData(view) {
35
35
  after,
36
36
  });
37
37
  }
38
- export function buildMineStartData(result) {
39
- const after = {
40
- started: result.started,
41
- runtime: summarizeRuntime(result.snapshot),
42
- };
43
- return buildStateChangeData({
44
- kind: "mine-start",
45
- state: after,
46
- after,
47
- });
48
- }
49
- export function buildMineStopData(snapshot) {
50
- const after = {
51
- stopped: snapshot !== null,
52
- runtime: summarizeRuntime(snapshot),
53
- note: snapshot?.note ?? "Background mining was not active.",
54
- };
55
- return buildStateChangeData({
56
- kind: "mine-stop",
57
- state: after,
58
- after,
59
- });
60
- }
61
38
  export function buildMinePromptData(result) {
62
39
  return {
63
40
  domain: result.domain,
@@ -330,8 +330,8 @@ export function createCliErrorPresentation(errorCode, fallbackMessage, error) {
330
330
  if (errorCode === "wallet_client_password_locked") {
331
331
  return {
332
332
  what: "Client password is locked.",
333
- why: "This command needs the password-protected local wallet secret, but no active unlock session is available.",
334
- next: "Run `cogcoin client unlock`, or rerun the command in an interactive terminal so Cogcoin can prompt for the client password.",
333
+ why: "This command needs the password-protected local wallet secret, but this process does not currently hold an unlocked client-password session.",
334
+ next: "Rerun the command in an interactive terminal so Cogcoin can prompt for the client password. Separate CLI invocations no longer share unlocked state.",
335
335
  };
336
336
  }
337
337
  if (errorCode === "wallet_client_password_change_requires_tty") {
@@ -341,6 +341,20 @@ export function createCliErrorPresentation(errorCode, fallbackMessage, error) {
341
341
  next: "Run `cogcoin client change-password` in an interactive terminal.",
342
342
  };
343
343
  }
344
+ if (errorCode === "cli_client_unlock_removed") {
345
+ return {
346
+ what: "`client unlock` was removed.",
347
+ why: "Cogcoin no longer shares unlocked client-password sessions across separate CLI commands.",
348
+ next: "Rerun password-aware commands in an interactive terminal so Cogcoin can prompt for the client password when needed.",
349
+ };
350
+ }
351
+ if (errorCode === "cli_client_lock_removed") {
352
+ return {
353
+ what: "`client lock` was removed.",
354
+ why: "Cogcoin no longer keeps reusable unlocked client-password sessions after a command exits.",
355
+ next: "Fresh CLI invocations start locked automatically and prompt when wallet-local secrets are needed.",
356
+ };
357
+ }
344
358
  if (errorCode === "cli_restore_removed" || errorCode === "cli_wallet_restore_removed") {
345
359
  return {
346
360
  what: "Standalone restore commands were removed.",
package/dist/cli/parse.js CHANGED
@@ -282,8 +282,6 @@ export function parseCliArgs(argv) {
282
282
  || command === "sync"
283
283
  || command === "follow"
284
284
  || command === "mine"
285
- || command === "mine-start"
286
- || command === "mine-stop"
287
285
  || command === "mine-setup"
288
286
  || command === "mine-prompt-list"
289
287
  || command === "mine-status"