trac-msb 0.2.24 → 0.3.0-beta.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 (137) hide show
  1. package/SECURITY.md +2 -2
  2. package/cli/commandHandler.js +317 -20
  3. package/cli/handlers.js +9 -1
  4. package/cli/interactive.js +4 -3
  5. package/cli/tokenSupplyAudit.js +90 -0
  6. package/msb.mjs +1 -0
  7. package/package.json +15 -6
  8. package/rpc/create_server.js +12 -3
  9. package/rpc/handlers.js +103 -0
  10. package/rpc/routes/v1.js +8 -0
  11. package/src/codecs/apply/applyOperationCodec.js +334 -0
  12. package/src/codecs/apply/applyOperations.generated.cjs +6380 -0
  13. package/src/codecs/consensus/v1/consensusV1.generated.cjs +3508 -0
  14. package/src/codecs/consensus/v1/consensusV1OperationCodec.js +161 -0
  15. package/src/codecs/consensus/v1/vdfConfigCodec.js +83 -0
  16. package/src/{utils/protobuf → codecs/network/v1}/networkV1.generated.cjs +664 -393
  17. package/src/codecs/network/v1/networkV1OperationCodec.js +25 -0
  18. package/src/codecs/protobufRuntime.cjs +95 -0
  19. package/src/codecs/state/escrowEntryCodec.js +45 -0
  20. package/src/codecs/state/state.generated.cjs +659 -0
  21. package/src/config/args.js +0 -1
  22. package/src/config/config.js +46 -7
  23. package/src/config/env.js +33 -6
  24. package/src/core/consensus/epochAppenderSelection/EpochAppenderSelectionError.js +55 -0
  25. package/src/core/consensus/epochAppenderSelection/EpochAppenderSelectionOperations.js +118 -0
  26. package/src/core/consensus/epochAppenderSelection/EpochAppenderSelector.js +1042 -0
  27. package/src/core/consensus/epochAppenderSelection/createEpochAppenderSelector.js +23 -0
  28. package/src/core/consensus/epochAppenderSelection/epochAppenderSelectionLedgerReader.js +274 -0
  29. package/src/core/consensus/epochAppenderSelection/epochAppenderSelectionState.js +488 -0
  30. package/src/core/consensus/epochAppenderSelection/epochAppenderSelectionStorage.js +93 -0
  31. package/src/core/consensus/quorum.js +11 -0
  32. package/src/core/consensus/services/EpochCoordinationRound.js +839 -0
  33. package/src/core/consensus/services/EpochCoordinatorOperations.js +211 -0
  34. package/src/core/consensus/services/EpochCoordinatorService.js +335 -0
  35. package/src/core/consensus/services/EpochRoundListeners.js +116 -0
  36. package/src/core/consensus/services/EpochStateMachine.js +141 -0
  37. package/src/core/consensus/services/VDFBare.js +291 -0
  38. package/src/core/consensus/services/VDFNode.js +111 -0
  39. package/src/core/consensus/services/VDFProgressWatchdog.js +79 -0
  40. package/src/core/consensus/services/VDFService.js +87 -0
  41. package/src/core/consensus/services/VDFServiceManager.js +147 -0
  42. package/src/core/consensus/services/createVDFService.js +16 -0
  43. package/src/core/consensus/services/vdf-guardian.js +32 -0
  44. package/src/core/consensus/services/vdf-worker.js +90 -0
  45. package/src/core/network/Network.js +327 -238
  46. package/src/core/network/protocols/consensus/IndexerMessages.js +72 -0
  47. package/src/core/network/protocols/consensus/v1/ConsensusV1ConnectionPolicy.js +57 -0
  48. package/src/core/network/protocols/consensus/v1/ConsensusV1MessageRouter.js +147 -0
  49. package/src/core/network/protocols/consensus/v1/ConsensusV1Protocol.js +72 -0
  50. package/src/core/network/protocols/consensus/v1/IndexerPendingRequestService.js +108 -0
  51. package/src/core/network/protocols/consensus/v1/V1ConsensusProtocolError.js +29 -0
  52. package/src/core/network/protocols/consensus/v1/handlers/V1EpochAppendOperationHandler.js +68 -0
  53. package/src/core/network/protocols/consensus/v1/handlers/V1EpochProofProposalOperationHandler.js +226 -0
  54. package/src/core/network/protocols/consensus/v1/validators/ConsensusValidationSchema.js +192 -0
  55. package/src/core/network/protocols/consensus/v1/validators/V1BaseConsensusOperation.js +428 -0
  56. package/src/core/network/protocols/consensus/v1/validators/V1EpochAppendReply.js +47 -0
  57. package/src/core/network/protocols/consensus/v1/validators/V1EpochAppendRequest.js +17 -0
  58. package/src/core/network/protocols/consensus/v1/validators/V1EpochProofProposalApproval.js +116 -0
  59. package/src/core/network/protocols/consensus/v1/validators/V1EpochProofProposalRequest.js +152 -0
  60. package/src/core/network/protocols/consensus/v1/validators/consensusValidationSchemaHelpers.js +145 -0
  61. package/src/core/network/protocols/shared/ConnectionOperationHandler.js +27 -0
  62. package/src/core/network/protocols/{NetworkMessages.js → validators/ValidatorMessages.js} +24 -14
  63. package/src/core/network/protocols/{ProtocolSession.js → validators/ValidatorProtocolSession.js} +22 -25
  64. package/src/core/network/protocols/{legacy/NetworkMessageRouter.js → validators/legacy/ValidatorLegacyMessageRouter.js} +6 -6
  65. package/src/core/network/protocols/{LegacyProtocol.js → validators/legacy/ValidatorLegacyProtocol.js} +9 -7
  66. package/src/core/network/protocols/{legacy → validators/legacy}/handlers/BaseStateOperationHandler.js +1 -1
  67. package/src/core/network/protocols/{legacy → validators/legacy}/handlers/LegacyGetRequestHandler.js +5 -5
  68. package/src/core/network/protocols/{legacy → validators/legacy}/handlers/LegacyRoleOperationHandler.js +5 -5
  69. package/src/core/network/protocols/{legacy → validators/legacy}/handlers/LegacySubnetworkOperationHandler.js +5 -5
  70. package/src/core/network/protocols/{legacy → validators/legacy}/handlers/LegacyTransferOperationHandler.js +5 -5
  71. package/src/core/network/protocols/{ProtocolInterface.js → validators/shared/ValidatorProtocolInterface.js} +5 -5
  72. package/src/core/network/protocols/{shared → validators/shared}/validators/PartialBootstrapDeploymentValidator.js +1 -1
  73. package/src/core/network/protocols/validators/shared/validators/PartialHtlcValidator.js +325 -0
  74. package/src/core/network/protocols/{shared → validators/shared}/validators/PartialOperationValidator.js +44 -21
  75. package/src/core/network/protocols/{shared → validators/shared}/validators/PartialRoleAccessValidator.js +3 -3
  76. package/src/core/network/protocols/{shared → validators/shared}/validators/PartialTransactionValidator.js +3 -3
  77. package/src/core/network/protocols/{shared → validators/shared}/validators/PartialTransferValidator.js +4 -4
  78. package/src/core/network/protocols/{v1 → validators/v1}/V1ProtocolError.js +1 -1
  79. package/src/core/network/{services/PendingRequestService.js → protocols/validators/v1/ValidatorPendingRequestService.js} +19 -82
  80. package/src/core/network/protocols/{v1/NetworkMessageRouter.js → validators/v1/ValidatorV1MessageRouter.js} +9 -9
  81. package/src/core/network/protocols/{V1Protocol.js → validators/v1/ValidatorV1Protocol.js} +10 -8
  82. package/src/core/network/protocols/{connectionPolicies.js → validators/v1/connectionPolicies.js} +1 -1
  83. package/src/core/network/protocols/{v1 → validators/v1}/handlers/V1BaseOperationHandler.js +6 -23
  84. package/src/core/network/protocols/{v1 → validators/v1}/handlers/V1BroadcastTransactionOperationHandler.js +14 -9
  85. package/src/core/network/protocols/{v1 → validators/v1}/handlers/V1LivenessOperationHandler.js +5 -4
  86. package/src/core/network/protocols/{v1 → validators/v1}/handlers/broadcastTransaction/BroadcastTransactionErrorMapper.js +3 -3
  87. package/src/core/network/protocols/{v1 → validators/v1}/handlers/broadcastTransaction/BroadcastTransactionOperationStrategies.js +44 -1
  88. package/src/core/network/protocols/{v1 → validators/v1}/handlers/broadcastTransaction/BroadcastTransactionPayloadUtils.js +1 -1
  89. package/src/core/network/protocols/{v1 → validators/v1}/validators/V1BaseOperation.js +19 -15
  90. package/src/core/network/protocols/{v1 → validators/v1}/validators/V1BroadcastTransactionRequest.js +2 -2
  91. package/src/core/network/protocols/{v1 → validators/v1}/validators/V1BroadcastTransactionResponse.js +34 -18
  92. package/src/core/network/protocols/{v1 → validators/v1}/validators/V1ValidationSchema.js +3 -3
  93. package/src/core/network/services/IndexerConnectionManager.js +88 -0
  94. package/src/core/network/services/TransactionPoolService.js +11 -18
  95. package/src/core/network/services/TransactionRateLimiterService.js +1 -1
  96. package/src/core/network/services/ValidatorConnectionManager.js +163 -0
  97. package/src/core/network/services/{MessageOrchestrator.js → ValidatorMessageOrchestrator.js} +34 -42
  98. package/src/core/network/services/ValidatorObserverService.js +21 -36
  99. package/src/core/network/shared/BasePendingRequestService.js +67 -0
  100. package/src/core/network/shared/PeerConnectionManager.js +185 -0
  101. package/src/core/state/ConfirmationWatch.js +82 -0
  102. package/src/core/state/State.js +1794 -173
  103. package/src/core/state/StateEventQueue.js +69 -0
  104. package/src/core/state/utils/address.js +10 -6
  105. package/src/core/state/utils/epochProof.js +109 -0
  106. package/src/core/state/utils/escrowEntry.js +178 -0
  107. package/src/core/state/validators/StateValidationSchema.js +757 -0
  108. package/src/core/state/validators/stateValidationRules.js +312 -0
  109. package/src/index.js +255 -65
  110. package/src/messages/consensus/v1/ConsensusMessageBuilder.js +368 -0
  111. package/src/messages/consensus/v1/ConsensusMessageDirector.js +142 -0
  112. package/src/messages/consensus/v1/consensusMessageFactory.js +12 -0
  113. package/src/messages/consensus/v1/epochAppendMessage.js +58 -0
  114. package/src/messages/network/v1/NetworkMessageBuilder.js +15 -7
  115. package/src/messages/state/ApplyStateMessageBuilder.js +499 -13
  116. package/src/messages/state/ApplyStateMessageDirector.js +261 -2
  117. package/src/utils/StateMachine.js +125 -0
  118. package/src/utils/applyOperations.js +45 -2
  119. package/src/utils/buffer.js +239 -59
  120. package/src/utils/consensusConfig.js +76 -0
  121. package/src/utils/constants.js +174 -73
  122. package/src/utils/helpers.js +0 -25
  123. package/src/utils/htlcLock.js +122 -0
  124. package/src/utils/logger.js +10 -4
  125. package/src/utils/migrationUtils.js +2 -1
  126. package/src/utils/normalizers.js +113 -0
  127. package/src/utils/scheduler/SchedulableService.js +107 -0
  128. package/src/utils/{Scheduler.js → scheduler/Scheduler.js} +56 -17
  129. package/src/core/network/services/ConnectionManager.js +0 -406
  130. package/src/utils/check.js +0 -525
  131. package/src/utils/protobuf/applyOperations.cjs +0 -1373
  132. package/src/utils/protobuf/operationHelpers.js +0 -81
  133. /package/src/core/network/protocols/{legacy → validators/legacy}/handlers/LegacyResponseHandler.js +0 -0
  134. /package/src/core/network/protocols/{legacy → validators/legacy}/validators/ValidatorResponse.js +0 -0
  135. /package/src/core/network/protocols/{legacy → validators/legacy}/validators/base/BaseResponse.js +0 -0
  136. /package/src/core/network/protocols/{v1 → validators/v1}/validators/V1LivenessRequest.js +0 -0
  137. /package/src/core/network/protocols/{v1 → validators/v1}/validators/V1LivenessResponse.js +0 -0
@@ -1,4 +1,6 @@
1
- import { OperationType } from '../../utils/constants.js';
1
+ import { ConsensusVersion, OperationType } from '../../utils/constants.js';
2
+ import { encodeEpochProofV1 } from '../../codecs/apply/applyOperationCodec.js';
3
+ import { uint8ToBuffer } from '../../utils/buffer.js';
2
4
 
3
5
  /**
4
6
  * Director that orchestrates ApplyStateMessageBuilder for partial and complete messages.
@@ -511,6 +513,263 @@ class ApplyStateMessageDirector {
511
513
  .build();
512
514
  return this.#builder.getPayload();
513
515
  }
514
- }
515
516
 
517
+ /**
518
+ * Build a complete set epoch payload.
519
+ * @param {string|Buffer} invokerAddress
520
+ * @param {string|Buffer} proofData
521
+ * @param {Array<string|Buffer>} approvals
522
+ * @returns {Promise<object>}
523
+ */
524
+ async buildCompleteSetEpochMessage(invokerAddress, proofData, approvals) {
525
+ if (!this.#builder) throw new Error('Builder has not been set.');
526
+ const schemaVersion = uint8ToBuffer(ConsensusVersion.VDF_V1);
527
+ const epochData = encodeEpochProofV1({ pd: proofData, app: approvals });
528
+
529
+ await this.#builder
530
+ .setPhase('complete')
531
+ .setOutput('buffer')
532
+ .setOperationType(OperationType.SET_EPOCH)
533
+ .setAddress(invokerAddress)
534
+ .setEpochData(schemaVersion, epochData)
535
+ .build();
536
+ return this.#builder.getPayload();
537
+ }
538
+
539
+ /**
540
+ * Build a complete set genesis epoch payload.
541
+ * @param {string|Buffer} invokerAddress
542
+ * @param {string|Buffer} txValidity
543
+ * @param {Buffer} encodedConsensusConfig
544
+ * @returns {Promise<object>}
545
+ */
546
+ async buildCompleteSetGenesisEpochMessage(invokerAddress, txValidity, encodedConsensusConfig) {
547
+ if (!this.#builder) throw new Error('Builder has not been set.');
548
+ await this.#builder
549
+ .setPhase('complete')
550
+ .setOutput('buffer')
551
+ .setOperationType(OperationType.SET_GENESIS_EPOCH)
552
+ .setAddress(invokerAddress)
553
+ .setTxValidity(txValidity)
554
+ .setConsensusConfig(encodedConsensusConfig)
555
+ .build();
556
+ return this.#builder.getPayload();
557
+ }
558
+
559
+ /**
560
+ * Build a complete set consensus config payload.
561
+ * @param {string|Buffer} invokerAddress
562
+ * @param {string|Buffer} txValidity
563
+ * @param {Buffer} encodedConsensusConfig
564
+ * @returns {Promise<object>}
565
+ */
566
+ async buildCompleteSetConsensusConfigMessage(invokerAddress, txValidity, encodedConsensusConfig) {
567
+ if (!this.#builder) throw new Error('Builder has not been set.');
568
+ await this.#builder
569
+ .setPhase('complete')
570
+ .setOutput('buffer')
571
+ .setOperationType(OperationType.SET_CONSENSUS_CONFIG)
572
+ .setAddress(invokerAddress)
573
+ .setTxValidity(txValidity)
574
+ .setConsensusConfig(encodedConsensusConfig)
575
+ .build();
576
+ return this.#builder.getPayload();
577
+ }
578
+
579
+ /**
580
+ * Build a partial HTLC lock operation.
581
+ * The transaction hash produced by the builder is the lock identifier.
582
+ *
583
+ * @param {string|Buffer} invokerAddress Locker address.
584
+ * @param {string|Buffer} txValidity Current transaction-validity value.
585
+ * @param {object} lock Canonical HTLC lock terms and authorizations.
586
+ * @param {string|Buffer} [lock.metadata] Opaque application bytes (1–1024 bytes), or their hex representation.
587
+ * @param {'json'|'buffer'} output Output format.
588
+ * @returns {Promise<object>}
589
+ */
590
+ async buildPartialHtlcLockOperationMessage(invokerAddress, txValidity, lock, output = 'buffer') {
591
+ if (!this.#builder) throw new Error('Builder has not been set.');
592
+ const {
593
+ claimAddress,
594
+ refundAddress,
595
+ amount,
596
+ feeAmount,
597
+ feeRecipient,
598
+ hashLock,
599
+ refundEpoch,
600
+ metadata,
601
+ signerSet,
602
+ threshold,
603
+ cosignerSignatures = [],
604
+ nonce
605
+ } = lock ?? {};
606
+
607
+ const builder = this.#builder
608
+ .setPhase('partial')
609
+ .setOutput(output)
610
+ .setOperationType(OperationType.HTLC_LOCK)
611
+ .setAddress(invokerAddress)
612
+ .setTxValidity(txValidity)
613
+ .setAmount(amount)
614
+ .setHtlcClaimAddress(claimAddress)
615
+ .setHtlcRefundAddress(refundAddress)
616
+ .setHtlcFeeAmount(feeAmount)
617
+ .setHtlcFeeRecipient(feeRecipient)
618
+ .setHtlcHashLock(hashLock)
619
+ .setHtlcRefundEpoch(refundEpoch)
620
+ .setHtlcMetadata(metadata)
621
+ .setHtlcSignerSet(signerSet)
622
+ .setHtlcThreshold(threshold)
623
+ .setHtlcCosignerSignatures(cosignerSignatures);
624
+
625
+ if (nonce !== undefined) builder.setNonce(nonce);
626
+ await builder.build();
627
+ return this.#builder.getPayload();
628
+ }
629
+
630
+ /**
631
+ * Build a signed partial HTLC claim payload.
632
+ * @param {string|Buffer} invokerAddress
633
+ * @param {string|Buffer} txValidity
634
+ * @param {string|Buffer} lockId
635
+ * @param {string|Buffer} preimage
636
+ * @returns {Promise<object>}
637
+ */
638
+ async buildPartialHtlcClaimOperationMessage(invokerAddress, txValidity, lockId, preimage) {
639
+ if (!this.#builder) throw new Error('Builder has not been set.');
640
+ await this.#builder
641
+ .setPhase('partial')
642
+ .setOutput('buffer')
643
+ .setOperationType(OperationType.HTLC_CLAIM)
644
+ .setAddress(invokerAddress)
645
+ .setTxValidity(txValidity)
646
+ .setHtlcLockId(lockId)
647
+ .setHtlcPreimage(preimage)
648
+ .build();
649
+ return this.#builder.getPayload();
650
+ }
651
+
652
+ /**
653
+ * Add validator metadata to an already validated partial HTLC lock operation.
654
+ *
655
+ * @param {string|Buffer} invokerAddress Locker address.
656
+ * @param {object} operation Decoded partial hlo payload.
657
+ * @returns {Promise<object>}
658
+ */
659
+ async buildCompleteHtlcLockOperationMessage(invokerAddress, operation) {
660
+ if (!this.#builder) throw new Error('Builder has not been set.');
661
+ await this.#builder
662
+ .setPhase('complete')
663
+ .setOutput('buffer')
664
+ .setOperationType(OperationType.HTLC_LOCK)
665
+ .setAddress(invokerAddress)
666
+ .setTxHash(operation?.tx)
667
+ .setTxValidity(operation?.txv)
668
+ .setAmount(operation?.am)
669
+ .setHtlcClaimAddress(operation?.ca)
670
+ .setHtlcRefundAddress(operation?.ra)
671
+ .setHtlcFeeAmount(operation?.fa)
672
+ .setHtlcFeeRecipient(operation?.fr)
673
+ .setHtlcHashLock(operation?.hl)
674
+ .setHtlcRefundEpoch(operation?.re)
675
+ .setHtlcMetadata(operation?.md)
676
+ .setHtlcSignerSet(operation?.ss)
677
+ .setHtlcThreshold(operation?.th)
678
+ .setHtlcCosignerSignatures(operation?.cs)
679
+ .setIncomingNonce(operation?.in)
680
+ .setIncomingSignature(operation?.is)
681
+ .build();
682
+ return this.#builder.getPayload();
683
+ }
684
+
685
+ /**
686
+ * Complete a submitter-signed HTLC claim with validator metadata.
687
+ * @param {string|Buffer} invokerAddress
688
+ * @param {string|Buffer} transactionHash
689
+ * @param {string|Buffer} txValidity
690
+ * @param {string|Buffer} lockId
691
+ * @param {string|Buffer} preimage
692
+ * @param {string|Buffer} incomingNonce
693
+ * @param {string|Buffer} incomingSignature
694
+ * @returns {Promise<object>}
695
+ */
696
+ async buildCompleteHtlcClaimOperationMessage(
697
+ invokerAddress,
698
+ transactionHash,
699
+ txValidity,
700
+ lockId,
701
+ preimage,
702
+ incomingNonce,
703
+ incomingSignature
704
+ ) {
705
+ if (!this.#builder) throw new Error('Builder has not been set.');
706
+ await this.#builder
707
+ .setPhase('complete')
708
+ .setOutput('buffer')
709
+ .setOperationType(OperationType.HTLC_CLAIM)
710
+ .setAddress(invokerAddress)
711
+ .setTxHash(transactionHash)
712
+ .setTxValidity(txValidity)
713
+ .setHtlcLockId(lockId)
714
+ .setHtlcPreimage(preimage)
715
+ .setIncomingNonce(incomingNonce)
716
+ .setIncomingSignature(incomingSignature)
717
+ .build();
718
+ return this.#builder.getPayload();
719
+ }
720
+
721
+ /**
722
+ * Build a signed partial HTLC refund payload.
723
+ * @param {string|Buffer} invokerAddress
724
+ * @param {string|Buffer} txValidity
725
+ * @param {string|Buffer} lockId
726
+ * @param {'json'|'buffer'} output
727
+ * @returns {Promise<object>}
728
+ */
729
+ async buildPartialHtlcRefundOperationMessage(invokerAddress, txValidity, lockId, output = 'buffer') {
730
+ if (!this.#builder) throw new Error('Builder has not been set.');
731
+ await this.#builder
732
+ .setPhase('partial')
733
+ .setOutput(output)
734
+ .setOperationType(OperationType.HTLC_REFUND)
735
+ .setAddress(invokerAddress)
736
+ .setTxValidity(txValidity)
737
+ .setHtlcLockId(lockId)
738
+ .build();
739
+ return this.#builder.getPayload();
740
+ }
741
+
742
+ /**
743
+ * Add validator metadata to a validated, submitter-signed HTLC refund.
744
+ * @param {string|Buffer} invokerAddress
745
+ * @param {string|Buffer} transactionHash
746
+ * @param {string|Buffer} txValidity
747
+ * @param {string|Buffer} lockId
748
+ * @param {string|Buffer} incomingNonce
749
+ * @param {string|Buffer} incomingSignature
750
+ * @returns {Promise<object>}
751
+ */
752
+ async buildCompleteHtlcRefundOperationMessage(
753
+ invokerAddress,
754
+ transactionHash,
755
+ txValidity,
756
+ lockId,
757
+ incomingNonce,
758
+ incomingSignature
759
+ ) {
760
+ if (!this.#builder) throw new Error('Builder has not been set.');
761
+ await this.#builder
762
+ .setPhase('complete')
763
+ .setOutput('buffer')
764
+ .setOperationType(OperationType.HTLC_REFUND)
765
+ .setAddress(invokerAddress)
766
+ .setTxHash(transactionHash)
767
+ .setTxValidity(txValidity)
768
+ .setHtlcLockId(lockId)
769
+ .setIncomingNonce(incomingNonce)
770
+ .setIncomingSignature(incomingSignature)
771
+ .build();
772
+ return this.#builder.getPayload();
773
+ }
774
+ }
516
775
  export default ApplyStateMessageDirector;
@@ -0,0 +1,125 @@
1
+ import ReadyResource from 'ready-resource';
2
+
3
+ const READY_RESOURCE_EVENTS = ['ready', 'close'];
4
+
5
+ export class StateMachine extends ReadyResource {
6
+ #state;
7
+ #context = {};
8
+ #discardState;
9
+ #listeners = new Map();
10
+ #transitions;
11
+ #handlers;
12
+ #transition = null;
13
+
14
+ constructor(transitions, initialState, discardState, handlers = {}) {
15
+ super();
16
+ if (!transitions) throw new Error('StateMachine: transitions is required');
17
+ if (!initialState) throw new Error('StateMachine: initialState is required');
18
+ if (discardState === undefined) throw new Error('StateMachine: discardState is required (pass null to disable context clearing)');
19
+
20
+ this.#transitions = transitions;
21
+ this.#state = initialState;
22
+ this.#discardState = discardState;
23
+ this.#handlers = handlers;
24
+ }
25
+
26
+ async _close() {
27
+ this.clearListeners();
28
+ }
29
+
30
+ get state() {
31
+ return this.#state;
32
+ }
33
+
34
+ get context() {
35
+ return this.#context;
36
+ }
37
+
38
+ appendContext(payload = {}) {
39
+ Object.assign(this.#context, payload);
40
+ return this.#context;
41
+ }
42
+
43
+ shouldRun() {
44
+ return this.closing === null && !this.closed;
45
+ }
46
+
47
+ async send(event, payload = {}) {
48
+ if (!this.shouldRun()) return false;
49
+
50
+ const next = this.#transitions[this.#state]?.[event];
51
+ if (!next) return false;
52
+
53
+ this.appendContext(payload);
54
+
55
+ const prev = this.#state;
56
+ const transition = { machine: this, prev, next, context: this.#context };
57
+ this.#transition = transition;
58
+ this.#state = next;
59
+ await this.#emit(event, transition);
60
+
61
+ // Another transition may have run while an event listener was awaited.
62
+ if (!this.shouldRun() || this.#transition !== transition) return false;
63
+
64
+ if (this.#discardState !== null && next === this.#discardState) {
65
+ this.#context = {};
66
+ }
67
+
68
+ await this.#dispatch(next);
69
+
70
+ return transition;
71
+ }
72
+
73
+ // The initial state is assigned directly in the constructor, not reached via send(),
74
+ // so its handler never fires on its own - nothing ever "transitions into" it. This
75
+ // dispatches to the current state's handler once, the same way any other transition
76
+ // does, so callers never need to know which state that is.
77
+ async enter(payload = {}) {
78
+ if (!this.shouldRun()) return false;
79
+
80
+ this.appendContext(payload);
81
+
82
+ const transition = { machine: this, prev: null, next: this.#state, context: this.#context };
83
+ this.#transition = transition;
84
+ await this.#emit('ENTER', transition);
85
+
86
+ if (!this.shouldRun() || this.#transition !== transition) return false;
87
+
88
+ await this.#dispatch(transition.next);
89
+
90
+ return transition;
91
+ }
92
+
93
+ async #dispatch(state) {
94
+ const handler = this.#handlers[state];
95
+ if (handler) await handler(this.#context, this);
96
+ }
97
+
98
+ on(event, fn) {
99
+ if (READY_RESOURCE_EVENTS.includes(event)) {
100
+ super.on(event, fn);
101
+ return this;
102
+ }
103
+
104
+ if (!this.#listeners.has(event)) this.#listeners.set(event, []);
105
+
106
+ this.#listeners.get(event).push(fn);
107
+ return this;
108
+ }
109
+
110
+ clearListeners() {
111
+ this.#listeners.clear();
112
+ return this;
113
+ }
114
+
115
+ async #emit(event, data) {
116
+ for (const fn of this.#listeners.get(event) ?? []) {
117
+ if (!this.shouldRun() || this.#transition !== data) return;
118
+ await fn(data);
119
+ }
120
+ for (const fn of this.#listeners.get('*') ?? []) {
121
+ if (!this.shouldRun() || this.#transition !== data) return;
122
+ await fn({ event, ...data });
123
+ }
124
+ }
125
+ }
@@ -48,6 +48,26 @@ const isBalanceInitialization = type => {
48
48
  ].includes(type);
49
49
  }
50
50
 
51
+ const isHtlc = type => {
52
+ return [
53
+ OperationType.HTLC_LOCK,
54
+ OperationType.HTLC_CLAIM,
55
+ OperationType.HTLC_REFUND
56
+ ].includes(type);
57
+ }
58
+ const isSetEpoch = type => {
59
+ return [
60
+ OperationType.SET_EPOCH
61
+ ].includes(type);
62
+ }
63
+
64
+ const isConsensusControl = type => {
65
+ return [
66
+ OperationType.SET_GENESIS_EPOCH,
67
+ OperationType.SET_CONSENSUS_CONFIG
68
+ ].includes(type);
69
+ }
70
+
51
71
  const operationToPayload = type => {
52
72
  const fromTo = [
53
73
  {
@@ -77,6 +97,26 @@ const operationToPayload = type => {
77
97
  {
78
98
  condition: isBalanceInitialization,
79
99
  jsonPath: 'bio'
100
+ },
101
+ {
102
+ condition: type => type === OperationType.HTLC_LOCK,
103
+ jsonPath: 'hlo'
104
+ },
105
+ {
106
+ condition: type => type === OperationType.HTLC_CLAIM,
107
+ jsonPath: 'hco'
108
+ },
109
+ {
110
+ condition: type => type === OperationType.HTLC_REFUND,
111
+ jsonPath: 'hro'
112
+ },
113
+ {
114
+ condition: isSetEpoch,
115
+ jsonPath: 'seo'
116
+ },
117
+ {
118
+ condition: isConsensusControl,
119
+ jsonPath: 'cco'
80
120
  }
81
121
  ]
82
122
  const match = fromTo.find(entry => !!entry.condition(type))
@@ -91,5 +131,8 @@ export {
91
131
  isBootstrapDeployment,
92
132
  operationToPayload,
93
133
  isTransfer,
94
- isBalanceInitialization
95
- }
134
+ isBalanceInitialization,
135
+ isHtlc,
136
+ isSetEpoch,
137
+ isConsensusControl
138
+ }