@cogcoin/client 0.5.15 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (172) 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 +38 -3
  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 +51 -4
  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 +4 -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/types.d.ts +8 -17
  75. package/dist/cli/types.js +0 -2
  76. package/dist/cli/wallet-format.d.ts +1 -0
  77. package/dist/cli/wallet-format.js +205 -144
  78. package/dist/cli/workflow-hints.d.ts +3 -3
  79. package/dist/cli/workflow-hints.js +11 -8
  80. package/dist/client/default-client.d.ts +3 -1
  81. package/dist/client/default-client.js +45 -2
  82. package/dist/client/factory.js +1 -1
  83. package/dist/client/initialization.js +23 -0
  84. package/dist/client/persistence.js +5 -5
  85. package/dist/client/store-adapter.js +1 -0
  86. package/dist/sqlite/checkpoints.d.ts +1 -0
  87. package/dist/sqlite/checkpoints.js +7 -0
  88. package/dist/sqlite/store.js +14 -1
  89. package/dist/types.d.ts +1 -0
  90. package/dist/wallet/coin-control.d.ts +41 -12
  91. package/dist/wallet/coin-control.js +100 -428
  92. package/dist/wallet/descriptor-normalization.d.ts +1 -3
  93. package/dist/wallet/descriptor-normalization.js +0 -16
  94. package/dist/wallet/lifecycle.d.ts +7 -99
  95. package/dist/wallet/lifecycle.js +513 -968
  96. package/dist/wallet/managed-core-wallet.d.ts +13 -0
  97. package/dist/wallet/managed-core-wallet.js +20 -0
  98. package/dist/wallet/mining/constants.d.ts +5 -12
  99. package/dist/wallet/mining/constants.js +5 -12
  100. package/dist/wallet/mining/control.d.ts +1 -13
  101. package/dist/wallet/mining/control.js +45 -349
  102. package/dist/wallet/mining/index.d.ts +3 -4
  103. package/dist/wallet/mining/index.js +1 -2
  104. package/dist/wallet/mining/runner.d.ts +116 -13
  105. package/dist/wallet/mining/runner.js +885 -501
  106. package/dist/wallet/mining/runtime-artifacts.js +23 -3
  107. package/dist/wallet/mining/sentence-protocol.d.ts +44 -0
  108. package/dist/wallet/mining/sentence-protocol.js +123 -0
  109. package/dist/wallet/mining/sentences.d.ts +4 -8
  110. package/dist/wallet/mining/sentences.js +3 -52
  111. package/dist/wallet/mining/state.d.ts +11 -6
  112. package/dist/wallet/mining/state.js +7 -6
  113. package/dist/wallet/mining/types.d.ts +2 -30
  114. package/dist/wallet/mining/visualizer.d.ts +31 -3
  115. package/dist/wallet/mining/visualizer.js +135 -13
  116. package/dist/wallet/read/context.d.ts +0 -2
  117. package/dist/wallet/read/context.js +119 -140
  118. package/dist/wallet/read/filter.js +2 -11
  119. package/dist/wallet/read/index.d.ts +1 -1
  120. package/dist/wallet/read/project.js +24 -77
  121. package/dist/wallet/read/types.d.ts +10 -25
  122. package/dist/wallet/reset.d.ts +0 -1
  123. package/dist/wallet/reset.js +60 -138
  124. package/dist/wallet/root-resolution.d.ts +1 -5
  125. package/dist/wallet/root-resolution.js +0 -18
  126. package/dist/wallet/runtime.d.ts +0 -6
  127. package/dist/wallet/runtime.js +0 -8
  128. package/dist/wallet/state/client-password-agent.js +208 -0
  129. package/dist/wallet/state/client-password.d.ts +65 -0
  130. package/dist/wallet/state/client-password.js +952 -0
  131. package/dist/wallet/state/crypto.d.ts +1 -20
  132. package/dist/wallet/state/crypto.js +0 -63
  133. package/dist/wallet/state/provider.d.ts +23 -11
  134. package/dist/wallet/state/provider.js +248 -290
  135. package/dist/wallet/state/storage.d.ts +2 -2
  136. package/dist/wallet/state/storage.js +48 -16
  137. package/dist/wallet/tx/anchor.d.ts +3 -28
  138. package/dist/wallet/tx/anchor.js +349 -1250
  139. package/dist/wallet/tx/bitcoin-transfer.d.ts +35 -0
  140. package/dist/wallet/tx/bitcoin-transfer.js +200 -0
  141. package/dist/wallet/tx/cog.d.ts +5 -1
  142. package/dist/wallet/tx/cog.js +149 -185
  143. package/dist/wallet/tx/common.d.ts +61 -8
  144. package/dist/wallet/tx/common.js +266 -146
  145. package/dist/wallet/tx/domain-admin.d.ts +3 -1
  146. package/dist/wallet/tx/domain-admin.js +61 -99
  147. package/dist/wallet/tx/domain-market.d.ts +5 -1
  148. package/dist/wallet/tx/domain-market.js +221 -228
  149. package/dist/wallet/tx/field.d.ts +4 -10
  150. package/dist/wallet/tx/field.js +83 -924
  151. package/dist/wallet/tx/identity-selector.d.ts +9 -3
  152. package/dist/wallet/tx/identity-selector.js +17 -35
  153. package/dist/wallet/tx/index.d.ts +3 -1
  154. package/dist/wallet/tx/index.js +2 -1
  155. package/dist/wallet/tx/register.d.ts +3 -1
  156. package/dist/wallet/tx/register.js +62 -220
  157. package/dist/wallet/tx/reputation.d.ts +3 -1
  158. package/dist/wallet/tx/reputation.js +58 -95
  159. package/dist/wallet/types.d.ts +8 -122
  160. package/package.json +5 -5
  161. package/dist/wallet/archive.d.ts +0 -4
  162. package/dist/wallet/archive.js +0 -41
  163. package/dist/wallet/mining/hook-protocol.d.ts +0 -47
  164. package/dist/wallet/mining/hook-protocol.js +0 -161
  165. package/dist/wallet/mining/hook-runner.js +0 -52
  166. package/dist/wallet/mining/hooks.d.ts +0 -38
  167. package/dist/wallet/mining/hooks.js +0 -520
  168. package/dist/wallet/state/explicit-lock.d.ts +0 -4
  169. package/dist/wallet/state/explicit-lock.js +0 -19
  170. package/dist/wallet/state/session.d.ts +0 -12
  171. package/dist/wallet/state/session.js +0 -23
  172. /package/dist/wallet/{mining/hook-runner.d.ts → state/client-password-agent.d.ts} +0 -0
@@ -1,11 +1,14 @@
1
- import { parseUnlockDurationToMs } from "../../wallet/lifecycle.js";
2
- import { buildInitMutationData, buildResetMutationData, buildRestoreMutationData, buildWalletDeleteMutationData, buildUnlockMutationData, buildRepairMutationData, buildWalletExportMutationData, buildWalletImportMutationData, buildWalletLockMutationData, } from "../mutation-json.js";
3
- import { buildResetPreviewData, buildRepairPreviewData, buildWalletLockPreviewData, } from "../preview-json.js";
1
+ import { buildInitMutationData, buildResetMutationData, buildRestoreMutationData, buildWalletDeleteMutationData, buildRepairMutationData, } from "../mutation-json.js";
2
+ import { buildResetPreviewData, buildRepairPreviewData, } from "../preview-json.js";
4
3
  import { writeLine } from "../io.js";
5
4
  import { createTerminalPrompter } from "../prompt.js";
6
5
  import { createPreviewSuccessEnvelope, createMutationSuccessEnvelope, describeCanonicalCommand, resolvePreviewJsonSchema, resolveStableMutationJsonSchema, writeHandledCliError, writeJsonValue, } from "../output.js";
7
- import { formatNextStepLines, getFundingQuickstartGuidance, getInitNextSteps, getRestoreNextSteps, } from "../workflow-hints.js";
6
+ import { loadWelcomeArtText } from "../art.js";
7
+ import { formatNextStepLines, getFundingQuickstartGuidance, getInitNextSteps, getRestoreNextSteps, getSetupUnlockGuidanceLines, } from "../workflow-hints.js";
8
8
  import { createOwnedLockCleanupSignalWatcher, waitForCompletionOrStop, } from "../signals.js";
9
+ import { runSyncCommand } from "./sync.js";
10
+ import { CLIENT_PASSWORD_SETUP_AUTO_UNLOCK_SECONDS } from "../../wallet/state/client-password.js";
11
+ import { withInteractiveWalletSecretProvider } from "../../wallet/state/provider.js";
9
12
  function createCommandPrompter(parsed, context) {
10
13
  return parsed.outputMode !== "text"
11
14
  ? createTerminalPrompter(context.stdin, context.stderr)
@@ -21,24 +24,32 @@ function getResetWarnings(result) {
21
24
  ? ["Some existing Cogcoin secret-provider entries could not be discovered from the remaining local wallet artifacts and may need manual cleanup."]
22
25
  : [];
23
26
  }
27
+ function writeSetupUnlockGuidance(stdout) {
28
+ for (const line of getSetupUnlockGuidanceLines(CLIENT_PASSWORD_SETUP_AUTO_UNLOCK_SECONDS)) {
29
+ writeLine(stdout, line);
30
+ }
31
+ }
24
32
  function getResetNextSteps(result) {
25
33
  return result.walletAction === "deleted" || result.walletAction === "not-present"
26
34
  ? ["Run `cogcoin init` to create a new wallet."]
27
35
  : ["Run `cogcoin sync` to bootstrap assumeutxo and the managed Bitcoin/indexer state."];
28
36
  }
37
+ function getRepairNextSteps() {
38
+ return ["Run `cogcoin status` to review the repaired local state."];
39
+ }
29
40
  function formatResetBitcoinDataDirStatus(result) {
30
41
  if (result.bitcoinDataDir.status === "outside-reset-scope") {
31
42
  return "preserved (outside reset scope)";
32
43
  }
33
44
  return result.bitcoinDataDir.status;
34
45
  }
35
- function resetTextEntry(label, value, ok) {
46
+ function sectionTextEntry(label, value, ok) {
36
47
  return {
37
48
  text: `${label}: ${value}`,
38
49
  ok,
39
50
  };
40
51
  }
41
- function formatResetSection(header, entries) {
52
+ function formatAdminSection(header, entries) {
42
53
  return [header, ...entries.map((entry) => `${entry.ok ? "✓" : "✗"} ${entry.text}`)].join("\n");
43
54
  }
44
55
  function formatResetResultText(result) {
@@ -47,30 +58,30 @@ function formatResetResultText(result) {
47
58
  const secretCleanupOk = result.secretCleanupStatus !== "unknown" && result.secretCleanupStatus !== "failed";
48
59
  const managedCleanupOk = result.stoppedProcesses.survivors === 0;
49
60
  const outcomeEntries = [
50
- resetTextEntry("Wallet action", result.walletAction, true),
51
- resetTextEntry("Snapshot", result.bootstrapSnapshot.status, true),
52
- resetTextEntry("Bitcoin datadir", formatResetBitcoinDataDirStatus(result), true),
53
- resetTextEntry("Secret cleanup", result.secretCleanupStatus, secretCleanupOk),
61
+ sectionTextEntry("Wallet action", result.walletAction, true),
62
+ sectionTextEntry("Snapshot", result.bootstrapSnapshot.status, true),
63
+ sectionTextEntry("Bitcoin datadir", formatResetBitcoinDataDirStatus(result), true),
64
+ sectionTextEntry("Secret cleanup", result.secretCleanupStatus, secretCleanupOk),
54
65
  ];
55
66
  if (result.walletAction !== "retain-mnemonic" && result.walletOldRootId !== null) {
56
- outcomeEntries.push(resetTextEntry("Previous wallet root", result.walletOldRootId, true));
67
+ outcomeEntries.push(sectionTextEntry("Previous wallet root", result.walletOldRootId, true));
57
68
  }
58
69
  if (result.walletAction !== "retain-mnemonic" && result.walletNewRootId !== null) {
59
- outcomeEntries.push(resetTextEntry("New wallet root", result.walletNewRootId, true));
70
+ outcomeEntries.push(sectionTextEntry("New wallet root", result.walletNewRootId, true));
60
71
  }
61
72
  const sections = [
62
- formatResetSection("Paths", [
63
- resetTextEntry("Data root", result.dataRoot, true),
73
+ formatAdminSection("Paths", [
74
+ sectionTextEntry("Data root", result.dataRoot, true),
64
75
  ]),
65
- formatResetSection("Reset Outcome", outcomeEntries),
66
- formatResetSection("Managed Cleanup", [
67
- resetTextEntry("Managed bitcoind processes stopped", String(result.stoppedProcesses.managedBitcoind), managedCleanupOk),
68
- resetTextEntry("Indexer daemons stopped", String(result.stoppedProcesses.indexerDaemon), managedCleanupOk),
69
- resetTextEntry("Background miners stopped", String(result.stoppedProcesses.backgroundMining), managedCleanupOk),
76
+ formatAdminSection("Reset Outcome", outcomeEntries),
77
+ formatAdminSection("Managed Cleanup", [
78
+ sectionTextEntry("Managed bitcoind processes stopped", String(result.stoppedProcesses.managedBitcoind), managedCleanupOk),
79
+ sectionTextEntry("Indexer daemons stopped", String(result.stoppedProcesses.indexerDaemon), managedCleanupOk),
80
+ sectionTextEntry("Background miners stopped", String(result.stoppedProcesses.backgroundMining), managedCleanupOk),
70
81
  ]),
71
82
  ];
72
83
  if (warnings.length > 0) {
73
- sections.push(formatResetSection("Warnings", warnings.map((warning) => resetTextEntry("Warning", warning, false))));
84
+ sections.push(formatAdminSection("Warnings", warnings.map((warning) => sectionTextEntry("Warning", warning, false))));
74
85
  }
75
86
  const parts = [
76
87
  "\n⛭ Cogcoin Reset ⛭",
@@ -81,6 +92,68 @@ function formatResetResultText(result) {
81
92
  }
82
93
  return parts.join("\n\n");
83
94
  }
95
+ function isRepairMiningResumeActionOk(action) {
96
+ return action === "none"
97
+ || action === "skipped-not-resumable"
98
+ || action === "resumed-background";
99
+ }
100
+ function buildRepairWarningEntries(result) {
101
+ const entries = [];
102
+ if (result.miningResumeError !== null) {
103
+ entries.push(sectionTextEntry("Mining resume error", result.miningResumeError, false));
104
+ }
105
+ for (const warning of getRepairWarnings(result)) {
106
+ if (result.miningResumeError !== null && warning.includes(result.miningResumeError)) {
107
+ continue;
108
+ }
109
+ entries.push(sectionTextEntry("Warning", warning, false));
110
+ }
111
+ return entries;
112
+ }
113
+ function formatRepairResultText(result) {
114
+ const nextStep = getRepairNextSteps()[0] ?? null;
115
+ const warningEntries = buildRepairWarningEntries(result);
116
+ const sections = [
117
+ formatAdminSection("Wallet", [
118
+ sectionTextEntry("Wallet root", result.walletRootId, true),
119
+ sectionTextEntry("Recovered from backup", result.recoveredFromBackup ? "yes" : "no", true),
120
+ sectionTextEntry("Managed Core wallet recreated", result.recreatedManagedCoreWallet ? "yes" : "no", true),
121
+ ]),
122
+ formatAdminSection("Managed Bitcoind", [
123
+ sectionTextEntry("Managed bitcoind action", result.bitcoindServiceAction, true),
124
+ sectionTextEntry("Managed bitcoind compatibility issue", result.bitcoindCompatibilityIssue, result.bitcoindCompatibilityIssue === "none"),
125
+ sectionTextEntry("Managed Core replica action", result.managedCoreReplicaAction, true),
126
+ sectionTextEntry("Managed bitcoind post-repair health", result.bitcoindPostRepairHealth, result.bitcoindPostRepairHealth === "ready"),
127
+ ]),
128
+ formatAdminSection("Indexer", [
129
+ sectionTextEntry("Indexer database reset", result.resetIndexerDatabase ? "yes" : "no", true),
130
+ sectionTextEntry("Indexer daemon action", result.indexerDaemonAction, true),
131
+ sectionTextEntry("Indexer compatibility issue", result.indexerCompatibilityIssue, result.indexerCompatibilityIssue === "none"),
132
+ sectionTextEntry("Indexer post-repair health", result.indexerPostRepairHealth, result.indexerPostRepairHealth === "synced"),
133
+ ]),
134
+ formatAdminSection("Mining", [
135
+ sectionTextEntry("Mining mode before repair", result.miningPreRepairRunMode, true),
136
+ sectionTextEntry("Mining resume action", result.miningResumeAction, isRepairMiningResumeActionOk(result.miningResumeAction)),
137
+ sectionTextEntry("Mining mode after repair", result.miningPostRepairRunMode, true),
138
+ ]),
139
+ ];
140
+ if (result.note !== null) {
141
+ sections.push(formatAdminSection("Notes", [
142
+ sectionTextEntry("Note", result.note, true),
143
+ ]));
144
+ }
145
+ if (warningEntries.length > 0) {
146
+ sections.push(formatAdminSection("Warnings", warningEntries));
147
+ }
148
+ const parts = [
149
+ "\n⛭ Cogcoin Repair ⛭",
150
+ ...sections,
151
+ ];
152
+ if (nextStep !== null) {
153
+ parts.push(`Next step: ${nextStep}`);
154
+ }
155
+ return parts.join("\n\n");
156
+ }
84
157
  export async function runWalletAdminCommand(parsed, context) {
85
158
  const runtimePaths = context.resolveWalletRuntimePaths(parsed.seedName);
86
159
  const stopWatcher = createOwnedLockCleanupSignalWatcher(context.signalSource, context.forceExit, [
@@ -89,15 +162,17 @@ export async function runWalletAdminCommand(parsed, context) {
89
162
  runtimePaths.bitcoindLockPath,
90
163
  runtimePaths.indexerDaemonLockPath,
91
164
  ]);
165
+ let shouldAutoSyncAfterInit = false;
92
166
  try {
93
167
  const outcome = await waitForCompletionOrStop((async () => {
94
168
  const provider = context.walletSecretProvider;
95
169
  if (parsed.command === "init" || parsed.command === "wallet-init") {
96
170
  const dataDir = parsed.dataDir ?? context.resolveDefaultBitcoindDataDir();
97
171
  const prompter = createCommandPrompter(parsed, context);
172
+ const interactiveProvider = withInteractiveWalletSecretProvider(provider, prompter);
98
173
  const result = await context.initializeWallet({
99
174
  dataDir,
100
- provider,
175
+ provider: interactiveProvider,
101
176
  prompter,
102
177
  paths: runtimePaths,
103
178
  });
@@ -109,22 +184,42 @@ export async function runWalletAdminCommand(parsed, context) {
109
184
  }));
110
185
  return 0;
111
186
  }
112
- writeLine(context.stdout, `Wallet initialized.`);
113
- writeLine(context.stdout, `Wallet root: ${result.walletRootId}`);
114
- writeLine(context.stdout, `Funding address: ${result.fundingAddress}`);
115
- writeLine(context.stdout, `Unlocked until: ${new Date(result.unlockUntilUnixMs).toISOString()}`);
116
- writeLine(context.stdout, `Quickstart: ${getFundingQuickstartGuidance()}`);
117
- for (const line of formatNextStepLines(nextSteps)) {
118
- writeLine(context.stdout, line);
187
+ writeLine(context.stdout, "");
188
+ writeLine(context.stdout, loadWelcomeArtText());
189
+ writeLine(context.stdout, "");
190
+ writeLine(context.stdout, result.walletAction === "already-initialized"
191
+ ? "Wallet already initialized."
192
+ : "Wallet initialized.");
193
+ if (result.walletAction === "already-initialized") {
194
+ writeLine(context.stdout, "");
195
+ writeLine(context.stdout, "Wallet");
196
+ writeLine(context.stdout, `✓ Client password: ${result.passwordAction}`);
197
+ writeLine(context.stdout, `✓ Wallet root: ${result.walletRootId}`);
198
+ writeLine(context.stdout, `✓ Funding address: ${result.fundingAddress}`);
199
+ if (result.passwordAction !== "already-configured") {
200
+ writeSetupUnlockGuidance(context.stdout);
201
+ }
202
+ }
203
+ else {
204
+ writeLine(context.stdout, `Client password: ${result.passwordAction}`);
205
+ if (result.passwordAction !== "already-configured") {
206
+ writeSetupUnlockGuidance(context.stdout);
207
+ }
208
+ writeLine(context.stdout, `Wallet root: ${result.walletRootId}`);
209
+ writeLine(context.stdout, `Funding address: ${result.fundingAddress}`);
119
210
  }
211
+ writeLine(context.stdout, "");
212
+ writeLine(context.stdout, `Quickstart: ${getFundingQuickstartGuidance()}`);
213
+ shouldAutoSyncAfterInit = true;
120
214
  return 0;
121
215
  }
122
216
  if (parsed.command === "restore" || parsed.command === "wallet-restore") {
123
217
  const dataDir = parsed.dataDir ?? context.resolveDefaultBitcoindDataDir();
124
218
  const prompter = createCommandPrompter(parsed, context);
219
+ const interactiveProvider = withInteractiveWalletSecretProvider(provider, prompter);
125
220
  const result = await context.restoreWalletFromMnemonic({
126
221
  dataDir,
127
- provider,
222
+ provider: interactiveProvider,
128
223
  prompter,
129
224
  paths: runtimePaths,
130
225
  });
@@ -139,9 +234,11 @@ export async function runWalletAdminCommand(parsed, context) {
139
234
  return 0;
140
235
  }
141
236
  writeLine(context.stdout, `Wallet seed "${result.seedName}" restored from mnemonic.`);
237
+ if (result.passwordAction !== "already-configured") {
238
+ writeSetupUnlockGuidance(context.stdout);
239
+ }
142
240
  writeLine(context.stdout, `Wallet root: ${result.walletRootId}`);
143
241
  writeLine(context.stdout, `Funding address: ${result.fundingAddress}`);
144
- writeLine(context.stdout, `Unlocked until: ${new Date(result.unlockUntilUnixMs).toISOString()}`);
145
242
  writeLine(context.stdout, "Note: Managed Bitcoin/indexer bootstrap is deferred until you run `cogcoin sync`.");
146
243
  for (const warning of result.warnings ?? []) {
147
244
  writeLine(context.stdout, `Warning: ${warning}`);
@@ -154,9 +251,10 @@ export async function runWalletAdminCommand(parsed, context) {
154
251
  if (parsed.command === "wallet-delete") {
155
252
  const dataDir = parsed.dataDir ?? context.resolveDefaultBitcoindDataDir();
156
253
  const prompter = createCommandPrompter(parsed, context);
254
+ const interactiveProvider = withInteractiveWalletSecretProvider(provider, prompter);
157
255
  const result = await context.deleteImportedWalletSeed({
158
256
  dataDir,
159
- provider,
257
+ provider: interactiveProvider,
160
258
  prompter,
161
259
  assumeYes: parsed.assumeYes,
162
260
  paths: runtimePaths,
@@ -172,29 +270,13 @@ export async function runWalletAdminCommand(parsed, context) {
172
270
  if (parsed.command === "wallet-show-mnemonic") {
173
271
  const prompter = createCommandPrompter(parsed, context);
174
272
  await context.showWalletMnemonic({
175
- provider,
273
+ provider: withInteractiveWalletSecretProvider(provider, prompter),
176
274
  prompter,
177
275
  paths: runtimePaths,
178
276
  });
179
277
  return 0;
180
278
  }
181
279
  const dbPath = parsed.dbPath ?? context.resolveDefaultClientDatabasePath();
182
- if (parsed.command === "unlock" || parsed.command === "wallet-unlock") {
183
- const durationMs = parseUnlockDurationToMs(parsed.unlockFor);
184
- const result = await context.unlockWallet({
185
- provider,
186
- unlockDurationMs: durationMs,
187
- paths: runtimePaths,
188
- });
189
- if (parsed.outputMode === "json") {
190
- writeJsonValue(context.stdout, createMutationSuccessEnvelope(resolveStableMutationJsonSchema(parsed), describeCanonicalCommand(parsed), "unlocked", buildUnlockMutationData(result)));
191
- return 0;
192
- }
193
- writeLine(context.stdout, `Wallet unlocked.`);
194
- writeLine(context.stdout, `Wallet root: ${result.state.walletRootId}`);
195
- writeLine(context.stdout, `Unlocked until: ${new Date(result.unlockUntilUnixMs).toISOString()}`);
196
- return 0;
197
- }
198
280
  if (parsed.command === "reset") {
199
281
  const dataDir = parsed.dataDir ?? context.resolveDefaultBitcoindDataDir();
200
282
  if (parsed.outputMode === "preview-json") {
@@ -208,7 +290,7 @@ export async function runWalletAdminCommand(parsed, context) {
208
290
  const prompter = createCommandPrompter(parsed, context);
209
291
  const result = await context.resetWallet({
210
292
  dataDir,
211
- provider,
293
+ provider: withInteractiveWalletSecretProvider(provider, prompter),
212
294
  prompter,
213
295
  });
214
296
  if (parsed.outputMode === "json") {
@@ -221,113 +303,33 @@ export async function runWalletAdminCommand(parsed, context) {
221
303
  writeLine(context.stdout, formatResetResultText(result));
222
304
  return 0;
223
305
  }
224
- if (parsed.command === "wallet-export") {
225
- const dataDir = parsed.dataDir ?? context.resolveDefaultBitcoindDataDir();
226
- const prompter = createCommandPrompter(parsed, context);
227
- const result = await context.exportWallet({
228
- archivePath: parsed.args[0],
229
- dataDir,
230
- databasePath: dbPath,
231
- provider,
232
- prompter,
233
- paths: runtimePaths,
234
- });
235
- if (parsed.outputMode === "json") {
236
- writeJsonValue(context.stdout, createMutationSuccessEnvelope(resolveStableMutationJsonSchema(parsed), describeCanonicalCommand(parsed), "exported", buildWalletExportMutationData(result)));
237
- return 0;
238
- }
239
- writeLine(context.stdout, `Wallet exported.`);
240
- writeLine(context.stdout, `Wallet root: ${result.walletRootId}`);
241
- writeLine(context.stdout, `Archive path: ${result.archivePath}`);
242
- return 0;
243
- }
244
- if (parsed.command === "wallet-import") {
245
- const dataDir = parsed.dataDir ?? context.resolveDefaultBitcoindDataDir();
246
- const prompter = createCommandPrompter(parsed, context);
247
- const result = await context.importWallet({
248
- archivePath: parsed.args[0],
249
- dataDir,
250
- databasePath: dbPath,
251
- provider,
252
- prompter,
253
- paths: runtimePaths,
254
- });
255
- if (parsed.outputMode === "json") {
256
- writeJsonValue(context.stdout, createMutationSuccessEnvelope(resolveStableMutationJsonSchema(parsed), describeCanonicalCommand(parsed), "imported", buildWalletImportMutationData(result)));
257
- return 0;
258
- }
259
- writeLine(context.stdout, `Wallet imported.`);
260
- writeLine(context.stdout, `Wallet root: ${result.walletRootId}`);
261
- writeLine(context.stdout, `Funding address: ${result.fundingAddress}`);
262
- writeLine(context.stdout, `Unlocked until: ${new Date(result.unlockUntilUnixMs).toISOString()}`);
263
- return 0;
264
- }
265
- if (parsed.command === "wallet-lock") {
266
- const dataDir = parsed.dataDir ?? context.resolveDefaultBitcoindDataDir();
267
- const result = await context.lockWallet({
268
- dataDir,
269
- provider,
270
- paths: runtimePaths,
271
- });
272
- if (parsed.outputMode === "preview-json") {
273
- writeJsonValue(context.stdout, createPreviewSuccessEnvelope(resolvePreviewJsonSchema(parsed), describeCanonicalCommand(parsed), "locked", buildWalletLockPreviewData(result)));
274
- return 0;
275
- }
276
- if (parsed.outputMode === "json") {
277
- writeJsonValue(context.stdout, createMutationSuccessEnvelope(resolveStableMutationJsonSchema(parsed), "cogcoin wallet lock", "locked", buildWalletLockMutationData(result)));
278
- return 0;
279
- }
280
- writeLine(context.stdout, `Wallet locked.`);
281
- writeLine(context.stdout, `Wallet root: ${result.walletRootId ?? "none"}`);
282
- return 0;
283
- }
284
306
  if (parsed.command === "repair") {
285
307
  const dataDir = parsed.dataDir ?? context.resolveDefaultBitcoindDataDir();
308
+ const repairProvider = parsed.outputMode === "preview-json"
309
+ ? provider
310
+ : withInteractiveWalletSecretProvider(provider, createCommandPrompter(parsed, context));
286
311
  const result = await context.repairWallet({
287
312
  dataDir,
288
313
  databasePath: dbPath,
289
- provider,
314
+ provider: repairProvider,
290
315
  assumeYes: parsed.assumeYes,
291
316
  paths: runtimePaths,
292
317
  });
293
318
  if (parsed.outputMode === "preview-json") {
294
319
  writeJsonValue(context.stdout, createPreviewSuccessEnvelope(resolvePreviewJsonSchema(parsed), describeCanonicalCommand(parsed), "completed", buildRepairPreviewData(result), {
295
- nextSteps: ["Run `cogcoin status` to review the repaired local state."],
320
+ nextSteps: getRepairNextSteps(),
296
321
  warnings: getRepairWarnings(result),
297
322
  }));
298
323
  return 0;
299
324
  }
300
325
  if (parsed.outputMode === "json") {
301
326
  writeJsonValue(context.stdout, createMutationSuccessEnvelope(resolveStableMutationJsonSchema(parsed), "cogcoin repair", "completed", buildRepairMutationData(result), {
302
- nextSteps: ["Run `cogcoin status` to review the repaired local state."],
327
+ nextSteps: getRepairNextSteps(),
303
328
  warnings: getRepairWarnings(result),
304
329
  }));
305
330
  return 0;
306
331
  }
307
- writeLine(context.stdout, `Wallet repair completed.`);
308
- writeLine(context.stdout, `Wallet root: ${result.walletRootId}`);
309
- writeLine(context.stdout, `Recovered from backup: ${result.recoveredFromBackup ? "yes" : "no"}`);
310
- writeLine(context.stdout, `Managed Core wallet recreated: ${result.recreatedManagedCoreWallet ? "yes" : "no"}`);
311
- writeLine(context.stdout, `Managed bitcoind action: ${result.bitcoindServiceAction}`);
312
- writeLine(context.stdout, `Managed bitcoind compatibility issue: ${result.bitcoindCompatibilityIssue}`);
313
- writeLine(context.stdout, `Managed Core replica action: ${result.managedCoreReplicaAction}`);
314
- writeLine(context.stdout, `Managed bitcoind post-repair health: ${result.bitcoindPostRepairHealth}`);
315
- writeLine(context.stdout, `Indexer database reset: ${result.resetIndexerDatabase ? "yes" : "no"}`);
316
- writeLine(context.stdout, `Indexer daemon action: ${result.indexerDaemonAction}`);
317
- writeLine(context.stdout, `Indexer compatibility issue: ${result.indexerCompatibilityIssue}`);
318
- writeLine(context.stdout, `Indexer post-repair health: ${result.indexerPostRepairHealth}`);
319
- writeLine(context.stdout, `Mining mode before repair: ${result.miningPreRepairRunMode}`);
320
- writeLine(context.stdout, `Mining resume action: ${result.miningResumeAction}`);
321
- writeLine(context.stdout, `Mining mode after repair: ${result.miningPostRepairRunMode}`);
322
- if (result.miningResumeError !== null) {
323
- writeLine(context.stdout, `Mining resume error: ${result.miningResumeError}`);
324
- }
325
- if (result.note !== null) {
326
- writeLine(context.stdout, `Note: ${result.note}`);
327
- }
328
- for (const warning of getRepairWarnings(result)) {
329
- writeLine(context.stdout, `Warning: ${warning}`);
330
- }
332
+ writeLine(context.stdout, formatRepairResultText(result));
331
333
  return 0;
332
334
  }
333
335
  writeLine(context.stderr, `wallet admin command not implemented: ${parsed.command}`);
@@ -336,6 +338,10 @@ export async function runWalletAdminCommand(parsed, context) {
336
338
  if (outcome.kind === "stopped") {
337
339
  return outcome.code;
338
340
  }
341
+ if (shouldAutoSyncAfterInit && outcome.value === 0) {
342
+ stopWatcher.cleanup();
343
+ return await runSyncCommand(parsed, context);
344
+ }
339
345
  return outcome.value;
340
346
  }
341
347
  catch (error) {