@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
@@ -1,494 +1 @@
1
- import { createHash, randomBytes } from "node:crypto";
2
- import { encodeSentence } from "@cogcoin/scoring";
3
- import { lookupDomain } from "@cogcoin/indexer/queries";
4
- import { attachOrStartManagedBitcoindService } from "../../bitcoind/service.js";
5
- import { createRpcClient } from "../../bitcoind/node.js";
6
- import {} from "../runtime.js";
7
- import {} from "../state/provider.js";
8
- import { serializeDomainAnchor, validateDomainName, } from "../cogop/index.js";
9
- import { openWalletReadContext } from "../read/index.js";
10
- import { assertWalletMutationContextReady, buildWalletMutationTransactionWithReserveFallback, createWalletMutationFeeMetadata, mergeFixedWalletInputs, outpointKey, saveWalletStatePreservingUnlock, unlockTemporaryBuilderLocks, updateMutationRecord, } from "./common.js";
11
- import { executeWalletMutationOperation, persistWalletMutationState, publishWalletMutation, resolveExistingWalletMutation, } from "./executor.js";
12
- import { upsertPendingMutation } from "./journal.js";
13
- function normalizeDomainName(domainName) {
14
- const normalized = domainName.trim().toLowerCase();
15
- if (normalized.length === 0) {
16
- throw new Error("wallet_anchor_missing_domain");
17
- }
18
- validateDomainName(normalized);
19
- return normalized;
20
- }
21
- function encodeOpReturnScript(payload) {
22
- if (payload.length <= 75) {
23
- return Buffer.concat([
24
- Buffer.from([0x6a, payload.length]),
25
- Buffer.from(payload),
26
- ]).toString("hex");
27
- }
28
- return Buffer.concat([
29
- Buffer.from([0x6a, 0x4c, payload.length]),
30
- Buffer.from(payload),
31
- ]).toString("hex");
32
- }
33
- function satsToBtcNumber(value) {
34
- return Number(value) / 100_000_000;
35
- }
36
- function valueToSats(value) {
37
- const text = typeof value === "number" ? value.toFixed(8) : value;
38
- const match = /^(-?)(\d+)(?:\.(\d{0,8}))?$/.exec(text.trim());
39
- if (match == null) {
40
- throw new Error(`wallet_anchor_invalid_amount_${text}`);
41
- }
42
- const sign = match[1] === "-" ? -1n : 1n;
43
- const whole = BigInt(match[2] ?? "0");
44
- const fraction = BigInt((match[3] ?? "").padEnd(8, "0"));
45
- return sign * ((whole * 100000000n) + fraction);
46
- }
47
- function createIntentFingerprint(parts) {
48
- return createHash("sha256")
49
- .update(parts.map((part) => String(part)).join("\n"))
50
- .digest("hex");
51
- }
52
- function sortUtxos(entries) {
53
- return entries
54
- .slice()
55
- .sort((left, right) => right.amount - left.amount
56
- || left.txid.localeCompare(right.txid)
57
- || left.vout - right.vout);
58
- }
59
- function isSpendableFundingUtxo(entry, fundingScriptPubKeyHex) {
60
- return entry.scriptPubKey === fundingScriptPubKeyHex
61
- && entry.confirmations >= 1
62
- && entry.spendable !== false
63
- && entry.safe !== false;
64
- }
65
- function encodeFoundingMessage(foundingMessageText) {
66
- const trimmed = foundingMessageText?.trim() ?? "";
67
- if (trimmed === "") {
68
- return Promise.resolve({
69
- text: null,
70
- payloadHex: null,
71
- });
72
- }
73
- return encodeSentence(trimmed)
74
- .then((payload) => ({
75
- text: trimmed,
76
- payloadHex: Buffer.from(payload).toString("hex"),
77
- }))
78
- .catch((error) => {
79
- throw new Error(error instanceof Error ? `wallet_anchor_invalid_message_${error.message}` : "wallet_anchor_invalid_message");
80
- });
81
- }
82
- function extractAnchorInvalidMessageReason(error) {
83
- const message = error instanceof Error ? error.message : String(error);
84
- if (message === "wallet_anchor_invalid_message") {
85
- return null;
86
- }
87
- if (!message.startsWith("wallet_anchor_invalid_message_")) {
88
- return null;
89
- }
90
- const reason = message.slice("wallet_anchor_invalid_message_".length).trim();
91
- return reason === "" ? null : reason;
92
- }
93
- async function resolveFoundingMessage(options) {
94
- if (!options.promptForFoundingMessageWhenMissing || options.foundingMessageText != null) {
95
- return encodeFoundingMessage(options.foundingMessageText ?? null);
96
- }
97
- for (;;) {
98
- const answer = await options.prompter.prompt("Founding message (optional, press Enter to skip): ");
99
- try {
100
- return await encodeFoundingMessage(answer);
101
- }
102
- catch (error) {
103
- const reason = extractAnchorInvalidMessageReason(error);
104
- options.prompter.writeLine("Founding message cannot be encoded in canonical Coglex.");
105
- if (reason !== null) {
106
- options.prompter.writeLine(`Reason: ${reason}`);
107
- }
108
- }
109
- }
110
- }
111
- async function confirmDirectAnchor(prompter, options) {
112
- prompter.writeLine(`You are anchoring "${options.domainName}".`);
113
- prompter.writeLine(`Wallet address: ${options.walletAddress}`);
114
- prompter.writeLine("Anchoring publishes a standalone DOMAIN_ANCHOR from the local wallet address.");
115
- if (options.foundingMessageText !== null) {
116
- prompter.writeLine("The founding message bytes will be public in mempool and on-chain.");
117
- prompter.writeLine(`Founding message: ${options.foundingMessageText}`);
118
- }
119
- const answer = (await prompter.prompt("Type the domain name to continue: ")).trim();
120
- if (answer !== options.domainName) {
121
- throw new Error("wallet_anchor_confirmation_rejected");
122
- }
123
- }
124
- function buildDirectAnchorPlan(options) {
125
- const fundingUtxos = sortUtxos(options.allUtxos.filter((entry) => isSpendableFundingUtxo(entry, options.state.funding.scriptPubKeyHex)));
126
- const foundingPayload = options.foundingMessagePayloadHex === null
127
- ? undefined
128
- : Buffer.from(options.foundingMessagePayloadHex, "hex");
129
- const opReturnData = serializeDomainAnchor(options.domainId, foundingPayload).opReturnData;
130
- return {
131
- fixedInputs: [],
132
- outputs: [{ data: Buffer.from(opReturnData).toString("hex") }],
133
- changeAddress: options.state.funding.address,
134
- changePosition: 1,
135
- expectedOpReturnScriptHex: encodeOpReturnScript(opReturnData),
136
- allowedFundingScriptPubKeyHex: options.state.funding.scriptPubKeyHex,
137
- eligibleFundingOutpointKeys: new Set(fundingUtxos.map((entry) => outpointKey({ txid: entry.txid, vout: entry.vout }))),
138
- };
139
- }
140
- function validateDirectAnchorDraft(decoded, funded, plan) {
141
- const outputs = decoded.tx.vout;
142
- if (outputs[0]?.scriptPubKey?.hex !== plan.expectedOpReturnScriptHex) {
143
- throw new Error("wallet_anchor_opreturn_mismatch");
144
- }
145
- if (funded.changepos === -1) {
146
- if (outputs.length !== 1) {
147
- throw new Error("wallet_anchor_unexpected_output_count");
148
- }
149
- return;
150
- }
151
- if (funded.changepos !== plan.changePosition || outputs.length !== 2) {
152
- throw new Error("wallet_anchor_change_position_mismatch");
153
- }
154
- if (outputs[funded.changepos]?.scriptPubKey?.hex !== plan.allowedFundingScriptPubKeyHex) {
155
- throw new Error("wallet_anchor_change_output_mismatch");
156
- }
157
- }
158
- function createDraftAnchorMutation(options) {
159
- const existing = options.existing ?? null;
160
- if (existing !== null) {
161
- return {
162
- ...existing,
163
- kind: "anchor",
164
- domainName: options.domainName,
165
- parentDomainName: null,
166
- senderScriptPubKeyHex: options.state.funding.scriptPubKeyHex,
167
- senderLocalIndex: 0,
168
- intentFingerprintHex: options.intentFingerprintHex,
169
- status: "draft",
170
- lastUpdatedAtUnixMs: options.nowUnixMs,
171
- attemptedTxid: null,
172
- attemptedWtxid: null,
173
- ...createWalletMutationFeeMetadata(options.feeSelection),
174
- temporaryBuilderLockedOutpoints: [],
175
- };
176
- }
177
- return {
178
- mutationId: randomBytes(12).toString("hex"),
179
- kind: "anchor",
180
- domainName: options.domainName,
181
- parentDomainName: null,
182
- senderScriptPubKeyHex: options.state.funding.scriptPubKeyHex,
183
- senderLocalIndex: 0,
184
- intentFingerprintHex: options.intentFingerprintHex,
185
- status: "draft",
186
- createdAtUnixMs: options.nowUnixMs,
187
- lastUpdatedAtUnixMs: options.nowUnixMs,
188
- attemptedTxid: null,
189
- attemptedWtxid: null,
190
- ...createWalletMutationFeeMetadata(options.feeSelection),
191
- temporaryBuilderLockedOutpoints: [],
192
- };
193
- }
194
- function upsertAnchoredDomainRecord(options) {
195
- const domains = options.state.domains.slice();
196
- const existingIndex = domains.findIndex((entry) => entry.name === options.domainName);
197
- const current = existingIndex >= 0 ? domains[existingIndex] : null;
198
- const nextRecord = {
199
- name: options.domainName,
200
- domainId: options.domainId,
201
- currentOwnerScriptPubKeyHex: options.state.funding.scriptPubKeyHex,
202
- canonicalChainStatus: "anchored",
203
- foundingMessageText: options.foundingMessageText ?? current?.foundingMessageText ?? null,
204
- birthTime: current?.birthTime ?? options.state.lastWrittenAtUnixMs,
205
- };
206
- if (existingIndex >= 0) {
207
- domains[existingIndex] = nextRecord;
208
- }
209
- else {
210
- domains.push(nextRecord);
211
- }
212
- return {
213
- ...options.state,
214
- domains,
215
- };
216
- }
217
- function anchorConfirmedOnSnapshot(options) {
218
- const chainDomain = lookupDomain(options.snapshot.state, options.domainName);
219
- if (chainDomain === null || !chainDomain.anchored) {
220
- return false;
221
- }
222
- const ownerHex = Buffer.from(chainDomain.ownerScriptPubKey).toString("hex");
223
- return ownerHex === options.state.funding.scriptPubKeyHex
224
- || (options.state.localScriptPubKeyHexes ?? []).includes(ownerHex);
225
- }
226
- async function saveState(options) {
227
- return persistWalletMutationState(options);
228
- }
229
- async function reconcilePendingAnchorMutation(options) {
230
- if (options.mutation.status === "repair-required") {
231
- return {
232
- state: options.state,
233
- mutation: options.mutation,
234
- resolution: "repair-required",
235
- };
236
- }
237
- if (options.context.snapshot !== null && anchorConfirmedOnSnapshot({
238
- snapshot: options.context.snapshot,
239
- state: options.state,
240
- domainName: options.mutation.domainName,
241
- })) {
242
- await unlockTemporaryBuilderLocks(options.rpc, options.walletName, options.mutation.temporaryBuilderLockedOutpoints);
243
- const confirmedMutation = updateMutationRecord(options.mutation, "confirmed", options.nowUnixMs, {
244
- temporaryBuilderLockedOutpoints: [],
245
- });
246
- const chainDomain = lookupDomain(options.context.snapshot.state, options.mutation.domainName);
247
- const nextState = upsertAnchoredDomainRecord({
248
- state: upsertPendingMutation(options.state, confirmedMutation),
249
- domainName: options.mutation.domainName,
250
- domainId: chainDomain?.domainId ?? 0,
251
- foundingMessageText: options.foundingMessageText,
252
- });
253
- return {
254
- state: await saveState({
255
- state: nextState,
256
- provider: options.provider,
257
- nowUnixMs: options.nowUnixMs,
258
- paths: options.paths,
259
- }),
260
- mutation: confirmedMutation,
261
- resolution: "confirmed",
262
- };
263
- }
264
- if (options.mutation.attemptedTxid !== null) {
265
- const mempool = await options.rpc.getRawMempool().catch(() => []);
266
- if (mempool.includes(options.mutation.attemptedTxid)) {
267
- await unlockTemporaryBuilderLocks(options.rpc, options.walletName, options.mutation.temporaryBuilderLockedOutpoints);
268
- const liveMutation = updateMutationRecord(options.mutation, "live", options.nowUnixMs, {
269
- temporaryBuilderLockedOutpoints: [],
270
- });
271
- const domainId = (options.context.snapshot === null
272
- ? null
273
- : lookupDomain(options.context.snapshot.state, options.mutation.domainName)?.domainId)
274
- ?? options.state.domains.find((domain) => domain.name === options.mutation.domainName)?.domainId
275
- ?? 0;
276
- const nextState = upsertAnchoredDomainRecord({
277
- state: upsertPendingMutation(options.state, liveMutation),
278
- domainName: options.mutation.domainName,
279
- domainId,
280
- foundingMessageText: options.foundingMessageText,
281
- });
282
- return {
283
- state: await saveState({
284
- state: nextState,
285
- provider: options.provider,
286
- nowUnixMs: options.nowUnixMs,
287
- paths: options.paths,
288
- }),
289
- mutation: liveMutation,
290
- resolution: "live",
291
- };
292
- }
293
- }
294
- if (options.mutation.status === "broadcast-unknown"
295
- || options.mutation.status === "live"
296
- || options.mutation.status === "draft"
297
- || options.mutation.status === "broadcasting") {
298
- await unlockTemporaryBuilderLocks(options.rpc, options.walletName, options.mutation.temporaryBuilderLockedOutpoints);
299
- const canceledMutation = updateMutationRecord(options.mutation, "canceled", options.nowUnixMs, {
300
- temporaryBuilderLockedOutpoints: [],
301
- });
302
- const nextState = upsertPendingMutation(options.state, canceledMutation);
303
- return {
304
- state: await saveState({
305
- state: nextState,
306
- provider: options.provider,
307
- nowUnixMs: options.nowUnixMs,
308
- paths: options.paths,
309
- }),
310
- mutation: canceledMutation,
311
- resolution: "not-seen",
312
- };
313
- }
314
- return {
315
- state: options.state,
316
- mutation: options.mutation,
317
- resolution: "continue",
318
- };
319
- }
320
- function ensureSameTipHeight(context, bestHeight, errorCode) {
321
- if (context.snapshot?.tip?.height !== bestHeight) {
322
- throw new Error(errorCode);
323
- }
324
- }
325
- export async function anchorDomain(options) {
326
- if (!options.prompter.isInteractive) {
327
- throw new Error("wallet_anchor_requires_tty");
328
- }
329
- const normalizedDomainName = normalizeDomainName(options.domainName);
330
- const execution = await executeWalletMutationOperation({
331
- ...options,
332
- controlLockPurpose: "wallet-anchor",
333
- preemptionReason: "wallet-anchor",
334
- async resolveOperation(readContext) {
335
- assertWalletMutationContextReady(readContext, "wallet_anchor");
336
- const message = await resolveFoundingMessage({
337
- foundingMessageText: options.foundingMessageText,
338
- promptForFoundingMessageWhenMissing: options.promptForFoundingMessageWhenMissing,
339
- prompter: options.prompter,
340
- });
341
- const state = readContext.localState.state;
342
- const chainDomain = lookupDomain(readContext.snapshot.state, normalizedDomainName);
343
- if (chainDomain === null) {
344
- throw new Error("wallet_anchor_domain_not_found");
345
- }
346
- if (chainDomain.anchored) {
347
- throw new Error("wallet_anchor_domain_already_anchored");
348
- }
349
- const ownerHex = Buffer.from(chainDomain.ownerScriptPubKey).toString("hex");
350
- const localScriptHexes = new Set([
351
- state.funding.scriptPubKeyHex,
352
- ...(state.localScriptPubKeyHexes ?? []),
353
- ]);
354
- if (!localScriptHexes.has(ownerHex)) {
355
- throw new Error("wallet_anchor_owner_not_locally_controlled");
356
- }
357
- if (state.funding.address.trim() === "") {
358
- throw new Error("wallet_anchor_owner_identity_not_supported");
359
- }
360
- return {
361
- state,
362
- normalizedDomainName,
363
- chainDomain,
364
- message,
365
- };
366
- },
367
- createIntentFingerprint(operation) {
368
- return createIntentFingerprint([
369
- "anchor",
370
- operation.state.walletRootId,
371
- operation.normalizedDomainName,
372
- operation.state.funding.scriptPubKeyHex,
373
- operation.message.payloadHex ?? "",
374
- ]);
375
- },
376
- async resolveExistingMutation({ operation, existingMutation, execution }) {
377
- if (existingMutation === null) {
378
- return { state: operation.state, replacementFixedInputs: null, result: null };
379
- }
380
- return resolveExistingWalletMutation({
381
- existingMutation,
382
- execution,
383
- repairRequiredErrorCode: "wallet_anchor_repair_required",
384
- reconcileExistingMutation: (mutation) => reconcilePendingAnchorMutation({
385
- state: operation.state,
386
- mutation,
387
- provider: execution.provider,
388
- nowUnixMs: execution.nowUnixMs,
389
- paths: execution.paths,
390
- rpc: execution.rpc,
391
- walletName: execution.walletName,
392
- context: execution.readContext,
393
- foundingMessageText: operation.message.text,
394
- }),
395
- createReuseResult: ({ mutation, resolution, fees }) => ({
396
- domainName: operation.normalizedDomainName,
397
- txid: mutation.attemptedTxid ?? "unknown",
398
- status: resolution,
399
- reusedExisting: true,
400
- foundingMessageText: operation.message.text,
401
- fees,
402
- }),
403
- });
404
- },
405
- confirm({ operation }) {
406
- return confirmDirectAnchor(options.prompter, {
407
- domainName: operation.normalizedDomainName,
408
- walletAddress: operation.state.funding.address,
409
- foundingMessageText: operation.message.text,
410
- });
411
- },
412
- createDraftMutation({ operation, existingMutation, execution, intentFingerprintHex }) {
413
- return {
414
- mutation: createDraftAnchorMutation({
415
- state: operation.state,
416
- domainName: operation.normalizedDomainName,
417
- intentFingerprintHex,
418
- nowUnixMs: execution.nowUnixMs,
419
- feeSelection: execution.feeSelection,
420
- existing: existingMutation ?? null,
421
- }),
422
- prepared: null,
423
- };
424
- },
425
- async build({ operation, state, execution, replacementFixedInputs }) {
426
- const directAnchorPlan = buildDirectAnchorPlan({
427
- state,
428
- allUtxos: await execution.rpc.listUnspent(execution.walletName, 1),
429
- domainId: operation.chainDomain.domainId,
430
- foundingMessagePayloadHex: operation.message.payloadHex,
431
- });
432
- return buildWalletMutationTransactionWithReserveFallback({
433
- rpc: execution.rpc,
434
- walletName: execution.walletName,
435
- state,
436
- plan: {
437
- ...directAnchorPlan,
438
- fixedInputs: mergeFixedWalletInputs(directAnchorPlan.fixedInputs, replacementFixedInputs),
439
- },
440
- validateFundedDraft: validateDirectAnchorDraft,
441
- finalizeErrorCode: "wallet_anchor_finalize_failed",
442
- mempoolRejectPrefix: "wallet_anchor_mempool_rejected",
443
- feeRate: execution.feeSelection.feeRateSatVb,
444
- });
445
- },
446
- publish({ operation, state, execution, built, mutation }) {
447
- return publishWalletMutation({
448
- rpc: execution.rpc,
449
- walletName: execution.walletName,
450
- snapshotHeight: execution.readContext.snapshot?.tip?.height ?? null,
451
- built,
452
- mutation,
453
- state,
454
- provider: execution.provider,
455
- nowUnixMs: execution.nowUnixMs,
456
- paths: execution.paths,
457
- errorPrefix: "wallet_anchor",
458
- async afterAccepted({ state: acceptedState, broadcastingMutation, built, nowUnixMs }) {
459
- const finalStatus = anchorConfirmedOnSnapshot({
460
- snapshot: execution.readContext.snapshot,
461
- state: acceptedState,
462
- domainName: operation.normalizedDomainName,
463
- }) ? "confirmed" : "live";
464
- const finalMutation = updateMutationRecord(broadcastingMutation, finalStatus, nowUnixMs, {
465
- attemptedTxid: built.txid,
466
- attemptedWtxid: built.wtxid,
467
- temporaryBuilderLockedOutpoints: [],
468
- });
469
- return {
470
- state: upsertAnchoredDomainRecord({
471
- state: upsertPendingMutation(acceptedState, finalMutation),
472
- domainName: operation.normalizedDomainName,
473
- domainId: operation.chainDomain.domainId,
474
- foundingMessageText: operation.message.text,
475
- }),
476
- mutation: finalMutation,
477
- status: finalStatus,
478
- };
479
- },
480
- });
481
- },
482
- createResult({ operation, mutation, built, status, reusedExisting, fees }) {
483
- return {
484
- domainName: operation.normalizedDomainName,
485
- txid: mutation.attemptedTxid ?? built?.txid ?? "unknown",
486
- status: status,
487
- reusedExisting,
488
- foundingMessageText: operation.message.text,
489
- fees,
490
- };
491
- },
492
- });
493
- return execution.result;
494
- }
1
+ export * from "./anchor/index.js";
@@ -0,0 +1,7 @@
1
+ import type { WalletPrompter } from "../../lifecycle.js";
2
+ export declare function confirmBitcoinTransfer(prompter: WalletPrompter, options: {
3
+ senderAddress: string;
4
+ recipientAddress: string;
5
+ amountSats: bigint;
6
+ assumeYes?: boolean;
7
+ }): Promise<void>;
@@ -0,0 +1,11 @@
1
+ import { confirmYesNo } from "../confirm.js";
2
+ export async function confirmBitcoinTransfer(prompter, options) {
3
+ prompter.writeLine(`You are sending ${options.amountSats.toString()} sats.`);
4
+ prompter.writeLine(`Wallet address: ${options.senderAddress}`);
5
+ prompter.writeLine(`Recipient: ${options.recipientAddress}`);
6
+ await confirmYesNo(prompter, "This will publish a standard Bitcoin payment from the wallet address.", {
7
+ assumeYes: options.assumeYes,
8
+ errorCode: "wallet_bitcoin_transfer_confirmation_rejected",
9
+ requiresTtyErrorCode: "wallet_bitcoin_transfer_requires_tty",
10
+ });
11
+ }
@@ -0,0 +1,5 @@
1
+ import { type TransferBitcoinOptions } from "./intent.js";
2
+ import { type BitcoinTransferResult } from "./result.js";
3
+ export type { TransferBitcoinOptions } from "./intent.js";
4
+ export type { BitcoinTransferResult } from "./result.js";
5
+ export declare function transferBitcoin(options: TransferBitcoinOptions): Promise<BitcoinTransferResult>;
@@ -0,0 +1,112 @@
1
+ import { attachOrStartManagedBitcoindService } from "../../../bitcoind/service.js";
2
+ import { createRpcClient } from "../../../bitcoind/node.js";
3
+ import { acquireFileLock } from "../../fs/lock.js";
4
+ import { openWalletReadContext } from "../../read/index.js";
5
+ import { resolveWalletRuntimePathsForTesting } from "../../runtime.js";
6
+ import { createDefaultWalletSecretProvider, } from "../../state/provider.js";
7
+ import { assertWalletBitcoinTransferContextReady, buildWalletMutationTransaction, isAlreadyAcceptedError, isBroadcastUnknownError, isInsufficientFundsError, outpointKey, pauseMiningForWalletMutation, unlockTemporaryBuilderLocks, } from "../common.js";
8
+ import { confirmBitcoinTransfer } from "./confirm.js";
9
+ import { buildPlanForBitcoinTransfer, resolveBitcoinTransferIntent, } from "./intent.js";
10
+ import { validateFundedBitcoinTransfer } from "./plan.js";
11
+ import { createBitcoinTransferResult } from "./result.js";
12
+ export async function transferBitcoin(options) {
13
+ const intent = resolveBitcoinTransferIntent(options);
14
+ const provider = options.provider ?? createDefaultWalletSecretProvider();
15
+ const paths = options.paths ?? resolveWalletRuntimePathsForTesting();
16
+ const controlLock = await acquireFileLock(paths.walletControlLockPath, {
17
+ purpose: "wallet-bitcoin-transfer",
18
+ walletRootId: null,
19
+ });
20
+ try {
21
+ const miningPreemption = await pauseMiningForWalletMutation({
22
+ paths,
23
+ reason: "wallet-bitcoin-transfer",
24
+ });
25
+ const readContext = await (options.openReadContext ?? openWalletReadContext)({
26
+ dataDir: options.dataDir,
27
+ databasePath: options.databasePath,
28
+ secretProvider: provider,
29
+ walletControlLockHeld: true,
30
+ paths,
31
+ });
32
+ try {
33
+ assertWalletBitcoinTransferContextReady(readContext, "wallet_bitcoin_transfer");
34
+ const state = readContext.localState.state;
35
+ if (state.funding.scriptPubKeyHex === intent.recipientScriptPubKeyHex) {
36
+ throw new Error("wallet_bitcoin_transfer_self_transfer");
37
+ }
38
+ await confirmBitcoinTransfer(options.prompter, {
39
+ senderAddress: state.funding.address,
40
+ recipientAddress: intent.recipientAddress,
41
+ amountSats: intent.amountSats,
42
+ assumeYes: options.assumeYes,
43
+ });
44
+ const node = await (options.attachService ?? attachOrStartManagedBitcoindService)({
45
+ dataDir: options.dataDir,
46
+ chain: "main",
47
+ startHeight: 0,
48
+ walletRootId: state.walletRootId,
49
+ });
50
+ const rpc = (options.rpcFactory ?? createRpcClient)(node.rpc);
51
+ const walletName = state.managedCoreWallet.walletName;
52
+ const allUtxos = await rpc.listUnspent(walletName, 1);
53
+ const plan = buildPlanForBitcoinTransfer({
54
+ state,
55
+ allUtxos,
56
+ recipientAddress: intent.recipientAddress,
57
+ recipientScriptPubKeyHex: intent.recipientScriptPubKeyHex,
58
+ amountSats: intent.amountSats,
59
+ outpointKey,
60
+ });
61
+ let built;
62
+ try {
63
+ built = await buildWalletMutationTransaction({
64
+ rpc,
65
+ walletName,
66
+ state,
67
+ plan,
68
+ validateFundedDraft: validateFundedBitcoinTransfer,
69
+ finalizeErrorCode: "wallet_bitcoin_transfer_finalize_failed",
70
+ mempoolRejectPrefix: "wallet_bitcoin_transfer_mempool_reject",
71
+ });
72
+ }
73
+ catch (error) {
74
+ if (isInsufficientFundsError(error)) {
75
+ throw new Error("wallet_bitcoin_transfer_insufficient_funds", { cause: error });
76
+ }
77
+ throw error;
78
+ }
79
+ try {
80
+ await rpc.sendRawTransaction(built.rawHex);
81
+ }
82
+ catch (error) {
83
+ if (!isAlreadyAcceptedError(error)) {
84
+ if (isInsufficientFundsError(error)) {
85
+ throw new Error("wallet_bitcoin_transfer_insufficient_funds", { cause: error });
86
+ }
87
+ if (isBroadcastUnknownError(error)) {
88
+ throw new Error("wallet_bitcoin_transfer_broadcast_unknown", { cause: error });
89
+ }
90
+ throw error;
91
+ }
92
+ }
93
+ finally {
94
+ await unlockTemporaryBuilderLocks(rpc, walletName, built.temporaryBuilderLockedOutpoints);
95
+ }
96
+ return createBitcoinTransferResult({
97
+ state,
98
+ built,
99
+ amountSats: intent.amountSats,
100
+ recipientAddress: intent.recipientAddress,
101
+ recipientScriptPubKeyHex: intent.recipientScriptPubKeyHex,
102
+ });
103
+ }
104
+ finally {
105
+ await readContext.close();
106
+ await miningPreemption.release();
107
+ }
108
+ }
109
+ finally {
110
+ await controlLock.release();
111
+ }
112
+ }
@@ -0,0 +1,52 @@
1
+ import type { RpcListUnspentEntry } from "../../../bitcoind/types.js";
2
+ import { attachOrStartManagedBitcoindService } from "../../../bitcoind/service.js";
3
+ import { createRpcClient } from "../../../bitcoind/node.js";
4
+ import type { WalletPrompter } from "../../lifecycle.js";
5
+ import { openWalletReadContext } from "../../read/index.js";
6
+ import type { WalletRuntimePaths } from "../../runtime.js";
7
+ import type { WalletSecretProvider } from "../../state/provider.js";
8
+ import type { WalletStateV1 } from "../../types.js";
9
+ import type { FixedWalletInput, WalletMutationRpcClient } from "../common.js";
10
+ export interface WalletBitcoinTransferRpcClient extends WalletMutationRpcClient {
11
+ sendRawTransaction(hex: string): Promise<string>;
12
+ }
13
+ export interface TransferBitcoinOptions {
14
+ amountSatsText: string;
15
+ target: string;
16
+ dataDir: string;
17
+ databasePath: string;
18
+ provider?: WalletSecretProvider;
19
+ prompter: WalletPrompter;
20
+ assumeYes?: boolean;
21
+ paths?: WalletRuntimePaths;
22
+ openReadContext?: typeof openWalletReadContext;
23
+ attachService?: typeof attachOrStartManagedBitcoindService;
24
+ rpcFactory?: (config: Parameters<typeof createRpcClient>[0]) => WalletBitcoinTransferRpcClient;
25
+ }
26
+ export interface BitcoinTransferIntent {
27
+ amountSats: bigint;
28
+ recipientAddress: string;
29
+ recipientScriptPubKeyHex: string;
30
+ }
31
+ export interface BitcoinTransferPlan {
32
+ fixedInputs: FixedWalletInput[];
33
+ outputs: unknown[];
34
+ changeAddress: string;
35
+ changePosition: number | null;
36
+ allowedFundingScriptPubKeyHex: string;
37
+ eligibleFundingOutpointKeys: Set<string>;
38
+ recipientScriptPubKeyHex: string;
39
+ amountSats: bigint;
40
+ }
41
+ export declare function resolveBitcoinTransferIntent(options: TransferBitcoinOptions): BitcoinTransferIntent;
42
+ export declare function buildPlanForBitcoinTransfer(options: {
43
+ state: WalletStateV1;
44
+ allUtxos: RpcListUnspentEntry[];
45
+ recipientAddress: string;
46
+ recipientScriptPubKeyHex: string;
47
+ amountSats: bigint;
48
+ outpointKey(outpoint: {
49
+ txid: string;
50
+ vout: number;
51
+ }): string;
52
+ }): BitcoinTransferPlan;