@cogcoin/client 1.1.8 → 1.1.10

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 (295) hide show
  1. package/README.md +1 -1
  2. package/dist/bitcoind/managed-bitcoind-service-config.d.ts +13 -0
  3. package/dist/bitcoind/managed-bitcoind-service-config.js +165 -0
  4. package/dist/bitcoind/managed-bitcoind-service-lifecycle.d.ts +28 -0
  5. package/dist/bitcoind/managed-bitcoind-service-lifecycle.js +290 -0
  6. package/dist/bitcoind/managed-bitcoind-service-process.d.ts +8 -0
  7. package/dist/bitcoind/managed-bitcoind-service-process.js +48 -0
  8. package/dist/bitcoind/managed-bitcoind-service-replica.d.ts +8 -0
  9. package/dist/bitcoind/managed-bitcoind-service-replica.js +142 -0
  10. package/dist/bitcoind/managed-bitcoind-service-status.d.ts +42 -0
  11. package/dist/bitcoind/managed-bitcoind-service-status.js +178 -0
  12. package/dist/bitcoind/managed-bitcoind-service-types.d.ts +36 -0
  13. package/dist/bitcoind/managed-bitcoind-service-types.js +1 -0
  14. package/dist/bitcoind/service.d.ts +7 -63
  15. package/dist/bitcoind/service.js +7 -797
  16. package/dist/cli/commands/mining-read.js +1 -1
  17. package/dist/cli/commands/wallet-mutation/anchor.d.ts +2 -0
  18. package/dist/cli/commands/wallet-mutation/anchor.js +33 -0
  19. package/dist/cli/commands/wallet-mutation/bitcoin-transfer.d.ts +2 -0
  20. package/dist/cli/commands/wallet-mutation/bitcoin-transfer.js +32 -0
  21. package/dist/cli/commands/wallet-mutation/cog.d.ts +2 -0
  22. package/dist/cli/commands/wallet-mutation/cog.js +131 -0
  23. package/dist/cli/commands/wallet-mutation/context.d.ts +3 -0
  24. package/dist/cli/commands/wallet-mutation/context.js +18 -0
  25. package/dist/cli/commands/wallet-mutation/domain-admin.d.ts +2 -0
  26. package/dist/cli/commands/wallet-mutation/domain-admin.js +173 -0
  27. package/dist/cli/commands/wallet-mutation/domain-market.d.ts +2 -0
  28. package/dist/cli/commands/wallet-mutation/domain-market.js +107 -0
  29. package/dist/cli/commands/wallet-mutation/field.d.ts +2 -0
  30. package/dist/cli/commands/wallet-mutation/field.js +125 -0
  31. package/dist/cli/commands/wallet-mutation/register.d.ts +2 -0
  32. package/dist/cli/commands/wallet-mutation/register.js +38 -0
  33. package/dist/cli/commands/wallet-mutation/registry.d.ts +3 -0
  34. package/dist/cli/commands/wallet-mutation/registry.js +39 -0
  35. package/dist/cli/commands/wallet-mutation/reputation.d.ts +2 -0
  36. package/dist/cli/commands/wallet-mutation/reputation.js +57 -0
  37. package/dist/cli/commands/wallet-mutation/types.d.ts +32 -0
  38. package/dist/cli/commands/wallet-mutation/types.js +1 -0
  39. package/dist/cli/commands/wallet-mutation.js +13 -765
  40. package/dist/cli/commands/wallet-read.js +4 -4
  41. package/dist/cli/mutation-success.d.ts +0 -2
  42. package/dist/cli/output/classify.d.ts +7 -0
  43. package/dist/cli/output/classify.js +94 -0
  44. package/dist/cli/output/render.d.ts +2 -0
  45. package/dist/cli/output/render.js +13 -0
  46. package/dist/cli/output/rules/cli-surface.d.ts +2 -0
  47. package/dist/cli/output/rules/cli-surface.js +110 -0
  48. package/dist/cli/output/rules/generic.d.ts +2 -0
  49. package/dist/cli/output/rules/generic.js +13 -0
  50. package/dist/cli/output/rules/index.d.ts +2 -0
  51. package/dist/cli/output/rules/index.js +24 -0
  52. package/dist/cli/output/rules/mining-update.d.ts +2 -0
  53. package/dist/cli/output/rules/mining-update.js +68 -0
  54. package/dist/cli/output/rules/services.d.ts +2 -0
  55. package/dist/cli/output/rules/services.js +110 -0
  56. package/dist/cli/output/rules/wallet-admin.d.ts +2 -0
  57. package/dist/cli/output/rules/wallet-admin.js +224 -0
  58. package/dist/cli/output/rules/wallet-mutations.d.ts +2 -0
  59. package/dist/cli/output/rules/wallet-mutations.js +274 -0
  60. package/dist/cli/output/types.d.ts +16 -0
  61. package/dist/cli/output/types.js +1 -0
  62. package/dist/cli/output.d.ts +2 -168
  63. package/dist/cli/output.js +6 -989
  64. package/dist/cli/pagination.d.ts +15 -0
  65. package/dist/cli/pagination.js +16 -0
  66. package/dist/cli/recommendations.d.ts +4 -0
  67. package/dist/cli/recommendations.js +108 -0
  68. package/dist/cli/wallet-format/availability.d.ts +5 -0
  69. package/dist/cli/wallet-format/availability.js +96 -0
  70. package/dist/cli/wallet-format/balance.d.ts +2 -0
  71. package/dist/cli/wallet-format/balance.js +162 -0
  72. package/dist/cli/wallet-format/domains.d.ts +8 -0
  73. package/dist/cli/wallet-format/domains.js +84 -0
  74. package/dist/cli/wallet-format/fields.d.ts +6 -0
  75. package/dist/cli/wallet-format/fields.js +61 -0
  76. package/dist/cli/wallet-format/identity.d.ts +5 -0
  77. package/dist/cli/wallet-format/identity.js +19 -0
  78. package/dist/cli/wallet-format/locks.d.ts +7 -0
  79. package/dist/cli/wallet-format/locks.js +52 -0
  80. package/dist/cli/wallet-format/overview.d.ts +2 -0
  81. package/dist/cli/wallet-format/overview.js +122 -0
  82. package/dist/cli/wallet-format/pending.d.ts +13 -0
  83. package/dist/cli/wallet-format/pending.js +101 -0
  84. package/dist/cli/wallet-format/shared.d.ts +7 -0
  85. package/dist/cli/wallet-format/shared.js +31 -0
  86. package/dist/cli/wallet-format/status.d.ts +3 -0
  87. package/dist/cli/wallet-format/status.js +27 -0
  88. package/dist/cli/wallet-format.d.ts +8 -30
  89. package/dist/cli/wallet-format.js +8 -830
  90. package/dist/cli/wallet-read-helpers.d.ts +6 -0
  91. package/dist/cli/wallet-read-helpers.js +17 -0
  92. package/dist/wallet/mining/candidate.d.ts +1 -1
  93. package/dist/wallet/mining/candidate.js +3 -3
  94. package/dist/wallet/mining/constants.d.ts +2 -2
  95. package/dist/wallet/mining/constants.js +2 -2
  96. package/dist/wallet/mining/engine-types.d.ts +1 -0
  97. package/dist/wallet/mining/engine-types.js +9 -1
  98. package/dist/wallet/mining/publish.js +3 -6
  99. package/dist/wallet/mining/runner.js +30 -18
  100. package/dist/wallet/mining/sentence-protocol.d.ts +2 -2
  101. package/dist/wallet/mining/sentences.js +8 -8
  102. package/dist/wallet/mining/visualizer.js +7 -6
  103. package/dist/wallet/read/context.d.ts +4 -10
  104. package/dist/wallet/read/context.js +4 -227
  105. package/dist/wallet/read/local-state.d.ts +28 -0
  106. package/dist/wallet/read/local-state.js +233 -0
  107. package/dist/wallet/read/managed-bitcoind.d.ts +30 -0
  108. package/dist/wallet/read/managed-bitcoind.js +138 -0
  109. package/dist/wallet/read/managed-indexer.d.ts +23 -0
  110. package/dist/wallet/read/managed-indexer.js +87 -0
  111. package/dist/wallet/read/managed-services.d.ts +6 -21
  112. package/dist/wallet/read/managed-services.js +23 -196
  113. package/dist/wallet/tx/anchor/confirm.d.ts +15 -0
  114. package/dist/wallet/tx/anchor/confirm.js +60 -0
  115. package/dist/wallet/tx/anchor/draft.d.ts +39 -0
  116. package/dist/wallet/tx/anchor/draft.js +167 -0
  117. package/dist/wallet/tx/anchor/index.d.ts +5 -0
  118. package/dist/wallet/tx/anchor/index.js +148 -0
  119. package/dist/wallet/tx/anchor/intent.d.ts +61 -0
  120. package/dist/wallet/tx/anchor/intent.js +101 -0
  121. package/dist/wallet/tx/anchor/plan.d.ts +3 -0
  122. package/dist/wallet/tx/anchor/plan.js +18 -0
  123. package/dist/wallet/tx/anchor/result.d.ts +25 -0
  124. package/dist/wallet/tx/anchor/result.js +20 -0
  125. package/dist/wallet/tx/anchor.d.ts +1 -39
  126. package/dist/wallet/tx/anchor.js +1 -494
  127. package/dist/wallet/tx/bitcoin-transfer/confirm.d.ts +7 -0
  128. package/dist/wallet/tx/bitcoin-transfer/confirm.js +11 -0
  129. package/dist/wallet/tx/bitcoin-transfer/index.d.ts +5 -0
  130. package/dist/wallet/tx/bitcoin-transfer/index.js +112 -0
  131. package/dist/wallet/tx/bitcoin-transfer/intent.d.ts +52 -0
  132. package/dist/wallet/tx/bitcoin-transfer/intent.js +74 -0
  133. package/dist/wallet/tx/bitcoin-transfer/plan.d.ts +5 -0
  134. package/dist/wallet/tx/bitcoin-transfer/plan.js +21 -0
  135. package/dist/wallet/tx/bitcoin-transfer/result.d.ts +19 -0
  136. package/dist/wallet/tx/bitcoin-transfer/result.js +16 -0
  137. package/dist/wallet/tx/bitcoin-transfer.d.ts +1 -35
  138. package/dist/wallet/tx/bitcoin-transfer.js +1 -200
  139. package/dist/wallet/tx/cog/confirm.d.ts +13 -0
  140. package/dist/wallet/tx/cog/confirm.js +59 -0
  141. package/dist/wallet/tx/cog/draft.d.ts +20 -0
  142. package/dist/wallet/tx/cog/draft.js +114 -0
  143. package/dist/wallet/tx/cog/index.d.ts +6 -0
  144. package/dist/wallet/tx/cog/index.js +117 -0
  145. package/dist/wallet/tx/cog/intent.d.ts +30 -0
  146. package/dist/wallet/tx/cog/intent.js +169 -0
  147. package/dist/wallet/tx/cog/plan.d.ts +19 -0
  148. package/dist/wallet/tx/cog/plan.js +65 -0
  149. package/dist/wallet/tx/cog/result.d.ts +27 -0
  150. package/dist/wallet/tx/cog/result.js +28 -0
  151. package/dist/wallet/tx/cog/types.d.ts +186 -0
  152. package/dist/wallet/tx/cog/types.js +2 -0
  153. package/dist/wallet/tx/cog/variants/claim.d.ts +3 -0
  154. package/dist/wallet/tx/cog/variants/claim.js +92 -0
  155. package/dist/wallet/tx/cog/variants/lock.d.ts +2 -0
  156. package/dist/wallet/tx/cog/variants/lock.js +102 -0
  157. package/dist/wallet/tx/cog/variants/send.d.ts +2 -0
  158. package/dist/wallet/tx/cog/variants/send.js +77 -0
  159. package/dist/wallet/tx/cog.d.ts +1 -96
  160. package/dist/wallet/tx/cog.js +1 -824
  161. package/dist/wallet/tx/common.d.ts +14 -199
  162. package/dist/wallet/tx/common.js +10 -493
  163. package/dist/wallet/tx/domain-admin/confirm.d.ts +17 -0
  164. package/dist/wallet/tx/domain-admin/confirm.js +58 -0
  165. package/dist/wallet/tx/domain-admin/draft.d.ts +20 -0
  166. package/dist/wallet/tx/domain-admin/draft.js +161 -0
  167. package/dist/wallet/tx/domain-admin/index.d.ts +9 -0
  168. package/dist/wallet/tx/domain-admin/index.js +150 -0
  169. package/dist/wallet/tx/domain-admin/intent.d.ts +12 -0
  170. package/dist/wallet/tx/domain-admin/intent.js +61 -0
  171. package/dist/wallet/tx/domain-admin/plan.d.ts +19 -0
  172. package/dist/wallet/tx/domain-admin/plan.js +64 -0
  173. package/dist/wallet/tx/domain-admin/result.d.ts +19 -0
  174. package/dist/wallet/tx/domain-admin/result.js +33 -0
  175. package/dist/wallet/tx/domain-admin/types.d.ts +162 -0
  176. package/dist/wallet/tx/domain-admin/types.js +1 -0
  177. package/dist/wallet/tx/domain-admin/variants/canonical.d.ts +2 -0
  178. package/dist/wallet/tx/domain-admin/variants/canonical.js +22 -0
  179. package/dist/wallet/tx/domain-admin/variants/delegate.d.ts +3 -0
  180. package/dist/wallet/tx/domain-admin/variants/delegate.js +60 -0
  181. package/dist/wallet/tx/domain-admin/variants/endpoint.d.ts +3 -0
  182. package/dist/wallet/tx/domain-admin/variants/endpoint.js +102 -0
  183. package/dist/wallet/tx/domain-admin/variants/miner.d.ts +3 -0
  184. package/dist/wallet/tx/domain-admin/variants/miner.js +59 -0
  185. package/dist/wallet/tx/domain-admin.d.ts +1 -107
  186. package/dist/wallet/tx/domain-admin.js +1 -729
  187. package/dist/wallet/tx/domain-market/confirm.d.ts +6 -0
  188. package/dist/wallet/tx/domain-market/confirm.js +52 -0
  189. package/dist/wallet/tx/domain-market/draft.d.ts +43 -0
  190. package/dist/wallet/tx/domain-market/draft.js +286 -0
  191. package/dist/wallet/tx/domain-market/index.d.ts +6 -0
  192. package/dist/wallet/tx/domain-market/index.js +145 -0
  193. package/dist/wallet/tx/domain-market/intent.d.ts +15 -0
  194. package/dist/wallet/tx/domain-market/intent.js +131 -0
  195. package/dist/wallet/tx/domain-market/plan.d.ts +31 -0
  196. package/dist/wallet/tx/domain-market/plan.js +98 -0
  197. package/dist/wallet/tx/domain-market/result.d.ts +45 -0
  198. package/dist/wallet/tx/domain-market/result.js +88 -0
  199. package/dist/wallet/tx/domain-market/types.d.ts +221 -0
  200. package/dist/wallet/tx/domain-market/types.js +1 -0
  201. package/dist/wallet/tx/domain-market/variants/buy.d.ts +2 -0
  202. package/dist/wallet/tx/domain-market/variants/buy.js +103 -0
  203. package/dist/wallet/tx/domain-market/variants/sell.d.ts +2 -0
  204. package/dist/wallet/tx/domain-market/variants/sell.js +91 -0
  205. package/dist/wallet/tx/domain-market/variants/transfer.d.ts +2 -0
  206. package/dist/wallet/tx/domain-market/variants/transfer.js +105 -0
  207. package/dist/wallet/tx/domain-market.d.ts +1 -116
  208. package/dist/wallet/tx/domain-market.js +1 -1078
  209. package/dist/wallet/tx/draft-build.d.ts +60 -0
  210. package/dist/wallet/tx/draft-build.js +127 -0
  211. package/dist/wallet/tx/executor.d.ts +6 -40
  212. package/dist/wallet/tx/executor.js +6 -100
  213. package/dist/wallet/tx/fee.d.ts +30 -0
  214. package/dist/wallet/tx/fee.js +98 -0
  215. package/dist/wallet/tx/field/confirm.d.ts +11 -0
  216. package/dist/wallet/tx/field/confirm.js +19 -0
  217. package/dist/wallet/tx/field/draft.d.ts +23 -0
  218. package/dist/wallet/tx/field/draft.js +202 -0
  219. package/dist/wallet/tx/field/index.d.ts +5 -0
  220. package/dist/wallet/tx/field/index.js +140 -0
  221. package/dist/wallet/tx/field/intent.d.ts +5 -0
  222. package/dist/wallet/tx/field/intent.js +50 -0
  223. package/dist/wallet/tx/field/plan.d.ts +20 -0
  224. package/dist/wallet/tx/field/plan.js +65 -0
  225. package/dist/wallet/tx/field/result.d.ts +29 -0
  226. package/dist/wallet/tx/field/result.js +103 -0
  227. package/dist/wallet/tx/field/types.d.ts +163 -0
  228. package/dist/wallet/tx/field/types.js +1 -0
  229. package/dist/wallet/tx/field/variants/clear.d.ts +2 -0
  230. package/dist/wallet/tx/field/variants/clear.js +60 -0
  231. package/dist/wallet/tx/field/variants/create.d.ts +2 -0
  232. package/dist/wallet/tx/field/variants/create.js +67 -0
  233. package/dist/wallet/tx/field/variants/set.d.ts +2 -0
  234. package/dist/wallet/tx/field/variants/set.js +195 -0
  235. package/dist/wallet/tx/field.d.ts +1 -95
  236. package/dist/wallet/tx/field.js +1 -920
  237. package/dist/wallet/tx/mining-preemption.d.ts +6 -0
  238. package/dist/wallet/tx/mining-preemption.js +7 -0
  239. package/dist/wallet/tx/primitives.d.ts +13 -0
  240. package/dist/wallet/tx/primitives.js +42 -0
  241. package/dist/wallet/tx/psbt-assert.d.ts +14 -0
  242. package/dist/wallet/tx/psbt-assert.js +39 -0
  243. package/dist/wallet/tx/publish.d.ts +37 -0
  244. package/dist/wallet/tx/publish.js +88 -0
  245. package/dist/wallet/tx/readiness.d.ts +7 -0
  246. package/dist/wallet/tx/readiness.js +61 -0
  247. package/dist/wallet/tx/reconcile.d.ts +24 -0
  248. package/dist/wallet/tx/reconcile.js +72 -0
  249. package/dist/wallet/tx/register/confirm.d.ts +6 -0
  250. package/dist/wallet/tx/register/confirm.js +66 -0
  251. package/dist/wallet/tx/register/draft.d.ts +42 -0
  252. package/dist/wallet/tx/register/draft.js +181 -0
  253. package/dist/wallet/tx/register/index.d.ts +6 -0
  254. package/dist/wallet/tx/register/index.js +158 -0
  255. package/dist/wallet/tx/register/intent.d.ts +74 -0
  256. package/dist/wallet/tx/register/intent.js +119 -0
  257. package/dist/wallet/tx/register/plan.d.ts +43 -0
  258. package/dist/wallet/tx/register/plan.js +168 -0
  259. package/dist/wallet/tx/register/result.d.ts +78 -0
  260. package/dist/wallet/tx/register/result.js +41 -0
  261. package/dist/wallet/tx/register.d.ts +1 -70
  262. package/dist/wallet/tx/register.js +1 -681
  263. package/dist/wallet/tx/reputation/confirm.d.ts +11 -0
  264. package/dist/wallet/tx/reputation/confirm.js +51 -0
  265. package/dist/wallet/tx/reputation/draft.d.ts +20 -0
  266. package/dist/wallet/tx/reputation/draft.js +130 -0
  267. package/dist/wallet/tx/reputation/index.d.ts +4 -0
  268. package/dist/wallet/tx/reputation/index.js +162 -0
  269. package/dist/wallet/tx/reputation/intent.d.ts +36 -0
  270. package/dist/wallet/tx/reputation/intent.js +157 -0
  271. package/dist/wallet/tx/reputation/plan.d.ts +19 -0
  272. package/dist/wallet/tx/reputation/plan.js +64 -0
  273. package/dist/wallet/tx/reputation/result.d.ts +21 -0
  274. package/dist/wallet/tx/reputation/result.js +31 -0
  275. package/dist/wallet/tx/reputation/types.d.ts +130 -0
  276. package/dist/wallet/tx/reputation/types.js +1 -0
  277. package/dist/wallet/tx/reputation.d.ts +1 -74
  278. package/dist/wallet/tx/reputation.js +1 -556
  279. package/dist/wallet/tx/signing.d.ts +18 -0
  280. package/dist/wallet/tx/signing.js +31 -0
  281. package/dist/wallet/tx/state-persist.d.ts +27 -0
  282. package/dist/wallet/tx/state-persist.js +54 -0
  283. package/dist/wallet/tx/types.d.ts +44 -0
  284. package/dist/wallet/tx/types.js +1 -0
  285. package/package.json +1 -1
  286. package/dist/cli/mining-json.d.ts +0 -20
  287. package/dist/cli/mining-json.js +0 -46
  288. package/dist/cli/mutation-json.d.ts +0 -325
  289. package/dist/cli/mutation-json.js +0 -269
  290. package/dist/cli/mutation-resolved-json.d.ts +0 -117
  291. package/dist/cli/mutation-resolved-json.js +0 -123
  292. package/dist/cli/preview-json.d.ts +0 -319
  293. package/dist/cli/preview-json.js +0 -254
  294. package/dist/cli/read-json.d.ts +0 -190
  295. package/dist/cli/read-json.js +0 -627
@@ -0,0 +1,233 @@
1
+ import { access, constants } from "node:fs/promises";
2
+ import { normalizeWalletStateRecord, persistWalletCoinControlStateIfNeeded } from "../coin-control.js";
3
+ import { persistNormalizedWalletDescriptorStateIfNeeded } from "../descriptor-normalization.js";
4
+ import { attachOrStartManagedBitcoindService } from "../../bitcoind/service.js";
5
+ import { createRpcClient } from "../../bitcoind/node.js";
6
+ import { normalizeMiningStateRecord } from "../mining/state.js";
7
+ import { resolveWalletRootIdFromLocalArtifacts } from "../root-resolution.js";
8
+ import { resolveWalletRuntimePathsForTesting } from "../runtime.js";
9
+ import { extractWalletRootIdHintFromWalletStateEnvelope, loadRawWalletStateEnvelope, loadWalletState, } from "../state/storage.js";
10
+ import { createDefaultWalletSecretProvider, createWalletSecretReference, inspectClientPasswordSetupReadiness, } from "../state/provider.js";
11
+ import { describeClientPasswordLockedMessage, describeClientPasswordMigrationMessage, describeClientPasswordSetupMessage, } from "../state/client-password.js";
12
+ const defaultWalletLocalStateDeps = {
13
+ attachOrStartManagedBitcoindService,
14
+ createRpcClient,
15
+ };
16
+ function btcAmountToSats(value) {
17
+ return BigInt(Math.round(value * 100_000_000));
18
+ }
19
+ function isSpendableFundingUtxo(entry, fundingScriptPubKeyHex) {
20
+ return entry.scriptPubKey === fundingScriptPubKeyHex
21
+ && entry.confirmations >= 1
22
+ && entry.spendable !== false
23
+ && entry.safe !== false;
24
+ }
25
+ async function pathExists(path) {
26
+ try {
27
+ await access(path, constants.F_OK);
28
+ return true;
29
+ }
30
+ catch {
31
+ return false;
32
+ }
33
+ }
34
+ function isWalletAccessError(error) {
35
+ const message = error instanceof Error ? error.message : String(error);
36
+ return message.startsWith("wallet_secret_missing_")
37
+ || message.startsWith("wallet_secret_provider_")
38
+ || message.startsWith("wallet_client_password_")
39
+ || message === "wallet_state_legacy_envelope_unsupported";
40
+ }
41
+ function describeWalletAccessMessage(options) {
42
+ const message = options.accessError instanceof Error ? options.accessError.message : String(options.accessError ?? "");
43
+ if (message === "wallet_state_legacy_envelope_unsupported") {
44
+ return "Wallet state exists but was created by an older Cogcoin wallet format that this version no longer loads directly.";
45
+ }
46
+ if (message === "wallet_client_password_setup_required") {
47
+ return describeClientPasswordSetupMessage();
48
+ }
49
+ if (message === "wallet_client_password_migration_required") {
50
+ return describeClientPasswordMigrationMessage();
51
+ }
52
+ if (message === "wallet_client_password_locked") {
53
+ return describeClientPasswordLockedMessage();
54
+ }
55
+ if (message.startsWith("wallet_secret_provider_")) {
56
+ return "Wallet state exists but the local secret provider is unavailable.";
57
+ }
58
+ if (message.startsWith("wallet_secret_missing_")) {
59
+ return "Wallet state exists but its local secret-provider material is unavailable.";
60
+ }
61
+ return message.length > 0
62
+ ? message
63
+ : "Wallet state exists but could not be loaded from the local secret provider.";
64
+ }
65
+ async function normalizeLoadedWalletStateForRead(options) {
66
+ if (options.dataDir === undefined) {
67
+ return options.loaded;
68
+ }
69
+ const node = await options.dependencies.attachOrStartManagedBitcoindService({
70
+ dataDir: options.dataDir,
71
+ chain: "main",
72
+ startHeight: 0,
73
+ walletRootId: options.loaded.state.walletRootId,
74
+ });
75
+ try {
76
+ const access = {
77
+ provider: options.access.provider,
78
+ secretReference: createWalletSecretReference(options.loaded.state.walletRootId),
79
+ };
80
+ const normalized = await persistNormalizedWalletDescriptorStateIfNeeded({
81
+ state: options.loaded.state,
82
+ access,
83
+ paths: options.paths,
84
+ nowUnixMs: options.now,
85
+ replacePrimary: options.loaded.source === "backup",
86
+ rpc: options.dependencies.createRpcClient(node.rpc),
87
+ });
88
+ const coinControl = await persistWalletCoinControlStateIfNeeded({
89
+ state: normalized.state,
90
+ access,
91
+ paths: options.paths,
92
+ nowUnixMs: options.now,
93
+ replacePrimary: (normalized.changed ? "primary" : options.loaded.source) === "backup",
94
+ rpc: options.dependencies.createRpcClient(node.rpc),
95
+ });
96
+ return {
97
+ source: coinControl.changed ? "primary" : normalized.changed ? "primary" : options.loaded.source,
98
+ state: coinControl.state,
99
+ };
100
+ }
101
+ finally {
102
+ await node.stop?.().catch(() => undefined);
103
+ }
104
+ }
105
+ export async function inspectWalletLocalStateWithDependencies(options = {}, dependencies = defaultWalletLocalStateDeps) {
106
+ const paths = options.paths ?? resolveWalletRuntimePathsForTesting();
107
+ const now = options.now ?? Date.now();
108
+ const provider = options.secretProvider ?? createDefaultWalletSecretProvider();
109
+ const [hasPrimaryStateFile, hasBackupStateFile] = await Promise.all([
110
+ pathExists(paths.walletStatePath),
111
+ pathExists(paths.walletStateBackupPath),
112
+ ]);
113
+ const clientPasswordReadiness = await inspectClientPasswordSetupReadiness(provider).catch(() => "ready");
114
+ if (!hasPrimaryStateFile && !hasBackupStateFile) {
115
+ return {
116
+ availability: "uninitialized",
117
+ clientPasswordReadiness,
118
+ unlockRequired: false,
119
+ walletRootId: null,
120
+ state: null,
121
+ source: null,
122
+ hasPrimaryStateFile,
123
+ hasBackupStateFile,
124
+ message: "Wallet state has not been initialized yet.",
125
+ };
126
+ }
127
+ if (clientPasswordReadiness !== "ready") {
128
+ const rawEnvelope = await loadRawWalletStateEnvelope({
129
+ primaryPath: paths.walletStatePath,
130
+ backupPath: paths.walletStateBackupPath,
131
+ }).catch(() => null);
132
+ if (rawEnvelope?.envelope.secretProvider == null) {
133
+ return {
134
+ availability: "local-state-corrupt",
135
+ clientPasswordReadiness: "ready",
136
+ unlockRequired: false,
137
+ walletRootId: extractWalletRootIdHintFromWalletStateEnvelope(rawEnvelope?.envelope ?? null),
138
+ state: null,
139
+ source: null,
140
+ hasPrimaryStateFile,
141
+ hasBackupStateFile,
142
+ message: "Wallet state exists but was created by an older Cogcoin wallet format that this version no longer loads directly.",
143
+ };
144
+ }
145
+ const resolvedRoot = await resolveWalletRootIdFromLocalArtifacts({
146
+ paths,
147
+ provider,
148
+ }).catch(() => null);
149
+ return {
150
+ availability: "local-state-corrupt",
151
+ clientPasswordReadiness,
152
+ unlockRequired: false,
153
+ walletRootId: resolvedRoot?.walletRootId ?? null,
154
+ state: null,
155
+ source: null,
156
+ hasPrimaryStateFile,
157
+ hasBackupStateFile,
158
+ message: clientPasswordReadiness === "migration-required"
159
+ ? describeClientPasswordMigrationMessage()
160
+ : describeClientPasswordSetupMessage(),
161
+ };
162
+ }
163
+ try {
164
+ const loaded = await loadWalletState({
165
+ primaryPath: paths.walletStatePath,
166
+ backupPath: paths.walletStateBackupPath,
167
+ }, {
168
+ provider,
169
+ });
170
+ const normalized = await normalizeLoadedWalletStateForRead({
171
+ loaded,
172
+ access: { provider },
173
+ dataDir: options.dataDir,
174
+ now,
175
+ paths,
176
+ dependencies,
177
+ });
178
+ return {
179
+ availability: "ready",
180
+ clientPasswordReadiness,
181
+ unlockRequired: false,
182
+ walletRootId: normalized.state.walletRootId,
183
+ state: normalizeWalletStateRecord({
184
+ ...normalized.state,
185
+ miningState: normalizeMiningStateRecord(normalized.state.miningState),
186
+ }),
187
+ source: normalized.source,
188
+ hasPrimaryStateFile,
189
+ hasBackupStateFile,
190
+ message: null,
191
+ };
192
+ }
193
+ catch (error) {
194
+ const resolvedRoot = await resolveWalletRootIdFromLocalArtifacts({
195
+ paths,
196
+ provider,
197
+ }).catch(() => null);
198
+ const message = error instanceof Error ? error.message : String(error);
199
+ return {
200
+ availability: "local-state-corrupt",
201
+ clientPasswordReadiness,
202
+ unlockRequired: message === "wallet_client_password_locked",
203
+ walletRootId: resolvedRoot?.walletRootId ?? null,
204
+ state: null,
205
+ source: null,
206
+ hasPrimaryStateFile,
207
+ hasBackupStateFile,
208
+ message: isWalletAccessError(error)
209
+ ? describeWalletAccessMessage({ accessError: error })
210
+ : error instanceof Error
211
+ ? error.message
212
+ : String(error),
213
+ };
214
+ }
215
+ }
216
+ export async function inspectWalletLocalState(options = {}) {
217
+ return inspectWalletLocalStateWithDependencies(options);
218
+ }
219
+ export async function readFundingSpendableSats(options) {
220
+ if (options.state === null || options.rpc === null) {
221
+ return null;
222
+ }
223
+ const state = options.state;
224
+ try {
225
+ const utxos = await options.rpc.listUnspent(state.managedCoreWallet.walletName, 1);
226
+ return utxos.reduce((sum, entry) => isSpendableFundingUtxo(entry, state.funding.scriptPubKeyHex)
227
+ ? sum + btcAmountToSats(entry.amount)
228
+ : sum, 0n);
229
+ }
230
+ catch {
231
+ return null;
232
+ }
233
+ }
@@ -0,0 +1,30 @@
1
+ import { loadBundledGenesisParameters } from "@cogcoin/indexer";
2
+ import type { ManagedWalletNodeConnection } from "../../bitcoind/managed-runtime/types.js";
3
+ import { createRpcClient } from "../../bitcoind/node.js";
4
+ import { attachOrStartManagedBitcoindService, probeManagedBitcoindService } from "../../bitcoind/service.js";
5
+ import type { ManagedBitcoindNodeHandle } from "../../bitcoind/types.js";
6
+ import { verifyManagedCoreWalletReplica } from "../lifecycle.js";
7
+ import type { WalletBitcoindStatus, WalletLocalStateStatus, WalletNodeStatus, WalletServiceHealth } from "./types.js";
8
+ export type ManagedWalletBitcoindReadDeps = {
9
+ loadBundledGenesisParameters: typeof loadBundledGenesisParameters;
10
+ probeManagedBitcoindService: typeof probeManagedBitcoindService;
11
+ attachOrStartManagedBitcoindService: typeof attachOrStartManagedBitcoindService;
12
+ createRpcClient: typeof createRpcClient;
13
+ verifyManagedCoreWalletReplica: typeof verifyManagedCoreWalletReplica;
14
+ };
15
+ export interface ManagedWalletBitcoindReadState {
16
+ node: ManagedWalletNodeConnection<ManagedBitcoindNodeHandle, ReturnType<typeof createRpcClient>>;
17
+ bitcoind: WalletBitcoindStatus;
18
+ nodeHealth: WalletServiceHealth;
19
+ nodeMessage: string | null;
20
+ }
21
+ export declare function deriveNodeHealthForTesting(status: WalletNodeStatus | null, bitcoindHealth: WalletBitcoindStatus["health"]): {
22
+ health: WalletServiceHealth;
23
+ message: string | null;
24
+ };
25
+ export declare function openManagedWalletBitcoindReadState(options: {
26
+ dataDir: string;
27
+ walletRootId: string;
28
+ localState: WalletLocalStateStatus;
29
+ startupTimeoutMs: number;
30
+ }, dependencies?: ManagedWalletBitcoindReadDeps): Promise<ManagedWalletBitcoindReadState>;
@@ -0,0 +1,138 @@
1
+ import { loadBundledGenesisParameters } from "@cogcoin/indexer";
2
+ import { deriveManagedBitcoindWalletStatus, resolveManagedBitcoindProbeDecision, } from "../../bitcoind/managed-runtime/bitcoind-policy.js";
3
+ import { createRpcClient } from "../../bitcoind/node.js";
4
+ import { resolveCogcoinProcessingStartHeight } from "../../bitcoind/processing-start-height.js";
5
+ import { attachOrStartManagedBitcoindService, probeManagedBitcoindService, } from "../../bitcoind/service.js";
6
+ import { verifyManagedCoreWalletReplica } from "../lifecycle.js";
7
+ const TOLERATED_NODE_HEADER_LEAD_BLOCKS = 2;
8
+ const TOLERATED_NODE_HEADER_LEAD_MESSAGE = "Bitcoin headers can briefly lead validated blocks; a short 1-2 block lead is normal and is being tolerated.";
9
+ const NODE_CATCHING_UP_MESSAGE = "Bitcoin Core is still catching up to headers.";
10
+ const defaultManagedWalletBitcoindReadDeps = {
11
+ loadBundledGenesisParameters,
12
+ probeManagedBitcoindService,
13
+ attachOrStartManagedBitcoindService,
14
+ createRpcClient,
15
+ verifyManagedCoreWalletReplica,
16
+ };
17
+ function deriveNodeHealth(status, bitcoindHealth) {
18
+ if (bitcoindHealth !== "ready" || status === null || !status.ready) {
19
+ return {
20
+ health: "catching-up",
21
+ message: NODE_CATCHING_UP_MESSAGE,
22
+ };
23
+ }
24
+ const headerLead = status.nodeBestHeight !== null && status.nodeHeaderHeight !== null
25
+ ? status.nodeHeaderHeight - status.nodeBestHeight
26
+ : null;
27
+ if (headerLead !== null && headerLead > 0) {
28
+ if (headerLead <= TOLERATED_NODE_HEADER_LEAD_BLOCKS) {
29
+ return {
30
+ health: "synced",
31
+ message: TOLERATED_NODE_HEADER_LEAD_MESSAGE,
32
+ };
33
+ }
34
+ return {
35
+ health: "catching-up",
36
+ message: NODE_CATCHING_UP_MESSAGE,
37
+ };
38
+ }
39
+ return {
40
+ health: "synced",
41
+ message: null,
42
+ };
43
+ }
44
+ export function deriveNodeHealthForTesting(status, bitcoindHealth) {
45
+ return deriveNodeHealth(status, bitcoindHealth);
46
+ }
47
+ async function attachNodeStatus(options, dependencies) {
48
+ try {
49
+ const probe = await dependencies.probeManagedBitcoindService({
50
+ dataDir: options.dataDir,
51
+ chain: "main",
52
+ startHeight: 0,
53
+ walletRootId: options.walletRootId,
54
+ startupTimeoutMs: options.startupTimeoutMs,
55
+ });
56
+ const decision = resolveManagedBitcoindProbeDecision(probe);
57
+ if (decision.action === "reject") {
58
+ return {
59
+ handle: null,
60
+ rpc: null,
61
+ status: null,
62
+ observedStatus: probe.status,
63
+ error: decision.error,
64
+ };
65
+ }
66
+ const genesis = await dependencies.loadBundledGenesisParameters();
67
+ const handle = await dependencies.attachOrStartManagedBitcoindService({
68
+ dataDir: options.dataDir,
69
+ chain: "main",
70
+ startHeight: resolveCogcoinProcessingStartHeight(genesis),
71
+ walletRootId: options.walletRootId,
72
+ startupTimeoutMs: options.startupTimeoutMs,
73
+ });
74
+ const rpc = dependencies.createRpcClient(handle.rpc);
75
+ const [chainInfo, serviceStatus] = await Promise.all([
76
+ rpc.getBlockchainInfo(),
77
+ handle.refreshServiceStatus?.(),
78
+ ]);
79
+ const status = {
80
+ ready: true,
81
+ chain: chainInfo.chain,
82
+ pid: handle.pid,
83
+ walletRootId: handle.walletRootId ?? null,
84
+ nodeBestHeight: chainInfo.blocks,
85
+ nodeBestHashHex: chainInfo.bestblockhash,
86
+ nodeHeaderHeight: chainInfo.headers,
87
+ serviceUpdatedAtUnixMs: serviceStatus?.updatedAtUnixMs ?? null,
88
+ serviceStatus: serviceStatus ?? null,
89
+ walletReplica: serviceStatus?.walletReplica ?? null,
90
+ walletReplicaMessage: serviceStatus?.walletReplica?.message ?? null,
91
+ };
92
+ return {
93
+ handle,
94
+ rpc,
95
+ status,
96
+ observedStatus: serviceStatus ?? null,
97
+ error: null,
98
+ };
99
+ }
100
+ catch (error) {
101
+ return {
102
+ handle: null,
103
+ rpc: null,
104
+ status: null,
105
+ observedStatus: null,
106
+ error: error instanceof Error ? error.message : String(error),
107
+ };
108
+ }
109
+ }
110
+ export async function openManagedWalletBitcoindReadState(options, dependencies = defaultManagedWalletBitcoindReadDeps) {
111
+ const node = await attachNodeStatus({
112
+ dataDir: options.dataDir,
113
+ walletRootId: options.walletRootId,
114
+ startupTimeoutMs: options.startupTimeoutMs,
115
+ }, dependencies);
116
+ if (options.localState.state !== null && node.status !== null) {
117
+ const verifiedReplica = await dependencies.verifyManagedCoreWalletReplica(options.localState.state, options.dataDir, {
118
+ nodeHandle: node.handle ?? undefined,
119
+ });
120
+ node.status = {
121
+ ...node.status,
122
+ walletReplica: verifiedReplica,
123
+ walletReplicaMessage: verifiedReplica.message ?? null,
124
+ };
125
+ }
126
+ const bitcoind = deriveManagedBitcoindWalletStatus({
127
+ status: node.observedStatus,
128
+ nodeStatus: node.status,
129
+ startupError: node.error,
130
+ });
131
+ const nodeDerived = deriveNodeHealth(node.status, bitcoind.health);
132
+ return {
133
+ node,
134
+ bitcoind,
135
+ nodeHealth: nodeDerived.health,
136
+ nodeMessage: nodeDerived.message,
137
+ };
138
+ }
@@ -0,0 +1,23 @@
1
+ import { attachOrStartIndexerDaemon, probeIndexerDaemon, readObservedIndexerDaemonStatus, readSnapshotWithRetry, type IndexerDaemonClient } from "../../bitcoind/indexer-daemon.js";
2
+ import type { ManagedBitcoindNodeHandle } from "../../bitcoind/types.js";
3
+ import type { WalletIndexerStatus, WalletSnapshotView } from "./types.js";
4
+ export type ManagedWalletIndexerReadDeps = {
5
+ probeIndexerDaemon: typeof probeIndexerDaemon;
6
+ attachOrStartIndexerDaemon: typeof attachOrStartIndexerDaemon;
7
+ readSnapshotWithRetry: typeof readSnapshotWithRetry;
8
+ readObservedIndexerDaemonStatus: typeof readObservedIndexerDaemonStatus;
9
+ };
10
+ export interface ManagedWalletIndexerReadState {
11
+ daemonClient: IndexerDaemonClient | null;
12
+ indexer: WalletIndexerStatus;
13
+ snapshot: WalletSnapshotView | null;
14
+ }
15
+ export declare function openManagedWalletIndexerReadState(options: {
16
+ dataDir: string;
17
+ databasePath: string;
18
+ walletRootId: string;
19
+ startupTimeoutMs: number;
20
+ expectedIndexerBinaryVersion: string | null;
21
+ now: number;
22
+ nodeHandle: ManagedBitcoindNodeHandle | null;
23
+ }, dependencies?: ManagedWalletIndexerReadDeps): Promise<ManagedWalletIndexerReadState>;
@@ -0,0 +1,87 @@
1
+ import { deserializeIndexerState } from "@cogcoin/indexer";
2
+ import { attachOrStartIndexerDaemon, INDEXER_DAEMON_BACKGROUND_FOLLOW_RECOVERY_FAILED, probeIndexerDaemon, readObservedIndexerDaemonStatus, readSnapshotWithRetry, } from "../../bitcoind/indexer-daemon.js";
3
+ import { deriveManagedIndexerWalletStatus, resolveIndexerDaemonProbeDecision, } from "../../bitcoind/managed-runtime/indexer-policy.js";
4
+ const defaultManagedWalletIndexerReadDeps = {
5
+ probeIndexerDaemon,
6
+ attachOrStartIndexerDaemon,
7
+ readSnapshotWithRetry,
8
+ readObservedIndexerDaemonStatus,
9
+ };
10
+ export async function openManagedWalletIndexerReadState(options, dependencies = defaultManagedWalletIndexerReadDeps) {
11
+ let daemonClient = null;
12
+ let daemonStatus = null;
13
+ let observedDaemonStatus = null;
14
+ let snapshot = null;
15
+ let indexerSource = "none";
16
+ let daemonError = null;
17
+ try {
18
+ const probe = await dependencies.probeIndexerDaemon({
19
+ dataDir: options.dataDir,
20
+ walletRootId: options.walletRootId,
21
+ });
22
+ const probeDecision = resolveIndexerDaemonProbeDecision({
23
+ probe,
24
+ expectedBinaryVersion: options.expectedIndexerBinaryVersion,
25
+ });
26
+ if (probeDecision.action !== "reject") {
27
+ await probe.client?.close().catch(() => undefined);
28
+ daemonClient = await dependencies.attachOrStartIndexerDaemon({
29
+ dataDir: options.dataDir,
30
+ databasePath: options.databasePath,
31
+ walletRootId: options.walletRootId,
32
+ startupTimeoutMs: options.startupTimeoutMs,
33
+ ensureBackgroundFollow: true,
34
+ expectedBinaryVersion: options.expectedIndexerBinaryVersion,
35
+ });
36
+ }
37
+ else {
38
+ observedDaemonStatus = probe.status;
39
+ indexerSource = probe.status === null ? "none" : "probe";
40
+ daemonError = probeDecision.error;
41
+ }
42
+ if (daemonClient !== null) {
43
+ const lease = await dependencies.readSnapshotWithRetry(daemonClient, options.walletRootId);
44
+ daemonStatus = lease.status;
45
+ observedDaemonStatus = lease.status;
46
+ snapshot = {
47
+ tip: lease.payload.tip,
48
+ state: deserializeIndexerState(Buffer.from(lease.payload.stateBase64, "base64")),
49
+ source: "lease",
50
+ daemonInstanceId: lease.payload.daemonInstanceId,
51
+ snapshotSeq: lease.payload.snapshotSeq,
52
+ openedAtUnixMs: lease.payload.openedAtUnixMs,
53
+ };
54
+ indexerSource = "lease";
55
+ }
56
+ }
57
+ catch (error) {
58
+ daemonError = error instanceof Error ? error.message : String(error);
59
+ if (daemonError === INDEXER_DAEMON_BACKGROUND_FOLLOW_RECOVERY_FAILED) {
60
+ await daemonClient?.close().catch(() => undefined);
61
+ await options.nodeHandle?.stop().catch(() => undefined);
62
+ throw error;
63
+ }
64
+ if (observedDaemonStatus === null) {
65
+ observedDaemonStatus = await dependencies.readObservedIndexerDaemonStatus({
66
+ dataDir: options.dataDir,
67
+ walletRootId: options.walletRootId,
68
+ }).catch(() => null);
69
+ if (observedDaemonStatus !== null) {
70
+ indexerSource = "status-file";
71
+ }
72
+ }
73
+ }
74
+ const indexer = deriveManagedIndexerWalletStatus({
75
+ daemonStatus,
76
+ observedStatus: observedDaemonStatus,
77
+ snapshot,
78
+ source: indexerSource,
79
+ now: options.now,
80
+ startupError: daemonError,
81
+ });
82
+ return {
83
+ daemonClient,
84
+ indexer,
85
+ snapshot,
86
+ };
87
+ }
@@ -1,26 +1,11 @@
1
- import { loadBundledGenesisParameters } from "@cogcoin/indexer";
2
- import { attachOrStartIndexerDaemon, probeIndexerDaemon, readObservedIndexerDaemonStatus, readSnapshotWithRetry, type IndexerDaemonClient } from "../../bitcoind/indexer-daemon.js";
1
+ import { type IndexerDaemonClient } from "../../bitcoind/indexer-daemon.js";
3
2
  import type { ManagedWalletReadServiceBundle } from "../../bitcoind/managed-runtime/types.js";
4
3
  import { createRpcClient } from "../../bitcoind/node.js";
5
- import { attachOrStartManagedBitcoindService, probeManagedBitcoindService } from "../../bitcoind/service.js";
6
4
  import type { ManagedBitcoindNodeHandle } from "../../bitcoind/types.js";
7
- import { verifyManagedCoreWalletReplica } from "../lifecycle.js";
8
- import type { WalletBitcoindStatus, WalletLocalStateStatus, WalletNodeStatus, WalletServiceHealth } from "./types.js";
9
- type ManagedWalletReadServiceDeps = {
10
- loadBundledGenesisParameters: typeof loadBundledGenesisParameters;
11
- probeManagedBitcoindService: typeof probeManagedBitcoindService;
12
- attachOrStartManagedBitcoindService: typeof attachOrStartManagedBitcoindService;
13
- createRpcClient: typeof createRpcClient;
14
- verifyManagedCoreWalletReplica: typeof verifyManagedCoreWalletReplica;
15
- probeIndexerDaemon: typeof probeIndexerDaemon;
16
- attachOrStartIndexerDaemon: typeof attachOrStartIndexerDaemon;
17
- readSnapshotWithRetry: typeof readSnapshotWithRetry;
18
- readObservedIndexerDaemonStatus: typeof readObservedIndexerDaemonStatus;
19
- };
20
- export declare function deriveNodeHealthForTesting(status: WalletNodeStatus | null, bitcoindHealth: WalletBitcoindStatus["health"]): {
21
- health: WalletServiceHealth;
22
- message: string | null;
23
- };
5
+ import type { WalletLocalStateStatus } from "./types.js";
6
+ import { deriveNodeHealthForTesting, type ManagedWalletBitcoindReadDeps } from "./managed-bitcoind.js";
7
+ import { type ManagedWalletIndexerReadDeps } from "./managed-indexer.js";
8
+ type ManagedWalletReadServiceDeps = ManagedWalletBitcoindReadDeps & ManagedWalletIndexerReadDeps;
24
9
  export declare function openManagedWalletReadServiceBundle(options: {
25
10
  dataDir: string;
26
11
  databasePath: string;
@@ -30,4 +15,4 @@ export declare function openManagedWalletReadServiceBundle(options: {
30
15
  expectedIndexerBinaryVersion: string | null;
31
16
  now: number;
32
17
  }, dependencies?: ManagedWalletReadServiceDeps): Promise<ManagedWalletReadServiceBundle<ManagedBitcoindNodeHandle, ReturnType<typeof createRpcClient>, IndexerDaemonClient>>;
33
- export {};
18
+ export { deriveNodeHealthForTesting };