@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,920 +1 @@
1
- import { createHash, randomBytes } from "node:crypto";
2
- import { readFile } from "node:fs/promises";
3
- import { resolve as resolvePath } from "node:path";
4
- import { getBalance, lookupDomain, } from "@cogcoin/indexer/queries";
5
- import { attachOrStartManagedBitcoindService } from "../../bitcoind/service.js";
6
- import { createRpcClient } from "../../bitcoind/node.js";
7
- import {} from "../runtime.js";
8
- import {} from "../state/provider.js";
9
- import { FIELD_FORMAT_BYTES, serializeDataUpdate, serializeFieldReg, } from "../cogop/index.js";
10
- import { validateFieldName } from "../cogop/validate-name.js";
11
- import { findDomainField, openWalletReadContext, } from "../read/index.js";
12
- import { assertWalletMutationContextReady, buildWalletMutationTransactionWithReserveFallback, createWalletMutationFeeMetadata, mergeFixedWalletInputs, outpointKey, unlockTemporaryBuilderLocks, updateMutationRecord, } from "./common.js";
13
- import { confirmTypedAcknowledgement as confirmSharedTypedAcknowledgement, confirmYesNo as confirmSharedYesNo, } from "./confirm.js";
14
- import { executeWalletMutationOperation, persistWalletMutationState, publishWalletMutation, resolveExistingWalletMutation, } from "./executor.js";
15
- import { upsertPendingMutation } from "./journal.js";
16
- function createResolvedFieldSenderSummary(sender, selector) {
17
- return {
18
- selector,
19
- localIndex: sender.localIndex,
20
- scriptPubKeyHex: sender.scriptPubKeyHex,
21
- address: sender.address,
22
- };
23
- }
24
- function createResolvedFieldValueSummary(format, value) {
25
- return {
26
- format,
27
- byteLength: typeof value === "string" ? value.length / 2 : value.length,
28
- };
29
- }
30
- function createResolvedFieldSummary(options) {
31
- if (options.kind === "field-create") {
32
- return {
33
- sender: createResolvedFieldSenderSummary(options.sender, options.senderSelector),
34
- path: "standalone-field-reg",
35
- value: null,
36
- effect: {
37
- kind: "create-empty-field",
38
- burnCogtoshi: "100",
39
- },
40
- };
41
- }
42
- if (options.kind === "field-set") {
43
- return {
44
- sender: createResolvedFieldSenderSummary(options.sender, options.senderSelector),
45
- path: "standalone-data-update",
46
- value: options.value,
47
- effect: {
48
- kind: "write-field-value",
49
- burnCogtoshi: "1",
50
- },
51
- };
52
- }
53
- return {
54
- sender: createResolvedFieldSenderSummary(options.sender, options.senderSelector),
55
- path: "standalone-data-clear",
56
- value: null,
57
- effect: {
58
- kind: "clear-field-value",
59
- burnCogtoshi: "0",
60
- },
61
- };
62
- }
63
- function createResolvedFieldValueFromStoredData(kind, format, valueHex) {
64
- if (kind === "field-clear" || format === null || format === undefined || valueHex === null || valueHex === undefined) {
65
- return null;
66
- }
67
- return createResolvedFieldValueSummary(format, valueHex);
68
- }
69
- function describeFieldEffect(effect) {
70
- switch (effect.kind) {
71
- case "create-empty-field":
72
- return `burn ${effect.burnCogtoshi} cogtoshi to create an empty field`;
73
- case "write-field-value":
74
- return `burn ${effect.burnCogtoshi} cogtoshi to write the field value`;
75
- case "clear-field-value":
76
- return "clear the field value with no additional COG burn";
77
- }
78
- }
79
- function normalizeDomainName(domainName) {
80
- const normalized = domainName.trim().toLowerCase();
81
- if (normalized.length === 0) {
82
- throw new Error("wallet_field_missing_domain");
83
- }
84
- return normalized;
85
- }
86
- function normalizeFieldName(fieldName) {
87
- const normalized = fieldName.trim().toLowerCase();
88
- if (normalized.length === 0) {
89
- throw new Error("wallet_field_missing_field_name");
90
- }
91
- validateFieldName(normalized);
92
- return normalized;
93
- }
94
- function encodeOpReturnScript(payload) {
95
- if (payload.length <= 75) {
96
- return Buffer.concat([
97
- Buffer.from([0x6a, payload.length]),
98
- Buffer.from(payload),
99
- ]).toString("hex");
100
- }
101
- return Buffer.concat([
102
- Buffer.from([0x6a, 0x4c, payload.length]),
103
- Buffer.from(payload),
104
- ]).toString("hex");
105
- }
106
- function satsToBtcNumber(value) {
107
- return Number(value) / 100_000_000;
108
- }
109
- function valueToSats(value) {
110
- const text = typeof value === "number" ? value.toFixed(8) : value;
111
- const match = /^(-?)(\d+)(?:\.(\d{0,8}))?$/.exec(text.trim());
112
- if (match == null) {
113
- throw new Error(`wallet_field_invalid_amount_${text}`);
114
- }
115
- const sign = match[1] === "-" ? -1n : 1n;
116
- const whole = BigInt(match[2] ?? "0");
117
- const fraction = BigInt((match[3] ?? "").padEnd(8, "0"));
118
- return sign * ((whole * 100000000n) + fraction);
119
- }
120
- function createIntentFingerprint(parts) {
121
- return createHash("sha256")
122
- .update(parts.map((part) => String(part)).join("\n"))
123
- .digest("hex");
124
- }
125
- function hex(value) {
126
- if (value === null || value === undefined) {
127
- return null;
128
- }
129
- return Buffer.from(value).toString("hex");
130
- }
131
- function isActiveMutationStatus(status) {
132
- return status === "draft"
133
- || status === "broadcasting"
134
- || status === "broadcast-unknown"
135
- || status === "live"
136
- || status === "repair-required";
137
- }
138
- function findActiveFieldCreateMutationByDomain(state, domainName, intentFingerprintHex) {
139
- return (state.pendingMutations ?? []).find((mutation) => mutation.kind === "field-create"
140
- && mutation.domainName === domainName
141
- && mutation.intentFingerprintHex !== intentFingerprintHex
142
- && isActiveMutationStatus(mutation.status)) ?? null;
143
- }
144
- function resolveAnchoredFieldOperation(context, domainName, errorPrefix) {
145
- assertWalletMutationContextReady(context, errorPrefix);
146
- const chainDomain = lookupDomain(context.snapshot.state, domainName);
147
- if (chainDomain === null) {
148
- throw new Error(`${errorPrefix}_domain_not_found`);
149
- }
150
- if (!chainDomain.anchored) {
151
- throw new Error(`${errorPrefix}_domain_not_anchored`);
152
- }
153
- const ownerHex = Buffer.from(chainDomain.ownerScriptPubKey).toString("hex");
154
- const state = context.localState.state;
155
- if (ownerHex !== state.funding.scriptPubKeyHex || state.funding.address.trim() === "") {
156
- throw new Error(`${errorPrefix}_owner_not_locally_controlled`);
157
- }
158
- return {
159
- readContext: context,
160
- state,
161
- sender: {
162
- localIndex: 0,
163
- scriptPubKeyHex: state.funding.scriptPubKeyHex,
164
- address: state.funding.address,
165
- },
166
- senderSelector: state.funding.address,
167
- chainDomain,
168
- };
169
- }
170
- function buildAnchoredFieldPlan(options) {
171
- const fundingUtxos = options.allUtxos.filter((entry) => entry.scriptPubKey === options.state.funding.scriptPubKeyHex
172
- && entry.confirmations >= 1
173
- && entry.spendable !== false
174
- && entry.safe !== false);
175
- return {
176
- sender: options.sender,
177
- changeAddress: options.state.funding.address,
178
- fixedInputs: [],
179
- outputs: [{ data: Buffer.from(options.opReturnData).toString("hex") }],
180
- changePosition: 1,
181
- expectedOpReturnScriptHex: encodeOpReturnScript(options.opReturnData),
182
- allowedFundingScriptPubKeyHex: options.state.funding.scriptPubKeyHex,
183
- eligibleFundingOutpointKeys: new Set(fundingUtxos.map((entry) => outpointKey({ txid: entry.txid, vout: entry.vout }))),
184
- errorPrefix: options.errorPrefix,
185
- };
186
- }
187
- function validateFieldDraft(decoded, funded, plan) {
188
- const inputs = decoded.tx.vin;
189
- const outputs = decoded.tx.vout;
190
- if (inputs.length === 0) {
191
- throw new Error(`${plan.errorPrefix}_missing_sender_input`);
192
- }
193
- if (outputs[0]?.scriptPubKey?.hex !== plan.expectedOpReturnScriptHex) {
194
- throw new Error(`${plan.errorPrefix}_opreturn_mismatch`);
195
- }
196
- if (funded.changepos === -1) {
197
- if (outputs.length !== 1) {
198
- throw new Error(`${plan.errorPrefix}_unexpected_output_count`);
199
- }
200
- return;
201
- }
202
- if (funded.changepos !== plan.changePosition || outputs.length !== 2) {
203
- throw new Error(`${plan.errorPrefix}_change_position_mismatch`);
204
- }
205
- if (outputs[funded.changepos]?.scriptPubKey?.hex !== plan.allowedFundingScriptPubKeyHex) {
206
- throw new Error(`${plan.errorPrefix}_change_output_mismatch`);
207
- }
208
- }
209
- async function buildFieldTransaction(options) {
210
- return buildWalletMutationTransactionWithReserveFallback({
211
- rpc: options.rpc,
212
- walletName: options.walletName,
213
- state: options.state,
214
- plan: options.plan,
215
- validateFundedDraft: validateFieldDraft,
216
- finalizeErrorCode: `${options.plan.errorPrefix}_finalize_failed`,
217
- mempoolRejectPrefix: `${options.plan.errorPrefix}_mempool_rejected`,
218
- feeRate: options.feeRateSatVb,
219
- availableFundingMinConf: options.availableFundingMinConf,
220
- });
221
- }
222
- async function saveUpdatedState(options) {
223
- return persistWalletMutationState(options);
224
- }
225
- function createStandaloneFieldMutation(options) {
226
- if (options.existing !== null && options.existing !== undefined) {
227
- return {
228
- ...options.existing,
229
- kind: options.kind,
230
- domainName: options.domainName,
231
- senderScriptPubKeyHex: options.sender.scriptPubKeyHex,
232
- senderLocalIndex: options.sender.localIndex,
233
- fieldName: options.fieldName,
234
- fieldId: options.fieldId ?? null,
235
- fieldPermanent: options.fieldPermanent ?? null,
236
- fieldFormat: options.fieldFormat ?? null,
237
- fieldValueHex: options.fieldValueHex ?? null,
238
- status: "draft",
239
- lastUpdatedAtUnixMs: options.nowUnixMs,
240
- attemptedTxid: null,
241
- attemptedWtxid: null,
242
- ...createWalletMutationFeeMetadata(options.feeSelection),
243
- temporaryBuilderLockedOutpoints: [],
244
- };
245
- }
246
- return {
247
- mutationId: randomBytes(12).toString("hex"),
248
- kind: options.kind,
249
- domainName: options.domainName,
250
- parentDomainName: null,
251
- senderScriptPubKeyHex: options.sender.scriptPubKeyHex,
252
- senderLocalIndex: options.sender.localIndex,
253
- fieldName: options.fieldName,
254
- fieldId: options.fieldId ?? null,
255
- fieldPermanent: options.fieldPermanent ?? null,
256
- fieldFormat: options.fieldFormat ?? null,
257
- fieldValueHex: options.fieldValueHex ?? null,
258
- intentFingerprintHex: options.intentFingerprintHex,
259
- status: "draft",
260
- createdAtUnixMs: options.nowUnixMs,
261
- lastUpdatedAtUnixMs: options.nowUnixMs,
262
- attemptedTxid: null,
263
- attemptedWtxid: null,
264
- ...createWalletMutationFeeMetadata(options.feeSelection),
265
- temporaryBuilderLockedOutpoints: [],
266
- };
267
- }
268
- function getObservedFieldState(context, domainName, fieldName) {
269
- if (context.snapshot === null) {
270
- return null;
271
- }
272
- return findDomainField(context, domainName, fieldName);
273
- }
274
- function standaloneMutationConfirmedOnChain(mutation, context) {
275
- const observed = mutation.fieldName == null
276
- ? null
277
- : getObservedFieldState(context, mutation.domainName, mutation.fieldName);
278
- const chainDomain = context.snapshot === null ? null : lookupDomain(context.snapshot.state, mutation.domainName);
279
- if (chainDomain === null || !chainDomain.anchored) {
280
- return false;
281
- }
282
- const ownerHex = Buffer.from(chainDomain.ownerScriptPubKey).toString("hex");
283
- if (ownerHex !== mutation.senderScriptPubKeyHex) {
284
- return false;
285
- }
286
- if (mutation.kind === "field-create") {
287
- return observed !== null
288
- && (mutation.fieldPermanent == null || observed.permanent === mutation.fieldPermanent);
289
- }
290
- if (mutation.kind === "field-clear") {
291
- return observed !== null && !observed.hasValue;
292
- }
293
- return observed !== null
294
- && observed.hasValue
295
- && observed.format === (mutation.fieldFormat ?? null)
296
- && observed.rawValueHex === (mutation.fieldValueHex ?? null);
297
- }
298
- function standaloneMutationNeedsRepair(mutation, context) {
299
- if (context.snapshot === null) {
300
- return false;
301
- }
302
- const chainDomain = lookupDomain(context.snapshot.state, mutation.domainName);
303
- if (chainDomain === null || !chainDomain.anchored) {
304
- return true;
305
- }
306
- const ownerHex = Buffer.from(chainDomain.ownerScriptPubKey).toString("hex");
307
- if (ownerHex !== mutation.senderScriptPubKeyHex) {
308
- return true;
309
- }
310
- if (mutation.fieldName == null) {
311
- return false;
312
- }
313
- const observed = getObservedFieldState(context, mutation.domainName, mutation.fieldName);
314
- if (mutation.kind === "field-create") {
315
- return observed !== null
316
- && mutation.fieldPermanent !== null
317
- && observed.permanent !== mutation.fieldPermanent;
318
- }
319
- if (mutation.kind === "field-set") {
320
- return observed !== null
321
- && observed.hasValue
322
- && ((mutation.fieldFormat ?? null) !== observed.format || (mutation.fieldValueHex ?? null) !== observed.rawValueHex);
323
- }
324
- return false;
325
- }
326
- async function reconcilePendingFieldMutation(options) {
327
- if (options.mutation.status === "confirmed" || options.mutation.status === "live") {
328
- return {
329
- state: options.state,
330
- mutation: options.mutation,
331
- resolution: options.mutation.status,
332
- };
333
- }
334
- if (options.mutation.status === "repair-required") {
335
- return {
336
- state: options.state,
337
- mutation: options.mutation,
338
- resolution: "repair-required",
339
- };
340
- }
341
- if (standaloneMutationConfirmedOnChain(options.mutation, options.context)) {
342
- await unlockTemporaryBuilderLocks(options.rpc, options.walletName, options.mutation.temporaryBuilderLockedOutpoints);
343
- const confirmed = updateMutationRecord(options.mutation, "confirmed", options.nowUnixMs, {
344
- temporaryBuilderLockedOutpoints: [],
345
- });
346
- let nextState = upsertPendingMutation(options.state, confirmed);
347
- nextState = await saveUpdatedState({
348
- state: nextState,
349
- provider: options.provider,
350
- nowUnixMs: options.nowUnixMs,
351
- paths: options.paths,
352
- });
353
- return { state: nextState, mutation: confirmed, resolution: "confirmed" };
354
- }
355
- if (standaloneMutationNeedsRepair(options.mutation, options.context)) {
356
- await unlockTemporaryBuilderLocks(options.rpc, options.walletName, options.mutation.temporaryBuilderLockedOutpoints);
357
- const repair = updateMutationRecord(options.mutation, "repair-required", options.nowUnixMs, {
358
- temporaryBuilderLockedOutpoints: [],
359
- });
360
- let nextState = upsertPendingMutation(options.state, repair);
361
- nextState = await saveUpdatedState({
362
- state: nextState,
363
- provider: options.provider,
364
- nowUnixMs: options.nowUnixMs,
365
- paths: options.paths,
366
- });
367
- return { state: nextState, mutation: repair, resolution: "repair-required" };
368
- }
369
- const known = options.mutation.attemptedTxid === null
370
- ? false
371
- : await options.rpc.getRawTransaction(options.mutation.attemptedTxid, true).then(() => true).catch(() => false);
372
- if (known) {
373
- await unlockTemporaryBuilderLocks(options.rpc, options.walletName, options.mutation.temporaryBuilderLockedOutpoints);
374
- const live = updateMutationRecord(options.mutation, "live", options.nowUnixMs, {
375
- temporaryBuilderLockedOutpoints: [],
376
- });
377
- let nextState = upsertPendingMutation(options.state, live);
378
- nextState = await saveUpdatedState({
379
- state: nextState,
380
- provider: options.provider,
381
- nowUnixMs: options.nowUnixMs,
382
- paths: options.paths,
383
- });
384
- return { state: nextState, mutation: live, resolution: "live" };
385
- }
386
- if (options.mutation.status === "broadcast-unknown"
387
- || options.mutation.status === "draft"
388
- || options.mutation.status === "broadcasting") {
389
- await unlockTemporaryBuilderLocks(options.rpc, options.walletName, options.mutation.temporaryBuilderLockedOutpoints);
390
- const canceled = updateMutationRecord(options.mutation, "canceled", options.nowUnixMs, {
391
- temporaryBuilderLockedOutpoints: [],
392
- });
393
- let nextState = upsertPendingMutation(options.state, canceled);
394
- nextState = await saveUpdatedState({
395
- state: nextState,
396
- provider: options.provider,
397
- nowUnixMs: options.nowUnixMs,
398
- paths: options.paths,
399
- });
400
- return { state: nextState, mutation: canceled, resolution: "not-seen" };
401
- }
402
- return {
403
- state: options.state,
404
- mutation: options.mutation,
405
- resolution: "continue",
406
- };
407
- }
408
- async function confirmYesNo(prompter, message, errorCode, options) {
409
- await confirmSharedYesNo(prompter, message, {
410
- assumeYes: options.assumeYes,
411
- errorCode,
412
- requiresTtyErrorCode: options.requiresTtyErrorCode,
413
- });
414
- }
415
- async function confirmTyped(prompter, expected, prompt, errorCode, options) {
416
- await confirmSharedTypedAcknowledgement(prompter, {
417
- assumeYes: options.assumeYes,
418
- expected,
419
- prompt,
420
- errorCode,
421
- requiresTtyErrorCode: options.requiresTtyErrorCode,
422
- typedAckRequiredErrorCode: options.typedAckRequiredErrorCode,
423
- });
424
- }
425
- async function confirmFieldCreate(prompter, options) {
426
- const fieldRef = `${options.domainName}:${options.fieldName}`;
427
- prompter.writeLine(`Creating field "${fieldRef}" as ${options.permanent ? "permanent" : "mutable"}.`);
428
- prompter.writeLine(`Resolved sender: ${options.sender.selector} (${options.sender.address})`);
429
- prompter.writeLine("Path: standalone-field-reg");
430
- prompter.writeLine(`Effect: ${describeFieldEffect({ kind: "create-empty-field", burnCogtoshi: "100" })}.`);
431
- prompter.writeLine("This publishes a standalone FIELD_REG and burns 0.00000100 COG.");
432
- await confirmYesNo(prompter, "The field will be created empty and the burn is not reversible.", "wallet_field_create_confirmation_rejected", {
433
- assumeYes: options.assumeYes,
434
- requiresTtyErrorCode: "wallet_field_create_requires_tty",
435
- });
436
- }
437
- async function confirmFieldSet(prompter, options) {
438
- const fieldRef = `${options.domainName}:${options.fieldName}`;
439
- prompter.writeLine(`Updating field "${fieldRef}".`);
440
- prompter.writeLine(`Resolved sender: ${options.sender.selector} (${options.sender.address})`);
441
- prompter.writeLine("Path: standalone-data-update");
442
- prompter.writeLine(`Effect: ${describeFieldEffect({ kind: "write-field-value", burnCogtoshi: "1" })}.`);
443
- prompter.writeLine(`Format: ${options.value.formatLabel}`);
444
- prompter.writeLine(`Value bytes: ${options.value.value.length}`);
445
- prompter.writeLine("Warning: the field value is public in the mempool and on-chain.");
446
- if (options.isFirstPermanentWrite && options.fieldPermanent) {
447
- prompter.writeLine("This is the first non-clear value write to a permanent field.");
448
- await confirmTyped(prompter, fieldRef, `Type ${fieldRef} to continue: `, "wallet_field_set_confirmation_rejected", {
449
- assumeYes: options.assumeYes,
450
- requiresTtyErrorCode: "wallet_field_set_requires_tty",
451
- typedAckRequiredErrorCode: "wallet_field_set_typed_ack_required",
452
- });
453
- return;
454
- }
455
- await confirmYesNo(prompter, "This publishes a standalone DATA_UPDATE.", "wallet_field_set_confirmation_rejected", {
456
- assumeYes: options.assumeYes,
457
- requiresTtyErrorCode: "wallet_field_set_requires_tty",
458
- });
459
- }
460
- function describeRawFormat(format) {
461
- if (format === FIELD_FORMAT_BYTES.bytes) {
462
- return "bytes (0x01)";
463
- }
464
- if (format === FIELD_FORMAT_BYTES.text) {
465
- return "text (0x02)";
466
- }
467
- if (format === FIELD_FORMAT_BYTES.json) {
468
- return "json (0x09)";
469
- }
470
- return `raw (0x${format.toString(16).padStart(2, "0")})`;
471
- }
472
- async function loadFieldValue(source) {
473
- if (source.kind === "text") {
474
- if (source.value.length === 0) {
475
- throw new Error("wallet_field_value_missing");
476
- }
477
- const value = new TextEncoder().encode(source.value);
478
- return {
479
- format: FIELD_FORMAT_BYTES.text,
480
- formatLabel: "text (0x02)",
481
- value,
482
- valueHex: Buffer.from(value).toString("hex"),
483
- };
484
- }
485
- if (source.kind === "json") {
486
- if (source.value.length === 0) {
487
- throw new Error("wallet_field_value_missing");
488
- }
489
- try {
490
- JSON.parse(source.value);
491
- }
492
- catch {
493
- throw new Error("wallet_field_invalid_json");
494
- }
495
- const value = new TextEncoder().encode(source.value);
496
- return {
497
- format: FIELD_FORMAT_BYTES.json,
498
- formatLabel: "json (0x09)",
499
- value,
500
- valueHex: Buffer.from(value).toString("hex"),
501
- };
502
- }
503
- if (source.kind === "bytes") {
504
- let value;
505
- if (source.value.startsWith("hex:")) {
506
- const payload = source.value.slice(4);
507
- if (!/^[0-9a-f]+$/.test(payload) || payload.length % 2 !== 0) {
508
- throw new Error("wallet_field_invalid_bytes");
509
- }
510
- value = Buffer.from(payload, "hex");
511
- }
512
- else if (source.value.startsWith("@")) {
513
- const filePath = source.value.slice(1);
514
- if (filePath.trim() === "") {
515
- throw new Error("wallet_field_invalid_bytes");
516
- }
517
- value = await readFile(resolvePath(process.cwd(), filePath));
518
- }
519
- else {
520
- throw new Error("wallet_field_invalid_bytes");
521
- }
522
- if (value.length === 0) {
523
- throw new Error("wallet_field_value_missing");
524
- }
525
- return {
526
- format: FIELD_FORMAT_BYTES.bytes,
527
- formatLabel: "bytes (0x01)",
528
- value,
529
- valueHex: value.toString("hex"),
530
- };
531
- }
532
- const match = /^raw:(\d{1,3})$/.exec(source.format);
533
- if (match == null) {
534
- throw new Error("wallet_field_invalid_raw_format");
535
- }
536
- const format = Number.parseInt(match[1], 10);
537
- if (!Number.isInteger(format) || format < 0 || format > 0xff || format === FIELD_FORMAT_BYTES.clear) {
538
- throw new Error("wallet_field_invalid_raw_format");
539
- }
540
- let value;
541
- if (source.value.startsWith("hex:")) {
542
- const payload = source.value.slice(4);
543
- if (!/^[0-9a-f]+$/.test(payload) || payload.length % 2 !== 0) {
544
- throw new Error("wallet_field_invalid_value");
545
- }
546
- value = Buffer.from(payload, "hex");
547
- }
548
- else if (source.value.startsWith("@")) {
549
- const filePath = source.value.slice(1);
550
- if (filePath.trim() === "") {
551
- throw new Error("wallet_field_invalid_value");
552
- }
553
- value = await readFile(resolvePath(process.cwd(), filePath));
554
- }
555
- else if (source.value.startsWith("utf8:")) {
556
- value = new TextEncoder().encode(source.value.slice(5));
557
- }
558
- else {
559
- throw new Error("wallet_field_invalid_value");
560
- }
561
- if (value.length === 0) {
562
- throw new Error("wallet_field_value_missing");
563
- }
564
- return {
565
- format,
566
- formatLabel: describeRawFormat(format),
567
- value,
568
- valueHex: Buffer.from(value).toString("hex"),
569
- };
570
- }
571
- async function submitStandaloneFieldMutation(options) {
572
- if (!options.prompter.isInteractive && options.assumeYes !== true) {
573
- throw new Error(`${options.errorPrefix}_requires_tty`);
574
- }
575
- const execution = await executeWalletMutationOperation({
576
- ...options,
577
- controlLockPurpose: options.errorPrefix,
578
- preemptionReason: options.errorPrefix,
579
- resolveOperation(readContext) {
580
- const normalizedDomainName = normalizeDomainName(options.domainName);
581
- const normalizedFieldName = normalizeFieldName(options.fieldName);
582
- const operation = resolveAnchoredFieldOperation(readContext, normalizedDomainName, options.errorPrefix);
583
- return {
584
- ...operation,
585
- normalizedDomainName,
586
- normalizedFieldName,
587
- existingObservedField: getObservedFieldState(readContext, normalizedDomainName, normalizedFieldName),
588
- };
589
- },
590
- createIntentFingerprint(operation) {
591
- return createIntentFingerprint([
592
- options.kind,
593
- operation.state.walletRootId,
594
- operation.normalizedDomainName,
595
- operation.normalizedFieldName,
596
- ]);
597
- },
598
- async resolveExistingMutation({ operation, existingMutation, execution }) {
599
- if (existingMutation === null) {
600
- return {
601
- state: operation.state,
602
- replacementFixedInputs: null,
603
- result: null,
604
- };
605
- }
606
- return resolveExistingWalletMutation({
607
- existingMutation,
608
- execution,
609
- repairRequiredErrorCode: `${options.errorPrefix}_repair_required`,
610
- reconcileExistingMutation: (mutation) => reconcilePendingFieldMutation({
611
- state: operation.state,
612
- mutation,
613
- provider: execution.provider,
614
- nowUnixMs: execution.nowUnixMs,
615
- paths: execution.paths,
616
- rpc: execution.rpc,
617
- walletName: execution.walletName,
618
- context: execution.readContext,
619
- }),
620
- createReuseResult: ({ mutation, resolution, fees }) => ({
621
- kind: options.kind,
622
- domainName: operation.normalizedDomainName,
623
- fieldName: operation.normalizedFieldName,
624
- fieldId: mutation.fieldId ?? operation.existingObservedField?.fieldId ?? null,
625
- txid: mutation.attemptedTxid ?? "unknown",
626
- permanent: mutation.fieldPermanent ?? operation.existingObservedField?.permanent ?? null,
627
- format: mutation.fieldFormat ?? operation.existingObservedField?.format ?? null,
628
- status: resolution,
629
- reusedExisting: true,
630
- resolved: createResolvedFieldSummary({
631
- sender: operation.sender,
632
- senderSelector: operation.senderSelector,
633
- kind: options.kind,
634
- value: createResolvedFieldValueFromStoredData(options.kind, mutation.fieldFormat ?? operation.existingObservedField?.format ?? null, mutation.fieldValueHex),
635
- }),
636
- fees,
637
- }),
638
- });
639
- },
640
- confirm({ operation }) {
641
- return options.confirm(operation);
642
- },
643
- async createDraftMutation({ operation, existingMutation, execution }) {
644
- const prepared = await options.createMutation(operation, existingMutation, execution.feeSelection);
645
- return {
646
- mutation: prepared.mutation,
647
- prepared: {
648
- opReturnData: prepared.opReturnData,
649
- },
650
- };
651
- },
652
- async build({ operation, state, execution, replacementFixedInputs, prepared }) {
653
- const fieldPlan = buildAnchoredFieldPlan({
654
- state,
655
- allUtxos: await execution.rpc.listUnspent(execution.walletName, 1),
656
- sender: operation.sender,
657
- opReturnData: prepared.opReturnData,
658
- errorPrefix: options.errorPrefix,
659
- });
660
- return buildFieldTransaction({
661
- rpc: execution.rpc,
662
- walletName: execution.walletName,
663
- state,
664
- plan: {
665
- ...fieldPlan,
666
- fixedInputs: mergeFixedWalletInputs(fieldPlan.fixedInputs, replacementFixedInputs),
667
- },
668
- feeRateSatVb: execution.feeSelection.feeRateSatVb,
669
- });
670
- },
671
- publish({ state, execution, built, mutation }) {
672
- return publishWalletMutation({
673
- rpc: execution.rpc,
674
- walletName: execution.walletName,
675
- snapshotHeight: execution.readContext.snapshot?.tip?.height ?? null,
676
- built,
677
- mutation,
678
- state,
679
- provider: execution.provider,
680
- nowUnixMs: execution.nowUnixMs,
681
- paths: execution.paths,
682
- errorPrefix: options.errorPrefix,
683
- });
684
- },
685
- createResult({ operation, mutation, built, status, reusedExisting, fees }) {
686
- return {
687
- kind: options.kind,
688
- domainName: operation.normalizedDomainName,
689
- fieldName: operation.normalizedFieldName,
690
- fieldId: mutation.fieldId ?? operation.existingObservedField?.fieldId ?? null,
691
- txid: mutation.attemptedTxid ?? built?.txid ?? "unknown",
692
- permanent: mutation.fieldPermanent ?? operation.existingObservedField?.permanent ?? null,
693
- format: mutation.fieldFormat ?? operation.existingObservedField?.format ?? null,
694
- status: status,
695
- reusedExisting,
696
- resolved: createResolvedFieldSummary({
697
- sender: operation.sender,
698
- senderSelector: operation.senderSelector,
699
- kind: options.kind,
700
- value: createResolvedFieldValueFromStoredData(options.kind, mutation.fieldFormat ?? operation.existingObservedField?.format ?? null, mutation.fieldValueHex),
701
- }),
702
- fees,
703
- };
704
- },
705
- });
706
- return execution.result;
707
- }
708
- export async function createField(options) {
709
- const permanent = options.permanent ?? false;
710
- return submitStandaloneFieldMutation({
711
- kind: "field-create",
712
- errorPrefix: "wallet_field_create",
713
- domainName: options.domainName,
714
- fieldName: options.fieldName,
715
- dataDir: options.dataDir,
716
- databasePath: options.databasePath,
717
- provider: options.provider,
718
- prompter: options.prompter,
719
- assumeYes: options.assumeYes,
720
- nowUnixMs: options.nowUnixMs,
721
- paths: options.paths,
722
- openReadContext: options.openReadContext,
723
- attachService: options.attachService,
724
- rpcFactory: options.rpcFactory,
725
- async createMutation(operation, existing, feeSelection) {
726
- const existingField = getObservedFieldState(operation.readContext, normalizeDomainName(options.domainName), normalizeFieldName(options.fieldName));
727
- if (existingField !== null) {
728
- throw new Error("wallet_field_create_field_exists");
729
- }
730
- if (operation.chainDomain.nextFieldId === 0xffff_ffff) {
731
- throw new Error("wallet_field_create_field_id_exhausted");
732
- }
733
- const senderBalance = getBalance(operation.readContext.snapshot.state, Buffer.from(operation.sender.scriptPubKeyHex, "hex"));
734
- if (senderBalance < 100n) {
735
- throw new Error("wallet_field_create_insufficient_cog");
736
- }
737
- const normalizedDomainName = normalizeDomainName(options.domainName);
738
- const normalizedFieldName = normalizeFieldName(options.fieldName);
739
- const intentFingerprintHex = createIntentFingerprint([
740
- "field-create",
741
- operation.state.walletRootId,
742
- normalizedDomainName,
743
- normalizedFieldName,
744
- permanent ? 1 : 0,
745
- ]);
746
- const conflictCreate = findActiveFieldCreateMutationByDomain(operation.state, normalizedDomainName, intentFingerprintHex);
747
- if (conflictCreate !== null) {
748
- throw new Error("wallet_field_create_registration_already_pending");
749
- }
750
- return {
751
- opReturnData: serializeFieldReg(operation.chainDomain.domainId, permanent, normalizedFieldName).opReturnData,
752
- mutation: createStandaloneFieldMutation({
753
- kind: "field-create",
754
- domainName: normalizedDomainName,
755
- fieldName: normalizedFieldName,
756
- sender: operation.sender,
757
- intentFingerprintHex,
758
- nowUnixMs: options.nowUnixMs ?? Date.now(),
759
- feeSelection,
760
- existing,
761
- fieldId: operation.chainDomain.nextFieldId,
762
- fieldPermanent: permanent,
763
- }),
764
- };
765
- },
766
- async confirm(operation) {
767
- await confirmFieldCreate(options.prompter, {
768
- domainName: normalizeDomainName(options.domainName),
769
- fieldName: normalizeFieldName(options.fieldName),
770
- permanent,
771
- sender: createResolvedFieldSenderSummary(operation.sender, operation.senderSelector),
772
- assumeYes: options.assumeYes,
773
- });
774
- },
775
- });
776
- }
777
- export async function setField(options) {
778
- const value = await loadFieldValue(options.source);
779
- return submitStandaloneFieldMutation({
780
- kind: "field-set",
781
- errorPrefix: "wallet_field_set",
782
- domainName: options.domainName,
783
- fieldName: options.fieldName,
784
- dataDir: options.dataDir,
785
- databasePath: options.databasePath,
786
- provider: options.provider,
787
- prompter: options.prompter,
788
- assumeYes: options.assumeYes,
789
- nowUnixMs: options.nowUnixMs,
790
- paths: options.paths,
791
- openReadContext: options.openReadContext,
792
- attachService: options.attachService,
793
- rpcFactory: options.rpcFactory,
794
- async createMutation(operation, existing, feeSelection) {
795
- const normalizedDomainName = normalizeDomainName(options.domainName);
796
- const normalizedFieldName = normalizeFieldName(options.fieldName);
797
- const observedField = getObservedFieldState(operation.readContext, normalizedDomainName, normalizedFieldName);
798
- if (observedField === null) {
799
- throw new Error("wallet_field_set_field_not_found");
800
- }
801
- if (observedField.permanent && observedField.hasValue) {
802
- throw new Error("wallet_field_set_permanent_field_frozen");
803
- }
804
- const senderBalance = getBalance(operation.readContext.snapshot.state, Buffer.from(operation.sender.scriptPubKeyHex, "hex"));
805
- if (senderBalance < 1n) {
806
- throw new Error("wallet_field_set_insufficient_cog");
807
- }
808
- const intentFingerprintHex = createIntentFingerprint([
809
- "field-set",
810
- operation.state.walletRootId,
811
- normalizedDomainName,
812
- observedField.fieldId,
813
- value.format,
814
- value.valueHex,
815
- ]);
816
- return {
817
- opReturnData: serializeDataUpdate(operation.chainDomain.domainId, observedField.fieldId, value.format, value.value).opReturnData,
818
- mutation: createStandaloneFieldMutation({
819
- kind: "field-set",
820
- domainName: normalizedDomainName,
821
- fieldName: normalizedFieldName,
822
- sender: operation.sender,
823
- intentFingerprintHex,
824
- nowUnixMs: options.nowUnixMs ?? Date.now(),
825
- feeSelection,
826
- existing,
827
- fieldId: observedField.fieldId,
828
- fieldPermanent: observedField.permanent,
829
- fieldFormat: value.format,
830
- fieldValueHex: value.valueHex,
831
- }),
832
- };
833
- },
834
- async confirm(operation) {
835
- const normalizedDomainName = normalizeDomainName(options.domainName);
836
- const normalizedFieldName = normalizeFieldName(options.fieldName);
837
- const observedField = getObservedFieldState(operation.readContext, normalizedDomainName, normalizedFieldName);
838
- if (observedField === null) {
839
- throw new Error("wallet_field_set_field_not_found");
840
- }
841
- await confirmFieldSet(options.prompter, {
842
- domainName: normalizedDomainName,
843
- fieldName: normalizedFieldName,
844
- fieldPermanent: observedField.permanent,
845
- isFirstPermanentWrite: observedField.permanent && !observedField.hasValue,
846
- value,
847
- sender: createResolvedFieldSenderSummary(operation.sender, operation.senderSelector),
848
- assumeYes: options.assumeYes,
849
- });
850
- },
851
- });
852
- }
853
- export async function clearField(options) {
854
- return submitStandaloneFieldMutation({
855
- kind: "field-clear",
856
- errorPrefix: "wallet_field_clear",
857
- domainName: options.domainName,
858
- fieldName: options.fieldName,
859
- dataDir: options.dataDir,
860
- databasePath: options.databasePath,
861
- provider: options.provider,
862
- prompter: options.prompter,
863
- assumeYes: options.assumeYes,
864
- nowUnixMs: options.nowUnixMs,
865
- paths: options.paths,
866
- openReadContext: options.openReadContext,
867
- attachService: options.attachService,
868
- rpcFactory: options.rpcFactory,
869
- async createMutation(operation, existing, feeSelection) {
870
- const normalizedDomainName = normalizeDomainName(options.domainName);
871
- const normalizedFieldName = normalizeFieldName(options.fieldName);
872
- const observedField = getObservedFieldState(operation.readContext, normalizedDomainName, normalizedFieldName);
873
- if (observedField === null) {
874
- throw new Error("wallet_field_clear_field_not_found");
875
- }
876
- if (observedField.permanent && !observedField.hasValue) {
877
- throw new Error("wallet_field_clear_noop_permanent_clear");
878
- }
879
- const intentFingerprintHex = createIntentFingerprint([
880
- "field-clear",
881
- operation.state.walletRootId,
882
- normalizedDomainName,
883
- observedField.fieldId,
884
- ]);
885
- return {
886
- opReturnData: serializeDataUpdate(operation.chainDomain.domainId, observedField.fieldId, FIELD_FORMAT_BYTES.clear).opReturnData,
887
- mutation: createStandaloneFieldMutation({
888
- kind: "field-clear",
889
- domainName: normalizedDomainName,
890
- fieldName: normalizedFieldName,
891
- sender: operation.sender,
892
- intentFingerprintHex,
893
- nowUnixMs: options.nowUnixMs ?? Date.now(),
894
- feeSelection,
895
- existing,
896
- fieldId: observedField.fieldId,
897
- fieldPermanent: observedField.permanent,
898
- fieldFormat: FIELD_FORMAT_BYTES.clear,
899
- fieldValueHex: "",
900
- }),
901
- };
902
- },
903
- async confirm(operation) {
904
- const normalizedDomainName = normalizeDomainName(options.domainName);
905
- const normalizedFieldName = normalizeFieldName(options.fieldName);
906
- const observedField = getObservedFieldState(operation.readContext, normalizedDomainName, normalizedFieldName);
907
- if (observedField === null) {
908
- throw new Error("wallet_field_clear_field_not_found");
909
- }
910
- if (observedField.permanent && !observedField.hasValue) {
911
- throw new Error("wallet_field_clear_noop_permanent_clear");
912
- }
913
- options.prompter.writeLine(`Clearing field "${normalizedDomainName}:${normalizedFieldName}".`);
914
- options.prompter.writeLine(`Resolved sender: ${operation.senderSelector} (${operation.sender.address})`);
915
- options.prompter.writeLine("Path: standalone-data-clear");
916
- options.prompter.writeLine(`Effect: ${describeFieldEffect({ kind: "clear-field-value", burnCogtoshi: "0" })}.`);
917
- options.prompter.writeLine("This publishes a standalone DATA_UPDATE clear.");
918
- },
919
- });
920
- }
1
+ export * from "./field/index.js";