@xyo-network/chain-services 1.5.11 → 1.5.13

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.
@@ -394,8 +394,8 @@ var XyoBlockProducer = class _XyoBlockProducer extends BaseService {
394
394
  get pendingTransactionsService() {
395
395
  return assertEx3(this.params.pendingTransactionsService, () => "Missing pendingTransactionsService");
396
396
  }
397
- get rejectedTransactionsArchivist() {
398
- return assertEx3(this.params.rejectedTransactionsArchivist, () => "No rejected transactions archivist");
397
+ get rejectedBundledTransactionsArchivist() {
398
+ return assertEx3(this.params.rejectedBundledTransactionsArchivist, () => "No rejected bundled transactions archivist");
399
399
  }
400
400
  get rewardAddress() {
401
401
  return assertEx3(this.params.rewardAddress, () => "No reward address provided");
@@ -502,7 +502,7 @@ var XyoBlockProducer = class _XyoBlockProducer extends BaseService {
502
502
  if (errors.length > 0) {
503
503
  this.logger?.warn(`Validation of produced block failed: ${errors.at(0)?.message}`);
504
504
  const rejectedTransactions = block[1];
505
- await this.rejectedTransactionsArchivist.insert(rejectedTransactions);
505
+ await this.rejectedBundledTransactionsArchivist.insert(rejectedTransactions);
506
506
  } else {
507
507
  return block;
508
508
  }
@@ -651,8 +651,8 @@ var XyoValidator = class extends BaseService {
651
651
  get electionService() {
652
652
  return assertEx6(this.params.electionService, () => "electionService is required");
653
653
  }
654
- get pendingTransactionsArchivist() {
655
- return assertEx6(this.params.pendingTransactionsArchivist, () => "pendingTransactions is required");
654
+ get pendingBundledTransactionsArchivist() {
655
+ return assertEx6(this.params.pendingBundledTransactionsArchivist, () => "pendingBundledTransactions is required");
656
656
  }
657
657
  get rewardService() {
658
658
  return assertEx6(this.params.rewardService, () => "rewardService is required");
@@ -729,14 +729,16 @@ XyoElectionService = _ts_decorate6([
729
729
 
730
730
  // src/PendingTransactions/PendingTransactions.ts
731
731
  import { ValueType } from "@opentelemetry/api";
732
- import { filterAs, filterAsync } from "@xylabs/array";
732
+ import { filterAsync } from "@xylabs/array";
733
733
  import { assertEx as assertEx8 } from "@xylabs/assert";
734
734
  import { exists as exists2 } from "@xylabs/exists";
735
735
  import { forget } from "@xylabs/forget";
736
736
  import { MemoryArchivist } from "@xyo-network/archivist-memory";
737
+ import { globalAttributes } from "@xyo-network/chain-telemetry";
737
738
  import { validateTransaction } from "@xyo-network/chain-validation";
738
- import { asOptionalTransactionBoundWitnessWithStorageMeta } from "@xyo-network/xl1-protocol";
739
- import { flattenHydratedTransactions, tryHydrateTransaction } from "@xyo-network/xl1-protocol-sdk";
739
+ import { PayloadBuilder as PayloadBuilder4 } from "@xyo-network/payload-builder";
740
+ import { asOptionalTransactionBoundWitnessWithStorageMeta, isTransactionBoundWitnessWithStorageMeta } from "@xyo-network/xl1-protocol";
741
+ import { flattenHydratedTransaction } from "@xyo-network/xl1-protocol-sdk";
740
742
  import { Mutex as Mutex2 } from "async-mutex";
741
743
  function _ts_decorate7(decorators, target, key, desc) {
742
744
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -745,6 +747,18 @@ function _ts_decorate7(decorators, target, key, desc) {
745
747
  return c > 3 && r && Object.defineProperty(target, key, r), r;
746
748
  }
747
749
  __name(_ts_decorate7, "_ts_decorate");
750
+ async function bundledPayloadsToHydratedTransaction(payload) {
751
+ const withStorageMeta = await PayloadBuilder4.addStorageMeta(payload.payloads);
752
+ const tx = asOptionalTransactionBoundWitnessWithStorageMeta(withStorageMeta.find((p) => p._hash === payload.root));
753
+ if (tx) {
754
+ return [
755
+ tx,
756
+ withStorageMeta.map((p) => p._hash === payload.root ? void 0 : p).filter(exists2)
757
+ ];
758
+ }
759
+ }
760
+ __name(bundledPayloadsToHydratedTransaction, "bundledPayloadsToHydratedTransaction");
761
+ globalAttributes.setAttribute("XyoPendingTransactionsService:status", "unknown");
748
762
  var XyoPendingTransactionsService = class _XyoPendingTransactionsService extends BaseService {
749
763
  static {
750
764
  __name(this, "XyoPendingTransactionsService");
@@ -776,11 +790,12 @@ var XyoPendingTransactionsService = class _XyoPendingTransactionsService extends
776
790
  * A local Archivist optimized for fast retrieval that stores only validated
777
791
  * pending transactions
778
792
  */
779
- _curatedPendingTransactionsArchivist;
793
+ _curatedPendingBundledTransactionsArchivist;
780
794
  /**
781
795
  * The last count of total pending transactions
782
796
  */
783
797
  _pendingTransactionsCount = 0;
798
+ _removablePendingTransactionHashes = /* @__PURE__ */ new Set();
784
799
  /**
785
800
  * A mutex to ensure that the curated pending transactions archivist is
786
801
  * updated in a thread-safe manner
@@ -792,73 +807,80 @@ var XyoPendingTransactionsService = class _XyoPendingTransactionsService extends
792
807
  get chainIdentification() {
793
808
  return assertEx8(this.params.chainIdentification, () => "No chain id");
794
809
  }
795
- get pendingTransactionsArchivist() {
796
- return assertEx8(this.params.pendingTransactionsArchivist, () => "No pending transactions archivist");
810
+ get pendingBundledTransactionsArchivist() {
811
+ return assertEx8(this.params.pendingBundledTransactionsArchivist, () => "No pending bundled transactions archivist");
812
+ }
813
+ get pendingBundledTransactionsLocalArchivist() {
814
+ return assertEx8(this._curatedPendingBundledTransactionsArchivist, () => "No pending bundled transactions curated archivist");
797
815
  }
798
816
  get pendingTransactionsCount() {
799
817
  forget(this.countPendingTransactions());
800
818
  return this._pendingTransactionsCount;
801
819
  }
802
- get pendingTransactionsLocalArchivist() {
803
- return assertEx8(this._curatedPendingTransactionsArchivist, () => "No pending transactions curated archivist");
804
- }
805
- get rejectedTransactionsArchivist() {
806
- return assertEx8(this.params.rejectedTransactionsArchivist, () => "No rejected transactions archivist");
820
+ get rejectedBundledTransactionsArchivist() {
821
+ return assertEx8(this.params.rejectedBundledTransactionsArchivist, () => "No rejected bundled transactions archivist");
807
822
  }
808
823
  async createHandler() {
809
824
  await super.createHandler();
810
- this._curatedPendingTransactionsArchivist = await MemoryArchivist.create({
825
+ this._curatedPendingBundledTransactionsArchivist = await MemoryArchivist.create({
811
826
  account: "random"
812
827
  });
813
- this.pendingTransactionsArchivist.on("inserted", async ({ payloads }) => {
828
+ this.pendingBundledTransactionsArchivist.on("inserted", async ({ payloads }) => {
814
829
  await this.insertNewTransactions(payloads);
815
830
  });
816
- this.chainArchivist.on("inserted", async ({ payloads }) => {
817
- await this.removeFinalizedTransactions(payloads);
831
+ this.chainArchivist.on("inserted", ({ payloads }) => {
832
+ this.removeFinalizedTransactions(payloads);
818
833
  });
819
- this.rejectedTransactionsArchivist.on("inserted", async ({ payloads }) => {
820
- await this.removeRejectedTransactions(payloads);
834
+ this.rejectedBundledTransactionsArchivist.on("inserted", ({ payloads }) => {
835
+ this.removeRejectedBundledTransactions(payloads);
821
836
  });
822
- const pendingTransactionsGauge = this.meter?.createObservableGauge("xyo_pending_transactions_count", {
837
+ const pendingTransactionsCounter = this.meter?.createObservableUpDownCounter("xyo_pending_transactions_counter", {
823
838
  description: "The current number of pending transactions",
824
- valueType: ValueType.INT
839
+ valueType: ValueType.INT,
840
+ unit: "1"
825
841
  });
826
- pendingTransactionsGauge?.addCallback((observer) => {
842
+ pendingTransactionsCounter?.addCallback((observer) => {
827
843
  observer.observe(this.pendingTransactionsCount);
828
844
  });
845
+ globalAttributes.setAttribute("XyoPendingTransactionsService:status", "created");
829
846
  }
830
847
  async getPendingTransactions(head, limit) {
831
848
  return await this.spanAsync("getPendingTransactions", async () => {
832
849
  return await this._updateCuratedPendingTransactionsArchivistMutex.runExclusive(async () => {
833
850
  const foundPendingTransactions = [];
851
+ const foundPendingTransactionsToDeleteHashes = [];
834
852
  let cursor;
835
853
  while (foundPendingTransactions.length < limit) {
836
- const payloads = await this.pendingTransactionsLocalArchivist.next({
854
+ const payloads = await this.pendingBundledTransactionsLocalArchivist.next({
837
855
  limit: 100,
838
856
  order: "asc",
839
857
  cursor
840
858
  });
841
859
  if (payloads.length === 0) break;
842
860
  cursor = payloads.at(-1)?._sequence;
843
- const transactions = payloads.map((payload) => asOptionalTransactionBoundWitnessWithStorageMeta(payload)).filter(exists2);
861
+ const deletedTransactionBundles = payloads.filter((tx) => this._removablePendingTransactionHashes.has(tx.root));
862
+ foundPendingTransactionsToDeleteHashes.push(...deletedTransactionBundles.map((tx) => tx._hash).filter(exists2));
863
+ const undeletedTransactionBundles = payloads.filter((tx) => !this._removablePendingTransactionHashes.has(tx.root));
864
+ const transactions = (await Promise.all(undeletedTransactionBundles.map((p) => bundledPayloadsToHydratedTransaction(p)))).filter(exists2);
844
865
  foundPendingTransactions.push(...transactions);
845
866
  }
846
- const hydratedTransactions = await Promise.all(foundPendingTransactions.map((tx) => tryHydrateTransaction(this.pendingTransactionsLocalArchivist, tx._hash)));
847
- return hydratedTransactions.filter(exists2);
867
+ for (const hash of foundPendingTransactionsToDeleteHashes) {
868
+ this._removablePendingTransactionHashes.delete(hash);
869
+ }
870
+ await this.pendingBundledTransactionsLocalArchivist.delete(foundPendingTransactionsToDeleteHashes);
871
+ return foundPendingTransactions;
848
872
  }, _XyoPendingTransactionsService.MutexPriority.ReadTransactions);
849
873
  });
850
874
  }
851
875
  async countPendingTransactions() {
852
876
  if (this._countPendingTransactionsMutex.isLocked()) return;
853
877
  await this._countPendingTransactionsMutex.runExclusive(async () => {
854
- const payloads = await this._curatedPendingTransactionsArchivist?.all() ?? [];
855
- const pendingTransactions = filterAs(payloads, asOptionalTransactionBoundWitnessWithStorageMeta);
856
- this._pendingTransactionsCount = pendingTransactions.length;
878
+ const payloads = await this._curatedPendingBundledTransactionsArchivist?.all() ?? [];
879
+ this._pendingTransactionsCount = payloads.length;
857
880
  });
858
881
  }
859
- async filterAlreadyFinalizedTransactions(payloads) {
860
- const incomingTransactions = filterAs(payloads, asOptionalTransactionBoundWitnessWithStorageMeta);
861
- const incomingTransactionHashes = incomingTransactions.map((payload) => payload._hash);
882
+ async filterAlreadyFinalizedTransactions(incomingTransactions) {
883
+ const incomingTransactionHashes = incomingTransactions.map((payload) => payload.root);
862
884
  const finalizedTransactions = await this.chainArchivist.get(incomingTransactionHashes);
863
885
  const finalizedTransactionHashes = new Set(finalizedTransactions.map((item) => item._hash));
864
886
  const nonFinalizedTransactions = incomingTransactions.filter((item) => !finalizedTransactionHashes.has(item._hash));
@@ -869,8 +891,8 @@ var XyoPendingTransactionsService = class _XyoPendingTransactionsService extends
869
891
  return await this.spanAsync("InsertNewTransactions", async () => {
870
892
  return await this._updateCuratedPendingTransactionsArchivistMutex.runExclusive(async () => {
871
893
  const unprocessedTransactions = await this.filterAlreadyFinalizedTransactions(payloads);
872
- const hydratedUnprocessedTransactions = (await Promise.all(unprocessedTransactions.map((tx) => {
873
- return tryHydrateTransaction(this.pendingTransactionsArchivist, tx._hash);
894
+ const hydratedUnprocessedTransactions = (await Promise.all(unprocessedTransactions.map(async (tx) => {
895
+ return await bundledPayloadsToHydratedTransaction(tx);
874
896
  }))).filter(exists2);
875
897
  const validTransactions = await filterAsync(hydratedUnprocessedTransactions, async (tx) => {
876
898
  const errors = await validateTransaction(tx, this.chainIdentification.id);
@@ -880,32 +902,47 @@ var XyoPendingTransactionsService = class _XyoPendingTransactionsService extends
880
902
  return errors.length > 0 ? false : true;
881
903
  });
882
904
  if (validTransactions.length > 0) {
883
- await this.pendingTransactionsLocalArchivist.insert(flattenHydratedTransactions(validTransactions));
905
+ await this.pendingBundledTransactionsLocalArchivist.insert(validTransactions.map((tx) => {
906
+ return {
907
+ root: tx[0]._hash,
908
+ payloads: flattenHydratedTransaction(tx)
909
+ };
910
+ }));
884
911
  }
885
912
  }, _XyoPendingTransactionsService.MutexPriority.InsertNewTransactions);
886
913
  });
887
914
  }
888
- async removeFinalizedTransactions(payloads) {
889
- return await this.removeTransactions(payloads, "RemoveFinalizedTransactions");
890
- }
891
- async removeRejectedTransactions(payloads) {
892
- return await this.removeTransactions(payloads, "RemoveRejectedTransactions");
893
- }
894
- async removeTransactions(payloads, priority) {
915
+ async removeBundledTransactions(bundledPayloads, priority) {
895
916
  return await this.spanAsync(priority, async () => {
896
917
  return await this._updateCuratedPendingTransactionsArchivistMutex.runExclusive(async () => {
897
- const transactions = filterAs(payloads, asOptionalTransactionBoundWitnessWithStorageMeta);
898
- await this.pendingTransactionsLocalArchivist.delete(transactions.map((tx) => tx._hash));
918
+ const bundledTransactions = (await Promise.all(bundledPayloads.map(async (payload) => {
919
+ const withStorageMeta = await PayloadBuilder4.addStorageMeta(payload.payloads);
920
+ const tx = asOptionalTransactionBoundWitnessWithStorageMeta(withStorageMeta.find((p) => p._hash === payload.root));
921
+ return tx !== void 0 && payload._hash !== void 0 ? tx : void 0;
922
+ }))).filter(exists2);
923
+ await this.pendingBundledTransactionsLocalArchivist.delete(bundledTransactions.map((btx) => btx._hash));
899
924
  }, _XyoPendingTransactionsService.MutexPriority[priority]);
900
925
  });
901
926
  }
927
+ removeFinalizedTransactions(payloads) {
928
+ const finalizedTransactionHashes = payloads.filter(isTransactionBoundWitnessWithStorageMeta).map((p) => p._hash);
929
+ for (const hash of finalizedTransactionHashes) {
930
+ this._removablePendingTransactionHashes.add(hash);
931
+ }
932
+ }
933
+ removeRejectedBundledTransactions(payloads) {
934
+ const rejectedTransactionHashes = payloads.filter(isTransactionBoundWitnessWithStorageMeta).map((p) => p._hash);
935
+ for (const hash of rejectedTransactionHashes) {
936
+ this._removablePendingTransactionHashes.add(hash);
937
+ }
938
+ }
902
939
  };
903
940
  XyoPendingTransactionsService = _ts_decorate7([
904
941
  creatableService()
905
942
  ], XyoPendingTransactionsService);
906
943
 
907
944
  // src/StakeIntent/lib/getBlockSignedStakeDeclarations.ts
908
- import { filterAs as filterAs2 } from "@xylabs/array";
945
+ import { filterAs } from "@xylabs/array";
909
946
  import { exists as exists3 } from "@xylabs/exists";
910
947
  import { asOptionalBoundWitness } from "@xyo-network/boundwitness-model";
911
948
  import { payloadSchemasContains } from "@xyo-network/boundwitness-validator";
@@ -913,13 +950,13 @@ import { BoundWitnessWrapper } from "@xyo-network/boundwitness-wrapper";
913
950
  import { asOptionalChainStakeIntent, ChainStakeIntentSchema as ChainStakeIntentSchema2 } from "@xyo-network/xl1-protocol";
914
951
  var getBlockSignedStakeDeclarations = /* @__PURE__ */ __name(async (block, archivist, intent) => {
915
952
  const blockData = await archivist.get(block.payload_hashes);
916
- const bwsFromBlock = filterAs2(blockData, asOptionalBoundWitness);
953
+ const bwsFromBlock = filterAs(blockData, asOptionalBoundWitness);
917
954
  const bwsFromBlockWithDeclarations = bwsFromBlock.filter((bw) => payloadSchemasContains(bw, ChainStakeIntentSchema2));
918
955
  const validBlockBwsWithDeclarations = await filterToValidSignedBoundWitnesses(bwsFromBlockWithDeclarations);
919
956
  return (await Promise.all(validBlockBwsWithDeclarations.map(async (bw) => {
920
957
  const stakeIntentHashes = validBlockBwsWithDeclarations.flatMap(mapBoundWitnessToStakeIntentHashes).filter(exists3);
921
958
  const payloads = await archivist.get(stakeIntentHashes);
922
- const stakeIntents = filterAs2(payloads, asOptionalChainStakeIntent).filter((p) => p.intent === intent).filter((p) => bw.addresses.includes(p.from));
959
+ const stakeIntents = filterAs(payloads, asOptionalChainStakeIntent).filter((p) => p.intent === intent).filter((p) => bw.addresses.includes(p.from));
923
960
  return stakeIntents;
924
961
  }))).flat();
925
962
  }, "getBlockSignedStakeDeclarations");
@@ -932,12 +969,12 @@ var mapBoundWitnessToStakeIntentHashes = /* @__PURE__ */ __name((bw) => {
932
969
  }, "mapBoundWitnessToStakeIntentHashes");
933
970
 
934
971
  // src/StakeIntent/XyoStakeIntentService.ts
935
- import { filterAs as filterAs3 } from "@xylabs/array";
972
+ import { filterAs as filterAs2 } from "@xylabs/array";
936
973
  import { assertEx as assertEx9 } from "@xylabs/assert";
937
974
  import { asAddress } from "@xylabs/hex";
938
975
  import { analyzeChain as analyzeChain3, ChainStakeIntentAnalyzer, isChainSummaryStakeIntent } from "@xyo-network/chain-analyze";
939
976
  import { DEFAULT_FIND_FIRST_MATCHING_NEXT_OPTIONS, findFirstMatching, IntervalMap } from "@xyo-network/chain-utils";
940
- import { PayloadBuilder as PayloadBuilder4 } from "@xyo-network/payload-builder";
977
+ import { PayloadBuilder as PayloadBuilder5 } from "@xyo-network/payload-builder";
941
978
  import { asOptionalBlockBoundWitness, asOptionalBlockBoundWitnessWithStorageMeta, asOptionalChainIndexingServiceStateWithStorageMeta, asOptionalChainStakeIntent as asOptionalChainStakeIntent2, ChainIndexingServiceStateSchema, isChainIndexingServiceState } from "@xyo-network/xl1-protocol";
942
979
  import { Mutex as Mutex3 } from "async-mutex";
943
980
  import { LRUCache } from "lru-cache";
@@ -993,7 +1030,7 @@ var XyoStakeIntentService = class extends BaseService {
993
1030
  }
994
1031
  async createHandler() {
995
1032
  const head = await this.chainIterator.head();
996
- const headHash = await PayloadBuilder4.hash(head);
1033
+ const headHash = await PayloadBuilder5.hash(head);
997
1034
  if (head?.block === void 0) return;
998
1035
  await this.recoverState(headHash);
999
1036
  await this.updateIndex(true);
@@ -1048,7 +1085,7 @@ var XyoStakeIntentService = class extends BaseService {
1048
1085
  }
1049
1086
  async persistState(current) {
1050
1087
  const state = this._producers.serialize();
1051
- const payload = new PayloadBuilder4({
1088
+ const payload = new PayloadBuilder5({
1052
1089
  schema: ChainIndexingServiceStateSchema
1053
1090
  }).fields({
1054
1091
  endBlockHash: current,
@@ -1099,11 +1136,11 @@ var XyoStakeIntentService = class extends BaseService {
1099
1136
  await this._updateMutex.runExclusive(async () => {
1100
1137
  return await this.spanAsync("updateIndex", async () => {
1101
1138
  const currentHead = await this.chainIterator.head();
1102
- const currentHeadHash = await PayloadBuilder4.hash(currentHead);
1139
+ const currentHeadHash = await PayloadBuilder5.hash(currentHead);
1103
1140
  const result = await analyzeChain3(this.chainArchivist, [
1104
1141
  new ChainStakeIntentAnalyzer("producer")
1105
1142
  ], currentHeadHash, this._lastIndexedBlockHash);
1106
- const signedDeclarations = filterAs3(result.find(isChainSummaryStakeIntent)?.intents ?? [], asOptionalChainStakeIntent2);
1143
+ const signedDeclarations = filterAs2(result.find(isChainSummaryStakeIntent)?.intents ?? [], asOptionalChainStakeIntent2);
1107
1144
  if (currentHead.block === void 0) return;
1108
1145
  const currentHeadBlockNum = currentHead.block;
1109
1146
  if (displayProgress) this.logger?.info(`Updating index through 0x${currentHeadBlockNum}`);
@@ -1224,7 +1261,7 @@ var EvmChainService = class extends Base {
1224
1261
  import { assertEx as assertEx10 } from "@xylabs/assert";
1225
1262
  import { BaseEmitter as BaseEmitter2 } from "@xylabs/events";
1226
1263
  import { isDefined as isDefined2, isNull } from "@xylabs/typeof";
1227
- import { PayloadBuilder as PayloadBuilder5 } from "@xyo-network/payload-builder";
1264
+ import { PayloadBuilder as PayloadBuilder6 } from "@xyo-network/payload-builder";
1228
1265
  import { asBlockBoundWitness as asBlockBoundWitness2, asOptionalBlockBoundWitness as asOptionalBlockBoundWitness2, isBlockBoundWitness } from "@xyo-network/xl1-protocol";
1229
1266
  import { LRUCache as LRUCache2 } from "lru-cache";
1230
1267
  var XyoChainBlockNumberIterator = class _XyoChainBlockNumberIterator extends BaseEmitter2 {
@@ -1261,7 +1298,7 @@ var XyoChainBlockNumberIterator = class _XyoChainBlockNumberIterator extends Bas
1261
1298
  const cached = this._blocksByBlockNumber.get(block);
1262
1299
  if (cached) return cached;
1263
1300
  const startingBlock = this._head;
1264
- const currentBlockHash = await PayloadBuilder5.hash(startingBlock);
1301
+ const currentBlockHash = await PayloadBuilder6.hash(startingBlock);
1265
1302
  let currentBlock = (await this._chainArchivist.get([
1266
1303
  currentBlockHash
1267
1304
  ])).at(0);
@@ -1304,7 +1341,7 @@ var XyoChainBlockNumberIterator = class _XyoChainBlockNumberIterator extends Bas
1304
1341
  ]);
1305
1342
  currentBlock = asOptionalBlockBoundWitness2(nextBlock[0]);
1306
1343
  } else {
1307
- const hash = PayloadBuilder5.hash(currentBlock);
1344
+ const hash = PayloadBuilder6.hash(currentBlock);
1308
1345
  assertEx10(asBlockBoundWitness2(currentBlock), () => `Expected hash to be a block bound witness [${hash}]`);
1309
1346
  }
1310
1347
  }