@xyo-network/chain-services 1.14.0 → 1.14.2

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 (33) hide show
  1. package/dist/neutral/AccountBalance/BaseAccountBalanceService.d.ts.map +1 -1
  2. package/dist/neutral/BaseService.d.ts +5 -3
  3. package/dist/neutral/BaseService.d.ts.map +1 -1
  4. package/dist/neutral/BlockProducer/BaseBlockProducerService.d.ts +5 -1
  5. package/dist/neutral/BlockProducer/BaseBlockProducerService.d.ts.map +1 -1
  6. package/dist/neutral/Bridge/BaseBridgeService.d.ts +15 -0
  7. package/dist/neutral/Bridge/BaseBridgeService.d.ts.map +1 -0
  8. package/dist/neutral/Bridge/index.d.ts +2 -0
  9. package/dist/neutral/Bridge/index.d.ts.map +1 -0
  10. package/dist/neutral/StepStake/BaseStepStakeService.d.ts +14 -0
  11. package/dist/neutral/StepStake/BaseStepStakeService.d.ts.map +1 -0
  12. package/dist/neutral/StepStake/index.d.ts +2 -0
  13. package/dist/neutral/StepStake/index.d.ts.map +1 -0
  14. package/dist/neutral/Time/BaseTimeSyncService.d.ts +22 -0
  15. package/dist/neutral/Time/BaseTimeSyncService.d.ts.map +1 -0
  16. package/dist/neutral/Time/index.d.ts +2 -0
  17. package/dist/neutral/Time/index.d.ts.map +1 -0
  18. package/dist/neutral/index.d.ts +3 -0
  19. package/dist/neutral/index.d.ts.map +1 -1
  20. package/dist/neutral/index.mjs +211 -51
  21. package/dist/neutral/index.mjs.map +1 -1
  22. package/package.json +11 -11
  23. package/src/AccountBalance/BaseAccountBalanceService.ts +11 -8
  24. package/src/BaseService.ts +8 -3
  25. package/src/BlockProducer/BaseBlockProducerService.ts +48 -19
  26. package/src/BlockProducer/spec/BaseBlockProducerService.spec.ts +5 -0
  27. package/src/Bridge/BaseBridgeService.ts +35 -0
  28. package/src/Bridge/index.ts +1 -0
  29. package/src/StepStake/BaseStepStakeService.ts +26 -0
  30. package/src/StepStake/index.ts +1 -0
  31. package/src/Time/BaseTimeSyncService.ts +79 -0
  32. package/src/Time/index.ts +1 -0
  33. package/src/index.ts +3 -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.14.0",
4
+ "version": "1.14.2",
5
5
  "description": "XYO Layer One SDK Services",
6
6
  "homepage": "https://xylabs.com",
7
7
  "bugs": {
@@ -54,17 +54,17 @@
54
54
  "@xyo-network/boundwitness-model": "~5.1.0",
55
55
  "@xyo-network/boundwitness-validator": "~5.1.0",
56
56
  "@xyo-network/boundwitness-wrapper": "~5.1.0",
57
- "@xyo-network/chain-analyze": "~1.14.0",
58
- "@xyo-network/chain-modules": "~1.14.0",
59
- "@xyo-network/chain-protocol": "~1.14.0",
60
- "@xyo-network/chain-utils": "~1.14.0",
57
+ "@xyo-network/chain-analyze": "~1.14.2",
58
+ "@xyo-network/chain-modules": "~1.14.2",
59
+ "@xyo-network/chain-protocol": "~1.14.2",
60
+ "@xyo-network/chain-utils": "~1.14.2",
61
61
  "@xyo-network/payload-builder": "~5.1.0",
62
62
  "@xyo-network/payload-model": "~5.1.0",
63
- "@xyo-network/typechain": "~4.0.1",
64
- "@xyo-network/xl1-protocol": "~1.11.0",
65
- "@xyo-network/xl1-protocol-sdk": "~1.14.0",
66
- "@xyo-network/xl1-validation": "~1.14.0",
67
- "@xyo-network/xl1-wrappers": "~1.14.0",
63
+ "@xyo-network/typechain": "~4.0.6",
64
+ "@xyo-network/xl1-protocol": "~1.12.14",
65
+ "@xyo-network/xl1-protocol-sdk": "~1.14.2",
66
+ "@xyo-network/xl1-validation": "~1.14.2",
67
+ "@xyo-network/xl1-wrappers": "~1.14.2",
68
68
  "async-mutex": "~0.5.0",
69
69
  "ethers": "6.15.0",
70
70
  "lru-cache": "~11.1.0"
@@ -77,7 +77,7 @@
77
77
  "@xylabs/vitest-extended": "~5.0.11",
78
78
  "@xyo-network/account": "~5.1.0",
79
79
  "@xyo-network/account-model": "~5.1.0",
80
- "@xyo-network/chain-validation": "~1.14.0",
80
+ "@xyo-network/chain-validation": "~1.14.2",
81
81
  "@xyo-network/wallet": "~5.1.0",
82
82
  "eslint": "^9.34.0",
83
83
  "tslib": "~2.8.1",
@@ -1,5 +1,6 @@
1
1
  import { creatable } from '@xylabs/creatable'
2
2
  import { Address, Hash } from '@xylabs/hex'
3
+ import { spanAsync } from '@xylabs/telemetry'
3
4
  import { ReadArchivist } from '@xyo-network/archivist-model'
4
5
  import {
5
6
  AccountBalanceServiceV2,
@@ -21,14 +22,16 @@ export interface BaseAccountBalanceServiceParams extends BaseServiceParams {
21
22
  @creatable()
22
23
  export class BaseAccountBalanceService extends BaseService<BaseAccountBalanceServiceParams> implements AccountBalanceServiceV2 {
23
24
  async balances(head: Hash, address: Address[]): Promise<Partial<Record<Address, AttoXL1>>> {
24
- const summary = await balanceSummary({
25
- chainArchivist: this.params.chainArchivist, summaryRepository: this.params.summaryRepository, head,
25
+ return await spanAsync('balances', async () => {
26
+ const summary = await balanceSummary({
27
+ chainArchivist: this.params.chainArchivist, summaryRepository: this.params.summaryRepository, head,
28
+ })
29
+ const result: Record<Address, AttoXL1> = {}
30
+ for (const addr of address) {
31
+ const summaryBalance = summary[addr] ?? 0n
32
+ result[addr] = AttoXL1(summaryBalance < 0n ? 0n : summaryBalance)
33
+ }
34
+ return result
26
35
  })
27
- const result: Record<Address, AttoXL1> = {}
28
- for (const addr of address) {
29
- const summaryBalance = summary[addr] ?? 0n
30
- result[addr] = AttoXL1(summaryBalance < 0n ? 0n : summaryBalance)
31
- }
32
- return result
33
36
  }
34
37
  }
@@ -1,8 +1,9 @@
1
1
  import { AbstractCreatable, creatable } from '@xylabs/creatable'
2
2
  import type { EventData } from '@xylabs/events'
3
+ import { Hash } from '@xylabs/hex'
3
4
  import type { Promisable } from '@xylabs/promise'
4
5
  import { span, spanAsync } from '@xylabs/telemetry'
5
- import type { Service } from '@xyo-network/xl1-protocol'
6
+ import type { ServiceInterface } from '@xyo-network/xl1-protocol'
6
7
  import { Mutex } from 'async-mutex'
7
8
 
8
9
  import type { BaseAccountableServiceParams, BaseServiceParams } from './model/index.ts'
@@ -13,7 +14,7 @@ declare global {
13
14
 
14
15
  @creatable()
15
16
  export class BaseService<TParams extends BaseServiceParams = BaseServiceParams, TEventData extends EventData = EventData>
16
- extends AbstractCreatable<TParams, TEventData> {
17
+ extends AbstractCreatable<TParams, TEventData> implements ServiceInterface {
17
18
  private static singletonInitMutex = new Mutex()
18
19
 
19
20
  static get singletons() {
@@ -38,6 +39,10 @@ export class BaseService<TParams extends BaseServiceParams = BaseServiceParams,
38
39
  async spanAsync<T>(name: string, fn: () => Promise<T>): Promise<T> {
39
40
  return await spanAsync(name, fn, this.tracer)
40
41
  }
42
+
43
+ sync(_head: Hash): Promise<void> {
44
+ throw new Error('Method not implemented.')
45
+ }
41
46
  }
42
47
 
43
48
  export abstract class BaseAccountableService<
@@ -46,7 +51,7 @@ export abstract class BaseAccountableService<
46
51
  // Base class for services that have an account
47
52
  }
48
53
 
49
- export interface CreatableService<T extends BaseService = BaseService> extends Service {
54
+ export interface CreatableService<T extends BaseService = BaseService> extends ServiceInterface {
50
55
  new(params: T['params']): T
51
56
  create<T extends BaseService>(this: CreatableService<T>, params?: Partial<T['params']>): Promisable<T>
52
57
  }
@@ -15,7 +15,8 @@ import {
15
15
  AccountBalanceServiceV2,
16
16
  AllowedBlockPayload, asBlockBoundWitness, AttoXL1, BlockBoundWitness, BlockNumber, BlockNumberSchema,
17
17
  BlockProducerService, ChainStakeIntent,
18
- HydratedBlock, PendingTransactionsService, StakeIntentService, Transfer,
18
+ defaultRewardRatio,
19
+ HydratedBlock, PendingTransactionsService, SignedHydratedTransaction, StakeIntentService, TimePayload, TimeSchema, TimeSyncViewInterface, TransactionBoundWitness, Transfer,
19
20
  } from '@xyo-network/xl1-protocol'
20
21
 
21
22
  import { BaseService } from '../BaseService.ts'
@@ -43,6 +44,7 @@ export interface BaseBlockProducerServiceParams extends XyoValidatorParams {
43
44
  pendingTransactionsService: PendingTransactionsService
44
45
  rejectedTransactionsArchivist: ArchivistInstance
45
46
  rewardAddress: Address
47
+ time: TimeSyncViewInterface
46
48
  }
47
49
 
48
50
  @creatable()
@@ -116,6 +118,10 @@ export class BaseBlockProducerService extends BaseService<BaseBlockProducerServi
116
118
  return assertEx(this.params.stakeIntentService, () => 'No StakeIntentService provided')
117
119
  }
118
120
 
121
+ protected get time(): TimeSyncViewInterface {
122
+ return assertEx(this.params.time, () => 'No TimeSyncViewInterface provided')
123
+ }
124
+
119
125
  protected get validateHydratedBlockState() {
120
126
  return assertEx(this.params.validateHydratedBlockState, () => 'validateHydratedBlockState is required')
121
127
  }
@@ -139,7 +145,7 @@ export class BaseBlockProducerService extends BaseService<BaseBlockProducerServi
139
145
  blockRewardService: this.rewardService,
140
146
  config: {
141
147
  rewardAddress: this.rewardAddress,
142
- rewardPercentageRatio: 0.5,
148
+ rewardPercentageRatio: defaultRewardRatio,
143
149
  schema: FixedPercentageBlockRewardDivinerConfigSchema,
144
150
  },
145
151
  })
@@ -194,24 +200,11 @@ export class BaseBlockProducerService extends BaseService<BaseBlockProducerServi
194
200
  if (rewardTransferPayload) blockPayloads.push(rewardTransferPayload)
195
201
 
196
202
  const transactionTransfers = await generateTransactionFeeTransfers(this.address, nextBlockTransactions)
203
+ const timePayload = await this.generateTimePayload(nextBlock)
197
204
 
198
- const fundedTransfers: Transfer[] = []
199
- const fundedNextBlockTransactions = (await Promise.all(nextBlockTransactions.map(async (tx) => {
200
- const transfer: Transfer | undefined = transactionTransfers.find(txTransfer => txTransfer.from === tx[0].from)
201
- if (!transfer) return
202
- const totalTransferCost = Object.values(transfer?.transfers).reduce((acc, t) => acc + hexToBigInt(t ?? '00' as Hex), 0n)
203
- if (validateBalances) {
204
- const balance = (await this.balanceService.balances(head._hash, [transfer.from]))[transfer.from] ?? AttoXL1(0n)
205
- if (balance >= totalTransferCost) {
206
- fundedTransfers.push(transfer)
207
- return tx
208
- }
209
- } else {
210
- fundedTransfers.push(transfer)
211
- return tx
212
- }
213
- }))).filter(exists)
214
- blockPayloads.push(...fundedTransfers)
205
+ const [fundedNextBlockTransactions, fundedTransfers] = await this.filterByFunded(head, nextBlockTransactions, transactionTransfers, validateBalances)
206
+
207
+ blockPayloads.push(...fundedTransfers, timePayload)
215
208
 
216
209
  // Build the block
217
210
  this.logger?.info(`buildNextBlock: Building block ${head.block + 1} (${new Date().toISOString()})`)
@@ -229,4 +222,40 @@ export class BaseBlockProducerService extends BaseService<BaseBlockProducerServi
229
222
  }
230
223
  })
231
224
  }
225
+
226
+ // remove unfunded transactions and block transfers
227
+ private async filterByFunded(
228
+ head: WithStorageMeta<BlockBoundWitness>,
229
+ txs: SignedHydratedTransaction[],
230
+ transfers: Transfer[],
231
+ validateBalances = false,
232
+ ): Promise<[SignedHydratedTransaction[], Transfer[]]> {
233
+ const fundedTransfers: Transfer[] = []
234
+ const fundedTransactions = (await Promise.all(txs.map(async (tx) => {
235
+ const transfer: Transfer | undefined = transfers.find(transfer => transfer.from === tx[0].from)
236
+ if (!transfer) return
237
+ const totalTransferCost = Object.values(transfer?.transfers).reduce((acc, t) => acc + hexToBigInt(t ?? '00' as Hex), 0n)
238
+ if (validateBalances) {
239
+ const balance = (await this.balanceService.balances(head._hash, [transfer.from]))[transfer.from] ?? AttoXL1(0n)
240
+ if (balance >= totalTransferCost) {
241
+ fundedTransfers.push(transfer)
242
+ return tx
243
+ }
244
+ } else {
245
+ fundedTransfers.push(transfer)
246
+ return tx
247
+ }
248
+ }))).filter(exists)
249
+ return [fundedTransactions, fundedTransfers]
250
+ }
251
+
252
+ private async generateTimePayload(nextBlock: number) {
253
+ const timePayload: TimePayload = {
254
+ schema: TimeSchema,
255
+ xl1: nextBlock,
256
+ ethereum: await this.time.currentTime('ethereum'),
257
+ epoch: Date.now(),
258
+ }
259
+ return timePayload
260
+ }
232
261
  }
@@ -23,6 +23,7 @@ import type {
23
23
  HydratedBlock,
24
24
  HydratedBlockStateValidationFunctionV2,
25
25
  StakeIntentService,
26
+ TimeSyncViewInterface,
26
27
  } from '@xyo-network/xl1-protocol'
27
28
  import {
28
29
  asBlockBoundWitness,
@@ -60,6 +61,7 @@ describe('XyoBlockProducer', () => {
60
61
  let rewardAddress = '1111111111111111111111111111111111111111' as Address
61
62
  let rewardService: BlockRewardService
62
63
  let stakeIntentService: ReturnType<typeof mock<StakeIntentService>>
64
+ let time: TimeSyncViewInterface
63
65
  let transactionAccount: AccountInstance
64
66
  const validPendingTransactions = Math.ceil(BaseBlockProducerService.DefaultBlockSize)
65
67
  let config: Config
@@ -93,6 +95,7 @@ describe('XyoBlockProducer', () => {
93
95
 
94
96
  stakeIntentService = mock<StakeIntentService>()
95
97
  stakeIntentService.getDeclaredCandidateRanges.mockResolvedValue([])
98
+ time = mock<TimeSyncViewInterface>()
96
99
  rewardService = await MemoryBlockRewardService.create()
97
100
  const balanceService = await accountBalanceServiceFromArchivist(chainArchivist)
98
101
  const params: BaseBlockProducerServiceParams = {
@@ -109,6 +112,7 @@ describe('XyoBlockProducer', () => {
109
112
  rewardAddress,
110
113
  rewardService,
111
114
  stakeIntentService,
115
+ time,
112
116
  validateHydratedBlockState,
113
117
  }
114
118
  blockProducer = await BaseBlockProducerService.create(params)
@@ -194,6 +198,7 @@ describe('XyoBlockProducer', () => {
194
198
  rewardAddress,
195
199
  rewardService,
196
200
  stakeIntentService,
201
+ time,
197
202
  validateHydratedBlockState,
198
203
  }
199
204
  blockProducer = await BaseBlockProducerService.create(params)
@@ -0,0 +1,35 @@
1
+ import { creatable } from '@xylabs/creatable'
2
+ import { Promisable } from '@xylabs/promise'
3
+ import { ReadArchivist } from '@xyo-network/archivist-model'
4
+ import {
5
+ BridgeBack,
6
+ BridgeComplete,
7
+ BridgeRequest,
8
+ BridgeService,
9
+ } from '@xyo-network/xl1-protocol'
10
+
11
+ import { BaseService } from '../BaseService.ts'
12
+ import { BaseServiceParams } from '../model/index.ts'
13
+
14
+ export interface BaseBridgeServiceParams extends BaseServiceParams {
15
+ chainArchivist: ReadArchivist
16
+ }
17
+
18
+ @creatable()
19
+ export class BaseBridgeService extends BaseService<BaseBridgeServiceParams> implements BridgeService {
20
+ completedBridgeBack(): Promisable<BridgeBack[]> {
21
+ throw new Error('Method not implemented.')
22
+ }
23
+
24
+ completedBridgeRequests(): Promisable<[BridgeRequest, BridgeComplete][]> {
25
+ throw new Error('Method not implemented.')
26
+ }
27
+
28
+ pendingBridgeBack(): Promisable<BridgeBack[]> {
29
+ throw new Error('Method not implemented.')
30
+ }
31
+
32
+ pendingBridgeRequests(): Promisable<BridgeRequest[]> {
33
+ throw new Error('Method not implemented.')
34
+ }
35
+ }
@@ -0,0 +1 @@
1
+ export * from './BaseBridgeService.ts'
@@ -0,0 +1,26 @@
1
+ import { creatable } from '@xylabs/creatable'
2
+ import { Address } from '@xylabs/hex'
3
+ import { Promisable } from '@xylabs/promise'
4
+ import { ReadArchivist } from '@xyo-network/archivist-model'
5
+ import {
6
+ CompletedStep,
7
+ StepStakeService,
8
+ } from '@xyo-network/xl1-protocol'
9
+
10
+ import { BaseService } from '../BaseService.ts'
11
+ import { BaseServiceParams } from '../model/index.ts'
12
+
13
+ export interface BaseStepStakeServiceParams extends BaseServiceParams {
14
+ chainArchivist: ReadArchivist
15
+ }
16
+
17
+ @creatable()
18
+ export class BaseStepStakeService extends BaseService<BaseStepStakeServiceParams> implements StepStakeService {
19
+ stepStake(_step: CompletedStep): Promisable<Record<Address, bigint>> {
20
+ throw new Error('Method not implemented.')
21
+ }
22
+
23
+ stepStakeForAddress(_address: Address, _step: CompletedStep): Promisable<bigint> {
24
+ throw new Error('Method not implemented.')
25
+ }
26
+ }
@@ -0,0 +1 @@
1
+ export * from './BaseStepStakeService.ts'
@@ -0,0 +1,79 @@
1
+ import { assertEx } from '@xylabs/assert'
2
+ import { creatable } from '@xylabs/creatable'
3
+ import { ReadArchivist } from '@xyo-network/archivist-model'
4
+ import {
5
+ asTimePayload,
6
+ EventingChainBlockNumberIteratorService, TimeDomain, TimeSchema, TimeSyncService,
7
+ } from '@xyo-network/xl1-protocol'
8
+ import { Provider } from 'ethers'
9
+
10
+ import { BaseService } from '../BaseService.ts'
11
+ import { BaseServiceParams } from '../model/index.ts'
12
+
13
+ export interface BaseTimeServiceParams extends BaseServiceParams {
14
+ chainArchivist: ReadArchivist
15
+ chainIterator: EventingChainBlockNumberIteratorService
16
+ ethProvider?: Provider
17
+ }
18
+
19
+ @creatable()
20
+ export class BaseTimeSyncService extends BaseService<BaseTimeServiceParams> implements TimeSyncService {
21
+ get chainArchivist() {
22
+ return this.params.chainArchivist
23
+ }
24
+
25
+ get chainIterator() {
26
+ return this.params.chainIterator
27
+ }
28
+
29
+ get ethProvider() {
30
+ return this.params.ethProvider
31
+ }
32
+
33
+ async convertTime(fromDomain: TimeDomain, toDomain: TimeDomain, from: number): Promise<number> {
34
+ switch (fromDomain) {
35
+ case 'xl1': {
36
+ const block = assertEx(await this.chainIterator.get(from), () => 'Block not found')
37
+ const timeSchemaIndex = block.payload_schemas.indexOf(TimeSchema)
38
+ const hash = timeSchemaIndex === -1 ? undefined : block.payload_hashes[timeSchemaIndex]
39
+ const [payload] = hash === undefined ? [] : await this.chainArchivist.get([hash])
40
+ const timePayload = asTimePayload(payload)
41
+ if (timePayload === undefined) return 0
42
+ switch (toDomain) {
43
+ case 'xl1': {
44
+ return timePayload.xl1 ?? 0
45
+ }
46
+ case 'epoch': {
47
+ return timePayload.epoch ?? 0
48
+ }
49
+ case 'ethereum': {
50
+ return timePayload.ethereum ?? 0
51
+ }
52
+ default: {
53
+ throw new Error(`Unsupported to toDomain: ${toDomain}`)
54
+ }
55
+ }
56
+ }
57
+ default: {
58
+ throw new Error(`Unsupported from fromDomain: ${fromDomain}`)
59
+ }
60
+ }
61
+ }
62
+
63
+ async currentTime(domain: TimeDomain): Promise<number> {
64
+ switch (domain) {
65
+ case 'xl1': {
66
+ return (await this.chainIterator.head()).block
67
+ }
68
+ case 'epoch': {
69
+ return Date.now()
70
+ }
71
+ case 'ethereum': {
72
+ return await this.ethProvider?.getBlockNumber() ?? 0
73
+ }
74
+ default: {
75
+ throw new Error(`Unknown time domain: ${domain}`)
76
+ }
77
+ }
78
+ }
79
+ }
@@ -0,0 +1 @@
1
+ export * from './BaseTimeSyncService.ts'
package/src/index.ts CHANGED
@@ -2,6 +2,7 @@ export * from './AccountBalance/index.ts'
2
2
  export * from './BaseService.ts'
3
3
  export * from './BlockProducer/index.ts'
4
4
  export * from './BlockReward/index.ts'
5
+ export * from './Bridge/index.ts'
5
6
  export * from './ChainBlockNumberIteration/index.ts'
6
7
  export * from './ChainService/index.ts'
7
8
  export * from './ChainValidator/index.ts'
@@ -9,3 +10,5 @@ export * from './Election/index.ts'
9
10
  export * from './model/index.ts'
10
11
  export * from './PendingTransactions/index.ts'
11
12
  export * from './StakeIntent/index.ts'
13
+ export * from './StepStake/index.ts'
14
+ export * from './Time/index.ts'