@cogcoin/client 1.1.5 → 1.1.7

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 (132) hide show
  1. package/README.md +2 -2
  2. package/dist/bitcoind/indexer-daemon.d.ts +3 -7
  3. package/dist/bitcoind/indexer-daemon.js +39 -204
  4. package/dist/bitcoind/managed-runtime/bitcoind-policy.d.ts +16 -0
  5. package/dist/bitcoind/managed-runtime/bitcoind-policy.js +177 -0
  6. package/dist/bitcoind/managed-runtime/bitcoind-runtime.d.ts +20 -0
  7. package/dist/bitcoind/managed-runtime/bitcoind-runtime.js +74 -0
  8. package/dist/bitcoind/managed-runtime/bitcoind-status.d.ts +11 -0
  9. package/dist/bitcoind/managed-runtime/bitcoind-status.js +44 -0
  10. package/dist/bitcoind/managed-runtime/indexer-policy.d.ts +34 -0
  11. package/dist/bitcoind/managed-runtime/indexer-policy.js +200 -0
  12. package/dist/bitcoind/managed-runtime/indexer-runtime.d.ts +15 -0
  13. package/dist/bitcoind/managed-runtime/indexer-runtime.js +82 -0
  14. package/dist/bitcoind/managed-runtime/status.d.ts +11 -0
  15. package/dist/bitcoind/managed-runtime/status.js +59 -0
  16. package/dist/bitcoind/managed-runtime/types.d.ts +77 -0
  17. package/dist/bitcoind/node.d.ts +2 -2
  18. package/dist/bitcoind/node.js +2 -2
  19. package/dist/bitcoind/rpc.d.ts +2 -1
  20. package/dist/bitcoind/rpc.js +53 -3
  21. package/dist/bitcoind/service.d.ts +2 -7
  22. package/dist/bitcoind/service.js +79 -207
  23. package/dist/cli/command-registry.d.ts +1 -1
  24. package/dist/cli/command-registry.js +2 -64
  25. package/dist/cli/commands/client-admin.js +3 -18
  26. package/dist/cli/commands/mining-runtime.js +4 -60
  27. package/dist/cli/commands/wallet-admin.js +6 -6
  28. package/dist/cli/context.js +1 -3
  29. package/dist/cli/mining-json.d.ts +1 -22
  30. package/dist/cli/mining-json.js +0 -23
  31. package/dist/cli/output.js +16 -2
  32. package/dist/cli/parse.js +0 -2
  33. package/dist/cli/preview-json.d.ts +1 -22
  34. package/dist/cli/preview-json.js +0 -19
  35. package/dist/cli/types.d.ts +1 -3
  36. package/dist/cli/wallet-format.js +1 -1
  37. package/dist/cli/workflow-hints.d.ts +1 -2
  38. package/dist/cli/workflow-hints.js +5 -8
  39. package/dist/wallet/lifecycle/access.d.ts +5 -0
  40. package/dist/wallet/lifecycle/access.js +79 -0
  41. package/dist/wallet/lifecycle/context.d.ts +26 -0
  42. package/dist/wallet/lifecycle/context.js +57 -0
  43. package/dist/wallet/lifecycle/managed-core.d.ts +1 -9
  44. package/dist/wallet/lifecycle/managed-core.js +3 -63
  45. package/dist/wallet/lifecycle/repair-bitcoind.d.ts +10 -0
  46. package/dist/wallet/lifecycle/repair-bitcoind.js +142 -0
  47. package/dist/wallet/lifecycle/repair-indexer.d.ts +8 -0
  48. package/dist/wallet/lifecycle/repair-indexer.js +117 -0
  49. package/dist/wallet/lifecycle/repair-mining.d.ts +1 -5
  50. package/dist/wallet/lifecycle/repair-mining.js +5 -39
  51. package/dist/wallet/lifecycle/repair.d.ts +2 -4
  52. package/dist/wallet/lifecycle/repair.js +74 -318
  53. package/dist/wallet/lifecycle/setup-prompts.d.ts +7 -0
  54. package/dist/wallet/lifecycle/setup-prompts.js +88 -0
  55. package/dist/wallet/lifecycle/setup-state.d.ts +26 -0
  56. package/dist/wallet/lifecycle/setup-state.js +159 -0
  57. package/dist/wallet/lifecycle/setup.d.ts +3 -4
  58. package/dist/wallet/lifecycle/setup.js +47 -351
  59. package/dist/wallet/lifecycle/types.d.ts +33 -5
  60. package/dist/wallet/managed-core-wallet.d.ts +2 -0
  61. package/dist/wallet/managed-core-wallet.js +27 -1
  62. package/dist/wallet/mining/candidate.d.ts +1 -0
  63. package/dist/wallet/mining/candidate.js +38 -6
  64. package/dist/wallet/mining/competitiveness.d.ts +1 -0
  65. package/dist/wallet/mining/competitiveness.js +6 -0
  66. package/dist/wallet/mining/cycle.d.ts +2 -0
  67. package/dist/wallet/mining/cycle.js +14 -4
  68. package/dist/wallet/mining/engine-types.d.ts +1 -0
  69. package/dist/wallet/mining/index.d.ts +1 -1
  70. package/dist/wallet/mining/index.js +1 -1
  71. package/dist/wallet/mining/publish.d.ts +3 -0
  72. package/dist/wallet/mining/publish.js +78 -6
  73. package/dist/wallet/mining/runner.d.ts +0 -32
  74. package/dist/wallet/mining/runner.js +59 -104
  75. package/dist/wallet/mining/stop.d.ts +7 -0
  76. package/dist/wallet/mining/stop.js +23 -0
  77. package/dist/wallet/mining/supervisor.d.ts +2 -36
  78. package/dist/wallet/mining/supervisor.js +139 -246
  79. package/dist/wallet/read/context.d.ts +1 -5
  80. package/dist/wallet/read/context.js +20 -379
  81. package/dist/wallet/read/managed-services.d.ts +33 -0
  82. package/dist/wallet/read/managed-services.js +222 -0
  83. package/dist/wallet/state/client-password/bootstrap.d.ts +2 -0
  84. package/dist/wallet/state/client-password/bootstrap.js +3 -0
  85. package/dist/wallet/state/client-password/context.d.ts +10 -0
  86. package/dist/wallet/state/client-password/context.js +46 -0
  87. package/dist/wallet/state/client-password/crypto.d.ts +34 -0
  88. package/dist/wallet/state/client-password/crypto.js +117 -0
  89. package/dist/wallet/state/client-password/files.d.ts +10 -0
  90. package/dist/wallet/state/client-password/files.js +109 -0
  91. package/dist/wallet/state/client-password/legacy-cleanup.d.ts +11 -0
  92. package/dist/wallet/state/client-password/legacy-cleanup.js +338 -0
  93. package/dist/wallet/state/client-password/messages.d.ts +3 -0
  94. package/dist/wallet/state/client-password/messages.js +9 -0
  95. package/dist/wallet/state/client-password/migration.d.ts +4 -0
  96. package/dist/wallet/state/client-password/migration.js +32 -0
  97. package/dist/wallet/state/client-password/prompts.d.ts +12 -0
  98. package/dist/wallet/state/client-password/prompts.js +79 -0
  99. package/dist/wallet/state/client-password/protected-secrets.d.ts +13 -0
  100. package/dist/wallet/state/client-password/protected-secrets.js +90 -0
  101. package/dist/wallet/state/client-password/readiness.d.ts +4 -0
  102. package/dist/wallet/state/client-password/readiness.js +48 -0
  103. package/dist/wallet/state/client-password/references.d.ts +1 -0
  104. package/dist/wallet/state/client-password/references.js +56 -0
  105. package/dist/wallet/state/client-password/rotation.d.ts +6 -0
  106. package/dist/wallet/state/client-password/rotation.js +98 -0
  107. package/dist/wallet/state/client-password/session-policy.d.ts +6 -0
  108. package/dist/wallet/state/client-password/session-policy.js +28 -0
  109. package/dist/wallet/state/client-password/session.d.ts +19 -0
  110. package/dist/wallet/state/client-password/session.js +170 -0
  111. package/dist/wallet/state/client-password/setup.d.ts +8 -0
  112. package/dist/wallet/state/client-password/setup.js +49 -0
  113. package/dist/wallet/state/client-password/types.d.ts +82 -0
  114. package/dist/wallet/state/client-password/types.js +5 -0
  115. package/dist/wallet/state/client-password.d.ts +7 -38
  116. package/dist/wallet/state/client-password.js +52 -937
  117. package/dist/wallet/tx/anchor.js +123 -216
  118. package/dist/wallet/tx/cog.js +294 -489
  119. package/dist/wallet/tx/common.d.ts +2 -0
  120. package/dist/wallet/tx/common.js +2 -0
  121. package/dist/wallet/tx/domain-admin.js +111 -220
  122. package/dist/wallet/tx/domain-market.js +401 -681
  123. package/dist/wallet/tx/executor.d.ts +176 -0
  124. package/dist/wallet/tx/executor.js +302 -0
  125. package/dist/wallet/tx/field.js +109 -215
  126. package/dist/wallet/tx/register.js +158 -269
  127. package/dist/wallet/tx/reputation.js +120 -227
  128. package/package.json +1 -1
  129. package/dist/wallet/mining/worker-main.js +0 -17
  130. package/dist/wallet/state/client-password-agent.d.ts +0 -1
  131. package/dist/wallet/state/client-password-agent.js +0 -211
  132. /package/dist/{wallet/mining/worker-main.d.ts → bitcoind/managed-runtime/types.js} +0 -0
@@ -3,15 +3,15 @@ import { loadBundledGenesisParameters } from "@cogcoin/indexer";
3
3
  import { getBalance, getParent, lookupDomain } from "@cogcoin/indexer/queries";
4
4
  import { attachOrStartManagedBitcoindService } from "../../bitcoind/service.js";
5
5
  import { createRpcClient } from "../../bitcoind/node.js";
6
- import { acquireFileLock } from "../fs/lock.js";
7
- import { resolveWalletRuntimePathsForTesting } from "../runtime.js";
8
- import { createDefaultWalletSecretProvider, } from "../state/provider.js";
6
+ import {} from "../runtime.js";
7
+ import {} from "../state/provider.js";
9
8
  import { computeRootRegistrationPriceSats, serializeDomainReg } from "../cogop/index.js";
10
9
  import { openWalletReadContext } from "../read/index.js";
11
- import { assertFixedInputPrefixMatches, assertFundingInputsAfterFixedPrefix, assertWalletMutationContextReady, buildWalletMutationTransactionWithReserveFallback, createBuiltWalletMutationFeeSummary, createFundingMutationSender, createWalletMutationFeeMetadata, formatCogAmount, getDecodedInputScriptPubKeyHex, isLocalWalletScript, isAlreadyAcceptedError, isBroadcastUnknownError, mergeFixedWalletInputs, outpointKey, pauseMiningForWalletMutation, resolvePendingMutationReuseDecision, resolveWalletMutationFeeSelection, saveWalletStatePreservingUnlock, unlockTemporaryBuilderLocks, updateMutationRecord, } from "./common.js";
10
+ import { assertFixedInputPrefixMatches, assertFundingInputsAfterFixedPrefix, assertWalletMutationContextReady, buildWalletMutationTransactionWithReserveFallback, createFundingMutationSender, createWalletMutationFeeMetadata, formatCogAmount, getDecodedInputScriptPubKeyHex, isLocalWalletScript, mergeFixedWalletInputs, outpointKey, saveWalletStatePreservingUnlock, unlockTemporaryBuilderLocks, updateMutationRecord, } from "./common.js";
12
11
  import { confirmTypedAcknowledgement, confirmYesNo } from "./confirm.js";
12
+ import { executeWalletMutationOperation, publishWalletMutation, resolveExistingWalletMutation, } from "./executor.js";
13
13
  import { getCanonicalIdentitySelector, resolveIdentityBySelector, } from "./identity-selector.js";
14
- import { findPendingMutationByIntent, upsertPendingMutation } from "./journal.js";
14
+ import { upsertPendingMutation } from "./journal.js";
15
15
  const SUBDOMAIN_REGISTRATION_FEE_COGTOSHI = 100n;
16
16
  function normalizeDomainName(domainName) {
17
17
  const normalized = domainName.trim().toLowerCase();
@@ -489,36 +489,21 @@ export async function registerDomain(options) {
489
489
  if (!options.prompter.isInteractive && options.assumeYes !== true) {
490
490
  throw new Error("wallet_register_requires_tty");
491
491
  }
492
- const provider = options.provider ?? createDefaultWalletSecretProvider();
493
- const nowUnixMs = options.nowUnixMs ?? Date.now();
494
- const paths = options.paths ?? resolveWalletRuntimePathsForTesting();
495
- const controlLock = await acquireFileLock(paths.walletControlLockPath, {
496
- purpose: "wallet-register",
497
- walletRootId: null,
498
- });
499
492
  const normalizedDomainName = normalizeDomainName(options.domainName);
500
- try {
501
- const miningPreemption = await pauseMiningForWalletMutation({
502
- paths,
503
- reason: "wallet-register",
504
- });
505
- const readContext = await (options.openReadContext ?? openWalletReadContext)({
506
- dataDir: options.dataDir,
507
- databasePath: options.databasePath,
508
- secretProvider: provider,
509
- walletControlLockHeld: true,
510
- paths,
511
- });
512
- try {
493
+ const execution = await executeWalletMutationOperation({
494
+ ...options,
495
+ controlLockPurpose: "wallet-register",
496
+ preemptionReason: "wallet-register",
497
+ async resolveOperation(readContext) {
513
498
  assertWalletMutationContextReady(readContext, "wallet_register");
514
499
  const state = readContext.localState.state;
515
500
  const senderResolution = resolveRegisterSender(readContext, normalizedDomainName, options.fromIdentity);
516
- const intentFingerprintHex = createRegisterIntentFingerprint({
517
- walletRootId: state.walletRootId,
518
- domainName: normalizedDomainName,
519
- registerKind: senderResolution.registerKind,
520
- senderScriptPubKeyHex: senderResolution.sender.scriptPubKeyHex,
521
- });
501
+ if (lookupDomain(readContext.snapshot.state, normalizedDomainName) !== null) {
502
+ throw new Error("wallet_register_domain_already_registered");
503
+ }
504
+ if (readContext.snapshot.state.consensus.nextDomainId === 0xffff_ffff) {
505
+ throw new Error("wallet_register_next_domain_id_exhausted");
506
+ }
522
507
  const rootPriceSats = computeRootRegistrationPriceSats(normalizedDomainName);
523
508
  const resolvedSummary = createRegisterResolvedSummary({
524
509
  registerKind: senderResolution.registerKind,
@@ -528,265 +513,169 @@ export async function registerDomain(options) {
528
513
  economicEffectKind: senderResolution.registerKind === "root" ? "treasury-payment" : "cog-burn",
529
514
  economicEffectAmount: senderResolution.registerKind === "root" ? rootPriceSats : SUBDOMAIN_REGISTRATION_FEE_COGTOSHI,
530
515
  });
531
- const node = await (options.attachService ?? attachOrStartManagedBitcoindService)({
532
- dataDir: options.dataDir,
533
- chain: "main",
534
- startHeight: 0,
535
- walletRootId: state.walletRootId,
536
- });
537
- const rpc = (options.rpcFactory ?? createRpcClient)(node.rpc);
538
- const walletName = state.managedCoreWallet.walletName;
539
- const feeSelection = await resolveWalletMutationFeeSelection({
540
- rpc,
541
- feeRateSatVb: options.feeRateSatVb ?? null,
516
+ const genesis = await (options.loadGenesisParameters ?? loadBundledGenesisParameters)();
517
+ return {
518
+ state,
519
+ normalizedDomainName,
520
+ senderResolution,
521
+ rootPriceSats,
522
+ resolvedSummary,
523
+ genesis,
524
+ };
525
+ },
526
+ createIntentFingerprint(operation) {
527
+ return createRegisterIntentFingerprint({
528
+ walletRootId: operation.state.walletRootId,
529
+ domainName: operation.normalizedDomainName,
530
+ registerKind: operation.senderResolution.registerKind,
531
+ senderScriptPubKeyHex: operation.senderResolution.sender.scriptPubKeyHex,
542
532
  });
543
- const existingMutation = findPendingMutationByIntent(state, intentFingerprintHex);
544
- let workingState = state;
545
- let replacementFixedInputs = null;
546
- if (existingMutation !== null) {
547
- const reconciled = await reconcilePendingRegisterMutation({
548
- state,
549
- mutation: existingMutation,
550
- provider,
551
- nowUnixMs,
552
- paths,
553
- rpc,
554
- walletName,
555
- context: readContext,
556
- sender: senderResolution.sender,
557
- });
558
- workingState = reconciled.state;
559
- if (reconciled.resolution === "confirmed" || reconciled.resolution === "live") {
560
- const reuse = await resolvePendingMutationReuseDecision({
561
- rpc,
562
- walletName,
563
- mutation: reconciled.mutation,
564
- nextFeeSelection: feeSelection,
565
- });
566
- if (reuse.reuseExisting) {
567
- return {
568
- domainName: normalizedDomainName,
569
- registerKind: senderResolution.registerKind,
570
- parentDomainName: senderResolution.parentDomainName,
571
- senderSelector: senderResolution.senderSelector,
572
- senderLocalIndex: senderResolution.sender.localIndex,
573
- senderScriptPubKeyHex: senderResolution.sender.scriptPubKeyHex,
574
- senderAddress: senderResolution.sender.address,
575
- economicEffectKind: senderResolution.registerKind === "root" ? "treasury-payment" : "cog-burn",
576
- economicEffectAmount: senderResolution.registerKind === "root" ? rootPriceSats : SUBDOMAIN_REGISTRATION_FEE_COGTOSHI,
577
- resolved: resolvedSummary,
578
- txid: reconciled.mutation.attemptedTxid ?? "unknown",
579
- status: reconciled.resolution,
580
- reusedExisting: true,
581
- fees: reuse.fees,
582
- };
583
- }
584
- replacementFixedInputs = reuse.replacementFixedInputs;
585
- }
586
- if (reconciled.resolution === "repair-required") {
587
- throw new Error("wallet_register_repair_required");
588
- }
589
- }
590
- if (lookupDomain(readContext.snapshot.state, normalizedDomainName) !== null) {
591
- throw new Error("wallet_register_domain_already_registered");
592
- }
593
- if (readContext.snapshot.state.consensus.nextDomainId === 0xffff_ffff) {
594
- throw new Error("wallet_register_next_domain_id_exhausted");
533
+ },
534
+ async resolveExistingMutation({ operation, existingMutation, execution }) {
535
+ if (existingMutation === null) {
536
+ return { state: operation.state, replacementFixedInputs: null, result: null };
595
537
  }
596
- const genesis = await (options.loadGenesisParameters ?? loadBundledGenesisParameters)();
597
- const competingRootTxids = senderResolution.registerKind === "root"
598
- ? await findCompetingRootRegistrationTxids(rpc, normalizedDomainName)
599
- : [];
600
- if (senderResolution.registerKind === "root") {
538
+ return resolveExistingWalletMutation({
539
+ existingMutation,
540
+ execution,
541
+ repairRequiredErrorCode: "wallet_register_repair_required",
542
+ reconcileExistingMutation: (mutation) => reconcilePendingRegisterMutation({
543
+ state: operation.state,
544
+ mutation,
545
+ provider: execution.provider,
546
+ nowUnixMs: execution.nowUnixMs,
547
+ paths: execution.paths,
548
+ rpc: execution.rpc,
549
+ walletName: execution.walletName,
550
+ context: execution.readContext,
551
+ sender: operation.senderResolution.sender,
552
+ }),
553
+ createReuseResult: ({ mutation, resolution, fees }) => ({
554
+ domainName: operation.normalizedDomainName,
555
+ registerKind: operation.senderResolution.registerKind,
556
+ parentDomainName: operation.senderResolution.parentDomainName,
557
+ senderSelector: operation.senderResolution.senderSelector,
558
+ senderLocalIndex: operation.senderResolution.sender.localIndex,
559
+ senderScriptPubKeyHex: operation.senderResolution.sender.scriptPubKeyHex,
560
+ senderAddress: operation.senderResolution.sender.address,
561
+ economicEffectKind: operation.senderResolution.registerKind === "root" ? "treasury-payment" : "cog-burn",
562
+ economicEffectAmount: operation.senderResolution.registerKind === "root"
563
+ ? operation.rootPriceSats
564
+ : SUBDOMAIN_REGISTRATION_FEE_COGTOSHI,
565
+ resolved: operation.resolvedSummary,
566
+ txid: mutation.attemptedTxid ?? "unknown",
567
+ status: resolution,
568
+ reusedExisting: true,
569
+ fees,
570
+ }),
571
+ });
572
+ },
573
+ async confirm({ operation, execution }) {
574
+ if (operation.senderResolution.registerKind === "root") {
575
+ const competingRootTxids = await findCompetingRootRegistrationTxids(execution.rpc, operation.normalizedDomainName);
601
576
  if (competingRootTxids.length > 0 && !options.forceRace) {
602
577
  throw new Error("wallet_register_root_race_detected");
603
578
  }
604
- await confirmRootRegistration(options.prompter, normalizedDomainName, resolvedSummary, competingRootTxids.length > 0, options.assumeYes);
579
+ await confirmRootRegistration(options.prompter, operation.normalizedDomainName, operation.resolvedSummary, competingRootTxids.length > 0, options.assumeYes);
580
+ return;
605
581
  }
606
- else {
607
- await confirmSubdomainRegistration(options.prompter, normalizedDomainName, resolvedSummary, options.assumeYes);
608
- }
609
- let nextState = upsertPendingMutation(workingState, createDraftMutation({
610
- domainName: normalizedDomainName,
611
- parentDomainName: senderResolution.parentDomainName,
612
- sender: senderResolution.sender,
613
- registerKind: senderResolution.registerKind,
614
- intentFingerprintHex,
615
- nowUnixMs,
616
- feeSelection,
617
- existing: existingMutation,
618
- }));
619
- nextState = {
620
- ...nextState,
621
- stateRevision: nextState.stateRevision + 1,
622
- lastWrittenAtUnixMs: nowUnixMs,
582
+ await confirmSubdomainRegistration(options.prompter, operation.normalizedDomainName, operation.resolvedSummary, options.assumeYes);
583
+ },
584
+ createDraftMutation({ operation, existingMutation, execution, intentFingerprintHex }) {
585
+ return {
586
+ mutation: createDraftMutation({
587
+ domainName: operation.normalizedDomainName,
588
+ parentDomainName: operation.senderResolution.parentDomainName,
589
+ sender: operation.senderResolution.sender,
590
+ registerKind: operation.senderResolution.registerKind,
591
+ intentFingerprintHex,
592
+ nowUnixMs: execution.nowUnixMs,
593
+ feeSelection: execution.feeSelection,
594
+ existing: existingMutation,
595
+ }),
596
+ prepared: null,
623
597
  };
624
- await saveWalletStatePreservingUnlock({
625
- state: nextState,
626
- provider,
627
- nowUnixMs,
628
- paths,
629
- });
630
- const allUtxos = await rpc.listUnspent(walletName, 1);
598
+ },
599
+ async build({ operation, state, execution, replacementFixedInputs }) {
631
600
  const plan = buildRegisterPlan({
632
- context: readContext,
633
- state: nextState,
634
- allUtxos,
635
- sender: senderResolution.sender,
636
- registerKind: senderResolution.registerKind,
637
- domainName: normalizedDomainName,
638
- parentDomainName: senderResolution.parentDomainName,
639
- treasuryAddress: genesis.treasuryAddress,
640
- treasuryScriptPubKeyHex: Buffer.from(genesis.treasuryScriptPubKey).toString("hex"),
641
- rootPriceSats,
601
+ context: execution.readContext,
602
+ state,
603
+ allUtxos: await execution.rpc.listUnspent(execution.walletName, 1),
604
+ sender: operation.senderResolution.sender,
605
+ registerKind: operation.senderResolution.registerKind,
606
+ domainName: operation.normalizedDomainName,
607
+ parentDomainName: operation.senderResolution.parentDomainName,
608
+ treasuryAddress: operation.genesis.treasuryAddress,
609
+ treasuryScriptPubKeyHex: Buffer.from(operation.genesis.treasuryScriptPubKey).toString("hex"),
610
+ rootPriceSats: operation.rootPriceSats,
642
611
  });
643
- const built = await buildRegisterTransaction({
644
- rpc,
645
- walletName,
646
- state: nextState,
612
+ return buildRegisterTransaction({
613
+ rpc: execution.rpc,
614
+ walletName: execution.walletName,
615
+ state,
647
616
  plan: {
648
617
  ...plan,
649
618
  fixedInputs: mergeFixedWalletInputs(plan.fixedInputs, replacementFixedInputs),
650
619
  },
651
- feeRateSatVb: feeSelection.feeRateSatVb,
652
- });
653
- const currentMutation = nextState.pendingMutations?.find((mutation) => mutation.intentFingerprintHex === intentFingerprintHex)
654
- ?? createDraftMutation({
655
- domainName: normalizedDomainName,
656
- parentDomainName: senderResolution.parentDomainName,
657
- sender: senderResolution.sender,
658
- registerKind: senderResolution.registerKind,
659
- intentFingerprintHex,
660
- nowUnixMs,
661
- feeSelection,
662
- });
663
- const broadcastingMutation = updateMutationRecord(currentMutation, "broadcasting", nowUnixMs, {
664
- attemptedTxid: built.txid,
665
- attemptedWtxid: built.wtxid,
666
- temporaryBuilderLockedOutpoints: built.temporaryBuilderLockedOutpoints,
620
+ feeRateSatVb: execution.feeSelection.feeRateSatVb,
667
621
  });
668
- nextState = {
669
- ...upsertPendingMutation(nextState, broadcastingMutation),
670
- stateRevision: nextState.stateRevision + 1,
671
- lastWrittenAtUnixMs: nowUnixMs,
672
- };
673
- await saveWalletStatePreservingUnlock({
674
- state: nextState,
675
- provider,
676
- nowUnixMs,
677
- paths,
678
- });
679
- const bestHeight = (await rpc.getBlockchainInfo()).blocks;
680
- if (readContext.snapshot?.tip?.height !== bestHeight) {
681
- await unlockTemporaryBuilderLocks(rpc, walletName, built.temporaryBuilderLockedOutpoints);
682
- throw new Error("wallet_register_tip_mismatch");
683
- }
684
- let accepted = false;
685
- try {
686
- await rpc.sendRawTransaction(built.rawHex);
687
- accepted = true;
688
- }
689
- catch (error) {
690
- if (isAlreadyAcceptedError(error)) {
691
- accepted = true;
692
- }
693
- else if (isBroadcastUnknownError(error)) {
694
- const unknownMutation = updateMutationRecord(broadcastingMutation, "broadcast-unknown", nowUnixMs, {
695
- attemptedTxid: built.txid,
696
- attemptedWtxid: built.wtxid,
697
- temporaryBuilderLockedOutpoints: built.temporaryBuilderLockedOutpoints,
698
- });
699
- nextState = {
700
- ...upsertPendingMutation(nextState, unknownMutation),
701
- stateRevision: nextState.stateRevision + 1,
702
- lastWrittenAtUnixMs: nowUnixMs,
703
- };
704
- await saveWalletStatePreservingUnlock({
705
- state: nextState,
706
- provider,
707
- nowUnixMs,
708
- paths,
622
+ },
623
+ publish({ operation, state, execution, built, mutation }) {
624
+ return publishWalletMutation({
625
+ rpc: execution.rpc,
626
+ walletName: execution.walletName,
627
+ snapshotHeight: execution.readContext.snapshot?.tip?.height ?? null,
628
+ built,
629
+ mutation,
630
+ state,
631
+ provider: execution.provider,
632
+ nowUnixMs: execution.nowUnixMs,
633
+ paths: execution.paths,
634
+ errorPrefix: "wallet_register",
635
+ async afterAccepted({ state: acceptedState, broadcastingMutation, built, nowUnixMs }) {
636
+ const finalStatus = getMutationStatusAfterAcceptance({
637
+ snapshot: execution.readContext.snapshot,
638
+ domainName: operation.normalizedDomainName,
639
+ senderScriptPubKeyHex: operation.senderResolution.sender.scriptPubKeyHex,
709
640
  });
710
- throw new Error("wallet_register_broadcast_unknown");
711
- }
712
- else {
713
- await unlockTemporaryBuilderLocks(rpc, walletName, built.temporaryBuilderLockedOutpoints);
714
- const canceledMutation = updateMutationRecord(broadcastingMutation, "canceled", nowUnixMs, {
641
+ const finalMutation = updateMutationRecord(broadcastingMutation, finalStatus, nowUnixMs, {
715
642
  attemptedTxid: built.txid,
716
643
  attemptedWtxid: built.wtxid,
717
644
  temporaryBuilderLockedOutpoints: [],
718
645
  });
719
- nextState = {
720
- ...upsertPendingMutation(nextState, canceledMutation),
721
- stateRevision: nextState.stateRevision + 1,
722
- lastWrittenAtUnixMs: nowUnixMs,
646
+ return {
647
+ state: reserveLocalDomainRecord({
648
+ state: upsertPendingMutation(acceptedState, finalMutation),
649
+ domainName: operation.normalizedDomainName,
650
+ sender: operation.senderResolution.sender,
651
+ nowUnixMs,
652
+ }),
653
+ mutation: finalMutation,
654
+ status: finalStatus,
723
655
  };
724
- await saveWalletStatePreservingUnlock({
725
- state: nextState,
726
- provider,
727
- nowUnixMs,
728
- paths,
729
- });
730
- throw error;
731
- }
732
- }
733
- if (!accepted) {
734
- throw new Error("wallet_register_broadcast_failed");
735
- }
736
- await unlockTemporaryBuilderLocks(rpc, walletName, built.temporaryBuilderLockedOutpoints);
737
- const finalStatus = getMutationStatusAfterAcceptance({
738
- snapshot: readContext.snapshot,
739
- domainName: normalizedDomainName,
740
- senderScriptPubKeyHex: senderResolution.sender.scriptPubKeyHex,
741
- });
742
- const finalMutation = updateMutationRecord(broadcastingMutation, finalStatus, nowUnixMs, {
743
- attemptedTxid: built.txid,
744
- attemptedWtxid: built.wtxid,
745
- temporaryBuilderLockedOutpoints: [],
746
- });
747
- nextState = reserveLocalDomainRecord({
748
- state: upsertPendingMutation(nextState, finalMutation),
749
- domainName: normalizedDomainName,
750
- sender: senderResolution.sender,
751
- nowUnixMs,
752
- });
753
- nextState = {
754
- ...nextState,
755
- stateRevision: nextState.stateRevision + 1,
756
- lastWrittenAtUnixMs: nowUnixMs,
757
- };
758
- await saveWalletStatePreservingUnlock({
759
- state: nextState,
760
- provider,
761
- nowUnixMs,
762
- paths,
656
+ },
763
657
  });
658
+ },
659
+ createResult({ operation, mutation, built, status, reusedExisting, fees }) {
764
660
  return {
765
- domainName: normalizedDomainName,
766
- registerKind: senderResolution.registerKind,
767
- parentDomainName: senderResolution.parentDomainName,
768
- senderSelector: senderResolution.senderSelector,
769
- senderLocalIndex: senderResolution.sender.localIndex,
770
- senderScriptPubKeyHex: senderResolution.sender.scriptPubKeyHex,
771
- senderAddress: senderResolution.sender.address,
772
- economicEffectKind: senderResolution.registerKind === "root" ? "treasury-payment" : "cog-burn",
773
- economicEffectAmount: senderResolution.registerKind === "root" ? rootPriceSats : SUBDOMAIN_REGISTRATION_FEE_COGTOSHI,
774
- resolved: resolvedSummary,
775
- txid: built.txid,
776
- status: finalStatus,
777
- reusedExisting: false,
778
- fees: createBuiltWalletMutationFeeSummary({
779
- selection: feeSelection,
780
- built,
781
- }),
661
+ domainName: operation.normalizedDomainName,
662
+ registerKind: operation.senderResolution.registerKind,
663
+ parentDomainName: operation.senderResolution.parentDomainName,
664
+ senderSelector: operation.senderResolution.senderSelector,
665
+ senderLocalIndex: operation.senderResolution.sender.localIndex,
666
+ senderScriptPubKeyHex: operation.senderResolution.sender.scriptPubKeyHex,
667
+ senderAddress: operation.senderResolution.sender.address,
668
+ economicEffectKind: operation.senderResolution.registerKind === "root" ? "treasury-payment" : "cog-burn",
669
+ economicEffectAmount: operation.senderResolution.registerKind === "root"
670
+ ? operation.rootPriceSats
671
+ : SUBDOMAIN_REGISTRATION_FEE_COGTOSHI,
672
+ resolved: operation.resolvedSummary,
673
+ txid: mutation.attemptedTxid ?? built?.txid ?? "unknown",
674
+ status: status,
675
+ reusedExisting,
676
+ fees,
782
677
  };
783
- }
784
- finally {
785
- await readContext.close();
786
- await miningPreemption.release();
787
- }
788
- }
789
- finally {
790
- await controlLock.release();
791
- }
678
+ },
679
+ });
680
+ return execution.result;
792
681
  }