@cogcoin/client 1.1.7 → 1.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (284) hide show
  1. package/README.md +1 -1
  2. package/dist/bitcoind/service.js +1 -1
  3. package/dist/cli/commands/mining-read.js +1 -1
  4. package/dist/cli/commands/wallet-mutation/anchor.d.ts +2 -0
  5. package/dist/cli/commands/wallet-mutation/anchor.js +33 -0
  6. package/dist/cli/commands/wallet-mutation/bitcoin-transfer.d.ts +2 -0
  7. package/dist/cli/commands/wallet-mutation/bitcoin-transfer.js +32 -0
  8. package/dist/cli/commands/wallet-mutation/cog.d.ts +2 -0
  9. package/dist/cli/commands/wallet-mutation/cog.js +131 -0
  10. package/dist/cli/commands/wallet-mutation/context.d.ts +3 -0
  11. package/dist/cli/commands/wallet-mutation/context.js +18 -0
  12. package/dist/cli/commands/wallet-mutation/domain-admin.d.ts +2 -0
  13. package/dist/cli/commands/wallet-mutation/domain-admin.js +173 -0
  14. package/dist/cli/commands/wallet-mutation/domain-market.d.ts +2 -0
  15. package/dist/cli/commands/wallet-mutation/domain-market.js +107 -0
  16. package/dist/cli/commands/wallet-mutation/field.d.ts +2 -0
  17. package/dist/cli/commands/wallet-mutation/field.js +125 -0
  18. package/dist/cli/commands/wallet-mutation/register.d.ts +2 -0
  19. package/dist/cli/commands/wallet-mutation/register.js +38 -0
  20. package/dist/cli/commands/wallet-mutation/registry.d.ts +3 -0
  21. package/dist/cli/commands/wallet-mutation/registry.js +39 -0
  22. package/dist/cli/commands/wallet-mutation/reputation.d.ts +2 -0
  23. package/dist/cli/commands/wallet-mutation/reputation.js +57 -0
  24. package/dist/cli/commands/wallet-mutation/types.d.ts +32 -0
  25. package/dist/cli/commands/wallet-mutation/types.js +1 -0
  26. package/dist/cli/commands/wallet-mutation.js +13 -765
  27. package/dist/cli/commands/wallet-read.js +4 -4
  28. package/dist/cli/mutation-success.d.ts +0 -2
  29. package/dist/cli/output/classify.d.ts +7 -0
  30. package/dist/cli/output/classify.js +94 -0
  31. package/dist/cli/output/render.d.ts +2 -0
  32. package/dist/cli/output/render.js +13 -0
  33. package/dist/cli/output/rules/cli-surface.d.ts +2 -0
  34. package/dist/cli/output/rules/cli-surface.js +110 -0
  35. package/dist/cli/output/rules/generic.d.ts +2 -0
  36. package/dist/cli/output/rules/generic.js +13 -0
  37. package/dist/cli/output/rules/index.d.ts +2 -0
  38. package/dist/cli/output/rules/index.js +24 -0
  39. package/dist/cli/output/rules/mining-update.d.ts +2 -0
  40. package/dist/cli/output/rules/mining-update.js +68 -0
  41. package/dist/cli/output/rules/services.d.ts +2 -0
  42. package/dist/cli/output/rules/services.js +110 -0
  43. package/dist/cli/output/rules/wallet-admin.d.ts +2 -0
  44. package/dist/cli/output/rules/wallet-admin.js +224 -0
  45. package/dist/cli/output/rules/wallet-mutations.d.ts +2 -0
  46. package/dist/cli/output/rules/wallet-mutations.js +274 -0
  47. package/dist/cli/output/types.d.ts +16 -0
  48. package/dist/cli/output/types.js +1 -0
  49. package/dist/cli/output.d.ts +2 -168
  50. package/dist/cli/output.js +6 -989
  51. package/dist/cli/pagination.d.ts +15 -0
  52. package/dist/cli/pagination.js +16 -0
  53. package/dist/cli/recommendations.d.ts +4 -0
  54. package/dist/cli/recommendations.js +108 -0
  55. package/dist/cli/wallet-format/availability.d.ts +5 -0
  56. package/dist/cli/wallet-format/availability.js +96 -0
  57. package/dist/cli/wallet-format/balance.d.ts +2 -0
  58. package/dist/cli/wallet-format/balance.js +162 -0
  59. package/dist/cli/wallet-format/domains.d.ts +8 -0
  60. package/dist/cli/wallet-format/domains.js +84 -0
  61. package/dist/cli/wallet-format/fields.d.ts +6 -0
  62. package/dist/cli/wallet-format/fields.js +61 -0
  63. package/dist/cli/wallet-format/identity.d.ts +5 -0
  64. package/dist/cli/wallet-format/identity.js +19 -0
  65. package/dist/cli/wallet-format/locks.d.ts +7 -0
  66. package/dist/cli/wallet-format/locks.js +52 -0
  67. package/dist/cli/wallet-format/overview.d.ts +2 -0
  68. package/dist/cli/wallet-format/overview.js +122 -0
  69. package/dist/cli/wallet-format/pending.d.ts +13 -0
  70. package/dist/cli/wallet-format/pending.js +101 -0
  71. package/dist/cli/wallet-format/shared.d.ts +7 -0
  72. package/dist/cli/wallet-format/shared.js +31 -0
  73. package/dist/cli/wallet-format/status.d.ts +3 -0
  74. package/dist/cli/wallet-format/status.js +27 -0
  75. package/dist/cli/wallet-format.d.ts +8 -30
  76. package/dist/cli/wallet-format.js +8 -830
  77. package/dist/cli/wallet-read-helpers.d.ts +6 -0
  78. package/dist/cli/wallet-read-helpers.js +17 -0
  79. package/dist/wallet/mining/candidate.d.ts +1 -1
  80. package/dist/wallet/mining/candidate.js +3 -3
  81. package/dist/wallet/mining/constants.d.ts +2 -2
  82. package/dist/wallet/mining/constants.js +2 -2
  83. package/dist/wallet/mining/engine-state.js +10 -0
  84. package/dist/wallet/mining/sentence-protocol.d.ts +2 -2
  85. package/dist/wallet/mining/sentences.js +8 -8
  86. package/dist/wallet/mining/visualizer-sync.js +79 -15
  87. package/dist/wallet/read/context.js +1 -1
  88. package/dist/wallet/reset/artifacts.d.ts +16 -0
  89. package/dist/wallet/reset/artifacts.js +141 -0
  90. package/dist/wallet/reset/execution.d.ts +38 -0
  91. package/dist/wallet/reset/execution.js +458 -0
  92. package/dist/wallet/reset/preflight.d.ts +7 -0
  93. package/dist/wallet/reset/preflight.js +116 -0
  94. package/dist/wallet/reset/preview.d.ts +2 -0
  95. package/dist/wallet/reset/preview.js +50 -0
  96. package/dist/wallet/reset/process-cleanup.d.ts +12 -0
  97. package/dist/wallet/reset/process-cleanup.js +179 -0
  98. package/dist/wallet/reset/types.d.ts +189 -0
  99. package/dist/wallet/reset/types.js +1 -0
  100. package/dist/wallet/reset.d.ts +4 -119
  101. package/dist/wallet/reset.js +4 -882
  102. package/dist/wallet/tx/anchor/confirm.d.ts +15 -0
  103. package/dist/wallet/tx/anchor/confirm.js +60 -0
  104. package/dist/wallet/tx/anchor/draft.d.ts +39 -0
  105. package/dist/wallet/tx/anchor/draft.js +167 -0
  106. package/dist/wallet/tx/anchor/index.d.ts +5 -0
  107. package/dist/wallet/tx/anchor/index.js +148 -0
  108. package/dist/wallet/tx/anchor/intent.d.ts +61 -0
  109. package/dist/wallet/tx/anchor/intent.js +101 -0
  110. package/dist/wallet/tx/anchor/plan.d.ts +3 -0
  111. package/dist/wallet/tx/anchor/plan.js +18 -0
  112. package/dist/wallet/tx/anchor/result.d.ts +25 -0
  113. package/dist/wallet/tx/anchor/result.js +20 -0
  114. package/dist/wallet/tx/anchor.d.ts +1 -39
  115. package/dist/wallet/tx/anchor.js +1 -494
  116. package/dist/wallet/tx/bitcoin-transfer/confirm.d.ts +7 -0
  117. package/dist/wallet/tx/bitcoin-transfer/confirm.js +11 -0
  118. package/dist/wallet/tx/bitcoin-transfer/index.d.ts +5 -0
  119. package/dist/wallet/tx/bitcoin-transfer/index.js +112 -0
  120. package/dist/wallet/tx/bitcoin-transfer/intent.d.ts +52 -0
  121. package/dist/wallet/tx/bitcoin-transfer/intent.js +74 -0
  122. package/dist/wallet/tx/bitcoin-transfer/plan.d.ts +5 -0
  123. package/dist/wallet/tx/bitcoin-transfer/plan.js +21 -0
  124. package/dist/wallet/tx/bitcoin-transfer/result.d.ts +19 -0
  125. package/dist/wallet/tx/bitcoin-transfer/result.js +16 -0
  126. package/dist/wallet/tx/bitcoin-transfer.d.ts +1 -35
  127. package/dist/wallet/tx/bitcoin-transfer.js +1 -200
  128. package/dist/wallet/tx/cog/confirm.d.ts +13 -0
  129. package/dist/wallet/tx/cog/confirm.js +59 -0
  130. package/dist/wallet/tx/cog/draft.d.ts +20 -0
  131. package/dist/wallet/tx/cog/draft.js +114 -0
  132. package/dist/wallet/tx/cog/index.d.ts +6 -0
  133. package/dist/wallet/tx/cog/index.js +117 -0
  134. package/dist/wallet/tx/cog/intent.d.ts +30 -0
  135. package/dist/wallet/tx/cog/intent.js +169 -0
  136. package/dist/wallet/tx/cog/plan.d.ts +19 -0
  137. package/dist/wallet/tx/cog/plan.js +65 -0
  138. package/dist/wallet/tx/cog/result.d.ts +27 -0
  139. package/dist/wallet/tx/cog/result.js +28 -0
  140. package/dist/wallet/tx/cog/types.d.ts +186 -0
  141. package/dist/wallet/tx/cog/types.js +2 -0
  142. package/dist/wallet/tx/cog/variants/claim.d.ts +3 -0
  143. package/dist/wallet/tx/cog/variants/claim.js +92 -0
  144. package/dist/wallet/tx/cog/variants/lock.d.ts +2 -0
  145. package/dist/wallet/tx/cog/variants/lock.js +102 -0
  146. package/dist/wallet/tx/cog/variants/send.d.ts +2 -0
  147. package/dist/wallet/tx/cog/variants/send.js +77 -0
  148. package/dist/wallet/tx/cog.d.ts +1 -96
  149. package/dist/wallet/tx/cog.js +1 -824
  150. package/dist/wallet/tx/common.d.ts +14 -199
  151. package/dist/wallet/tx/common.js +10 -493
  152. package/dist/wallet/tx/domain-admin/confirm.d.ts +17 -0
  153. package/dist/wallet/tx/domain-admin/confirm.js +58 -0
  154. package/dist/wallet/tx/domain-admin/draft.d.ts +20 -0
  155. package/dist/wallet/tx/domain-admin/draft.js +161 -0
  156. package/dist/wallet/tx/domain-admin/index.d.ts +9 -0
  157. package/dist/wallet/tx/domain-admin/index.js +150 -0
  158. package/dist/wallet/tx/domain-admin/intent.d.ts +12 -0
  159. package/dist/wallet/tx/domain-admin/intent.js +61 -0
  160. package/dist/wallet/tx/domain-admin/plan.d.ts +19 -0
  161. package/dist/wallet/tx/domain-admin/plan.js +64 -0
  162. package/dist/wallet/tx/domain-admin/result.d.ts +19 -0
  163. package/dist/wallet/tx/domain-admin/result.js +33 -0
  164. package/dist/wallet/tx/domain-admin/types.d.ts +162 -0
  165. package/dist/wallet/tx/domain-admin/types.js +1 -0
  166. package/dist/wallet/tx/domain-admin/variants/canonical.d.ts +2 -0
  167. package/dist/wallet/tx/domain-admin/variants/canonical.js +22 -0
  168. package/dist/wallet/tx/domain-admin/variants/delegate.d.ts +3 -0
  169. package/dist/wallet/tx/domain-admin/variants/delegate.js +60 -0
  170. package/dist/wallet/tx/domain-admin/variants/endpoint.d.ts +3 -0
  171. package/dist/wallet/tx/domain-admin/variants/endpoint.js +102 -0
  172. package/dist/wallet/tx/domain-admin/variants/miner.d.ts +3 -0
  173. package/dist/wallet/tx/domain-admin/variants/miner.js +59 -0
  174. package/dist/wallet/tx/domain-admin.d.ts +1 -107
  175. package/dist/wallet/tx/domain-admin.js +1 -729
  176. package/dist/wallet/tx/domain-market/confirm.d.ts +6 -0
  177. package/dist/wallet/tx/domain-market/confirm.js +52 -0
  178. package/dist/wallet/tx/domain-market/draft.d.ts +43 -0
  179. package/dist/wallet/tx/domain-market/draft.js +286 -0
  180. package/dist/wallet/tx/domain-market/index.d.ts +6 -0
  181. package/dist/wallet/tx/domain-market/index.js +145 -0
  182. package/dist/wallet/tx/domain-market/intent.d.ts +15 -0
  183. package/dist/wallet/tx/domain-market/intent.js +131 -0
  184. package/dist/wallet/tx/domain-market/plan.d.ts +31 -0
  185. package/dist/wallet/tx/domain-market/plan.js +98 -0
  186. package/dist/wallet/tx/domain-market/result.d.ts +45 -0
  187. package/dist/wallet/tx/domain-market/result.js +88 -0
  188. package/dist/wallet/tx/domain-market/types.d.ts +221 -0
  189. package/dist/wallet/tx/domain-market/types.js +1 -0
  190. package/dist/wallet/tx/domain-market/variants/buy.d.ts +2 -0
  191. package/dist/wallet/tx/domain-market/variants/buy.js +103 -0
  192. package/dist/wallet/tx/domain-market/variants/sell.d.ts +2 -0
  193. package/dist/wallet/tx/domain-market/variants/sell.js +91 -0
  194. package/dist/wallet/tx/domain-market/variants/transfer.d.ts +2 -0
  195. package/dist/wallet/tx/domain-market/variants/transfer.js +105 -0
  196. package/dist/wallet/tx/domain-market.d.ts +1 -116
  197. package/dist/wallet/tx/domain-market.js +1 -1078
  198. package/dist/wallet/tx/draft-build.d.ts +60 -0
  199. package/dist/wallet/tx/draft-build.js +127 -0
  200. package/dist/wallet/tx/executor.d.ts +6 -40
  201. package/dist/wallet/tx/executor.js +6 -100
  202. package/dist/wallet/tx/fee.d.ts +30 -0
  203. package/dist/wallet/tx/fee.js +98 -0
  204. package/dist/wallet/tx/field/confirm.d.ts +11 -0
  205. package/dist/wallet/tx/field/confirm.js +19 -0
  206. package/dist/wallet/tx/field/draft.d.ts +23 -0
  207. package/dist/wallet/tx/field/draft.js +202 -0
  208. package/dist/wallet/tx/field/index.d.ts +5 -0
  209. package/dist/wallet/tx/field/index.js +140 -0
  210. package/dist/wallet/tx/field/intent.d.ts +5 -0
  211. package/dist/wallet/tx/field/intent.js +50 -0
  212. package/dist/wallet/tx/field/plan.d.ts +20 -0
  213. package/dist/wallet/tx/field/plan.js +65 -0
  214. package/dist/wallet/tx/field/result.d.ts +29 -0
  215. package/dist/wallet/tx/field/result.js +103 -0
  216. package/dist/wallet/tx/field/types.d.ts +163 -0
  217. package/dist/wallet/tx/field/types.js +1 -0
  218. package/dist/wallet/tx/field/variants/clear.d.ts +2 -0
  219. package/dist/wallet/tx/field/variants/clear.js +60 -0
  220. package/dist/wallet/tx/field/variants/create.d.ts +2 -0
  221. package/dist/wallet/tx/field/variants/create.js +67 -0
  222. package/dist/wallet/tx/field/variants/set.d.ts +2 -0
  223. package/dist/wallet/tx/field/variants/set.js +195 -0
  224. package/dist/wallet/tx/field.d.ts +1 -95
  225. package/dist/wallet/tx/field.js +1 -920
  226. package/dist/wallet/tx/mining-preemption.d.ts +6 -0
  227. package/dist/wallet/tx/mining-preemption.js +7 -0
  228. package/dist/wallet/tx/primitives.d.ts +13 -0
  229. package/dist/wallet/tx/primitives.js +42 -0
  230. package/dist/wallet/tx/psbt-assert.d.ts +14 -0
  231. package/dist/wallet/tx/psbt-assert.js +39 -0
  232. package/dist/wallet/tx/publish.d.ts +37 -0
  233. package/dist/wallet/tx/publish.js +88 -0
  234. package/dist/wallet/tx/readiness.d.ts +7 -0
  235. package/dist/wallet/tx/readiness.js +61 -0
  236. package/dist/wallet/tx/reconcile.d.ts +24 -0
  237. package/dist/wallet/tx/reconcile.js +72 -0
  238. package/dist/wallet/tx/register/confirm.d.ts +6 -0
  239. package/dist/wallet/tx/register/confirm.js +66 -0
  240. package/dist/wallet/tx/register/draft.d.ts +42 -0
  241. package/dist/wallet/tx/register/draft.js +181 -0
  242. package/dist/wallet/tx/register/index.d.ts +6 -0
  243. package/dist/wallet/tx/register/index.js +158 -0
  244. package/dist/wallet/tx/register/intent.d.ts +74 -0
  245. package/dist/wallet/tx/register/intent.js +119 -0
  246. package/dist/wallet/tx/register/plan.d.ts +43 -0
  247. package/dist/wallet/tx/register/plan.js +168 -0
  248. package/dist/wallet/tx/register/result.d.ts +78 -0
  249. package/dist/wallet/tx/register/result.js +41 -0
  250. package/dist/wallet/tx/register.d.ts +1 -70
  251. package/dist/wallet/tx/register.js +1 -681
  252. package/dist/wallet/tx/reputation/confirm.d.ts +11 -0
  253. package/dist/wallet/tx/reputation/confirm.js +51 -0
  254. package/dist/wallet/tx/reputation/draft.d.ts +20 -0
  255. package/dist/wallet/tx/reputation/draft.js +130 -0
  256. package/dist/wallet/tx/reputation/index.d.ts +4 -0
  257. package/dist/wallet/tx/reputation/index.js +162 -0
  258. package/dist/wallet/tx/reputation/intent.d.ts +36 -0
  259. package/dist/wallet/tx/reputation/intent.js +157 -0
  260. package/dist/wallet/tx/reputation/plan.d.ts +19 -0
  261. package/dist/wallet/tx/reputation/plan.js +64 -0
  262. package/dist/wallet/tx/reputation/result.d.ts +21 -0
  263. package/dist/wallet/tx/reputation/result.js +31 -0
  264. package/dist/wallet/tx/reputation/types.d.ts +130 -0
  265. package/dist/wallet/tx/reputation/types.js +1 -0
  266. package/dist/wallet/tx/reputation.d.ts +1 -74
  267. package/dist/wallet/tx/reputation.js +1 -556
  268. package/dist/wallet/tx/signing.d.ts +18 -0
  269. package/dist/wallet/tx/signing.js +31 -0
  270. package/dist/wallet/tx/state-persist.d.ts +27 -0
  271. package/dist/wallet/tx/state-persist.js +54 -0
  272. package/dist/wallet/tx/types.d.ts +44 -0
  273. package/dist/wallet/tx/types.js +1 -0
  274. package/package.json +1 -1
  275. package/dist/cli/mining-json.d.ts +0 -20
  276. package/dist/cli/mining-json.js +0 -46
  277. package/dist/cli/mutation-json.d.ts +0 -325
  278. package/dist/cli/mutation-json.js +0 -269
  279. package/dist/cli/mutation-resolved-json.d.ts +0 -117
  280. package/dist/cli/mutation-resolved-json.js +0 -123
  281. package/dist/cli/preview-json.d.ts +0 -319
  282. package/dist/cli/preview-json.js +0 -254
  283. package/dist/cli/read-json.d.ts +0 -190
  284. package/dist/cli/read-json.js +0 -627
@@ -1,39 +1 @@
1
- import { attachOrStartManagedBitcoindService } from "../../bitcoind/service.js";
2
- import { createRpcClient } from "../../bitcoind/node.js";
3
- import type { WalletPrompter } from "../lifecycle.js";
4
- import { type WalletRuntimePaths } from "../runtime.js";
5
- import { type WalletSecretProvider } from "../state/provider.js";
6
- import { openWalletReadContext } from "../read/index.js";
7
- import { type WalletMutationFeeSummary, type WalletMutationRpcClient } from "./common.js";
8
- interface WalletAnchorRpcClient extends WalletMutationRpcClient {
9
- getBlockchainInfo(): Promise<{
10
- blocks: number;
11
- }>;
12
- sendRawTransaction(hex: string): Promise<string>;
13
- getRawMempool(): Promise<string[]>;
14
- }
15
- export interface AnchorDomainOptions {
16
- domainName: string;
17
- foundingMessageText?: string | null;
18
- promptForFoundingMessageWhenMissing?: boolean;
19
- feeRateSatVb?: number | null;
20
- dataDir: string;
21
- databasePath: string;
22
- provider?: WalletSecretProvider;
23
- prompter: WalletPrompter;
24
- nowUnixMs?: number;
25
- paths?: WalletRuntimePaths;
26
- openReadContext?: typeof openWalletReadContext;
27
- attachService?: typeof attachOrStartManagedBitcoindService;
28
- rpcFactory?: (config: Parameters<typeof createRpcClient>[0]) => WalletAnchorRpcClient;
29
- }
30
- export interface AnchorDomainResult {
31
- domainName: string;
32
- txid: string;
33
- status: "live" | "confirmed";
34
- reusedExisting: boolean;
35
- foundingMessageText?: string | null;
36
- fees: WalletMutationFeeSummary;
37
- }
38
- export declare function anchorDomain(options: AnchorDomainOptions): Promise<AnchorDomainResult>;
39
- export {};
1
+ export * from "./anchor/index.js";
@@ -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
+ }