@xyo-network/xl1-cli-lib 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/node/index.mjs +255 -51
- package/dist/node/index.mjs.map +1 -1
- package/dist/node/orchestration/actor/implementation/BalanceActor.d.ts +1 -1
- package/dist/node/orchestration/actor/implementation/BalanceActor.d.ts.map +1 -1
- package/dist/node/orchestration/actor/implementation/ProducerActor.d.ts +1 -1
- package/dist/node/orchestration/actor/implementation/ProducerActor.d.ts.map +1 -1
- package/dist/node/orchestration/actor/implementation/ValidatorActor.d.ts +1 -1
- package/dist/node/orchestration/actor/implementation/ValidatorActor.d.ts.map +1 -1
- package/dist/node/orchestration/archivists/lib/localPersistentArchivist.d.ts +1 -1
- package/dist/node/orchestration/archivists/lib/localPersistentArchivist.d.ts.map +1 -1
- package/dist/node/orchestration/initServices.d.ts.map +1 -1
- package/dist/node/orchestration/services/implementation/head/createBootstrapHead.d.ts +4 -0
- package/dist/node/orchestration/services/implementation/head/createBootstrapHead.d.ts.map +1 -0
- package/dist/node/orchestration/services/implementation/head/createForkedHead/config/getBridgeDestinationDetails.d.ts +18 -0
- package/dist/node/orchestration/services/implementation/head/createForkedHead/config/getBridgeDestinationDetails.d.ts.map +1 -0
- package/dist/node/orchestration/services/implementation/head/createForkedHead/config/getBridgeSourceDetails.d.ts +14 -0
- package/dist/node/orchestration/services/implementation/head/createForkedHead/config/getBridgeSourceDetails.d.ts.map +1 -0
- package/dist/node/orchestration/services/implementation/head/createForkedHead/config/getForkDetails.d.ts +4 -0
- package/dist/node/orchestration/services/implementation/head/createForkedHead/config/getForkDetails.d.ts.map +1 -0
- package/dist/node/orchestration/services/implementation/head/createForkedHead/config/index.d.ts +4 -0
- package/dist/node/orchestration/services/implementation/head/createForkedHead/config/index.d.ts.map +1 -0
- package/dist/node/orchestration/services/implementation/head/createForkedHead/createForkedHead.d.ts +5 -0
- package/dist/node/orchestration/services/implementation/head/createForkedHead/createForkedHead.d.ts.map +1 -0
- package/dist/node/orchestration/services/implementation/head/createForkedHead/getBridgeDestinationObservation.d.ts +10 -0
- package/dist/node/orchestration/services/implementation/head/createForkedHead/getBridgeDestinationObservation.d.ts.map +1 -0
- package/dist/node/orchestration/services/implementation/head/createForkedHead/getBridgeIntent.d.ts +10 -0
- package/dist/node/orchestration/services/implementation/head/createForkedHead/getBridgeIntent.d.ts.map +1 -0
- package/dist/node/orchestration/services/implementation/head/createForkedHead/getBridgeSourceObservation.d.ts +10 -0
- package/dist/node/orchestration/services/implementation/head/createForkedHead/getBridgeSourceObservation.d.ts.map +1 -0
- package/dist/node/orchestration/services/implementation/head/createForkedHead/getFirstBlockForNewChain.d.ts +12 -0
- package/dist/node/orchestration/services/implementation/head/createForkedHead/getFirstBlockForNewChain.d.ts.map +1 -0
- package/dist/node/orchestration/services/implementation/head/createForkedHead/index.d.ts +2 -0
- package/dist/node/orchestration/services/implementation/head/createForkedHead/index.d.ts.map +1 -0
- package/dist/node/orchestration/services/implementation/head/getForkFromBlock.d.ts +12 -0
- package/dist/node/orchestration/services/implementation/head/getForkFromBlock.d.ts.map +1 -0
- package/dist/node/orchestration/services/implementation/{head.d.ts → head/head.d.ts} +2 -1
- package/dist/node/orchestration/services/implementation/head/head.d.ts.map +1 -0
- package/dist/node/orchestration/services/implementation/head/index.d.ts +2 -0
- package/dist/node/orchestration/services/implementation/head/index.d.ts.map +1 -0
- package/dist/node/orchestration/services/implementation/head/submitNewChain.d.ts +10 -0
- package/dist/node/orchestration/services/implementation/head/submitNewChain.d.ts.map +1 -0
- package/dist/node/orchestration/services/implementation/index.d.ts +1 -1
- package/dist/node/orchestration/services/implementation/index.d.ts.map +1 -1
- package/dist/node/xl1.mjs +253 -49
- package/dist/node/xl1.mjs.map +1 -1
- package/package.json +13 -13
- package/src/orchestration/actor/implementation/BalanceActor.ts +2 -2
- package/src/orchestration/actor/implementation/ChainHeadUpdateActor.ts +2 -2
- package/src/orchestration/actor/implementation/ProducerActor.ts +4 -4
- package/src/orchestration/actor/implementation/ValidatorActor.ts +4 -4
- package/src/orchestration/actor/model/Actor.ts +2 -2
- package/src/orchestration/archivists/ChainFinalized/local.ts +1 -1
- package/src/orchestration/archivists/StakeIntentState/local.ts +1 -1
- package/src/orchestration/archivists/lib/localPersistentArchivist.ts +8 -1
- package/src/orchestration/initServices.ts +11 -7
- package/src/orchestration/services/implementation/head/createBootstrapHead.ts +8 -0
- package/src/orchestration/services/implementation/head/createForkedHead/config/getBridgeDestinationDetails.ts +27 -0
- package/src/orchestration/services/implementation/head/createForkedHead/config/getBridgeSourceDetails.ts +18 -0
- package/src/orchestration/services/implementation/head/createForkedHead/config/getForkDetails.ts +10 -0
- package/src/orchestration/services/implementation/head/createForkedHead/config/index.ts +3 -0
- package/src/orchestration/services/implementation/head/createForkedHead/createForkedHead.ts +31 -0
- package/src/orchestration/services/implementation/head/createForkedHead/getBridgeDestinationObservation.ts +38 -0
- package/src/orchestration/services/implementation/head/createForkedHead/getBridgeIntent.ts +50 -0
- package/src/orchestration/services/implementation/head/createForkedHead/getBridgeSourceObservation.ts +43 -0
- package/src/orchestration/services/implementation/head/createForkedHead/getFirstBlockForNewChain.ts +42 -0
- package/src/orchestration/services/implementation/head/createForkedHead/index.ts +1 -0
- package/src/orchestration/services/implementation/head/getForkFromBlock.ts +42 -0
- package/src/orchestration/services/implementation/head/head.ts +52 -0
- package/src/orchestration/services/implementation/head/index.ts +1 -0
- package/src/orchestration/services/implementation/head/submitNewChain.ts +27 -0
- package/src/orchestration/services/implementation/index.ts +1 -1
- package/src/spec/BootstrapChain.spec.ts +2 -2
- package/dist/node/orchestration/services/implementation/head.d.ts.map +0 -1
- package/src/orchestration/services/implementation/head.ts +0 -44
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xyo-network/xl1-cli-lib",
|
|
3
|
-
"version": "1.14.
|
|
3
|
+
"version": "1.14.3",
|
|
4
4
|
"description": "XYO Layer One CLI Library",
|
|
5
5
|
"homepage": "https://xylabs.com",
|
|
6
6
|
"bugs": {
|
|
@@ -52,20 +52,20 @@
|
|
|
52
52
|
"@xylabs/promise": "~5.0.11",
|
|
53
53
|
"@xylabs/telemetry": "~5.0.11",
|
|
54
54
|
"@xylabs/typeof": "~5.0.11",
|
|
55
|
-
"@xyo-network/archivist-lmdb": "~5.1.
|
|
56
|
-
"@xyo-network/archivist-memory": "~5.1.
|
|
57
|
-
"@xyo-network/archivist-model": "~5.1.
|
|
58
|
-
"@xyo-network/chain-api": "~1.14.
|
|
59
|
-
"@xyo-network/chain-sdk": "~1.14.
|
|
60
|
-
"@xyo-network/payload-builder": "~5.1.
|
|
61
|
-
"@xyo-network/payload-model": "~5.1.
|
|
62
|
-
"@xyo-network/wallet": "~5.1.
|
|
63
|
-
"@xyo-network/wallet-model": "~5.1.
|
|
64
|
-
"@xyo-network/xl1-protocol": "~1.
|
|
65
|
-
"@xyo-network/xl1-protocol-sdk": "~1.14.
|
|
55
|
+
"@xyo-network/archivist-lmdb": "~5.1.2",
|
|
56
|
+
"@xyo-network/archivist-memory": "~5.1.2",
|
|
57
|
+
"@xyo-network/archivist-model": "~5.1.2",
|
|
58
|
+
"@xyo-network/chain-api": "~1.14.3",
|
|
59
|
+
"@xyo-network/chain-sdk": "~1.14.3",
|
|
60
|
+
"@xyo-network/payload-builder": "~5.1.2",
|
|
61
|
+
"@xyo-network/payload-model": "~5.1.2",
|
|
62
|
+
"@xyo-network/wallet": "~5.1.2",
|
|
63
|
+
"@xyo-network/wallet-model": "~5.1.2",
|
|
64
|
+
"@xyo-network/xl1-protocol": "~1.12.22",
|
|
65
|
+
"@xyo-network/xl1-protocol-sdk": "~1.14.3",
|
|
66
66
|
"async-mutex": "~0.5.0",
|
|
67
67
|
"cosmiconfig": "~9.0.0",
|
|
68
|
-
"dotenv": "~17.2.
|
|
68
|
+
"dotenv": "~17.2.2",
|
|
69
69
|
"ethers": "~6.15.0",
|
|
70
70
|
"lmdb": "~3.4.2",
|
|
71
71
|
"yargs": "~18.0.0",
|
|
@@ -8,7 +8,7 @@ import { Mutex } from 'async-mutex'
|
|
|
8
8
|
import { Actor } from '../model/index.ts'
|
|
9
9
|
|
|
10
10
|
export type BalanceActorParams = BaseParams<
|
|
11
|
-
Pick<ChainServiceCollectionV2, '
|
|
11
|
+
Pick<ChainServiceCollectionV2, 'balance' | 'chainIterator'>
|
|
12
12
|
& { config: Config }>
|
|
13
13
|
|
|
14
14
|
export class BalanceActor extends Actor<BalanceActorParams> {
|
|
@@ -19,7 +19,7 @@ export class BalanceActor extends Actor<BalanceActorParams> {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
protected get balanceService() {
|
|
22
|
-
return assertEx(this.params.
|
|
22
|
+
return assertEx(this.params.balance, () => 'balanceService not set')
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
protected get chainIterator() {
|
|
@@ -57,9 +57,9 @@ export class ChainHeadUpdateActor extends Actor<ChainHeadUpdateActorParams> {
|
|
|
57
57
|
const candidateBlockNumberDisplay = `0x${toHex(candidateBlockNumber)}`
|
|
58
58
|
const currentBlockNumber = currentHead?.block ?? -1
|
|
59
59
|
if (candidateBlockNumber > currentBlockNumber) {
|
|
60
|
-
this.logger?.log('Found more recent head:', candidateBlockNumberDisplay)
|
|
60
|
+
this.logger?.log('Found more recent head:', candidateBlockNumber, candidateBlockNumberDisplay)
|
|
61
61
|
await this.chainIterator.updateHead(candidateBlock)
|
|
62
|
-
this.logger?.log('Updated head:', candidateBlockNumberDisplay)
|
|
62
|
+
this.logger?.log('Updated head:', candidateBlockNumber, candidateBlockNumberDisplay)
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
}
|
|
@@ -18,13 +18,13 @@ import { Actor } from '../model/index.ts'
|
|
|
18
18
|
export type ProducerActorParams = BaseParams<
|
|
19
19
|
Pick<ChainServiceCollectionV2,
|
|
20
20
|
'account'
|
|
21
|
-
| '
|
|
21
|
+
| 'balance'
|
|
22
22
|
| 'chainIterator'
|
|
23
23
|
| 'chainStakeViewer'
|
|
24
24
|
| 'chainSubmissionsArchivistWrite'
|
|
25
25
|
| 'pendingBundledTransactionsArchivistWrite'
|
|
26
26
|
| 'producer'
|
|
27
|
-
| '
|
|
27
|
+
| 'stakeIntent'
|
|
28
28
|
> & {
|
|
29
29
|
config: Config
|
|
30
30
|
}>
|
|
@@ -45,7 +45,7 @@ export class ProducerActor extends Actor<ProducerActorParams> {
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
protected get balanceService() {
|
|
48
|
-
return assertEx(this.params.
|
|
48
|
+
return assertEx(this.params.balance, () => 'balanceService not set')
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
protected get chainIterator() {
|
|
@@ -69,7 +69,7 @@ export class ProducerActor extends Actor<ProducerActorParams> {
|
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
protected get stakeIntentService() {
|
|
72
|
-
return assertEx(this.params.
|
|
72
|
+
return assertEx(this.params.stakeIntent, () => 'stakeIntentService not set')
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
static create(params: ProducerActorParams): Promisable<ProducerActor> {
|
|
@@ -13,12 +13,12 @@ import { Actor } from '../model/index.ts'
|
|
|
13
13
|
export type ValidatorActorParams = BaseParams<
|
|
14
14
|
Pick<ChainServiceCollectionV2,
|
|
15
15
|
'account'
|
|
16
|
-
| '
|
|
16
|
+
| 'balance'
|
|
17
17
|
| 'chainIterator'
|
|
18
18
|
| 'chainStakeViewer'
|
|
19
19
|
| 'chainSubmissionsArchivistWrite'
|
|
20
20
|
| 'pendingBundledTransactionsArchivistWrite'
|
|
21
|
-
| '
|
|
21
|
+
| 'stakeIntent'
|
|
22
22
|
> & {
|
|
23
23
|
config: Config
|
|
24
24
|
}>
|
|
@@ -36,7 +36,7 @@ export class ValidatorActor extends Actor<ValidatorActorParams> {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
protected get balanceService() {
|
|
39
|
-
return assertEx(this.params.
|
|
39
|
+
return assertEx(this.params.balance, () => 'balanceService not set')
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
protected get chainIterator() {
|
|
@@ -56,7 +56,7 @@ export class ValidatorActor extends Actor<ValidatorActorParams> {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
protected get stakeIntentService() {
|
|
59
|
-
return assertEx(this.params.
|
|
59
|
+
return assertEx(this.params.stakeIntent, () => 'stakeIntentService not set')
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
// protected get validator() {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { TracerProvider } from '@opentelemetry/api'
|
|
2
2
|
import { Base, type BaseParams } from '@xylabs/base'
|
|
3
3
|
import { IdLogger } from '@xylabs/logger'
|
|
4
|
-
import { span,
|
|
4
|
+
import { span, spanRootAsync } from '@xylabs/telemetry'
|
|
5
5
|
import type { Config } from '@xyo-network/xl1-protocol-sdk'
|
|
6
6
|
|
|
7
7
|
export interface IActor {
|
|
@@ -87,7 +87,7 @@ export class Actor<TParams extends ActorParams = ActorParams> extends Base<TPara
|
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
async spanAsync<T>(name: string, fn: () => Promise<T>): Promise<T> {
|
|
90
|
-
return await
|
|
90
|
+
return await spanRootAsync(`${this.name}:${name}`, fn, this.tracer)
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
/**
|
|
@@ -12,7 +12,7 @@ export const initLocalChainFinalizedArchivist: Initializable<{ config: Config },
|
|
|
12
12
|
return await mutex.runExclusive(async () => {
|
|
13
13
|
if (singleton) return singleton
|
|
14
14
|
const { root } = config.storage
|
|
15
|
-
singleton = await getLocalPersistentArchivist('chain', 'finalized', root)
|
|
15
|
+
singleton = await getLocalPersistentArchivist('local-finalized-chain', 'chain', 'finalized', root)
|
|
16
16
|
return singleton
|
|
17
17
|
})
|
|
18
18
|
}
|
|
@@ -13,7 +13,7 @@ export const initLocalStakeIntentStateArchivist: Initializable<{ config: Config
|
|
|
13
13
|
return await mutex.runExclusive(async () => {
|
|
14
14
|
if (singleton) return singleton
|
|
15
15
|
const { root } = config.storage
|
|
16
|
-
singleton = await getLocalPersistentArchivist('stakeIntent', 'state', root)
|
|
16
|
+
singleton = await getLocalPersistentArchivist('local-stake-intent-state', 'stakeIntent', 'state', root)
|
|
17
17
|
return assertEx(singleton, () => new Error('Failed to initialize stake intent state archivist'))
|
|
18
18
|
})
|
|
19
19
|
}
|
|
@@ -17,13 +17,20 @@ const DEFAULT_STORAGE_ROOT = Path.join(process.cwd(), '.store')
|
|
|
17
17
|
* @param kind The kind of the archivist
|
|
18
18
|
* @returns an archivist instance
|
|
19
19
|
*/
|
|
20
|
-
export const getLocalPersistentArchivist = (
|
|
20
|
+
export const getLocalPersistentArchivist = (
|
|
21
|
+
name: string,
|
|
22
|
+
dbName: string,
|
|
23
|
+
storeName: string,
|
|
24
|
+
storageRoot?: string,
|
|
25
|
+
kind: StoreKind = 'lmdb',
|
|
26
|
+
): Promise<ArchivistInstance> => {
|
|
21
27
|
switch (kind) {
|
|
22
28
|
case 'lmdb': {
|
|
23
29
|
const root = storageRoot ?? DEFAULT_STORAGE_ROOT
|
|
24
30
|
return LmdbArchivist.create({
|
|
25
31
|
account: 'random',
|
|
26
32
|
config: {
|
|
33
|
+
name,
|
|
27
34
|
clearStoreOnStart: false,
|
|
28
35
|
dbName,
|
|
29
36
|
location: getStoreDirectory(dbName, root, 'lmdb'),
|
|
@@ -5,7 +5,7 @@ import type { Logger } from '@xylabs/logger'
|
|
|
5
5
|
import { isDefined } from '@xylabs/typeof'
|
|
6
6
|
import type { BaseBlockProducerServiceParams, XyoValidatorParams } from '@xyo-network/chain-sdk'
|
|
7
7
|
import {
|
|
8
|
-
balanceSummaryRepositoryFromMap, initTelemetry, startupSpanAsync, validateHydratedBlockState,
|
|
8
|
+
balanceSummaryRepositoryFromMap, BaseTimeSyncService, initTelemetry, startupSpanAsync, validateHydratedBlockState,
|
|
9
9
|
} from '@xyo-network/chain-sdk'
|
|
10
10
|
import type { ChainServiceCollectionV2, Config } from '@xyo-network/xl1-protocol-sdk'
|
|
11
11
|
|
|
@@ -119,7 +119,7 @@ export const initServices = async (context: InitServicesContext): Promise<ChainS
|
|
|
119
119
|
const chainStakeViewer = chainService
|
|
120
120
|
const chainStaker = chainService
|
|
121
121
|
const head = await startupSpanAsync('initHead', () => initHead({
|
|
122
|
-
...initParams, account, chainArchivist, chainSubmissionsArchivistWrite,
|
|
122
|
+
...initParams, account, chainArchivist, chainSubmissionsArchivistWrite, chainService,
|
|
123
123
|
}))
|
|
124
124
|
const [
|
|
125
125
|
pendingTransactionsService,
|
|
@@ -199,6 +199,9 @@ export const initServices = async (context: InitServicesContext): Promise<ChainS
|
|
|
199
199
|
validateHydratedBlockState,
|
|
200
200
|
...initParams,
|
|
201
201
|
}
|
|
202
|
+
|
|
203
|
+
const time = await BaseTimeSyncService.create({ chainArchivist, chainIterator })
|
|
204
|
+
|
|
202
205
|
const rewardAddress = isDefined(config.producer.rewardAddress)
|
|
203
206
|
? assertEx(asAddress(config.producer.rewardAddress), () => 'Invalid block reward address provided')
|
|
204
207
|
: account.address
|
|
@@ -211,25 +214,26 @@ export const initServices = async (context: InitServicesContext): Promise<ChainS
|
|
|
211
214
|
pendingTransactionsService,
|
|
212
215
|
rejectedTransactionsArchivist,
|
|
213
216
|
rewardAddress,
|
|
217
|
+
time,
|
|
214
218
|
...initParams,
|
|
215
219
|
}
|
|
216
220
|
const producer = await startupSpanAsync('Producer', () => initBlockProducer(producerParams))
|
|
217
221
|
// TODO: Add to base service collection
|
|
218
222
|
const result: ChainServiceCollectionV2 = {
|
|
219
223
|
account,
|
|
220
|
-
balanceService,
|
|
224
|
+
balance: balanceService,
|
|
221
225
|
chainArchivist,
|
|
222
226
|
chainContractViewer,
|
|
223
227
|
chainIterator,
|
|
224
228
|
chainStaker,
|
|
225
229
|
chainStakeViewer,
|
|
226
230
|
chainSubmissionsArchivistWrite,
|
|
227
|
-
electionService,
|
|
231
|
+
election: electionService,
|
|
228
232
|
pendingBundledTransactionsArchivistWrite,
|
|
229
|
-
pendingTransactionsService,
|
|
233
|
+
pendingTransactions: pendingTransactionsService,
|
|
230
234
|
producer,
|
|
231
|
-
rewardService,
|
|
232
|
-
stakeIntentService,
|
|
235
|
+
reward: rewardService,
|
|
236
|
+
stakeIntent: stakeIntentService,
|
|
233
237
|
}
|
|
234
238
|
|
|
235
239
|
logger?.log('All services created. Starting...')
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ZERO_ADDRESS } from '@xylabs/hex'
|
|
2
|
+
import { createGenesisBlock } from '@xyo-network/chain-sdk'
|
|
3
|
+
import type { WalletInstance } from '@xyo-network/wallet-model'
|
|
4
|
+
import type { HydratedBlock } from '@xyo-network/xl1-protocol'
|
|
5
|
+
|
|
6
|
+
export const createBootstrapHead = async (account: WalletInstance): Promise<HydratedBlock> => {
|
|
7
|
+
return await createGenesisBlock(account, ZERO_ADDRESS, 10_000_000n, account.address)
|
|
8
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { toHex } from '@xylabs/hex'
|
|
2
|
+
import type { BridgeDetailsDestinationFields } from '@xyo-network/xl1-protocol'
|
|
3
|
+
|
|
4
|
+
import { getForkBlockRewardHex } from './getForkDetails.ts'
|
|
5
|
+
|
|
6
|
+
// const bridgeableTokenContract = toHex('0x4865Cb10d55cfB0E60DD2B4F9b888f6a49B76733')
|
|
7
|
+
// const bridgeDestAddress = toHex('0xe53218d47913b5f9E58bb74F0a0eD790bbF21972')
|
|
8
|
+
// const destConfirmation = toHex('0x4fa05d7e799f36f1d45c441a4866eb4570a00a753a39377f404a8d113c01a657') // Eth TX for mint
|
|
9
|
+
const ethChainId = toHex('0x1')
|
|
10
|
+
const bridgeableTokenContract = toHex('0x7789e11BB83b398A8Cca8E8D582B33F91499D6f5')
|
|
11
|
+
const bridgeDestAddress = toHex('0xe53218d47913b5f9E58bb74F0a0eD790bbF21972')
|
|
12
|
+
const destConfirmation = toHex('0x772ee028f9ad291ec692912c1a33ecd4409e71383fe06f6ebf39f7cdbb779069') // Eth TX for mint
|
|
13
|
+
|
|
14
|
+
export const getBridgeDestChainId = () => ethChainId
|
|
15
|
+
export const getBridgeDestToken = () => bridgeableTokenContract
|
|
16
|
+
export const getBridgeDestAddress = () => bridgeDestAddress
|
|
17
|
+
export const getBridgeDestAmount = () => getForkBlockRewardHex()
|
|
18
|
+
export const getBridgeDestConfirmation = () => destConfirmation
|
|
19
|
+
|
|
20
|
+
export const getBridgeDestinationDetails = (): BridgeDetailsDestinationFields => {
|
|
21
|
+
return {
|
|
22
|
+
dest: getBridgeDestChainId(),
|
|
23
|
+
destToken: getBridgeDestToken(),
|
|
24
|
+
destAddress: getBridgeDestAddress(),
|
|
25
|
+
destAmount: getBridgeDestAmount(),
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { AccountInstance } from '@xyo-network/account-model'
|
|
2
|
+
import type { BridgeDetailsSourceFields, ChainService } from '@xyo-network/xl1-protocol'
|
|
3
|
+
|
|
4
|
+
import { getForkBlockRewardHex } from './getForkDetails.ts'
|
|
5
|
+
|
|
6
|
+
export const getBridgeSrcChainId = (chainService: ChainService) => chainService.chainId
|
|
7
|
+
export const getBridgeSrcAddress = (account: AccountInstance) => account.address
|
|
8
|
+
export const getBridgeSrcToken = (chainService: ChainService) => chainService.chainId
|
|
9
|
+
export const getBridgeSrcAmount = () => getForkBlockRewardHex()
|
|
10
|
+
|
|
11
|
+
export const getBridgeSourceDetails = (account: AccountInstance, chainService: ChainService): BridgeDetailsSourceFields => {
|
|
12
|
+
return {
|
|
13
|
+
src: getBridgeSrcChainId(chainService),
|
|
14
|
+
srcAddress: getBridgeSrcAddress(account),
|
|
15
|
+
srcToken: getBridgeSrcToken(chainService),
|
|
16
|
+
srcAmount: getBridgeSrcAmount(),
|
|
17
|
+
}
|
|
18
|
+
}
|
package/src/orchestration/services/implementation/head/createForkedHead/config/getForkDetails.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type Hex, toHex } from '@xylabs/hex'
|
|
2
|
+
import { AttoXL1ConvertFactor } from '@xyo-network/xl1-protocol'
|
|
3
|
+
|
|
4
|
+
export const getForkBlockReward = (): bigint => {
|
|
5
|
+
return 18_000_000_000n * AttoXL1ConvertFactor.xl1 // 18b XL1 in AttoXL1
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const getForkBlockRewardHex = (): Hex => {
|
|
9
|
+
return toHex(getForkBlockReward())
|
|
10
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { WithHashStorageMeta } from '@xyo-network/payload-model'
|
|
2
|
+
import type { WalletInstance } from '@xyo-network/wallet-model'
|
|
3
|
+
import type {
|
|
4
|
+
BlockBoundWitness, ChainService, HydratedBlock,
|
|
5
|
+
} from '@xyo-network/xl1-protocol'
|
|
6
|
+
|
|
7
|
+
import { getBridgeDestinationObservation } from './getBridgeDestinationObservation.ts'
|
|
8
|
+
import { getBridgeIntent } from './getBridgeIntent.ts'
|
|
9
|
+
import { getBridgeSourceObservation } from './getBridgeSourceObservation.ts'
|
|
10
|
+
import { getFirstBlockForNewChain } from './getFirstBlockForNewChain.ts'
|
|
11
|
+
|
|
12
|
+
export const createForkedHead = async (
|
|
13
|
+
forkFromBlock: WithHashStorageMeta<BlockBoundWitness>,
|
|
14
|
+
account: WalletInstance,
|
|
15
|
+
chainService: ChainService,
|
|
16
|
+
): Promise<HydratedBlock[]> => {
|
|
17
|
+
const chain: HydratedBlock[] = []
|
|
18
|
+
// Build the first block for the new chain
|
|
19
|
+
const firstBlockForNewChain = await getFirstBlockForNewChain(forkFromBlock, account, chainService)
|
|
20
|
+
chain.push(firstBlockForNewChain)
|
|
21
|
+
// Build the bridge intent
|
|
22
|
+
const bridgeIntent = await getBridgeIntent(firstBlockForNewChain, account, chainService)
|
|
23
|
+
chain.push(bridgeIntent)
|
|
24
|
+
// Build the bridge source observation
|
|
25
|
+
const bridgeSourceObservation = await getBridgeSourceObservation(bridgeIntent, account, chainService)
|
|
26
|
+
chain.push(bridgeSourceObservation)
|
|
27
|
+
// Build the bridge destination observation
|
|
28
|
+
const bridgeDestinationObservation = await getBridgeDestinationObservation(bridgeSourceObservation, account, chainService)
|
|
29
|
+
chain.push(bridgeDestinationObservation)
|
|
30
|
+
return chain
|
|
31
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { BridgeDestinationObservationSchema, buildNextBlock } from '@xyo-network/chain-sdk'
|
|
2
|
+
import { PayloadBuilder } from '@xyo-network/payload-builder'
|
|
3
|
+
import type { WalletInstance } from '@xyo-network/wallet-model'
|
|
4
|
+
import type {
|
|
5
|
+
BridgeDestinationObservation, BridgeDestinationObservationFields, ChainService, HydratedBlock,
|
|
6
|
+
} from '@xyo-network/xl1-protocol'
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
getBridgeDestConfirmation, getBridgeDestinationDetails, getBridgeSourceDetails,
|
|
10
|
+
} from './config/index.ts'
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Get the bridge destination observation for a given block.
|
|
14
|
+
* @param previousBlock The previous block to base the observation on.
|
|
15
|
+
* @param account The wallet account to use for the observation.
|
|
16
|
+
* @param chainService The chain service to use for the observation.
|
|
17
|
+
*/
|
|
18
|
+
export const getBridgeDestinationObservation = async (
|
|
19
|
+
previousBlock: HydratedBlock,
|
|
20
|
+
account: WalletInstance,
|
|
21
|
+
chainService: ChainService,
|
|
22
|
+
): Promise<HydratedBlock> => {
|
|
23
|
+
const bridgeDestinationObservationFields: BridgeDestinationObservationFields = {
|
|
24
|
+
...getBridgeSourceDetails(account, chainService),
|
|
25
|
+
...getBridgeDestinationDetails(),
|
|
26
|
+
destConfirmation: getBridgeDestConfirmation(),
|
|
27
|
+
}
|
|
28
|
+
const bridgeDestinationObservation = new PayloadBuilder<BridgeDestinationObservation>({ schema: BridgeDestinationObservationSchema })
|
|
29
|
+
.fields(bridgeDestinationObservationFields)
|
|
30
|
+
.build()
|
|
31
|
+
|
|
32
|
+
return await buildNextBlock(
|
|
33
|
+
previousBlock[0],
|
|
34
|
+
[],
|
|
35
|
+
[bridgeDestinationObservation],
|
|
36
|
+
[account],
|
|
37
|
+
)
|
|
38
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BridgeIntentSchema, buildNextBlock, createTransferPayload, XYO_BRIDGE_ADDRESS,
|
|
3
|
+
} from '@xyo-network/chain-sdk'
|
|
4
|
+
import { PayloadBuilder } from '@xyo-network/payload-builder'
|
|
5
|
+
import type { WalletInstance } from '@xyo-network/wallet-model'
|
|
6
|
+
import type {
|
|
7
|
+
BridgeIntent, BridgeIntentFields, ChainService, HydratedBlock,
|
|
8
|
+
} from '@xyo-network/xl1-protocol'
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
getBridgeDestinationDetails, getBridgeSourceDetails, getForkBlockReward,
|
|
12
|
+
} from './config/index.ts'
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Get the bridge intent for a given block.
|
|
16
|
+
* @param previousBlock The previous block to base the intent on.
|
|
17
|
+
* @param account The wallet account to use for the intent.
|
|
18
|
+
* @param chainService The chain service to use for the intent.
|
|
19
|
+
*/
|
|
20
|
+
export const getBridgeIntent = async (
|
|
21
|
+
previousBlock: HydratedBlock,
|
|
22
|
+
account: WalletInstance,
|
|
23
|
+
chainService: ChainService,
|
|
24
|
+
): Promise<HydratedBlock> => {
|
|
25
|
+
// Create transfer to bridge address
|
|
26
|
+
const transferPayload = createTransferPayload(
|
|
27
|
+
account.address,
|
|
28
|
+
{ [XYO_BRIDGE_ADDRESS]: getForkBlockReward() },
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
// Use timestamp as nonce
|
|
32
|
+
const nonce = `${Date.now()}`
|
|
33
|
+
|
|
34
|
+
// Create Bridge Intent
|
|
35
|
+
const bridgeIntentFields: BridgeIntentFields = {
|
|
36
|
+
...getBridgeSourceDetails(account, chainService),
|
|
37
|
+
...getBridgeDestinationDetails(),
|
|
38
|
+
nonce,
|
|
39
|
+
}
|
|
40
|
+
const bridgeIntent = new PayloadBuilder<BridgeIntent>({ schema: BridgeIntentSchema })
|
|
41
|
+
.fields(bridgeIntentFields)
|
|
42
|
+
.build()
|
|
43
|
+
|
|
44
|
+
return await buildNextBlock(
|
|
45
|
+
previousBlock[0],
|
|
46
|
+
[],
|
|
47
|
+
[bridgeIntent, transferPayload],
|
|
48
|
+
[account],
|
|
49
|
+
)
|
|
50
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { BridgeSourceObservationSchema, buildNextBlock } from '@xyo-network/chain-sdk'
|
|
2
|
+
import { PayloadBuilder } from '@xyo-network/payload-builder'
|
|
3
|
+
import type { WalletInstance } from '@xyo-network/wallet-model'
|
|
4
|
+
import type {
|
|
5
|
+
BridgeSourceObservation, BridgeSourceObservationFields, ChainService, HydratedBlock,
|
|
6
|
+
} from '@xyo-network/xl1-protocol'
|
|
7
|
+
|
|
8
|
+
import { getBridgeDestinationDetails, getBridgeSourceDetails } from './config/index.ts'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Get the bridge source observation for a given block.
|
|
12
|
+
* @param previousBlock The previous block to base the observation on.
|
|
13
|
+
* @param account The wallet account to use for the observation.
|
|
14
|
+
* @param chainService The chain service to use for the observation.
|
|
15
|
+
*/
|
|
16
|
+
export const getBridgeSourceObservation = async (
|
|
17
|
+
previousBlock: HydratedBlock,
|
|
18
|
+
account: WalletInstance,
|
|
19
|
+
chainService: ChainService,
|
|
20
|
+
): Promise<HydratedBlock> => {
|
|
21
|
+
// TODO: Find actual transfer TX from previous block/source intent?
|
|
22
|
+
// This hash should contain both the source intent and the transfer to the bridge address
|
|
23
|
+
// As the block is itself both a block and a transaction, we can use its hash for now
|
|
24
|
+
const srcTxHash = previousBlock[0]._hash
|
|
25
|
+
|
|
26
|
+
const bridgeSourceObservationFields: BridgeSourceObservationFields = {
|
|
27
|
+
...getBridgeSourceDetails(account, chainService),
|
|
28
|
+
...getBridgeDestinationDetails(),
|
|
29
|
+
// Observation
|
|
30
|
+
srcConfirmation: srcTxHash,
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const bridgeSourceObservation = new PayloadBuilder<BridgeSourceObservation>({ schema: BridgeSourceObservationSchema })
|
|
34
|
+
.fields(bridgeSourceObservationFields)
|
|
35
|
+
.build()
|
|
36
|
+
|
|
37
|
+
return await buildNextBlock(
|
|
38
|
+
previousBlock[0],
|
|
39
|
+
[],
|
|
40
|
+
[bridgeSourceObservation],
|
|
41
|
+
[account],
|
|
42
|
+
)
|
|
43
|
+
}
|
package/src/orchestration/services/implementation/head/createForkedHead/getFirstBlockForNewChain.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { BuildNextBlockOptions } from '@xyo-network/chain-sdk'
|
|
2
|
+
import { buildBlock } from '@xyo-network/chain-sdk'
|
|
3
|
+
import type { WithHashStorageMeta } from '@xyo-network/payload-model'
|
|
4
|
+
import type { WalletInstance } from '@xyo-network/wallet-model'
|
|
5
|
+
import type {
|
|
6
|
+
BlockBoundWitness, ChainService, HydratedBlock,
|
|
7
|
+
} from '@xyo-network/xl1-protocol'
|
|
8
|
+
|
|
9
|
+
import { getForkBlockReward } from './config/index.ts'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Get the first block for the new forked chain.
|
|
13
|
+
* @param forkBlock The block to fork from
|
|
14
|
+
* @param account The wallet account to sign the block
|
|
15
|
+
* @param chainService The chain service instance
|
|
16
|
+
* @returns The first block for the new forked chain
|
|
17
|
+
*/
|
|
18
|
+
export const getFirstBlockForNewChain = async (
|
|
19
|
+
forkBlock: WithHashStorageMeta<BlockBoundWitness>,
|
|
20
|
+
account: WalletInstance,
|
|
21
|
+
chainService: ChainService,
|
|
22
|
+
): Promise<HydratedBlock> => {
|
|
23
|
+
const {
|
|
24
|
+
_hash: previousBlockHash, block: previousBlockNumber, step_hashes: previousStepHashes, protocol,
|
|
25
|
+
} = forkBlock
|
|
26
|
+
const chainId = chainService.chainId
|
|
27
|
+
const forkBlockReward = getForkBlockReward()
|
|
28
|
+
const options: BuildNextBlockOptions = {
|
|
29
|
+
blockPayloads: [],
|
|
30
|
+
chainId,
|
|
31
|
+
previousBlockHash,
|
|
32
|
+
previousBlockNumber,
|
|
33
|
+
previousStepHashes,
|
|
34
|
+
signers: [account],
|
|
35
|
+
txs: [],
|
|
36
|
+
protocol,
|
|
37
|
+
reward: forkBlockReward,
|
|
38
|
+
rewardAddress: account.address,
|
|
39
|
+
}
|
|
40
|
+
// NOTE: Can not use buildNextBlock because we need to control the chain id change here
|
|
41
|
+
return await buildBlock(options)
|
|
42
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './createForkedHead.ts'
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { Address, Hash } from '@xylabs/hex'
|
|
2
|
+
import { asHash, hexFromBigInt } from '@xylabs/hex'
|
|
3
|
+
import { isDefined } from '@xylabs/typeof'
|
|
4
|
+
import type { ArchivistInstance } from '@xyo-network/archivist-model'
|
|
5
|
+
import { isBlockBoundWitnessWithHashStorageMeta } from '@xyo-network/chain-sdk'
|
|
6
|
+
import type { WithHashStorageMeta, WithStorageMeta } from '@xyo-network/payload-model'
|
|
7
|
+
import type { BlockBoundWitness, ChainService } from '@xyo-network/xl1-protocol'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Determine if the chain should fork based on the current head and chain configuration.
|
|
11
|
+
* @param head The current head block
|
|
12
|
+
* @param chainService The chain service instance
|
|
13
|
+
* @param chainArchivist The chain archivist instance
|
|
14
|
+
* @returns The block to fork from if the chain should fork, undefined otherwise
|
|
15
|
+
*/
|
|
16
|
+
export const getForkFromBlock = async (
|
|
17
|
+
head: WithStorageMeta<BlockBoundWitness>,
|
|
18
|
+
chainService: ChainService,
|
|
19
|
+
chainArchivist: ArchivistInstance,
|
|
20
|
+
): Promise<WithHashStorageMeta<BlockBoundWitness> | undefined> => {
|
|
21
|
+
// If the head's chain doesn't match our chainId, we may need to fork
|
|
22
|
+
if (head.chain !== chainService.chainId) {
|
|
23
|
+
// Get the forked at hash from the chain service
|
|
24
|
+
const forkedAtBigInt = await chainService.forkedAtHash()
|
|
25
|
+
const forkedAtHex = hexFromBigInt(forkedAtBigInt) // Validate it's a proper hex string
|
|
26
|
+
const forkedAtHash: Hash | undefined = asHash(forkedAtHex)
|
|
27
|
+
if (isDefined(forkedAtHash)) {
|
|
28
|
+
// If we have a forkedAtHash, we need to check if the correct block exists
|
|
29
|
+
const [forkedAtBlock] = await chainArchivist.get([forkedAtHash])
|
|
30
|
+
const forkedChainId: Address = await chainService.forkedChainId()
|
|
31
|
+
const forkedAtBlockNumber: number = Number(await chainService.forkedAtBlockNumber())
|
|
32
|
+
// If we found the block hash we should fork at, check if it's a valid BlockBoundWitness
|
|
33
|
+
if (isBlockBoundWitnessWithHashStorageMeta(forkedAtBlock)
|
|
34
|
+
// And it is on the correct forked from chain
|
|
35
|
+
&& forkedAtBlock.chain === forkedChainId
|
|
36
|
+
// And it is the correct forked at block number
|
|
37
|
+
&& forkedAtBlock.block === forkedAtBlockNumber) {
|
|
38
|
+
return forkedAtBlock
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { assertEx } from '@xylabs/assert'
|
|
2
|
+
import type { Promisable } from '@xylabs/promise'
|
|
3
|
+
import { isDefined } from '@xylabs/typeof'
|
|
4
|
+
import type { ArchivistInstance } from '@xyo-network/archivist-model'
|
|
5
|
+
import { findMostRecentBlock } from '@xyo-network/chain-sdk'
|
|
6
|
+
import type { WithStorageMeta } from '@xyo-network/payload-model'
|
|
7
|
+
import type { WalletInstance } from '@xyo-network/wallet-model'
|
|
8
|
+
import type {
|
|
9
|
+
BlockBoundWitness, ChainService, Initializable,
|
|
10
|
+
} from '@xyo-network/xl1-protocol'
|
|
11
|
+
|
|
12
|
+
import { createBootstrapHead } from './createBootstrapHead.ts'
|
|
13
|
+
import { createForkedHead } from './createForkedHead/index.ts'
|
|
14
|
+
import { getForkFromBlock } from './getForkFromBlock.ts'
|
|
15
|
+
import { submitNewChain } from './submitNewChain.ts'
|
|
16
|
+
|
|
17
|
+
let headSingleton: Promisable<WithStorageMeta<BlockBoundWitness>> | undefined
|
|
18
|
+
|
|
19
|
+
export const initHead: Initializable<{
|
|
20
|
+
account: WalletInstance
|
|
21
|
+
chainArchivist: ArchivistInstance
|
|
22
|
+
chainService: ChainService
|
|
23
|
+
chainSubmissionsArchivistWrite: ArchivistInstance
|
|
24
|
+
}, WithStorageMeta<BlockBoundWitness>>
|
|
25
|
+
= async (params): Promise<WithStorageMeta<BlockBoundWitness>> => {
|
|
26
|
+
const {
|
|
27
|
+
account, chainArchivist, chainSubmissionsArchivistWrite, chainService,
|
|
28
|
+
} = params
|
|
29
|
+
if (headSingleton) return headSingleton
|
|
30
|
+
let head = await findMostRecentBlock(chainArchivist)
|
|
31
|
+
|
|
32
|
+
// If there is a head
|
|
33
|
+
if (head) {
|
|
34
|
+
// If there is a head but check if it matches our chainId or we should fork from it
|
|
35
|
+
const forkFromBlock = await getForkFromBlock(head, chainService, chainArchivist)
|
|
36
|
+
// If we should fork form a block in the current chain
|
|
37
|
+
if (isDefined(forkFromBlock)) {
|
|
38
|
+
// Create a new chain from the fork from block
|
|
39
|
+
const chain = await createForkedHead(forkFromBlock, account, chainService)
|
|
40
|
+
await submitNewChain(chain, chainArchivist, chainSubmissionsArchivistWrite)
|
|
41
|
+
const newBlock = assertEx(chain.at(-1), () => new Error('Failed to get new head after forking'))
|
|
42
|
+
head = newBlock[0]
|
|
43
|
+
}
|
|
44
|
+
} else {
|
|
45
|
+
// If there is no head, create one
|
|
46
|
+
const genesisBlock = await createBootstrapHead(account)
|
|
47
|
+
await submitNewChain([genesisBlock], chainArchivist, chainSubmissionsArchivistWrite)
|
|
48
|
+
head = genesisBlock[0]
|
|
49
|
+
}
|
|
50
|
+
headSingleton = head
|
|
51
|
+
return headSingleton
|
|
52
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './head.ts'
|