@cogcoin/client 1.1.8 → 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 (266) hide show
  1. package/README.md +1 -1
  2. package/dist/cli/commands/mining-read.js +1 -1
  3. package/dist/cli/commands/wallet-mutation/anchor.d.ts +2 -0
  4. package/dist/cli/commands/wallet-mutation/anchor.js +33 -0
  5. package/dist/cli/commands/wallet-mutation/bitcoin-transfer.d.ts +2 -0
  6. package/dist/cli/commands/wallet-mutation/bitcoin-transfer.js +32 -0
  7. package/dist/cli/commands/wallet-mutation/cog.d.ts +2 -0
  8. package/dist/cli/commands/wallet-mutation/cog.js +131 -0
  9. package/dist/cli/commands/wallet-mutation/context.d.ts +3 -0
  10. package/dist/cli/commands/wallet-mutation/context.js +18 -0
  11. package/dist/cli/commands/wallet-mutation/domain-admin.d.ts +2 -0
  12. package/dist/cli/commands/wallet-mutation/domain-admin.js +173 -0
  13. package/dist/cli/commands/wallet-mutation/domain-market.d.ts +2 -0
  14. package/dist/cli/commands/wallet-mutation/domain-market.js +107 -0
  15. package/dist/cli/commands/wallet-mutation/field.d.ts +2 -0
  16. package/dist/cli/commands/wallet-mutation/field.js +125 -0
  17. package/dist/cli/commands/wallet-mutation/register.d.ts +2 -0
  18. package/dist/cli/commands/wallet-mutation/register.js +38 -0
  19. package/dist/cli/commands/wallet-mutation/registry.d.ts +3 -0
  20. package/dist/cli/commands/wallet-mutation/registry.js +39 -0
  21. package/dist/cli/commands/wallet-mutation/reputation.d.ts +2 -0
  22. package/dist/cli/commands/wallet-mutation/reputation.js +57 -0
  23. package/dist/cli/commands/wallet-mutation/types.d.ts +32 -0
  24. package/dist/cli/commands/wallet-mutation/types.js +1 -0
  25. package/dist/cli/commands/wallet-mutation.js +13 -765
  26. package/dist/cli/commands/wallet-read.js +4 -4
  27. package/dist/cli/mutation-success.d.ts +0 -2
  28. package/dist/cli/output/classify.d.ts +7 -0
  29. package/dist/cli/output/classify.js +94 -0
  30. package/dist/cli/output/render.d.ts +2 -0
  31. package/dist/cli/output/render.js +13 -0
  32. package/dist/cli/output/rules/cli-surface.d.ts +2 -0
  33. package/dist/cli/output/rules/cli-surface.js +110 -0
  34. package/dist/cli/output/rules/generic.d.ts +2 -0
  35. package/dist/cli/output/rules/generic.js +13 -0
  36. package/dist/cli/output/rules/index.d.ts +2 -0
  37. package/dist/cli/output/rules/index.js +24 -0
  38. package/dist/cli/output/rules/mining-update.d.ts +2 -0
  39. package/dist/cli/output/rules/mining-update.js +68 -0
  40. package/dist/cli/output/rules/services.d.ts +2 -0
  41. package/dist/cli/output/rules/services.js +110 -0
  42. package/dist/cli/output/rules/wallet-admin.d.ts +2 -0
  43. package/dist/cli/output/rules/wallet-admin.js +224 -0
  44. package/dist/cli/output/rules/wallet-mutations.d.ts +2 -0
  45. package/dist/cli/output/rules/wallet-mutations.js +274 -0
  46. package/dist/cli/output/types.d.ts +16 -0
  47. package/dist/cli/output/types.js +1 -0
  48. package/dist/cli/output.d.ts +2 -168
  49. package/dist/cli/output.js +6 -989
  50. package/dist/cli/pagination.d.ts +15 -0
  51. package/dist/cli/pagination.js +16 -0
  52. package/dist/cli/recommendations.d.ts +4 -0
  53. package/dist/cli/recommendations.js +108 -0
  54. package/dist/cli/wallet-format/availability.d.ts +5 -0
  55. package/dist/cli/wallet-format/availability.js +96 -0
  56. package/dist/cli/wallet-format/balance.d.ts +2 -0
  57. package/dist/cli/wallet-format/balance.js +162 -0
  58. package/dist/cli/wallet-format/domains.d.ts +8 -0
  59. package/dist/cli/wallet-format/domains.js +84 -0
  60. package/dist/cli/wallet-format/fields.d.ts +6 -0
  61. package/dist/cli/wallet-format/fields.js +61 -0
  62. package/dist/cli/wallet-format/identity.d.ts +5 -0
  63. package/dist/cli/wallet-format/identity.js +19 -0
  64. package/dist/cli/wallet-format/locks.d.ts +7 -0
  65. package/dist/cli/wallet-format/locks.js +52 -0
  66. package/dist/cli/wallet-format/overview.d.ts +2 -0
  67. package/dist/cli/wallet-format/overview.js +122 -0
  68. package/dist/cli/wallet-format/pending.d.ts +13 -0
  69. package/dist/cli/wallet-format/pending.js +101 -0
  70. package/dist/cli/wallet-format/shared.d.ts +7 -0
  71. package/dist/cli/wallet-format/shared.js +31 -0
  72. package/dist/cli/wallet-format/status.d.ts +3 -0
  73. package/dist/cli/wallet-format/status.js +27 -0
  74. package/dist/cli/wallet-format.d.ts +8 -30
  75. package/dist/cli/wallet-format.js +8 -830
  76. package/dist/cli/wallet-read-helpers.d.ts +6 -0
  77. package/dist/cli/wallet-read-helpers.js +17 -0
  78. package/dist/wallet/mining/candidate.d.ts +1 -1
  79. package/dist/wallet/mining/candidate.js +3 -3
  80. package/dist/wallet/mining/constants.d.ts +2 -2
  81. package/dist/wallet/mining/constants.js +2 -2
  82. package/dist/wallet/mining/sentence-protocol.d.ts +2 -2
  83. package/dist/wallet/mining/sentences.js +8 -8
  84. package/dist/wallet/tx/anchor/confirm.d.ts +15 -0
  85. package/dist/wallet/tx/anchor/confirm.js +60 -0
  86. package/dist/wallet/tx/anchor/draft.d.ts +39 -0
  87. package/dist/wallet/tx/anchor/draft.js +167 -0
  88. package/dist/wallet/tx/anchor/index.d.ts +5 -0
  89. package/dist/wallet/tx/anchor/index.js +148 -0
  90. package/dist/wallet/tx/anchor/intent.d.ts +61 -0
  91. package/dist/wallet/tx/anchor/intent.js +101 -0
  92. package/dist/wallet/tx/anchor/plan.d.ts +3 -0
  93. package/dist/wallet/tx/anchor/plan.js +18 -0
  94. package/dist/wallet/tx/anchor/result.d.ts +25 -0
  95. package/dist/wallet/tx/anchor/result.js +20 -0
  96. package/dist/wallet/tx/anchor.d.ts +1 -39
  97. package/dist/wallet/tx/anchor.js +1 -494
  98. package/dist/wallet/tx/bitcoin-transfer/confirm.d.ts +7 -0
  99. package/dist/wallet/tx/bitcoin-transfer/confirm.js +11 -0
  100. package/dist/wallet/tx/bitcoin-transfer/index.d.ts +5 -0
  101. package/dist/wallet/tx/bitcoin-transfer/index.js +112 -0
  102. package/dist/wallet/tx/bitcoin-transfer/intent.d.ts +52 -0
  103. package/dist/wallet/tx/bitcoin-transfer/intent.js +74 -0
  104. package/dist/wallet/tx/bitcoin-transfer/plan.d.ts +5 -0
  105. package/dist/wallet/tx/bitcoin-transfer/plan.js +21 -0
  106. package/dist/wallet/tx/bitcoin-transfer/result.d.ts +19 -0
  107. package/dist/wallet/tx/bitcoin-transfer/result.js +16 -0
  108. package/dist/wallet/tx/bitcoin-transfer.d.ts +1 -35
  109. package/dist/wallet/tx/bitcoin-transfer.js +1 -200
  110. package/dist/wallet/tx/cog/confirm.d.ts +13 -0
  111. package/dist/wallet/tx/cog/confirm.js +59 -0
  112. package/dist/wallet/tx/cog/draft.d.ts +20 -0
  113. package/dist/wallet/tx/cog/draft.js +114 -0
  114. package/dist/wallet/tx/cog/index.d.ts +6 -0
  115. package/dist/wallet/tx/cog/index.js +117 -0
  116. package/dist/wallet/tx/cog/intent.d.ts +30 -0
  117. package/dist/wallet/tx/cog/intent.js +169 -0
  118. package/dist/wallet/tx/cog/plan.d.ts +19 -0
  119. package/dist/wallet/tx/cog/plan.js +65 -0
  120. package/dist/wallet/tx/cog/result.d.ts +27 -0
  121. package/dist/wallet/tx/cog/result.js +28 -0
  122. package/dist/wallet/tx/cog/types.d.ts +186 -0
  123. package/dist/wallet/tx/cog/types.js +2 -0
  124. package/dist/wallet/tx/cog/variants/claim.d.ts +3 -0
  125. package/dist/wallet/tx/cog/variants/claim.js +92 -0
  126. package/dist/wallet/tx/cog/variants/lock.d.ts +2 -0
  127. package/dist/wallet/tx/cog/variants/lock.js +102 -0
  128. package/dist/wallet/tx/cog/variants/send.d.ts +2 -0
  129. package/dist/wallet/tx/cog/variants/send.js +77 -0
  130. package/dist/wallet/tx/cog.d.ts +1 -96
  131. package/dist/wallet/tx/cog.js +1 -824
  132. package/dist/wallet/tx/common.d.ts +14 -199
  133. package/dist/wallet/tx/common.js +10 -493
  134. package/dist/wallet/tx/domain-admin/confirm.d.ts +17 -0
  135. package/dist/wallet/tx/domain-admin/confirm.js +58 -0
  136. package/dist/wallet/tx/domain-admin/draft.d.ts +20 -0
  137. package/dist/wallet/tx/domain-admin/draft.js +161 -0
  138. package/dist/wallet/tx/domain-admin/index.d.ts +9 -0
  139. package/dist/wallet/tx/domain-admin/index.js +150 -0
  140. package/dist/wallet/tx/domain-admin/intent.d.ts +12 -0
  141. package/dist/wallet/tx/domain-admin/intent.js +61 -0
  142. package/dist/wallet/tx/domain-admin/plan.d.ts +19 -0
  143. package/dist/wallet/tx/domain-admin/plan.js +64 -0
  144. package/dist/wallet/tx/domain-admin/result.d.ts +19 -0
  145. package/dist/wallet/tx/domain-admin/result.js +33 -0
  146. package/dist/wallet/tx/domain-admin/types.d.ts +162 -0
  147. package/dist/wallet/tx/domain-admin/types.js +1 -0
  148. package/dist/wallet/tx/domain-admin/variants/canonical.d.ts +2 -0
  149. package/dist/wallet/tx/domain-admin/variants/canonical.js +22 -0
  150. package/dist/wallet/tx/domain-admin/variants/delegate.d.ts +3 -0
  151. package/dist/wallet/tx/domain-admin/variants/delegate.js +60 -0
  152. package/dist/wallet/tx/domain-admin/variants/endpoint.d.ts +3 -0
  153. package/dist/wallet/tx/domain-admin/variants/endpoint.js +102 -0
  154. package/dist/wallet/tx/domain-admin/variants/miner.d.ts +3 -0
  155. package/dist/wallet/tx/domain-admin/variants/miner.js +59 -0
  156. package/dist/wallet/tx/domain-admin.d.ts +1 -107
  157. package/dist/wallet/tx/domain-admin.js +1 -729
  158. package/dist/wallet/tx/domain-market/confirm.d.ts +6 -0
  159. package/dist/wallet/tx/domain-market/confirm.js +52 -0
  160. package/dist/wallet/tx/domain-market/draft.d.ts +43 -0
  161. package/dist/wallet/tx/domain-market/draft.js +286 -0
  162. package/dist/wallet/tx/domain-market/index.d.ts +6 -0
  163. package/dist/wallet/tx/domain-market/index.js +145 -0
  164. package/dist/wallet/tx/domain-market/intent.d.ts +15 -0
  165. package/dist/wallet/tx/domain-market/intent.js +131 -0
  166. package/dist/wallet/tx/domain-market/plan.d.ts +31 -0
  167. package/dist/wallet/tx/domain-market/plan.js +98 -0
  168. package/dist/wallet/tx/domain-market/result.d.ts +45 -0
  169. package/dist/wallet/tx/domain-market/result.js +88 -0
  170. package/dist/wallet/tx/domain-market/types.d.ts +221 -0
  171. package/dist/wallet/tx/domain-market/types.js +1 -0
  172. package/dist/wallet/tx/domain-market/variants/buy.d.ts +2 -0
  173. package/dist/wallet/tx/domain-market/variants/buy.js +103 -0
  174. package/dist/wallet/tx/domain-market/variants/sell.d.ts +2 -0
  175. package/dist/wallet/tx/domain-market/variants/sell.js +91 -0
  176. package/dist/wallet/tx/domain-market/variants/transfer.d.ts +2 -0
  177. package/dist/wallet/tx/domain-market/variants/transfer.js +105 -0
  178. package/dist/wallet/tx/domain-market.d.ts +1 -116
  179. package/dist/wallet/tx/domain-market.js +1 -1078
  180. package/dist/wallet/tx/draft-build.d.ts +60 -0
  181. package/dist/wallet/tx/draft-build.js +127 -0
  182. package/dist/wallet/tx/executor.d.ts +6 -40
  183. package/dist/wallet/tx/executor.js +6 -100
  184. package/dist/wallet/tx/fee.d.ts +30 -0
  185. package/dist/wallet/tx/fee.js +98 -0
  186. package/dist/wallet/tx/field/confirm.d.ts +11 -0
  187. package/dist/wallet/tx/field/confirm.js +19 -0
  188. package/dist/wallet/tx/field/draft.d.ts +23 -0
  189. package/dist/wallet/tx/field/draft.js +202 -0
  190. package/dist/wallet/tx/field/index.d.ts +5 -0
  191. package/dist/wallet/tx/field/index.js +140 -0
  192. package/dist/wallet/tx/field/intent.d.ts +5 -0
  193. package/dist/wallet/tx/field/intent.js +50 -0
  194. package/dist/wallet/tx/field/plan.d.ts +20 -0
  195. package/dist/wallet/tx/field/plan.js +65 -0
  196. package/dist/wallet/tx/field/result.d.ts +29 -0
  197. package/dist/wallet/tx/field/result.js +103 -0
  198. package/dist/wallet/tx/field/types.d.ts +163 -0
  199. package/dist/wallet/tx/field/types.js +1 -0
  200. package/dist/wallet/tx/field/variants/clear.d.ts +2 -0
  201. package/dist/wallet/tx/field/variants/clear.js +60 -0
  202. package/dist/wallet/tx/field/variants/create.d.ts +2 -0
  203. package/dist/wallet/tx/field/variants/create.js +67 -0
  204. package/dist/wallet/tx/field/variants/set.d.ts +2 -0
  205. package/dist/wallet/tx/field/variants/set.js +195 -0
  206. package/dist/wallet/tx/field.d.ts +1 -95
  207. package/dist/wallet/tx/field.js +1 -920
  208. package/dist/wallet/tx/mining-preemption.d.ts +6 -0
  209. package/dist/wallet/tx/mining-preemption.js +7 -0
  210. package/dist/wallet/tx/primitives.d.ts +13 -0
  211. package/dist/wallet/tx/primitives.js +42 -0
  212. package/dist/wallet/tx/psbt-assert.d.ts +14 -0
  213. package/dist/wallet/tx/psbt-assert.js +39 -0
  214. package/dist/wallet/tx/publish.d.ts +37 -0
  215. package/dist/wallet/tx/publish.js +88 -0
  216. package/dist/wallet/tx/readiness.d.ts +7 -0
  217. package/dist/wallet/tx/readiness.js +61 -0
  218. package/dist/wallet/tx/reconcile.d.ts +24 -0
  219. package/dist/wallet/tx/reconcile.js +72 -0
  220. package/dist/wallet/tx/register/confirm.d.ts +6 -0
  221. package/dist/wallet/tx/register/confirm.js +66 -0
  222. package/dist/wallet/tx/register/draft.d.ts +42 -0
  223. package/dist/wallet/tx/register/draft.js +181 -0
  224. package/dist/wallet/tx/register/index.d.ts +6 -0
  225. package/dist/wallet/tx/register/index.js +158 -0
  226. package/dist/wallet/tx/register/intent.d.ts +74 -0
  227. package/dist/wallet/tx/register/intent.js +119 -0
  228. package/dist/wallet/tx/register/plan.d.ts +43 -0
  229. package/dist/wallet/tx/register/plan.js +168 -0
  230. package/dist/wallet/tx/register/result.d.ts +78 -0
  231. package/dist/wallet/tx/register/result.js +41 -0
  232. package/dist/wallet/tx/register.d.ts +1 -70
  233. package/dist/wallet/tx/register.js +1 -681
  234. package/dist/wallet/tx/reputation/confirm.d.ts +11 -0
  235. package/dist/wallet/tx/reputation/confirm.js +51 -0
  236. package/dist/wallet/tx/reputation/draft.d.ts +20 -0
  237. package/dist/wallet/tx/reputation/draft.js +130 -0
  238. package/dist/wallet/tx/reputation/index.d.ts +4 -0
  239. package/dist/wallet/tx/reputation/index.js +162 -0
  240. package/dist/wallet/tx/reputation/intent.d.ts +36 -0
  241. package/dist/wallet/tx/reputation/intent.js +157 -0
  242. package/dist/wallet/tx/reputation/plan.d.ts +19 -0
  243. package/dist/wallet/tx/reputation/plan.js +64 -0
  244. package/dist/wallet/tx/reputation/result.d.ts +21 -0
  245. package/dist/wallet/tx/reputation/result.js +31 -0
  246. package/dist/wallet/tx/reputation/types.d.ts +130 -0
  247. package/dist/wallet/tx/reputation/types.js +1 -0
  248. package/dist/wallet/tx/reputation.d.ts +1 -74
  249. package/dist/wallet/tx/reputation.js +1 -556
  250. package/dist/wallet/tx/signing.d.ts +18 -0
  251. package/dist/wallet/tx/signing.js +31 -0
  252. package/dist/wallet/tx/state-persist.d.ts +27 -0
  253. package/dist/wallet/tx/state-persist.js +54 -0
  254. package/dist/wallet/tx/types.d.ts +44 -0
  255. package/dist/wallet/tx/types.js +1 -0
  256. package/package.json +1 -1
  257. package/dist/cli/mining-json.d.ts +0 -20
  258. package/dist/cli/mining-json.js +0 -46
  259. package/dist/cli/mutation-json.d.ts +0 -325
  260. package/dist/cli/mutation-json.js +0 -269
  261. package/dist/cli/mutation-resolved-json.d.ts +0 -117
  262. package/dist/cli/mutation-resolved-json.js +0 -123
  263. package/dist/cli/preview-json.d.ts +0 -319
  264. package/dist/cli/preview-json.js +0 -254
  265. package/dist/cli/read-json.d.ts +0 -190
  266. package/dist/cli/read-json.js +0 -627
@@ -0,0 +1,202 @@
1
+ import { randomBytes } from "node:crypto";
2
+ import { lookupDomain } from "@cogcoin/indexer/queries";
3
+ import { findDomainField } from "../../read/index.js";
4
+ import { createWalletMutationFeeMetadata, unlockTemporaryBuilderLocks, updateMutationRecord, } from "../common.js";
5
+ import { persistWalletMutationState } from "../executor.js";
6
+ import { upsertPendingMutation } from "../journal.js";
7
+ export function createStandaloneFieldMutation(options) {
8
+ if (options.existing !== null && options.existing !== undefined) {
9
+ return {
10
+ ...options.existing,
11
+ kind: options.kind,
12
+ domainName: options.domainName,
13
+ senderScriptPubKeyHex: options.sender.scriptPubKeyHex,
14
+ senderLocalIndex: options.sender.localIndex,
15
+ fieldName: options.fieldName,
16
+ fieldId: options.fieldId ?? null,
17
+ fieldPermanent: options.fieldPermanent ?? null,
18
+ fieldFormat: options.fieldFormat ?? null,
19
+ fieldValueHex: options.fieldValueHex ?? null,
20
+ status: "draft",
21
+ lastUpdatedAtUnixMs: options.nowUnixMs,
22
+ attemptedTxid: null,
23
+ attemptedWtxid: null,
24
+ ...createWalletMutationFeeMetadata(options.feeSelection),
25
+ temporaryBuilderLockedOutpoints: [],
26
+ };
27
+ }
28
+ return {
29
+ mutationId: randomBytes(12).toString("hex"),
30
+ kind: options.kind,
31
+ domainName: options.domainName,
32
+ parentDomainName: null,
33
+ senderScriptPubKeyHex: options.sender.scriptPubKeyHex,
34
+ senderLocalIndex: options.sender.localIndex,
35
+ fieldName: options.fieldName,
36
+ fieldId: options.fieldId ?? null,
37
+ fieldPermanent: options.fieldPermanent ?? null,
38
+ fieldFormat: options.fieldFormat ?? null,
39
+ fieldValueHex: options.fieldValueHex ?? null,
40
+ intentFingerprintHex: options.intentFingerprintHex,
41
+ status: "draft",
42
+ createdAtUnixMs: options.nowUnixMs,
43
+ lastUpdatedAtUnixMs: options.nowUnixMs,
44
+ attemptedTxid: null,
45
+ attemptedWtxid: null,
46
+ ...createWalletMutationFeeMetadata(options.feeSelection),
47
+ temporaryBuilderLockedOutpoints: [],
48
+ };
49
+ }
50
+ function isActiveMutationStatus(status) {
51
+ return status === "draft"
52
+ || status === "broadcasting"
53
+ || status === "broadcast-unknown"
54
+ || status === "live"
55
+ || status === "repair-required";
56
+ }
57
+ export function findActiveFieldCreateMutationByDomain(state, domainName, intentFingerprintHex) {
58
+ return (state.pendingMutations ?? []).find((mutation) => mutation.kind === "field-create"
59
+ && mutation.domainName === domainName
60
+ && mutation.intentFingerprintHex !== intentFingerprintHex
61
+ && isActiveMutationStatus(mutation.status)) ?? null;
62
+ }
63
+ export function getObservedFieldState(context, domainName, fieldName) {
64
+ if (context.snapshot === null) {
65
+ return null;
66
+ }
67
+ return findDomainField(context, domainName, fieldName);
68
+ }
69
+ function standaloneMutationConfirmedOnChain(mutation, context) {
70
+ const observed = mutation.fieldName == null
71
+ ? null
72
+ : getObservedFieldState(context, mutation.domainName, mutation.fieldName);
73
+ const chainDomain = context.snapshot === null ? null : lookupDomain(context.snapshot.state, mutation.domainName);
74
+ if (chainDomain === null || !chainDomain.anchored) {
75
+ return false;
76
+ }
77
+ const ownerHex = Buffer.from(chainDomain.ownerScriptPubKey).toString("hex");
78
+ if (ownerHex !== mutation.senderScriptPubKeyHex) {
79
+ return false;
80
+ }
81
+ if (mutation.kind === "field-create") {
82
+ return observed !== null
83
+ && (mutation.fieldPermanent == null || observed.permanent === mutation.fieldPermanent);
84
+ }
85
+ if (mutation.kind === "field-clear") {
86
+ return observed !== null && !observed.hasValue;
87
+ }
88
+ return observed !== null
89
+ && observed.hasValue
90
+ && observed.format === (mutation.fieldFormat ?? null)
91
+ && observed.rawValueHex === (mutation.fieldValueHex ?? null);
92
+ }
93
+ function standaloneMutationNeedsRepair(mutation, context) {
94
+ if (context.snapshot === null) {
95
+ return false;
96
+ }
97
+ const chainDomain = lookupDomain(context.snapshot.state, mutation.domainName);
98
+ if (chainDomain === null || !chainDomain.anchored) {
99
+ return true;
100
+ }
101
+ const ownerHex = Buffer.from(chainDomain.ownerScriptPubKey).toString("hex");
102
+ if (ownerHex !== mutation.senderScriptPubKeyHex) {
103
+ return true;
104
+ }
105
+ if (mutation.fieldName == null) {
106
+ return false;
107
+ }
108
+ const observed = getObservedFieldState(context, mutation.domainName, mutation.fieldName);
109
+ if (mutation.kind === "field-create") {
110
+ return observed !== null
111
+ && mutation.fieldPermanent !== null
112
+ && observed.permanent !== mutation.fieldPermanent;
113
+ }
114
+ if (mutation.kind === "field-set") {
115
+ return observed !== null
116
+ && observed.hasValue
117
+ && ((mutation.fieldFormat ?? null) !== observed.format || (mutation.fieldValueHex ?? null) !== observed.rawValueHex);
118
+ }
119
+ return false;
120
+ }
121
+ export async function reconcilePendingFieldMutation(options) {
122
+ if (options.mutation.status === "confirmed" || options.mutation.status === "live") {
123
+ return {
124
+ state: options.state,
125
+ mutation: options.mutation,
126
+ resolution: options.mutation.status,
127
+ };
128
+ }
129
+ if (options.mutation.status === "repair-required") {
130
+ return {
131
+ state: options.state,
132
+ mutation: options.mutation,
133
+ resolution: "repair-required",
134
+ };
135
+ }
136
+ if (standaloneMutationConfirmedOnChain(options.mutation, options.context)) {
137
+ await unlockTemporaryBuilderLocks(options.rpc, options.walletName, options.mutation.temporaryBuilderLockedOutpoints);
138
+ const confirmed = updateMutationRecord(options.mutation, "confirmed", options.nowUnixMs, {
139
+ temporaryBuilderLockedOutpoints: [],
140
+ });
141
+ let nextState = upsertPendingMutation(options.state, confirmed);
142
+ nextState = await persistWalletMutationState({
143
+ state: nextState,
144
+ provider: options.provider,
145
+ nowUnixMs: options.nowUnixMs,
146
+ paths: options.paths,
147
+ });
148
+ return { state: nextState, mutation: confirmed, resolution: "confirmed" };
149
+ }
150
+ if (standaloneMutationNeedsRepair(options.mutation, options.context)) {
151
+ await unlockTemporaryBuilderLocks(options.rpc, options.walletName, options.mutation.temporaryBuilderLockedOutpoints);
152
+ const repair = updateMutationRecord(options.mutation, "repair-required", options.nowUnixMs, {
153
+ temporaryBuilderLockedOutpoints: [],
154
+ });
155
+ let nextState = upsertPendingMutation(options.state, repair);
156
+ nextState = await persistWalletMutationState({
157
+ state: nextState,
158
+ provider: options.provider,
159
+ nowUnixMs: options.nowUnixMs,
160
+ paths: options.paths,
161
+ });
162
+ return { state: nextState, mutation: repair, resolution: "repair-required" };
163
+ }
164
+ const known = options.mutation.attemptedTxid === null
165
+ ? false
166
+ : await options.rpc.getRawTransaction(options.mutation.attemptedTxid, true).then(() => true).catch(() => false);
167
+ if (known) {
168
+ await unlockTemporaryBuilderLocks(options.rpc, options.walletName, options.mutation.temporaryBuilderLockedOutpoints);
169
+ const live = updateMutationRecord(options.mutation, "live", options.nowUnixMs, {
170
+ temporaryBuilderLockedOutpoints: [],
171
+ });
172
+ let nextState = upsertPendingMutation(options.state, live);
173
+ nextState = await persistWalletMutationState({
174
+ state: nextState,
175
+ provider: options.provider,
176
+ nowUnixMs: options.nowUnixMs,
177
+ paths: options.paths,
178
+ });
179
+ return { state: nextState, mutation: live, resolution: "live" };
180
+ }
181
+ if (options.mutation.status === "broadcast-unknown"
182
+ || options.mutation.status === "draft"
183
+ || options.mutation.status === "broadcasting") {
184
+ await unlockTemporaryBuilderLocks(options.rpc, options.walletName, options.mutation.temporaryBuilderLockedOutpoints);
185
+ const canceled = updateMutationRecord(options.mutation, "canceled", options.nowUnixMs, {
186
+ temporaryBuilderLockedOutpoints: [],
187
+ });
188
+ let nextState = upsertPendingMutation(options.state, canceled);
189
+ nextState = await persistWalletMutationState({
190
+ state: nextState,
191
+ provider: options.provider,
192
+ nowUnixMs: options.nowUnixMs,
193
+ paths: options.paths,
194
+ });
195
+ return { state: nextState, mutation: canceled, resolution: "not-seen" };
196
+ }
197
+ return {
198
+ state: options.state,
199
+ mutation: options.mutation,
200
+ resolution: "continue",
201
+ };
202
+ }
@@ -0,0 +1,5 @@
1
+ import type { ClearFieldOptions, CreateFieldOptions, FieldMutationResult, SetFieldOptions } from "./types.js";
2
+ export type { ClearFieldOptions, CreateFieldOptions, FieldMutationResult, FieldResolvedEffect, FieldResolvedPath, FieldResolvedSenderSummary, FieldResolvedSummary, FieldResolvedValueSummary, FieldValueInputSource, SetFieldOptions, } from "./types.js";
3
+ export declare function createField(options: CreateFieldOptions): Promise<FieldMutationResult>;
4
+ export declare function setField(options: SetFieldOptions): Promise<FieldMutationResult>;
5
+ export declare function clearField(options: ClearFieldOptions): Promise<FieldMutationResult>;
@@ -0,0 +1,140 @@
1
+ import { mergeFixedWalletInputs, } from "../common.js";
2
+ import { executeWalletMutationOperation, publishWalletMutation, resolveExistingWalletMutation, } from "../executor.js";
3
+ import { getObservedFieldState, reconcilePendingFieldMutation, } from "./draft.js";
4
+ import { createFieldIntentFingerprint, normalizeFieldDomainName, normalizeFieldNameInput, resolveAnchoredFieldOperation, } from "./intent.js";
5
+ import { buildAnchoredFieldPlan, buildFieldTransaction, } from "./plan.js";
6
+ import { createFieldResult, createFieldReuseResult, } from "./result.js";
7
+ import { createClearFieldVariant } from "./variants/clear.js";
8
+ import { createFieldCreateVariant } from "./variants/create.js";
9
+ import { createSetFieldVariant } from "./variants/set.js";
10
+ async function submitStandaloneFieldMutation(options, variant) {
11
+ if (!options.prompter.isInteractive && options.assumeYes !== true) {
12
+ throw new Error(`${variant.errorPrefix}_requires_tty`);
13
+ }
14
+ const execution = await executeWalletMutationOperation({
15
+ ...options,
16
+ controlLockPurpose: variant.errorPrefix,
17
+ preemptionReason: variant.errorPrefix,
18
+ resolveOperation(readContext) {
19
+ const normalizedDomainName = normalizeFieldDomainName(options.domainName);
20
+ const normalizedFieldName = normalizeFieldNameInput(options.fieldName);
21
+ const operation = resolveAnchoredFieldOperation(readContext, normalizedDomainName, variant.errorPrefix);
22
+ return {
23
+ ...operation,
24
+ normalizedDomainName,
25
+ normalizedFieldName,
26
+ existingObservedField: getObservedFieldState(readContext, normalizedDomainName, normalizedFieldName),
27
+ };
28
+ },
29
+ createIntentFingerprint(operation) {
30
+ return createFieldIntentFingerprint([
31
+ variant.kind,
32
+ operation.state.walletRootId,
33
+ operation.normalizedDomainName,
34
+ operation.normalizedFieldName,
35
+ ]);
36
+ },
37
+ async resolveExistingMutation({ operation, existingMutation, execution }) {
38
+ if (existingMutation === null) {
39
+ return {
40
+ state: operation.state,
41
+ replacementFixedInputs: null,
42
+ result: null,
43
+ };
44
+ }
45
+ return resolveExistingWalletMutation({
46
+ existingMutation,
47
+ execution,
48
+ repairRequiredErrorCode: `${variant.errorPrefix}_repair_required`,
49
+ reconcileExistingMutation: (mutation) => reconcilePendingFieldMutation({
50
+ state: operation.state,
51
+ mutation,
52
+ provider: execution.provider,
53
+ nowUnixMs: execution.nowUnixMs,
54
+ paths: execution.paths,
55
+ rpc: execution.rpc,
56
+ walletName: execution.walletName,
57
+ context: execution.readContext,
58
+ }),
59
+ createReuseResult: ({ mutation, resolution, fees }) => createFieldReuseResult({
60
+ kind: variant.kind,
61
+ operation,
62
+ mutation,
63
+ resolution,
64
+ fees,
65
+ }),
66
+ });
67
+ },
68
+ confirm({ operation }) {
69
+ return variant.confirm(operation);
70
+ },
71
+ async createDraftMutation({ operation, existingMutation, execution }) {
72
+ const prepared = await variant.createMutation({
73
+ operation,
74
+ existing: existingMutation,
75
+ feeSelection: execution.feeSelection,
76
+ nowUnixMs: execution.nowUnixMs,
77
+ });
78
+ return {
79
+ mutation: prepared.mutation,
80
+ prepared: {
81
+ opReturnData: prepared.opReturnData,
82
+ },
83
+ };
84
+ },
85
+ async build({ operation, state, execution, replacementFixedInputs, prepared }) {
86
+ const fieldPlan = buildAnchoredFieldPlan({
87
+ state,
88
+ allUtxos: await execution.rpc.listUnspent(execution.walletName, 1),
89
+ sender: operation.sender,
90
+ opReturnData: prepared.opReturnData,
91
+ errorPrefix: variant.errorPrefix,
92
+ });
93
+ return buildFieldTransaction({
94
+ rpc: execution.rpc,
95
+ walletName: execution.walletName,
96
+ state,
97
+ plan: {
98
+ ...fieldPlan,
99
+ fixedInputs: mergeFixedWalletInputs(fieldPlan.fixedInputs, replacementFixedInputs),
100
+ },
101
+ feeRateSatVb: execution.feeSelection.feeRateSatVb,
102
+ });
103
+ },
104
+ publish({ state, execution, built, mutation }) {
105
+ return publishWalletMutation({
106
+ rpc: execution.rpc,
107
+ walletName: execution.walletName,
108
+ snapshotHeight: execution.readContext.snapshot?.tip?.height ?? null,
109
+ built,
110
+ mutation,
111
+ state,
112
+ provider: execution.provider,
113
+ nowUnixMs: execution.nowUnixMs,
114
+ paths: execution.paths,
115
+ errorPrefix: variant.errorPrefix,
116
+ });
117
+ },
118
+ createResult({ operation, mutation, built, status, reusedExisting, fees }) {
119
+ return createFieldResult({
120
+ kind: variant.kind,
121
+ operation,
122
+ mutation,
123
+ builtTxid: built?.txid ?? null,
124
+ status: status,
125
+ reusedExisting,
126
+ fees,
127
+ });
128
+ },
129
+ });
130
+ return execution.result;
131
+ }
132
+ export async function createField(options) {
133
+ return submitStandaloneFieldMutation(options, createFieldCreateVariant(options));
134
+ }
135
+ export async function setField(options) {
136
+ return submitStandaloneFieldMutation(options, await createSetFieldVariant(options));
137
+ }
138
+ export async function clearField(options) {
139
+ return submitStandaloneFieldMutation(options, createClearFieldVariant(options));
140
+ }
@@ -0,0 +1,5 @@
1
+ import type { FieldOperation, ReadyWalletReadContext } from "./types.js";
2
+ export declare function normalizeFieldDomainName(domainName: string): string;
3
+ export declare function normalizeFieldNameInput(fieldName: string): string;
4
+ export declare function createFieldIntentFingerprint(parts: Array<string | number | bigint>): string;
5
+ export declare function resolveAnchoredFieldOperation(context: ReadyWalletReadContext, domainName: string, errorPrefix: string): FieldOperation;
@@ -0,0 +1,50 @@
1
+ import { createHash } from "node:crypto";
2
+ import { lookupDomain } from "@cogcoin/indexer/queries";
3
+ import { validateFieldName } from "../../cogop/validate-name.js";
4
+ import { assertWalletMutationContextReady } from "../common.js";
5
+ export function normalizeFieldDomainName(domainName) {
6
+ const normalized = domainName.trim().toLowerCase();
7
+ if (normalized.length === 0) {
8
+ throw new Error("wallet_field_missing_domain");
9
+ }
10
+ return normalized;
11
+ }
12
+ export function normalizeFieldNameInput(fieldName) {
13
+ const normalized = fieldName.trim().toLowerCase();
14
+ if (normalized.length === 0) {
15
+ throw new Error("wallet_field_missing_field_name");
16
+ }
17
+ validateFieldName(normalized);
18
+ return normalized;
19
+ }
20
+ export function createFieldIntentFingerprint(parts) {
21
+ return createHash("sha256")
22
+ .update(parts.map((part) => String(part)).join("\n"))
23
+ .digest("hex");
24
+ }
25
+ export function resolveAnchoredFieldOperation(context, domainName, errorPrefix) {
26
+ assertWalletMutationContextReady(context, errorPrefix);
27
+ const chainDomain = lookupDomain(context.snapshot.state, domainName);
28
+ if (chainDomain === null) {
29
+ throw new Error(`${errorPrefix}_domain_not_found`);
30
+ }
31
+ if (!chainDomain.anchored) {
32
+ throw new Error(`${errorPrefix}_domain_not_anchored`);
33
+ }
34
+ const ownerHex = Buffer.from(chainDomain.ownerScriptPubKey).toString("hex");
35
+ const state = context.localState.state;
36
+ if (ownerHex !== state.funding.scriptPubKeyHex || state.funding.address.trim() === "") {
37
+ throw new Error(`${errorPrefix}_owner_not_locally_controlled`);
38
+ }
39
+ return {
40
+ readContext: context,
41
+ state,
42
+ sender: {
43
+ localIndex: 0,
44
+ scriptPubKeyHex: state.funding.scriptPubKeyHex,
45
+ address: state.funding.address,
46
+ },
47
+ senderSelector: state.funding.address,
48
+ chainDomain,
49
+ };
50
+ }
@@ -0,0 +1,20 @@
1
+ import type { RpcDecodedPsbt, RpcListUnspentEntry } from "../../../bitcoind/types.js";
2
+ import { type BuiltWalletMutationTransaction, type MutationSender } from "../common.js";
3
+ import type { FieldPlan, FieldRpcClient } from "./types.js";
4
+ import type { WalletStateV1 } from "../../types.js";
5
+ export declare function buildAnchoredFieldPlan(options: {
6
+ state: WalletStateV1;
7
+ allUtxos: RpcListUnspentEntry[];
8
+ sender: MutationSender;
9
+ opReturnData: Uint8Array;
10
+ errorPrefix: string;
11
+ }): FieldPlan;
12
+ export declare function validateFieldDraft(decoded: RpcDecodedPsbt, funded: BuiltWalletMutationTransaction["funded"], plan: FieldPlan): void;
13
+ export declare function buildFieldTransaction(options: {
14
+ rpc: FieldRpcClient;
15
+ walletName: string;
16
+ state: WalletStateV1;
17
+ plan: FieldPlan;
18
+ feeRateSatVb: number;
19
+ availableFundingMinConf?: number;
20
+ }): Promise<BuiltWalletMutationTransaction>;
@@ -0,0 +1,65 @@
1
+ import { buildWalletMutationTransactionWithReserveFallback, outpointKey, } from "../common.js";
2
+ function encodeOpReturnScript(payload) {
3
+ if (payload.length <= 75) {
4
+ return Buffer.concat([
5
+ Buffer.from([0x6a, payload.length]),
6
+ Buffer.from(payload),
7
+ ]).toString("hex");
8
+ }
9
+ return Buffer.concat([
10
+ Buffer.from([0x6a, 0x4c, payload.length]),
11
+ Buffer.from(payload),
12
+ ]).toString("hex");
13
+ }
14
+ export function buildAnchoredFieldPlan(options) {
15
+ const fundingUtxos = options.allUtxos.filter((entry) => entry.scriptPubKey === options.state.funding.scriptPubKeyHex
16
+ && entry.confirmations >= 1
17
+ && entry.spendable !== false
18
+ && entry.safe !== false);
19
+ return {
20
+ sender: options.sender,
21
+ changeAddress: options.state.funding.address,
22
+ fixedInputs: [],
23
+ outputs: [{ data: Buffer.from(options.opReturnData).toString("hex") }],
24
+ changePosition: 1,
25
+ expectedOpReturnScriptHex: encodeOpReturnScript(options.opReturnData),
26
+ allowedFundingScriptPubKeyHex: options.state.funding.scriptPubKeyHex,
27
+ eligibleFundingOutpointKeys: new Set(fundingUtxos.map((entry) => outpointKey({ txid: entry.txid, vout: entry.vout }))),
28
+ errorPrefix: options.errorPrefix,
29
+ };
30
+ }
31
+ export function validateFieldDraft(decoded, funded, plan) {
32
+ const inputs = decoded.tx.vin;
33
+ const outputs = decoded.tx.vout;
34
+ if (inputs.length === 0) {
35
+ throw new Error(`${plan.errorPrefix}_missing_sender_input`);
36
+ }
37
+ if (outputs[0]?.scriptPubKey?.hex !== plan.expectedOpReturnScriptHex) {
38
+ throw new Error(`${plan.errorPrefix}_opreturn_mismatch`);
39
+ }
40
+ if (funded.changepos === -1) {
41
+ if (outputs.length !== 1) {
42
+ throw new Error(`${plan.errorPrefix}_unexpected_output_count`);
43
+ }
44
+ return;
45
+ }
46
+ if (funded.changepos !== plan.changePosition || outputs.length !== 2) {
47
+ throw new Error(`${plan.errorPrefix}_change_position_mismatch`);
48
+ }
49
+ if (outputs[funded.changepos]?.scriptPubKey?.hex !== plan.allowedFundingScriptPubKeyHex) {
50
+ throw new Error(`${plan.errorPrefix}_change_output_mismatch`);
51
+ }
52
+ }
53
+ export async function buildFieldTransaction(options) {
54
+ return buildWalletMutationTransactionWithReserveFallback({
55
+ rpc: options.rpc,
56
+ walletName: options.walletName,
57
+ state: options.state,
58
+ plan: options.plan,
59
+ validateFundedDraft: validateFieldDraft,
60
+ finalizeErrorCode: `${options.plan.errorPrefix}_finalize_failed`,
61
+ mempoolRejectPrefix: `${options.plan.errorPrefix}_mempool_rejected`,
62
+ feeRate: options.feeRateSatVb,
63
+ availableFundingMinConf: options.availableFundingMinConf,
64
+ });
65
+ }
@@ -0,0 +1,29 @@
1
+ import type { PendingMutationRecord } from "../../types.js";
2
+ import type { FieldMutationKind, FieldMutationResult, FieldResolvedEffect, FieldResolvedSenderSummary, FieldResolvedSummary, FieldResolvedValueSummary, StandaloneFieldMutationOperation } from "./types.js";
3
+ import type { MutationSender, WalletMutationFeeSummary } from "../common.js";
4
+ export declare function createResolvedFieldSenderSummary(sender: MutationSender, selector: string): FieldResolvedSenderSummary;
5
+ export declare function createResolvedFieldValueSummary(format: number, value: Uint8Array | string): FieldResolvedValueSummary;
6
+ export declare function createResolvedFieldSummary(options: {
7
+ sender: MutationSender;
8
+ senderSelector: string;
9
+ kind: FieldMutationKind;
10
+ value: FieldResolvedValueSummary | null;
11
+ }): FieldResolvedSummary;
12
+ export declare function createResolvedFieldValueFromStoredData(kind: FieldMutationKind, format: number | null | undefined, valueHex: string | null | undefined): FieldResolvedValueSummary | null;
13
+ export declare function describeFieldEffect(effect: FieldResolvedEffect): string;
14
+ export declare function createFieldReuseResult(options: {
15
+ kind: FieldMutationKind;
16
+ operation: StandaloneFieldMutationOperation;
17
+ mutation: PendingMutationRecord;
18
+ resolution: "confirmed" | "live";
19
+ fees: WalletMutationFeeSummary;
20
+ }): FieldMutationResult;
21
+ export declare function createFieldResult(options: {
22
+ kind: FieldMutationKind;
23
+ operation: StandaloneFieldMutationOperation;
24
+ mutation: PendingMutationRecord;
25
+ builtTxid: string | null;
26
+ status: "live" | "confirmed";
27
+ reusedExisting: boolean;
28
+ fees: WalletMutationFeeSummary;
29
+ }): FieldMutationResult;
@@ -0,0 +1,103 @@
1
+ export function createResolvedFieldSenderSummary(sender, selector) {
2
+ return {
3
+ selector,
4
+ localIndex: sender.localIndex,
5
+ scriptPubKeyHex: sender.scriptPubKeyHex,
6
+ address: sender.address,
7
+ };
8
+ }
9
+ export function createResolvedFieldValueSummary(format, value) {
10
+ return {
11
+ format,
12
+ byteLength: typeof value === "string" ? value.length / 2 : value.length,
13
+ };
14
+ }
15
+ export function createResolvedFieldSummary(options) {
16
+ if (options.kind === "field-create") {
17
+ return {
18
+ sender: createResolvedFieldSenderSummary(options.sender, options.senderSelector),
19
+ path: "standalone-field-reg",
20
+ value: null,
21
+ effect: {
22
+ kind: "create-empty-field",
23
+ burnCogtoshi: "100",
24
+ },
25
+ };
26
+ }
27
+ if (options.kind === "field-set") {
28
+ return {
29
+ sender: createResolvedFieldSenderSummary(options.sender, options.senderSelector),
30
+ path: "standalone-data-update",
31
+ value: options.value,
32
+ effect: {
33
+ kind: "write-field-value",
34
+ burnCogtoshi: "1",
35
+ },
36
+ };
37
+ }
38
+ return {
39
+ sender: createResolvedFieldSenderSummary(options.sender, options.senderSelector),
40
+ path: "standalone-data-clear",
41
+ value: null,
42
+ effect: {
43
+ kind: "clear-field-value",
44
+ burnCogtoshi: "0",
45
+ },
46
+ };
47
+ }
48
+ export function createResolvedFieldValueFromStoredData(kind, format, valueHex) {
49
+ if (kind === "field-clear" || format === null || format === undefined || valueHex === null || valueHex === undefined) {
50
+ return null;
51
+ }
52
+ return createResolvedFieldValueSummary(format, valueHex);
53
+ }
54
+ export function describeFieldEffect(effect) {
55
+ switch (effect.kind) {
56
+ case "create-empty-field":
57
+ return `burn ${effect.burnCogtoshi} cogtoshi to create an empty field`;
58
+ case "write-field-value":
59
+ return `burn ${effect.burnCogtoshi} cogtoshi to write the field value`;
60
+ case "clear-field-value":
61
+ return "clear the field value with no additional COG burn";
62
+ }
63
+ }
64
+ export function createFieldReuseResult(options) {
65
+ return {
66
+ kind: options.kind,
67
+ domainName: options.operation.normalizedDomainName,
68
+ fieldName: options.operation.normalizedFieldName,
69
+ fieldId: options.mutation.fieldId ?? options.operation.existingObservedField?.fieldId ?? null,
70
+ txid: options.mutation.attemptedTxid ?? "unknown",
71
+ permanent: options.mutation.fieldPermanent ?? options.operation.existingObservedField?.permanent ?? null,
72
+ format: options.mutation.fieldFormat ?? options.operation.existingObservedField?.format ?? null,
73
+ status: options.resolution,
74
+ reusedExisting: true,
75
+ resolved: createResolvedFieldSummary({
76
+ sender: options.operation.sender,
77
+ senderSelector: options.operation.senderSelector,
78
+ kind: options.kind,
79
+ value: createResolvedFieldValueFromStoredData(options.kind, options.mutation.fieldFormat ?? options.operation.existingObservedField?.format ?? null, options.mutation.fieldValueHex),
80
+ }),
81
+ fees: options.fees,
82
+ };
83
+ }
84
+ export function createFieldResult(options) {
85
+ return {
86
+ kind: options.kind,
87
+ domainName: options.operation.normalizedDomainName,
88
+ fieldName: options.operation.normalizedFieldName,
89
+ fieldId: options.mutation.fieldId ?? options.operation.existingObservedField?.fieldId ?? null,
90
+ txid: options.mutation.attemptedTxid ?? options.builtTxid ?? "unknown",
91
+ permanent: options.mutation.fieldPermanent ?? options.operation.existingObservedField?.permanent ?? null,
92
+ format: options.mutation.fieldFormat ?? options.operation.existingObservedField?.format ?? null,
93
+ status: options.status,
94
+ reusedExisting: options.reusedExisting,
95
+ resolved: createResolvedFieldSummary({
96
+ sender: options.operation.sender,
97
+ senderSelector: options.operation.senderSelector,
98
+ kind: options.kind,
99
+ value: createResolvedFieldValueFromStoredData(options.kind, options.mutation.fieldFormat ?? options.operation.existingObservedField?.format ?? null, options.mutation.fieldValueHex),
100
+ }),
101
+ fees: options.fees,
102
+ };
103
+ }