@xyo-network/xl1-cli-lib 1.17.0 → 1.17.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.
- package/dist/node/commands/index.d.ts +0 -1
- package/dist/node/commands/index.d.ts.map +1 -1
- package/dist/node/commands/validator/runValidator.d.ts +2 -2
- package/dist/node/commands/validator/runValidator.d.ts.map +1 -1
- package/dist/node/index.mjs +190 -1356
- package/dist/node/index.mjs.map +1 -1
- package/dist/node/orchestration/actor/implementation/BalanceActor.d.ts +2 -6
- package/dist/node/orchestration/actor/implementation/BalanceActor.d.ts.map +1 -1
- package/dist/node/orchestration/actor/implementation/ValidatorActor.d.ts +5 -10
- package/dist/node/orchestration/actor/implementation/ValidatorActor.d.ts.map +1 -1
- package/dist/node/orchestration/actor/implementation/index.d.ts +0 -1
- package/dist/node/orchestration/actor/implementation/index.d.ts.map +1 -1
- package/dist/node/orchestration/actor/index.d.ts +0 -1
- package/dist/node/orchestration/actor/index.d.ts.map +1 -1
- package/dist/node/orchestration/index.d.ts +0 -1
- package/dist/node/orchestration/index.d.ts.map +1 -1
- package/dist/node/orchestration/initServices.d.ts.map +1 -1
- package/dist/node/runCLI.d.ts.map +1 -1
- package/dist/node/xl1.mjs +24 -1386
- package/dist/node/xl1.mjs.map +1 -1
- package/package.json +30 -31
- package/src/commands/index.ts +0 -1
- package/src/commands/validator/runValidator.ts +6 -8
- package/src/orchestration/actor/implementation/BalanceActor.ts +4 -16
- package/src/orchestration/actor/implementation/ValidatorActor.ts +19 -27
- package/src/orchestration/actor/implementation/index.ts +0 -1
- package/src/orchestration/actor/index.ts +0 -1
- package/src/orchestration/index.ts +0 -1
- package/src/orchestration/initServices.ts +69 -112
- package/src/runCLI.ts +15 -14
- package/dist/node/commands/producer/index.d.ts +0 -2
- package/dist/node/commands/producer/index.d.ts.map +0 -1
- package/dist/node/commands/producer/runProducer.d.ts +0 -11
- package/dist/node/commands/producer/runProducer.d.ts.map +0 -1
- package/dist/node/orchestration/actor/implementation/ProducerActor.d.ts +0 -35
- package/dist/node/orchestration/actor/implementation/ProducerActor.d.ts.map +0 -1
- package/dist/node/orchestration/actor/model/Actor.d.ts +0 -41
- package/dist/node/orchestration/actor/model/Actor.d.ts.map +0 -1
- package/dist/node/orchestration/actor/model/Orchestrator.d.ts +0 -27
- package/dist/node/orchestration/actor/model/Orchestrator.d.ts.map +0 -1
- package/dist/node/orchestration/actor/model/index.d.ts +0 -3
- package/dist/node/orchestration/actor/model/index.d.ts.map +0 -1
- package/dist/node/orchestration/services/implementation/accountBalance.d.ts +0 -7
- package/dist/node/orchestration/services/implementation/accountBalance.d.ts.map +0 -1
- package/dist/node/orchestration/services/implementation/blockViewer.d.ts +0 -7
- package/dist/node/orchestration/services/implementation/blockViewer.d.ts.map +0 -1
- package/dist/node/orchestration/services/implementation/chain/evm.d.ts +0 -7
- package/dist/node/orchestration/services/implementation/chain/evm.d.ts.map +0 -1
- package/dist/node/orchestration/services/implementation/chain/index.d.ts +0 -7
- package/dist/node/orchestration/services/implementation/chain/index.d.ts.map +0 -1
- package/dist/node/orchestration/services/implementation/evm/index.d.ts +0 -2
- package/dist/node/orchestration/services/implementation/evm/index.d.ts.map +0 -1
- package/dist/node/orchestration/services/implementation/evm/initChainId.d.ts +0 -4
- package/dist/node/orchestration/services/implementation/evm/initChainId.d.ts.map +0 -1
- package/dist/node/orchestration/services/implementation/evm/initEvmProvider.d.ts +0 -11
- package/dist/node/orchestration/services/implementation/evm/initEvmProvider.d.ts.map +0 -1
- package/dist/node/orchestration/services/implementation/evm/initInfuraProvider.d.ts +0 -6
- package/dist/node/orchestration/services/implementation/evm/initInfuraProvider.d.ts.map +0 -1
- package/dist/node/orchestration/services/implementation/evm/initJsonRpcProvider.d.ts +0 -6
- package/dist/node/orchestration/services/implementation/evm/initJsonRpcProvider.d.ts.map +0 -1
- package/dist/node/orchestration/services/implementation/head/createBootstrapHead.d.ts +0 -5
- package/dist/node/orchestration/services/implementation/head/createBootstrapHead.d.ts.map +0 -1
- package/dist/node/orchestration/services/implementation/head/createForkedHead/config/getBridgeDestinationDetails.d.ts +0 -8
- package/dist/node/orchestration/services/implementation/head/createForkedHead/config/getBridgeDestinationDetails.d.ts.map +0 -1
- package/dist/node/orchestration/services/implementation/head/createForkedHead/config/getBridgeSourceDetails.d.ts +0 -9
- package/dist/node/orchestration/services/implementation/head/createForkedHead/config/getBridgeSourceDetails.d.ts.map +0 -1
- package/dist/node/orchestration/services/implementation/head/createForkedHead/config/getForkDetails.d.ts +0 -4
- package/dist/node/orchestration/services/implementation/head/createForkedHead/config/getForkDetails.d.ts.map +0 -1
- package/dist/node/orchestration/services/implementation/head/createForkedHead/config/index.d.ts +0 -4
- package/dist/node/orchestration/services/implementation/head/createForkedHead/config/index.d.ts.map +0 -1
- package/dist/node/orchestration/services/implementation/head/createForkedHead/createForkedHead.d.ts +0 -5
- package/dist/node/orchestration/services/implementation/head/createForkedHead/createForkedHead.d.ts.map +0 -1
- package/dist/node/orchestration/services/implementation/head/createForkedHead/getBridgeDestinationObservation.d.ts +0 -11
- package/dist/node/orchestration/services/implementation/head/createForkedHead/getBridgeDestinationObservation.d.ts.map +0 -1
- package/dist/node/orchestration/services/implementation/head/createForkedHead/getBridgeIntent.d.ts +0 -11
- package/dist/node/orchestration/services/implementation/head/createForkedHead/getBridgeIntent.d.ts.map +0 -1
- package/dist/node/orchestration/services/implementation/head/createForkedHead/getBridgeSourceObservation.d.ts +0 -11
- package/dist/node/orchestration/services/implementation/head/createForkedHead/getBridgeSourceObservation.d.ts.map +0 -1
- package/dist/node/orchestration/services/implementation/head/createForkedHead/getFirstBlockForNewChain.d.ts +0 -13
- package/dist/node/orchestration/services/implementation/head/createForkedHead/getFirstBlockForNewChain.d.ts.map +0 -1
- package/dist/node/orchestration/services/implementation/head/createForkedHead/index.d.ts +0 -2
- package/dist/node/orchestration/services/implementation/head/createForkedHead/index.d.ts.map +0 -1
- package/dist/node/orchestration/services/implementation/head/getForkFromBlock.d.ts +0 -12
- package/dist/node/orchestration/services/implementation/head/getForkFromBlock.d.ts.map +0 -1
- package/dist/node/orchestration/services/implementation/head/head.d.ts +0 -11
- package/dist/node/orchestration/services/implementation/head/head.d.ts.map +0 -1
- package/dist/node/orchestration/services/implementation/head/index.d.ts +0 -2
- package/dist/node/orchestration/services/implementation/head/index.d.ts.map +0 -1
- package/dist/node/orchestration/services/implementation/head/submitNewChain.d.ts +0 -10
- package/dist/node/orchestration/services/implementation/head/submitNewChain.d.ts.map +0 -1
- package/dist/node/orchestration/services/implementation/index.d.ts +0 -12
- package/dist/node/orchestration/services/implementation/index.d.ts.map +0 -1
- package/dist/node/orchestration/services/implementation/pendingTransactions.d.ts +0 -9
- package/dist/node/orchestration/services/implementation/pendingTransactions.d.ts.map +0 -1
- package/dist/node/orchestration/services/implementation/producer.d.ts +0 -5
- package/dist/node/orchestration/services/implementation/producer.d.ts.map +0 -1
- package/dist/node/orchestration/services/implementation/reward.d.ts +0 -5
- package/dist/node/orchestration/services/implementation/reward.d.ts.map +0 -1
- package/dist/node/orchestration/services/implementation/time.d.ts +0 -6
- package/dist/node/orchestration/services/implementation/time.d.ts.map +0 -1
- package/dist/node/orchestration/services/implementation/transfer.d.ts +0 -5
- package/dist/node/orchestration/services/implementation/transfer.d.ts.map +0 -1
- package/dist/node/orchestration/services/implementation/validator.d.ts +0 -5
- package/dist/node/orchestration/services/implementation/validator.d.ts.map +0 -1
- package/dist/node/orchestration/services/index.d.ts +0 -2
- package/dist/node/orchestration/services/index.d.ts.map +0 -1
- package/src/commands/producer/index.ts +0 -1
- package/src/commands/producer/runProducer.ts +0 -40
- package/src/orchestration/actor/implementation/ProducerActor.ts +0 -302
- package/src/orchestration/actor/model/Actor.ts +0 -167
- package/src/orchestration/actor/model/Orchestrator.ts +0 -71
- package/src/orchestration/actor/model/index.ts +0 -2
- package/src/orchestration/services/implementation/accountBalance.ts +0 -29
- package/src/orchestration/services/implementation/blockViewer.ts +0 -29
- package/src/orchestration/services/implementation/chain/evm.ts +0 -39
- package/src/orchestration/services/implementation/chain/index.ts +0 -45
- package/src/orchestration/services/implementation/evm/index.ts +0 -1
- package/src/orchestration/services/implementation/evm/initChainId.ts +0 -20
- package/src/orchestration/services/implementation/evm/initEvmProvider.ts +0 -24
- package/src/orchestration/services/implementation/evm/initInfuraProvider.ts +0 -26
- package/src/orchestration/services/implementation/evm/initJsonRpcProvider.ts +0 -20
- package/src/orchestration/services/implementation/head/createBootstrapHead.ts +0 -31
- package/src/orchestration/services/implementation/head/createForkedHead/config/getBridgeDestinationDetails.ts +0 -27
- package/src/orchestration/services/implementation/head/createForkedHead/config/getBridgeSourceDetails.ts +0 -19
- package/src/orchestration/services/implementation/head/createForkedHead/config/getForkDetails.ts +0 -10
- package/src/orchestration/services/implementation/head/createForkedHead/config/index.ts +0 -3
- package/src/orchestration/services/implementation/head/createForkedHead/createForkedHead.ts +0 -29
- package/src/orchestration/services/implementation/head/createForkedHead/getBridgeDestinationObservation.ts +0 -42
- package/src/orchestration/services/implementation/head/createForkedHead/getBridgeIntent.ts +0 -51
- package/src/orchestration/services/implementation/head/createForkedHead/getBridgeSourceObservation.ts +0 -46
- package/src/orchestration/services/implementation/head/createForkedHead/getFirstBlockForNewChain.ts +0 -41
- package/src/orchestration/services/implementation/head/createForkedHead/index.ts +0 -1
- package/src/orchestration/services/implementation/head/getForkFromBlock.ts +0 -43
- package/src/orchestration/services/implementation/head/head.ts +0 -49
- package/src/orchestration/services/implementation/head/index.ts +0 -1
- package/src/orchestration/services/implementation/head/submitNewChain.ts +0 -27
- package/src/orchestration/services/implementation/index.ts +0 -11
- package/src/orchestration/services/implementation/pendingTransactions.ts +0 -35
- package/src/orchestration/services/implementation/producer.ts +0 -15
- package/src/orchestration/services/implementation/reward.ts +0 -50
- package/src/orchestration/services/implementation/time.ts +0 -26
- package/src/orchestration/services/implementation/transfer.ts +0 -15
- package/src/orchestration/services/implementation/validator.ts +0 -15
- package/src/orchestration/services/index.ts +0 -1
|
@@ -1,302 +0,0 @@
|
|
|
1
|
-
import type { Attributes, Counter } from '@opentelemetry/api'
|
|
2
|
-
import type { Promisable } from '@xylabs/sdk-js'
|
|
3
|
-
import {
|
|
4
|
-
assertEx, isDefined, isUndefined, toHex,
|
|
5
|
-
} from '@xylabs/sdk-js'
|
|
6
|
-
import { createDeclarationIntent } from '@xyo-network/chain-protocol'
|
|
7
|
-
import { BaseBlockProducerService } from '@xyo-network/chain-services'
|
|
8
|
-
import { PayloadBuilder } from '@xyo-network/payload-builder'
|
|
9
|
-
import type { PayloadBundle } from '@xyo-network/payload-model'
|
|
10
|
-
import { PayloadBundleSchema } from '@xyo-network/payload-model'
|
|
11
|
-
import type {
|
|
12
|
-
ChainStakeIntent, HydratedBlockWithHashMeta,
|
|
13
|
-
XL1BlockNumber,
|
|
14
|
-
} from '@xyo-network/xl1-protocol'
|
|
15
|
-
import { asXL1BlockNumber } from '@xyo-network/xl1-protocol'
|
|
16
|
-
import type { ChainServiceCollectionV2 } from '@xyo-network/xl1-protocol-sdk'
|
|
17
|
-
import {
|
|
18
|
-
buildTransaction, flattenHydratedBlock, flattenHydratedTransaction,
|
|
19
|
-
} from '@xyo-network/xl1-protocol-sdk'
|
|
20
|
-
import { Mutex } from 'async-mutex'
|
|
21
|
-
|
|
22
|
-
import type { ActorParams } from '../model/index.ts'
|
|
23
|
-
import { Actor } from '../model/index.ts'
|
|
24
|
-
|
|
25
|
-
export type ProducerActorParams = ActorParams<
|
|
26
|
-
Pick<
|
|
27
|
-
ChainServiceCollectionV2,
|
|
28
|
-
'account'
|
|
29
|
-
| 'balance'
|
|
30
|
-
| 'blockViewer'
|
|
31
|
-
| 'chainStakeViewer'
|
|
32
|
-
| 'chainSubmissionsArchivistWrite'
|
|
33
|
-
| 'pendingBundledTransactionsArchivistWrite'
|
|
34
|
-
| 'producer'
|
|
35
|
-
| 'stakeIntent'
|
|
36
|
-
>
|
|
37
|
-
>
|
|
38
|
-
|
|
39
|
-
const SHOULD_REGISTER_REDECLARATION_INTENT_TIMER = true
|
|
40
|
-
const TEN_MINUTES = 10 * 60 * 1000 // 10 minutes in milliseconds
|
|
41
|
-
|
|
42
|
-
export class ProducerActor extends Actor<ProducerActorParams> {
|
|
43
|
-
protected _lastProducedBlock: HydratedBlockWithHashMeta | undefined
|
|
44
|
-
protected _lastRedeclarationIntent: ChainStakeIntent | undefined
|
|
45
|
-
protected readonly _metricAttributes: Attributes
|
|
46
|
-
protected readonly _producerActorBlockProductionAttempts: Counter<Attributes> | undefined
|
|
47
|
-
protected readonly _producerActorBlockProductionChecks: Counter<Attributes> | undefined
|
|
48
|
-
protected readonly _producerActorBlocksProduced: Counter<Attributes> | undefined
|
|
49
|
-
protected readonly _producerActorBlocksPublished: Counter<Attributes> | undefined
|
|
50
|
-
|
|
51
|
-
private _produceBlockMutex = new Mutex()
|
|
52
|
-
|
|
53
|
-
protected constructor(params: ProducerActorParams) {
|
|
54
|
-
super(params.producer.address, 'Producer', params)
|
|
55
|
-
// Create the consistent meter attributes that will
|
|
56
|
-
// be included with all metrics from this actor
|
|
57
|
-
this._metricAttributes = { address: this.account.address.toString() }
|
|
58
|
-
// Create the metrics
|
|
59
|
-
this._producerActorBlockProductionChecks = this.meter?.createCounter(
|
|
60
|
-
'producer_actor_block_production_checks',
|
|
61
|
-
{ description: 'Number of block production checks' },
|
|
62
|
-
)
|
|
63
|
-
this._producerActorBlockProductionAttempts = this.meter?.createCounter(
|
|
64
|
-
'producer_actor_block_production_attempts',
|
|
65
|
-
{ description: 'Number of block production attempts' },
|
|
66
|
-
)
|
|
67
|
-
this._producerActorBlocksProduced = this.meter?.createCounter(
|
|
68
|
-
'producer_actor_blocks_produced',
|
|
69
|
-
{ description: 'Number of blocks produced' },
|
|
70
|
-
)
|
|
71
|
-
this._producerActorBlocksPublished = this.meter?.createCounter(
|
|
72
|
-
'producer_actor_blocks_published',
|
|
73
|
-
{ description: 'Number of blocks published' },
|
|
74
|
-
)
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
protected get account() {
|
|
78
|
-
return assertEx(this.params.account, () => 'account not set')
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
protected get balanceService() {
|
|
82
|
-
return assertEx(this.params.balance, () => 'balanceService not set')
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
protected get blockViewer() {
|
|
86
|
-
return assertEx(this.params.blockViewer, () => 'blockViewer not set')
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
protected get chainStakeViewer() {
|
|
90
|
-
return assertEx(this.params.chainStakeViewer, () => 'chainStakeViewer not set')
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
protected get chainSubmissionsArchivistWrite() {
|
|
94
|
-
return assertEx(this.params.chainSubmissionsArchivistWrite, () => 'chainSubmissionsArchivistWrite not set')
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
protected get pendingBundledTransactionsArchivistWrite() {
|
|
98
|
-
return assertEx(this.params.pendingBundledTransactionsArchivistWrite, () => 'pendingBundledTransactionsArchivistWrite not set')
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
protected get producer() {
|
|
102
|
-
return assertEx(this.params.producer, () => 'producer not set')
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
protected get stakeIntentService() {
|
|
106
|
-
return assertEx(this.params.stakeIntent, () => 'stakeIntentService not set')
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
static create(params: ProducerActorParams): Promisable<ProducerActor> {
|
|
110
|
-
return new ProducerActor(params)
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
override async start(): Promise<void> {
|
|
114
|
-
await super.start()
|
|
115
|
-
// Register a timer to check if we should produce a block
|
|
116
|
-
this.registerTimer('BlockProductionTimer', async () => {
|
|
117
|
-
await this.produceBlock()
|
|
118
|
-
}, 2000, 1500/* 500 */)
|
|
119
|
-
|
|
120
|
-
if (SHOULD_REGISTER_REDECLARATION_INTENT_TIMER) {
|
|
121
|
-
// Register a timer to check if we should redeclare the producer
|
|
122
|
-
this.registerTimer('ProducerRedeclarationTimer', async () => {
|
|
123
|
-
await this.redeclareIntent()
|
|
124
|
-
}, TEN_MINUTES, TEN_MINUTES)
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
protected async calculateBlocksUntilProducerDeclarationExpiration(currentBlock: number): Promise<number> {
|
|
129
|
-
// Decide if we need to redeclare intent
|
|
130
|
-
const ranges = await this.stakeIntentService.getDeclaredCandidateRanges(this.account.address, 'producer')
|
|
131
|
-
// TODO: This doesn't handle the case where the producer had declared a range for the future
|
|
132
|
-
// but we're in a range that's not the future
|
|
133
|
-
// Sort in ascending order based on ending range to get range with highest ending block
|
|
134
|
-
const lastRange = ranges.toSorted((a, b) => a[1] > b[1] ? 1 : -1).at(-1)
|
|
135
|
-
|
|
136
|
-
// Use the most recent range's end block as the current declaration end OR
|
|
137
|
-
const [, currentDeclarationEnd] = lastRange
|
|
138
|
-
// If we have no ranges, we need to declare intent, so use the current block
|
|
139
|
-
?? [undefined, currentBlock]
|
|
140
|
-
|
|
141
|
-
// Calculate the time until the producer's declaration expires
|
|
142
|
-
const timeToProducerExpiration = currentDeclarationEnd - currentBlock
|
|
143
|
-
return timeToProducerExpiration
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
protected async produceBlock(): Promise<void> {
|
|
147
|
-
this._producerActorBlockProductionChecks?.add(1, this._metricAttributes)
|
|
148
|
-
await this.spanAsync('produceBlock', async () => {
|
|
149
|
-
if (this._produceBlockMutex.isLocked()) {
|
|
150
|
-
this.logger?.log('Skipping block production, previous production still in progress')
|
|
151
|
-
return
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
await this._produceBlockMutex.runExclusive(async () => {
|
|
155
|
-
// Get the updated head
|
|
156
|
-
const headStart = Date.now()
|
|
157
|
-
const head = (await this.blockViewer.currentBlock())[0]
|
|
158
|
-
const headDuration = Date.now() - headStart
|
|
159
|
-
if (headDuration > 500) this.logger?.warn(`[Slow] Fetched head in ${headDuration}ms: 0x${toHex(head._hash)}`)
|
|
160
|
-
// Check if we've already produced the next block for this head
|
|
161
|
-
const headHash = head._hash
|
|
162
|
-
// If our last produced block was the next block for the current head, we do not
|
|
163
|
-
// need to produce another. This prevents duplicate blocks from being produced
|
|
164
|
-
if (this._lastProducedBlock && this._lastProducedBlock[0].previous === headHash) {
|
|
165
|
-
this.logger?.log('Block already produced:', `0x${toHex(this._lastProducedBlock[0].block)}`, this._lastProducedBlock[0].block)
|
|
166
|
-
} else {
|
|
167
|
-
this._producerActorBlockProductionAttempts?.add(1, this._metricAttributes)
|
|
168
|
-
// Produce the next block
|
|
169
|
-
const nextStart = Date.now()
|
|
170
|
-
const nextBlock = await this.producer.next(head)
|
|
171
|
-
const nextDuration = Date.now() - nextStart
|
|
172
|
-
if (nextDuration > 1000) this.logger?.warn(`[Slow] Generated next block in ${nextDuration}ms, block: ${nextBlock?.[0]._hash}`)
|
|
173
|
-
// If it was produced
|
|
174
|
-
if (nextBlock) {
|
|
175
|
-
const displayBlockNumber = `0x${toHex(nextBlock[0].block)}`
|
|
176
|
-
this.logger?.log('Produced block:', displayBlockNumber)
|
|
177
|
-
this._producerActorBlocksProduced?.add(1, this._metricAttributes)
|
|
178
|
-
// Insert the block into the chain
|
|
179
|
-
await this.chainSubmissionsArchivistWrite.insert(flattenHydratedBlock(nextBlock))
|
|
180
|
-
this.logger?.log('Published block:', displayBlockNumber, nextBlock[0].block)
|
|
181
|
-
this._producerActorBlocksPublished?.add(1, this._metricAttributes)
|
|
182
|
-
// Record that we have produced a block so we do not produce it again
|
|
183
|
-
this._lastProducedBlock = nextBlock
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
})
|
|
187
|
-
})
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
protected async redeclareIntent(): Promise<void> {
|
|
191
|
-
await this.spanAsync('redeclareIntent', async () => {
|
|
192
|
-
// Decide if we should redeclare intent
|
|
193
|
-
if (this.params.config.producer.disableIntentRedeclaration) return
|
|
194
|
-
|
|
195
|
-
// Get the current block
|
|
196
|
-
const head = (await this.blockViewer.currentBlock())[0]
|
|
197
|
-
if (isUndefined(head)) return
|
|
198
|
-
const currentBlock = head.block
|
|
199
|
-
|
|
200
|
-
// Calculate the time until the producer's declaration expires
|
|
201
|
-
const blocksUntilExpiration = await this.calculateBlocksUntilProducerDeclarationExpiration(currentBlock)
|
|
202
|
-
|
|
203
|
-
// Allow the producer time to redeclare itself via block production
|
|
204
|
-
// (for free) before submitting a redeclaration intent transaction.
|
|
205
|
-
if (blocksUntilExpiration > BaseBlockProducerService.RedeclarationWindow * 0.1) {
|
|
206
|
-
// Clear any previous redeclaration intent
|
|
207
|
-
this._lastRedeclarationIntent = undefined
|
|
208
|
-
// No need to redeclare yet
|
|
209
|
-
return
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
// If we already have a valid redeclaration intent, do not create another
|
|
213
|
-
// unless it has expired.
|
|
214
|
-
if (this._lastRedeclarationIntent) {
|
|
215
|
-
// Check if the last redeclaration intent is still valid
|
|
216
|
-
if (this._lastRedeclarationIntent.exp > currentBlock) return
|
|
217
|
-
// If it has expired, clear the last redeclaration intent
|
|
218
|
-
this._lastRedeclarationIntent = undefined
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
// Check if we have a valid balance before declaring intent
|
|
222
|
-
if (!await this.validateCurrentBalance()) {
|
|
223
|
-
this.logger?.error(
|
|
224
|
-
`Add balance to address ${this.account.address} for the producer to declare it's intent.`,
|
|
225
|
-
)
|
|
226
|
-
return
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
// Check if we have a valid stake before declaring intent
|
|
230
|
-
if (!(await this.validateCurrentStake())) {
|
|
231
|
-
this.logger?.error(
|
|
232
|
-
`Add stake to contract address ${this.params.config.chain.id}`
|
|
233
|
-
+ ' for the producer to declare it\'s intent.',
|
|
234
|
-
)
|
|
235
|
-
return
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
// Create a redeclaration intent
|
|
239
|
-
this.logger?.log('Creating redeclaration intent for producer:', this.account.address)
|
|
240
|
-
const redeclarationIntent = createDeclarationIntent(
|
|
241
|
-
this.account.address,
|
|
242
|
-
'producer',
|
|
243
|
-
currentBlock,
|
|
244
|
-
currentBlock + BaseBlockProducerService.RedeclarationDuration,
|
|
245
|
-
)
|
|
246
|
-
|
|
247
|
-
// Submit the redeclaration intent
|
|
248
|
-
await this.submitRedeclarationIntent(currentBlock, redeclarationIntent)
|
|
249
|
-
|
|
250
|
-
// On successful submission, save the redeclaration intent
|
|
251
|
-
this._lastRedeclarationIntent = redeclarationIntent
|
|
252
|
-
})
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
protected async submitRedeclarationIntent(currentBlock: XL1BlockNumber, redeclarationIntent: ChainStakeIntent): Promise<void> {
|
|
256
|
-
this.logger?.log('Submitting redeclaration intent for producer:', this.account.address)
|
|
257
|
-
// Create a transaction to submit the redeclaration intent
|
|
258
|
-
const tx = await buildTransaction(
|
|
259
|
-
await this.chainStakeViewer.chainId(),
|
|
260
|
-
[redeclarationIntent],
|
|
261
|
-
[],
|
|
262
|
-
this.account,
|
|
263
|
-
currentBlock,
|
|
264
|
-
asXL1BlockNumber(currentBlock + 1000, true),
|
|
265
|
-
)
|
|
266
|
-
const payloads = flattenHydratedTransaction(tx)
|
|
267
|
-
const root = tx[0]._hash
|
|
268
|
-
const payloadBundle = new PayloadBuilder<PayloadBundle>({ schema: PayloadBundleSchema }).fields({ payloads, root }).build()
|
|
269
|
-
|
|
270
|
-
// Submit the redeclaration intent
|
|
271
|
-
await this.pendingBundledTransactionsArchivistWrite.insert([payloadBundle])
|
|
272
|
-
|
|
273
|
-
this.logger?.log('Submitted redeclaration intent for producer:', this.account.address)
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
protected async validateCurrentBalance(): Promise<boolean> {
|
|
277
|
-
// Check if we have a valid balance before declaring intent
|
|
278
|
-
const head = this._lastProducedBlock?.[0]._hash
|
|
279
|
-
if (isDefined(head)) {
|
|
280
|
-
const balances = await this.balanceService.accountsBalances([this.account.address], head)
|
|
281
|
-
const currentBalance = balances[this.account.address] ?? 0n
|
|
282
|
-
if (currentBalance <= 0n) {
|
|
283
|
-
this.logger?.error(`Producer ${this.account.address} has no balance.`)
|
|
284
|
-
return false
|
|
285
|
-
}
|
|
286
|
-
return true
|
|
287
|
-
}
|
|
288
|
-
return true
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
protected async validateCurrentStake(): Promise<boolean> {
|
|
292
|
-
// Use StakeIntentService to get the required minimum stake
|
|
293
|
-
const requiredMinimumStake = this.stakeIntentService.getRequiredMinimumStakeForIntent('producer')
|
|
294
|
-
// Check if we have a valid stake before declaring intent
|
|
295
|
-
const currentStake = await this.chainStakeViewer.activeByStaked(this.account.address)
|
|
296
|
-
if (currentStake < requiredMinimumStake) {
|
|
297
|
-
this.logger?.error(`Producer ${this.account.address} has insufficient stake.`)
|
|
298
|
-
return false
|
|
299
|
-
}
|
|
300
|
-
return true
|
|
301
|
-
}
|
|
302
|
-
}
|
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
import type { BaseParams, EmptyObject } from '@xylabs/sdk-js'
|
|
2
|
-
import {
|
|
3
|
-
Base, delay, IdLogger,
|
|
4
|
-
} from '@xylabs/sdk-js'
|
|
5
|
-
import { span, spanRootAsync } from '@xylabs/telemetry'
|
|
6
|
-
import type { Config } from '@xyo-network/xl1-protocol-sdk'
|
|
7
|
-
import { Semaphore } from 'async-mutex'
|
|
8
|
-
|
|
9
|
-
export interface IActor {
|
|
10
|
-
start(): Promise<void>
|
|
11
|
-
stop(): Promise<void>
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export type ActorParams<T extends EmptyObject | void = void> = BaseParams<{
|
|
15
|
-
config: Config
|
|
16
|
-
name: string
|
|
17
|
-
} & (T extends void ? EmptyObject : T)>
|
|
18
|
-
|
|
19
|
-
export class Actor<TParams extends ActorParams = ActorParams> extends Base<TParams> implements IActor {
|
|
20
|
-
protected readonly _intervals: Map<string, ReturnType<typeof setInterval>> = new Map()
|
|
21
|
-
protected readonly _semaphores: Map<string, Semaphore> = new Map()
|
|
22
|
-
protected readonly _timeouts: Map<string, ReturnType<typeof setTimeout>> = new Map()
|
|
23
|
-
private _active = false
|
|
24
|
-
private readonly _displayName: string
|
|
25
|
-
private readonly _id: string
|
|
26
|
-
|
|
27
|
-
constructor(id: string, displayName: string = 'Actor', params: TParams) {
|
|
28
|
-
const logger = params.logger ?? new IdLogger(Base.defaultLogger ?? console, () => `[${displayName} (${id})] `)
|
|
29
|
-
super({ ...params, logger })
|
|
30
|
-
this._displayName = displayName
|
|
31
|
-
this._id = id
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
get displayName() {
|
|
35
|
-
return this._displayName
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
get id() {
|
|
39
|
-
return this._id
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
get name() {
|
|
43
|
-
return this.params.name
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
protected get logPrefix() {
|
|
47
|
-
return `[${this.displayName} (${this.id})] `
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* The timer runs until the actor is deactivated (or you manually stop it).
|
|
52
|
-
*/
|
|
53
|
-
registerTimer(timerName: string, callback: () => Promise<void>, dueTimeMs: number, periodMs: number) {
|
|
54
|
-
if (!this._active) {
|
|
55
|
-
this.logger?.warn(
|
|
56
|
-
`Cannot register timer '${timerName}' because actor is not active.`,
|
|
57
|
-
)
|
|
58
|
-
return
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
let running = false
|
|
62
|
-
|
|
63
|
-
this._semaphores.set(timerName, new Semaphore(1))
|
|
64
|
-
|
|
65
|
-
const timeoutId = setTimeout(() => {
|
|
66
|
-
const intervalId = setInterval(() => {
|
|
67
|
-
const semaphore = this._semaphores.get(timerName)
|
|
68
|
-
if (!this._active || !this._intervals.has(timerName) || !semaphore || running) return
|
|
69
|
-
if (semaphore.isLocked()) {
|
|
70
|
-
this.logger?.warn(
|
|
71
|
-
`Skipping timer '${this.name}:${timerName}' execution because previous execution is still running.`,
|
|
72
|
-
)
|
|
73
|
-
return
|
|
74
|
-
}
|
|
75
|
-
semaphore.acquire().then(([, release]) => {
|
|
76
|
-
const startTime = Date.now()
|
|
77
|
-
running = true
|
|
78
|
-
callback()
|
|
79
|
-
.then(() => {
|
|
80
|
-
const duration = Date.now() - startTime
|
|
81
|
-
if (duration > periodMs) {
|
|
82
|
-
this.logger?.warn(
|
|
83
|
-
`Timer '${this.name}:${timerName}' execution took longer (${duration}ms) than the period (${periodMs}ms).`,
|
|
84
|
-
)
|
|
85
|
-
} else if (duration > 5000) {
|
|
86
|
-
this.logger?.warn(
|
|
87
|
-
`Timer '${this.name}:${timerName}' execution took longer (${duration}ms) than 5000ms.`,
|
|
88
|
-
)
|
|
89
|
-
}
|
|
90
|
-
})
|
|
91
|
-
.catch((error) => {
|
|
92
|
-
this.logger?.error(`Error in timer '${this.name}:${timerName}': ${error}`)
|
|
93
|
-
})
|
|
94
|
-
.finally(() => {
|
|
95
|
-
release()
|
|
96
|
-
running = false
|
|
97
|
-
})
|
|
98
|
-
}).catch((error) => {
|
|
99
|
-
this.logger?.error(`Error acquiring semaphore for timer '${this.name}:${timerName}': ${error}`)
|
|
100
|
-
})
|
|
101
|
-
}, periodMs)
|
|
102
|
-
|
|
103
|
-
// store interval so we can clear it on stop()
|
|
104
|
-
this._intervals.set(timerName, intervalId)
|
|
105
|
-
}, dueTimeMs)
|
|
106
|
-
|
|
107
|
-
// store timeout so we can clear it on stop() if interval hasn't started yet
|
|
108
|
-
this._timeouts.set(timerName, timeoutId)
|
|
109
|
-
|
|
110
|
-
this.logger?.log(
|
|
111
|
-
`Timer '${this.name}:${timerName}' registered: first call after ${dueTimeMs}ms, recurring every ${periodMs}ms.`,
|
|
112
|
-
)
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
span<T>(name: string, fn: () => T): T {
|
|
116
|
-
return span(`${this.name}:${name}`, fn, this.tracer)
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
async spanAsync<T>(name: string, fn: () => Promise<T>): Promise<T> {
|
|
120
|
-
return await spanRootAsync(`${this.name}:${name}`, fn, this.tracer)
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Called by the Orchestrator when the actor is activated.
|
|
125
|
-
*/
|
|
126
|
-
async start() {
|
|
127
|
-
await Promise.resolve()
|
|
128
|
-
this._active = true
|
|
129
|
-
this.logger?.log('Started.')
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Called by the Orchestrator when the actor is deactivated.
|
|
134
|
-
* Stop all running timers.
|
|
135
|
-
*/
|
|
136
|
-
async stop() {
|
|
137
|
-
await Promise.resolve()
|
|
138
|
-
this._active = false
|
|
139
|
-
this.logger?.log('Stopping all timers...')
|
|
140
|
-
|
|
141
|
-
// wait for all semaphores to be free and acquire them to prevent new tasks from starting
|
|
142
|
-
await Promise.all(
|
|
143
|
-
[...this._semaphores.values()].map(async (semaphore) => {
|
|
144
|
-
// Wait for any running tasks to complete
|
|
145
|
-
while (semaphore.isLocked()) {
|
|
146
|
-
this.logger?.log('Waiting for running timer task to complete...')
|
|
147
|
-
await delay(500)
|
|
148
|
-
}
|
|
149
|
-
await semaphore.acquire()
|
|
150
|
-
}),
|
|
151
|
-
)
|
|
152
|
-
|
|
153
|
-
this._semaphores.clear()
|
|
154
|
-
|
|
155
|
-
for (const [, timeoutRef] of this._timeouts.entries()) {
|
|
156
|
-
clearTimeout(timeoutRef)
|
|
157
|
-
}
|
|
158
|
-
this._timeouts.clear()
|
|
159
|
-
|
|
160
|
-
for (const [, intervalRef] of this._intervals.entries()) {
|
|
161
|
-
clearInterval(intervalRef)
|
|
162
|
-
}
|
|
163
|
-
this._intervals.clear()
|
|
164
|
-
|
|
165
|
-
this.logger?.log('Stopped.')
|
|
166
|
-
}
|
|
167
|
-
}
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import type { Logger } from '@xylabs/sdk-js'
|
|
2
|
-
|
|
3
|
-
import type { IActor } from './Actor.ts'
|
|
4
|
-
|
|
5
|
-
export interface IOrchestrator {
|
|
6
|
-
start(): Promise<void>
|
|
7
|
-
stop(): Promise<void>
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export class Orchestrator implements IOrchestrator {
|
|
11
|
-
protected actors: IActor[] = []
|
|
12
|
-
protected keepAliveHandle: NodeJS.Timeout | null = null
|
|
13
|
-
protected readonly logger?: Logger
|
|
14
|
-
protected running = false
|
|
15
|
-
|
|
16
|
-
constructor(logger?: Logger) {
|
|
17
|
-
this.logger = logger
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Registers an actor.
|
|
22
|
-
* (We won't activate the actor until `start()` is called.)
|
|
23
|
-
*/
|
|
24
|
-
async registerActor(actor: IActor) {
|
|
25
|
-
if (this.running) {
|
|
26
|
-
// If the orchestrator is already running, activate the actor immediately
|
|
27
|
-
await actor.start()
|
|
28
|
-
}
|
|
29
|
-
this.actors.push(actor)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Starts the orchestrator: activates all actors.
|
|
34
|
-
*/
|
|
35
|
-
async start() {
|
|
36
|
-
await Promise.resolve()
|
|
37
|
-
if (this.running) {
|
|
38
|
-
this.logger?.warn('[Orchestrator] Already started.')
|
|
39
|
-
return
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
this.logger?.log('[Orchestrator] Starting...')
|
|
43
|
-
this.running = true
|
|
44
|
-
for (const actor of this.actors) {
|
|
45
|
-
await actor.start()
|
|
46
|
-
}
|
|
47
|
-
// This interval will fire every 24.8 days (2^31 - 1 ms), effectively never finishing
|
|
48
|
-
this.keepAliveHandle = setInterval(() => {
|
|
49
|
-
// No-op
|
|
50
|
-
}, 2_147_483_647)
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Stops the orchestrator: deactivates all actors.
|
|
55
|
-
*/
|
|
56
|
-
async stop() {
|
|
57
|
-
await Promise.resolve()
|
|
58
|
-
if (!this.running) {
|
|
59
|
-
this.logger?.log('[Orchestrator] Already stopped.')
|
|
60
|
-
return
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
this.logger?.log('[Orchestrator] Stopping...')
|
|
64
|
-
for (const actor of this.actors) {
|
|
65
|
-
await actor.stop()
|
|
66
|
-
}
|
|
67
|
-
this.running = false
|
|
68
|
-
if (this.keepAliveHandle) clearInterval(this.keepAliveHandle)
|
|
69
|
-
this.logger?.log('[Orchestrator] Stopped...')
|
|
70
|
-
}
|
|
71
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { isDefined, type Promisable } from '@xylabs/sdk-js'
|
|
2
|
-
import type { Initializable, InitializableParams } from '@xyo-network/xl1-protocol'
|
|
3
|
-
import type { AccountBalanceViewer, Config } from '@xyo-network/xl1-protocol-sdk'
|
|
4
|
-
import {
|
|
5
|
-
AccountBalanceViewerRpcSchemas,
|
|
6
|
-
HttpRpcTransport,
|
|
7
|
-
JsonRpcAccountBalanceViewer,
|
|
8
|
-
} from '@xyo-network/xl1-rpc'
|
|
9
|
-
|
|
10
|
-
let balanceServiceSingleton: Promisable<AccountBalanceViewer> | undefined
|
|
11
|
-
|
|
12
|
-
export type InitAccountBalanceServiceParams = InitializableParams<{
|
|
13
|
-
config: Config
|
|
14
|
-
}>
|
|
15
|
-
|
|
16
|
-
export const initAccountBalanceService: Initializable<InitAccountBalanceServiceParams, AccountBalanceViewer>
|
|
17
|
-
= (params): Promisable<AccountBalanceViewer> => {
|
|
18
|
-
const { config, logger } = params
|
|
19
|
-
if (balanceServiceSingleton) return balanceServiceSingleton
|
|
20
|
-
const endpoint = config.services?.accountBalanceViewerEndpoint ?? config.services?.apiEndpoint
|
|
21
|
-
if (isDefined(endpoint)) {
|
|
22
|
-
const transport = new HttpRpcTransport(endpoint, { ...AccountBalanceViewerRpcSchemas })
|
|
23
|
-
const viewer = new JsonRpcAccountBalanceViewer(transport)
|
|
24
|
-
logger?.log('Using AccountBalanceViewer RPC service at', endpoint)
|
|
25
|
-
return viewer
|
|
26
|
-
} else {
|
|
27
|
-
throw new Error('No AccountBalanceViewer endpoint configured')
|
|
28
|
-
}
|
|
29
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { isDefined, type Promisable } from '@xylabs/sdk-js'
|
|
2
|
-
import type { Initializable, InitializableParams } from '@xyo-network/xl1-protocol'
|
|
3
|
-
import type { BlockViewer, Config } from '@xyo-network/xl1-protocol-sdk'
|
|
4
|
-
import {
|
|
5
|
-
BlockViewerRpcSchemas,
|
|
6
|
-
HttpRpcTransport,
|
|
7
|
-
JsonRpcBlockViewer,
|
|
8
|
-
} from '@xyo-network/xl1-rpc'
|
|
9
|
-
|
|
10
|
-
let blockViewerSingleton: Promisable<BlockViewer> | undefined
|
|
11
|
-
|
|
12
|
-
export type InitBlockViewerParams = InitializableParams<{
|
|
13
|
-
config: Config
|
|
14
|
-
}>
|
|
15
|
-
|
|
16
|
-
export const initBlockViewer: Initializable<InitBlockViewerParams, BlockViewer>
|
|
17
|
-
= (params): Promisable<BlockViewer> => {
|
|
18
|
-
const { config, logger } = params
|
|
19
|
-
if (blockViewerSingleton) return blockViewerSingleton
|
|
20
|
-
const endpoint = config.services?.apiEndpoint
|
|
21
|
-
if (isDefined(endpoint)) {
|
|
22
|
-
const transport = new HttpRpcTransport(endpoint, { ...BlockViewerRpcSchemas })
|
|
23
|
-
const viewer = new JsonRpcBlockViewer(transport)
|
|
24
|
-
logger?.log('Using BlockViewer RPC service at', endpoint)
|
|
25
|
-
return viewer
|
|
26
|
-
} else {
|
|
27
|
-
throw new Error('No BlockViewer endpoint configured')
|
|
28
|
-
}
|
|
29
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import type { Address, Promisable } from '@xylabs/sdk-js'
|
|
2
|
-
import {
|
|
3
|
-
asAddress, assertEx, isDefined, ZERO_ADDRESS,
|
|
4
|
-
} from '@xylabs/sdk-js'
|
|
5
|
-
import type { BaseAccountableServiceParams } from '@xyo-network/chain-services'
|
|
6
|
-
import { EvmChainService } from '@xyo-network/chain-services'
|
|
7
|
-
import type { Initializable } from '@xyo-network/xl1-protocol'
|
|
8
|
-
import type { Config } from '@xyo-network/xl1-protocol-sdk'
|
|
9
|
-
import type { ContractRunner } from 'ethers'
|
|
10
|
-
import { Wallet } from 'ethers/wallet'
|
|
11
|
-
|
|
12
|
-
import { canUseEvmProvider, initEvmProvider } from '../evm/index.ts'
|
|
13
|
-
|
|
14
|
-
let chainStakeServiceSingleton: Promisable<EvmChainService> | undefined
|
|
15
|
-
|
|
16
|
-
export const canUseEvmContractChainService = (config: Pick<Config, 'chain' | 'evm'>) => {
|
|
17
|
-
const { id } = config.chain
|
|
18
|
-
return isDefined(id) && id !== ZERO_ADDRESS && canUseEvmProvider({ config })
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export const initEvmContractChainService: Initializable<BaseAccountableServiceParams<Pick<Config, 'chain' | 'evm'>>, EvmChainService> = async ({
|
|
22
|
-
account, config, traceProvider, meterProvider, logger,
|
|
23
|
-
}) => {
|
|
24
|
-
if (chainStakeServiceSingleton) return chainStakeServiceSingleton
|
|
25
|
-
// Parse config
|
|
26
|
-
const emvStakingContractAddress = assertEx(config.chain.id, () => 'config.chain.id is required')
|
|
27
|
-
// Configure ContractRunner
|
|
28
|
-
const id: Address = assertEx(asAddress(emvStakingContractAddress), () => 'config.chain.id is not a valid address')
|
|
29
|
-
const provider = assertEx(await initEvmProvider({ config }))
|
|
30
|
-
const privateKey = assertEx(account.private?.hex, () => 'Account does not have a private key')
|
|
31
|
-
const runner: ContractRunner = new Wallet(privateKey, provider)
|
|
32
|
-
// Create service
|
|
33
|
-
chainStakeServiceSingleton = EvmChainService.create({
|
|
34
|
-
id, runner, traceProvider, meterProvider, logger,
|
|
35
|
-
})
|
|
36
|
-
const result = await chainStakeServiceSingleton
|
|
37
|
-
await result.start()
|
|
38
|
-
return result
|
|
39
|
-
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
assertEx, type CreatableName, type Promisable,
|
|
3
|
-
} from '@xylabs/sdk-js'
|
|
4
|
-
import { type BaseAccountableServiceParams, MemoryChainService } from '@xyo-network/chain-services'
|
|
5
|
-
import type { Initializable } from '@xyo-network/xl1-protocol'
|
|
6
|
-
import type { ChainService } from '@xyo-network/xl1-protocol-sdk'
|
|
7
|
-
import type { Config } from 'cosmiconfig'
|
|
8
|
-
|
|
9
|
-
import { canUseEvmContractChainService, initEvmContractChainService } from './evm.ts'
|
|
10
|
-
|
|
11
|
-
let chainStakeServiceSingleton: Promisable<ChainService> | undefined
|
|
12
|
-
|
|
13
|
-
export const initChainService: Initializable<BaseAccountableServiceParams<
|
|
14
|
-
Pick<Config, 'chain' | 'evm' | 'producer'>>,
|
|
15
|
-
ChainService> = ({
|
|
16
|
-
account, config, logger,
|
|
17
|
-
}) => {
|
|
18
|
-
logger?.log('ChainService: Initializing...')
|
|
19
|
-
const result = init({
|
|
20
|
-
config, name: 'ChainService' as CreatableName, account,
|
|
21
|
-
})
|
|
22
|
-
logger?.log('ChainService: Initialized')
|
|
23
|
-
return result
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export const initMemoryChainService: Initializable<BaseAccountableServiceParams<
|
|
27
|
-
Pick<Config, 'producer'>>, ChainService> = async ({ config }) => {
|
|
28
|
-
const result = await MemoryChainService.create({
|
|
29
|
-
config,
|
|
30
|
-
name: 'MemoryChainService' as CreatableName,
|
|
31
|
-
})
|
|
32
|
-
assertEx(await result.start(), () => 'Failed to start MemoryChainService')
|
|
33
|
-
return result
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const init: Initializable<BaseAccountableServiceParams<Pick<Config, 'chain' | 'evm' | 'producer'>>,
|
|
37
|
-
ChainService> = async (params): Promise<ChainService> => {
|
|
38
|
-
if (chainStakeServiceSingleton) return chainStakeServiceSingleton
|
|
39
|
-
const { config } = params
|
|
40
|
-
chainStakeServiceSingleton = canUseEvmContractChainService(config)
|
|
41
|
-
? await initEvmContractChainService({ ...params, name: 'ChainStakeService' as CreatableName })
|
|
42
|
-
: await initMemoryChainService(params)
|
|
43
|
-
// Create service
|
|
44
|
-
return chainStakeServiceSingleton
|
|
45
|
-
}
|