@xyo-network/chain-services 1.5.10 → 1.5.12

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