@cogcoin/client 0.5.15 → 1.0.1

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 (174) hide show
  1. package/README.md +80 -25
  2. package/dist/app-paths.d.ts +5 -6
  3. package/dist/app-paths.js +8 -16
  4. package/dist/art/balance.txt +10 -0
  5. package/dist/art/welcome.txt +16 -0
  6. package/dist/bitcoind/bootstrap/controller.d.ts +1 -0
  7. package/dist/bitcoind/bootstrap/controller.js +53 -1
  8. package/dist/bitcoind/client/follow-block-times.d.ts +1 -0
  9. package/dist/bitcoind/client/follow-block-times.js +1 -1
  10. package/dist/bitcoind/client/internal-types.d.ts +7 -3
  11. package/dist/bitcoind/client/managed-client.d.ts +4 -2
  12. package/dist/bitcoind/client/managed-client.js +14 -0
  13. package/dist/bitcoind/client/sync-engine.js +72 -11
  14. package/dist/bitcoind/hash-order.d.ts +4 -0
  15. package/dist/bitcoind/hash-order.js +13 -0
  16. package/dist/bitcoind/indexer-daemon-main.js +11 -3
  17. package/dist/bitcoind/normalize.js +3 -2
  18. package/dist/bitcoind/processing-start-height.d.ts +5 -0
  19. package/dist/bitcoind/processing-start-height.js +7 -0
  20. package/dist/bitcoind/progress/constants.d.ts +4 -0
  21. package/dist/bitcoind/progress/constants.js +4 -0
  22. package/dist/bitcoind/progress/controller.d.ts +2 -1
  23. package/dist/bitcoind/progress/controller.js +3 -3
  24. package/dist/bitcoind/progress/follow-scene.d.ts +6 -2
  25. package/dist/bitcoind/progress/follow-scene.js +29 -6
  26. package/dist/bitcoind/progress/formatting.d.ts +1 -0
  27. package/dist/bitcoind/progress/formatting.js +6 -0
  28. package/dist/bitcoind/progress/train-scene.js +37 -18
  29. package/dist/bitcoind/progress/tty-renderer.d.ts +6 -1
  30. package/dist/bitcoind/progress/tty-renderer.js +8 -4
  31. package/dist/bitcoind/rpc.d.ts +2 -1
  32. package/dist/bitcoind/rpc.js +3 -0
  33. package/dist/bitcoind/types.d.ts +6 -0
  34. package/dist/bytes.d.ts +1 -0
  35. package/dist/bytes.js +3 -0
  36. package/dist/cli/art.d.ts +2 -0
  37. package/dist/cli/art.js +37 -0
  38. package/dist/cli/commands/client-admin.d.ts +2 -0
  39. package/dist/cli/commands/client-admin.js +91 -0
  40. package/dist/cli/commands/follow.js +0 -2
  41. package/dist/cli/commands/mining-admin.js +6 -47
  42. package/dist/cli/commands/mining-read.js +11 -50
  43. package/dist/cli/commands/mining-runtime.js +142 -5
  44. package/dist/cli/commands/service-runtime.js +0 -2
  45. package/dist/cli/commands/status.js +8 -2
  46. package/dist/cli/commands/sync.js +49 -92
  47. package/dist/cli/commands/wallet-admin.js +142 -136
  48. package/dist/cli/commands/wallet-mutation.js +91 -79
  49. package/dist/cli/commands/wallet-read.js +15 -18
  50. package/dist/cli/context.js +5 -14
  51. package/dist/cli/mining-format.d.ts +0 -1
  52. package/dist/cli/mining-format.js +5 -37
  53. package/dist/cli/mining-json.d.ts +0 -18
  54. package/dist/cli/mining-json.js +0 -35
  55. package/dist/cli/mutation-command-groups.d.ts +1 -2
  56. package/dist/cli/mutation-command-groups.js +0 -5
  57. package/dist/cli/mutation-json.d.ts +24 -145
  58. package/dist/cli/mutation-json.js +30 -136
  59. package/dist/cli/mutation-resolved-json.d.ts +0 -7
  60. package/dist/cli/mutation-resolved-json.js +4 -10
  61. package/dist/cli/mutation-success.d.ts +2 -0
  62. package/dist/cli/mutation-success.js +11 -1
  63. package/dist/cli/mutation-text-format.js +1 -3
  64. package/dist/cli/output.d.ts +1 -1
  65. package/dist/cli/output.js +254 -231
  66. package/dist/cli/parse.d.ts +1 -1
  67. package/dist/cli/parse.js +93 -122
  68. package/dist/cli/preview-json.d.ts +17 -120
  69. package/dist/cli/preview-json.js +14 -97
  70. package/dist/cli/prompt.js +8 -13
  71. package/dist/cli/read-json.d.ts +15 -37
  72. package/dist/cli/read-json.js +44 -140
  73. package/dist/cli/runner.js +10 -13
  74. package/dist/cli/sync-progress.d.ts +6 -0
  75. package/dist/cli/sync-progress.js +91 -0
  76. package/dist/cli/types.d.ts +9 -17
  77. package/dist/cli/types.js +0 -2
  78. package/dist/cli/wallet-format.d.ts +1 -0
  79. package/dist/cli/wallet-format.js +208 -144
  80. package/dist/cli/workflow-hints.d.ts +3 -3
  81. package/dist/cli/workflow-hints.js +11 -8
  82. package/dist/client/default-client.d.ts +3 -1
  83. package/dist/client/default-client.js +45 -2
  84. package/dist/client/factory.js +1 -1
  85. package/dist/client/initialization.js +23 -0
  86. package/dist/client/persistence.js +5 -5
  87. package/dist/client/store-adapter.js +1 -0
  88. package/dist/sqlite/checkpoints.d.ts +1 -0
  89. package/dist/sqlite/checkpoints.js +7 -0
  90. package/dist/sqlite/store.js +14 -1
  91. package/dist/types.d.ts +1 -0
  92. package/dist/wallet/coin-control.d.ts +41 -12
  93. package/dist/wallet/coin-control.js +100 -428
  94. package/dist/wallet/descriptor-normalization.d.ts +1 -3
  95. package/dist/wallet/descriptor-normalization.js +0 -16
  96. package/dist/wallet/lifecycle.d.ts +7 -99
  97. package/dist/wallet/lifecycle.js +513 -968
  98. package/dist/wallet/managed-core-wallet.d.ts +13 -0
  99. package/dist/wallet/managed-core-wallet.js +20 -0
  100. package/dist/wallet/mining/constants.d.ts +5 -12
  101. package/dist/wallet/mining/constants.js +5 -12
  102. package/dist/wallet/mining/control.d.ts +1 -13
  103. package/dist/wallet/mining/control.js +45 -349
  104. package/dist/wallet/mining/index.d.ts +4 -5
  105. package/dist/wallet/mining/index.js +2 -3
  106. package/dist/wallet/mining/runner.d.ts +123 -13
  107. package/dist/wallet/mining/runner.js +899 -511
  108. package/dist/wallet/mining/runtime-artifacts.js +23 -3
  109. package/dist/wallet/mining/sentence-protocol.d.ts +44 -0
  110. package/dist/wallet/mining/sentence-protocol.js +123 -0
  111. package/dist/wallet/mining/sentences.d.ts +4 -8
  112. package/dist/wallet/mining/sentences.js +3 -52
  113. package/dist/wallet/mining/state.d.ts +11 -6
  114. package/dist/wallet/mining/state.js +7 -6
  115. package/dist/wallet/mining/types.d.ts +2 -30
  116. package/dist/wallet/mining/visualizer.d.ts +31 -3
  117. package/dist/wallet/mining/visualizer.js +135 -13
  118. package/dist/wallet/read/context.d.ts +0 -2
  119. package/dist/wallet/read/context.js +119 -140
  120. package/dist/wallet/read/filter.js +2 -11
  121. package/dist/wallet/read/index.d.ts +1 -1
  122. package/dist/wallet/read/project.js +24 -77
  123. package/dist/wallet/read/types.d.ts +10 -25
  124. package/dist/wallet/reset.d.ts +0 -1
  125. package/dist/wallet/reset.js +60 -138
  126. package/dist/wallet/root-resolution.d.ts +1 -5
  127. package/dist/wallet/root-resolution.js +0 -18
  128. package/dist/wallet/runtime.d.ts +0 -6
  129. package/dist/wallet/runtime.js +0 -8
  130. package/dist/wallet/state/client-password-agent.js +208 -0
  131. package/dist/wallet/state/client-password.d.ts +65 -0
  132. package/dist/wallet/state/client-password.js +952 -0
  133. package/dist/wallet/state/crypto.d.ts +1 -20
  134. package/dist/wallet/state/crypto.js +0 -63
  135. package/dist/wallet/state/provider.d.ts +23 -11
  136. package/dist/wallet/state/provider.js +248 -290
  137. package/dist/wallet/state/storage.d.ts +2 -2
  138. package/dist/wallet/state/storage.js +48 -16
  139. package/dist/wallet/tx/anchor.d.ts +3 -28
  140. package/dist/wallet/tx/anchor.js +349 -1250
  141. package/dist/wallet/tx/bitcoin-transfer.d.ts +35 -0
  142. package/dist/wallet/tx/bitcoin-transfer.js +200 -0
  143. package/dist/wallet/tx/cog.d.ts +5 -1
  144. package/dist/wallet/tx/cog.js +149 -185
  145. package/dist/wallet/tx/common.d.ts +61 -8
  146. package/dist/wallet/tx/common.js +266 -146
  147. package/dist/wallet/tx/domain-admin.d.ts +3 -1
  148. package/dist/wallet/tx/domain-admin.js +61 -99
  149. package/dist/wallet/tx/domain-market.d.ts +5 -1
  150. package/dist/wallet/tx/domain-market.js +221 -228
  151. package/dist/wallet/tx/field.d.ts +4 -10
  152. package/dist/wallet/tx/field.js +83 -924
  153. package/dist/wallet/tx/identity-selector.d.ts +9 -3
  154. package/dist/wallet/tx/identity-selector.js +17 -35
  155. package/dist/wallet/tx/index.d.ts +3 -1
  156. package/dist/wallet/tx/index.js +2 -1
  157. package/dist/wallet/tx/register.d.ts +3 -1
  158. package/dist/wallet/tx/register.js +62 -220
  159. package/dist/wallet/tx/reputation.d.ts +3 -1
  160. package/dist/wallet/tx/reputation.js +58 -95
  161. package/dist/wallet/types.d.ts +8 -122
  162. package/package.json +5 -5
  163. package/dist/wallet/archive.d.ts +0 -4
  164. package/dist/wallet/archive.js +0 -41
  165. package/dist/wallet/mining/hook-protocol.d.ts +0 -47
  166. package/dist/wallet/mining/hook-protocol.js +0 -161
  167. package/dist/wallet/mining/hook-runner.js +0 -52
  168. package/dist/wallet/mining/hooks.d.ts +0 -38
  169. package/dist/wallet/mining/hooks.js +0 -520
  170. package/dist/wallet/state/explicit-lock.d.ts +0 -4
  171. package/dist/wallet/state/explicit-lock.js +0 -19
  172. package/dist/wallet/state/session.d.ts +0 -12
  173. package/dist/wallet/state/session.js +0 -23
  174. /package/dist/wallet/{mining/hook-runner.d.ts → state/client-password-agent.d.ts} +0 -0
@@ -9,7 +9,7 @@ import { resolveWalletRuntimePathsForTesting } from "../runtime.js";
9
9
  import { createDefaultWalletSecretProvider, } from "../state/provider.js";
10
10
  import { serializeSetCanonical, serializeSetDelegate, serializeSetEndpoint, serializeSetMiner, validateDomainName, } from "../cogop/index.js";
11
11
  import { openWalletReadContext } from "../read/index.js";
12
- import { assertFixedInputPrefixMatches, assertFundingInputsAfterFixedPrefix, assertWalletMutationContextReady, buildWalletMutationTransactionWithReserveFallback, getDecodedInputScriptPubKeyHex, isAlreadyAcceptedError, isBroadcastUnknownError, outpointKey, pauseMiningForWalletMutation, saveWalletStatePreservingUnlock, unlockTemporaryBuilderLocks, updateMutationRecord, } from "./common.js";
12
+ import { assertFixedInputPrefixMatches, assertFundingInputsAfterFixedPrefix, assertWalletMutationContextReady, buildWalletMutationTransactionWithReserveFallback, createBuiltWalletMutationFeeSummary, createFundingMutationSender, createWalletMutationFeeMetadata, getDecodedInputScriptPubKeyHex, isLocalWalletScript, isAlreadyAcceptedError, isBroadcastUnknownError, mergeFixedWalletInputs, outpointKey, pauseMiningForWalletMutation, resolvePendingMutationReuseDecision, resolveWalletMutationFeeSelection, saveWalletStatePreservingUnlock, unlockTemporaryBuilderLocks, updateMutationRecord, } from "./common.js";
13
13
  import { confirmYesNo } from "./confirm.js";
14
14
  import { getCanonicalIdentitySelector } from "./identity-selector.js";
15
15
  import { findPendingMutationByIntent, upsertPendingMutation } from "./journal.js";
@@ -71,17 +71,6 @@ function createIntentFingerprint(parts) {
71
71
  .update(parts.map((part) => String(part)).join("\n"))
72
72
  .digest("hex");
73
73
  }
74
- function resolveAnchorOutpointForSender(state, sender, errorPrefix) {
75
- const anchoredDomain = state.domains.find((domain) => domain.currentOwnerLocalIndex === sender.index
76
- && domain.canonicalChainStatus === "anchored") ?? null;
77
- if (anchoredDomain?.currentCanonicalAnchorOutpoint === null || anchoredDomain === null) {
78
- throw new Error(`${errorPrefix}_anchor_outpoint_unavailable`);
79
- }
80
- return {
81
- txid: anchoredDomain.currentCanonicalAnchorOutpoint.txid,
82
- vout: anchoredDomain.currentCanonicalAnchorOutpoint.vout,
83
- };
84
- }
85
74
  function resolveAnchoredDomainOperation(context, domainName, errorPrefix, options = {}) {
86
75
  assertWalletMutationContextReady(context, errorPrefix);
87
76
  const chainDomain = lookupDomain(context.snapshot.state, domainName);
@@ -95,24 +84,14 @@ function resolveAnchoredDomainOperation(context, domainName, errorPrefix, option
95
84
  throw new Error(`${errorPrefix}_root_domain_required`);
96
85
  }
97
86
  const ownerHex = Buffer.from(chainDomain.ownerScriptPubKey).toString("hex");
98
- const ownerIdentity = context.model.identities.find((identity) => identity.scriptPubKeyHex === ownerHex) ?? null;
99
- if (ownerIdentity === null || ownerIdentity.address === null) {
87
+ if (ownerHex !== context.localState.state.funding.scriptPubKeyHex || context.model.walletAddress == null) {
100
88
  throw new Error(`${errorPrefix}_owner_not_locally_controlled`);
101
89
  }
102
- if ((options.rejectReadOnly ?? true) && ownerIdentity.readOnly) {
103
- throw new Error(`${errorPrefix}_owner_read_only`);
104
- }
105
90
  return {
106
91
  readContext: context,
107
92
  state: context.localState.state,
108
- unlockUntilUnixMs: context.localState.unlockUntilUnixMs,
109
- sender: {
110
- localIndex: ownerIdentity.index,
111
- scriptPubKeyHex: ownerIdentity.scriptPubKeyHex,
112
- address: ownerIdentity.address,
113
- },
114
- senderSelector: getCanonicalIdentitySelector(ownerIdentity),
115
- anchorOutpoint: resolveAnchorOutpointForSender(context.localState.state, ownerIdentity, errorPrefix),
93
+ sender: createFundingMutationSender(context.localState.state),
94
+ senderSelector: context.model.walletAddress,
116
95
  chainDomain,
117
96
  };
118
97
  }
@@ -121,29 +100,13 @@ function buildPlanForDomainAdminOperation(options) {
121
100
  && entry.confirmations >= 1
122
101
  && entry.spendable !== false
123
102
  && entry.safe !== false);
124
- const anchorUtxo = options.allUtxos.find((entry) => entry.txid === options.anchorOutpoint.txid
125
- && entry.vout === options.anchorOutpoint.vout
126
- && entry.scriptPubKey === options.sender.scriptPubKeyHex
127
- && entry.confirmations >= 1
128
- && entry.spendable !== false
129
- && entry.safe !== false);
130
- if (anchorUtxo === undefined) {
131
- throw new Error(`${options.errorPrefix}_anchor_utxo_missing`);
132
- }
133
103
  return {
134
104
  sender: options.sender,
135
105
  changeAddress: options.state.funding.address,
136
- fixedInputs: [
137
- { txid: anchorUtxo.txid, vout: anchorUtxo.vout },
138
- ],
139
- outputs: [
140
- { data: Buffer.from(options.opReturnData).toString("hex") },
141
- { [options.sender.address]: satsToBtcNumber(BigInt(options.state.anchorValueSats)) },
142
- ],
143
- changePosition: 2,
106
+ fixedInputs: [],
107
+ outputs: [{ data: Buffer.from(options.opReturnData).toString("hex") }],
108
+ changePosition: 1,
144
109
  expectedOpReturnScriptHex: encodeOpReturnScript(options.opReturnData),
145
- expectedAnchorScriptHex: options.sender.scriptPubKeyHex,
146
- expectedAnchorValueSats: BigInt(options.state.anchorValueSats),
147
110
  allowedFundingScriptPubKeyHex: options.state.funding.scriptPubKeyHex,
148
111
  eligibleFundingOutpointKeys: new Set(fundingUtxos.map((entry) => outpointKey({ txid: entry.txid, vout: entry.vout }))),
149
112
  errorPrefix: options.errorPrefix,
@@ -155,33 +118,16 @@ function validateFundedDraft(decoded, funded, plan) {
155
118
  if (inputs.length === 0) {
156
119
  throw new Error(`${plan.errorPrefix}_missing_sender_input`);
157
120
  }
158
- assertFixedInputPrefixMatches(inputs, plan.fixedInputs, `${plan.errorPrefix}_sender_input_mismatch`);
159
- if (getDecodedInputScriptPubKeyHex(decoded, 0) !== plan.sender.scriptPubKeyHex) {
160
- throw new Error(`${plan.errorPrefix}_sender_input_mismatch`);
161
- }
162
- assertFundingInputsAfterFixedPrefix({
163
- decoded,
164
- fixedInputs: plan.fixedInputs,
165
- allowedFundingScriptPubKeyHex: plan.allowedFundingScriptPubKeyHex,
166
- eligibleFundingOutpointKeys: plan.eligibleFundingOutpointKeys,
167
- errorCode: `${plan.errorPrefix}_unexpected_funding_input`,
168
- });
169
121
  if (outputs[0]?.scriptPubKey?.hex !== plan.expectedOpReturnScriptHex) {
170
122
  throw new Error(`${plan.errorPrefix}_opreturn_mismatch`);
171
123
  }
172
- if (outputs[1]?.scriptPubKey?.hex !== plan.expectedAnchorScriptHex) {
173
- throw new Error(`${plan.errorPrefix}_anchor_output_mismatch`);
174
- }
175
- if (valueToSats(outputs[1]?.value ?? 0) !== plan.expectedAnchorValueSats) {
176
- throw new Error(`${plan.errorPrefix}_anchor_value_mismatch`);
177
- }
178
124
  if (funded.changepos === -1) {
179
- if (outputs.length !== 2) {
125
+ if (outputs.length !== 1) {
180
126
  throw new Error(`${plan.errorPrefix}_unexpected_output_count`);
181
127
  }
182
128
  return;
183
129
  }
184
- if (funded.changepos !== plan.changePosition || outputs.length !== 3) {
130
+ if (funded.changepos !== plan.changePosition || outputs.length !== 2) {
185
131
  throw new Error(`${plan.errorPrefix}_change_position_mismatch`);
186
132
  }
187
133
  if (outputs[funded.changepos]?.scriptPubKey?.hex !== plan.allowedFundingScriptPubKeyHex) {
@@ -197,7 +143,7 @@ async function buildTransaction(options) {
197
143
  validateFundedDraft,
198
144
  finalizeErrorCode: `${options.plan.errorPrefix}_finalize_failed`,
199
145
  mempoolRejectPrefix: `${options.plan.errorPrefix}_mempool_rejected`,
200
- reserveCandidates: options.state.proactiveReserveOutpoints,
146
+ feeRate: options.feeRateSatVb,
201
147
  });
202
148
  }
203
149
  function createDraftMutation(options) {
@@ -214,6 +160,7 @@ function createDraftMutation(options) {
214
160
  lastUpdatedAtUnixMs: options.nowUnixMs,
215
161
  attemptedTxid: null,
216
162
  attemptedWtxid: null,
163
+ ...createWalletMutationFeeMetadata(options.feeSelection),
217
164
  temporaryBuilderLockedOutpoints: [],
218
165
  };
219
166
  }
@@ -232,6 +179,7 @@ function createDraftMutation(options) {
232
179
  lastUpdatedAtUnixMs: options.nowUnixMs,
233
180
  attemptedTxid: null,
234
181
  attemptedWtxid: null,
182
+ ...createWalletMutationFeeMetadata(options.feeSelection),
235
183
  temporaryBuilderLockedOutpoints: [],
236
184
  };
237
185
  }
@@ -244,7 +192,6 @@ async function saveUpdatedMutationState(options) {
244
192
  await saveWalletStatePreservingUnlock({
245
193
  state: nextState,
246
194
  provider: options.provider,
247
- unlockUntilUnixMs: options.unlockUntilUnixMs,
248
195
  nowUnixMs: options.nowUnixMs,
249
196
  paths: options.paths,
250
197
  });
@@ -310,7 +257,6 @@ async function reconcilePendingAdminMutation(options) {
310
257
  nextState = await saveUpdatedMutationState({
311
258
  state: nextState,
312
259
  provider: options.provider,
313
- unlockUntilUnixMs: options.unlockUntilUnixMs,
314
260
  nowUnixMs: options.nowUnixMs,
315
261
  paths: options.paths,
316
262
  });
@@ -325,7 +271,6 @@ async function reconcilePendingAdminMutation(options) {
325
271
  nextState = await saveUpdatedMutationState({
326
272
  state: nextState,
327
273
  provider: options.provider,
328
- unlockUntilUnixMs: options.unlockUntilUnixMs,
329
274
  nowUnixMs: options.nowUnixMs,
330
275
  paths: options.paths,
331
276
  });
@@ -343,7 +288,6 @@ async function reconcilePendingAdminMutation(options) {
343
288
  nextState = await saveUpdatedMutationState({
344
289
  state: nextState,
345
290
  provider: options.provider,
346
- unlockUntilUnixMs: options.unlockUntilUnixMs,
347
291
  nowUnixMs: options.nowUnixMs,
348
292
  paths: options.paths,
349
293
  });
@@ -360,7 +304,6 @@ async function reconcilePendingAdminMutation(options) {
360
304
  nextState = await saveUpdatedMutationState({
361
305
  state: nextState,
362
306
  provider: options.provider,
363
- unlockUntilUnixMs: options.unlockUntilUnixMs,
364
307
  nowUnixMs: options.nowUnixMs,
365
308
  paths: options.paths,
366
309
  });
@@ -483,7 +426,6 @@ async function sendBuiltTransaction(options) {
483
426
  nextState = await saveUpdatedMutationState({
484
427
  state: nextState,
485
428
  provider: options.provider,
486
- unlockUntilUnixMs: options.unlockUntilUnixMs,
487
429
  nowUnixMs: options.nowUnixMs,
488
430
  paths: options.paths,
489
431
  });
@@ -506,7 +448,6 @@ async function sendBuiltTransaction(options) {
506
448
  nextState = await saveUpdatedMutationState({
507
449
  state: nextState,
508
450
  provider: options.provider,
509
- unlockUntilUnixMs: options.unlockUntilUnixMs,
510
451
  nowUnixMs: options.nowUnixMs,
511
452
  paths: options.paths,
512
453
  });
@@ -522,7 +463,6 @@ async function sendBuiltTransaction(options) {
522
463
  nextState = await saveUpdatedMutationState({
523
464
  state: nextState,
524
465
  provider: options.provider,
525
- unlockUntilUnixMs: options.unlockUntilUnixMs,
526
466
  nowUnixMs: options.nowUnixMs,
527
467
  paths: options.paths,
528
468
  });
@@ -539,7 +479,6 @@ async function sendBuiltTransaction(options) {
539
479
  nextState = await saveUpdatedMutationState({
540
480
  state: nextState,
541
481
  provider: options.provider,
542
- unlockUntilUnixMs: options.unlockUntilUnixMs,
543
482
  nowUnixMs: options.nowUnixMs,
544
483
  paths: options.paths,
545
484
  });
@@ -583,46 +522,63 @@ async function submitDomainAdminMutation(options) {
583
522
  });
584
523
  const rpc = (options.rpcFactory ?? createRpcClient)(node.rpc);
585
524
  const walletName = operation.state.managedCoreWallet.walletName;
525
+ const feeSelection = await resolveWalletMutationFeeSelection({
526
+ rpc,
527
+ feeRateSatVb: options.feeRateSatVb ?? null,
528
+ });
586
529
  const existingMutation = findPendingMutationByIntent(operation.state, intentFingerprintHex);
530
+ let workingState = operation.state;
531
+ let replacementFixedInputs = null;
587
532
  if (existingMutation !== null) {
588
533
  const reconciled = await reconcilePendingAdminMutation({
589
534
  state: operation.state,
590
535
  mutation: existingMutation,
591
536
  provider,
592
- unlockUntilUnixMs: operation.unlockUntilUnixMs,
593
537
  nowUnixMs,
594
538
  paths,
595
539
  rpc,
596
540
  walletName,
597
541
  context: readContext,
598
542
  });
543
+ workingState = reconciled.state;
599
544
  if (reconciled.resolution === "confirmed" || reconciled.resolution === "live") {
600
- return {
601
- kind: options.kind,
602
- domainName: normalizedDomainName,
603
- txid: reconciled.mutation.attemptedTxid ?? "unknown",
604
- status: reconciled.resolution,
605
- reusedExisting: true,
606
- recipientScriptPubKeyHex: payload.recipientScriptPubKeyHex ?? null,
607
- endpointValueHex: payload.endpointValueHex ?? null,
608
- resolved: {
609
- sender: resolvedSender,
610
- target: payload.resolvedTarget,
611
- effect: payload.resolvedEffect,
612
- },
613
- };
545
+ const reuse = await resolvePendingMutationReuseDecision({
546
+ rpc,
547
+ walletName,
548
+ mutation: reconciled.mutation,
549
+ nextFeeSelection: feeSelection,
550
+ });
551
+ if (reuse.reuseExisting) {
552
+ return {
553
+ kind: options.kind,
554
+ domainName: normalizedDomainName,
555
+ txid: reconciled.mutation.attemptedTxid ?? "unknown",
556
+ status: reconciled.resolution,
557
+ reusedExisting: true,
558
+ recipientScriptPubKeyHex: payload.recipientScriptPubKeyHex ?? null,
559
+ endpointValueHex: payload.endpointValueHex ?? null,
560
+ resolved: {
561
+ sender: resolvedSender,
562
+ target: payload.resolvedTarget,
563
+ effect: payload.resolvedEffect,
564
+ },
565
+ fees: reuse.fees,
566
+ };
567
+ }
568
+ replacementFixedInputs = reuse.replacementFixedInputs;
614
569
  }
615
570
  if (reconciled.resolution === "repair-required") {
616
571
  throw new Error(`${options.errorPrefix}_repair_required`);
617
572
  }
618
573
  }
619
574
  await options.confirm(operation);
620
- let nextState = upsertPendingMutation(operation.state, createDraftMutation({
575
+ let nextState = upsertPendingMutation(workingState, createDraftMutation({
621
576
  kind: options.kind,
622
577
  domainName: normalizedDomainName,
623
578
  sender: operation.sender,
624
579
  intentFingerprintHex,
625
580
  nowUnixMs,
581
+ feeSelection,
626
582
  recipientScriptPubKeyHex: payload.recipientScriptPubKeyHex ?? null,
627
583
  endpointValueHex: payload.endpointValueHex ?? null,
628
584
  existing: existingMutation,
@@ -630,22 +586,25 @@ async function submitDomainAdminMutation(options) {
630
586
  nextState = await saveUpdatedMutationState({
631
587
  state: nextState,
632
588
  provider,
633
- unlockUntilUnixMs: operation.unlockUntilUnixMs,
634
589
  nowUnixMs,
635
590
  paths,
636
591
  });
592
+ const adminPlan = buildPlanForDomainAdminOperation({
593
+ state: nextState,
594
+ allUtxos: await rpc.listUnspent(walletName, 1),
595
+ sender: operation.sender,
596
+ opReturnData: payload.opReturnData,
597
+ errorPrefix: options.errorPrefix,
598
+ });
637
599
  const built = await buildTransaction({
638
600
  rpc,
639
601
  walletName,
640
602
  state: nextState,
641
- plan: buildPlanForDomainAdminOperation({
642
- state: nextState,
643
- allUtxos: await rpc.listUnspent(walletName, 1),
644
- sender: operation.sender,
645
- anchorOutpoint: operation.anchorOutpoint,
646
- opReturnData: payload.opReturnData,
647
- errorPrefix: options.errorPrefix,
648
- }),
603
+ plan: {
604
+ ...adminPlan,
605
+ fixedInputs: mergeFixedWalletInputs(adminPlan.fixedInputs, replacementFixedInputs),
606
+ },
607
+ feeRateSatVb: feeSelection.feeRateSatVb,
649
608
  });
650
609
  const final = await sendBuiltTransaction({
651
610
  rpc,
@@ -655,7 +614,6 @@ async function submitDomainAdminMutation(options) {
655
614
  mutation: nextState.pendingMutations.find((mutation) => mutation.intentFingerprintHex === intentFingerprintHex),
656
615
  state: nextState,
657
616
  provider,
658
- unlockUntilUnixMs: operation.unlockUntilUnixMs,
659
617
  nowUnixMs,
660
618
  paths,
661
619
  errorPrefix: options.errorPrefix,
@@ -673,6 +631,10 @@ async function submitDomainAdminMutation(options) {
673
631
  target: payload.resolvedTarget,
674
632
  effect: payload.resolvedEffect,
675
633
  },
634
+ fees: createBuiltWalletMutationFeeSummary({
635
+ selection: feeSelection,
636
+ built,
637
+ }),
676
638
  };
677
639
  }
678
640
  finally {
@@ -5,7 +5,7 @@ import type { WalletPrompter } from "../lifecycle.js";
5
5
  import { type WalletRuntimePaths } from "../runtime.js";
6
6
  import { type WalletSecretProvider } from "../state/provider.js";
7
7
  import { openWalletReadContext } from "../read/index.js";
8
- import { type WalletMutationRpcClient } from "./common.js";
8
+ import { type WalletMutationFeeSummary, type WalletMutationRpcClient } from "./common.js";
9
9
  type DomainMarketKind = "transfer" | "sell" | "buy";
10
10
  interface DomainMarketRpcClient extends WalletMutationRpcClient {
11
11
  getBlockchainInfo(): Promise<{
@@ -54,6 +54,7 @@ export interface DomainMarketResolvedSummary {
54
54
  export interface TransferDomainOptions {
55
55
  domainName: string;
56
56
  target: string;
57
+ feeRateSatVb?: number | null;
57
58
  dataDir: string;
58
59
  databasePath: string;
59
60
  provider?: WalletSecretProvider;
@@ -68,6 +69,7 @@ export interface TransferDomainOptions {
68
69
  export interface SellDomainOptions {
69
70
  domainName: string;
70
71
  listedPriceCogtoshi: bigint;
72
+ feeRateSatVb?: number | null;
71
73
  dataDir: string;
72
74
  databasePath: string;
73
75
  provider?: WalletSecretProvider;
@@ -82,6 +84,7 @@ export interface SellDomainOptions {
82
84
  export interface BuyDomainOptions {
83
85
  domainName: string;
84
86
  fromIdentity?: string | null;
87
+ feeRateSatVb?: number | null;
85
88
  dataDir: string;
86
89
  databasePath: string;
87
90
  provider?: WalletSecretProvider;
@@ -104,6 +107,7 @@ export interface DomainMarketMutationResult {
104
107
  resolved?: DomainMarketResolvedSummary | null;
105
108
  resolvedBuyer?: DomainMarketResolvedBuyerSummary | null;
106
109
  resolvedSeller?: DomainMarketResolvedSellerSummary | null;
110
+ fees: WalletMutationFeeSummary;
107
111
  }
108
112
  export declare function parseCogAmountToCogtoshi(raw: string): bigint;
109
113
  export declare function transferDomain(options: TransferDomainOptions): Promise<DomainMarketMutationResult>;