@xyo-network/chain-services 1.5.11 → 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.
@@ -9,7 +9,7 @@ export interface XyoValidatorParams extends BaseServiceParams {
9
9
  chainArchivist: ReadArchivist;
10
10
  chainInformation: ChainInformation;
11
11
  electionService: ElectionService;
12
- pendingTransactionsArchivist: ArchivistInstance;
12
+ pendingBundledTransactionsArchivist: ArchivistInstance;
13
13
  rewardService: BlockRewardService;
14
14
  stakeIntentService: StakeIntentService;
15
15
  validateHydratedBlockState: HydratedBlockStateValidationFunction;
@@ -20,7 +20,7 @@ export declare class XyoValidator<TParams extends XyoValidatorParams = XyoValida
20
20
  protected get chainArchivist(): TParams["chainArchivist"];
21
21
  protected get chainInfo(): TParams["chainInformation"];
22
22
  protected get electionService(): TParams["electionService"];
23
- protected get pendingTransactionsArchivist(): TParams["pendingTransactionsArchivist"];
23
+ protected get pendingBundledTransactionsArchivist(): TParams["pendingBundledTransactionsArchivist"];
24
24
  protected get rewardService(): TParams["rewardService"];
25
25
  validatePendingBlock(_block: BlockBoundWitness): Promisable<Error[]>;
26
26
  validatePendingTransaction(hydratedTransaction: HydratedTransaction): Promise<boolean>;
@@ -1 +1 @@
1
- {"version":3,"file":"XyoValidator.d.ts","sourceRoot":"","sources":["../../../src/ChainValidator/XyoValidator.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAA;AAC5D,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAA;AAE/E,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EACf,oCAAoC,EACpC,mBAAmB,EAEnB,kBAAkB,EACnB,MAAM,2BAA2B,CAAA;AAElC,OAAO,EAAE,WAAW,EAAoB,MAAM,mBAAmB,CAAA;AACjE,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAM5C,MAAM,WAAW,kBAAmB,SAAQ,iBAAiB;IAC3D,OAAO,EAAE,eAAe,CAAA;IACxB,cAAc,EAAE,aAAa,CAAA;IAC7B,gBAAgB,EAAE,gBAAgB,CAAA;IAClC,eAAe,EAAE,eAAe,CAAA;IAChC,4BAA4B,EAAE,iBAAiB,CAAA;IAC/C,aAAa,EAAE,kBAAkB,CAAA;IACjC,kBAAkB,EAAE,kBAAkB,CAAA;IACtC,0BAA0B,EAAE,oCAAoC,CAAA;CACjE;AAED,qBACa,YAAY,CAAC,OAAO,SAAS,kBAAkB,GAAG,kBAAkB,CAAE,SAAQ,WAAW,CAAC,OAAO,CAAE,YAAW,SAAS;IAClI,IAAI,OAAO,sBAEV;IAED,SAAS,KAAK,OAAO,uBAEpB;IAED,SAAS,KAAK,cAAc,8BAE3B;IAED,SAAS,KAAK,SAAS,gCAEtB;IAED,SAAS,KAAK,eAAe,+BAE5B;IAED,SAAS,KAAK,4BAA4B,4CAEzC;IAED,SAAS,KAAK,aAAa,6BAE1B;IAED,oBAAoB,CAAC,MAAM,EAAE,iBAAiB,GAAG,UAAU,CAAC,KAAK,EAAE,CAAC;IAK9D,0BAA0B,CAAC,mBAAmB,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC;CAQ7F"}
1
+ {"version":3,"file":"XyoValidator.d.ts","sourceRoot":"","sources":["../../../src/ChainValidator/XyoValidator.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAA;AAC5D,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAA;AAE/E,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EACf,oCAAoC,EACpC,mBAAmB,EAEnB,kBAAkB,EACnB,MAAM,2BAA2B,CAAA;AAElC,OAAO,EAAE,WAAW,EAAoB,MAAM,mBAAmB,CAAA;AACjE,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAM5C,MAAM,WAAW,kBAAmB,SAAQ,iBAAiB;IAC3D,OAAO,EAAE,eAAe,CAAA;IACxB,cAAc,EAAE,aAAa,CAAA;IAC7B,gBAAgB,EAAE,gBAAgB,CAAA;IAClC,eAAe,EAAE,eAAe,CAAA;IAChC,mCAAmC,EAAE,iBAAiB,CAAA;IACtD,aAAa,EAAE,kBAAkB,CAAA;IACjC,kBAAkB,EAAE,kBAAkB,CAAA;IACtC,0BAA0B,EAAE,oCAAoC,CAAA;CACjE;AAED,qBACa,YAAY,CAAC,OAAO,SAAS,kBAAkB,GAAG,kBAAkB,CAAE,SAAQ,WAAW,CAAC,OAAO,CAAE,YAAW,SAAS;IAClI,IAAI,OAAO,sBAEV;IAED,SAAS,KAAK,OAAO,uBAEpB;IAED,SAAS,KAAK,cAAc,8BAE3B;IAED,SAAS,KAAK,SAAS,gCAEtB;IAED,SAAS,KAAK,eAAe,+BAE5B;IAED,SAAS,KAAK,mCAAmC,mDAEhD;IAED,SAAS,KAAK,aAAa,6BAE1B;IAED,oBAAoB,CAAC,MAAM,EAAE,iBAAiB,GAAG,UAAU,CAAC,KAAK,EAAE,CAAC;IAK9D,0BAA0B,CAAC,mBAAmB,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC;CAQ7F"}
@@ -5,8 +5,8 @@ import { BaseService } from '../BaseService.ts';
5
5
  export interface XyoPendingTransactionsServiceParams extends BaseServiceParams {
6
6
  chainArchivist?: ArchivistInstance;
7
7
  chainIdentification?: ChainIdentification;
8
- pendingTransactionsArchivist?: ArchivistInstance;
9
- rejectedTransactionsArchivist?: ArchivistInstance;
8
+ pendingBundledTransactionsArchivist?: ArchivistInstance;
9
+ rejectedBundledTransactionsArchivist?: ArchivistInstance;
10
10
  }
11
11
  export declare class XyoPendingTransactionsService extends BaseService<XyoPendingTransactionsServiceParams> implements PendingTransactionsService {
12
12
  private static readonly MutexPriority;
@@ -19,11 +19,12 @@ export declare class XyoPendingTransactionsService extends BaseService<XyoPendin
19
19
  * A local Archivist optimized for fast retrieval that stores only validated
20
20
  * pending transactions
21
21
  */
22
- private _curatedPendingTransactionsArchivist;
22
+ private _curatedPendingBundledTransactionsArchivist;
23
23
  /**
24
24
  * The last count of total pending transactions
25
25
  */
26
26
  private _pendingTransactionsCount;
27
+ private _removablePendingTransactionHashes;
27
28
  /**
28
29
  * A mutex to ensure that the curated pending transactions archivist is
29
30
  * updated in a thread-safe manner
@@ -31,17 +32,17 @@ export declare class XyoPendingTransactionsService extends BaseService<XyoPendin
31
32
  private _updateCuratedPendingTransactionsArchivistMutex;
32
33
  private get chainArchivist();
33
34
  private get chainIdentification();
34
- private get pendingTransactionsArchivist();
35
+ private get pendingBundledTransactionsArchivist();
36
+ private get pendingBundledTransactionsLocalArchivist();
35
37
  private get pendingTransactionsCount();
36
- private get pendingTransactionsLocalArchivist();
37
- private get rejectedTransactionsArchivist();
38
+ private get rejectedBundledTransactionsArchivist();
38
39
  createHandler(): Promise<void>;
39
40
  getPendingTransactions(head: Hash, limit: number): Promise<HydratedTransactionWithStorageMeta[]>;
40
41
  private countPendingTransactions;
41
42
  private filterAlreadyFinalizedTransactions;
42
43
  private insertNewTransactions;
44
+ private removeBundledTransactions;
43
45
  private removeFinalizedTransactions;
44
- private removeRejectedTransactions;
45
- private removeTransactions;
46
+ private removeRejectedBundledTransactions;
46
47
  }
47
48
  //# sourceMappingURL=PendingTransactions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PendingTransactions.d.ts","sourceRoot":"","sources":["../../../src/PendingTransactions/PendingTransactions.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AAElC,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAA;AAKhE,OAAO,EAC6C,iBAAiB,EAAE,mBAAmB,EAAE,kCAAkC,EAC5H,0BAA0B,EAC3B,MAAM,2BAA2B,CAAA;AAIlC,OAAO,EAAE,WAAW,EAAoB,MAAM,mBAAmB,CAAA;AAEjE,MAAM,WAAW,mCAAoC,SAAQ,iBAAiB;IAC5E,cAAc,CAAC,EAAE,iBAAiB,CAAA;IAClC,mBAAmB,CAAC,EAAE,mBAAmB,CAAA;IACzC,4BAA4B,CAAC,EAAE,iBAAiB,CAAA;IAChD,6BAA6B,CAAC,EAAE,iBAAiB,CAAA;CAClD;AAED,qBACa,6BAA8B,SAAQ,WAAW,CAAC,mCAAmC,CAAE,YAAW,0BAA0B;IACvI,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAiB3B;IAEV;;;OAGG;IACH,OAAO,CAAC,8BAA8B,CAAc;IAEpD;;;OAGG;IACH,OAAO,CAAC,oCAAoC,CAA6B;IAEzE;;OAEG;IACH,OAAO,CAAC,yBAAyB,CAAY;IAE7C;;;OAGG;IACH,OAAO,CAAC,+CAA+C,CAAc;IAErE,OAAO,KAAK,cAAc,GAEzB;IAED,OAAO,KAAK,mBAAmB,GAE9B;IAED,OAAO,KAAK,4BAA4B,GAEvC;IAED,OAAO,KAAK,wBAAwB,GAGnC;IAED,OAAO,KAAK,iCAAiC,GAE5C;IAED,OAAO,KAAK,6BAA6B,GAExC;IAEc,aAAa;IA4BtB,sBAAsB,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,kCAAkC,EAAE,CAAC;YAsBxF,wBAAwB;YASxB,kCAAkC;YASlC,qBAAqB;YAyBrB,2BAA2B;YAI3B,0BAA0B;YAI1B,kBAAkB;CAWjC"}
1
+ {"version":3,"file":"PendingTransactions.d.ts","sourceRoot":"","sources":["../../../src/PendingTransactions/PendingTransactions.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AAElC,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAA;AAOhE,OAAO,EAC6C,iBAAiB,EACnE,mBAAmB,EAAE,kCAAkC,EAEvD,0BAA0B,EAC3B,MAAM,2BAA2B,CAAA;AAIlC,OAAO,EAAE,WAAW,EAAoB,MAAM,mBAAmB,CAAA;AAEjE,MAAM,WAAW,mCAAoC,SAAQ,iBAAiB;IAC5E,cAAc,CAAC,EAAE,iBAAiB,CAAA;IAClC,mBAAmB,CAAC,EAAE,mBAAmB,CAAA;IACzC,mCAAmC,CAAC,EAAE,iBAAiB,CAAA;IACvD,oCAAoC,CAAC,EAAE,iBAAiB,CAAA;CACzD;AAYD,qBACa,6BAA8B,SAAQ,WAAW,CAAC,mCAAmC,CAAE,YAAW,0BAA0B;IACvI,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAiB3B;IAEV;;;OAGG;IACH,OAAO,CAAC,8BAA8B,CAAc;IAEpD;;;OAGG;IACH,OAAO,CAAC,2CAA2C,CAA6B;IAEhF;;OAEG;IACH,OAAO,CAAC,yBAAyB,CAAY;IAE7C,OAAO,CAAC,kCAAkC,CAAuB;IAEjE;;;OAGG;IACH,OAAO,CAAC,+CAA+C,CAAc;IAErE,OAAO,KAAK,cAAc,GAEzB;IAED,OAAO,KAAK,mBAAmB,GAE9B;IAED,OAAO,KAAK,mCAAmC,GAE9C;IAED,OAAO,KAAK,wCAAwC,GAEnD;IAED,OAAO,KAAK,wBAAwB,GAGnC;IAED,OAAO,KAAK,oCAAoC,GAE/C;IAEc,aAAa;IA4BtB,sBAAsB,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,kCAAkC,EAAE,CAAC;YAgCxF,wBAAwB;YAQxB,kCAAkC;YAUlC,qBAAqB;YA8BrB,yBAAyB;IAgBvC,OAAO,CAAC,2BAA2B;IAOnC,OAAO,CAAC,iCAAiC;CAM1C"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "http://json.schemastore.org/package.json",
3
3
  "name": "@xyo-network/chain-services",
4
- "version": "1.5.11",
4
+ "version": "1.5.12",
5
5
  "description": "XYO Layer One SDK Services",
6
6
  "homepage": "https://xylabs.com",
7
7
  "bugs": {
@@ -46,24 +46,24 @@
46
46
  "@xylabs/promise": "^4.11.10",
47
47
  "@xylabs/telemetry": "^4.11.10",
48
48
  "@xylabs/typeof": "^4.11.10",
49
- "@xyo-network/account-model": "^3.18.0",
50
- "@xyo-network/archivist-memory": "^3.18.0",
51
- "@xyo-network/archivist-model": "^3.18.0",
52
- "@xyo-network/boundwitness-model": "^3.18.0",
53
- "@xyo-network/boundwitness-validator": "^3.18.0",
54
- "@xyo-network/boundwitness-wrapper": "^3.18.0",
55
- "@xyo-network/chain-analyze": "^1.5.11",
56
- "@xyo-network/chain-ethereum": "^1.5.11",
57
- "@xyo-network/chain-modules": "^1.5.11",
58
- "@xyo-network/chain-protocol": "^1.5.11",
59
- "@xyo-network/chain-utils": "^1.5.11",
60
- "@xyo-network/chain-validation": "^1.5.11",
61
- "@xyo-network/chain-wrappers": "^1.5.11",
62
- "@xyo-network/payload-builder": "^3.18.0",
63
- "@xyo-network/payload-model": "^3.18.0",
49
+ "@xyo-network/account-model": "^3.18.2",
50
+ "@xyo-network/archivist-memory": "^3.18.2",
51
+ "@xyo-network/archivist-model": "^3.18.2",
52
+ "@xyo-network/boundwitness-model": "^3.18.2",
53
+ "@xyo-network/boundwitness-validator": "^3.18.2",
54
+ "@xyo-network/boundwitness-wrapper": "^3.18.2",
55
+ "@xyo-network/chain-analyze": "^1.5.12",
56
+ "@xyo-network/chain-ethereum": "^1.5.12",
57
+ "@xyo-network/chain-modules": "^1.5.12",
58
+ "@xyo-network/chain-protocol": "^1.5.12",
59
+ "@xyo-network/chain-utils": "^1.5.12",
60
+ "@xyo-network/chain-validation": "^1.5.12",
61
+ "@xyo-network/chain-wrappers": "^1.5.12",
62
+ "@xyo-network/payload-builder": "^3.18.2",
63
+ "@xyo-network/payload-model": "^3.18.2",
64
64
  "@xyo-network/typechain": "^3.5.4",
65
65
  "@xyo-network/xl1-protocol": "^1.4.16",
66
- "@xyo-network/xl1-protocol-sdk": "^1.5.11",
66
+ "@xyo-network/xl1-protocol-sdk": "^1.5.12",
67
67
  "async-mutex": "^0.5.0",
68
68
  "ethers": "6.14.3",
69
69
  "lru-cache": "^11.1.0",
@@ -75,13 +75,13 @@
75
75
  "@xylabs/ts-scripts-yarn3": "^6.5.7",
76
76
  "@xylabs/tsconfig": "^6.5.7",
77
77
  "@xylabs/vitest-extended": "^4.11.10",
78
- "@xyo-network/account": "^3.18.0",
79
- "@xyo-network/account-model": "^3.18.0",
80
- "@xyo-network/chain-validation": "^1.5.11",
81
- "@xyo-network/wallet": "^3.18.0",
78
+ "@xyo-network/account": "^3.18.2",
79
+ "@xyo-network/account-model": "^3.18.2",
80
+ "@xyo-network/chain-validation": "^1.5.12",
81
+ "@xyo-network/wallet": "^3.18.2",
82
82
  "knip": "^5.59.1",
83
83
  "typescript": "^5.8.3",
84
- "vitest": "^3.2.0",
84
+ "vitest": "^3.2.1",
85
85
  "vitest-mock-extended": "^3.1.0"
86
86
  },
87
87
  "engines": {
@@ -40,7 +40,7 @@ export const XYO_PRODUCER_RESTAKE_WINDOW = 500n
40
40
  export interface XyoBlockProducerParams extends XyoValidatorParams {
41
41
  balanceService: AccountBalanceService
42
42
  pendingTransactionsService: PendingTransactionsService
43
- rejectedTransactionsArchivist: ArchivistInstance
43
+ rejectedBundledTransactionsArchivist: ArchivistInstance
44
44
  rewardAddress: Address
45
45
  }
46
46
 
@@ -80,8 +80,8 @@ export class XyoBlockProducer extends BaseService<XyoBlockProducerParams> implem
80
80
  return assertEx(this.params.pendingTransactionsService, () => 'Missing pendingTransactionsService')
81
81
  }
82
82
 
83
- protected get rejectedTransactionsArchivist() {
84
- return assertEx(this.params.rejectedTransactionsArchivist, () => 'No rejected transactions archivist')
83
+ protected get rejectedBundledTransactionsArchivist() {
84
+ return assertEx(this.params.rejectedBundledTransactionsArchivist, () => 'No rejected bundled transactions archivist')
85
85
  }
86
86
 
87
87
  protected get rewardAddress(): Address {
@@ -206,7 +206,7 @@ export class XyoBlockProducer extends BaseService<XyoBlockProducerParams> implem
206
206
  if (errors.length > 0) {
207
207
  this.logger?.warn(`Validation of produced block failed: ${errors.at(0)?.message}`)
208
208
  const rejectedTransactions = block[1]
209
- await this.rejectedTransactionsArchivist.insert(rejectedTransactions)
209
+ await this.rejectedBundledTransactionsArchivist.insert(rejectedTransactions)
210
210
  } else {
211
211
  return block
212
212
  }
@@ -27,7 +27,7 @@ export interface XyoValidatorParams extends BaseServiceParams {
27
27
  chainArchivist: ReadArchivist
28
28
  chainInformation: ChainInformation
29
29
  electionService: ElectionService
30
- pendingTransactionsArchivist: ArchivistInstance
30
+ pendingBundledTransactionsArchivist: ArchivistInstance
31
31
  rewardService: BlockRewardService
32
32
  stakeIntentService: StakeIntentService
33
33
  validateHydratedBlockState: HydratedBlockStateValidationFunction
@@ -55,8 +55,8 @@ export class XyoValidator<TParams extends XyoValidatorParams = XyoValidatorParam
55
55
  return assertEx(this.params.electionService, () => 'electionService is required')
56
56
  }
57
57
 
58
- protected get pendingTransactionsArchivist() {
59
- return assertEx(this.params.pendingTransactionsArchivist, () => 'pendingTransactions is required')
58
+ protected get pendingBundledTransactionsArchivist() {
59
+ return assertEx(this.params.pendingBundledTransactionsArchivist, () => 'pendingBundledTransactions is required')
60
60
  }
61
61
 
62
62
  protected get rewardService() {
@@ -1,5 +1,5 @@
1
1
  import { ValueType } from '@opentelemetry/api'
2
- import { filterAs, filterAsync } from '@xylabs/array'
2
+ import { filterAsync } from '@xylabs/array'
3
3
  import { assertEx } from '@xylabs/assert'
4
4
  import { exists } from '@xylabs/exists'
5
5
  import { forget } from '@xylabs/forget'
@@ -7,14 +7,18 @@ import { Hash } from '@xylabs/hex'
7
7
  import { MemoryArchivist } from '@xyo-network/archivist-memory'
8
8
  import { ArchivistInstance } from '@xyo-network/archivist-model'
9
9
  import { validateTransaction } from '@xyo-network/chain-validation'
10
+ import { PayloadBuilder } from '@xyo-network/payload-builder'
10
11
  import {
11
- Payload, Sequence, WithStorageMeta,
12
+ Payload,
13
+ PayloadBundle, Sequence, WithStorageMeta,
12
14
  } from '@xyo-network/payload-model'
13
15
  import {
14
- asOptionalTransactionBoundWitnessWithStorageMeta, BaseServiceParams, ChainIdentification, HydratedTransactionWithStorageMeta,
15
- PendingTransactionsService, TransactionBoundWitness,
16
+ asOptionalTransactionBoundWitnessWithStorageMeta, BaseServiceParams,
17
+ ChainIdentification, HydratedTransactionWithStorageMeta,
18
+ isTransactionBoundWitnessWithStorageMeta,
19
+ PendingTransactionsService,
16
20
  } from '@xyo-network/xl1-protocol'
17
- import { flattenHydratedTransactions, tryHydrateTransaction } from '@xyo-network/xl1-protocol-sdk'
21
+ import { flattenHydratedTransaction } from '@xyo-network/xl1-protocol-sdk'
18
22
  import { Mutex } from 'async-mutex'
19
23
 
20
24
  import { BaseService, creatableService } from '../BaseService.ts'
@@ -22,8 +26,18 @@ import { BaseService, creatableService } from '../BaseService.ts'
22
26
  export interface XyoPendingTransactionsServiceParams extends BaseServiceParams {
23
27
  chainArchivist?: ArchivistInstance
24
28
  chainIdentification?: ChainIdentification
25
- pendingTransactionsArchivist?: ArchivistInstance
26
- rejectedTransactionsArchivist?: ArchivistInstance
29
+ pendingBundledTransactionsArchivist?: ArchivistInstance
30
+ rejectedBundledTransactionsArchivist?: ArchivistInstance
31
+ }
32
+
33
+ async function bundledPayloadsToHydratedTransaction(
34
+ payload: WithStorageMeta<PayloadBundle>,
35
+ ): Promise<HydratedTransactionWithStorageMeta | undefined> {
36
+ const withStorageMeta = await PayloadBuilder.addStorageMeta(payload.payloads)
37
+ const tx = asOptionalTransactionBoundWitnessWithStorageMeta(withStorageMeta.find(p => p._hash === payload.root))
38
+ if (tx) {
39
+ return [tx, withStorageMeta.map(p => p._hash === payload.root ? undefined : p).filter(exists)]
40
+ }
27
41
  }
28
42
 
29
43
  @creatableService()
@@ -57,13 +71,15 @@ export class XyoPendingTransactionsService extends BaseService<XyoPendingTransac
57
71
  * A local Archivist optimized for fast retrieval that stores only validated
58
72
  * pending transactions
59
73
  */
60
- private _curatedPendingTransactionsArchivist: MemoryArchivist | undefined
74
+ private _curatedPendingBundledTransactionsArchivist: MemoryArchivist | undefined
61
75
 
62
76
  /**
63
77
  * The last count of total pending transactions
64
78
  */
65
79
  private _pendingTransactionsCount: number = 0
66
80
 
81
+ private _removablePendingTransactionHashes: Set<Hash> = new Set()
82
+
67
83
  /**
68
84
  * A mutex to ensure that the curated pending transactions archivist is
69
85
  * updated in a thread-safe manner
@@ -78,8 +94,12 @@ export class XyoPendingTransactionsService extends BaseService<XyoPendingTransac
78
94
  return assertEx(this.params.chainIdentification, () => 'No chain id')
79
95
  }
80
96
 
81
- private get pendingTransactionsArchivist() {
82
- return assertEx(this.params.pendingTransactionsArchivist, () => 'No pending transactions archivist')
97
+ private get pendingBundledTransactionsArchivist() {
98
+ return assertEx(this.params.pendingBundledTransactionsArchivist, () => 'No pending bundled transactions archivist')
99
+ }
100
+
101
+ private get pendingBundledTransactionsLocalArchivist() {
102
+ return assertEx(this._curatedPendingBundledTransactionsArchivist, () => 'No pending bundled transactions curated archivist')
83
103
  }
84
104
 
85
105
  private get pendingTransactionsCount() {
@@ -87,31 +107,27 @@ export class XyoPendingTransactionsService extends BaseService<XyoPendingTransac
87
107
  return this._pendingTransactionsCount
88
108
  }
89
109
 
90
- private get pendingTransactionsLocalArchivist() {
91
- return assertEx(this._curatedPendingTransactionsArchivist, () => 'No pending transactions curated archivist')
92
- }
93
-
94
- private get rejectedTransactionsArchivist() {
95
- return assertEx(this.params.rejectedTransactionsArchivist, () => 'No rejected transactions archivist')
110
+ private get rejectedBundledTransactionsArchivist() {
111
+ return assertEx(this.params.rejectedBundledTransactionsArchivist, () => 'No rejected bundled transactions archivist')
96
112
  }
97
113
 
98
114
  override async createHandler() {
99
115
  await super.createHandler()
100
- this._curatedPendingTransactionsArchivist = await MemoryArchivist.create({ account: 'random' })
116
+ this._curatedPendingBundledTransactionsArchivist = await MemoryArchivist.create({ account: 'random' })
101
117
 
102
118
  // On new pending transactions, insert them into the curated archivist
103
- this.pendingTransactionsArchivist.on('inserted', async ({ payloads }) => {
104
- await this.insertNewTransactions(payloads)
119
+ this.pendingBundledTransactionsArchivist.on('inserted', async ({ payloads }) => {
120
+ await this.insertNewTransactions(payloads as WithStorageMeta<PayloadBundle>[])
105
121
  })
106
122
 
107
123
  // On new finalized blocks, remove the transactions from the curated archivist
108
- this.chainArchivist.on('inserted', async ({ payloads }) => {
109
- await this.removeFinalizedTransactions(payloads)
124
+ this.chainArchivist.on('inserted', ({ payloads }) => {
125
+ this.removeFinalizedTransactions(payloads)
110
126
  })
111
127
 
112
128
  // On new rejected blocks, remove the transactions from the curated archivist
113
- this.rejectedTransactionsArchivist.on('inserted', async ({ payloads }) => {
114
- await this.removeRejectedTransactions(payloads)
129
+ this.rejectedBundledTransactionsArchivist.on('inserted', ({ payloads }) => {
130
+ this.removeRejectedBundledTransactions(payloads)
115
131
  })
116
132
 
117
133
  const pendingTransactionsGauge = this.meter?.createObservableGauge(
@@ -126,21 +142,31 @@ export class XyoPendingTransactionsService extends BaseService<XyoPendingTransac
126
142
  async getPendingTransactions(head: Hash, limit: number): Promise<HydratedTransactionWithStorageMeta[]> {
127
143
  return await this.spanAsync('getPendingTransactions', async () => {
128
144
  return await this._updateCuratedPendingTransactionsArchivistMutex.runExclusive(async () => {
129
- const foundPendingTransactions: WithStorageMeta<TransactionBoundWitness>[] = []
145
+ const foundPendingTransactions: HydratedTransactionWithStorageMeta[] = []
146
+ const foundPendingTransactionsToDeleteHashes: Hash[] = []
130
147
  let cursor: Sequence | undefined
131
148
  while (foundPendingTransactions.length < limit) {
132
- const payloads = await this.pendingTransactionsLocalArchivist.next({
149
+ const payloads = await this.pendingBundledTransactionsLocalArchivist.next({
133
150
  limit: 100, order: 'asc', cursor,
134
- })
151
+ }) as WithStorageMeta<PayloadBundle>[]
135
152
  if (payloads.length === 0) break
136
153
  cursor = payloads.at(-1)?._sequence
137
- const transactions = payloads.map(payload => asOptionalTransactionBoundWitnessWithStorageMeta(payload)).filter(exists)
154
+ const deletedTransactionBundles = payloads.filter(tx => this._removablePendingTransactionHashes.has(tx.root))
155
+ foundPendingTransactionsToDeleteHashes.push(...deletedTransactionBundles.map(tx => tx._hash).filter(exists))
156
+ const undeletedTransactionBundles = payloads.filter(tx => !this._removablePendingTransactionHashes.has(tx.root))
157
+ // add the items that are not to be deleted
158
+ const transactions = (await Promise.all(
159
+ undeletedTransactionBundles.map(p => bundledPayloadsToHydratedTransaction(p)),
160
+ )).filter(exists)
138
161
  foundPendingTransactions.push(...transactions)
139
162
  }
140
- const hydratedTransactions = await Promise.all(
141
- foundPendingTransactions.map(tx => tryHydrateTransaction(this.pendingTransactionsLocalArchivist, tx._hash)),
142
- )
143
- return hydratedTransactions.filter(exists)
163
+ // remove the hashes from delete queue
164
+ for (const hash of foundPendingTransactionsToDeleteHashes) {
165
+ this._removablePendingTransactionHashes.delete(hash)
166
+ }
167
+ // actually delete the bundles
168
+ await this.pendingBundledTransactionsLocalArchivist.delete(foundPendingTransactionsToDeleteHashes)
169
+ return foundPendingTransactions
144
170
  }, XyoPendingTransactionsService.MutexPriority.ReadTransactions)
145
171
  })
146
172
  }
@@ -148,30 +174,30 @@ export class XyoPendingTransactionsService extends BaseService<XyoPendingTransac
148
174
  private async countPendingTransactions() {
149
175
  if (this._countPendingTransactionsMutex.isLocked()) return
150
176
  await this._countPendingTransactionsMutex.runExclusive(async () => {
151
- const payloads = (await this._curatedPendingTransactionsArchivist?.all()) ?? []
152
- const pendingTransactions = filterAs(payloads, asOptionalTransactionBoundWitnessWithStorageMeta)
153
- this._pendingTransactionsCount = pendingTransactions.length
177
+ const payloads = (await this._curatedPendingBundledTransactionsArchivist?.all()) ?? []
178
+ this._pendingTransactionsCount = payloads.length
154
179
  })
155
180
  }
156
181
 
157
- private async filterAlreadyFinalizedTransactions(payloads: WithStorageMeta<Payload>[]): Promise<WithStorageMeta<TransactionBoundWitness>[]> {
158
- const incomingTransactions = filterAs(payloads, asOptionalTransactionBoundWitnessWithStorageMeta)
159
- const incomingTransactionHashes = incomingTransactions.map(payload => payload._hash)
182
+ private async filterAlreadyFinalizedTransactions(
183
+ incomingTransactions: WithStorageMeta<PayloadBundle>[],
184
+ ): Promise<WithStorageMeta<PayloadBundle>[]> {
185
+ const incomingTransactionHashes = incomingTransactions.map(payload => payload.root)
160
186
  const finalizedTransactions = await this.chainArchivist.get(incomingTransactionHashes)
161
187
  const finalizedTransactionHashes = new Set(finalizedTransactions.map(item => item._hash))
162
188
  const nonFinalizedTransactions = incomingTransactions.filter(item => !finalizedTransactionHashes.has(item._hash))
163
189
  return nonFinalizedTransactions
164
190
  }
165
191
 
166
- private async insertNewTransactions(payloads: WithStorageMeta<Payload>[]) {
192
+ private async insertNewTransactions(payloads: WithStorageMeta<PayloadBundle>[]) {
167
193
  this.logger?.log('insertNewTransactions', payloads)
168
194
  return await this.spanAsync('InsertNewTransactions', async () => {
169
195
  return await this._updateCuratedPendingTransactionsArchivistMutex.runExclusive(async () => {
170
196
  // Check incoming transactions against finalized transactions
171
197
  const unprocessedTransactions = await this.filterAlreadyFinalizedTransactions(payloads)
172
198
  // Hydrate all unprocessed transactions
173
- const hydratedUnprocessedTransactions = (await Promise.all(unprocessedTransactions.map((tx) => {
174
- return tryHydrateTransaction(this.pendingTransactionsArchivist, tx._hash)
199
+ const hydratedUnprocessedTransactions = (await Promise.all(unprocessedTransactions.map(async (tx) => {
200
+ return await bundledPayloadsToHydratedTransaction(tx)
175
201
  }))).filter(exists)
176
202
  // Filter to only valid transactions
177
203
  const validTransactions = await filterAsync(hydratedUnprocessedTransactions, async (tx) => {
@@ -182,29 +208,44 @@ export class XyoPendingTransactionsService extends BaseService<XyoPendingTransac
182
208
  return errors.length > 0 ? false : true
183
209
  })
184
210
  if (validTransactions.length > 0) {
185
- await this.pendingTransactionsLocalArchivist.insert(flattenHydratedTransactions(validTransactions))
211
+ await this.pendingBundledTransactionsLocalArchivist.insert(validTransactions.map((tx) => {
212
+ return {
213
+ root: tx[0]._hash,
214
+ payloads: flattenHydratedTransaction(tx),
215
+ } as PayloadBundle
216
+ }))
186
217
  }
187
218
  }, XyoPendingTransactionsService.MutexPriority.InsertNewTransactions)
188
219
  })
189
220
  }
190
221
 
191
- private async removeFinalizedTransactions(payloads: WithStorageMeta<Payload>[]) {
192
- return await this.removeTransactions(payloads, 'RemoveFinalizedTransactions')
193
- }
194
-
195
- private async removeRejectedTransactions(payloads: WithStorageMeta<Payload>[]) {
196
- return await this.removeTransactions(payloads, 'RemoveRejectedTransactions')
197
- }
198
-
199
- private async removeTransactions(
200
- payloads: WithStorageMeta<Payload>[],
222
+ private async removeBundledTransactions(
223
+ bundledPayloads: WithStorageMeta<PayloadBundle>[],
201
224
  priority: keyof typeof XyoPendingTransactionsService.MutexPriority,
202
225
  ) {
203
226
  return await this.spanAsync(priority, async () => {
204
227
  return await this._updateCuratedPendingTransactionsArchivistMutex.runExclusive(async () => {
205
- const transactions = filterAs(payloads, asOptionalTransactionBoundWitnessWithStorageMeta)
206
- await this.pendingTransactionsLocalArchivist.delete(transactions.map(tx => tx._hash))
228
+ const bundledTransactions = (await Promise.all(bundledPayloads.map(async (payload) => {
229
+ const withStorageMeta = await PayloadBuilder.addStorageMeta(payload.payloads)
230
+ const tx = asOptionalTransactionBoundWitnessWithStorageMeta(withStorageMeta.find(p => p._hash === payload.root))
231
+ return tx !== undefined && payload._hash !== undefined ? tx : undefined
232
+ }))).filter(exists)
233
+ await this.pendingBundledTransactionsLocalArchivist.delete(bundledTransactions.map(btx => btx._hash))
207
234
  }, XyoPendingTransactionsService.MutexPriority[priority])
208
235
  })
209
236
  }
237
+
238
+ private removeFinalizedTransactions(payloads: WithStorageMeta<Payload>[]) {
239
+ const finalizedTransactionHashes = payloads.filter(isTransactionBoundWitnessWithStorageMeta).map(p => p._hash)
240
+ for (const hash of finalizedTransactionHashes) {
241
+ this._removablePendingTransactionHashes.add(hash)
242
+ }
243
+ }
244
+
245
+ private removeRejectedBundledTransactions(payloads: WithStorageMeta<Payload>[]) {
246
+ const rejectedTransactionHashes = payloads.filter(isTransactionBoundWitnessWithStorageMeta).map(p => p._hash)
247
+ for (const hash of rejectedTransactionHashes) {
248
+ this._removablePendingTransactionHashes.add(hash)
249
+ }
250
+ }
210
251
  }