@xyo-network/chain-services 1.16.26 → 1.17.0

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 (37) hide show
  1. package/dist/neutral/AccountBalance/BaseAccountBalanceService.d.ts +2 -3
  2. package/dist/neutral/AccountBalance/BaseAccountBalanceService.d.ts.map +1 -1
  3. package/dist/neutral/AccountBalance/accountBalanceServiceFromArchivist.d.ts.map +1 -1
  4. package/dist/neutral/BlockProducer/BaseBlockProducerService.d.ts +4 -4
  5. package/dist/neutral/BlockProducer/BaseBlockProducerService.d.ts.map +1 -1
  6. package/dist/neutral/ChainBlockNumberIteration/ChainBlockNumberIterationService.d.ts +20 -10
  7. package/dist/neutral/ChainBlockNumberIteration/ChainBlockNumberIterationService.d.ts.map +1 -1
  8. package/dist/neutral/ChainService/Evm/Evm.d.ts +4 -4
  9. package/dist/neutral/ChainService/Evm/Evm.d.ts.map +1 -1
  10. package/dist/neutral/ChainService/Memory/Memory.d.ts +4 -4
  11. package/dist/neutral/ChainService/Memory/Memory.d.ts.map +1 -1
  12. package/dist/neutral/ChainValidator/XyoValidator.d.ts +4 -4
  13. package/dist/neutral/ChainValidator/XyoValidator.d.ts.map +1 -1
  14. package/dist/neutral/Election/BaseElectionService.d.ts +3 -3
  15. package/dist/neutral/Election/BaseElectionService.d.ts.map +1 -1
  16. package/dist/neutral/PendingTransactions/BasePendingTransactions.d.ts +3 -4
  17. package/dist/neutral/PendingTransactions/BasePendingTransactions.d.ts.map +1 -1
  18. package/dist/neutral/StakeIntent/XyoStakeIntentService.d.ts +3 -3
  19. package/dist/neutral/StakeIntent/XyoStakeIntentService.d.ts.map +1 -1
  20. package/dist/neutral/Time/BaseTimeSyncService.d.ts +3 -6
  21. package/dist/neutral/Time/BaseTimeSyncService.d.ts.map +1 -1
  22. package/dist/neutral/blockViewerFromChainIteratorAndArchivist.d.ts.map +1 -1
  23. package/dist/neutral/index.mjs +115 -67
  24. package/dist/neutral/index.mjs.map +1 -1
  25. package/package.json +10 -10
  26. package/src/AccountBalance/BaseAccountBalanceService.ts +2 -4
  27. package/src/AccountBalance/accountBalanceServiceFromArchivist.ts +3 -2
  28. package/src/BlockProducer/BaseBlockProducerService.ts +5 -5
  29. package/src/ChainBlockNumberIteration/ChainBlockNumberIterationService.ts +61 -5
  30. package/src/ChainService/Evm/Evm.ts +34 -32
  31. package/src/ChainService/Memory/Memory.ts +9 -7
  32. package/src/ChainValidator/XyoValidator.ts +6 -6
  33. package/src/Election/BaseElectionService.ts +5 -4
  34. package/src/PendingTransactions/BasePendingTransactions.ts +6 -5
  35. package/src/StakeIntent/XyoStakeIntentService.ts +9 -13
  36. package/src/Time/BaseTimeSyncService.ts +6 -16
  37. package/src/blockViewerFromChainIteratorAndArchivist.ts +12 -0
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.16.26",
4
+ "version": "1.17.0",
5
5
  "description": "XYO Layer One SDK Services",
6
6
  "homepage": "https://xylabs.com",
7
7
  "bugs": {
@@ -48,17 +48,17 @@
48
48
  "@xyo-network/boundwitness-model": "~5.2.10",
49
49
  "@xyo-network/boundwitness-validator": "~5.2.10",
50
50
  "@xyo-network/boundwitness-wrapper": "~5.2.10",
51
- "@xyo-network/chain-analyze": "~1.16.26",
52
- "@xyo-network/chain-modules": "~1.16.26",
53
- "@xyo-network/chain-protocol": "~1.16.26",
54
- "@xyo-network/chain-utils": "~1.16.26",
51
+ "@xyo-network/chain-analyze": "~1.17.0",
52
+ "@xyo-network/chain-modules": "~1.17.0",
53
+ "@xyo-network/chain-protocol": "~1.17.0",
54
+ "@xyo-network/chain-utils": "~1.17.0",
55
55
  "@xyo-network/payload-builder": "~5.2.10",
56
56
  "@xyo-network/payload-model": "~5.2.10",
57
57
  "@xyo-network/typechain": "~4.0.10",
58
58
  "@xyo-network/xl1-protocol": "~1.14.15",
59
- "@xyo-network/xl1-protocol-sdk": "~1.16.26",
60
- "@xyo-network/xl1-validation": "~1.16.26",
61
- "@xyo-network/xl1-wrappers": "~1.16.26",
59
+ "@xyo-network/xl1-protocol-sdk": "~1.17.0",
60
+ "@xyo-network/xl1-validation": "~1.17.0",
61
+ "@xyo-network/xl1-wrappers": "~1.17.0",
62
62
  "async-mutex": "~0.5.0",
63
63
  "ethers": "6.15.0",
64
64
  "lru-cache": "~11.2.2",
@@ -72,12 +72,12 @@
72
72
  "@xylabs/vitest-extended": "~5.0.46",
73
73
  "@xyo-network/account": "~5.2.10",
74
74
  "@xyo-network/account-model": "~5.2.10",
75
- "@xyo-network/chain-validation": "~1.16.26",
75
+ "@xyo-network/chain-validation": "~1.17.0",
76
76
  "@xyo-network/wallet": "~5.2.10",
77
77
  "eslint": "^9.39.1",
78
78
  "tslib": "~2.8.1",
79
79
  "typescript": "~5.9.3",
80
- "vitest": "~4.0.13",
80
+ "vitest": "~4.0.14",
81
81
  "vitest-mock-extended": "~3.1.0",
82
82
  "web3-types": "~1.10.0"
83
83
  },
@@ -10,7 +10,6 @@ import {
10
10
  balancesSummary,
11
11
  BalanceStepSummaryContext,
12
12
  BlockViewer,
13
- EventingChainBlockNumberIteratorService,
14
13
  SimpleAccountBalanceViewer,
15
14
  TransfersStepSummaryContext,
16
15
  } from '@xyo-network/xl1-protocol-sdk'
@@ -30,9 +29,8 @@ export const BaseAccountBalanceServiceParamsZod = z.object({
30
29
  export interface BaseAccountBalanceServiceParams extends BaseServiceParams {
31
30
  blockViewer: BlockViewer
32
31
  chainArchivist: ReadArchivist
33
- chainIterator: EventingChainBlockNumberIteratorService
34
32
  context: BalanceStepSummaryContext
35
- transferContext: TransfersStepSummaryContext
33
+ transfersSummaryContext: TransfersStepSummaryContext
36
34
  }
37
35
 
38
36
  @creatable()
@@ -93,7 +91,7 @@ export class BaseAccountBalanceService extends BaseService<BaseAccountBalanceSer
93
91
  override async createHandler() {
94
92
  this.accountBalanceViewer = await SimpleAccountBalanceViewer.create({
95
93
  context: this.params.context,
96
- transferContext: this.params.transferContext,
94
+ transfersSummaryContext: this.params.transfersSummaryContext,
97
95
  blockViewer: this.blockViewer,
98
96
  })
99
97
  }
@@ -1,12 +1,13 @@
1
1
  import type { Hash } from '@xylabs/sdk-js'
2
2
  import { assertEx } from '@xylabs/sdk-js'
3
3
  import type { ReadArchivist } from '@xyo-network/archivist-model'
4
- import { findMostRecentBlock } from '@xyo-network/chain-protocol'
5
4
  import type { Payload, WithStorageMeta } from '@xyo-network/payload-model'
6
5
  import type { ChainId } from '@xyo-network/xl1-protocol'
7
6
  import { StepSizes } from '@xyo-network/xl1-protocol'
8
7
  import type { AccountBalanceViewer, BalancesStepSummary } from '@xyo-network/xl1-protocol-sdk'
9
- import { LruCacheMap, readPayloadMapFromStore } from '@xyo-network/xl1-protocol-sdk'
8
+ import {
9
+ findMostRecentBlock, LruCacheMap, readPayloadMapFromStore,
10
+ } from '@xyo-network/xl1-protocol-sdk'
10
11
  import { Semaphore } from 'async-mutex'
11
12
 
12
13
  import { BaseAccountBalanceService } from './BaseAccountBalanceService.ts'
@@ -15,7 +15,7 @@ import {
15
15
  Transfer, XYO_STEP_REWARD_ADDRESS,
16
16
  } from '@xyo-network/xl1-protocol'
17
17
  import {
18
- AccountBalanceViewer, BlockProducerService, Config, PendingTransactionsService, StakeIntentService, TimeSyncViewer,
18
+ AccountBalanceViewer, BlockProducerService, Config, MempoolViewer, StakeIntentService, TimeSyncViewer,
19
19
  } from '@xyo-network/xl1-protocol-sdk'
20
20
  import z from 'zod'
21
21
 
@@ -49,7 +49,7 @@ export const BaseBlockProducerServiceParamsZod = z.object({
49
49
 
50
50
  export interface BaseBlockProducerServiceParams extends XyoValidatorParams<Pick<Config, 'producer'>> {
51
51
  balanceService: AccountBalanceViewer
52
- pendingTransactionsService: PendingTransactionsService
52
+ pendingTransactionsService: MempoolViewer
53
53
  rejectedTransactionsArchivist: ArchivistInstance
54
54
  rewardAddress: Address
55
55
  time: TimeSyncViewer
@@ -94,8 +94,8 @@ export class BaseBlockProducerService extends BaseService<BaseBlockProducerServi
94
94
  return assertEx(this.params.balanceService, () => 'balanceService is required')
95
95
  }
96
96
 
97
- protected get chainArchivist() {
98
- return assertEx(this.params.chainArchivist, () => 'chainArchivist is required')
97
+ protected get blockViewer() {
98
+ return assertEx(this.params.blockViewer, () => 'blockViewer is required')
99
99
  }
100
100
 
101
101
  protected get chainId() {
@@ -203,7 +203,7 @@ export class BaseBlockProducerService extends BaseService<BaseBlockProducerServi
203
203
  const { block: previousBlock } = assertEx(asBlockBoundWitness(head), () => 'Invalid head block')
204
204
  const nextBlock = previousBlock + 1
205
205
  const nextBlockTransactionsStart = Date.now()
206
- const nextBlockTransactions = await this.pendingTransactionsService.getPendingTransactions(head._hash, BaseBlockProducerService.DefaultBlockSize)
206
+ const nextBlockTransactions = await this.pendingTransactionsService.pendingTransactions({ limit: BaseBlockProducerService.DefaultBlockSize })
207
207
  const nextBlockTransactionsDuration = Date.now() - nextBlockTransactionsStart
208
208
  if (nextBlockTransactionsDuration > 200) {
209
209
  this.logger?.warn(`[Slow] Fetched ${nextBlockTransactions.length} pending transactions in ${nextBlockTransactionsDuration}ms}`)
@@ -1,24 +1,30 @@
1
- import type { Hex } from '@xylabs/sdk-js'
1
+ import type { Hash, Hex } from '@xylabs/sdk-js'
2
2
  import {
3
3
  assertEx,
4
4
  isDefined, isNull, isUndefined,
5
5
  } from '@xylabs/sdk-js'
6
6
  import { PayloadBuilder } from '@xyo-network/payload-builder'
7
7
  import type { Payload, WithStorageMeta } from '@xyo-network/payload-model'
8
- import type { BlockBoundWitness } from '@xyo-network/xl1-protocol'
8
+ import type {
9
+ BlockBoundWitness, SignedHydratedBlockWithHashMeta, XL1BlockNumber,
10
+ } from '@xyo-network/xl1-protocol'
9
11
  import {
10
- asBlockBoundWitness, asBlockBoundWitnessWithStorageMeta, isBlockBoundWitnessWithHashMeta,
12
+ asBlockBoundWitness, asBlockBoundWitnessWithStorageMeta, asSignedHydratedBlockWithHashMeta, asXL1BlockNumber, isBlockBoundWitnessWithHashMeta,
11
13
  } from '@xyo-network/xl1-protocol'
12
14
  import type {
13
- ChainIteratorServiceEventData, EventingChainBlockNumberIteratorService, PayloadMapRead,
15
+ BlockViewer,
16
+ ChainIteratorServiceEventData,
17
+ ChainStoreRead,
18
+ PayloadMapRead,
14
19
  } from '@xyo-network/xl1-protocol-sdk'
20
+ import { hydrateBlock } from '@xyo-network/xl1-protocol-sdk'
15
21
  import { LRUCache } from 'lru-cache'
16
22
 
17
23
  import { BaseService } from '../BaseService.ts'
18
24
  import type { XyoChainIteratorParams } from './model/index.ts'
19
25
 
20
26
  export class ChainBlockNumberIterationService extends BaseService<XyoChainIteratorParams, ChainIteratorServiceEventData>
21
- implements EventingChainBlockNumberIteratorService {
27
+ implements BlockViewer {
22
28
  protected _blocksByBlockNumber = new LRUCache<number, WithStorageMeta<BlockBoundWitness>>({ max: 10_000 })
23
29
  protected _currentHead: WithStorageMeta<BlockBoundWitness> | undefined
24
30
 
@@ -26,6 +32,56 @@ export class ChainBlockNumberIterationService extends BaseService<XyoChainIterat
26
32
 
27
33
  get chainMap(): PayloadMapRead<WithStorageMeta<Payload>> { return assertEx(this.params.chainMap) }
28
34
 
35
+ get chainStoreRead() {
36
+ return { chainMap: this.chainMap } satisfies ChainStoreRead
37
+ }
38
+
39
+ async blockByHash(hash: Hash): Promise<SignedHydratedBlockWithHashMeta | null> {
40
+ return asSignedHydratedBlockWithHashMeta(await hydrateBlock(this.chainStoreRead, hash)) ?? null
41
+ }
42
+
43
+ async blockByNumber(block: XL1BlockNumber): Promise<SignedHydratedBlockWithHashMeta | null> {
44
+ return asSignedHydratedBlockWithHashMeta(await this.get(block)) ?? null
45
+ }
46
+
47
+ async blocksByHash(hash: Hash, limit: number = 100): Promise<SignedHydratedBlockWithHashMeta[]> {
48
+ const results: SignedHydratedBlockWithHashMeta[] = []
49
+ let currentBlock = await this.blockByHash(hash)
50
+ while (currentBlock !== null && (isUndefined(limit) || results.length < limit)) {
51
+ results.push(currentBlock)
52
+ const previousHash = currentBlock[0].previous
53
+ if (isNull(previousHash)) break
54
+ currentBlock = await this.blockByHash(previousHash)
55
+ }
56
+ return results
57
+ }
58
+
59
+ async blocksByNumber(blockNumber: XL1BlockNumber, limit: number = 100): Promise<SignedHydratedBlockWithHashMeta[]> {
60
+ const results: SignedHydratedBlockWithHashMeta[] = []
61
+ let currentBlock = await this.blockByNumber(blockNumber)
62
+ while (currentBlock !== null && (isUndefined(limit) || results.length < limit)) {
63
+ results.push(currentBlock)
64
+ if (currentBlock[0].block === 0) break
65
+ const previousNumber = asXL1BlockNumber(currentBlock[0].block - 1, true)
66
+ currentBlock = await this.blockByNumber(previousNumber)
67
+ }
68
+ return results
69
+ }
70
+
71
+ async currentBlock(): Promise<SignedHydratedBlockWithHashMeta> {
72
+ return assertEx(await this.blockByHash(await this.currentBlockHash()), () => 'Current block not found')
73
+ }
74
+
75
+ async currentBlockHash(): Promise<Hash> {
76
+ const head = assertEx(await this.head(), () => 'Head is not set')
77
+ return head._hash
78
+ }
79
+
80
+ async currentBlockNumber(): Promise<XL1BlockNumber> {
81
+ const head = assertEx(await this.head(), () => 'Head is not set')
82
+ return head.block
83
+ }
84
+
29
85
  async get(block: number): Promise<WithStorageMeta<BlockBoundWitness>> {
30
86
  const head = await this.head()
31
87
  // if(isUndefined(head)) return undefined
@@ -1,4 +1,6 @@
1
- import type { Address } from '@xylabs/sdk-js'
1
+ import type {
2
+ Address, Hex, Promisable,
3
+ } from '@xylabs/sdk-js'
2
4
  import {
3
5
  assertEx, toAddress, toEthAddress,
4
6
  } from '@xylabs/sdk-js'
@@ -13,7 +15,7 @@ import type { BaseServiceParams } from '../../model/index.ts'
13
15
 
14
16
  export interface EvmChainServiceParams extends BaseServiceParams {
15
17
  contract: StakedXyoChain
16
- id: Address
18
+ id: Hex
17
19
  runner: ContractRunner
18
20
  }
19
21
 
@@ -21,91 +23,91 @@ export interface EvmChainServiceParams extends BaseServiceParams {
21
23
  * A class that represents a chain stake as backed by an EVM smart contract
22
24
  */
23
25
  export class EvmChainService extends BaseService<EvmChainServiceParams> implements ChainService {
24
- get chainId(): Address {
25
- return assertEx(this.params.id)
26
- }
27
-
28
- get contract() {
29
- if (this.params.contract === undefined) {
30
- this.params.contract = StakedXyoChainFactory.connect(
31
- toEthAddress(this.chainId),
32
- this.params.runner,
33
- ) as StakedXyoChain
34
- }
35
- return assertEx(this.params.contract)
36
- }
37
-
38
26
  get runner(): ContractRunner {
39
27
  return assertEx(this.params.runner)
40
28
  }
41
29
 
42
30
  async active(): Promise<bigint> {
43
- return await this.contract.active()
31
+ return await (await this.contract()).active()
44
32
  }
45
33
 
46
34
  async activeByStaked(staked: Address): Promise<bigint> {
47
- return await this.contract.activeByAddressStaked(getAddress(toEthAddress(staked)))
35
+ return await (await this.contract()).activeByAddressStaked(getAddress(toEthAddress(staked)))
48
36
  }
49
37
 
50
38
  async activeByStaker(address: Address): Promise<bigint> {
51
- return await this.contract.activeByStaker(getAddress(toEthAddress(address)))
39
+ return await (await this.contract()).activeByStaker(getAddress(toEthAddress(address)))
52
40
  }
53
41
 
54
42
  async addStake(staked: Address, amount: bigint): Promise<boolean> {
55
- const result = await this.contract.addStake(getAddress(toEthAddress(staked)), amount)
43
+ const result = await (await this.contract()).addStake(getAddress(toEthAddress(staked)), amount)
56
44
  await result.wait()
57
45
  return true
58
46
  }
59
47
 
48
+ chainId(): Promisable<Hex> {
49
+ return assertEx(this.params.id)
50
+ }
51
+
52
+ async contract() {
53
+ if (this.params.contract === undefined) {
54
+ this.params.contract = StakedXyoChainFactory.connect(
55
+ toEthAddress(await this.chainId()),
56
+ this.params.runner,
57
+ ) as StakedXyoChain
58
+ }
59
+ return assertEx(this.params.contract)
60
+ }
61
+
60
62
  async forkedAtBlockNumber(): Promise<bigint> {
61
- return await this.contract.forkedAtBlockNumber()
63
+ return await (await this.contract()).forkedAtBlockNumber()
62
64
  }
63
65
 
64
66
  async forkedAtHash(): Promise<bigint> {
65
- return await this.contract.forkedAtHash()
67
+ return await (await this.contract()).forkedAtHash()
66
68
  }
67
69
 
68
70
  async forkedChainId(): Promise<Address> {
69
- return toAddress(await this.contract.forkedChainId())
71
+ return toAddress(await (await this.contract()).forkedChainId())
70
72
  }
71
73
 
72
74
  async minWithdrawalBlocks(): Promise<bigint> {
73
- return await this.contract.minWithdrawalBlocks()
75
+ return await (await this.contract()).minWithdrawalBlocks()
74
76
  }
75
77
 
76
78
  async pending(): Promise<bigint> {
77
- return await this.contract.pending()
79
+ return await (await this.contract()).pending()
78
80
  }
79
81
 
80
82
  async pendingByStaker(staker: Address): Promise<bigint> {
81
- return await this.contract.pendingByStaker(getAddress(toEthAddress(staker)))
83
+ return await (await this.contract()).pendingByStaker(getAddress(toEthAddress(staker)))
82
84
  }
83
85
 
84
86
  async removeStake(slot: bigint): Promise<boolean> {
85
- const result = await this.contract.removeStake(slot)
87
+ const result = await (await this.contract()).removeStake(slot)
86
88
  await result.wait()
87
89
  return true
88
90
  }
89
91
 
90
92
  async rewardsContract(): Promise<string> {
91
- return await this.contract.rewardsContract()
93
+ return await (await this.contract()).rewardsContract()
92
94
  }
93
95
 
94
96
  async stakingTokenAddress(): Promise<string> {
95
- return await this.contract.stakingTokenAddress()
97
+ return await (await this.contract()).stakingTokenAddress()
96
98
  }
97
99
 
98
100
  async withdrawStake(slot: bigint): Promise<boolean> {
99
- const result = await this.contract.withdrawStake(slot)
101
+ const result = await (await this.contract()).withdrawStake(slot)
100
102
  await result.wait()
101
103
  return true
102
104
  }
103
105
 
104
106
  async withdrawn(): Promise<bigint> {
105
- return await this.contract.withdrawn()
107
+ return await (await this.contract()).withdrawn()
106
108
  }
107
109
 
108
110
  async withdrawnByStaker(staker: string): Promise<bigint> {
109
- return await this.contract.withdrawnByStaker(getAddress(staker))
111
+ return await (await this.contract()).withdrawnByStaker(getAddress(staker))
110
112
  }
111
113
  }
@@ -1,4 +1,6 @@
1
- import type { Address } from '@xylabs/sdk-js'
1
+ import type {
2
+ Address, Hex, Promisable,
3
+ } from '@xylabs/sdk-js'
2
4
  import {
3
5
  assertEx, toAddress, ZERO_ADDRESS,
4
6
  } from '@xylabs/sdk-js'
@@ -8,20 +10,16 @@ import { BaseService } from '../../BaseService.ts'
8
10
  import type { BaseServiceParams } from '../../model/index.ts'
9
11
 
10
12
  export interface MemoryChainServiceParams extends BaseServiceParams<Pick<Config, 'producer'>> {
11
- chainId: Address
13
+ chainId: Hex
12
14
  }
13
15
 
14
16
  /**
15
17
  * A class that represents a chain stake as backed in memory
16
18
  */
17
19
  export class MemoryChainService extends BaseService<MemoryChainServiceParams> implements ChainService {
18
- protected _chainId: Address | undefined
20
+ protected _chainId: Hex | undefined
19
21
  protected _simulatedStake: bigint = 1n
20
22
 
21
- get chainId(): Address {
22
- return assertEx(this._chainId, () => 'Chain ID not set')
23
- }
24
-
25
23
  async active(): Promise<bigint> {
26
24
  return await Promise.resolve(this._simulatedStake)
27
25
  }
@@ -38,6 +36,10 @@ export class MemoryChainService extends BaseService<MemoryChainServiceParams> im
38
36
  return await Promise.resolve(true)
39
37
  }
40
38
 
39
+ chainId(): Promisable<Hex> {
40
+ return assertEx(this._chainId, () => 'Chain ID not set')
41
+ }
42
+
41
43
  override createHandler(): void {
42
44
  const { minStake = 1 } = this.params.config.producer ?? {}
43
45
  this._simulatedStake = BigInt(minStake)
@@ -3,14 +3,14 @@ import {
3
3
  Promisable,
4
4
  } from '@xylabs/sdk-js'
5
5
  import { AccountInstance } from '@xyo-network/account-model'
6
- import { ArchivistInstance, ReadArchivist } from '@xyo-network/archivist-model'
6
+ import { ArchivistInstance } from '@xyo-network/archivist-model'
7
7
  import {
8
8
  BlockBoundWitness,
9
9
  ChainId,
10
10
  SignedHydratedTransactionWithStorageMeta,
11
11
  } from '@xyo-network/xl1-protocol'
12
12
  import {
13
- BlockRewardService, ElectionService, HydratedBlockStateValidationFunction, StakeIntentService,
13
+ BlockRewardService, BlockViewer, ElectionService, HydratedBlockStateValidationFunction, StakeIntentService,
14
14
  } from '@xyo-network/xl1-protocol-sdk'
15
15
 
16
16
  import { BaseService } from '../BaseService.ts'
@@ -19,7 +19,7 @@ import { Validator } from './model/index.ts'
19
19
 
20
20
  export interface XyoValidatorParams<TConfig extends EmptyObject = EmptyObject> extends BaseServiceParams<TConfig> {
21
21
  account: AccountInstance
22
- chainArchivist: ReadArchivist
22
+ blockViewer: BlockViewer
23
23
  chainId: ChainId
24
24
  electionService: ElectionService
25
25
  pendingBundledTransactionsArchivist: ArchivistInstance
@@ -38,8 +38,8 @@ export class XyoValidator<TParams extends XyoValidatorParams = XyoValidatorParam
38
38
  return assertEx(this.params.account, () => 'account is required')
39
39
  }
40
40
 
41
- protected get chainArchivist() {
42
- return assertEx(this.params.chainArchivist, () => 'chainArchivist is required')
41
+ protected get blockViewer() {
42
+ return assertEx(this.params.blockViewer, () => 'blockViewer is required')
43
43
  }
44
44
 
45
45
  protected get chainInfo() {
@@ -66,7 +66,7 @@ export class XyoValidator<TParams extends XyoValidatorParams = XyoValidatorParam
66
66
  async validatePendingTransaction(hydratedTransaction: SignedHydratedTransactionWithStorageMeta): Promise<boolean> {
67
67
  const [tx] = hydratedTransaction
68
68
  // Ensure not confirmed already (replay attack)
69
- if ((await this.chainArchivist.get([tx._hash])).length > 0) return false
69
+ if ((await this.blockViewer.blockByHash(tx._hash)) !== undefined) return false
70
70
  // TODO: Ensure transaction is valid (double spend, has voucher, has required stake, etc.)
71
71
  // TODO: Ensure validator stake is valid
72
72
  return await Promise.resolve(true)
@@ -5,22 +5,23 @@ import { hexToLast4BytesInt, shuffleWithSeed } from '@xyo-network/chain-utils'
5
5
  import { WithHashMeta } from '@xyo-network/payload-model'
6
6
  import { BlockBoundWitness } from '@xyo-network/xl1-protocol'
7
7
  import type {
8
- ChainBlockNumberIteratorService, ChainStakeViewer, ElectionService, StakeIntentService,
8
+ BlockViewer,
9
+ ChainStakeViewer, ElectionService, StakeIntentService,
9
10
  } from '@xyo-network/xl1-protocol-sdk'
10
11
 
11
12
  import { BaseService } from '../BaseService.ts'
12
13
  import { BaseServiceParams } from '../model/index.ts'
13
14
 
14
15
  export interface BaseElectionServicesParams extends BaseServiceParams {
15
- chainIterator?: ChainBlockNumberIteratorService
16
+ blockViewer?: BlockViewer
16
17
  chainStakeViewer?: ChainStakeViewer
17
18
  stakeIntentService?: StakeIntentService
18
19
  }
19
20
 
20
21
  @creatable()
21
22
  export class BaseElectionService extends BaseService<BaseElectionServicesParams> implements ElectionService {
22
- get chainIterator() {
23
- return assertEx(this.params.chainIterator, () => 'No chain iterator')
23
+ get blockViewer() {
24
+ return assertEx(this.params.blockViewer, () => 'No block viewer')
24
25
  }
25
26
 
26
27
  get chainStakeViewer() {
@@ -7,7 +7,6 @@ import {
7
7
  } from '@xylabs/sdk-js'
8
8
  import { MemoryArchivist } from '@xyo-network/archivist-memory'
9
9
  import { ArchivistInstance } from '@xyo-network/archivist-model'
10
- import { findMostRecentBlock } from '@xyo-network/chain-protocol'
11
10
  import {
12
11
  Payload, PayloadBundle, Sequence, WithStorageMeta,
13
12
  } from '@xyo-network/payload-model'
@@ -17,7 +16,9 @@ import {
17
16
  SignedHydratedTransactionWithStorageMeta,
18
17
  XL1BlockNumber,
19
18
  } from '@xyo-network/xl1-protocol'
20
- import { PendingTransactionsService } from '@xyo-network/xl1-protocol-sdk'
19
+ import {
20
+ findMostRecentBlock, MempoolViewer, PendingTransactionsOptions,
21
+ } from '@xyo-network/xl1-protocol-sdk'
21
22
  import { TransactionJsonSchemaValidator, validateTransaction } from '@xyo-network/xl1-validation'
22
23
  import { Mutex } from 'async-mutex'
23
24
 
@@ -35,7 +36,7 @@ export interface BasePendingTransactionsServiceParams extends BaseServiceParams
35
36
  }
36
37
 
37
38
  @creatable()
38
- export class BasePendingTransactionsService extends BaseService<BasePendingTransactionsServiceParams> implements PendingTransactionsService {
39
+ export class BasePendingTransactionsService extends BaseService<BasePendingTransactionsServiceParams> implements MempoolViewer {
39
40
  private static readonly MutexPriority = {
40
41
  /**
41
42
  * Priority for inserting new transactions
@@ -142,12 +143,12 @@ export class BasePendingTransactionsService extends BaseService<BasePendingTrans
142
143
  })
143
144
  }
144
145
 
145
- async getPendingTransactions(head: Hash, limit: number): Promise<SignedHydratedTransactionWithStorageMeta[]> {
146
+ async pendingTransactions({ limit = 100 }: PendingTransactionsOptions = {}): Promise<SignedHydratedTransactionWithStorageMeta[]> {
146
147
  return await this.spanAsync('getPendingTransactions', async () => {
147
148
  // Acquires an exclusive mutex to ensure no race conditions while accessing pending transactions.
148
149
  return await this._updateCuratedPendingTransactionsArchivistMutex.runExclusive(async () => {
149
150
  // Find the supplied head
150
- let [lastHead] = filterAs(await this.chainArchivist.get([head]), x => asBlockBoundWitnessWithHashMeta(x))
151
+ let lastHead = (filterAs(await this.chainArchivist.next({ limit: 100 }), x => asBlockBoundWitnessWithHashMeta(x))).at(-1)
151
152
  if (isUndefined(lastHead)) return []
152
153
 
153
154
  await this.pruneCuratedPendingTransactionsArchivist(lastHead._hash)
@@ -19,9 +19,9 @@ import {
19
19
  } from '@xyo-network/xl1-protocol'
20
20
  import {
21
21
  asChainIndexingServiceStateWithStorageMeta,
22
+ BlockViewer,
22
23
  ChainIndexingServiceState, ChainIndexingServiceStateSchema, ChainStakeViewer,
23
24
  Config,
24
- EventingChainBlockNumberIteratorService,
25
25
  isChainIndexingServiceState,
26
26
  readPayloadMapFromStore,
27
27
  StakeIntentService,
@@ -34,8 +34,8 @@ import { BaseService } from '../BaseService.ts'
34
34
  import { BaseServiceParams } from '../model/index.ts'
35
35
 
36
36
  export interface XyoStakeIntentServiceParams extends BaseServiceParams<Pick<Config, 'producer'>> {
37
+ blockViewer?: BlockViewer
37
38
  chainArchivist?: ArchivistInstance
38
- chainIterator?: EventingChainBlockNumberIteratorService
39
39
  chainStakeViewer?: ChainStakeViewer
40
40
  stakeIntentStateArchivist?: ArchivistInstance
41
41
  }
@@ -65,12 +65,12 @@ export class XyoStakeIntentService extends BaseService<XyoStakeIntentServicePara
65
65
  protected _stakeCache = new LRUCache<Address, bigint>({ max: STAKE_CACHE_MAX_ENTRIES })
66
66
  protected _updateMutex = new Mutex()
67
67
 
68
- protected get chainArchivist() {
69
- return assertEx(this.params.chainArchivist, () => 'chainArchivist not set')
68
+ protected get blockViewer() {
69
+ return assertEx(this.params.blockViewer, () => 'blockViewer not set')
70
70
  }
71
71
 
72
- protected get chainIterator() {
73
- return assertEx(this.params.chainIterator, () => 'chainIterator not set')
72
+ protected get chainArchivist() {
73
+ return assertEx(this.params.chainArchivist, () => 'chainArchivist not set')
74
74
  }
75
75
 
76
76
  protected get chainStakeViewer() {
@@ -82,13 +82,9 @@ export class XyoStakeIntentService extends BaseService<XyoStakeIntentServicePara
82
82
  }
83
83
 
84
84
  override async createHandler() {
85
- this.chainIterator.on('headUpdated', async () => {
86
- await this.updateIndex()
87
- })
88
- const head = await this.chainIterator.head()
85
+ const head = await this.blockViewer.currentBlock()
89
86
  if (isUndefined(head)) return
90
- const headHash = await PayloadBuilder.hash(head)
91
- await this.recoverState(headHash)
87
+ await this.recoverState(head[0]._hash)
92
88
  }
93
89
 
94
90
  async getDeclaredCandidateRanges(address: Address, intent: Intent): Promise<Readonly<Readonly<[number, number]>[]>> {
@@ -208,7 +204,7 @@ export class XyoStakeIntentService extends BaseService<XyoStakeIntentServicePara
208
204
  }
209
205
  await this._updateMutex.runExclusive(async () => {
210
206
  return await this.spanAsync('updateIndex', async () => {
211
- const currentHead = await this.chainIterator.head()
207
+ const currentHead = (await this.blockViewer.currentBlock())[0]
212
208
  if (isUndefined(currentHead)) return
213
209
  return await timeBudget('XyoStakeIntentService.updateIndex', console, async () => {
214
210
  const currentHeadHash = currentHead._hash
@@ -1,18 +1,16 @@
1
1
  import { creatable, EmptyObject } from '@xylabs/sdk-js'
2
- import { ReadArchivist } from '@xyo-network/archivist-model'
3
2
  import { TimeDomain, TimePayload } from '@xyo-network/xl1-protocol'
4
3
  import {
5
- EventingChainBlockNumberIteratorService, SimpleTimeSyncViewer, TimeSyncViewer,
4
+ BlockViewer,
5
+ SimpleTimeSyncViewer, TimeSyncViewer,
6
6
  } from '@xyo-network/xl1-protocol-sdk'
7
7
  import { Provider } from 'ethers'
8
8
 
9
9
  import { BaseService } from '../BaseService.ts'
10
- import { blockViewerFromChainIteratorAndArchivist } from '../blockViewerFromChainIteratorAndArchivist.ts'
11
10
  import { BaseServiceParams } from '../model/index.ts'
12
11
 
13
12
  export interface BaseTimeServiceParams<TConfig extends EmptyObject = EmptyObject> extends BaseServiceParams<TConfig> {
14
- chainArchivist: ReadArchivist
15
- chainIterator: EventingChainBlockNumberIteratorService
13
+ blockViewer: BlockViewer
16
14
  ethProvider?: Provider
17
15
  }
18
16
 
@@ -20,12 +18,8 @@ export interface BaseTimeServiceParams<TConfig extends EmptyObject = EmptyObject
20
18
  export class BaseTimeSyncService extends BaseService<BaseTimeServiceParams> implements TimeSyncViewer {
21
19
  protected timeSyncViewer!: TimeSyncViewer
22
20
 
23
- protected get chainArchivist() {
24
- return this.params.chainArchivist
25
- }
26
-
27
- protected get chainIterator() {
28
- return this.params.chainIterator
21
+ protected get blockViewer() {
22
+ return this.params.blockViewer
29
23
  }
30
24
 
31
25
  protected get ethProvider() {
@@ -38,11 +32,7 @@ export class BaseTimeSyncService extends BaseService<BaseTimeServiceParams> impl
38
32
 
39
33
  override async createHandler(): Promise<void> {
40
34
  await super.createHandler()
41
- const blockViewer = blockViewerFromChainIteratorAndArchivist(
42
- this.chainIterator,
43
- this.chainArchivist,
44
- )
45
- this.timeSyncViewer = new SimpleTimeSyncViewer(blockViewer, this.ethProvider)
35
+ this.timeSyncViewer = new SimpleTimeSyncViewer(this.blockViewer, this.ethProvider)
46
36
  }
47
37
 
48
38
  async currentTime(domain: TimeDomain): Promise<[string, number]> {
@@ -44,6 +44,18 @@ export function blockViewerFromChainIteratorAndArchivist(
44
44
  }
45
45
  return results
46
46
  },
47
+ blocksByNumber: async function (number: XL1BlockNumber, limit = 10): Promise<SignedHydratedBlockWithHashMeta[]> {
48
+ const results: SignedHydratedBlockWithHashMeta[] = []
49
+ for (let i = 0; i < limit; i++) {
50
+ const block = await this.blockByNumber(number)
51
+ if (block) {
52
+ results.push(block)
53
+ } else {
54
+ break
55
+ }
56
+ }
57
+ return results
58
+ },
47
59
  currentBlock: async function (): Promise<SignedHydratedBlockWithHashMeta> {
48
60
  const head = await chainIterator.head()
49
61
  return this.blockByHash(head._hash) as Promise<SignedHydratedBlockWithHashMeta>