@cogcoin/client 0.5.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 (289) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +136 -0
  3. package/dist/app-paths.d.ts +38 -0
  4. package/dist/app-paths.js +121 -0
  5. package/dist/art/banner.txt +13 -0
  6. package/dist/art/scroll.txt +13 -0
  7. package/dist/art/train-car.txt +6 -0
  8. package/dist/art/train-smoke.txt +6 -0
  9. package/dist/art/train.txt +6 -0
  10. package/dist/bitcoind/bootstrap/chainstate.d.ts +4 -0
  11. package/dist/bitcoind/bootstrap/chainstate.js +13 -0
  12. package/dist/bitcoind/bootstrap/constants.d.ts +7 -0
  13. package/dist/bitcoind/bootstrap/constants.js +12 -0
  14. package/dist/bitcoind/bootstrap/controller.d.ts +29 -0
  15. package/dist/bitcoind/bootstrap/controller.js +101 -0
  16. package/dist/bitcoind/bootstrap/download.d.ts +2 -0
  17. package/dist/bitcoind/bootstrap/download.js +196 -0
  18. package/dist/bitcoind/bootstrap/headers.d.ts +13 -0
  19. package/dist/bitcoind/bootstrap/headers.js +61 -0
  20. package/dist/bitcoind/bootstrap/paths.d.ts +4 -0
  21. package/dist/bitcoind/bootstrap/paths.js +15 -0
  22. package/dist/bitcoind/bootstrap/snapshot-file.d.ts +7 -0
  23. package/dist/bitcoind/bootstrap/snapshot-file.js +42 -0
  24. package/dist/bitcoind/bootstrap/state.d.ts +40 -0
  25. package/dist/bitcoind/bootstrap/state.js +70 -0
  26. package/dist/bitcoind/bootstrap/types.d.ts +28 -0
  27. package/dist/bitcoind/bootstrap/types.js +1 -0
  28. package/dist/bitcoind/bootstrap.d.ts +8 -0
  29. package/dist/bitcoind/bootstrap.js +7 -0
  30. package/dist/bitcoind/client/factory.d.ts +3 -0
  31. package/dist/bitcoind/client/factory.js +57 -0
  32. package/dist/bitcoind/client/follow-block-times.d.ts +8 -0
  33. package/dist/bitcoind/client/follow-block-times.js +25 -0
  34. package/dist/bitcoind/client/follow-loop.d.ts +10 -0
  35. package/dist/bitcoind/client/follow-loop.js +57 -0
  36. package/dist/bitcoind/client/internal-types.d.ts +63 -0
  37. package/dist/bitcoind/client/internal-types.js +18 -0
  38. package/dist/bitcoind/client/managed-client.d.ts +20 -0
  39. package/dist/bitcoind/client/managed-client.js +197 -0
  40. package/dist/bitcoind/client/rate-tracker.d.ts +2 -0
  41. package/dist/bitcoind/client/rate-tracker.js +24 -0
  42. package/dist/bitcoind/client/sync-engine.d.ts +3 -0
  43. package/dist/bitcoind/client/sync-engine.js +143 -0
  44. package/dist/bitcoind/client.d.ts +1 -0
  45. package/dist/bitcoind/client.js +1 -0
  46. package/dist/bitcoind/errors.d.ts +1 -0
  47. package/dist/bitcoind/errors.js +49 -0
  48. package/dist/bitcoind/index.d.ts +2 -0
  49. package/dist/bitcoind/index.js +1 -0
  50. package/dist/bitcoind/indexer-daemon-main.d.ts +1 -0
  51. package/dist/bitcoind/indexer-daemon-main.js +472 -0
  52. package/dist/bitcoind/indexer-daemon.d.ts +107 -0
  53. package/dist/bitcoind/indexer-daemon.js +391 -0
  54. package/dist/bitcoind/node.d.ts +8 -0
  55. package/dist/bitcoind/node.js +219 -0
  56. package/dist/bitcoind/normalize.d.ts +3 -0
  57. package/dist/bitcoind/normalize.js +47 -0
  58. package/dist/bitcoind/progress/assets.d.ts +10 -0
  59. package/dist/bitcoind/progress/assets.js +90 -0
  60. package/dist/bitcoind/progress/constants.d.ts +48 -0
  61. package/dist/bitcoind/progress/constants.js +53 -0
  62. package/dist/bitcoind/progress/controller.d.ts +28 -0
  63. package/dist/bitcoind/progress/controller.js +188 -0
  64. package/dist/bitcoind/progress/follow-scene.d.ts +40 -0
  65. package/dist/bitcoind/progress/follow-scene.js +367 -0
  66. package/dist/bitcoind/progress/formatting.d.ts +23 -0
  67. package/dist/bitcoind/progress/formatting.js +227 -0
  68. package/dist/bitcoind/progress/quote-scene.d.ts +4 -0
  69. package/dist/bitcoind/progress/quote-scene.js +137 -0
  70. package/dist/bitcoind/progress/train-scene.d.ts +9 -0
  71. package/dist/bitcoind/progress/train-scene.js +92 -0
  72. package/dist/bitcoind/progress/tty-renderer.d.ts +18 -0
  73. package/dist/bitcoind/progress/tty-renderer.js +150 -0
  74. package/dist/bitcoind/progress.d.ts +7 -0
  75. package/dist/bitcoind/progress.js +7 -0
  76. package/dist/bitcoind/quotes.d.ts +24 -0
  77. package/dist/bitcoind/quotes.js +195 -0
  78. package/dist/bitcoind/rpc.d.ts +71 -0
  79. package/dist/bitcoind/rpc.js +322 -0
  80. package/dist/bitcoind/service-paths.d.ts +19 -0
  81. package/dist/bitcoind/service-paths.js +49 -0
  82. package/dist/bitcoind/service.d.ts +40 -0
  83. package/dist/bitcoind/service.js +735 -0
  84. package/dist/bitcoind/testing.d.ts +9 -0
  85. package/dist/bitcoind/testing.js +9 -0
  86. package/dist/bitcoind/types.d.ts +396 -0
  87. package/dist/bitcoind/types.js +3 -0
  88. package/dist/bytes.d.ts +9 -0
  89. package/dist/bytes.js +36 -0
  90. package/dist/cli/commands/follow.d.ts +2 -0
  91. package/dist/cli/commands/follow.js +43 -0
  92. package/dist/cli/commands/mining-admin.d.ts +2 -0
  93. package/dist/cli/commands/mining-admin.js +92 -0
  94. package/dist/cli/commands/mining-read.d.ts +2 -0
  95. package/dist/cli/commands/mining-read.js +173 -0
  96. package/dist/cli/commands/mining-runtime.d.ts +2 -0
  97. package/dist/cli/commands/mining-runtime.js +108 -0
  98. package/dist/cli/commands/status.d.ts +2 -0
  99. package/dist/cli/commands/status.js +31 -0
  100. package/dist/cli/commands/sync.d.ts +2 -0
  101. package/dist/cli/commands/sync.js +52 -0
  102. package/dist/cli/commands/wallet-admin.d.ts +2 -0
  103. package/dist/cli/commands/wallet-admin.js +175 -0
  104. package/dist/cli/commands/wallet-mutation.d.ts +2 -0
  105. package/dist/cli/commands/wallet-mutation.js +681 -0
  106. package/dist/cli/commands/wallet-read.d.ts +2 -0
  107. package/dist/cli/commands/wallet-read.js +265 -0
  108. package/dist/cli/context.d.ts +3 -0
  109. package/dist/cli/context.js +75 -0
  110. package/dist/cli/io.d.ts +3 -0
  111. package/dist/cli/io.js +12 -0
  112. package/dist/cli/mining-format.d.ts +5 -0
  113. package/dist/cli/mining-format.js +156 -0
  114. package/dist/cli/mining-json.d.ts +49 -0
  115. package/dist/cli/mining-json.js +89 -0
  116. package/dist/cli/mutation-command-groups.d.ts +15 -0
  117. package/dist/cli/mutation-command-groups.js +71 -0
  118. package/dist/cli/mutation-json.d.ts +430 -0
  119. package/dist/cli/mutation-json.js +311 -0
  120. package/dist/cli/mutation-resolved-json.d.ts +124 -0
  121. package/dist/cli/mutation-resolved-json.js +129 -0
  122. package/dist/cli/mutation-success.d.ts +20 -0
  123. package/dist/cli/mutation-success.js +47 -0
  124. package/dist/cli/mutation-text-format.d.ts +22 -0
  125. package/dist/cli/mutation-text-format.js +171 -0
  126. package/dist/cli/mutation-text-write.d.ts +13 -0
  127. package/dist/cli/mutation-text-write.js +16 -0
  128. package/dist/cli/output.d.ts +185 -0
  129. package/dist/cli/output.js +1085 -0
  130. package/dist/cli/parse.d.ts +3 -0
  131. package/dist/cli/parse.js +971 -0
  132. package/dist/cli/preview-json.d.ts +416 -0
  133. package/dist/cli/preview-json.js +293 -0
  134. package/dist/cli/prompt.d.ts +3 -0
  135. package/dist/cli/prompt.js +33 -0
  136. package/dist/cli/read-json.d.ts +187 -0
  137. package/dist/cli/read-json.js +675 -0
  138. package/dist/cli/runner.d.ts +2 -0
  139. package/dist/cli/runner.js +129 -0
  140. package/dist/cli/signals.d.ts +3 -0
  141. package/dist/cli/signals.js +63 -0
  142. package/dist/cli/status-format.d.ts +2 -0
  143. package/dist/cli/status-format.js +48 -0
  144. package/dist/cli/types.d.ts +148 -0
  145. package/dist/cli/types.js +2 -0
  146. package/dist/cli/wallet-format.d.ts +29 -0
  147. package/dist/cli/wallet-format.js +637 -0
  148. package/dist/cli/workflow-hints.d.ts +13 -0
  149. package/dist/cli/workflow-hints.js +94 -0
  150. package/dist/cli-runner.d.ts +3 -0
  151. package/dist/cli-runner.js +3 -0
  152. package/dist/cli.d.ts +2 -0
  153. package/dist/cli.js +6 -0
  154. package/dist/client/default-client.d.ts +11 -0
  155. package/dist/client/default-client.js +118 -0
  156. package/dist/client/factory.d.ts +2 -0
  157. package/dist/client/factory.js +15 -0
  158. package/dist/client/initialization.d.ts +6 -0
  159. package/dist/client/initialization.js +30 -0
  160. package/dist/client/persistence.d.ts +5 -0
  161. package/dist/client/persistence.js +28 -0
  162. package/dist/client/store-adapter.d.ts +3 -0
  163. package/dist/client/store-adapter.js +20 -0
  164. package/dist/client.d.ts +2 -0
  165. package/dist/client.js +2 -0
  166. package/dist/index.d.ts +2 -0
  167. package/dist/index.js +1 -0
  168. package/dist/passive-status.d.ts +36 -0
  169. package/dist/passive-status.js +100 -0
  170. package/dist/sqlite/better-sqlite3.d.ts +26 -0
  171. package/dist/sqlite/better-sqlite3.js +4 -0
  172. package/dist/sqlite/checkpoints.d.ts +11 -0
  173. package/dist/sqlite/checkpoints.js +27 -0
  174. package/dist/sqlite/driver.d.ts +17 -0
  175. package/dist/sqlite/driver.js +98 -0
  176. package/dist/sqlite/index.d.ts +4 -0
  177. package/dist/sqlite/index.js +9 -0
  178. package/dist/sqlite/migrate.d.ts +2 -0
  179. package/dist/sqlite/migrate.js +37 -0
  180. package/dist/sqlite/store.d.ts +3 -0
  181. package/dist/sqlite/store.js +122 -0
  182. package/dist/sqlite/tip-meta.d.ts +26 -0
  183. package/dist/sqlite/tip-meta.js +97 -0
  184. package/dist/sqlite/types.d.ts +10 -0
  185. package/dist/sqlite/types.js +1 -0
  186. package/dist/types.d.ts +55 -0
  187. package/dist/types.js +1 -0
  188. package/dist/wallet/archive.d.ts +4 -0
  189. package/dist/wallet/archive.js +39 -0
  190. package/dist/wallet/cogop/constants.d.ts +32 -0
  191. package/dist/wallet/cogop/constants.js +32 -0
  192. package/dist/wallet/cogop/index.d.ts +32 -0
  193. package/dist/wallet/cogop/index.js +213 -0
  194. package/dist/wallet/cogop/numeric.d.ts +3 -0
  195. package/dist/wallet/cogop/numeric.js +24 -0
  196. package/dist/wallet/cogop/scriptpubkey.d.ts +2 -0
  197. package/dist/wallet/cogop/scriptpubkey.js +13 -0
  198. package/dist/wallet/cogop/validate-name.d.ts +2 -0
  199. package/dist/wallet/cogop/validate-name.js +18 -0
  200. package/dist/wallet/fs/atomic.d.ts +6 -0
  201. package/dist/wallet/fs/atomic.js +46 -0
  202. package/dist/wallet/fs/lock.d.ts +19 -0
  203. package/dist/wallet/fs/lock.js +61 -0
  204. package/dist/wallet/fs/status-file.d.ts +1 -0
  205. package/dist/wallet/fs/status-file.js +4 -0
  206. package/dist/wallet/lifecycle.d.ts +193 -0
  207. package/dist/wallet/lifecycle.js +1475 -0
  208. package/dist/wallet/material.d.ts +45 -0
  209. package/dist/wallet/material.js +118 -0
  210. package/dist/wallet/mining/config.d.ts +18 -0
  211. package/dist/wallet/mining/config.js +44 -0
  212. package/dist/wallet/mining/constants.d.ts +24 -0
  213. package/dist/wallet/mining/constants.js +24 -0
  214. package/dist/wallet/mining/control.d.ts +53 -0
  215. package/dist/wallet/mining/control.js +758 -0
  216. package/dist/wallet/mining/coordination.d.ts +40 -0
  217. package/dist/wallet/mining/coordination.js +121 -0
  218. package/dist/wallet/mining/hook-protocol.d.ts +47 -0
  219. package/dist/wallet/mining/hook-protocol.js +161 -0
  220. package/dist/wallet/mining/hook-runner.d.ts +1 -0
  221. package/dist/wallet/mining/hook-runner.js +52 -0
  222. package/dist/wallet/mining/hooks.d.ts +38 -0
  223. package/dist/wallet/mining/hooks.js +520 -0
  224. package/dist/wallet/mining/index.d.ts +8 -0
  225. package/dist/wallet/mining/index.js +6 -0
  226. package/dist/wallet/mining/runner.d.ts +155 -0
  227. package/dist/wallet/mining/runner.js +2574 -0
  228. package/dist/wallet/mining/runtime-artifacts.d.ts +17 -0
  229. package/dist/wallet/mining/runtime-artifacts.js +166 -0
  230. package/dist/wallet/mining/sentences.d.ts +23 -0
  231. package/dist/wallet/mining/sentences.js +281 -0
  232. package/dist/wallet/mining/state.d.ts +9 -0
  233. package/dist/wallet/mining/state.js +75 -0
  234. package/dist/wallet/mining/types.d.ts +141 -0
  235. package/dist/wallet/mining/types.js +1 -0
  236. package/dist/wallet/mining/visualizer.d.ts +19 -0
  237. package/dist/wallet/mining/visualizer.js +134 -0
  238. package/dist/wallet/mining/worker-main.d.ts +1 -0
  239. package/dist/wallet/mining/worker-main.js +17 -0
  240. package/dist/wallet/read/context.d.ts +20 -0
  241. package/dist/wallet/read/context.js +532 -0
  242. package/dist/wallet/read/filter.d.ts +9 -0
  243. package/dist/wallet/read/filter.js +42 -0
  244. package/dist/wallet/read/index.d.ts +4 -0
  245. package/dist/wallet/read/index.js +3 -0
  246. package/dist/wallet/read/project.d.ts +11 -0
  247. package/dist/wallet/read/project.js +300 -0
  248. package/dist/wallet/read/types.d.ts +144 -0
  249. package/dist/wallet/read/types.js +1 -0
  250. package/dist/wallet/runtime.d.ts +26 -0
  251. package/dist/wallet/runtime.js +28 -0
  252. package/dist/wallet/state/crypto.d.ts +31 -0
  253. package/dist/wallet/state/crypto.js +127 -0
  254. package/dist/wallet/state/provider.d.ts +37 -0
  255. package/dist/wallet/state/provider.js +312 -0
  256. package/dist/wallet/state/session.d.ts +12 -0
  257. package/dist/wallet/state/session.js +23 -0
  258. package/dist/wallet/state/storage.d.ts +19 -0
  259. package/dist/wallet/state/storage.js +55 -0
  260. package/dist/wallet/tx/anchor.d.ts +40 -0
  261. package/dist/wallet/tx/anchor.js +1210 -0
  262. package/dist/wallet/tx/cog.d.ts +92 -0
  263. package/dist/wallet/tx/cog.js +1055 -0
  264. package/dist/wallet/tx/common.d.ts +89 -0
  265. package/dist/wallet/tx/common.js +156 -0
  266. package/dist/wallet/tx/confirm.d.ts +15 -0
  267. package/dist/wallet/tx/confirm.js +24 -0
  268. package/dist/wallet/tx/domain-admin.d.ts +105 -0
  269. package/dist/wallet/tx/domain-admin.js +869 -0
  270. package/dist/wallet/tx/domain-market.d.ts +112 -0
  271. package/dist/wallet/tx/domain-market.js +1365 -0
  272. package/dist/wallet/tx/field.d.ts +101 -0
  273. package/dist/wallet/tx/field.js +1853 -0
  274. package/dist/wallet/tx/identity-selector.d.ts +12 -0
  275. package/dist/wallet/tx/identity-selector.js +52 -0
  276. package/dist/wallet/tx/index.d.ts +7 -0
  277. package/dist/wallet/tx/index.js +7 -0
  278. package/dist/wallet/tx/journal.d.ts +5 -0
  279. package/dist/wallet/tx/journal.js +31 -0
  280. package/dist/wallet/tx/register.d.ts +68 -0
  281. package/dist/wallet/tx/register.js +952 -0
  282. package/dist/wallet/tx/reputation.d.ts +72 -0
  283. package/dist/wallet/tx/reputation.js +693 -0
  284. package/dist/wallet/tx/targets.d.ts +7 -0
  285. package/dist/wallet/tx/targets.js +122 -0
  286. package/dist/wallet/types.d.ts +249 -0
  287. package/dist/wallet/types.js +1 -0
  288. package/dist/writing_quotes.json +1654 -0
  289. package/package.json +78 -0
@@ -0,0 +1,637 @@
1
+ import { findDomainField, findWalletDomain, formatFieldFormat, listDomainFields, listWalletLocks, } from "../wallet/read/index.js";
2
+ import { formatMiningSummaryLine } from "./mining-format.js";
3
+ import { getBootstrapSyncNextStep } from "./workflow-hints.js";
4
+ function formatCogAmount(value) {
5
+ const sign = value < 0n ? "-" : "";
6
+ const absolute = value < 0n ? -value : value;
7
+ const whole = absolute / 100000000n;
8
+ const fraction = absolute % 100000000n;
9
+ return `${sign}${whole.toString()}.${fraction.toString().padStart(8, "0")} COG`;
10
+ }
11
+ function formatServiceHealth(health) {
12
+ return health.replaceAll("-", " ");
13
+ }
14
+ function formatMaybe(value) {
15
+ return value === null ? "unavailable" : String(value);
16
+ }
17
+ function formatIndexerTruthSource(source) {
18
+ switch (source) {
19
+ case "lease":
20
+ return "coherent snapshot lease";
21
+ case "probe":
22
+ return "live daemon probe";
23
+ case "status-file":
24
+ return "advisory status file";
25
+ default:
26
+ return "none";
27
+ }
28
+ }
29
+ function formatUnlockExpiry(unlockUntilUnixMs) {
30
+ if (unlockUntilUnixMs === null) {
31
+ return "locked";
32
+ }
33
+ return `unlocked until ${new Date(unlockUntilUnixMs).toISOString()}`;
34
+ }
35
+ function isReputationMutation(mutation) {
36
+ return (mutation.kind === "rep-give" || mutation.kind === "rep-revoke")
37
+ && mutation.recipientDomainName !== undefined
38
+ && mutation.recipientDomainName !== null;
39
+ }
40
+ function formatPendingMutationKind(mutation) {
41
+ if (mutation.kind === "sell" && mutation.priceCogtoshi === 0n) {
42
+ return "unsell";
43
+ }
44
+ if (mutation.kind === "claim" && mutation.preimageHex === "0000000000000000000000000000000000000000000000000000000000000000") {
45
+ return "reclaim";
46
+ }
47
+ if (mutation.kind === "endpoint" && mutation.endpointValueHex === "") {
48
+ return "endpoint-clear";
49
+ }
50
+ if (mutation.kind === "delegate" && mutation.recipientScriptPubKeyHex === null) {
51
+ return "delegate-clear";
52
+ }
53
+ if (mutation.kind === "miner" && mutation.recipientScriptPubKeyHex === null) {
54
+ return "miner-clear";
55
+ }
56
+ return mutation.kind;
57
+ }
58
+ function formatPendingMutationSummaryLabel(mutation) {
59
+ if (isReputationMutation(mutation)) {
60
+ return `${formatPendingMutationKind(mutation)} ${mutation.domainName}->${mutation.recipientDomainName}`;
61
+ }
62
+ return `${formatPendingMutationKind(mutation)}${mutation.domainName === "" ? "" : ` ${mutation.domainName}`}${mutation.fieldName == null ? "" : `.${mutation.fieldName}`}`;
63
+ }
64
+ function formatPendingMutationDomainLabel(mutation) {
65
+ if (isReputationMutation(mutation)) {
66
+ return `${formatPendingMutationKind(mutation)} ${mutation.domainName}->${mutation.recipientDomainName}`;
67
+ }
68
+ const kind = mutation.kind === "endpoint" && mutation.endpointValueHex === ""
69
+ ? "endpoint-clear"
70
+ : mutation.kind === "delegate" && mutation.recipientScriptPubKeyHex === null
71
+ ? "delegate-clear"
72
+ : mutation.kind === "miner" && mutation.recipientScriptPubKeyHex === null
73
+ ? "miner-clear"
74
+ : formatPendingMutationKind(mutation);
75
+ return kind;
76
+ }
77
+ export function getRepairRecommendation(context) {
78
+ if (context.localState.availability === "local-state-corrupt") {
79
+ return "Run `cogcoin repair` to recover local wallet state.";
80
+ }
81
+ if (context.bitcoind.health === "service-version-mismatch"
82
+ || context.bitcoind.health === "wallet-root-mismatch"
83
+ || context.bitcoind.health === "runtime-mismatch"
84
+ || context.bitcoind.health === "replica-missing"
85
+ || context.bitcoind.health === "replica-mismatch"
86
+ || context.bitcoind.health === "failed") {
87
+ return "Run `cogcoin repair` to recover the managed bitcoind service and Core wallet replica.";
88
+ }
89
+ if (context.indexer.health === "failed"
90
+ || context.indexer.health === "schema-mismatch"
91
+ || context.indexer.health === "service-version-mismatch"
92
+ || context.indexer.health === "wallet-root-mismatch") {
93
+ return "Run `cogcoin repair` to recover the managed indexer daemon and local indexer artifacts.";
94
+ }
95
+ if (context.localState.state?.miningState.state === "repair-required"
96
+ || context.localState.state?.proactiveFamilies.some((family) => family.status === "repair-required")
97
+ || context.localState.state?.domains.some((domain) => domain.localAnchorIntent === "repair-required")
98
+ || (context.localState.state?.pendingMutations ?? []).some((mutation) => mutation.status === "repair-required")) {
99
+ return "Run `cogcoin repair` before relying on local wallet state.";
100
+ }
101
+ return null;
102
+ }
103
+ export function getMutationRecommendation(context) {
104
+ const unresolvedFamily = (context.localState.state?.proactiveFamilies ?? []).find((family) => (family.type === "anchor" || family.type === "field")
105
+ && (family.status === "broadcast-unknown" || family.status === "repair-required"));
106
+ if (unresolvedFamily !== undefined) {
107
+ if (unresolvedFamily.status === "repair-required") {
108
+ return unresolvedFamily.type === "field"
109
+ ? "Run `cogcoin repair` before starting another field family."
110
+ : "Run `cogcoin repair` before starting another anchor family.";
111
+ }
112
+ return unresolvedFamily.type === "field"
113
+ ? `Rerun \`cogcoin field create ${unresolvedFamily.domainName} ${unresolvedFamily.fieldName} ...\` to reconcile the pending field family, or run \`cogcoin repair\` if it remains unresolved.`
114
+ : `Rerun \`cogcoin anchor ${unresolvedFamily.domainName}\` to reconcile the pending anchor family, or run \`cogcoin repair\` if it remains unresolved.`;
115
+ }
116
+ const pendingMutations = context.localState.state?.pendingMutations ?? [];
117
+ const unresolved = pendingMutations.find((mutation) => mutation.status === "broadcast-unknown" || mutation.status === "repair-required");
118
+ if (unresolved === undefined) {
119
+ return null;
120
+ }
121
+ if (unresolved.status === "repair-required") {
122
+ return "Run `cogcoin repair` before starting another mutation.";
123
+ }
124
+ if (unresolved.kind === "register") {
125
+ return `Rerun \`cogcoin register ${unresolved.domainName}\` to reconcile the pending registration, or run \`cogcoin repair\` if it remains unresolved.`;
126
+ }
127
+ if (unresolved.kind === "transfer") {
128
+ return `Rerun \`cogcoin transfer ${unresolved.domainName}\` with the same target to reconcile the pending transfer, or run \`cogcoin repair\` if it remains unresolved.`;
129
+ }
130
+ if (unresolved.kind === "sell") {
131
+ const command = unresolved.priceCogtoshi === 0n ? "unsell" : "sell";
132
+ return `Rerun \`cogcoin ${command} ${unresolved.domainName}\` to reconcile the pending listing change, or run \`cogcoin repair\` if it remains unresolved.`;
133
+ }
134
+ if (unresolved.kind === "buy") {
135
+ return `Rerun \`cogcoin buy ${unresolved.domainName}\` to reconcile the pending purchase, or run \`cogcoin repair\` if it remains unresolved.`;
136
+ }
137
+ if (unresolved.kind === "endpoint") {
138
+ return unresolved.endpointValueHex === ""
139
+ ? `Rerun \`cogcoin domain endpoint clear ${unresolved.domainName}\` to reconcile the pending endpoint clear, or run \`cogcoin repair\` if it remains unresolved.`
140
+ : `Rerun \`cogcoin domain endpoint set ${unresolved.domainName} ...\` to reconcile the pending endpoint update, or run \`cogcoin repair\` if it remains unresolved.`;
141
+ }
142
+ if (unresolved.kind === "delegate") {
143
+ return unresolved.recipientScriptPubKeyHex === null
144
+ ? `Rerun \`cogcoin domain delegate clear ${unresolved.domainName}\` to reconcile the pending delegate clear, or run \`cogcoin repair\` if it remains unresolved.`
145
+ : `Rerun \`cogcoin domain delegate set ${unresolved.domainName} ...\` to reconcile the pending delegate update, or run \`cogcoin repair\` if it remains unresolved.`;
146
+ }
147
+ if (unresolved.kind === "miner") {
148
+ return unresolved.recipientScriptPubKeyHex === null
149
+ ? `Rerun \`cogcoin domain miner clear ${unresolved.domainName}\` to reconcile the pending miner clear, or run \`cogcoin repair\` if it remains unresolved.`
150
+ : `Rerun \`cogcoin domain miner set ${unresolved.domainName} ...\` to reconcile the pending miner update, or run \`cogcoin repair\` if it remains unresolved.`;
151
+ }
152
+ if (unresolved.kind === "canonical") {
153
+ return `Rerun \`cogcoin domain canonical ${unresolved.domainName}\` to reconcile the pending canonical update, or run \`cogcoin repair\` if it remains unresolved.`;
154
+ }
155
+ if (unresolved.kind === "field-create") {
156
+ return `Rerun \`cogcoin field create ${unresolved.domainName} ${unresolved.fieldName} ...\` to reconcile the pending field creation, or run \`cogcoin repair\` if it remains unresolved.`;
157
+ }
158
+ if (unresolved.kind === "field-set") {
159
+ return `Rerun \`cogcoin field set ${unresolved.domainName} ${unresolved.fieldName} ...\` to reconcile the pending field update, or run \`cogcoin repair\` if it remains unresolved.`;
160
+ }
161
+ if (unresolved.kind === "field-clear") {
162
+ return `Rerun \`cogcoin field clear ${unresolved.domainName} ${unresolved.fieldName}\` to reconcile the pending field clear, or run \`cogcoin repair\` if it remains unresolved.`;
163
+ }
164
+ if (unresolved.kind === "rep-give") {
165
+ return `Rerun \`cogcoin rep give ${unresolved.domainName} ${unresolved.recipientDomainName ?? "..."} ...\` to reconcile the pending reputation support, or run \`cogcoin repair\` if it remains unresolved.`;
166
+ }
167
+ if (unresolved.kind === "rep-revoke") {
168
+ return `Rerun \`cogcoin rep revoke ${unresolved.domainName} ${unresolved.recipientDomainName ?? "..."} ...\` to reconcile the pending reputation revoke, or run \`cogcoin repair\` if it remains unresolved.`;
169
+ }
170
+ if (unresolved.kind === "send") {
171
+ return "Rerun the same `cogcoin send ...` command to reconcile the pending transfer, or run `cogcoin repair` if it remains unresolved.";
172
+ }
173
+ if (unresolved.kind === "lock") {
174
+ return "Rerun the same `cogcoin cog lock ...` command to reconcile the pending lock, or run `cogcoin repair` if it remains unresolved.";
175
+ }
176
+ return unresolved.preimageHex === "0000000000000000000000000000000000000000000000000000000000000000"
177
+ ? "Rerun the same `cogcoin reclaim ...` command to reconcile the pending reclaim, or run `cogcoin repair` if it remains unresolved."
178
+ : "Rerun the same `cogcoin claim ...` command to reconcile the pending claim, or run `cogcoin repair` if it remains unresolved.";
179
+ }
180
+ function appendPendingMutationSummary(lines, context) {
181
+ const pendingFamilies = (context.localState.state?.proactiveFamilies ?? [])
182
+ .filter((family) => (family.type === "anchor" || family.type === "field")
183
+ && family.status !== "confirmed"
184
+ && family.status !== "canceled");
185
+ const pendingMutations = (context.localState.state?.pendingMutations ?? [])
186
+ .filter((mutation) => mutation.status !== "confirmed" && mutation.status !== "canceled");
187
+ if (pendingFamilies.length === 0 && pendingMutations.length === 0) {
188
+ lines.push("Pending mutations: none");
189
+ return;
190
+ }
191
+ for (const family of pendingFamilies) {
192
+ const label = family.type === "field"
193
+ ? `Pending field family: ${family.domainName ?? "unknown"}.${family.fieldName ?? "unknown"}`
194
+ : `Pending anchor family: ${family.domainName ?? "unknown"}`;
195
+ lines.push(`${label} ${family.status}${family.currentStep === null || family.currentStep === undefined ? "" : ` step ${family.currentStep}`}${family.reservedDedicatedIndex == null ? "" : ` index ${family.reservedDedicatedIndex}`}`);
196
+ }
197
+ for (const mutation of pendingMutations) {
198
+ lines.push(`Pending mutation: ${formatPendingMutationSummaryLabel(mutation)} ${mutation.status} sender spk:${mutation.senderScriptPubKeyHex}${mutation.priceCogtoshi === undefined || mutation.priceCogtoshi === null ? "" : ` price ${formatCogAmount(mutation.priceCogtoshi)}`}${mutation.amountCogtoshi === undefined || mutation.amountCogtoshi === null ? "" : ` amount ${formatCogAmount(mutation.amountCogtoshi)}`}${isReputationMutation(mutation) ? "" : mutation.recipientDomainName === undefined || mutation.recipientDomainName === null ? "" : ` domain ${mutation.recipientDomainName}`}${mutation.lockId === undefined || mutation.lockId === null ? "" : ` lock ${mutation.lockId}`}${mutation.recipientScriptPubKeyHex === undefined || mutation.recipientScriptPubKeyHex === null ? "" : ` recipient spk:${mutation.recipientScriptPubKeyHex}`}${mutation.kind === "endpoint" ? (mutation.endpointValueHex === "" ? " endpoint clear" : ` endpoint-bytes ${(mutation.endpointValueHex?.length ?? 0) / 2}`) : ""}${mutation.kind === "field-create" || mutation.kind === "field-set" ? ` format ${formatFieldFormat(mutation.fieldFormat ?? 0)}` : ""}${mutation.kind === "field-clear" ? " clear" : ""}${mutation.reviewPayloadHex === undefined || mutation.reviewPayloadHex === null ? "" : " review"}`);
199
+ }
200
+ }
201
+ function listPendingDomainMutations(context, domainName) {
202
+ return (context.localState.state?.pendingMutations ?? [])
203
+ .filter((mutation) => (mutation.kind === "register"
204
+ || mutation.kind === "transfer"
205
+ || mutation.kind === "sell"
206
+ || mutation.kind === "buy"
207
+ || mutation.kind === "endpoint"
208
+ || mutation.kind === "delegate"
209
+ || mutation.kind === "miner"
210
+ || mutation.kind === "canonical"
211
+ || mutation.kind === "field-create"
212
+ || mutation.kind === "field-set"
213
+ || mutation.kind === "field-clear")
214
+ && mutation.domainName === domainName
215
+ && mutation.status !== "confirmed"
216
+ && mutation.status !== "canceled");
217
+ }
218
+ function listPendingAnchorFamilies(context, domainName) {
219
+ return (context.localState.state?.proactiveFamilies ?? [])
220
+ .filter((family) => family.type === "anchor"
221
+ && family.domainName === domainName
222
+ && family.status !== "confirmed"
223
+ && family.status !== "canceled");
224
+ }
225
+ function listPendingFieldFamilies(context, domainName) {
226
+ return (context.localState.state?.proactiveFamilies ?? [])
227
+ .filter((family) => family.type === "field"
228
+ && family.domainName === domainName
229
+ && family.status !== "confirmed"
230
+ && family.status !== "canceled");
231
+ }
232
+ function listPendingDomainShowMutations(context, domainName) {
233
+ return (context.localState.state?.pendingMutations ?? [])
234
+ .filter((mutation) => (mutation.kind === "register"
235
+ || mutation.kind === "transfer"
236
+ || mutation.kind === "sell"
237
+ || mutation.kind === "buy"
238
+ || mutation.kind === "endpoint"
239
+ || mutation.kind === "delegate"
240
+ || mutation.kind === "miner"
241
+ || mutation.kind === "canonical"
242
+ || mutation.kind === "field-create"
243
+ || mutation.kind === "field-set"
244
+ || mutation.kind === "field-clear"
245
+ || mutation.kind === "rep-give"
246
+ || mutation.kind === "rep-revoke")
247
+ && (mutation.domainName === domainName || mutation.recipientDomainName === domainName)
248
+ && mutation.status !== "confirmed"
249
+ && mutation.status !== "canceled");
250
+ }
251
+ function listPendingFieldMutations(context, domainName, fieldName) {
252
+ return (context.localState.state?.pendingMutations ?? [])
253
+ .filter((mutation) => (mutation.kind === "field-create" || mutation.kind === "field-set" || mutation.kind === "field-clear")
254
+ && mutation.domainName === domainName
255
+ && (fieldName === undefined || mutation.fieldName === fieldName)
256
+ && mutation.status !== "confirmed"
257
+ && mutation.status !== "canceled");
258
+ }
259
+ function appendServiceSummary(lines, context) {
260
+ lines.push(`Managed bitcoind: ${formatServiceHealth(context.bitcoind.health)}`);
261
+ if (context.bitcoind.message !== null) {
262
+ lines.push(`Managed bitcoind note: ${context.bitcoind.message}`);
263
+ }
264
+ lines.push(`Bitcoin service: ${formatServiceHealth(context.nodeHealth)}`);
265
+ if (context.nodeStatus !== null) {
266
+ lines.push(`Bitcoin best height: ${formatMaybe(context.nodeStatus.nodeBestHeight)}`);
267
+ lines.push(`Bitcoin headers: ${formatMaybe(context.nodeStatus.nodeHeaderHeight)}`);
268
+ }
269
+ if (context.nodeMessage !== null) {
270
+ lines.push(`Bitcoin note: ${context.nodeMessage}`);
271
+ }
272
+ lines.push(`Indexer service: ${formatServiceHealth(context.indexer.health)}`);
273
+ lines.push(`Indexer truth source: ${formatIndexerTruthSource(context.indexer.source)}`);
274
+ if (context.indexer.daemonInstanceId !== null) {
275
+ lines.push(`Indexer daemon instance: ${context.indexer.daemonInstanceId}`);
276
+ }
277
+ if (context.indexer.snapshotSeq !== null) {
278
+ lines.push(`Indexer snapshot sequence: ${context.indexer.snapshotSeq}`);
279
+ }
280
+ if (context.indexer.status?.reorgDepth !== null && context.indexer.status?.reorgDepth !== undefined) {
281
+ lines.push(`Indexer reorg depth: ${context.indexer.status.reorgDepth}`);
282
+ }
283
+ if (context.indexer.snapshotTip !== null) {
284
+ lines.push(`Indexer tip height: ${context.indexer.snapshotTip.height}`);
285
+ }
286
+ else {
287
+ lines.push("Indexer tip height: unavailable");
288
+ }
289
+ if (context.indexer.message !== null) {
290
+ lines.push(`Indexer note: ${context.indexer.message}`);
291
+ }
292
+ if (context.mining !== undefined) {
293
+ lines.push(`Mining: ${formatMiningSummaryLine(context.mining)}`);
294
+ if (context.mining.runtime.note !== null) {
295
+ lines.push(`Mining note: ${context.mining.runtime.note}`);
296
+ }
297
+ }
298
+ }
299
+ function appendWalletAvailability(lines, context) {
300
+ lines.push(`Wallet state: ${context.localState.availability}`);
301
+ lines.push(`Wallet root: ${context.model?.walletRootId ?? context.localState.walletRootId ?? context.nodeStatus?.walletRootId ?? "none"}`);
302
+ lines.push(`Wallet unlock: ${formatUnlockExpiry(context.localState.unlockUntilUnixMs)}`);
303
+ if (context.localState.message !== null) {
304
+ lines.push(`Wallet note: ${context.localState.message}`);
305
+ }
306
+ const nodeStatus = context.nodeStatus;
307
+ const replica = nodeStatus?.walletReplica ?? null;
308
+ if (replica !== null) {
309
+ lines.push(`Managed Core wallet: ${replica.proofStatus ?? "not-proven"}`);
310
+ }
311
+ if (nodeStatus?.walletReplicaMessage) {
312
+ lines.push(`Managed Core note: ${nodeStatus.walletReplicaMessage}`);
313
+ }
314
+ const repairRecommendation = getRepairRecommendation(context);
315
+ if (repairRecommendation !== null) {
316
+ lines.push(`Recommended next step: ${repairRecommendation}`);
317
+ }
318
+ else {
319
+ const bootstrapSync = getBootstrapSyncNextStep(context);
320
+ if (bootstrapSync !== null) {
321
+ lines.push("Recommended next step: Run `cogcoin sync` to bootstrap assumeutxo and the managed Bitcoin/indexer state.");
322
+ }
323
+ }
324
+ const mutationRecommendation = getMutationRecommendation(context);
325
+ if (mutationRecommendation !== null) {
326
+ lines.push(`Mutation note: ${mutationRecommendation}`);
327
+ }
328
+ }
329
+ export function formatWalletOverviewReport(context) {
330
+ const lines = [
331
+ "Cogcoin Status",
332
+ `DB path: ${context.databasePath}`,
333
+ `Bitcoin datadir: ${context.dataDir}`,
334
+ ];
335
+ appendWalletAvailability(lines, context);
336
+ appendServiceSummary(lines, context);
337
+ if (context.model !== null) {
338
+ lines.push(`Local identities: ${context.model.identities.length}`);
339
+ lines.push(`Locally related domains: ${context.model.domains.length}`);
340
+ lines.push(`Read-only identities: ${context.model.readOnlyIdentityCount}`);
341
+ }
342
+ else {
343
+ lines.push("Wallet-derived sections: unavailable");
344
+ }
345
+ appendPendingMutationSummary(lines, context);
346
+ return lines.join("\n");
347
+ }
348
+ export function formatDetailedWalletStatusReport(context) {
349
+ const lines = ["Cogcoin Wallet Status"];
350
+ appendWalletAvailability(lines, context);
351
+ appendServiceSummary(lines, context);
352
+ if (context.model === null) {
353
+ lines.push("Wallet details are unavailable until the encrypted wallet state can be read.");
354
+ return lines.join("\n");
355
+ }
356
+ lines.push(`Funding identity: ${context.model.fundingIdentity?.selectors[0] ?? "unavailable"}`);
357
+ lines.push(`Funding address: ${context.model.fundingIdentity?.address ?? "unavailable"}`);
358
+ lines.push(`Controlled identities: ${context.model.identities.length}`);
359
+ lines.push(`Locally related domains: ${context.model.domains.length}`);
360
+ lines.push(`Read-only identities: ${context.model.readOnlyIdentityCount}`);
361
+ appendPendingMutationSummary(lines, context);
362
+ return lines.join("\n");
363
+ }
364
+ export function formatFundingAddressReport(context) {
365
+ const lines = ["BTC Funding Address"];
366
+ if (context.model?.fundingIdentity === null || context.model === null) {
367
+ appendWalletAvailability(lines, context);
368
+ return lines.join("\n");
369
+ }
370
+ lines.push(`Selector: ${context.model.fundingIdentity.selectors[0]}`);
371
+ lines.push(`Address: ${context.model.fundingIdentity.address ?? "unavailable"}`);
372
+ lines.push(`ScriptPubKey: spk:${context.model.fundingIdentity.scriptPubKeyHex}`);
373
+ return lines.join("\n");
374
+ }
375
+ export function formatIdentityListReport(context, options = {}) {
376
+ const lines = ["Wallet Identities"];
377
+ if (context.model === null) {
378
+ appendWalletAvailability(lines, context);
379
+ return lines.join("\n");
380
+ }
381
+ const identities = context.model.identities;
382
+ if (identities.length === 0) {
383
+ lines.push("No local identities are recorded yet.");
384
+ return lines.join("\n");
385
+ }
386
+ const limit = options.all ? null : options.limit ?? null;
387
+ const renderedIdentities = limit === null ? identities : identities.slice(0, limit);
388
+ for (const identity of renderedIdentities) {
389
+ const domains = identity.ownedDomainNames.length === 0 ? "none" : identity.ownedDomainNames.join(", ");
390
+ const balance = identity.observedCogBalance === null ? "unavailable" : formatCogAmount(identity.observedCogBalance);
391
+ lines.push(`${identity.selectors[0]} ${identity.effectiveStatus} ${identity.address ?? `spk:${identity.scriptPubKeyHex}`} balance ${balance} domains ${domains} selectors ${identity.selectors.join(", ")}`);
392
+ }
393
+ if (limit !== null && identities.length > limit) {
394
+ lines.push(`Showing first ${renderedIdentities.length} of ${identities.length}. Use --limit <n> or --all for more.`);
395
+ }
396
+ return lines.join("\n");
397
+ }
398
+ export function formatBalanceReport(context) {
399
+ const lines = ["COG Balance"];
400
+ if (context.model === null) {
401
+ appendWalletAvailability(lines, context);
402
+ return lines.join("\n");
403
+ }
404
+ if (context.snapshot === null) {
405
+ lines.push(`Indexer-backed balances are unavailable while the indexer is ${formatServiceHealth(context.indexer.health)}.`);
406
+ return lines.join("\n");
407
+ }
408
+ const spendableTotal = context.model.identities.reduce((sum, identity) => identity.readOnly || identity.observedCogBalance === null
409
+ ? sum
410
+ : sum + identity.observedCogBalance, 0n);
411
+ lines.push(`Spendable total: ${formatCogAmount(spendableTotal)}`);
412
+ for (const identity of context.model.identities) {
413
+ lines.push(`${identity.selectors[0]} ${identity.address ?? `spk:${identity.scriptPubKeyHex}`} ${formatCogAmount(identity.observedCogBalance ?? 0n)}${identity.readOnly ? " read-only" : ""}`);
414
+ }
415
+ for (const mutation of (context.localState.state?.pendingMutations ?? [])
416
+ .filter((entry) => (entry.kind === "send" || entry.kind === "lock" || entry.kind === "claim")
417
+ && entry.status !== "confirmed"
418
+ && entry.status !== "canceled")) {
419
+ const label = mutation.kind === "claim" && mutation.preimageHex === "0000000000000000000000000000000000000000000000000000000000000000"
420
+ ? "reclaim"
421
+ : mutation.kind;
422
+ lines.push(`Pending: ${label} ${mutation.status}${mutation.amountCogtoshi === null || mutation.amountCogtoshi === undefined ? "" : ` ${formatCogAmount(mutation.amountCogtoshi)}`}`);
423
+ }
424
+ return lines.join("\n");
425
+ }
426
+ export function formatLocksReport(context, options = {}) {
427
+ const lines = ["COG Locks"];
428
+ if (context.model === null) {
429
+ appendWalletAvailability(lines, context);
430
+ return lines.join("\n");
431
+ }
432
+ const locks = listWalletLocks(context);
433
+ if (locks === null) {
434
+ lines.push(`Lock state is unavailable while the indexer is ${formatServiceHealth(context.indexer.health)}.`);
435
+ return lines.join("\n");
436
+ }
437
+ let filteredLocks = locks;
438
+ if (options.claimableOnly) {
439
+ filteredLocks = filteredLocks.filter((lock) => lock.claimableNow);
440
+ }
441
+ else if (options.reclaimableOnly) {
442
+ filteredLocks = filteredLocks.filter((lock) => lock.reclaimableNow);
443
+ }
444
+ const totalMatching = filteredLocks.length;
445
+ if (!options.all && options.limit !== null && options.limit !== undefined) {
446
+ filteredLocks = filteredLocks.slice(0, options.limit);
447
+ }
448
+ if (filteredLocks.length === 0) {
449
+ lines.push("No locally related active locks.");
450
+ return lines.join("\n");
451
+ }
452
+ for (const lock of filteredLocks) {
453
+ const role = lock.lockerLocalIndex !== null ? `locker ${lock.lockerLocalIndex}` : "recipient";
454
+ const action = lock.claimableNow
455
+ ? "claimable-now"
456
+ : lock.reclaimableNow
457
+ ? "reclaimable-now"
458
+ : "not-actionable-now";
459
+ lines.push(`lock:${lock.lockId} ${formatCogAmount(lock.amountCogtoshi)} timeout ${lock.timeoutHeight} domain ${lock.recipientDomainName ?? lock.recipientDomainId} ${role} ${action}`);
460
+ }
461
+ for (const mutation of (context.localState.state?.pendingMutations ?? [])
462
+ .filter((entry) => (entry.kind === "lock" || entry.kind === "claim")
463
+ && entry.status !== "confirmed"
464
+ && entry.status !== "canceled")) {
465
+ const label = mutation.kind === "claim" && mutation.preimageHex === "0000000000000000000000000000000000000000000000000000000000000000"
466
+ ? "reclaim"
467
+ : mutation.kind;
468
+ lines.push(`Pending: ${label} ${mutation.status}${mutation.lockId === null || mutation.lockId === undefined ? "" : ` lock:${mutation.lockId}`}${mutation.recipientDomainName === null || mutation.recipientDomainName === undefined ? "" : ` domain ${mutation.recipientDomainName}`}`);
469
+ }
470
+ if (!options.all && options.limit !== null && options.limit !== undefined && totalMatching > options.limit) {
471
+ lines.push(`Showing first ${filteredLocks.length} of ${totalMatching}. Use --limit <n> or --all for more.`);
472
+ }
473
+ return lines.join("\n");
474
+ }
475
+ export function formatDomainsReport(context, options = {}) {
476
+ const lines = ["Domains"];
477
+ if (context.model === null) {
478
+ appendWalletAvailability(lines, context);
479
+ return lines.join("\n");
480
+ }
481
+ const visibleDomains = options.domains ?? context.model.domains;
482
+ if (visibleDomains.length === 0) {
483
+ if ((options.activeFilters?.length ?? 0) > 0) {
484
+ lines.push(`No locally related domains matched the active filters (${options.activeFilters.join(", ")}).`);
485
+ return lines.join("\n");
486
+ }
487
+ lines.push("No locally related domains.");
488
+ return lines.join("\n");
489
+ }
490
+ const renderedDomains = options.all || options.limit === null || options.limit === undefined
491
+ ? visibleDomains
492
+ : visibleDomains.slice(0, options.limit);
493
+ for (const domain of renderedDomains) {
494
+ const pending = listPendingDomainMutations(context, domain.name);
495
+ const pendingAnchors = listPendingAnchorFamilies(context, domain.name);
496
+ const pendingFieldFamilies = listPendingFieldFamilies(context, domain.name);
497
+ const pendingFieldMutations = listPendingFieldMutations(context, domain.name);
498
+ const pendingText = pending.length === 0
499
+ ? ""
500
+ : ` pending ${pending.map((mutation) => mutation.kind === "sell" && mutation.priceCogtoshi === 0n
501
+ ? `unsell:${mutation.status}`
502
+ : mutation.kind === "endpoint" && mutation.endpointValueHex === ""
503
+ ? `endpoint-clear:${mutation.status}`
504
+ : mutation.kind === "delegate" && mutation.recipientScriptPubKeyHex === null
505
+ ? `delegate-clear:${mutation.status}`
506
+ : mutation.kind === "miner" && mutation.recipientScriptPubKeyHex === null
507
+ ? `miner-clear:${mutation.status}`
508
+ : `${mutation.kind}:${mutation.status}`).join(",")}`;
509
+ const pendingFieldsText = pendingFieldMutations.length === 0 && pendingFieldFamilies.length === 0
510
+ ? ""
511
+ : ` field-pending ${[
512
+ ...pendingFieldMutations.map((mutation) => `${mutation.fieldName}:${mutation.kind}:${mutation.status}`),
513
+ ...pendingFieldFamilies.map((family) => `${family.fieldName}:family:${family.status}${family.currentStep == null ? "" : `:${family.currentStep}`}`),
514
+ ].join(",")}`;
515
+ const anchorText = pendingAnchors.length === 0 && (domain.localAnchorIntent === null || domain.localAnchorIntent === "none")
516
+ ? ""
517
+ : ` anchor ${(domain.localAnchorIntent === null || domain.localAnchorIntent === "none")
518
+ ? pendingAnchors.map((family) => `${family.currentStep ?? "reserved"}:${family.status}`).join(",")
519
+ : domain.localAnchorIntent}`;
520
+ lines.push(`${domain.name} ${domain.chainStatus} ${domain.localRelationship} owner ${domain.ownerLocalIndex === null ? (domain.ownerAddress ?? domain.ownerScriptPubKeyHex ?? "unknown") : `id:${domain.ownerLocalIndex}`} fields ${formatMaybe(domain.fieldCount)}${domain.readOnly ? " read-only" : ""}${anchorText}${pendingText}${pendingFieldsText}`);
521
+ }
522
+ if (!options.all && options.limit !== null && options.limit !== undefined && visibleDomains.length > options.limit) {
523
+ lines.push(`Showing first ${renderedDomains.length} of ${visibleDomains.length}. Use --limit <n> or --all for more.`);
524
+ }
525
+ return lines.join("\n");
526
+ }
527
+ export function formatDomainReport(context, domainName) {
528
+ const lines = [`Domain: ${domainName}`];
529
+ if (context.snapshot === null && context.model?.domains.find((domain) => domain.name === domainName) === undefined) {
530
+ lines.push(`Domain state is unavailable while the indexer is ${formatServiceHealth(context.indexer.health)}.`);
531
+ return lines.join("\n");
532
+ }
533
+ const view = findWalletDomain(context, domainName);
534
+ if (view === null) {
535
+ lines.push("Domain not found.");
536
+ return lines.join("\n");
537
+ }
538
+ lines.push(`Domain ID: ${formatMaybe(view.domain.domainId)}`);
539
+ lines.push(`Anchored: ${view.domain.anchored === null ? "unknown" : (view.domain.anchored ? "yes" : "no")}`);
540
+ lines.push(`Owner: ${view.domain.ownerLocalIndex === null ? (view.domain.ownerAddress ?? view.domain.ownerScriptPubKeyHex ?? "unknown") : `id:${view.domain.ownerLocalIndex}`}`);
541
+ lines.push(`Local relationship: ${view.localRelationship}`);
542
+ lines.push(`Listing price: ${view.domain.listingPriceCogtoshi === null ? "none" : formatCogAmount(view.domain.listingPriceCogtoshi)}`);
543
+ lines.push(`Field count: ${formatMaybe(view.domain.fieldCount)}`);
544
+ if (view.domain.selfStakeCogtoshi !== null
545
+ || view.domain.supportedStakeCogtoshi !== null
546
+ || view.domain.totalSupportedCogtoshi !== null
547
+ || view.domain.totalRevokedCogtoshi !== null) {
548
+ lines.push(`Reputation self-stake: ${view.domain.selfStakeCogtoshi === null ? "unavailable" : formatCogAmount(view.domain.selfStakeCogtoshi)}`);
549
+ lines.push(`Reputation supported stake: ${view.domain.supportedStakeCogtoshi === null ? "unavailable" : formatCogAmount(view.domain.supportedStakeCogtoshi)}`);
550
+ lines.push(`Reputation total supported: ${view.domain.totalSupportedCogtoshi === null ? "unavailable" : formatCogAmount(view.domain.totalSupportedCogtoshi)}`);
551
+ lines.push(`Reputation total revoked: ${view.domain.totalRevokedCogtoshi === null ? "unavailable" : formatCogAmount(view.domain.totalRevokedCogtoshi)}`);
552
+ }
553
+ lines.push(`Local anchor intent: ${view.domain.localAnchorIntent ?? "none"}`);
554
+ lines.push(`Delegate: ${view.domain.delegateScriptPubKeyHex ?? "none"}`);
555
+ lines.push(`Designated miner: ${view.domain.minerScriptPubKeyHex ?? "none"}`);
556
+ lines.push(`Endpoint: ${view.domain.endpointText ?? "none"}`);
557
+ lines.push(`Founding message: ${view.domain.foundingMessageText ?? "none"}`);
558
+ for (const family of listPendingAnchorFamilies(context, domainName)) {
559
+ lines.push(`Pending anchor family: ${family.status}${family.currentStep == null ? "" : ` step ${family.currentStep}`}${family.reservedDedicatedIndex == null ? "" : ` index ${family.reservedDedicatedIndex}`}`);
560
+ }
561
+ for (const family of listPendingFieldFamilies(context, domainName)) {
562
+ lines.push(`Pending field family: ${family.fieldName ?? "unknown"} ${family.status}${family.currentStep == null ? "" : ` step ${family.currentStep}`}`);
563
+ }
564
+ for (const mutation of listPendingDomainShowMutations(context, domainName)) {
565
+ lines.push(`Pending mutation: ${formatPendingMutationDomainLabel(mutation)} ${mutation.status}`);
566
+ }
567
+ for (const mutation of listPendingFieldMutations(context, domainName)) {
568
+ lines.push(`Pending field mutation: ${mutation.fieldName ?? "unknown"} ${mutation.kind} ${mutation.status}`);
569
+ }
570
+ return lines.join("\n");
571
+ }
572
+ function renderFieldLine(field) {
573
+ return `${field.name} id ${field.fieldId} ${field.permanent ? "permanent" : "mutable"} ${field.hasValue ? formatFieldFormat(field.format) : "empty"} ${field.preview ?? "(no value)"}`;
574
+ }
575
+ export function formatFieldsReport(context, domainName, options = {}) {
576
+ const lines = [`Fields: ${domainName}`];
577
+ if (context.snapshot === null) {
578
+ lines.push(`Field state is unavailable while the indexer is ${formatServiceHealth(context.indexer.health)}.`);
579
+ return lines.join("\n");
580
+ }
581
+ const fields = listDomainFields(context, domainName);
582
+ if (fields === null) {
583
+ lines.push("Domain not found.");
584
+ return lines.join("\n");
585
+ }
586
+ const renderedFields = options.all || options.limit === null || options.limit === undefined
587
+ ? fields
588
+ : fields.slice(0, options.limit);
589
+ if (renderedFields.length === 0) {
590
+ lines.push("No fields found.");
591
+ }
592
+ else {
593
+ for (const field of renderedFields) {
594
+ lines.push(renderFieldLine(field));
595
+ }
596
+ }
597
+ for (const mutation of listPendingFieldMutations(context, domainName)) {
598
+ lines.push(`Pending field mutation: ${mutation.fieldName ?? "unknown"} ${mutation.kind} ${mutation.status}`);
599
+ }
600
+ for (const family of listPendingFieldFamilies(context, domainName)) {
601
+ lines.push(`Pending field family: ${family.fieldName ?? "unknown"} ${family.status}${family.currentStep == null ? "" : ` step ${family.currentStep}`}`);
602
+ }
603
+ if (!options.all && options.limit !== null && options.limit !== undefined && fields.length > options.limit) {
604
+ lines.push(`Showing first ${renderedFields.length} of ${fields.length}. Use --limit <n> or --all for more.`);
605
+ }
606
+ return lines.join("\n");
607
+ }
608
+ export function formatFieldReport(context, domainName, fieldName) {
609
+ const lines = [`Field: ${domainName}.${fieldName}`];
610
+ if (context.snapshot === null) {
611
+ lines.push(`Field state is unavailable while the indexer is ${formatServiceHealth(context.indexer.health)}.`);
612
+ return lines.join("\n");
613
+ }
614
+ const field = findDomainField(context, domainName, fieldName);
615
+ const pendingMutations = listPendingFieldMutations(context, domainName, fieldName);
616
+ const pendingFamilies = listPendingFieldFamilies(context, domainName)
617
+ .filter((family) => family.fieldName === fieldName);
618
+ if (field === null) {
619
+ lines.push("Field not found.");
620
+ }
621
+ else {
622
+ lines.push(`Domain ID: ${field.domainId}`);
623
+ lines.push(`Field ID: ${field.fieldId}`);
624
+ lines.push(`Permanent: ${field.permanent ? "yes" : "no"}`);
625
+ lines.push(`Has value: ${field.hasValue ? "yes" : "no"}`);
626
+ lines.push(`Format: ${formatFieldFormat(field.format)}`);
627
+ lines.push(`Preview: ${field.preview ?? "(no value)"}`);
628
+ lines.push(`Raw value hex: ${field.rawValueHex ?? "none"}`);
629
+ }
630
+ for (const mutation of pendingMutations) {
631
+ lines.push(`Pending field mutation: ${mutation.kind} ${mutation.status}`);
632
+ }
633
+ for (const family of pendingFamilies) {
634
+ lines.push(`Pending field family: ${family.status}${family.currentStep == null ? "" : ` step ${family.currentStep}`}`);
635
+ }
636
+ return lines.join("\n");
637
+ }
@@ -0,0 +1,13 @@
1
+ import type { WalletIdentityView, WalletLockView, WalletReadContext } from "../wallet/read/index.js";
2
+ export declare function formatNextStepLines(nextSteps: readonly string[]): string[];
3
+ export declare function getFundingQuickstartGuidance(): string;
4
+ export declare function getInitNextSteps(): string[];
5
+ export declare function getBootstrapSyncNextStep(context: Pick<WalletReadContext, "bitcoind" | "indexer" | "nodeHealth">): string | null;
6
+ export declare function getRegisterNextSteps(domainName: string, registerKind: "root" | "subdomain"): string[];
7
+ export declare function getAnchorNextSteps(domainName: string): string[];
8
+ export declare function getHooksEnableMiningNextSteps(): string[];
9
+ export declare function getMineSetupNextSteps(): string[];
10
+ export declare function getMineStopNextSteps(): string[];
11
+ export declare function getAddressNextSteps(context: Pick<WalletReadContext, "bitcoind" | "indexer" | "nodeHealth">, address: string | null | undefined): string[];
12
+ export declare function getIdsNextSteps(identities: readonly WalletIdentityView[] | null | undefined): string[];
13
+ export declare function getLocksNextSteps(locks: readonly WalletLockView[] | null | undefined): string[];