@cogcoin/client 1.1.6 → 1.1.8

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 (125) hide show
  1. package/README.md +2 -2
  2. package/dist/bitcoind/indexer-daemon.js +29 -79
  3. package/dist/bitcoind/managed-runtime/bitcoind-runtime.d.ts +20 -0
  4. package/dist/bitcoind/managed-runtime/bitcoind-runtime.js +74 -0
  5. package/dist/bitcoind/managed-runtime/bitcoind-status.d.ts +11 -0
  6. package/dist/bitcoind/managed-runtime/bitcoind-status.js +44 -0
  7. package/dist/bitcoind/managed-runtime/indexer-runtime.d.ts +15 -0
  8. package/dist/bitcoind/managed-runtime/indexer-runtime.js +82 -0
  9. package/dist/bitcoind/managed-runtime/types.d.ts +40 -0
  10. package/dist/bitcoind/node.d.ts +2 -2
  11. package/dist/bitcoind/node.js +2 -2
  12. package/dist/bitcoind/rpc.d.ts +2 -1
  13. package/dist/bitcoind/rpc.js +53 -3
  14. package/dist/bitcoind/service.js +47 -127
  15. package/dist/cli/command-registry.d.ts +1 -1
  16. package/dist/cli/command-registry.js +2 -64
  17. package/dist/cli/commands/client-admin.js +3 -18
  18. package/dist/cli/commands/mining-runtime.js +4 -60
  19. package/dist/cli/commands/wallet-admin.js +6 -6
  20. package/dist/cli/context.js +1 -3
  21. package/dist/cli/mining-json.d.ts +1 -22
  22. package/dist/cli/mining-json.js +0 -23
  23. package/dist/cli/output.js +16 -2
  24. package/dist/cli/parse.js +0 -2
  25. package/dist/cli/preview-json.d.ts +1 -22
  26. package/dist/cli/preview-json.js +0 -19
  27. package/dist/cli/types.d.ts +1 -3
  28. package/dist/cli/wallet-format.js +1 -1
  29. package/dist/cli/workflow-hints.d.ts +1 -2
  30. package/dist/cli/workflow-hints.js +5 -8
  31. package/dist/wallet/lifecycle/context.js +0 -1
  32. package/dist/wallet/lifecycle/repair-mining.d.ts +1 -5
  33. package/dist/wallet/lifecycle/repair-mining.js +5 -39
  34. package/dist/wallet/lifecycle/repair.js +0 -3
  35. package/dist/wallet/lifecycle/setup.js +10 -8
  36. package/dist/wallet/lifecycle/types.d.ts +1 -4
  37. package/dist/wallet/managed-core-wallet.d.ts +2 -0
  38. package/dist/wallet/managed-core-wallet.js +27 -1
  39. package/dist/wallet/mining/candidate.d.ts +1 -0
  40. package/dist/wallet/mining/candidate.js +38 -6
  41. package/dist/wallet/mining/competitiveness.d.ts +1 -0
  42. package/dist/wallet/mining/competitiveness.js +6 -0
  43. package/dist/wallet/mining/cycle.d.ts +2 -0
  44. package/dist/wallet/mining/cycle.js +14 -4
  45. package/dist/wallet/mining/engine-state.js +10 -0
  46. package/dist/wallet/mining/engine-types.d.ts +1 -0
  47. package/dist/wallet/mining/index.d.ts +1 -1
  48. package/dist/wallet/mining/index.js +1 -1
  49. package/dist/wallet/mining/publish.d.ts +3 -0
  50. package/dist/wallet/mining/publish.js +78 -6
  51. package/dist/wallet/mining/runner.d.ts +0 -32
  52. package/dist/wallet/mining/runner.js +59 -104
  53. package/dist/wallet/mining/stop.d.ts +7 -0
  54. package/dist/wallet/mining/stop.js +23 -0
  55. package/dist/wallet/mining/supervisor.d.ts +2 -36
  56. package/dist/wallet/mining/supervisor.js +139 -246
  57. package/dist/wallet/mining/visualizer-sync.js +79 -15
  58. package/dist/wallet/read/context.d.ts +1 -5
  59. package/dist/wallet/read/context.js +21 -205
  60. package/dist/wallet/read/managed-services.d.ts +33 -0
  61. package/dist/wallet/read/managed-services.js +222 -0
  62. package/dist/wallet/reset/artifacts.d.ts +16 -0
  63. package/dist/wallet/reset/artifacts.js +141 -0
  64. package/dist/wallet/reset/execution.d.ts +38 -0
  65. package/dist/wallet/reset/execution.js +458 -0
  66. package/dist/wallet/reset/preflight.d.ts +7 -0
  67. package/dist/wallet/reset/preflight.js +116 -0
  68. package/dist/wallet/reset/preview.d.ts +2 -0
  69. package/dist/wallet/reset/preview.js +50 -0
  70. package/dist/wallet/reset/process-cleanup.d.ts +12 -0
  71. package/dist/wallet/reset/process-cleanup.js +179 -0
  72. package/dist/wallet/reset/types.d.ts +189 -0
  73. package/dist/wallet/reset/types.js +1 -0
  74. package/dist/wallet/reset.d.ts +4 -119
  75. package/dist/wallet/reset.js +4 -882
  76. package/dist/wallet/state/client-password/bootstrap.d.ts +2 -0
  77. package/dist/wallet/state/client-password/bootstrap.js +3 -0
  78. package/dist/wallet/state/client-password/context.d.ts +10 -0
  79. package/dist/wallet/state/client-password/context.js +46 -0
  80. package/dist/wallet/state/client-password/crypto.d.ts +34 -0
  81. package/dist/wallet/state/client-password/crypto.js +117 -0
  82. package/dist/wallet/state/client-password/files.d.ts +10 -0
  83. package/dist/wallet/state/client-password/files.js +109 -0
  84. package/dist/wallet/state/client-password/legacy-cleanup.d.ts +11 -0
  85. package/dist/wallet/state/client-password/legacy-cleanup.js +338 -0
  86. package/dist/wallet/state/client-password/messages.d.ts +3 -0
  87. package/dist/wallet/state/client-password/messages.js +9 -0
  88. package/dist/wallet/state/client-password/migration.d.ts +4 -0
  89. package/dist/wallet/state/client-password/migration.js +32 -0
  90. package/dist/wallet/state/client-password/prompts.d.ts +12 -0
  91. package/dist/wallet/state/client-password/prompts.js +79 -0
  92. package/dist/wallet/state/client-password/protected-secrets.d.ts +13 -0
  93. package/dist/wallet/state/client-password/protected-secrets.js +90 -0
  94. package/dist/wallet/state/client-password/readiness.d.ts +4 -0
  95. package/dist/wallet/state/client-password/readiness.js +48 -0
  96. package/dist/wallet/state/client-password/references.d.ts +1 -0
  97. package/dist/wallet/state/client-password/references.js +56 -0
  98. package/dist/wallet/state/client-password/rotation.d.ts +6 -0
  99. package/dist/wallet/state/client-password/rotation.js +98 -0
  100. package/dist/wallet/state/client-password/session-policy.d.ts +6 -0
  101. package/dist/wallet/state/client-password/session-policy.js +28 -0
  102. package/dist/wallet/state/client-password/session.d.ts +19 -0
  103. package/dist/wallet/state/client-password/session.js +170 -0
  104. package/dist/wallet/state/client-password/setup.d.ts +8 -0
  105. package/dist/wallet/state/client-password/setup.js +49 -0
  106. package/dist/wallet/state/client-password/types.d.ts +82 -0
  107. package/dist/wallet/state/client-password/types.js +5 -0
  108. package/dist/wallet/state/client-password.d.ts +7 -38
  109. package/dist/wallet/state/client-password.js +52 -937
  110. package/dist/wallet/tx/anchor.js +123 -216
  111. package/dist/wallet/tx/cog.js +294 -489
  112. package/dist/wallet/tx/common.d.ts +2 -0
  113. package/dist/wallet/tx/common.js +2 -0
  114. package/dist/wallet/tx/domain-admin.js +111 -220
  115. package/dist/wallet/tx/domain-market.js +401 -681
  116. package/dist/wallet/tx/executor.d.ts +176 -0
  117. package/dist/wallet/tx/executor.js +302 -0
  118. package/dist/wallet/tx/field.js +109 -215
  119. package/dist/wallet/tx/register.js +158 -269
  120. package/dist/wallet/tx/reputation.js +120 -227
  121. package/package.json +1 -1
  122. package/dist/wallet/mining/worker-main.d.ts +0 -1
  123. package/dist/wallet/mining/worker-main.js +0 -17
  124. package/dist/wallet/state/client-password-agent.d.ts +0 -1
  125. package/dist/wallet/state/client-password-agent.js +0 -211
@@ -3,15 +3,15 @@ import { encodeSentence } from "@cogcoin/scoring";
3
3
  import { getBalance, 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 { serializeRepCommit, serializeRepRevoke, validateDomainName, } 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, unlockTemporaryBuilderLocks, updateMutationRecord, } from "./common.js";
12
11
  import { confirmTypedAcknowledgement as confirmSharedTypedAcknowledgement, confirmYesNo as confirmSharedYesNo, } from "./confirm.js";
12
+ import { executeWalletMutationOperation, persistWalletMutationState, publishWalletMutation, resolveExistingWalletMutation, } from "./executor.js";
13
13
  import { getCanonicalIdentitySelector } from "./identity-selector.js";
14
- import { findPendingMutationByIntent, upsertPendingMutation } from "./journal.js";
14
+ import { upsertPendingMutation } from "./journal.js";
15
15
  function normalizeDomainName(domainName, errorCode) {
16
16
  const normalized = domainName.trim().toLowerCase();
17
17
  if (normalized.length === 0) {
@@ -215,18 +215,7 @@ function createDraftMutation(options) {
215
215
  };
216
216
  }
217
217
  async function saveUpdatedMutationState(options) {
218
- const nextState = {
219
- ...options.state,
220
- stateRevision: options.state.stateRevision + 1,
221
- lastWrittenAtUnixMs: options.nowUnixMs,
222
- };
223
- await saveWalletStatePreservingUnlock({
224
- state: nextState,
225
- provider: options.provider,
226
- nowUnixMs: options.nowUnixMs,
227
- paths: options.paths,
228
- });
229
- return nextState;
218
+ return persistWalletMutationState(options);
230
219
  }
231
220
  function mutationNeedsRepair(mutation, context) {
232
221
  if (context.snapshot === null || mutation.recipientDomainName == null) {
@@ -381,75 +370,6 @@ async function encodeReviewText(reviewText, errorPrefix) {
381
370
  throw new Error(error instanceof Error ? `${errorPrefix}_invalid_review_${error.message}` : `${errorPrefix}_invalid_review`);
382
371
  });
383
372
  }
384
- async function sendBuiltTransaction(options) {
385
- let nextState = options.state;
386
- const broadcasting = updateMutationRecord(options.mutation, "broadcasting", options.nowUnixMs, {
387
- attemptedTxid: options.built.txid,
388
- attemptedWtxid: options.built.wtxid,
389
- temporaryBuilderLockedOutpoints: options.built.temporaryBuilderLockedOutpoints,
390
- });
391
- nextState = upsertPendingMutation(nextState, broadcasting);
392
- nextState = await saveUpdatedMutationState({
393
- state: nextState,
394
- provider: options.provider,
395
- nowUnixMs: options.nowUnixMs,
396
- paths: options.paths,
397
- });
398
- if (options.snapshotHeight !== null && options.snapshotHeight !== (await options.rpc.getBlockchainInfo()).blocks) {
399
- await unlockTemporaryBuilderLocks(options.rpc, options.walletName, options.built.temporaryBuilderLockedOutpoints);
400
- throw new Error(`${options.errorPrefix}_tip_mismatch`);
401
- }
402
- try {
403
- await options.rpc.sendRawTransaction(options.built.rawHex);
404
- }
405
- catch (error) {
406
- if (!isAlreadyAcceptedError(error)) {
407
- if (isBroadcastUnknownError(error)) {
408
- const unknown = updateMutationRecord(broadcasting, "broadcast-unknown", options.nowUnixMs, {
409
- attemptedTxid: options.built.txid,
410
- attemptedWtxid: options.built.wtxid,
411
- temporaryBuilderLockedOutpoints: options.built.temporaryBuilderLockedOutpoints,
412
- });
413
- nextState = upsertPendingMutation(nextState, unknown);
414
- nextState = await saveUpdatedMutationState({
415
- state: nextState,
416
- provider: options.provider,
417
- nowUnixMs: options.nowUnixMs,
418
- paths: options.paths,
419
- });
420
- throw new Error(`${options.errorPrefix}_broadcast_unknown`);
421
- }
422
- await unlockTemporaryBuilderLocks(options.rpc, options.walletName, options.built.temporaryBuilderLockedOutpoints);
423
- const canceled = updateMutationRecord(broadcasting, "canceled", options.nowUnixMs, {
424
- attemptedTxid: options.built.txid,
425
- attemptedWtxid: options.built.wtxid,
426
- temporaryBuilderLockedOutpoints: [],
427
- });
428
- nextState = upsertPendingMutation(nextState, canceled);
429
- nextState = await saveUpdatedMutationState({
430
- state: nextState,
431
- provider: options.provider,
432
- nowUnixMs: options.nowUnixMs,
433
- paths: options.paths,
434
- });
435
- throw error;
436
- }
437
- }
438
- await unlockTemporaryBuilderLocks(options.rpc, options.walletName, options.built.temporaryBuilderLockedOutpoints);
439
- const live = updateMutationRecord(broadcasting, "live", options.nowUnixMs, {
440
- attemptedTxid: options.built.txid,
441
- attemptedWtxid: options.built.wtxid,
442
- temporaryBuilderLockedOutpoints: [],
443
- });
444
- nextState = upsertPendingMutation(nextState, live);
445
- nextState = await saveUpdatedMutationState({
446
- state: nextState,
447
- provider: options.provider,
448
- nowUnixMs: options.nowUnixMs,
449
- paths: options.paths,
450
- });
451
- return { state: nextState, mutation: live };
452
- }
453
373
  async function submitReputationMutation(options) {
454
374
  if (!options.prompter.isInteractive && options.assumeYes !== true) {
455
375
  throw new Error(`${options.errorPrefix}_requires_tty`);
@@ -457,26 +377,11 @@ async function submitReputationMutation(options) {
457
377
  if (options.amountCogtoshi <= 0n) {
458
378
  throw new Error(`${options.errorPrefix}_invalid_amount`);
459
379
  }
460
- const provider = options.provider ?? createDefaultWalletSecretProvider();
461
- const nowUnixMs = options.nowUnixMs ?? Date.now();
462
- const paths = options.paths ?? resolveWalletRuntimePathsForTesting();
463
- const controlLock = await acquireFileLock(paths.walletControlLockPath, {
464
- purpose: options.errorPrefix,
465
- walletRootId: null,
466
- });
467
- try {
468
- const miningPreemption = await pauseMiningForWalletMutation({
469
- paths,
470
- reason: options.errorPrefix,
471
- });
472
- const readContext = await (options.openReadContext ?? openWalletReadContext)({
473
- dataDir: options.dataDir,
474
- databasePath: options.databasePath,
475
- secretProvider: provider,
476
- walletControlLockHeld: true,
477
- paths,
478
- });
479
- try {
380
+ const execution = await executeWalletMutationOperation({
381
+ ...options,
382
+ controlLockPurpose: options.errorPrefix,
383
+ preemptionReason: options.errorPrefix,
384
+ async resolveOperation(readContext) {
480
385
  const normalizedSourceDomainName = normalizeDomainName(options.sourceDomainName, `${options.errorPrefix}_missing_source_domain`);
481
386
  const normalizedTargetDomainName = normalizeDomainName(options.targetDomainName, `${options.errorPrefix}_missing_target_domain`);
482
387
  const operation = resolveReputationOperation(readContext, normalizedSourceDomainName, normalizedTargetDomainName, options.errorPrefix);
@@ -493,159 +398,147 @@ async function submitReputationMutation(options) {
493
398
  }
494
399
  const review = await encodeReviewText(options.reviewText, options.errorPrefix);
495
400
  const selfStake = operation.sourceDomain.domainId === operation.targetDomain.domainId;
496
- const resolved = createResolvedReputationSummary({
497
- kind: options.kind === "rep-give" ? "give" : "revoke",
498
- sender: operation.sender,
499
- senderSelector: operation.senderSelector,
500
- amountCogtoshi: options.amountCogtoshi,
401
+ return {
402
+ ...operation,
403
+ normalizedSourceDomainName,
404
+ normalizedTargetDomainName,
501
405
  review,
502
- selfStake,
503
- });
504
- const intentFingerprintHex = createIntentFingerprint([
406
+ resolved: createResolvedReputationSummary({
407
+ kind: options.kind === "rep-give" ? "give" : "revoke",
408
+ sender: operation.sender,
409
+ senderSelector: operation.senderSelector,
410
+ amountCogtoshi: options.amountCogtoshi,
411
+ review,
412
+ selfStake,
413
+ }),
414
+ };
415
+ },
416
+ createIntentFingerprint(operation) {
417
+ return createIntentFingerprint([
505
418
  options.kind,
506
419
  operation.state.walletRootId,
507
420
  operation.sourceDomain.name,
508
421
  operation.targetDomain.name,
509
422
  options.amountCogtoshi,
510
- review.payloadHex ?? "",
423
+ operation.review.payloadHex ?? "",
511
424
  ]);
512
- const node = await (options.attachService ?? attachOrStartManagedBitcoindService)({
513
- dataDir: options.dataDir,
514
- chain: "main",
515
- startHeight: 0,
516
- walletRootId: operation.state.walletRootId,
517
- });
518
- const rpc = (options.rpcFactory ?? createRpcClient)(node.rpc);
519
- const walletName = operation.state.managedCoreWallet.walletName;
520
- const feeSelection = await resolveWalletMutationFeeSelection({
521
- rpc,
522
- feeRateSatVb: options.feeRateSatVb ?? null,
523
- });
524
- const existingMutation = findPendingMutationByIntent(operation.state, intentFingerprintHex);
525
- let workingState = operation.state;
526
- let replacementFixedInputs = null;
527
- if (existingMutation !== null) {
528
- const reconciled = await reconcilePendingReputationMutation({
425
+ },
426
+ async resolveExistingMutation({ operation, existingMutation, execution }) {
427
+ if (existingMutation === null) {
428
+ return {
529
429
  state: operation.state,
530
- mutation: existingMutation,
531
- provider,
532
- nowUnixMs,
533
- paths,
534
- rpc,
535
- walletName,
536
- context: readContext,
537
- });
538
- workingState = reconciled.state;
539
- if (reconciled.resolution === "confirmed" || reconciled.resolution === "live") {
540
- const reuse = await resolvePendingMutationReuseDecision({
541
- rpc,
542
- walletName,
543
- mutation: reconciled.mutation,
544
- nextFeeSelection: feeSelection,
545
- });
546
- if (reuse.reuseExisting) {
547
- return {
548
- kind: options.kind === "rep-give" ? "give" : "revoke",
549
- sourceDomainName: normalizedSourceDomainName,
550
- targetDomainName: normalizedTargetDomainName,
551
- amountCogtoshi: options.amountCogtoshi,
552
- txid: reconciled.mutation.attemptedTxid ?? "unknown",
553
- status: reconciled.resolution,
554
- reusedExisting: true,
555
- reviewIncluded: review.payloadHex !== null,
556
- resolved,
557
- fees: reuse.fees,
558
- };
559
- }
560
- replacementFixedInputs = reuse.replacementFixedInputs;
561
- }
562
- if (reconciled.resolution === "repair-required") {
563
- throw new Error(`${options.errorPrefix}_repair_required`);
564
- }
430
+ replacementFixedInputs: null,
431
+ result: null,
432
+ };
565
433
  }
434
+ return resolveExistingWalletMutation({
435
+ existingMutation,
436
+ execution,
437
+ repairRequiredErrorCode: `${options.errorPrefix}_repair_required`,
438
+ reconcileExistingMutation: (mutation) => reconcilePendingReputationMutation({
439
+ state: operation.state,
440
+ mutation,
441
+ provider: execution.provider,
442
+ nowUnixMs: execution.nowUnixMs,
443
+ paths: execution.paths,
444
+ rpc: execution.rpc,
445
+ walletName: execution.walletName,
446
+ context: execution.readContext,
447
+ }),
448
+ createReuseResult: ({ mutation, resolution, fees }) => ({
449
+ kind: options.kind === "rep-give" ? "give" : "revoke",
450
+ sourceDomainName: operation.normalizedSourceDomainName,
451
+ targetDomainName: operation.normalizedTargetDomainName,
452
+ amountCogtoshi: options.amountCogtoshi,
453
+ txid: mutation.attemptedTxid ?? "unknown",
454
+ status: resolution,
455
+ reusedExisting: true,
456
+ reviewIncluded: operation.review.payloadHex !== null,
457
+ resolved: operation.resolved,
458
+ fees,
459
+ }),
460
+ });
461
+ },
462
+ async confirm({ operation }) {
566
463
  await confirmReputationMutation(options.prompter, {
567
464
  kind: options.kind === "rep-give" ? "give" : "revoke",
568
- sourceDomainName: normalizedSourceDomainName,
569
- targetDomainName: normalizedTargetDomainName,
465
+ sourceDomainName: operation.normalizedSourceDomainName,
466
+ targetDomainName: operation.normalizedTargetDomainName,
570
467
  amountCogtoshi: options.amountCogtoshi,
571
- reviewText: review.text,
572
- resolved,
468
+ reviewText: operation.review.text,
469
+ resolved: operation.resolved,
573
470
  assumeYes: options.assumeYes,
574
471
  });
575
- let nextState = upsertPendingMutation(workingState, createDraftMutation({
576
- kind: options.kind,
577
- sourceDomainName: normalizedSourceDomainName,
578
- targetDomainName: normalizedTargetDomainName,
579
- amountCogtoshi: options.amountCogtoshi,
580
- sender: operation.sender,
581
- intentFingerprintHex,
582
- nowUnixMs,
583
- reviewPayloadHex: review.payloadHex,
584
- feeSelection,
585
- existing: existingMutation,
586
- }));
587
- nextState = await saveUpdatedMutationState({
588
- state: nextState,
589
- provider,
590
- nowUnixMs,
591
- paths,
592
- });
472
+ },
473
+ createDraftMutation({ operation, existingMutation, execution, intentFingerprintHex }) {
474
+ return {
475
+ mutation: createDraftMutation({
476
+ kind: options.kind,
477
+ sourceDomainName: operation.normalizedSourceDomainName,
478
+ targetDomainName: operation.normalizedTargetDomainName,
479
+ amountCogtoshi: options.amountCogtoshi,
480
+ sender: operation.sender,
481
+ intentFingerprintHex,
482
+ nowUnixMs: execution.nowUnixMs,
483
+ reviewPayloadHex: operation.review.payloadHex,
484
+ feeSelection: execution.feeSelection,
485
+ existing: existingMutation,
486
+ }),
487
+ prepared: null,
488
+ };
489
+ },
490
+ async build({ operation, state, execution, replacementFixedInputs }) {
593
491
  const opReturnData = options.kind === "rep-give"
594
- ? serializeRepCommit(operation.sourceDomain.domainId, operation.targetDomain.domainId, options.amountCogtoshi, review.payload).opReturnData
595
- : serializeRepRevoke(operation.sourceDomain.domainId, operation.targetDomain.domainId, options.amountCogtoshi, review.payload).opReturnData;
492
+ ? serializeRepCommit(operation.sourceDomain.domainId, operation.targetDomain.domainId, options.amountCogtoshi, operation.review.payload).opReturnData
493
+ : serializeRepRevoke(operation.sourceDomain.domainId, operation.targetDomain.domainId, options.amountCogtoshi, operation.review.payload).opReturnData;
596
494
  const reputationPlan = buildPlanForReputationOperation({
597
- state: nextState,
598
- allUtxos: await rpc.listUnspent(walletName, 1),
495
+ state,
496
+ allUtxos: await execution.rpc.listUnspent(execution.walletName, 1),
599
497
  sender: operation.sender,
600
498
  opReturnData,
601
499
  errorPrefix: options.errorPrefix,
602
500
  });
603
- const built = await buildTransaction({
604
- rpc,
605
- walletName,
606
- state: nextState,
501
+ return buildTransaction({
502
+ rpc: execution.rpc,
503
+ walletName: execution.walletName,
504
+ state,
607
505
  plan: {
608
506
  ...reputationPlan,
609
507
  fixedInputs: mergeFixedWalletInputs(reputationPlan.fixedInputs, replacementFixedInputs),
610
508
  },
611
- feeRateSatVb: feeSelection.feeRateSatVb,
509
+ feeRateSatVb: execution.feeSelection.feeRateSatVb,
612
510
  });
613
- const final = await sendBuiltTransaction({
614
- rpc,
615
- walletName,
616
- snapshotHeight: readContext.snapshot?.tip?.height ?? null,
511
+ },
512
+ publish({ state, execution, built, mutation }) {
513
+ return publishWalletMutation({
514
+ rpc: execution.rpc,
515
+ walletName: execution.walletName,
516
+ snapshotHeight: execution.readContext.snapshot?.tip?.height ?? null,
617
517
  built,
618
- mutation: nextState.pendingMutations.find((mutation) => mutation.intentFingerprintHex === intentFingerprintHex),
619
- state: nextState,
620
- provider,
621
- nowUnixMs,
622
- paths,
518
+ mutation,
519
+ state,
520
+ provider: execution.provider,
521
+ nowUnixMs: execution.nowUnixMs,
522
+ paths: execution.paths,
623
523
  errorPrefix: options.errorPrefix,
624
524
  });
525
+ },
526
+ createResult({ operation, mutation, built, status, reusedExisting, fees }) {
625
527
  return {
626
528
  kind: options.kind === "rep-give" ? "give" : "revoke",
627
- sourceDomainName: normalizedSourceDomainName,
628
- targetDomainName: normalizedTargetDomainName,
529
+ sourceDomainName: operation.normalizedSourceDomainName,
530
+ targetDomainName: operation.normalizedTargetDomainName,
629
531
  amountCogtoshi: options.amountCogtoshi,
630
- txid: final.mutation.attemptedTxid ?? built.txid,
631
- status: "live",
632
- reusedExisting: false,
633
- reviewIncluded: review.payloadHex !== null,
634
- resolved,
635
- fees: createBuiltWalletMutationFeeSummary({
636
- selection: feeSelection,
637
- built,
638
- }),
532
+ txid: mutation.attemptedTxid ?? built?.txid ?? "unknown",
533
+ status: status,
534
+ reusedExisting,
535
+ reviewIncluded: operation.review.payloadHex !== null,
536
+ resolved: operation.resolved,
537
+ fees,
639
538
  };
640
- }
641
- finally {
642
- await readContext.close();
643
- await miningPreemption.release();
644
- }
645
- }
646
- finally {
647
- await controlLock.release();
648
- }
539
+ },
540
+ });
541
+ return execution.result;
649
542
  }
650
543
  export async function giveReputation(options) {
651
544
  return submitReputationMutation({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cogcoin/client",
3
- "version": "1.1.6",
3
+ "version": "1.1.8",
4
4
  "description": "Store-backed Cogcoin client with wallet flows, SQLite persistence, and managed Bitcoin Core integration.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1 +0,0 @@
1
- export {};
@@ -1,17 +0,0 @@
1
- import { runBackgroundMiningWorker } from "./runner.js";
2
- function readFlag(name) {
3
- const prefix = `--${name}=`;
4
- const match = process.argv.find((entry) => entry.startsWith(prefix));
5
- return match === undefined ? null : match.slice(prefix.length);
6
- }
7
- const dataDir = readFlag("data-dir");
8
- const databasePath = readFlag("database-path");
9
- const runId = readFlag("run-id");
10
- if (dataDir === null || databasePath === null || runId === null) {
11
- throw new Error("mining_worker_missing_args");
12
- }
13
- await runBackgroundMiningWorker({
14
- dataDir,
15
- databasePath,
16
- runId,
17
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,211 +0,0 @@
1
- import { createCipheriv, createDecipheriv, randomBytes } from "node:crypto";
2
- import net from "node:net";
3
- import { rm } from "node:fs/promises";
4
- function shouldRemoveAgentEndpointPath(endpoint) {
5
- return !endpoint.startsWith("\\\\.\\pipe\\");
6
- }
7
- function zeroizeBuffer(buffer) {
8
- if (buffer != null) {
9
- buffer.fill(0);
10
- }
11
- }
12
- function createAgentError(message) {
13
- return JSON.stringify({
14
- ok: false,
15
- error: message,
16
- });
17
- }
18
- async function readBootstrapConfig() {
19
- const endpoint = process.argv[2] ?? "";
20
- const unlockUntilUnixMs = Number(process.argv[3] ?? "");
21
- if (endpoint.length === 0 || !Number.isFinite(unlockUntilUnixMs)) {
22
- throw new Error("wallet_client_password_agent_bootstrap_invalid");
23
- }
24
- const raw = await new Promise((resolve, reject) => {
25
- let received = "";
26
- const onData = (chunk) => {
27
- received += chunk.toString("utf8");
28
- const newlineIndex = received.indexOf("\n");
29
- if (newlineIndex !== -1) {
30
- cleanup();
31
- resolve(received.slice(0, newlineIndex));
32
- }
33
- };
34
- const onEnd = () => {
35
- cleanup();
36
- reject(new Error("wallet_client_password_agent_bootstrap_missing"));
37
- };
38
- const onError = (error) => {
39
- cleanup();
40
- reject(error);
41
- };
42
- const cleanup = () => {
43
- process.stdin.off("data", onData);
44
- process.stdin.off("end", onEnd);
45
- process.stdin.off("error", onError);
46
- };
47
- process.stdin.on("data", onData);
48
- process.stdin.on("end", onEnd);
49
- process.stdin.on("error", onError);
50
- });
51
- const parsed = JSON.parse(raw);
52
- if (typeof parsed.derivedKeyBase64 !== "string") {
53
- throw new Error("wallet_client_password_agent_bootstrap_invalid");
54
- }
55
- return {
56
- endpoint,
57
- unlockUntilUnixMs,
58
- derivedKey: Buffer.from(parsed.derivedKeyBase64, "base64"),
59
- };
60
- }
61
- async function main() {
62
- const bootstrap = await readBootstrapConfig();
63
- let key = bootstrap.derivedKey;
64
- let unlockUntilUnixMs = bootstrap.unlockUntilUnixMs;
65
- let expiryTimer = null;
66
- const cleanupAndExit = async () => {
67
- if (expiryTimer !== null) {
68
- clearTimeout(expiryTimer);
69
- expiryTimer = null;
70
- }
71
- zeroizeBuffer(key);
72
- key = Buffer.alloc(0);
73
- if (shouldRemoveAgentEndpointPath(bootstrap.endpoint)) {
74
- await rm(bootstrap.endpoint, { force: true }).catch(() => undefined);
75
- }
76
- process.exit(0);
77
- };
78
- const refreshExpiry = () => {
79
- if (expiryTimer !== null) {
80
- clearTimeout(expiryTimer);
81
- }
82
- const remainingMs = Math.max(0, unlockUntilUnixMs - Date.now());
83
- expiryTimer = setTimeout(() => {
84
- void cleanupAndExit();
85
- }, remainingMs);
86
- expiryTimer.unref();
87
- };
88
- const encryptSecret = (secretBase64) => {
89
- const nonce = randomBytes(12);
90
- const cipher = createCipheriv("aes-256-gcm", key, nonce);
91
- const ciphertext = Buffer.concat([
92
- cipher.update(Buffer.from(secretBase64, "base64")),
93
- cipher.final(),
94
- ]);
95
- const tag = cipher.getAuthTag();
96
- return {
97
- nonce: nonce.toString("base64"),
98
- tag: tag.toString("base64"),
99
- ciphertext: ciphertext.toString("base64"),
100
- };
101
- };
102
- const decryptSecret = (options) => {
103
- const decipher = createDecipheriv("aes-256-gcm", key, Buffer.from(options.nonce, "base64"));
104
- decipher.setAuthTag(Buffer.from(options.tag, "base64"));
105
- return Buffer.concat([
106
- decipher.update(Buffer.from(options.ciphertext, "base64")),
107
- decipher.final(),
108
- ]).toString("base64");
109
- };
110
- const server = net.createServer((socket) => {
111
- let received = "";
112
- const send = (payload) => {
113
- socket.end(`${JSON.stringify(payload)}\n`);
114
- };
115
- socket.on("data", (chunk) => {
116
- received += chunk.toString("utf8");
117
- const newlineIndex = received.indexOf("\n");
118
- if (newlineIndex === -1) {
119
- return;
120
- }
121
- let parsed;
122
- try {
123
- parsed = JSON.parse(received.slice(0, newlineIndex));
124
- }
125
- catch {
126
- send({ ok: false, error: "wallet_client_password_agent_protocol_error" });
127
- return;
128
- }
129
- try {
130
- switch (parsed.command) {
131
- case "status":
132
- send({ ok: true, unlockUntilUnixMs });
133
- return;
134
- case "lock":
135
- send({ ok: true, unlockUntilUnixMs: null });
136
- setImmediate(() => {
137
- void cleanupAndExit();
138
- });
139
- return;
140
- case "refresh":
141
- if (!Number.isFinite(parsed.unlockUntilUnixMs)) {
142
- send({ ok: false, error: "wallet_client_password_agent_protocol_error" });
143
- return;
144
- }
145
- unlockUntilUnixMs = Number(parsed.unlockUntilUnixMs);
146
- refreshExpiry();
147
- send({ ok: true, unlockUntilUnixMs });
148
- return;
149
- case "encrypt":
150
- if (typeof parsed.secretBase64 !== "string") {
151
- send({ ok: false, error: "wallet_client_password_agent_protocol_error" });
152
- return;
153
- }
154
- send({
155
- ok: true,
156
- unlockUntilUnixMs,
157
- envelope: encryptSecret(parsed.secretBase64),
158
- });
159
- return;
160
- case "decrypt":
161
- if (typeof parsed.envelope?.nonce !== "string"
162
- || typeof parsed.envelope?.tag !== "string"
163
- || typeof parsed.envelope?.ciphertext !== "string") {
164
- send({ ok: false, error: "wallet_client_password_agent_protocol_error" });
165
- return;
166
- }
167
- send({
168
- ok: true,
169
- unlockUntilUnixMs,
170
- secretBase64: decryptSecret({
171
- nonce: parsed.envelope.nonce,
172
- tag: parsed.envelope.tag,
173
- ciphertext: parsed.envelope.ciphertext,
174
- }),
175
- });
176
- return;
177
- default:
178
- send({ ok: false, error: "wallet_client_password_agent_protocol_error" });
179
- }
180
- }
181
- catch (error) {
182
- send({
183
- ok: false,
184
- error: error instanceof Error ? error.message : String(error),
185
- });
186
- }
187
- });
188
- });
189
- process.on("SIGTERM", () => {
190
- void cleanupAndExit();
191
- });
192
- process.on("SIGINT", () => {
193
- void cleanupAndExit();
194
- });
195
- process.on("exit", () => {
196
- zeroizeBuffer(key);
197
- });
198
- refreshExpiry();
199
- await new Promise((resolve, reject) => {
200
- server.once("error", reject);
201
- server.listen(bootstrap.endpoint, () => {
202
- server.off("error", reject);
203
- resolve();
204
- });
205
- });
206
- process.stdout.write("ready\n");
207
- }
208
- void main().catch((error) => {
209
- process.stderr.write(`${createAgentError(error instanceof Error ? error.message : String(error))}\n`);
210
- process.exit(1);
211
- });