@cogcoin/client 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (289) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +136 -0
  3. package/dist/app-paths.d.ts +38 -0
  4. package/dist/app-paths.js +121 -0
  5. package/dist/art/banner.txt +13 -0
  6. package/dist/art/scroll.txt +13 -0
  7. package/dist/art/train-car.txt +6 -0
  8. package/dist/art/train-smoke.txt +6 -0
  9. package/dist/art/train.txt +6 -0
  10. package/dist/bitcoind/bootstrap/chainstate.d.ts +4 -0
  11. package/dist/bitcoind/bootstrap/chainstate.js +13 -0
  12. package/dist/bitcoind/bootstrap/constants.d.ts +7 -0
  13. package/dist/bitcoind/bootstrap/constants.js +12 -0
  14. package/dist/bitcoind/bootstrap/controller.d.ts +29 -0
  15. package/dist/bitcoind/bootstrap/controller.js +101 -0
  16. package/dist/bitcoind/bootstrap/download.d.ts +2 -0
  17. package/dist/bitcoind/bootstrap/download.js +196 -0
  18. package/dist/bitcoind/bootstrap/headers.d.ts +13 -0
  19. package/dist/bitcoind/bootstrap/headers.js +61 -0
  20. package/dist/bitcoind/bootstrap/paths.d.ts +4 -0
  21. package/dist/bitcoind/bootstrap/paths.js +15 -0
  22. package/dist/bitcoind/bootstrap/snapshot-file.d.ts +7 -0
  23. package/dist/bitcoind/bootstrap/snapshot-file.js +42 -0
  24. package/dist/bitcoind/bootstrap/state.d.ts +40 -0
  25. package/dist/bitcoind/bootstrap/state.js +70 -0
  26. package/dist/bitcoind/bootstrap/types.d.ts +28 -0
  27. package/dist/bitcoind/bootstrap/types.js +1 -0
  28. package/dist/bitcoind/bootstrap.d.ts +8 -0
  29. package/dist/bitcoind/bootstrap.js +7 -0
  30. package/dist/bitcoind/client/factory.d.ts +3 -0
  31. package/dist/bitcoind/client/factory.js +57 -0
  32. package/dist/bitcoind/client/follow-block-times.d.ts +8 -0
  33. package/dist/bitcoind/client/follow-block-times.js +25 -0
  34. package/dist/bitcoind/client/follow-loop.d.ts +10 -0
  35. package/dist/bitcoind/client/follow-loop.js +57 -0
  36. package/dist/bitcoind/client/internal-types.d.ts +63 -0
  37. package/dist/bitcoind/client/internal-types.js +18 -0
  38. package/dist/bitcoind/client/managed-client.d.ts +20 -0
  39. package/dist/bitcoind/client/managed-client.js +197 -0
  40. package/dist/bitcoind/client/rate-tracker.d.ts +2 -0
  41. package/dist/bitcoind/client/rate-tracker.js +24 -0
  42. package/dist/bitcoind/client/sync-engine.d.ts +3 -0
  43. package/dist/bitcoind/client/sync-engine.js +143 -0
  44. package/dist/bitcoind/client.d.ts +1 -0
  45. package/dist/bitcoind/client.js +1 -0
  46. package/dist/bitcoind/errors.d.ts +1 -0
  47. package/dist/bitcoind/errors.js +49 -0
  48. package/dist/bitcoind/index.d.ts +2 -0
  49. package/dist/bitcoind/index.js +1 -0
  50. package/dist/bitcoind/indexer-daemon-main.d.ts +1 -0
  51. package/dist/bitcoind/indexer-daemon-main.js +472 -0
  52. package/dist/bitcoind/indexer-daemon.d.ts +107 -0
  53. package/dist/bitcoind/indexer-daemon.js +391 -0
  54. package/dist/bitcoind/node.d.ts +8 -0
  55. package/dist/bitcoind/node.js +219 -0
  56. package/dist/bitcoind/normalize.d.ts +3 -0
  57. package/dist/bitcoind/normalize.js +47 -0
  58. package/dist/bitcoind/progress/assets.d.ts +10 -0
  59. package/dist/bitcoind/progress/assets.js +90 -0
  60. package/dist/bitcoind/progress/constants.d.ts +48 -0
  61. package/dist/bitcoind/progress/constants.js +53 -0
  62. package/dist/bitcoind/progress/controller.d.ts +28 -0
  63. package/dist/bitcoind/progress/controller.js +188 -0
  64. package/dist/bitcoind/progress/follow-scene.d.ts +40 -0
  65. package/dist/bitcoind/progress/follow-scene.js +367 -0
  66. package/dist/bitcoind/progress/formatting.d.ts +23 -0
  67. package/dist/bitcoind/progress/formatting.js +227 -0
  68. package/dist/bitcoind/progress/quote-scene.d.ts +4 -0
  69. package/dist/bitcoind/progress/quote-scene.js +137 -0
  70. package/dist/bitcoind/progress/train-scene.d.ts +9 -0
  71. package/dist/bitcoind/progress/train-scene.js +92 -0
  72. package/dist/bitcoind/progress/tty-renderer.d.ts +18 -0
  73. package/dist/bitcoind/progress/tty-renderer.js +150 -0
  74. package/dist/bitcoind/progress.d.ts +7 -0
  75. package/dist/bitcoind/progress.js +7 -0
  76. package/dist/bitcoind/quotes.d.ts +24 -0
  77. package/dist/bitcoind/quotes.js +195 -0
  78. package/dist/bitcoind/rpc.d.ts +71 -0
  79. package/dist/bitcoind/rpc.js +322 -0
  80. package/dist/bitcoind/service-paths.d.ts +19 -0
  81. package/dist/bitcoind/service-paths.js +49 -0
  82. package/dist/bitcoind/service.d.ts +40 -0
  83. package/dist/bitcoind/service.js +735 -0
  84. package/dist/bitcoind/testing.d.ts +9 -0
  85. package/dist/bitcoind/testing.js +9 -0
  86. package/dist/bitcoind/types.d.ts +396 -0
  87. package/dist/bitcoind/types.js +3 -0
  88. package/dist/bytes.d.ts +9 -0
  89. package/dist/bytes.js +36 -0
  90. package/dist/cli/commands/follow.d.ts +2 -0
  91. package/dist/cli/commands/follow.js +43 -0
  92. package/dist/cli/commands/mining-admin.d.ts +2 -0
  93. package/dist/cli/commands/mining-admin.js +92 -0
  94. package/dist/cli/commands/mining-read.d.ts +2 -0
  95. package/dist/cli/commands/mining-read.js +173 -0
  96. package/dist/cli/commands/mining-runtime.d.ts +2 -0
  97. package/dist/cli/commands/mining-runtime.js +108 -0
  98. package/dist/cli/commands/status.d.ts +2 -0
  99. package/dist/cli/commands/status.js +31 -0
  100. package/dist/cli/commands/sync.d.ts +2 -0
  101. package/dist/cli/commands/sync.js +52 -0
  102. package/dist/cli/commands/wallet-admin.d.ts +2 -0
  103. package/dist/cli/commands/wallet-admin.js +175 -0
  104. package/dist/cli/commands/wallet-mutation.d.ts +2 -0
  105. package/dist/cli/commands/wallet-mutation.js +681 -0
  106. package/dist/cli/commands/wallet-read.d.ts +2 -0
  107. package/dist/cli/commands/wallet-read.js +265 -0
  108. package/dist/cli/context.d.ts +3 -0
  109. package/dist/cli/context.js +75 -0
  110. package/dist/cli/io.d.ts +3 -0
  111. package/dist/cli/io.js +12 -0
  112. package/dist/cli/mining-format.d.ts +5 -0
  113. package/dist/cli/mining-format.js +156 -0
  114. package/dist/cli/mining-json.d.ts +49 -0
  115. package/dist/cli/mining-json.js +89 -0
  116. package/dist/cli/mutation-command-groups.d.ts +15 -0
  117. package/dist/cli/mutation-command-groups.js +71 -0
  118. package/dist/cli/mutation-json.d.ts +430 -0
  119. package/dist/cli/mutation-json.js +311 -0
  120. package/dist/cli/mutation-resolved-json.d.ts +124 -0
  121. package/dist/cli/mutation-resolved-json.js +129 -0
  122. package/dist/cli/mutation-success.d.ts +20 -0
  123. package/dist/cli/mutation-success.js +47 -0
  124. package/dist/cli/mutation-text-format.d.ts +22 -0
  125. package/dist/cli/mutation-text-format.js +171 -0
  126. package/dist/cli/mutation-text-write.d.ts +13 -0
  127. package/dist/cli/mutation-text-write.js +16 -0
  128. package/dist/cli/output.d.ts +185 -0
  129. package/dist/cli/output.js +1085 -0
  130. package/dist/cli/parse.d.ts +3 -0
  131. package/dist/cli/parse.js +971 -0
  132. package/dist/cli/preview-json.d.ts +416 -0
  133. package/dist/cli/preview-json.js +293 -0
  134. package/dist/cli/prompt.d.ts +3 -0
  135. package/dist/cli/prompt.js +33 -0
  136. package/dist/cli/read-json.d.ts +187 -0
  137. package/dist/cli/read-json.js +675 -0
  138. package/dist/cli/runner.d.ts +2 -0
  139. package/dist/cli/runner.js +129 -0
  140. package/dist/cli/signals.d.ts +3 -0
  141. package/dist/cli/signals.js +63 -0
  142. package/dist/cli/status-format.d.ts +2 -0
  143. package/dist/cli/status-format.js +48 -0
  144. package/dist/cli/types.d.ts +148 -0
  145. package/dist/cli/types.js +2 -0
  146. package/dist/cli/wallet-format.d.ts +29 -0
  147. package/dist/cli/wallet-format.js +637 -0
  148. package/dist/cli/workflow-hints.d.ts +13 -0
  149. package/dist/cli/workflow-hints.js +94 -0
  150. package/dist/cli-runner.d.ts +3 -0
  151. package/dist/cli-runner.js +3 -0
  152. package/dist/cli.d.ts +2 -0
  153. package/dist/cli.js +6 -0
  154. package/dist/client/default-client.d.ts +11 -0
  155. package/dist/client/default-client.js +118 -0
  156. package/dist/client/factory.d.ts +2 -0
  157. package/dist/client/factory.js +15 -0
  158. package/dist/client/initialization.d.ts +6 -0
  159. package/dist/client/initialization.js +30 -0
  160. package/dist/client/persistence.d.ts +5 -0
  161. package/dist/client/persistence.js +28 -0
  162. package/dist/client/store-adapter.d.ts +3 -0
  163. package/dist/client/store-adapter.js +20 -0
  164. package/dist/client.d.ts +2 -0
  165. package/dist/client.js +2 -0
  166. package/dist/index.d.ts +2 -0
  167. package/dist/index.js +1 -0
  168. package/dist/passive-status.d.ts +36 -0
  169. package/dist/passive-status.js +100 -0
  170. package/dist/sqlite/better-sqlite3.d.ts +26 -0
  171. package/dist/sqlite/better-sqlite3.js +4 -0
  172. package/dist/sqlite/checkpoints.d.ts +11 -0
  173. package/dist/sqlite/checkpoints.js +27 -0
  174. package/dist/sqlite/driver.d.ts +17 -0
  175. package/dist/sqlite/driver.js +98 -0
  176. package/dist/sqlite/index.d.ts +4 -0
  177. package/dist/sqlite/index.js +9 -0
  178. package/dist/sqlite/migrate.d.ts +2 -0
  179. package/dist/sqlite/migrate.js +37 -0
  180. package/dist/sqlite/store.d.ts +3 -0
  181. package/dist/sqlite/store.js +122 -0
  182. package/dist/sqlite/tip-meta.d.ts +26 -0
  183. package/dist/sqlite/tip-meta.js +97 -0
  184. package/dist/sqlite/types.d.ts +10 -0
  185. package/dist/sqlite/types.js +1 -0
  186. package/dist/types.d.ts +55 -0
  187. package/dist/types.js +1 -0
  188. package/dist/wallet/archive.d.ts +4 -0
  189. package/dist/wallet/archive.js +39 -0
  190. package/dist/wallet/cogop/constants.d.ts +32 -0
  191. package/dist/wallet/cogop/constants.js +32 -0
  192. package/dist/wallet/cogop/index.d.ts +32 -0
  193. package/dist/wallet/cogop/index.js +213 -0
  194. package/dist/wallet/cogop/numeric.d.ts +3 -0
  195. package/dist/wallet/cogop/numeric.js +24 -0
  196. package/dist/wallet/cogop/scriptpubkey.d.ts +2 -0
  197. package/dist/wallet/cogop/scriptpubkey.js +13 -0
  198. package/dist/wallet/cogop/validate-name.d.ts +2 -0
  199. package/dist/wallet/cogop/validate-name.js +18 -0
  200. package/dist/wallet/fs/atomic.d.ts +6 -0
  201. package/dist/wallet/fs/atomic.js +46 -0
  202. package/dist/wallet/fs/lock.d.ts +19 -0
  203. package/dist/wallet/fs/lock.js +61 -0
  204. package/dist/wallet/fs/status-file.d.ts +1 -0
  205. package/dist/wallet/fs/status-file.js +4 -0
  206. package/dist/wallet/lifecycle.d.ts +193 -0
  207. package/dist/wallet/lifecycle.js +1475 -0
  208. package/dist/wallet/material.d.ts +45 -0
  209. package/dist/wallet/material.js +118 -0
  210. package/dist/wallet/mining/config.d.ts +18 -0
  211. package/dist/wallet/mining/config.js +44 -0
  212. package/dist/wallet/mining/constants.d.ts +24 -0
  213. package/dist/wallet/mining/constants.js +24 -0
  214. package/dist/wallet/mining/control.d.ts +53 -0
  215. package/dist/wallet/mining/control.js +758 -0
  216. package/dist/wallet/mining/coordination.d.ts +40 -0
  217. package/dist/wallet/mining/coordination.js +121 -0
  218. package/dist/wallet/mining/hook-protocol.d.ts +47 -0
  219. package/dist/wallet/mining/hook-protocol.js +161 -0
  220. package/dist/wallet/mining/hook-runner.d.ts +1 -0
  221. package/dist/wallet/mining/hook-runner.js +52 -0
  222. package/dist/wallet/mining/hooks.d.ts +38 -0
  223. package/dist/wallet/mining/hooks.js +520 -0
  224. package/dist/wallet/mining/index.d.ts +8 -0
  225. package/dist/wallet/mining/index.js +6 -0
  226. package/dist/wallet/mining/runner.d.ts +155 -0
  227. package/dist/wallet/mining/runner.js +2574 -0
  228. package/dist/wallet/mining/runtime-artifacts.d.ts +17 -0
  229. package/dist/wallet/mining/runtime-artifacts.js +166 -0
  230. package/dist/wallet/mining/sentences.d.ts +23 -0
  231. package/dist/wallet/mining/sentences.js +281 -0
  232. package/dist/wallet/mining/state.d.ts +9 -0
  233. package/dist/wallet/mining/state.js +75 -0
  234. package/dist/wallet/mining/types.d.ts +141 -0
  235. package/dist/wallet/mining/types.js +1 -0
  236. package/dist/wallet/mining/visualizer.d.ts +19 -0
  237. package/dist/wallet/mining/visualizer.js +134 -0
  238. package/dist/wallet/mining/worker-main.d.ts +1 -0
  239. package/dist/wallet/mining/worker-main.js +17 -0
  240. package/dist/wallet/read/context.d.ts +20 -0
  241. package/dist/wallet/read/context.js +532 -0
  242. package/dist/wallet/read/filter.d.ts +9 -0
  243. package/dist/wallet/read/filter.js +42 -0
  244. package/dist/wallet/read/index.d.ts +4 -0
  245. package/dist/wallet/read/index.js +3 -0
  246. package/dist/wallet/read/project.d.ts +11 -0
  247. package/dist/wallet/read/project.js +300 -0
  248. package/dist/wallet/read/types.d.ts +144 -0
  249. package/dist/wallet/read/types.js +1 -0
  250. package/dist/wallet/runtime.d.ts +26 -0
  251. package/dist/wallet/runtime.js +28 -0
  252. package/dist/wallet/state/crypto.d.ts +31 -0
  253. package/dist/wallet/state/crypto.js +127 -0
  254. package/dist/wallet/state/provider.d.ts +37 -0
  255. package/dist/wallet/state/provider.js +312 -0
  256. package/dist/wallet/state/session.d.ts +12 -0
  257. package/dist/wallet/state/session.js +23 -0
  258. package/dist/wallet/state/storage.d.ts +19 -0
  259. package/dist/wallet/state/storage.js +55 -0
  260. package/dist/wallet/tx/anchor.d.ts +40 -0
  261. package/dist/wallet/tx/anchor.js +1210 -0
  262. package/dist/wallet/tx/cog.d.ts +92 -0
  263. package/dist/wallet/tx/cog.js +1055 -0
  264. package/dist/wallet/tx/common.d.ts +89 -0
  265. package/dist/wallet/tx/common.js +156 -0
  266. package/dist/wallet/tx/confirm.d.ts +15 -0
  267. package/dist/wallet/tx/confirm.js +24 -0
  268. package/dist/wallet/tx/domain-admin.d.ts +105 -0
  269. package/dist/wallet/tx/domain-admin.js +869 -0
  270. package/dist/wallet/tx/domain-market.d.ts +112 -0
  271. package/dist/wallet/tx/domain-market.js +1365 -0
  272. package/dist/wallet/tx/field.d.ts +101 -0
  273. package/dist/wallet/tx/field.js +1853 -0
  274. package/dist/wallet/tx/identity-selector.d.ts +12 -0
  275. package/dist/wallet/tx/identity-selector.js +52 -0
  276. package/dist/wallet/tx/index.d.ts +7 -0
  277. package/dist/wallet/tx/index.js +7 -0
  278. package/dist/wallet/tx/journal.d.ts +5 -0
  279. package/dist/wallet/tx/journal.js +31 -0
  280. package/dist/wallet/tx/register.d.ts +68 -0
  281. package/dist/wallet/tx/register.js +952 -0
  282. package/dist/wallet/tx/reputation.d.ts +72 -0
  283. package/dist/wallet/tx/reputation.js +693 -0
  284. package/dist/wallet/tx/targets.d.ts +7 -0
  285. package/dist/wallet/tx/targets.js +122 -0
  286. package/dist/wallet/types.d.ts +249 -0
  287. package/dist/wallet/types.js +1 -0
  288. package/dist/writing_quotes.json +1654 -0
  289. package/package.json +78 -0
@@ -0,0 +1,532 @@
1
+ import { access, constants } from "node:fs/promises";
2
+ import { deserializeIndexerState, loadBundledGenesisParameters } from "@cogcoin/indexer";
3
+ import { attachOrStartIndexerDaemon, probeIndexerDaemon, readObservedIndexerDaemonStatus, readSnapshotWithRetry, } from "../../bitcoind/indexer-daemon.js";
4
+ import { createRpcClient } from "../../bitcoind/node.js";
5
+ import { UNINITIALIZED_WALLET_ROOT_ID } from "../../bitcoind/service-paths.js";
6
+ import { attachOrStartManagedBitcoindService, probeManagedBitcoindService, } from "../../bitcoind/service.js";
7
+ import {} from "../../bitcoind/types.js";
8
+ import { loadUnlockedWalletState, verifyManagedCoreWalletReplica, } from "../lifecycle.js";
9
+ import { inspectMiningControlPlane } from "../mining/index.js";
10
+ import { normalizeMiningStateRecord } from "../mining/state.js";
11
+ import { resolveWalletRuntimePathsForTesting } from "../runtime.js";
12
+ import { loadWalletState } from "../state/storage.js";
13
+ import { createDefaultWalletSecretProvider, } from "../state/provider.js";
14
+ import { createWalletReadModel } from "./project.js";
15
+ const DEFAULT_SERVICE_START_TIMEOUT_MS = 10_000;
16
+ const STALE_HEARTBEAT_THRESHOLD_MS = 15_000;
17
+ async function pathExists(path) {
18
+ try {
19
+ await access(path, constants.F_OK);
20
+ return true;
21
+ }
22
+ catch {
23
+ return false;
24
+ }
25
+ }
26
+ async function inspectWalletLocalState(options = {}) {
27
+ const paths = options.paths ?? resolveWalletRuntimePathsForTesting();
28
+ const now = options.now ?? Date.now();
29
+ const [hasPrimaryStateFile, hasBackupStateFile, hasUnlockSessionFile] = await Promise.all([
30
+ pathExists(paths.walletStatePath),
31
+ pathExists(paths.walletStateBackupPath),
32
+ pathExists(paths.walletUnlockSessionPath),
33
+ ]);
34
+ if (!hasPrimaryStateFile && !hasBackupStateFile) {
35
+ return {
36
+ availability: "uninitialized",
37
+ walletRootId: null,
38
+ state: null,
39
+ source: null,
40
+ unlockUntilUnixMs: null,
41
+ hasPrimaryStateFile,
42
+ hasBackupStateFile,
43
+ hasUnlockSessionFile,
44
+ message: "Wallet state has not been initialized yet.",
45
+ };
46
+ }
47
+ if (options.passphrase === undefined) {
48
+ try {
49
+ const provider = options.secretProvider ?? createDefaultWalletSecretProvider();
50
+ const unlocked = await loadUnlockedWalletState({
51
+ provider,
52
+ nowUnixMs: now,
53
+ paths,
54
+ });
55
+ if (unlocked === null) {
56
+ try {
57
+ await loadWalletState({
58
+ primaryPath: paths.walletStatePath,
59
+ backupPath: paths.walletStateBackupPath,
60
+ }, {
61
+ provider,
62
+ });
63
+ }
64
+ catch (error) {
65
+ return {
66
+ availability: "local-state-corrupt",
67
+ walletRootId: null,
68
+ state: null,
69
+ source: null,
70
+ unlockUntilUnixMs: null,
71
+ hasPrimaryStateFile,
72
+ hasBackupStateFile,
73
+ hasUnlockSessionFile,
74
+ message: error instanceof Error ? error.message : String(error),
75
+ };
76
+ }
77
+ return {
78
+ availability: "locked",
79
+ walletRootId: null,
80
+ state: null,
81
+ source: null,
82
+ unlockUntilUnixMs: null,
83
+ hasPrimaryStateFile,
84
+ hasBackupStateFile,
85
+ hasUnlockSessionFile,
86
+ message: hasUnlockSessionFile
87
+ ? "Wallet state exists but the unlock session is expired, invalid, or belongs to a different wallet root."
88
+ : "Wallet state exists but is currently locked.",
89
+ };
90
+ }
91
+ return {
92
+ availability: "ready",
93
+ walletRootId: unlocked.state.walletRootId,
94
+ state: {
95
+ ...unlocked.state,
96
+ miningState: normalizeMiningStateRecord(unlocked.state.miningState),
97
+ },
98
+ source: unlocked.source,
99
+ unlockUntilUnixMs: unlocked.session.unlockUntilUnixMs,
100
+ hasPrimaryStateFile,
101
+ hasBackupStateFile,
102
+ hasUnlockSessionFile,
103
+ message: null,
104
+ };
105
+ }
106
+ catch (error) {
107
+ return {
108
+ availability: "local-state-corrupt",
109
+ walletRootId: null,
110
+ state: null,
111
+ source: null,
112
+ unlockUntilUnixMs: null,
113
+ hasPrimaryStateFile,
114
+ hasBackupStateFile,
115
+ hasUnlockSessionFile,
116
+ message: error instanceof Error ? error.message : String(error),
117
+ };
118
+ }
119
+ }
120
+ try {
121
+ const loaded = await loadWalletState({
122
+ primaryPath: paths.walletStatePath,
123
+ backupPath: paths.walletStateBackupPath,
124
+ }, options.passphrase);
125
+ return {
126
+ availability: "ready",
127
+ walletRootId: loaded.state.walletRootId,
128
+ state: {
129
+ ...loaded.state,
130
+ miningState: normalizeMiningStateRecord(loaded.state.miningState),
131
+ },
132
+ source: loaded.source,
133
+ unlockUntilUnixMs: null,
134
+ hasPrimaryStateFile,
135
+ hasBackupStateFile,
136
+ hasUnlockSessionFile,
137
+ message: null,
138
+ };
139
+ }
140
+ catch (error) {
141
+ return {
142
+ availability: "local-state-corrupt",
143
+ walletRootId: null,
144
+ state: null,
145
+ source: null,
146
+ unlockUntilUnixMs: null,
147
+ hasPrimaryStateFile,
148
+ hasBackupStateFile,
149
+ hasUnlockSessionFile,
150
+ message: error instanceof Error ? error.message : String(error),
151
+ };
152
+ }
153
+ }
154
+ function mapIndexerStartupError(message) {
155
+ switch (message) {
156
+ case "indexer_daemon_start_timeout":
157
+ return {
158
+ health: "starting",
159
+ message: "Indexer daemon is still starting.",
160
+ };
161
+ case "indexer_daemon_service_version_mismatch":
162
+ return {
163
+ health: "service-version-mismatch",
164
+ message: "The live indexer daemon is running an incompatible service API version.",
165
+ };
166
+ case "indexer_daemon_schema_mismatch":
167
+ return {
168
+ health: "schema-mismatch",
169
+ message: "The live indexer daemon is using an incompatible sqlite schema.",
170
+ };
171
+ case "indexer_daemon_wallet_root_mismatch":
172
+ return {
173
+ health: "wallet-root-mismatch",
174
+ message: "The live indexer daemon belongs to a different wallet root.",
175
+ };
176
+ case "indexer_daemon_protocol_error":
177
+ return {
178
+ health: "unavailable",
179
+ message: "The live indexer daemon socket responded with an invalid or incomplete protocol exchange.",
180
+ };
181
+ default:
182
+ return {
183
+ health: "unavailable",
184
+ message,
185
+ };
186
+ }
187
+ }
188
+ function mapBitcoindStartupError(message) {
189
+ switch (message) {
190
+ case "managed_bitcoind_service_start_timeout":
191
+ return {
192
+ health: "starting",
193
+ status: null,
194
+ message: "Managed bitcoind service is still starting.",
195
+ };
196
+ case "managed_bitcoind_service_version_mismatch":
197
+ return {
198
+ health: "service-version-mismatch",
199
+ status: null,
200
+ message: "The live managed bitcoind service is running an incompatible service version.",
201
+ };
202
+ case "managed_bitcoind_wallet_root_mismatch":
203
+ return {
204
+ health: "wallet-root-mismatch",
205
+ status: null,
206
+ message: "The live managed bitcoind service belongs to a different wallet root.",
207
+ };
208
+ case "managed_bitcoind_runtime_mismatch":
209
+ return {
210
+ health: "runtime-mismatch",
211
+ status: null,
212
+ message: "The live managed bitcoind service runtime does not match this wallet's expected data directory or chain.",
213
+ };
214
+ case "managed_bitcoind_protocol_error":
215
+ return {
216
+ health: "unavailable",
217
+ status: null,
218
+ message: "The managed bitcoind runtime artifacts are invalid or incomplete.",
219
+ };
220
+ default:
221
+ return {
222
+ health: "unavailable",
223
+ status: null,
224
+ message,
225
+ };
226
+ }
227
+ }
228
+ function deriveBitcoindHealth(options) {
229
+ if (options.startupError !== null) {
230
+ const mapped = mapBitcoindStartupError(options.startupError);
231
+ return {
232
+ ...mapped,
233
+ status: options.status,
234
+ };
235
+ }
236
+ if (options.status === null) {
237
+ return {
238
+ health: "unavailable",
239
+ status: null,
240
+ message: "Managed bitcoind service is unavailable.",
241
+ };
242
+ }
243
+ if (options.status.state === "starting") {
244
+ return {
245
+ health: "starting",
246
+ status: options.status,
247
+ message: options.status.lastError ?? "Managed bitcoind service is still starting.",
248
+ };
249
+ }
250
+ if (options.status.state === "failed") {
251
+ return {
252
+ health: "failed",
253
+ status: options.status,
254
+ message: options.status.lastError ?? "Managed bitcoind service refresh failed.",
255
+ };
256
+ }
257
+ const proofStatus = options.nodeStatus?.walletReplica?.proofStatus;
258
+ if (proofStatus === "missing") {
259
+ return {
260
+ health: "replica-missing",
261
+ status: options.status,
262
+ message: options.nodeStatus?.walletReplicaMessage ?? "Managed Core wallet replica is missing.",
263
+ };
264
+ }
265
+ if (proofStatus === "mismatch") {
266
+ return {
267
+ health: "replica-mismatch",
268
+ status: options.status,
269
+ message: options.nodeStatus?.walletReplicaMessage ?? "Managed Core wallet replica does not match trusted wallet state.",
270
+ };
271
+ }
272
+ return {
273
+ health: "ready",
274
+ status: options.status,
275
+ message: options.nodeStatus?.walletReplicaMessage ?? options.status.lastError,
276
+ };
277
+ }
278
+ function deriveNodeHealth(status, bitcoindHealth) {
279
+ if (bitcoindHealth !== "ready" || status === null || !status.ready) {
280
+ return {
281
+ health: "unavailable",
282
+ message: "Bitcoin service is unavailable.",
283
+ };
284
+ }
285
+ if (status.nodeBestHeight !== null && status.nodeHeaderHeight !== null && status.nodeBestHeight < status.nodeHeaderHeight) {
286
+ return {
287
+ health: "catching-up",
288
+ message: "Bitcoin Core is still catching up to headers.",
289
+ };
290
+ }
291
+ return {
292
+ health: "synced",
293
+ message: null,
294
+ };
295
+ }
296
+ function deriveIndexerHealth(options) {
297
+ const daemonStatus = options.source === "lease"
298
+ ? options.daemonStatus
299
+ : options.observedStatus ?? options.daemonStatus;
300
+ const snapshotTip = options.snapshot?.tip ?? null;
301
+ const daemonInstanceId = options.snapshot?.daemonInstanceId ?? daemonStatus?.daemonInstanceId ?? null;
302
+ const snapshotSeq = options.snapshot?.snapshotSeq ?? daemonStatus?.snapshotSeq ?? null;
303
+ const openedAtUnixMs = options.snapshot?.openedAtUnixMs ?? null;
304
+ const source = daemonStatus === null && options.snapshot === null ? "none" : options.source;
305
+ const createResult = (health, message) => ({
306
+ health,
307
+ status: daemonStatus,
308
+ message,
309
+ snapshotTip,
310
+ source,
311
+ daemonInstanceId,
312
+ snapshotSeq,
313
+ openedAtUnixMs,
314
+ });
315
+ if (options.startupError !== null) {
316
+ const mapped = mapIndexerStartupError(options.startupError);
317
+ return createResult(mapped.health, mapped.message);
318
+ }
319
+ if (daemonStatus === null) {
320
+ return createResult("unavailable", "Indexer daemon is unavailable.");
321
+ }
322
+ if ((options.now - daemonStatus.heartbeatAtUnixMs) > STALE_HEARTBEAT_THRESHOLD_MS) {
323
+ return createResult("stale-heartbeat", "Indexer daemon heartbeat is stale.");
324
+ }
325
+ if (daemonStatus.state === "schema-mismatch") {
326
+ return createResult("schema-mismatch", daemonStatus.lastError ?? "Indexer daemon sqlite schema is incompatible.");
327
+ }
328
+ if (daemonStatus.state === "failed") {
329
+ return createResult("failed", daemonStatus.lastError ?? "Indexer daemon refresh failed.");
330
+ }
331
+ if (daemonStatus.state === "service-version-mismatch") {
332
+ return createResult("service-version-mismatch", "Indexer daemon service API is incompatible.");
333
+ }
334
+ if (options.snapshot === null) {
335
+ if (daemonStatus.state === "reorging") {
336
+ return createResult("reorging", "Indexer daemon is replaying a reorg and refreshing the coherent snapshot.");
337
+ }
338
+ return createResult(daemonStatus.state === "catching-up" ? "catching-up" : "starting", "Indexer snapshot is not ready yet.");
339
+ }
340
+ if (daemonStatus.state === "catching-up") {
341
+ return createResult("catching-up", "Indexer daemon is still catching up to the managed Bitcoin tip.");
342
+ }
343
+ if (daemonStatus.state === "reorging") {
344
+ return createResult("reorging", "Indexer daemon is replaying a reorg and refreshing the coherent snapshot.");
345
+ }
346
+ return createResult("synced", null);
347
+ }
348
+ async function attachNodeStatus(options) {
349
+ try {
350
+ const probe = await probeManagedBitcoindService({
351
+ dataDir: options.dataDir,
352
+ chain: "main",
353
+ startHeight: 0,
354
+ walletRootId: options.walletRootId,
355
+ startupTimeoutMs: options.startupTimeoutMs,
356
+ });
357
+ if (probe.compatibility !== "compatible" && probe.compatibility !== "unreachable") {
358
+ return {
359
+ handle: null,
360
+ status: null,
361
+ observedStatus: probe.status,
362
+ error: probe.error,
363
+ };
364
+ }
365
+ const genesis = await loadBundledGenesisParameters();
366
+ const handle = await attachOrStartManagedBitcoindService({
367
+ dataDir: options.dataDir,
368
+ chain: "main",
369
+ startHeight: genesis.genesisBlock,
370
+ walletRootId: options.walletRootId,
371
+ startupTimeoutMs: options.startupTimeoutMs,
372
+ });
373
+ const rpc = createRpcClient(handle.rpc);
374
+ const [chainInfo, serviceStatus] = await Promise.all([
375
+ rpc.getBlockchainInfo(),
376
+ handle.refreshServiceStatus?.(),
377
+ ]);
378
+ const status = {
379
+ ready: true,
380
+ chain: chainInfo.chain,
381
+ pid: handle.pid,
382
+ walletRootId: handle.walletRootId ?? null,
383
+ nodeBestHeight: chainInfo.blocks,
384
+ nodeBestHashHex: chainInfo.bestblockhash,
385
+ nodeHeaderHeight: chainInfo.headers,
386
+ serviceUpdatedAtUnixMs: serviceStatus?.updatedAtUnixMs ?? null,
387
+ serviceStatus: serviceStatus ?? null,
388
+ walletReplica: serviceStatus?.walletReplica ?? null,
389
+ walletReplicaMessage: serviceStatus?.walletReplica?.message ?? null,
390
+ };
391
+ return {
392
+ handle,
393
+ status,
394
+ observedStatus: serviceStatus ?? null,
395
+ error: null,
396
+ };
397
+ }
398
+ catch (error) {
399
+ return {
400
+ handle: null,
401
+ status: null,
402
+ observedStatus: null,
403
+ error: error instanceof Error ? error.message : String(error),
404
+ };
405
+ }
406
+ }
407
+ export async function openWalletReadContext(options) {
408
+ const startupTimeoutMs = options.startupTimeoutMs ?? DEFAULT_SERVICE_START_TIMEOUT_MS;
409
+ const now = options.now ?? Date.now();
410
+ const localState = await inspectWalletLocalState({
411
+ passphrase: options.walletStatePassphrase,
412
+ secretProvider: options.secretProvider,
413
+ now,
414
+ paths: options.paths,
415
+ });
416
+ const walletRootId = localState.walletRootId ?? UNINITIALIZED_WALLET_ROOT_ID;
417
+ const node = await attachNodeStatus({
418
+ dataDir: options.dataDir,
419
+ walletRootId,
420
+ startupTimeoutMs,
421
+ });
422
+ if (localState.state !== null && node.status !== null) {
423
+ const verifiedReplica = await verifyManagedCoreWalletReplica(localState.state, options.dataDir, {
424
+ nodeHandle: node.handle ?? undefined,
425
+ });
426
+ node.status = {
427
+ ...node.status,
428
+ walletReplica: verifiedReplica,
429
+ walletReplicaMessage: verifiedReplica.message ?? null,
430
+ };
431
+ }
432
+ const bitcoind = deriveBitcoindHealth({
433
+ status: node.observedStatus,
434
+ nodeStatus: node.status,
435
+ startupError: node.error,
436
+ });
437
+ const nodeDerived = deriveNodeHealth(node.status, bitcoind.health);
438
+ let daemonClient = null;
439
+ let daemonStatus = null;
440
+ let observedDaemonStatus = null;
441
+ let snapshot = null;
442
+ let indexerSource = "none";
443
+ let daemonError = null;
444
+ try {
445
+ const probe = await probeIndexerDaemon({
446
+ dataDir: options.dataDir,
447
+ walletRootId,
448
+ });
449
+ if (probe.compatibility === "compatible") {
450
+ daemonClient = probe.client;
451
+ observedDaemonStatus = probe.status;
452
+ indexerSource = "probe";
453
+ }
454
+ else if (probe.compatibility === "unreachable") {
455
+ daemonClient = await attachOrStartIndexerDaemon({
456
+ dataDir: options.dataDir,
457
+ databasePath: options.databasePath,
458
+ walletRootId,
459
+ startupTimeoutMs,
460
+ });
461
+ }
462
+ else {
463
+ observedDaemonStatus = probe.status;
464
+ indexerSource = probe.status === null ? "none" : "probe";
465
+ daemonError = probe.error;
466
+ }
467
+ if (daemonClient !== null) {
468
+ const lease = await readSnapshotWithRetry(daemonClient, walletRootId);
469
+ daemonStatus = lease.status;
470
+ observedDaemonStatus = lease.status;
471
+ snapshot = {
472
+ tip: lease.payload.tip,
473
+ state: deserializeIndexerState(Buffer.from(lease.payload.stateBase64, "base64")),
474
+ source: "lease",
475
+ daemonInstanceId: lease.payload.daemonInstanceId,
476
+ snapshotSeq: lease.payload.snapshotSeq,
477
+ openedAtUnixMs: lease.payload.openedAtUnixMs,
478
+ };
479
+ indexerSource = "lease";
480
+ }
481
+ }
482
+ catch (error) {
483
+ daemonError = error instanceof Error ? error.message : String(error);
484
+ if (observedDaemonStatus === null) {
485
+ observedDaemonStatus = await readObservedIndexerDaemonStatus({
486
+ dataDir: options.dataDir,
487
+ walletRootId,
488
+ }).catch(() => null);
489
+ if (observedDaemonStatus !== null) {
490
+ indexerSource = "status-file";
491
+ }
492
+ }
493
+ }
494
+ const indexer = deriveIndexerHealth({
495
+ daemonStatus,
496
+ observedStatus: observedDaemonStatus,
497
+ snapshot,
498
+ source: indexerSource,
499
+ now,
500
+ startupError: daemonError,
501
+ });
502
+ const mining = await inspectMiningControlPlane({
503
+ provider: options.secretProvider,
504
+ localState,
505
+ bitcoind,
506
+ nodeStatus: node.status,
507
+ nodeHealth: nodeDerived.health,
508
+ indexer,
509
+ nowUnixMs: now,
510
+ paths: options.paths,
511
+ });
512
+ return {
513
+ dataDir: options.dataDir,
514
+ databasePath: options.databasePath,
515
+ localState,
516
+ bitcoind,
517
+ nodeStatus: node.status,
518
+ nodeHealth: nodeDerived.health,
519
+ nodeMessage: nodeDerived.message,
520
+ indexer,
521
+ snapshot,
522
+ model: localState.state === null
523
+ ? null
524
+ : createWalletReadModel(localState.state, snapshot),
525
+ mining,
526
+ async close() {
527
+ await daemonClient?.close().catch(() => undefined);
528
+ await node.handle?.stop().catch(() => undefined);
529
+ },
530
+ };
531
+ }
532
+ export { inspectWalletLocalState, readSnapshotWithRetry, };
@@ -0,0 +1,9 @@
1
+ import type { WalletDomainView, WalletReadContext } from "./types.js";
2
+ export interface WalletDomainFilterOptions {
3
+ anchoredOnly: boolean;
4
+ listedOnly: boolean;
5
+ mineableOnly: boolean;
6
+ }
7
+ export declare function isRootDomainName(name: string): boolean;
8
+ export declare function isMineableWalletDomain(context: WalletReadContext, domain: WalletDomainView): boolean;
9
+ export declare function filterWalletDomains(context: WalletReadContext, options: WalletDomainFilterOptions): WalletDomainView[] | null;
@@ -0,0 +1,42 @@
1
+ import { lookupDomain } from "@cogcoin/indexer/queries";
2
+ export function isRootDomainName(name) {
3
+ return !name.includes("-");
4
+ }
5
+ export function isMineableWalletDomain(context, domain) {
6
+ const state = context.localState.state;
7
+ const model = context.model;
8
+ const snapshot = context.snapshot;
9
+ if (state === null || model === null || snapshot === null) {
10
+ return false;
11
+ }
12
+ if (!isRootDomainName(domain.name) || domain.anchored !== true || domain.readOnly || domain.ownerLocalIndex === null || domain.domainId === null) {
13
+ return false;
14
+ }
15
+ const localRecord = state.domains.find((entry) => entry.name === domain.name);
16
+ const ownerIdentity = model.identities.find((identity) => identity.index === domain.ownerLocalIndex);
17
+ if (localRecord?.currentCanonicalAnchorOutpoint === null
18
+ || localRecord?.currentCanonicalAnchorOutpoint === undefined
19
+ || ownerIdentity?.address == null
20
+ || ownerIdentity.readOnly) {
21
+ return false;
22
+ }
23
+ const chainDomain = lookupDomain(snapshot.state, domain.name);
24
+ return chainDomain !== null && chainDomain.anchored;
25
+ }
26
+ export function filterWalletDomains(context, options) {
27
+ if (context.model === null) {
28
+ return null;
29
+ }
30
+ return context.model.domains.filter((domain) => {
31
+ if (options.anchoredOnly && domain.anchored !== true) {
32
+ return false;
33
+ }
34
+ if (options.listedOnly && domain.listingPriceCogtoshi === null) {
35
+ return false;
36
+ }
37
+ if (options.mineableOnly && !isMineableWalletDomain(context, domain)) {
38
+ return false;
39
+ }
40
+ return true;
41
+ });
42
+ }
@@ -0,0 +1,4 @@
1
+ export { openWalletReadContext, inspectWalletLocalState, readSnapshotWithRetry } from "./context.js";
2
+ export { filterWalletDomains, isMineableWalletDomain, isRootDomainName, type WalletDomainFilterOptions, } from "./filter.js";
3
+ export { createFieldPreview, createWalletReadModel, findDomainField, findWalletLock, findWalletDomain, formatFieldFormat, listDomainFields, listWalletLocks, } from "./project.js";
4
+ export type { WalletBitcoindStatus, WalletDomainDetailsView, WalletDomainView, WalletFieldView, WalletIdentityView, WalletIndexerStatus, WalletLocalStateStatus, WalletLockView, WalletNodeStatus, WalletReadContext, WalletReadModel, WalletServiceHealth, WalletSnapshotView, WalletStateAvailability, } from "./types.js";
@@ -0,0 +1,3 @@
1
+ export { openWalletReadContext, inspectWalletLocalState, readSnapshotWithRetry } from "./context.js";
2
+ export { filterWalletDomains, isMineableWalletDomain, isRootDomainName, } from "./filter.js";
3
+ export { createFieldPreview, createWalletReadModel, findDomainField, findWalletLock, findWalletDomain, formatFieldFormat, listDomainFields, listWalletLocks, } from "./project.js";
@@ -0,0 +1,11 @@
1
+ import { getLock } from "@cogcoin/indexer/queries";
2
+ import type { WalletDomainDetailsView, WalletFieldView, WalletLockView, WalletReadContext, WalletReadModel, WalletSnapshotView } from "./types.js";
3
+ import type { WalletStateV1 } from "../types.js";
4
+ export declare function createWalletReadModel(walletState: WalletStateV1, snapshot: WalletSnapshotView | null): WalletReadModel;
5
+ export declare function listWalletLocks(context: WalletReadContext): WalletLockView[] | null;
6
+ export declare function findWalletLock(context: WalletReadContext, lockId: number): ReturnType<typeof getLock>;
7
+ export declare function findWalletDomain(context: WalletReadContext, name: string): WalletDomainDetailsView | null;
8
+ export declare function listDomainFields(context: WalletReadContext, name: string): WalletFieldView[] | null;
9
+ export declare function findDomainField(context: WalletReadContext, domainName: string, fieldName: string): WalletFieldView | null;
10
+ export declare function createFieldPreview(value: Uint8Array, format: number): string;
11
+ export declare function formatFieldFormat(format: number | null): string;