@cogcoin/client 1.1.7 → 1.1.9

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 (284) hide show
  1. package/README.md +1 -1
  2. package/dist/bitcoind/service.js +1 -1
  3. package/dist/cli/commands/mining-read.js +1 -1
  4. package/dist/cli/commands/wallet-mutation/anchor.d.ts +2 -0
  5. package/dist/cli/commands/wallet-mutation/anchor.js +33 -0
  6. package/dist/cli/commands/wallet-mutation/bitcoin-transfer.d.ts +2 -0
  7. package/dist/cli/commands/wallet-mutation/bitcoin-transfer.js +32 -0
  8. package/dist/cli/commands/wallet-mutation/cog.d.ts +2 -0
  9. package/dist/cli/commands/wallet-mutation/cog.js +131 -0
  10. package/dist/cli/commands/wallet-mutation/context.d.ts +3 -0
  11. package/dist/cli/commands/wallet-mutation/context.js +18 -0
  12. package/dist/cli/commands/wallet-mutation/domain-admin.d.ts +2 -0
  13. package/dist/cli/commands/wallet-mutation/domain-admin.js +173 -0
  14. package/dist/cli/commands/wallet-mutation/domain-market.d.ts +2 -0
  15. package/dist/cli/commands/wallet-mutation/domain-market.js +107 -0
  16. package/dist/cli/commands/wallet-mutation/field.d.ts +2 -0
  17. package/dist/cli/commands/wallet-mutation/field.js +125 -0
  18. package/dist/cli/commands/wallet-mutation/register.d.ts +2 -0
  19. package/dist/cli/commands/wallet-mutation/register.js +38 -0
  20. package/dist/cli/commands/wallet-mutation/registry.d.ts +3 -0
  21. package/dist/cli/commands/wallet-mutation/registry.js +39 -0
  22. package/dist/cli/commands/wallet-mutation/reputation.d.ts +2 -0
  23. package/dist/cli/commands/wallet-mutation/reputation.js +57 -0
  24. package/dist/cli/commands/wallet-mutation/types.d.ts +32 -0
  25. package/dist/cli/commands/wallet-mutation/types.js +1 -0
  26. package/dist/cli/commands/wallet-mutation.js +13 -765
  27. package/dist/cli/commands/wallet-read.js +4 -4
  28. package/dist/cli/mutation-success.d.ts +0 -2
  29. package/dist/cli/output/classify.d.ts +7 -0
  30. package/dist/cli/output/classify.js +94 -0
  31. package/dist/cli/output/render.d.ts +2 -0
  32. package/dist/cli/output/render.js +13 -0
  33. package/dist/cli/output/rules/cli-surface.d.ts +2 -0
  34. package/dist/cli/output/rules/cli-surface.js +110 -0
  35. package/dist/cli/output/rules/generic.d.ts +2 -0
  36. package/dist/cli/output/rules/generic.js +13 -0
  37. package/dist/cli/output/rules/index.d.ts +2 -0
  38. package/dist/cli/output/rules/index.js +24 -0
  39. package/dist/cli/output/rules/mining-update.d.ts +2 -0
  40. package/dist/cli/output/rules/mining-update.js +68 -0
  41. package/dist/cli/output/rules/services.d.ts +2 -0
  42. package/dist/cli/output/rules/services.js +110 -0
  43. package/dist/cli/output/rules/wallet-admin.d.ts +2 -0
  44. package/dist/cli/output/rules/wallet-admin.js +224 -0
  45. package/dist/cli/output/rules/wallet-mutations.d.ts +2 -0
  46. package/dist/cli/output/rules/wallet-mutations.js +274 -0
  47. package/dist/cli/output/types.d.ts +16 -0
  48. package/dist/cli/output/types.js +1 -0
  49. package/dist/cli/output.d.ts +2 -168
  50. package/dist/cli/output.js +6 -989
  51. package/dist/cli/pagination.d.ts +15 -0
  52. package/dist/cli/pagination.js +16 -0
  53. package/dist/cli/recommendations.d.ts +4 -0
  54. package/dist/cli/recommendations.js +108 -0
  55. package/dist/cli/wallet-format/availability.d.ts +5 -0
  56. package/dist/cli/wallet-format/availability.js +96 -0
  57. package/dist/cli/wallet-format/balance.d.ts +2 -0
  58. package/dist/cli/wallet-format/balance.js +162 -0
  59. package/dist/cli/wallet-format/domains.d.ts +8 -0
  60. package/dist/cli/wallet-format/domains.js +84 -0
  61. package/dist/cli/wallet-format/fields.d.ts +6 -0
  62. package/dist/cli/wallet-format/fields.js +61 -0
  63. package/dist/cli/wallet-format/identity.d.ts +5 -0
  64. package/dist/cli/wallet-format/identity.js +19 -0
  65. package/dist/cli/wallet-format/locks.d.ts +7 -0
  66. package/dist/cli/wallet-format/locks.js +52 -0
  67. package/dist/cli/wallet-format/overview.d.ts +2 -0
  68. package/dist/cli/wallet-format/overview.js +122 -0
  69. package/dist/cli/wallet-format/pending.d.ts +13 -0
  70. package/dist/cli/wallet-format/pending.js +101 -0
  71. package/dist/cli/wallet-format/shared.d.ts +7 -0
  72. package/dist/cli/wallet-format/shared.js +31 -0
  73. package/dist/cli/wallet-format/status.d.ts +3 -0
  74. package/dist/cli/wallet-format/status.js +27 -0
  75. package/dist/cli/wallet-format.d.ts +8 -30
  76. package/dist/cli/wallet-format.js +8 -830
  77. package/dist/cli/wallet-read-helpers.d.ts +6 -0
  78. package/dist/cli/wallet-read-helpers.js +17 -0
  79. package/dist/wallet/mining/candidate.d.ts +1 -1
  80. package/dist/wallet/mining/candidate.js +3 -3
  81. package/dist/wallet/mining/constants.d.ts +2 -2
  82. package/dist/wallet/mining/constants.js +2 -2
  83. package/dist/wallet/mining/engine-state.js +10 -0
  84. package/dist/wallet/mining/sentence-protocol.d.ts +2 -2
  85. package/dist/wallet/mining/sentences.js +8 -8
  86. package/dist/wallet/mining/visualizer-sync.js +79 -15
  87. package/dist/wallet/read/context.js +1 -1
  88. package/dist/wallet/reset/artifacts.d.ts +16 -0
  89. package/dist/wallet/reset/artifacts.js +141 -0
  90. package/dist/wallet/reset/execution.d.ts +38 -0
  91. package/dist/wallet/reset/execution.js +458 -0
  92. package/dist/wallet/reset/preflight.d.ts +7 -0
  93. package/dist/wallet/reset/preflight.js +116 -0
  94. package/dist/wallet/reset/preview.d.ts +2 -0
  95. package/dist/wallet/reset/preview.js +50 -0
  96. package/dist/wallet/reset/process-cleanup.d.ts +12 -0
  97. package/dist/wallet/reset/process-cleanup.js +179 -0
  98. package/dist/wallet/reset/types.d.ts +189 -0
  99. package/dist/wallet/reset/types.js +1 -0
  100. package/dist/wallet/reset.d.ts +4 -119
  101. package/dist/wallet/reset.js +4 -882
  102. package/dist/wallet/tx/anchor/confirm.d.ts +15 -0
  103. package/dist/wallet/tx/anchor/confirm.js +60 -0
  104. package/dist/wallet/tx/anchor/draft.d.ts +39 -0
  105. package/dist/wallet/tx/anchor/draft.js +167 -0
  106. package/dist/wallet/tx/anchor/index.d.ts +5 -0
  107. package/dist/wallet/tx/anchor/index.js +148 -0
  108. package/dist/wallet/tx/anchor/intent.d.ts +61 -0
  109. package/dist/wallet/tx/anchor/intent.js +101 -0
  110. package/dist/wallet/tx/anchor/plan.d.ts +3 -0
  111. package/dist/wallet/tx/anchor/plan.js +18 -0
  112. package/dist/wallet/tx/anchor/result.d.ts +25 -0
  113. package/dist/wallet/tx/anchor/result.js +20 -0
  114. package/dist/wallet/tx/anchor.d.ts +1 -39
  115. package/dist/wallet/tx/anchor.js +1 -494
  116. package/dist/wallet/tx/bitcoin-transfer/confirm.d.ts +7 -0
  117. package/dist/wallet/tx/bitcoin-transfer/confirm.js +11 -0
  118. package/dist/wallet/tx/bitcoin-transfer/index.d.ts +5 -0
  119. package/dist/wallet/tx/bitcoin-transfer/index.js +112 -0
  120. package/dist/wallet/tx/bitcoin-transfer/intent.d.ts +52 -0
  121. package/dist/wallet/tx/bitcoin-transfer/intent.js +74 -0
  122. package/dist/wallet/tx/bitcoin-transfer/plan.d.ts +5 -0
  123. package/dist/wallet/tx/bitcoin-transfer/plan.js +21 -0
  124. package/dist/wallet/tx/bitcoin-transfer/result.d.ts +19 -0
  125. package/dist/wallet/tx/bitcoin-transfer/result.js +16 -0
  126. package/dist/wallet/tx/bitcoin-transfer.d.ts +1 -35
  127. package/dist/wallet/tx/bitcoin-transfer.js +1 -200
  128. package/dist/wallet/tx/cog/confirm.d.ts +13 -0
  129. package/dist/wallet/tx/cog/confirm.js +59 -0
  130. package/dist/wallet/tx/cog/draft.d.ts +20 -0
  131. package/dist/wallet/tx/cog/draft.js +114 -0
  132. package/dist/wallet/tx/cog/index.d.ts +6 -0
  133. package/dist/wallet/tx/cog/index.js +117 -0
  134. package/dist/wallet/tx/cog/intent.d.ts +30 -0
  135. package/dist/wallet/tx/cog/intent.js +169 -0
  136. package/dist/wallet/tx/cog/plan.d.ts +19 -0
  137. package/dist/wallet/tx/cog/plan.js +65 -0
  138. package/dist/wallet/tx/cog/result.d.ts +27 -0
  139. package/dist/wallet/tx/cog/result.js +28 -0
  140. package/dist/wallet/tx/cog/types.d.ts +186 -0
  141. package/dist/wallet/tx/cog/types.js +2 -0
  142. package/dist/wallet/tx/cog/variants/claim.d.ts +3 -0
  143. package/dist/wallet/tx/cog/variants/claim.js +92 -0
  144. package/dist/wallet/tx/cog/variants/lock.d.ts +2 -0
  145. package/dist/wallet/tx/cog/variants/lock.js +102 -0
  146. package/dist/wallet/tx/cog/variants/send.d.ts +2 -0
  147. package/dist/wallet/tx/cog/variants/send.js +77 -0
  148. package/dist/wallet/tx/cog.d.ts +1 -96
  149. package/dist/wallet/tx/cog.js +1 -824
  150. package/dist/wallet/tx/common.d.ts +14 -199
  151. package/dist/wallet/tx/common.js +10 -493
  152. package/dist/wallet/tx/domain-admin/confirm.d.ts +17 -0
  153. package/dist/wallet/tx/domain-admin/confirm.js +58 -0
  154. package/dist/wallet/tx/domain-admin/draft.d.ts +20 -0
  155. package/dist/wallet/tx/domain-admin/draft.js +161 -0
  156. package/dist/wallet/tx/domain-admin/index.d.ts +9 -0
  157. package/dist/wallet/tx/domain-admin/index.js +150 -0
  158. package/dist/wallet/tx/domain-admin/intent.d.ts +12 -0
  159. package/dist/wallet/tx/domain-admin/intent.js +61 -0
  160. package/dist/wallet/tx/domain-admin/plan.d.ts +19 -0
  161. package/dist/wallet/tx/domain-admin/plan.js +64 -0
  162. package/dist/wallet/tx/domain-admin/result.d.ts +19 -0
  163. package/dist/wallet/tx/domain-admin/result.js +33 -0
  164. package/dist/wallet/tx/domain-admin/types.d.ts +162 -0
  165. package/dist/wallet/tx/domain-admin/types.js +1 -0
  166. package/dist/wallet/tx/domain-admin/variants/canonical.d.ts +2 -0
  167. package/dist/wallet/tx/domain-admin/variants/canonical.js +22 -0
  168. package/dist/wallet/tx/domain-admin/variants/delegate.d.ts +3 -0
  169. package/dist/wallet/tx/domain-admin/variants/delegate.js +60 -0
  170. package/dist/wallet/tx/domain-admin/variants/endpoint.d.ts +3 -0
  171. package/dist/wallet/tx/domain-admin/variants/endpoint.js +102 -0
  172. package/dist/wallet/tx/domain-admin/variants/miner.d.ts +3 -0
  173. package/dist/wallet/tx/domain-admin/variants/miner.js +59 -0
  174. package/dist/wallet/tx/domain-admin.d.ts +1 -107
  175. package/dist/wallet/tx/domain-admin.js +1 -729
  176. package/dist/wallet/tx/domain-market/confirm.d.ts +6 -0
  177. package/dist/wallet/tx/domain-market/confirm.js +52 -0
  178. package/dist/wallet/tx/domain-market/draft.d.ts +43 -0
  179. package/dist/wallet/tx/domain-market/draft.js +286 -0
  180. package/dist/wallet/tx/domain-market/index.d.ts +6 -0
  181. package/dist/wallet/tx/domain-market/index.js +145 -0
  182. package/dist/wallet/tx/domain-market/intent.d.ts +15 -0
  183. package/dist/wallet/tx/domain-market/intent.js +131 -0
  184. package/dist/wallet/tx/domain-market/plan.d.ts +31 -0
  185. package/dist/wallet/tx/domain-market/plan.js +98 -0
  186. package/dist/wallet/tx/domain-market/result.d.ts +45 -0
  187. package/dist/wallet/tx/domain-market/result.js +88 -0
  188. package/dist/wallet/tx/domain-market/types.d.ts +221 -0
  189. package/dist/wallet/tx/domain-market/types.js +1 -0
  190. package/dist/wallet/tx/domain-market/variants/buy.d.ts +2 -0
  191. package/dist/wallet/tx/domain-market/variants/buy.js +103 -0
  192. package/dist/wallet/tx/domain-market/variants/sell.d.ts +2 -0
  193. package/dist/wallet/tx/domain-market/variants/sell.js +91 -0
  194. package/dist/wallet/tx/domain-market/variants/transfer.d.ts +2 -0
  195. package/dist/wallet/tx/domain-market/variants/transfer.js +105 -0
  196. package/dist/wallet/tx/domain-market.d.ts +1 -116
  197. package/dist/wallet/tx/domain-market.js +1 -1078
  198. package/dist/wallet/tx/draft-build.d.ts +60 -0
  199. package/dist/wallet/tx/draft-build.js +127 -0
  200. package/dist/wallet/tx/executor.d.ts +6 -40
  201. package/dist/wallet/tx/executor.js +6 -100
  202. package/dist/wallet/tx/fee.d.ts +30 -0
  203. package/dist/wallet/tx/fee.js +98 -0
  204. package/dist/wallet/tx/field/confirm.d.ts +11 -0
  205. package/dist/wallet/tx/field/confirm.js +19 -0
  206. package/dist/wallet/tx/field/draft.d.ts +23 -0
  207. package/dist/wallet/tx/field/draft.js +202 -0
  208. package/dist/wallet/tx/field/index.d.ts +5 -0
  209. package/dist/wallet/tx/field/index.js +140 -0
  210. package/dist/wallet/tx/field/intent.d.ts +5 -0
  211. package/dist/wallet/tx/field/intent.js +50 -0
  212. package/dist/wallet/tx/field/plan.d.ts +20 -0
  213. package/dist/wallet/tx/field/plan.js +65 -0
  214. package/dist/wallet/tx/field/result.d.ts +29 -0
  215. package/dist/wallet/tx/field/result.js +103 -0
  216. package/dist/wallet/tx/field/types.d.ts +163 -0
  217. package/dist/wallet/tx/field/types.js +1 -0
  218. package/dist/wallet/tx/field/variants/clear.d.ts +2 -0
  219. package/dist/wallet/tx/field/variants/clear.js +60 -0
  220. package/dist/wallet/tx/field/variants/create.d.ts +2 -0
  221. package/dist/wallet/tx/field/variants/create.js +67 -0
  222. package/dist/wallet/tx/field/variants/set.d.ts +2 -0
  223. package/dist/wallet/tx/field/variants/set.js +195 -0
  224. package/dist/wallet/tx/field.d.ts +1 -95
  225. package/dist/wallet/tx/field.js +1 -920
  226. package/dist/wallet/tx/mining-preemption.d.ts +6 -0
  227. package/dist/wallet/tx/mining-preemption.js +7 -0
  228. package/dist/wallet/tx/primitives.d.ts +13 -0
  229. package/dist/wallet/tx/primitives.js +42 -0
  230. package/dist/wallet/tx/psbt-assert.d.ts +14 -0
  231. package/dist/wallet/tx/psbt-assert.js +39 -0
  232. package/dist/wallet/tx/publish.d.ts +37 -0
  233. package/dist/wallet/tx/publish.js +88 -0
  234. package/dist/wallet/tx/readiness.d.ts +7 -0
  235. package/dist/wallet/tx/readiness.js +61 -0
  236. package/dist/wallet/tx/reconcile.d.ts +24 -0
  237. package/dist/wallet/tx/reconcile.js +72 -0
  238. package/dist/wallet/tx/register/confirm.d.ts +6 -0
  239. package/dist/wallet/tx/register/confirm.js +66 -0
  240. package/dist/wallet/tx/register/draft.d.ts +42 -0
  241. package/dist/wallet/tx/register/draft.js +181 -0
  242. package/dist/wallet/tx/register/index.d.ts +6 -0
  243. package/dist/wallet/tx/register/index.js +158 -0
  244. package/dist/wallet/tx/register/intent.d.ts +74 -0
  245. package/dist/wallet/tx/register/intent.js +119 -0
  246. package/dist/wallet/tx/register/plan.d.ts +43 -0
  247. package/dist/wallet/tx/register/plan.js +168 -0
  248. package/dist/wallet/tx/register/result.d.ts +78 -0
  249. package/dist/wallet/tx/register/result.js +41 -0
  250. package/dist/wallet/tx/register.d.ts +1 -70
  251. package/dist/wallet/tx/register.js +1 -681
  252. package/dist/wallet/tx/reputation/confirm.d.ts +11 -0
  253. package/dist/wallet/tx/reputation/confirm.js +51 -0
  254. package/dist/wallet/tx/reputation/draft.d.ts +20 -0
  255. package/dist/wallet/tx/reputation/draft.js +130 -0
  256. package/dist/wallet/tx/reputation/index.d.ts +4 -0
  257. package/dist/wallet/tx/reputation/index.js +162 -0
  258. package/dist/wallet/tx/reputation/intent.d.ts +36 -0
  259. package/dist/wallet/tx/reputation/intent.js +157 -0
  260. package/dist/wallet/tx/reputation/plan.d.ts +19 -0
  261. package/dist/wallet/tx/reputation/plan.js +64 -0
  262. package/dist/wallet/tx/reputation/result.d.ts +21 -0
  263. package/dist/wallet/tx/reputation/result.js +31 -0
  264. package/dist/wallet/tx/reputation/types.d.ts +130 -0
  265. package/dist/wallet/tx/reputation/types.js +1 -0
  266. package/dist/wallet/tx/reputation.d.ts +1 -74
  267. package/dist/wallet/tx/reputation.js +1 -556
  268. package/dist/wallet/tx/signing.d.ts +18 -0
  269. package/dist/wallet/tx/signing.js +31 -0
  270. package/dist/wallet/tx/state-persist.d.ts +27 -0
  271. package/dist/wallet/tx/state-persist.js +54 -0
  272. package/dist/wallet/tx/types.d.ts +44 -0
  273. package/dist/wallet/tx/types.js +1 -0
  274. package/package.json +1 -1
  275. package/dist/cli/mining-json.d.ts +0 -20
  276. package/dist/cli/mining-json.js +0 -46
  277. package/dist/cli/mutation-json.d.ts +0 -325
  278. package/dist/cli/mutation-json.js +0 -269
  279. package/dist/cli/mutation-resolved-json.d.ts +0 -117
  280. package/dist/cli/mutation-resolved-json.js +0 -123
  281. package/dist/cli/preview-json.d.ts +0 -319
  282. package/dist/cli/preview-json.js +0 -254
  283. package/dist/cli/read-json.d.ts +0 -190
  284. package/dist/cli/read-json.js +0 -627
@@ -1,830 +1,8 @@
1
- import { getBalance } from "@cogcoin/indexer/queries";
2
- import { findDomainField, findWalletDomain, formatFieldFormat, isRootDomainName, listDomainFields, listWalletLocks, } from "../wallet/read/index.js";
3
- import { loadBalanceArtText } from "./art.js";
4
- import { formatMiningSummaryLine } from "./mining-format.js";
5
- import { formatNextStepLines, getBootstrapSyncNextStep, getFundingQuickstartGuidance, } from "./workflow-hints.js";
6
- const BALANCE_QUICKSTART_THRESHOLD_SATS = 150000n;
7
- const BALANCE_BUY_ROOT_THRESHOLD_SATS = 100000n;
8
- const BALANCE_MINING_THRESHOLD_SATS = 10000n;
9
- function formatUnitAmount(value, unit) {
10
- const sign = value < 0n ? "-" : "";
11
- const absolute = value < 0n ? -value : value;
12
- const whole = absolute / 100000000n;
13
- const fraction = absolute % 100000000n;
14
- return `${sign}${whole.toString()}.${fraction.toString().padStart(8, "0")} ${unit}`;
15
- }
16
- function formatCogAmount(value) {
17
- return formatUnitAmount(value, "COG");
18
- }
19
- function formatBitcoinAmount(value) {
20
- return value === null ? "unavailable BTC" : formatUnitAmount(value, "BTC");
21
- }
22
- function formatServiceHealth(health) {
23
- return health.replaceAll("-", " ");
24
- }
25
- function formatMaybe(value) {
26
- return value === null ? "unavailable" : String(value);
27
- }
28
- function formatIndexerTruthSource(source) {
29
- switch (source) {
30
- case "lease":
31
- return "coherent snapshot lease";
32
- case "probe":
33
- return "live daemon probe";
34
- case "status-file":
35
- return "advisory status file";
36
- default:
37
- return "none";
38
- }
39
- }
40
- function isReputationMutation(mutation) {
41
- return (mutation.kind === "rep-give" || mutation.kind === "rep-revoke")
42
- && mutation.recipientDomainName !== undefined
43
- && mutation.recipientDomainName !== null;
44
- }
45
- function formatPendingMutationKind(mutation) {
46
- if (mutation.kind === "sell" && mutation.priceCogtoshi === 0n) {
47
- return "unsell";
48
- }
49
- if (mutation.kind === "claim" && mutation.preimageHex === "0000000000000000000000000000000000000000000000000000000000000000") {
50
- return "reclaim";
51
- }
52
- if (mutation.kind === "endpoint" && mutation.endpointValueHex === "") {
53
- return "endpoint-clear";
54
- }
55
- if (mutation.kind === "delegate" && mutation.recipientScriptPubKeyHex === null) {
56
- return "delegate-clear";
57
- }
58
- if (mutation.kind === "miner" && mutation.recipientScriptPubKeyHex === null) {
59
- return "miner-clear";
60
- }
61
- return mutation.kind;
62
- }
63
- function formatPendingMutationSummaryLabel(mutation) {
64
- if (isReputationMutation(mutation)) {
65
- return `${formatPendingMutationKind(mutation)} ${mutation.domainName}->${mutation.recipientDomainName}`;
66
- }
67
- return `${formatPendingMutationKind(mutation)}${mutation.domainName === "" ? "" : ` ${mutation.domainName}`}${mutation.fieldName == null ? "" : `.${mutation.fieldName}`}`;
68
- }
69
- function formatPendingMutationDomainLabel(mutation) {
70
- if (isReputationMutation(mutation)) {
71
- return `${formatPendingMutationKind(mutation)} ${mutation.domainName}->${mutation.recipientDomainName}`;
72
- }
73
- const kind = mutation.kind === "endpoint" && mutation.endpointValueHex === ""
74
- ? "endpoint-clear"
75
- : mutation.kind === "delegate" && mutation.recipientScriptPubKeyHex === null
76
- ? "delegate-clear"
77
- : mutation.kind === "miner" && mutation.recipientScriptPubKeyHex === null
78
- ? "miner-clear"
79
- : formatPendingMutationKind(mutation);
80
- return kind;
81
- }
82
- export function getRepairRecommendation(context) {
83
- if (context.localState.clientPasswordReadiness === "setup-required"
84
- || context.localState.clientPasswordReadiness === "migration-required") {
85
- return "Run `cogcoin init` to configure the client password and migrate local wallet secrets.";
86
- }
87
- if (context.localState.unlockRequired) {
88
- return null;
89
- }
90
- if (context.localState.availability === "uninitialized") {
91
- return "Run `cogcoin init` to create or restore a wallet.";
92
- }
93
- if (context.localState.availability === "local-state-corrupt") {
94
- return "Run `cogcoin repair` to recover local wallet state.";
95
- }
96
- if (context.bitcoind.health === "service-version-mismatch"
97
- || context.bitcoind.health === "wallet-root-mismatch"
98
- || context.bitcoind.health === "runtime-mismatch"
99
- || context.bitcoind.health === "replica-missing"
100
- || context.bitcoind.health === "replica-mismatch"
101
- || context.bitcoind.health === "failed") {
102
- return "Run `cogcoin repair` to recover the managed bitcoind service and Core wallet replica.";
103
- }
104
- if (context.indexer.health === "failed"
105
- || context.indexer.health === "schema-mismatch"
106
- || context.indexer.health === "service-version-mismatch"
107
- || context.indexer.health === "wallet-root-mismatch") {
108
- return "Run `cogcoin repair` to recover the managed indexer daemon and local indexer artifacts.";
109
- }
110
- if (context.localState.state?.miningState.state === "repair-required"
111
- || (context.localState.state?.pendingMutations ?? []).some((mutation) => mutation.status === "repair-required")) {
112
- return "Run `cogcoin repair` before relying on local wallet state.";
113
- }
114
- return null;
115
- }
116
- export function getClientUnlockRecommendation(context) {
117
- if (context.localState.unlockRequired) {
118
- return "Rerun this command in an interactive terminal so Cogcoin can prompt for the client password.";
119
- }
120
- return null;
121
- }
122
- export function getMutationRecommendation(context) {
123
- const pendingMutations = context.localState.state?.pendingMutations ?? [];
124
- const unresolved = pendingMutations.find((mutation) => mutation.status === "broadcast-unknown" || mutation.status === "repair-required");
125
- if (unresolved === undefined) {
126
- return null;
127
- }
128
- if (unresolved.status === "repair-required") {
129
- return "Run `cogcoin repair` before starting another mutation.";
130
- }
131
- if (unresolved.kind === "register") {
132
- return `Rerun \`cogcoin register ${unresolved.domainName}\` to reconcile the pending registration, or run \`cogcoin repair\` if it remains unresolved.`;
133
- }
134
- if (unresolved.kind === "anchor") {
135
- return `Rerun \`cogcoin anchor ${unresolved.domainName}\` to reconcile the pending anchor, or run \`cogcoin repair\` if it remains unresolved.`;
136
- }
137
- if (unresolved.kind === "transfer") {
138
- return `Rerun \`cogcoin transfer ${unresolved.domainName}\` with the same target to reconcile the pending transfer, or run \`cogcoin repair\` if it remains unresolved.`;
139
- }
140
- if (unresolved.kind === "sell") {
141
- const command = unresolved.priceCogtoshi === 0n ? "unsell" : "sell";
142
- return `Rerun \`cogcoin ${command} ${unresolved.domainName}\` to reconcile the pending listing change, or run \`cogcoin repair\` if it remains unresolved.`;
143
- }
144
- if (unresolved.kind === "buy") {
145
- return `Rerun \`cogcoin buy ${unresolved.domainName}\` to reconcile the pending purchase, or run \`cogcoin repair\` if it remains unresolved.`;
146
- }
147
- if (unresolved.kind === "endpoint") {
148
- return unresolved.endpointValueHex === ""
149
- ? `Rerun \`cogcoin domain endpoint clear ${unresolved.domainName}\` to reconcile the pending endpoint clear, or run \`cogcoin repair\` if it remains unresolved.`
150
- : `Rerun \`cogcoin domain endpoint set ${unresolved.domainName} ...\` to reconcile the pending endpoint update, or run \`cogcoin repair\` if it remains unresolved.`;
151
- }
152
- if (unresolved.kind === "delegate") {
153
- return unresolved.recipientScriptPubKeyHex === null
154
- ? `Rerun \`cogcoin domain delegate clear ${unresolved.domainName}\` to reconcile the pending delegate clear, or run \`cogcoin repair\` if it remains unresolved.`
155
- : `Rerun \`cogcoin domain delegate set ${unresolved.domainName} ...\` to reconcile the pending delegate update, or run \`cogcoin repair\` if it remains unresolved.`;
156
- }
157
- if (unresolved.kind === "miner") {
158
- return unresolved.recipientScriptPubKeyHex === null
159
- ? `Rerun \`cogcoin domain miner clear ${unresolved.domainName}\` to reconcile the pending miner clear, or run \`cogcoin repair\` if it remains unresolved.`
160
- : `Rerun \`cogcoin domain miner set ${unresolved.domainName} ...\` to reconcile the pending miner update, or run \`cogcoin repair\` if it remains unresolved.`;
161
- }
162
- if (unresolved.kind === "canonical") {
163
- return `Rerun \`cogcoin domain canonical ${unresolved.domainName}\` to reconcile the pending canonical update, or run \`cogcoin repair\` if it remains unresolved.`;
164
- }
165
- if (unresolved.kind === "field-create") {
166
- return `Rerun \`cogcoin field create ${unresolved.domainName} ${unresolved.fieldName} ...\` to reconcile the pending field creation, or run \`cogcoin repair\` if it remains unresolved.`;
167
- }
168
- if (unresolved.kind === "field-set") {
169
- return `Rerun \`cogcoin field set ${unresolved.domainName} ${unresolved.fieldName} ...\` to reconcile the pending field update, or run \`cogcoin repair\` if it remains unresolved.`;
170
- }
171
- if (unresolved.kind === "field-clear") {
172
- return `Rerun \`cogcoin field clear ${unresolved.domainName} ${unresolved.fieldName}\` to reconcile the pending field clear, or run \`cogcoin repair\` if it remains unresolved.`;
173
- }
174
- if (unresolved.kind === "rep-give") {
175
- return `Rerun \`cogcoin rep give ${unresolved.domainName} ${unresolved.recipientDomainName ?? "..."} ...\` to reconcile the pending reputation support, or run \`cogcoin repair\` if it remains unresolved.`;
176
- }
177
- if (unresolved.kind === "rep-revoke") {
178
- return `Rerun \`cogcoin rep revoke ${unresolved.domainName} ${unresolved.recipientDomainName ?? "..."} ...\` to reconcile the pending reputation revoke, or run \`cogcoin repair\` if it remains unresolved.`;
179
- }
180
- if (unresolved.kind === "send") {
181
- return "Rerun the same `cogcoin send ...` command to reconcile the pending transfer, or run `cogcoin repair` if it remains unresolved.";
182
- }
183
- if (unresolved.kind === "lock") {
184
- return "Rerun the same `cogcoin cog lock ...` command to reconcile the pending lock, or run `cogcoin repair` if it remains unresolved.";
185
- }
186
- return unresolved.preimageHex === "0000000000000000000000000000000000000000000000000000000000000000"
187
- ? "Rerun the same `cogcoin reclaim ...` command to reconcile the pending reclaim, or run `cogcoin repair` if it remains unresolved."
188
- : "Rerun the same `cogcoin claim ...` command to reconcile the pending claim, or run `cogcoin repair` if it remains unresolved.";
189
- }
190
- function appendPendingMutationSummary(lines, context) {
191
- const pendingMutations = (context.localState.state?.pendingMutations ?? [])
192
- .filter((mutation) => mutation.status !== "confirmed" && mutation.status !== "canceled");
193
- if (pendingMutations.length === 0) {
194
- lines.push("Pending mutations: none");
195
- return;
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 === "anchor"
208
- || mutation.kind === "endpoint"
209
- || mutation.kind === "delegate"
210
- || mutation.kind === "miner"
211
- || mutation.kind === "canonical"
212
- || mutation.kind === "field-create"
213
- || mutation.kind === "field-set"
214
- || mutation.kind === "field-clear")
215
- && mutation.domainName === domainName
216
- && mutation.status !== "confirmed"
217
- && mutation.status !== "canceled");
218
- }
219
- function listPendingDomainShowMutations(context, domainName) {
220
- return (context.localState.state?.pendingMutations ?? [])
221
- .filter((mutation) => (mutation.kind === "register"
222
- || mutation.kind === "transfer"
223
- || mutation.kind === "sell"
224
- || mutation.kind === "buy"
225
- || mutation.kind === "anchor"
226
- || mutation.kind === "endpoint"
227
- || mutation.kind === "delegate"
228
- || mutation.kind === "miner"
229
- || mutation.kind === "canonical"
230
- || mutation.kind === "field-create"
231
- || mutation.kind === "field-set"
232
- || mutation.kind === "field-clear"
233
- || mutation.kind === "rep-give"
234
- || mutation.kind === "rep-revoke")
235
- && (mutation.domainName === domainName || mutation.recipientDomainName === domainName)
236
- && mutation.status !== "confirmed"
237
- && mutation.status !== "canceled");
238
- }
239
- function listPendingFieldMutations(context, domainName, fieldName) {
240
- return (context.localState.state?.pendingMutations ?? [])
241
- .filter((mutation) => (mutation.kind === "field-create" || mutation.kind === "field-set" || mutation.kind === "field-clear")
242
- && mutation.domainName === domainName
243
- && (fieldName === undefined || mutation.fieldName === fieldName)
244
- && mutation.status !== "confirmed"
245
- && mutation.status !== "canceled");
246
- }
247
- function appendServiceSummary(lines, context) {
248
- lines.push(`Managed bitcoind: ${formatServiceHealth(context.bitcoind.health)}`);
249
- if (context.bitcoind.message !== null) {
250
- lines.push(`Managed bitcoind note: ${context.bitcoind.message}`);
251
- }
252
- lines.push(`Bitcoin service: ${formatServiceHealth(context.nodeHealth)}`);
253
- if (context.nodeStatus !== null) {
254
- lines.push(`Bitcoin best height: ${formatMaybe(context.nodeStatus.nodeBestHeight)}`);
255
- lines.push(`Bitcoin headers: ${formatMaybe(context.nodeStatus.nodeHeaderHeight)}`);
256
- }
257
- if (context.nodeMessage !== null) {
258
- lines.push(`Bitcoin note: ${context.nodeMessage}`);
259
- }
260
- lines.push(`Indexer service: ${formatServiceHealth(context.indexer.health)}`);
261
- lines.push(`Indexer truth source: ${formatIndexerTruthSource(context.indexer.source)}`);
262
- if (context.indexer.daemonInstanceId !== null) {
263
- lines.push(`Indexer daemon instance: ${context.indexer.daemonInstanceId}`);
264
- }
265
- if (context.indexer.snapshotSeq !== null) {
266
- lines.push(`Indexer snapshot sequence: ${context.indexer.snapshotSeq}`);
267
- }
268
- if (context.indexer.status?.reorgDepth !== null && context.indexer.status?.reorgDepth !== undefined) {
269
- lines.push(`Indexer reorg depth: ${context.indexer.status.reorgDepth}`);
270
- }
271
- if (context.indexer.snapshotTip !== null) {
272
- lines.push(`Indexer tip height: ${context.indexer.snapshotTip.height}`);
273
- }
274
- else {
275
- lines.push("Indexer tip height: unavailable");
276
- }
277
- if (context.indexer.message !== null) {
278
- lines.push(`Indexer note: ${context.indexer.message}`);
279
- }
280
- if (context.mining !== undefined) {
281
- lines.push(`Mining: ${formatMiningSummaryLine(context.mining)}`);
282
- if (context.mining.runtime.note !== null) {
283
- lines.push(`Mining note: ${context.mining.runtime.note}`);
284
- }
285
- }
286
- }
287
- function appendWalletAvailability(lines, context) {
288
- lines.push(`Wallet state: ${context.localState.availability}`);
289
- lines.push(`Wallet root: ${context.model?.walletRootId ?? context.localState.walletRootId ?? context.nodeStatus?.walletRootId ?? "none"}`);
290
- if (context.localState.message !== null) {
291
- lines.push(`Wallet note: ${context.localState.message}`);
292
- }
293
- const nodeStatus = context.nodeStatus;
294
- const replica = nodeStatus?.walletReplica ?? null;
295
- if (replica !== null) {
296
- lines.push(`Managed Core wallet: ${replica.proofStatus ?? "not-proven"}`);
297
- }
298
- if (nodeStatus?.walletReplicaMessage) {
299
- lines.push(`Managed Core note: ${nodeStatus.walletReplicaMessage}`);
300
- }
301
- const repairRecommendation = getRepairRecommendation(context);
302
- if (repairRecommendation !== null) {
303
- lines.push(`Recommended next step: ${repairRecommendation}`);
304
- }
305
- else {
306
- const clientUnlockRecommendation = getClientUnlockRecommendation(context);
307
- if (clientUnlockRecommendation !== null) {
308
- lines.push(`Recommended next step: ${clientUnlockRecommendation}`);
309
- }
310
- else if (getBootstrapSyncNextStep(context) !== null) {
311
- lines.push("Recommended next step: Run `cogcoin sync` to bootstrap assumeutxo and the managed Bitcoin/indexer state.");
312
- }
313
- }
314
- const mutationRecommendation = getMutationRecommendation(context);
315
- if (mutationRecommendation !== null) {
316
- lines.push(`Mutation note: ${mutationRecommendation}`);
317
- }
318
- }
319
- function overviewEntry(text, ok) {
320
- return { text, ok };
321
- }
322
- function formatOverviewSection(header, entries) {
323
- return [header, ...entries.map((entry) => `${entry.ok ? "✓" : "✗"} ${entry.text}`)].join("\n");
324
- }
325
- function isMiningOverviewOk(mining) {
326
- return mining.runtime.bitcoindHealth === "ready"
327
- && mining.runtime.nodeHealth === "synced"
328
- && mining.runtime.indexerHealth === "synced"
329
- && mining.runtime.miningState !== "repair-required"
330
- && mining.runtime.miningState !== "paused-stale"
331
- && !(mining.runtime.miningState === "paused" && mining.runtime.livePublishInMempool === true);
332
- }
333
- function buildOverviewPathsSection(context) {
334
- return [
335
- overviewEntry(`DB path: ${context.databasePath}`, true),
336
- overviewEntry(`Bitcoin datadir: ${context.dataDir}`, true),
337
- ];
338
- }
339
- function buildOverviewWalletSection(context) {
340
- const walletRoot = context.model?.walletRootId ?? context.localState.walletRootId ?? context.nodeStatus?.walletRootId ?? "none";
341
- const lines = [
342
- overviewEntry(`State: ${context.localState.availability}`, context.localState.availability === "ready"),
343
- overviewEntry(`Root: ${walletRoot}`, walletRoot !== "none"),
344
- ];
345
- if (context.localState.message !== null) {
346
- lines.push(overviewEntry(`Note: ${context.localState.message}`, false));
347
- }
348
- const nodeStatus = context.nodeStatus;
349
- const replica = nodeStatus?.walletReplica ?? null;
350
- if (replica !== null) {
351
- lines.push(overviewEntry(`Managed Core wallet: ${replica.proofStatus ?? "not-proven"}`, replica.proofStatus === "ready"));
352
- }
353
- if (nodeStatus?.walletReplicaMessage) {
354
- lines.push(overviewEntry(`Managed Core note: ${nodeStatus.walletReplicaMessage}`, replica?.proofStatus === "ready"));
355
- }
356
- return lines;
357
- }
358
- function buildOverviewServicesSection(context) {
359
- const bitcoindOk = context.bitcoind.health === "ready";
360
- const nodeOk = context.nodeHealth === "synced";
361
- const indexerOk = context.indexer.health === "synced";
362
- const lines = [
363
- overviewEntry(`Managed bitcoind: ${formatServiceHealth(context.bitcoind.health)}`, bitcoindOk),
364
- ];
365
- if (context.bitcoind.message !== null) {
366
- lines.push(overviewEntry(`Managed bitcoind note: ${context.bitcoind.message}`, bitcoindOk));
367
- }
368
- lines.push(overviewEntry(`Bitcoin service: ${formatServiceHealth(context.nodeHealth)}`, nodeOk));
369
- if (context.nodeStatus !== null) {
370
- lines.push(overviewEntry(`Bitcoin best height: ${formatMaybe(context.nodeStatus.nodeBestHeight)}`, nodeOk));
371
- lines.push(overviewEntry(`Bitcoin headers: ${formatMaybe(context.nodeStatus.nodeHeaderHeight)}`, nodeOk));
372
- }
373
- if (context.nodeMessage !== null) {
374
- lines.push(overviewEntry(`Bitcoin note: ${context.nodeMessage}`, nodeOk));
375
- }
376
- lines.push(overviewEntry(`Indexer service: ${formatServiceHealth(context.indexer.health)}`, indexerOk));
377
- lines.push(overviewEntry(`Indexer truth source: ${formatIndexerTruthSource(context.indexer.source)}`, indexerOk));
378
- if (context.indexer.daemonInstanceId !== null && context.indexer.daemonInstanceId !== undefined) {
379
- lines.push(overviewEntry(`Indexer daemon instance: ${context.indexer.daemonInstanceId}`, indexerOk));
380
- }
381
- if (context.indexer.snapshotSeq !== null && context.indexer.snapshotSeq !== undefined) {
382
- lines.push(overviewEntry(`Indexer snapshot sequence: ${context.indexer.snapshotSeq}`, indexerOk));
383
- }
384
- if (context.indexer.status?.reorgDepth !== null && context.indexer.status?.reorgDepth !== undefined) {
385
- lines.push(overviewEntry(`Indexer reorg depth: ${context.indexer.status.reorgDepth}`, indexerOk));
386
- }
387
- lines.push(overviewEntry(`Indexer tip height: ${context.indexer.snapshotTip === null ? "unavailable" : context.indexer.snapshotTip.height}`, indexerOk));
388
- if (context.indexer.message !== null) {
389
- lines.push(overviewEntry(`Indexer note: ${context.indexer.message}`, indexerOk));
390
- }
391
- if (context.mining !== undefined) {
392
- const miningOk = isMiningOverviewOk(context.mining);
393
- lines.push(overviewEntry(`Mining: ${formatMiningSummaryLine(context.mining)}`, miningOk));
394
- if (context.mining.runtime.note !== null) {
395
- lines.push(overviewEntry(`Mining note: ${context.mining.runtime.note}`, miningOk));
396
- }
397
- }
398
- return lines;
399
- }
400
- function buildOverviewLocalInventorySection(context) {
401
- if (context.model === null) {
402
- return [overviewEntry("Status: Wallet-derived sections unavailable", false)];
403
- }
404
- return [
405
- overviewEntry("Local wallet address: 1", true),
406
- overviewEntry(`Locally related domains: ${context.model.domains.length}`, true),
407
- ];
408
- }
409
- function buildOverviewPendingWorkSection(context) {
410
- const pendingMutations = (context.localState.state?.pendingMutations ?? [])
411
- .filter((mutation) => mutation.status !== "confirmed" && mutation.status !== "canceled");
412
- if (pendingMutations.length === 0) {
413
- return [overviewEntry("Status: none", true)];
414
- }
415
- const lines = [];
416
- for (const mutation of pendingMutations) {
417
- lines.push(overviewEntry(`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"}`, false));
418
- }
419
- return lines;
420
- }
421
- function getOverviewNextStep(context) {
422
- const repairRecommendation = getRepairRecommendation(context);
423
- if (repairRecommendation !== null) {
424
- return repairRecommendation;
425
- }
426
- const clientUnlockRecommendation = getClientUnlockRecommendation(context);
427
- if (clientUnlockRecommendation !== null) {
428
- return clientUnlockRecommendation;
429
- }
430
- if (getBootstrapSyncNextStep(context) !== null) {
431
- return "Run `cogcoin sync` to bootstrap assumeutxo and the managed Bitcoin/indexer state.";
432
- }
433
- return getMutationRecommendation(context);
434
- }
435
- export function formatWalletOverviewReport(context, version) {
436
- const parts = [
437
- `\n⛭ Cogcoin Status v${version} ⛭`,
438
- formatOverviewSection("Paths", buildOverviewPathsSection(context)),
439
- formatOverviewSection("Wallet", buildOverviewWalletSection(context)),
440
- formatOverviewSection("Services", buildOverviewServicesSection(context)),
441
- formatOverviewSection("Local Inventory", buildOverviewLocalInventorySection(context)),
442
- formatOverviewSection("Pending Work", buildOverviewPendingWorkSection(context)),
443
- ];
444
- const nextStep = getOverviewNextStep(context);
445
- if (nextStep !== null) {
446
- parts.push(`Next step: ${nextStep}`);
447
- }
448
- return parts.join("\n\n");
449
- }
450
- export function formatDetailedWalletStatusReport(context) {
451
- const lines = ["Cogcoin Wallet Status"];
452
- appendWalletAvailability(lines, context);
453
- appendServiceSummary(lines, context);
454
- if (context.model === null) {
455
- lines.push("Wallet details are unavailable until the encrypted wallet state can be read.");
456
- return lines.join("\n");
457
- }
458
- lines.push(`Wallet address: ${context.model.walletAddress ?? "unavailable"}`);
459
- lines.push(`Wallet script: spk:${context.model.walletScriptPubKeyHex ?? "unavailable"}`);
460
- lines.push("Local wallet addresses: 1");
461
- lines.push(`Locally related domains: ${context.model.domains.length}`);
462
- appendPendingMutationSummary(lines, context);
463
- return lines.join("\n");
464
- }
465
- export function formatFundingAddressReport(context) {
466
- const lines = ["BTC Wallet Address"];
467
- if (context.model === null) {
468
- appendWalletAvailability(lines, context);
469
- return lines.join("\n");
470
- }
471
- lines.push(`Address: ${context.model.walletAddress ?? "unavailable"}`);
472
- lines.push(`ScriptPubKey: spk:${context.model.walletScriptPubKeyHex}`);
473
- return lines.join("\n");
474
- }
475
- function renderBalanceArtLine(templateLine, label, value) {
476
- const labelIndex = templateLine.indexOf(label);
477
- if (labelIndex === -1) {
478
- throw new Error(`balance_art_label_missing_${label}`);
479
- }
480
- const fieldStart = labelIndex + label.length;
481
- const borderIndex = Math.max(templateLine.lastIndexOf("│"), templateLine.lastIndexOf("|"));
482
- if (borderIndex <= fieldStart) {
483
- throw new Error(`balance_art_field_invalid_${label}`);
484
- }
485
- const fieldWidth = borderIndex - fieldStart;
486
- const fieldValue = value.slice(0, fieldWidth).padEnd(fieldWidth, " ");
487
- const rendered = `${templateLine.slice(0, fieldStart)}${fieldValue}${templateLine.slice(borderIndex)}`;
488
- if (rendered.length !== templateLine.length) {
489
- throw new Error(`balance_art_render_width_invalid_${label}`);
490
- }
491
- return rendered;
492
- }
493
- function renderBalanceArtCard(context) {
494
- const templateLines = loadBalanceArtText().split("\n");
495
- const fundingAddress = context.model.walletAddress ?? "unavailable";
496
- const spendableCog = getBalance(context.snapshot.state, new Uint8Array(Buffer.from(context.model.walletScriptPubKeyHex, "hex")));
497
- return templateLines.map((line) => {
498
- if (line.includes("Funding address:")) {
499
- return renderBalanceArtLine(line, "Funding address:", ` ${fundingAddress}`);
500
- }
501
- if (line.includes("Bitcoin Balance:")) {
502
- return renderBalanceArtLine(line, "Bitcoin Balance:", ` ${formatBitcoinAmount(context.fundingSpendableSats ?? null)}`);
503
- }
504
- if (line.includes("Cogcoin Balance:")) {
505
- return renderBalanceArtLine(line, "Cogcoin Balance:", ` ${formatCogAmount(spendableCog)}`);
506
- }
507
- if (line.includes("mempool.space/address/")) {
508
- return renderBalanceArtLine(line, "mempool.space/address/", fundingAddress);
509
- }
510
- return line;
511
- });
512
- }
513
- function hasRegisteredOrAnchoredDomain(model) {
514
- return model.domains.some((domain) => domain.localRelationship === "local"
515
- && (domain.chainStatus === "registered-unanchored" || domain.chainStatus === "anchored"));
516
- }
517
- function listBalanceDomainsByStatus(model, status) {
518
- return model.domains
519
- .filter((domain) => domain.localRelationship === "local" && domain.chainStatus === status)
520
- .sort((left, right) => left.name.localeCompare(right.name));
521
- }
522
- function shouldShowBalanceQuickstart(context) {
523
- return context.fundingSpendableSats !== null
524
- && context.fundingSpendableSats < BALANCE_QUICKSTART_THRESHOLD_SATS
525
- && !hasRegisteredOrAnchoredDomain(context.model);
526
- }
527
- function formatBalanceDomainSection(title, icon, domains, emptyLabel) {
528
- const domainItems = domains.map((domain) => `${icon} ${domain.name}`);
529
- const wrappedDomainLines = [];
530
- let currentLine = "";
531
- for (const item of domainItems) {
532
- const candidate = currentLine.length === 0 ? item : `${currentLine}, ${item}`;
533
- if (candidate.length <= 80) {
534
- currentLine = candidate;
535
- continue;
536
- }
537
- if (currentLine.length > 0) {
538
- wrappedDomainLines.push(currentLine);
539
- }
540
- currentLine = item;
541
- }
542
- if (currentLine.length > 0) {
543
- wrappedDomainLines.push(currentLine);
544
- }
545
- return [
546
- title,
547
- ...(domains.length === 0
548
- ? [emptyLabel]
549
- : wrappedDomainLines),
550
- ];
551
- }
552
- function getBalanceNextSteps(context) {
553
- const anchoredDomains = listBalanceDomainsByStatus(context.model, "anchored");
554
- const anchoredRootDomains = anchoredDomains.filter((domain) => isRootDomainName(domain.name));
555
- const unanchoredDomains = listBalanceDomainsByStatus(context.model, "registered-unanchored");
556
- if (anchoredRootDomains.length > 0) {
557
- if (context.fundingSpendableSats !== null && context.fundingSpendableSats < BALANCE_MINING_THRESHOLD_SATS) {
558
- return [`Transfer BTC to ${context.model.walletAddress ?? "this wallet address"} so your anchored root domain can keep mining.`];
559
- }
560
- if (context.fundingSpendableSats !== null && context.fundingSpendableSats > BALANCE_MINING_THRESHOLD_SATS) {
561
- if (context.mining?.provider.status === "missing") {
562
- return ["Run `cogcoin mine setup` to configure your mining provider."];
563
- }
564
- return ["Run `cogcoin mine` to start mining with your anchored root domain."];
565
- }
566
- return [];
567
- }
568
- if (unanchoredDomains.length > 0) {
569
- return [`Run \`cogcoin anchor ${unanchoredDomains[0].name}\` to anchor your unanchored domain.`];
570
- }
571
- if (context.fundingSpendableSats !== null && context.fundingSpendableSats > BALANCE_BUY_ROOT_THRESHOLD_SATS) {
572
- return ["Buy a 6+ character root domain with `cogcoin register <root>`."];
573
- }
574
- return [];
575
- }
576
- function listPendingBalanceLines(context) {
577
- const lines = [];
578
- for (const mutation of (context.localState.state?.pendingMutations ?? [])
579
- .filter((entry) => (entry.kind === "send" || entry.kind === "lock" || entry.kind === "claim")
580
- && entry.status !== "confirmed"
581
- && entry.status !== "canceled")) {
582
- const label = mutation.kind === "claim" && mutation.preimageHex === "0000000000000000000000000000000000000000000000000000000000000000"
583
- ? "reclaim"
584
- : mutation.kind;
585
- lines.push(`Pending: ${label} ${mutation.status}${mutation.amountCogtoshi === null || mutation.amountCogtoshi === undefined ? "" : ` ${formatCogAmount(mutation.amountCogtoshi)}`}`);
586
- }
587
- return lines;
588
- }
589
- function formatReadyBalanceReport(context) {
590
- const anchoredDomains = listBalanceDomainsByStatus(context.model, "anchored");
591
- const unanchoredDomains = listBalanceDomainsByStatus(context.model, "registered-unanchored");
592
- const nextStepLines = formatNextStepLines(getBalanceNextSteps(context));
593
- const lines = [
594
- "",
595
- ...renderBalanceArtCard(context),
596
- "",
597
- ...formatBalanceDomainSection("Anchored Domains", "⌂", anchoredDomains, "--- No anchored domains ---"),
598
- "",
599
- ...formatBalanceDomainSection("Unanchored Domains", "~", unanchoredDomains, "--- No unanchored domains ---"),
600
- ];
601
- if (shouldShowBalanceQuickstart(context)) {
602
- lines.push("");
603
- lines.push(`Quickstart: ${getFundingQuickstartGuidance()}`);
604
- }
605
- if (nextStepLines.length > 0) {
606
- lines.push("");
607
- lines.push(...nextStepLines);
608
- }
609
- const pendingLines = listPendingBalanceLines(context);
610
- if (pendingLines.length > 0) {
611
- lines.push("");
612
- lines.push(...pendingLines);
613
- }
614
- return lines.join("\n");
615
- }
616
- export function formatIdentityListReport(context, options = {}) {
617
- const lines = ["Wallet Address"];
618
- if (context.model === null) {
619
- appendWalletAvailability(lines, context);
620
- return lines.join("\n");
621
- }
622
- const domains = context.model.domains
623
- .filter((domain) => domain.localRelationship === "local")
624
- .map((domain) => domain.name)
625
- .sort();
626
- const balance = context.snapshot === null
627
- ? null
628
- : getBalance(context.snapshot.state, new Uint8Array(Buffer.from(context.model.walletScriptPubKeyHex, "hex")));
629
- lines.push(`${context.model.walletAddress ?? `spk:${context.model.walletScriptPubKeyHex}`} balance ${balance === null ? "unavailable" : formatCogAmount(balance)} domains ${domains.length === 0 ? "none" : domains.join(", ")}`);
630
- return lines.join("\n");
631
- }
632
- export function formatBalanceReport(context) {
633
- const lines = ["COG Balance"];
634
- if (context.model === null) {
635
- appendWalletAvailability(lines, context);
636
- return lines.join("\n");
637
- }
638
- if (context.snapshot === null) {
639
- lines.push(`Indexer-backed balances are unavailable while the indexer is ${formatServiceHealth(context.indexer.health)}.`);
640
- return lines.join("\n");
641
- }
642
- return formatReadyBalanceReport(context);
643
- }
644
- export function formatLocksReport(context, options = {}) {
645
- const lines = ["COG Locks"];
646
- if (context.model === null) {
647
- appendWalletAvailability(lines, context);
648
- return lines.join("\n");
649
- }
650
- const locks = listWalletLocks(context);
651
- if (locks === null) {
652
- lines.push(`Lock state is unavailable while the indexer is ${formatServiceHealth(context.indexer.health)}.`);
653
- return lines.join("\n");
654
- }
655
- let filteredLocks = locks;
656
- if (options.claimableOnly) {
657
- filteredLocks = filteredLocks.filter((lock) => lock.claimableNow);
658
- }
659
- else if (options.reclaimableOnly) {
660
- filteredLocks = filteredLocks.filter((lock) => lock.reclaimableNow);
661
- }
662
- const totalMatching = filteredLocks.length;
663
- if (!options.all && options.limit !== null && options.limit !== undefined) {
664
- filteredLocks = filteredLocks.slice(0, options.limit);
665
- }
666
- if (filteredLocks.length === 0) {
667
- lines.push("No locally related active locks.");
668
- return lines.join("\n");
669
- }
670
- for (const lock of filteredLocks) {
671
- const role = lock.lockerLocalIndex !== null ? `locker ${lock.lockerLocalIndex}` : "recipient";
672
- const action = lock.claimableNow
673
- ? "claimable-now"
674
- : lock.reclaimableNow
675
- ? "reclaimable-now"
676
- : "not-actionable-now";
677
- lines.push(`lock:${lock.lockId} ${formatCogAmount(lock.amountCogtoshi)} timeout ${lock.timeoutHeight} domain ${lock.recipientDomainName ?? lock.recipientDomainId} ${role} ${action}`);
678
- }
679
- for (const mutation of (context.localState.state?.pendingMutations ?? [])
680
- .filter((entry) => (entry.kind === "lock" || entry.kind === "claim")
681
- && entry.status !== "confirmed"
682
- && entry.status !== "canceled")) {
683
- const label = mutation.kind === "claim" && mutation.preimageHex === "0000000000000000000000000000000000000000000000000000000000000000"
684
- ? "reclaim"
685
- : mutation.kind;
686
- lines.push(`Pending: ${label} ${mutation.status}${mutation.lockId === null || mutation.lockId === undefined ? "" : ` lock:${mutation.lockId}`}${mutation.recipientDomainName === null || mutation.recipientDomainName === undefined ? "" : ` domain ${mutation.recipientDomainName}`}`);
687
- }
688
- if (!options.all && options.limit !== null && options.limit !== undefined && totalMatching > options.limit) {
689
- lines.push(`Showing first ${filteredLocks.length} of ${totalMatching}. Use --limit <n> or --all for more.`);
690
- }
691
- return lines.join("\n");
692
- }
693
- export function formatDomainsReport(context, options = {}) {
694
- const lines = ["Domains"];
695
- if (context.model === null) {
696
- appendWalletAvailability(lines, context);
697
- return lines.join("\n");
698
- }
699
- const visibleDomains = options.domains ?? context.model.domains;
700
- if (visibleDomains.length === 0) {
701
- if ((options.activeFilters?.length ?? 0) > 0) {
702
- lines.push(`No locally related domains matched the active filters (${options.activeFilters.join(", ")}).`);
703
- return lines.join("\n");
704
- }
705
- lines.push("No locally related domains.");
706
- return lines.join("\n");
707
- }
708
- const renderedDomains = options.all || options.limit === null || options.limit === undefined
709
- ? visibleDomains
710
- : visibleDomains.slice(0, options.limit);
711
- for (const domain of renderedDomains) {
712
- const pending = listPendingDomainMutations(context, domain.name);
713
- const pendingFieldMutations = listPendingFieldMutations(context, domain.name);
714
- const pendingText = pending.length === 0
715
- ? ""
716
- : ` pending ${pending.map((mutation) => mutation.kind === "sell" && mutation.priceCogtoshi === 0n
717
- ? `unsell:${mutation.status}`
718
- : mutation.kind === "endpoint" && mutation.endpointValueHex === ""
719
- ? `endpoint-clear:${mutation.status}`
720
- : mutation.kind === "delegate" && mutation.recipientScriptPubKeyHex === null
721
- ? `delegate-clear:${mutation.status}`
722
- : mutation.kind === "miner" && mutation.recipientScriptPubKeyHex === null
723
- ? `miner-clear:${mutation.status}`
724
- : `${mutation.kind}:${mutation.status}`).join(",")}`;
725
- const pendingFieldsText = pendingFieldMutations.length === 0
726
- ? ""
727
- : ` field-pending ${pendingFieldMutations.map((mutation) => `${mutation.fieldName}:${mutation.kind}:${mutation.status}`).join(",")}`;
728
- lines.push(`${domain.name} ${domain.chainStatus} ${domain.localRelationship} owner ${domain.ownerAddress ?? domain.ownerScriptPubKeyHex ?? "unknown"} fields ${formatMaybe(domain.fieldCount)}${pendingText}${pendingFieldsText}`);
729
- }
730
- if (!options.all && options.limit !== null && options.limit !== undefined && visibleDomains.length > options.limit) {
731
- lines.push(`Showing first ${renderedDomains.length} of ${visibleDomains.length}. Use --limit <n> or --all for more.`);
732
- }
733
- return lines.join("\n");
734
- }
735
- export function formatDomainReport(context, domainName) {
736
- const lines = [`Domain: ${domainName}`];
737
- if (context.snapshot === null && context.model?.domains.find((domain) => domain.name === domainName) === undefined) {
738
- lines.push(`Domain state is unavailable while the indexer is ${formatServiceHealth(context.indexer.health)}.`);
739
- return lines.join("\n");
740
- }
741
- const view = findWalletDomain(context, domainName);
742
- if (view === null) {
743
- lines.push("Domain not found.");
744
- return lines.join("\n");
745
- }
746
- lines.push(`Domain ID: ${formatMaybe(view.domain.domainId)}`);
747
- lines.push(`Anchored: ${view.domain.anchored === null ? "unknown" : (view.domain.anchored ? "yes" : "no")}`);
748
- lines.push(`Owner: ${view.domain.ownerAddress ?? view.domain.ownerScriptPubKeyHex ?? "unknown"}`);
749
- lines.push(`Local relationship: ${view.localRelationship}`);
750
- lines.push(`Listing price: ${view.domain.listingPriceCogtoshi === null ? "none" : formatCogAmount(view.domain.listingPriceCogtoshi)}`);
751
- lines.push(`Field count: ${formatMaybe(view.domain.fieldCount)}`);
752
- if (view.domain.selfStakeCogtoshi !== null
753
- || view.domain.supportedStakeCogtoshi !== null
754
- || view.domain.totalSupportedCogtoshi !== null
755
- || view.domain.totalRevokedCogtoshi !== null) {
756
- lines.push(`Reputation self-stake: ${view.domain.selfStakeCogtoshi === null ? "unavailable" : formatCogAmount(view.domain.selfStakeCogtoshi)}`);
757
- lines.push(`Reputation supported stake: ${view.domain.supportedStakeCogtoshi === null ? "unavailable" : formatCogAmount(view.domain.supportedStakeCogtoshi)}`);
758
- lines.push(`Reputation total supported: ${view.domain.totalSupportedCogtoshi === null ? "unavailable" : formatCogAmount(view.domain.totalSupportedCogtoshi)}`);
759
- lines.push(`Reputation total revoked: ${view.domain.totalRevokedCogtoshi === null ? "unavailable" : formatCogAmount(view.domain.totalRevokedCogtoshi)}`);
760
- }
761
- lines.push(`Delegate: ${view.domain.delegateScriptPubKeyHex ?? "none"}`);
762
- lines.push(`Designated miner: ${view.domain.minerScriptPubKeyHex ?? "none"}`);
763
- lines.push(`Endpoint: ${view.domain.endpointText ?? "none"}`);
764
- lines.push(`Founding message: ${view.domain.foundingMessageText ?? "none"}`);
765
- for (const mutation of listPendingDomainShowMutations(context, domainName)) {
766
- lines.push(`Pending mutation: ${formatPendingMutationDomainLabel(mutation)} ${mutation.status}`);
767
- }
768
- for (const mutation of listPendingFieldMutations(context, domainName)) {
769
- lines.push(`Pending field mutation: ${mutation.fieldName ?? "unknown"} ${mutation.kind} ${mutation.status}`);
770
- }
771
- return lines.join("\n");
772
- }
773
- function renderFieldLine(field) {
774
- return `${field.name} id ${field.fieldId} ${field.permanent ? "permanent" : "mutable"} ${field.hasValue ? formatFieldFormat(field.format) : "empty"} ${field.preview ?? "(no value)"}`;
775
- }
776
- export function formatFieldsReport(context, domainName, options = {}) {
777
- const lines = [`Fields: ${domainName}`];
778
- if (context.snapshot === null) {
779
- lines.push(`Field state is unavailable while the indexer is ${formatServiceHealth(context.indexer.health)}.`);
780
- return lines.join("\n");
781
- }
782
- const fields = listDomainFields(context, domainName);
783
- if (fields === null) {
784
- lines.push("Domain not found.");
785
- return lines.join("\n");
786
- }
787
- const renderedFields = options.all || options.limit === null || options.limit === undefined
788
- ? fields
789
- : fields.slice(0, options.limit);
790
- if (renderedFields.length === 0) {
791
- lines.push("No fields found.");
792
- }
793
- else {
794
- for (const field of renderedFields) {
795
- lines.push(renderFieldLine(field));
796
- }
797
- }
798
- for (const mutation of listPendingFieldMutations(context, domainName)) {
799
- lines.push(`Pending field mutation: ${mutation.fieldName ?? "unknown"} ${mutation.kind} ${mutation.status}`);
800
- }
801
- if (!options.all && options.limit !== null && options.limit !== undefined && fields.length > options.limit) {
802
- lines.push(`Showing first ${renderedFields.length} of ${fields.length}. Use --limit <n> or --all for more.`);
803
- }
804
- return lines.join("\n");
805
- }
806
- export function formatFieldReport(context, domainName, fieldName) {
807
- const lines = [`Field: ${domainName}.${fieldName}`];
808
- if (context.snapshot === null) {
809
- lines.push(`Field state is unavailable while the indexer is ${formatServiceHealth(context.indexer.health)}.`);
810
- return lines.join("\n");
811
- }
812
- const field = findDomainField(context, domainName, fieldName);
813
- const pendingMutations = listPendingFieldMutations(context, domainName, fieldName);
814
- if (field === null) {
815
- lines.push("Field not found.");
816
- }
817
- else {
818
- lines.push(`Domain ID: ${field.domainId}`);
819
- lines.push(`Field ID: ${field.fieldId}`);
820
- lines.push(`Permanent: ${field.permanent ? "yes" : "no"}`);
821
- lines.push(`Has value: ${field.hasValue ? "yes" : "no"}`);
822
- lines.push(`Format: ${formatFieldFormat(field.format)}`);
823
- lines.push(`Preview: ${field.preview ?? "(no value)"}`);
824
- lines.push(`Raw value hex: ${field.rawValueHex ?? "none"}`);
825
- }
826
- for (const mutation of pendingMutations) {
827
- lines.push(`Pending field mutation: ${mutation.kind} ${mutation.status}`);
828
- }
829
- return lines.join("\n");
830
- }
1
+ export { getClientUnlockRecommendation, getMutationRecommendation, getRepairRecommendation, } from "./recommendations.js";
2
+ export { formatWalletOverviewReport } from "./wallet-format/overview.js";
3
+ export { formatDetailedWalletStatusReport, formatFundingAddressReport, } from "./wallet-format/status.js";
4
+ export { formatBalanceReport } from "./wallet-format/balance.js";
5
+ export { formatIdentityListReport } from "./wallet-format/identity.js";
6
+ export { formatLocksReport } from "./wallet-format/locks.js";
7
+ export { formatDomainsReport, formatDomainReport, } from "./wallet-format/domains.js";
8
+ export { formatFieldsReport, formatFieldReport, } from "./wallet-format/fields.js";