@xyo-network/chain-services 1.14.1 → 1.14.3
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.
- package/dist/neutral/AccountBalance/BaseAccountBalanceService.d.ts.map +1 -1
- package/dist/neutral/BaseService.d.ts +5 -3
- package/dist/neutral/BaseService.d.ts.map +1 -1
- package/dist/neutral/BlockProducer/BaseBlockProducerService.d.ts +5 -1
- package/dist/neutral/BlockProducer/BaseBlockProducerService.d.ts.map +1 -1
- package/dist/neutral/BlockReward/spec/MemoryBlockRewardService.spec.d.ts +2 -0
- package/dist/neutral/BlockReward/spec/MemoryBlockRewardService.spec.d.ts.map +1 -0
- package/dist/neutral/Bridge/BaseBridgeService.d.ts +15 -0
- package/dist/neutral/Bridge/BaseBridgeService.d.ts.map +1 -0
- package/dist/neutral/Bridge/index.d.ts +2 -0
- package/dist/neutral/Bridge/index.d.ts.map +1 -0
- package/dist/neutral/StepStake/BaseStepStakeService.d.ts +14 -0
- package/dist/neutral/StepStake/BaseStepStakeService.d.ts.map +1 -0
- package/dist/neutral/StepStake/index.d.ts +2 -0
- package/dist/neutral/StepStake/index.d.ts.map +1 -0
- package/dist/neutral/Time/BaseTimeSyncService.d.ts +22 -0
- package/dist/neutral/Time/BaseTimeSyncService.d.ts.map +1 -0
- package/dist/neutral/Time/index.d.ts +2 -0
- package/dist/neutral/Time/index.d.ts.map +1 -0
- package/dist/neutral/index.d.ts +3 -0
- package/dist/neutral/index.d.ts.map +1 -1
- package/dist/neutral/index.mjs +232 -58
- package/dist/neutral/index.mjs.map +1 -1
- package/package.json +24 -24
- package/src/AccountBalance/BaseAccountBalanceService.ts +11 -8
- package/src/BaseService.ts +11 -6
- package/src/BlockProducer/BaseBlockProducerService.ts +63 -23
- package/src/BlockProducer/spec/BaseBlockProducerService.spec.ts +5 -0
- package/src/BlockReward/spec/MemoryBlockRewardService.spec.ts +64 -0
- package/src/Bridge/BaseBridgeService.ts +35 -0
- package/src/Bridge/index.ts +1 -0
- package/src/StepStake/BaseStepStakeService.ts +26 -0
- package/src/StepStake/index.ts +1 -0
- package/src/Time/BaseTimeSyncService.ts +79 -0
- package/src/Time/index.ts +1 -0
- 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.
|
|
4
|
+
"version": "1.14.3",
|
|
5
5
|
"description": "XYO Layer One SDK Services",
|
|
6
6
|
"homepage": "https://xylabs.com",
|
|
7
7
|
"bugs": {
|
|
@@ -48,37 +48,37 @@
|
|
|
48
48
|
"@xylabs/promise": "~5.0.11",
|
|
49
49
|
"@xylabs/telemetry": "~5.0.11",
|
|
50
50
|
"@xylabs/typeof": "~5.0.11",
|
|
51
|
-
"@xyo-network/account-model": "~5.1.
|
|
52
|
-
"@xyo-network/archivist-memory": "~5.1.
|
|
53
|
-
"@xyo-network/archivist-model": "~5.1.
|
|
54
|
-
"@xyo-network/boundwitness-model": "~5.1.
|
|
55
|
-
"@xyo-network/boundwitness-validator": "~5.1.
|
|
56
|
-
"@xyo-network/boundwitness-wrapper": "~5.1.
|
|
57
|
-
"@xyo-network/chain-analyze": "~1.14.
|
|
58
|
-
"@xyo-network/chain-modules": "~1.14.
|
|
59
|
-
"@xyo-network/chain-protocol": "~1.14.
|
|
60
|
-
"@xyo-network/chain-utils": "~1.14.
|
|
61
|
-
"@xyo-network/payload-builder": "~5.1.
|
|
62
|
-
"@xyo-network/payload-model": "~5.1.
|
|
63
|
-
"@xyo-network/typechain": "~4.0.
|
|
64
|
-
"@xyo-network/xl1-protocol": "~1.
|
|
65
|
-
"@xyo-network/xl1-protocol-sdk": "~1.14.
|
|
66
|
-
"@xyo-network/xl1-validation": "~1.14.
|
|
67
|
-
"@xyo-network/xl1-wrappers": "~1.14.
|
|
51
|
+
"@xyo-network/account-model": "~5.1.2",
|
|
52
|
+
"@xyo-network/archivist-memory": "~5.1.2",
|
|
53
|
+
"@xyo-network/archivist-model": "~5.1.2",
|
|
54
|
+
"@xyo-network/boundwitness-model": "~5.1.2",
|
|
55
|
+
"@xyo-network/boundwitness-validator": "~5.1.2",
|
|
56
|
+
"@xyo-network/boundwitness-wrapper": "~5.1.2",
|
|
57
|
+
"@xyo-network/chain-analyze": "~1.14.3",
|
|
58
|
+
"@xyo-network/chain-modules": "~1.14.3",
|
|
59
|
+
"@xyo-network/chain-protocol": "~1.14.3",
|
|
60
|
+
"@xyo-network/chain-utils": "~1.14.3",
|
|
61
|
+
"@xyo-network/payload-builder": "~5.1.2",
|
|
62
|
+
"@xyo-network/payload-model": "~5.1.2",
|
|
63
|
+
"@xyo-network/typechain": "~4.0.8",
|
|
64
|
+
"@xyo-network/xl1-protocol": "~1.12.22",
|
|
65
|
+
"@xyo-network/xl1-protocol-sdk": "~1.14.3",
|
|
66
|
+
"@xyo-network/xl1-validation": "~1.14.3",
|
|
67
|
+
"@xyo-network/xl1-wrappers": "~1.14.3",
|
|
68
68
|
"async-mutex": "~0.5.0",
|
|
69
69
|
"ethers": "6.15.0",
|
|
70
|
-
"lru-cache": "~11.1
|
|
70
|
+
"lru-cache": "~11.2.1"
|
|
71
71
|
},
|
|
72
72
|
"devDependencies": {
|
|
73
|
-
"@types/node": "~24.3.
|
|
73
|
+
"@types/node": "~24.3.1",
|
|
74
74
|
"@xylabs/delay": "~5.0.11",
|
|
75
75
|
"@xylabs/ts-scripts-yarn3": "~7.1.7",
|
|
76
76
|
"@xylabs/tsconfig": "~7.1.7",
|
|
77
77
|
"@xylabs/vitest-extended": "~5.0.11",
|
|
78
|
-
"@xyo-network/account": "~5.1.
|
|
79
|
-
"@xyo-network/account-model": "~5.1.
|
|
80
|
-
"@xyo-network/chain-validation": "~1.14.
|
|
81
|
-
"@xyo-network/wallet": "~5.1.
|
|
78
|
+
"@xyo-network/account": "~5.1.2",
|
|
79
|
+
"@xyo-network/account-model": "~5.1.2",
|
|
80
|
+
"@xyo-network/chain-validation": "~1.14.3",
|
|
81
|
+
"@xyo-network/wallet": "~5.1.2",
|
|
82
82
|
"eslint": "^9.34.0",
|
|
83
83
|
"tslib": "~2.8.1",
|
|
84
84
|
"typescript": "~5.9.2",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { creatable } from '@xylabs/creatable'
|
|
2
2
|
import { Address, Hash } from '@xylabs/hex'
|
|
3
|
+
import { spanRootAsync } 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
|
-
|
|
25
|
-
|
|
25
|
+
return await spanRootAsync('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
|
}
|
package/src/BaseService.ts
CHANGED
|
@@ -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
|
-
import {
|
|
5
|
-
import type {
|
|
5
|
+
import { spanRoot, spanRootAsync } from '@xylabs/telemetry'
|
|
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() {
|
|
@@ -32,11 +33,15 @@ export class BaseService<TParams extends BaseServiceParams = BaseServiceParams,
|
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
span<T>(name: string, fn: () => T): T {
|
|
35
|
-
return
|
|
36
|
+
return spanRoot(name, fn, this.tracer)
|
|
36
37
|
}
|
|
37
38
|
|
|
38
39
|
async spanAsync<T>(name: string, fn: () => Promise<T>): Promise<T> {
|
|
39
|
-
return await
|
|
40
|
+
return await spanRootAsync(name, fn, this.tracer)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
sync(_head: Hash): Promise<void> {
|
|
44
|
+
throw new Error('Method not implemented.')
|
|
40
45
|
}
|
|
41
46
|
}
|
|
42
47
|
|
|
@@ -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
|
|
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,9 @@ import {
|
|
|
15
15
|
AccountBalanceServiceV2,
|
|
16
16
|
AllowedBlockPayload, asBlockBoundWitness, AttoXL1, BlockBoundWitness, BlockNumber, BlockNumberSchema,
|
|
17
17
|
BlockProducerService, ChainStakeIntent,
|
|
18
|
-
|
|
18
|
+
defaultRewardRatio,
|
|
19
|
+
HydratedBlock, PendingTransactionsService, SignedHydratedTransaction, StakeIntentService,
|
|
20
|
+
TimePayload, TimeSchema, TimeSyncViewInterface, Transfer,
|
|
19
21
|
} from '@xyo-network/xl1-protocol'
|
|
20
22
|
|
|
21
23
|
import { BaseService } from '../BaseService.ts'
|
|
@@ -43,6 +45,7 @@ export interface BaseBlockProducerServiceParams extends XyoValidatorParams {
|
|
|
43
45
|
pendingTransactionsService: PendingTransactionsService
|
|
44
46
|
rejectedTransactionsArchivist: ArchivistInstance
|
|
45
47
|
rewardAddress: Address
|
|
48
|
+
time: TimeSyncViewInterface
|
|
46
49
|
}
|
|
47
50
|
|
|
48
51
|
@creatable()
|
|
@@ -116,6 +119,10 @@ export class BaseBlockProducerService extends BaseService<BaseBlockProducerServi
|
|
|
116
119
|
return assertEx(this.params.stakeIntentService, () => 'No StakeIntentService provided')
|
|
117
120
|
}
|
|
118
121
|
|
|
122
|
+
protected get time(): TimeSyncViewInterface {
|
|
123
|
+
return assertEx(this.params.time, () => 'No TimeSyncViewInterface provided')
|
|
124
|
+
}
|
|
125
|
+
|
|
119
126
|
protected get validateHydratedBlockState() {
|
|
120
127
|
return assertEx(this.params.validateHydratedBlockState, () => 'validateHydratedBlockState is required')
|
|
121
128
|
}
|
|
@@ -139,7 +146,7 @@ export class BaseBlockProducerService extends BaseService<BaseBlockProducerServi
|
|
|
139
146
|
blockRewardService: this.rewardService,
|
|
140
147
|
config: {
|
|
141
148
|
rewardAddress: this.rewardAddress,
|
|
142
|
-
rewardPercentageRatio:
|
|
149
|
+
rewardPercentageRatio: defaultRewardRatio,
|
|
143
150
|
schema: FixedPercentageBlockRewardDivinerConfigSchema,
|
|
144
151
|
},
|
|
145
152
|
})
|
|
@@ -194,32 +201,26 @@ export class BaseBlockProducerService extends BaseService<BaseBlockProducerServi
|
|
|
194
201
|
if (rewardTransferPayload) blockPayloads.push(rewardTransferPayload)
|
|
195
202
|
|
|
196
203
|
const transactionTransfers = await generateTransactionFeeTransfers(this.address, nextBlockTransactions)
|
|
204
|
+
const timePayload = await this.generateTimePayload(nextBlock)
|
|
197
205
|
|
|
198
|
-
const fundedTransfers
|
|
199
|
-
|
|
200
|
-
|
|
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)
|
|
206
|
+
const [fundedNextBlockTransactions, fundedTransfers] = await this.filterByFunded(head, nextBlockTransactions, transactionTransfers, validateBalances)
|
|
207
|
+
|
|
208
|
+
blockPayloads.push(...fundedTransfers, timePayload)
|
|
215
209
|
|
|
216
210
|
// Build the block
|
|
217
|
-
this.logger?.info(`
|
|
211
|
+
this.logger?.info(`Building block ${head.block + 1}`)
|
|
212
|
+
const startBuild = Date.now()
|
|
218
213
|
const block = await buildNextBlock(head, fundedNextBlockTransactions, blockPayloads, [this.account])
|
|
219
|
-
|
|
220
|
-
this.logger?.info(
|
|
214
|
+
|
|
215
|
+
this.logger?.info(
|
|
216
|
+
`Built block ${block[0].block} in ${Date.now() - startBuild}ms with ${block[1].length} payloads`,
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
this.logger?.info(`Validating block ${block[0].block} with ${block[1].length} payloads`)
|
|
220
|
+
const startValidate = Date.now()
|
|
221
221
|
const errors = await this.validateHydratedBlockState(block, this.chainId, { accountBalance: this.balanceService })
|
|
222
|
-
this.logger?.info(`
|
|
222
|
+
this.logger?.info(`Validated block ${block[0].block} in ${Date.now() - startValidate}ms with ${block[1].length} payloads`)
|
|
223
|
+
|
|
223
224
|
if (errors.length > 0) {
|
|
224
225
|
this.logger?.warn(`Validation of produced block failed: ${errors.at(0)?.message}`)
|
|
225
226
|
const rejectedTransactions = block[1]
|
|
@@ -229,4 +230,43 @@ export class BaseBlockProducerService extends BaseService<BaseBlockProducerServi
|
|
|
229
230
|
}
|
|
230
231
|
})
|
|
231
232
|
}
|
|
233
|
+
|
|
234
|
+
// remove unfunded transactions and block transfers
|
|
235
|
+
private async filterByFunded(
|
|
236
|
+
head: WithStorageMeta<BlockBoundWitness>,
|
|
237
|
+
txs: SignedHydratedTransaction[],
|
|
238
|
+
transfers: Transfer[],
|
|
239
|
+
validateBalances = false,
|
|
240
|
+
): Promise<[SignedHydratedTransaction[], Transfer[]]> {
|
|
241
|
+
const start = Date.now()
|
|
242
|
+
const fundedTransfers: Transfer[] = []
|
|
243
|
+
const fundedTransactions = (await Promise.all(txs.map(async (tx) => {
|
|
244
|
+
const transfer: Transfer | undefined = transfers.find(transfer => transfer.from === tx[0].from)
|
|
245
|
+
if (!transfer) return
|
|
246
|
+
const totalTransferCost = Object.values(transfer?.transfers).reduce((acc, t) => acc + hexToBigInt(t ?? '00' as Hex), 0n)
|
|
247
|
+
if (validateBalances) {
|
|
248
|
+
const balance = (await this.balanceService.balances(head._hash, [transfer.from]))[transfer.from] ?? AttoXL1(0n)
|
|
249
|
+
if (balance >= totalTransferCost) {
|
|
250
|
+
fundedTransfers.push(transfer)
|
|
251
|
+
return tx
|
|
252
|
+
}
|
|
253
|
+
} else {
|
|
254
|
+
fundedTransfers.push(transfer)
|
|
255
|
+
return tx
|
|
256
|
+
}
|
|
257
|
+
}))).filter(exists)
|
|
258
|
+
this.logger?.info(`Filtered ${txs.length} transactions to ${fundedTransactions.length} funded transactions in ${Date.now() - start}ms`)
|
|
259
|
+
return [fundedTransactions, fundedTransfers]
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
private async generateTimePayload(nextBlock: number) {
|
|
263
|
+
const timePayload: TimePayload = {
|
|
264
|
+
schema: TimeSchema,
|
|
265
|
+
xl1: nextBlock,
|
|
266
|
+
// TODO: Change to entire tuple for time in ETH
|
|
267
|
+
ethereum: (await this.time.currentTime('ethereum'))[1],
|
|
268
|
+
epoch: Date.now(),
|
|
269
|
+
}
|
|
270
|
+
return timePayload
|
|
271
|
+
}
|
|
232
272
|
}
|
|
@@ -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,64 @@
|
|
|
1
|
+
import '@xylabs/vitest-extended'
|
|
2
|
+
|
|
3
|
+
import { toFixedPoint } from '@xylabs/decimal-precision'
|
|
4
|
+
import {
|
|
5
|
+
beforeAll, describe, expect, it,
|
|
6
|
+
} from 'vitest'
|
|
7
|
+
|
|
8
|
+
import { MemoryBlockRewardService } from '../index.ts'
|
|
9
|
+
|
|
10
|
+
describe('MemoryBlockRewardService', () => {
|
|
11
|
+
let sut: MemoryBlockRewardService
|
|
12
|
+
// const genesisReward = toFixedPoint(18_000_000_000n)
|
|
13
|
+
// const initialReward = toFixedPoint(500n)
|
|
14
|
+
// const minRewardPerBlock = toFixedPoint(10n)
|
|
15
|
+
const genesisReward = 18_000_000_000_000_000_000_000_000_000n
|
|
16
|
+
const initialReward = 500_000_000_000_000_000_000n
|
|
17
|
+
const minRewardPerBlock = 10_000_000_000_000_000_000n
|
|
18
|
+
const stepFactorDenominator = 100n
|
|
19
|
+
const stepFactorNumerator = 95n
|
|
20
|
+
const stepSize = 1_000_000n
|
|
21
|
+
beforeAll(async () => {
|
|
22
|
+
sut = await MemoryBlockRewardService.create({
|
|
23
|
+
stepFactorNumerator,
|
|
24
|
+
stepFactorDenominator,
|
|
25
|
+
stepSize,
|
|
26
|
+
initialStepReward: initialReward,
|
|
27
|
+
minRewardPerBlock,
|
|
28
|
+
creatorReward: genesisReward,
|
|
29
|
+
})
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
describe('rewards', () => {
|
|
33
|
+
it('for block 0', async () => {
|
|
34
|
+
const reward = await sut.getRewardForBlock(0n)
|
|
35
|
+
expect(reward).toEqual(18_000_000_000_000_000_000_000_000_000n)
|
|
36
|
+
expect(reward).toEqual(toFixedPoint(18_000_000_000n))
|
|
37
|
+
})
|
|
38
|
+
it('for block 1', async () => {
|
|
39
|
+
const reward = await sut.getRewardForBlock(1n)
|
|
40
|
+
expect(reward).toEqual(500_000_000_000_000_000_000n)
|
|
41
|
+
expect(reward).toEqual(toFixedPoint(500n))
|
|
42
|
+
})
|
|
43
|
+
it('for block 2', async () => {
|
|
44
|
+
const reward = await sut.getRewardForBlock(2n)
|
|
45
|
+
expect(reward).toEqual(500_000_000_000_000_000_000n)
|
|
46
|
+
expect(reward).toEqual(toFixedPoint(500n))
|
|
47
|
+
})
|
|
48
|
+
it('for block 3', async () => {
|
|
49
|
+
const reward = await sut.getRewardForBlock(3n)
|
|
50
|
+
expect(reward).toEqual(500_000_000_000_000_000_000n)
|
|
51
|
+
expect(reward).toEqual(toFixedPoint(500n))
|
|
52
|
+
})
|
|
53
|
+
it('for block 4', async () => {
|
|
54
|
+
const reward = await sut.getRewardForBlock(4n)
|
|
55
|
+
expect(reward).toEqual(500_000_000_000_000_000_000n)
|
|
56
|
+
expect(reward).toEqual(toFixedPoint(500n))
|
|
57
|
+
})
|
|
58
|
+
it('for block 1000000', async () => {
|
|
59
|
+
const reward = await sut.getRewardForBlock(1_000_000n)
|
|
60
|
+
expect(reward).toEqual(475_000_000_000_000_000_000n)
|
|
61
|
+
expect(reward).toEqual(toFixedPoint(475n))
|
|
62
|
+
})
|
|
63
|
+
})
|
|
64
|
+
})
|
|
@@ -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<[string, number]> {
|
|
64
|
+
switch (domain) {
|
|
65
|
+
case 'xl1': {
|
|
66
|
+
return ['xl1', (await this.chainIterator.head()).block]
|
|
67
|
+
}
|
|
68
|
+
case 'epoch': {
|
|
69
|
+
return ['epoch', Date.now()]
|
|
70
|
+
}
|
|
71
|
+
case 'ethereum': {
|
|
72
|
+
return ['ethereum', (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'
|