@xyo-network/chain-orchestration 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.
Files changed (34) hide show
  1. package/dist/neutral/actor/Actor.d.ts +45 -0
  2. package/dist/neutral/actor/Actor.d.ts.map +1 -0
  3. package/dist/neutral/actor/index.d.ts +2 -0
  4. package/dist/neutral/actor/index.d.ts.map +1 -0
  5. package/dist/neutral/index.d.ts +2 -0
  6. package/dist/neutral/index.d.ts.map +1 -1
  7. package/dist/neutral/index.mjs +293 -16
  8. package/dist/neutral/index.mjs.map +1 -1
  9. package/dist/neutral/init/index.d.ts +2 -0
  10. package/dist/neutral/init/index.d.ts.map +1 -1
  11. package/dist/neutral/init/initChainStakeViewer.d.ts +1 -1
  12. package/dist/neutral/init/initChainStakeViewer.d.ts.map +1 -1
  13. package/dist/neutral/init/initPendingBlockArchivist.d.ts +4 -0
  14. package/dist/neutral/init/initPendingBlockArchivist.d.ts.map +1 -0
  15. package/dist/neutral/init/initPendingTransactionArchivist.d.ts +4 -0
  16. package/dist/neutral/init/initPendingTransactionArchivist.d.ts.map +1 -0
  17. package/dist/neutral/orchestrator/Orchestrator.d.ts +27 -0
  18. package/dist/neutral/orchestrator/Orchestrator.d.ts.map +1 -0
  19. package/dist/neutral/orchestrator/index.d.ts +2 -0
  20. package/dist/neutral/orchestrator/index.d.ts.map +1 -0
  21. package/package.json +35 -34
  22. package/src/actor/Actor.ts +163 -0
  23. package/src/actor/index.ts +1 -0
  24. package/src/index.ts +2 -0
  25. package/src/init/index.ts +2 -0
  26. package/src/init/initChainStakeViewer.ts +1 -1
  27. package/src/init/initPendingBlockArchivist.ts +31 -0
  28. package/src/init/initPendingTransactionArchivist.ts +31 -0
  29. package/src/manifest/public/WithMempool/Chain.json +1 -1
  30. package/src/manifest/public/WithMempool/Pending.json +16 -2
  31. package/src/manifest/public/WithoutMempool/Chain.json +1 -1
  32. package/src/manifest/public/WithoutMempool/Pending.json +16 -2
  33. package/src/orchestrator/Orchestrator.ts +69 -0
  34. package/src/orchestrator/index.ts +1 -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-orchestration",
4
- "version": "1.17.0",
4
+ "version": "1.17.2",
5
5
  "description": "XYO Layer One SDK Orchestration",
6
6
  "homepage": "https://xylabs.com",
7
7
  "bugs": {
@@ -40,47 +40,48 @@
40
40
  ],
41
41
  "dependencies": {
42
42
  "@opentelemetry/api": "~1.9.0",
43
- "@xylabs/mongo": "~5.0.46",
44
- "@xylabs/sdk-js": "~5.0.46",
45
- "@xyo-network/archivist-memory": "~5.2.10",
46
- "@xyo-network/archivist-model": "~5.2.10",
47
- "@xyo-network/archivist-mongodb": "~5.2.10",
48
- "@xyo-network/archivist-view": "~5.2.10",
43
+ "@xylabs/mongo": "~5.0.50",
44
+ "@xylabs/sdk-js": "~5.0.50",
45
+ "@xyo-network/archivist-memory": "~5.2.17",
46
+ "@xyo-network/archivist-model": "~5.2.17",
47
+ "@xyo-network/archivist-mongodb": "~5.2.17",
48
+ "@xyo-network/archivist-view": "~5.2.17",
49
49
  "@xyo-network/bios": "~7.2.0",
50
- "@xyo-network/bridge-http": "~5.2.10",
51
- "@xyo-network/bridge-model": "~5.2.10",
52
- "@xyo-network/chain-modules": "~1.17.0",
53
- "@xyo-network/chain-protocol": "~1.17.0",
54
- "@xyo-network/chain-sdk": "~1.17.0",
55
- "@xyo-network/chain-services": "~1.17.0",
56
- "@xyo-network/chain-telemetry": "~1.17.0",
57
- "@xyo-network/diviner-model": "~5.2.10",
58
- "@xyo-network/manifest-wrapper": "~5.2.10",
59
- "@xyo-network/module-abstract": "~5.2.10",
60
- "@xyo-network/module-factory-locator": "~5.2.10",
61
- "@xyo-network/module-model": "~5.2.10",
62
- "@xyo-network/node-memory": "~5.2.10",
63
- "@xyo-network/sentinel-memory": "~5.2.10",
64
- "@xyo-network/sentinel-model": "~5.2.10",
65
- "@xyo-network/typechain": "~4.0.10",
66
- "@xyo-network/wallet": "~5.2.10",
67
- "@xyo-network/xl1-protocol": "~1.14.15",
68
- "@xyo-network/xl1-protocol-sdk": "~1.17.0",
50
+ "@xyo-network/bridge-http": "~5.2.17",
51
+ "@xyo-network/bridge-model": "~5.2.17",
52
+ "@xyo-network/chain-modules": "~1.17.2",
53
+ "@xyo-network/chain-protocol": "~1.17.2",
54
+ "@xyo-network/chain-sdk": "~1.17.2",
55
+ "@xyo-network/chain-services": "~1.17.2",
56
+ "@xyo-network/chain-telemetry": "~1.17.2",
57
+ "@xyo-network/diviner-model": "~5.2.17",
58
+ "@xyo-network/manifest-wrapper": "~5.2.17",
59
+ "@xyo-network/module-abstract": "~5.2.17",
60
+ "@xyo-network/module-factory-locator": "~5.2.17",
61
+ "@xyo-network/module-model": "~5.2.17",
62
+ "@xyo-network/node-memory": "~5.2.17",
63
+ "@xyo-network/sentinel-memory": "~5.2.17",
64
+ "@xyo-network/sentinel-model": "~5.2.17",
65
+ "@xyo-network/typechain": "~4.0.11",
66
+ "@xyo-network/wallet": "~5.2.17",
67
+ "@xyo-network/xl1-protocol": "~1.14.16",
68
+ "@xyo-network/xl1-protocol-sdk": "~1.17.2",
69
69
  "async-mutex": "~0.5.0",
70
- "ethers": "~6.15.0"
70
+ "ethers": "^6.16.0"
71
71
  },
72
72
  "devDependencies": {
73
73
  "@types/node": "~24.10.1",
74
- "@xylabs/sdk-js": "~5.0.46",
74
+ "@xylabs/sdk-js": "~5.0.50",
75
+ "@xylabs/telemetry": "~5.0.50",
75
76
  "@xylabs/ts-scripts-yarn3": "~7.2.8",
76
77
  "@xylabs/tsconfig": "~7.2.8",
77
- "@xyo-network/account-model": "~5.2.10",
78
+ "@xyo-network/account-model": "~5.2.17",
78
79
  "@xyo-network/bios-model": "~7.2.0",
79
- "@xyo-network/manifest-model": "~5.2.10",
80
- "@xyo-network/module-model-mongodb": "~5.2.10",
81
- "@xyo-network/node-model": "~5.2.10",
82
- "@xyo-network/payload-model": "~5.2.10",
83
- "@xyo-network/wallet-model": "~5.2.10",
80
+ "@xyo-network/manifest-model": "~5.2.17",
81
+ "@xyo-network/module-model-mongodb": "~5.2.17",
82
+ "@xyo-network/node-model": "~5.2.17",
83
+ "@xyo-network/payload-model": "~5.2.17",
84
+ "@xyo-network/wallet-model": "~5.2.17",
84
85
  "eslint": "^9.39.1",
85
86
  "typescript": "~5.9.3"
86
87
  },
@@ -0,0 +1,163 @@
1
+ import type {
2
+ CreatableInstance, CreatableParams, EmptyObject,
3
+ } from '@xylabs/sdk-js'
4
+ import {
5
+ AbstractCreatable,
6
+ Base, creatable, delay, IdLogger,
7
+ } from '@xylabs/sdk-js'
8
+ import { span, spanRootAsync } from '@xylabs/telemetry'
9
+ import type { Config } from '@xyo-network/xl1-protocol-sdk'
10
+ import { Semaphore } from 'async-mutex'
11
+
12
+ export type ActorParams<T extends EmptyObject | void = void> = CreatableParams & {
13
+ config: Config
14
+ displayName?: string
15
+ id: string
16
+ } & (T extends void ? EmptyObject : T)
17
+
18
+ export type ActorInstance<T extends ActorParams = ActorParams> = CreatableInstance<T> & {
19
+ start(): Promise<boolean>
20
+ stop(): Promise<boolean>
21
+ }
22
+
23
+ @creatable()
24
+ export class Actor<TParams extends ActorParams = ActorParams> extends AbstractCreatable<TParams> {
25
+ protected readonly _intervals: Map<string, ReturnType<typeof setInterval>> = new Map()
26
+ protected readonly _semaphores: Map<string, Semaphore> = new Map()
27
+ protected readonly _timeouts: Map<string, ReturnType<typeof setTimeout>> = new Map()
28
+ private _active = false
29
+
30
+ get displayName() {
31
+ return this.params.displayName!
32
+ }
33
+
34
+ get id() {
35
+ return this.params.id
36
+ }
37
+
38
+ protected get logPrefix() {
39
+ return `[${this.displayName} (${this.id})] `
40
+ }
41
+
42
+ static override async paramsHandler<T extends ActorParams>(params?: Partial<T>) {
43
+ const baseParams = await super.paramsHandler(params)
44
+ const id = params?.id ?? baseParams.name
45
+ const displayName = params?.displayName ?? baseParams.name
46
+ return {
47
+ ...baseParams,
48
+ displayName,
49
+ id,
50
+ logger: baseParams.logger ?? new IdLogger(Base.defaultLogger ?? console, () => `[${displayName} (${id})] `),
51
+ }
52
+ }
53
+
54
+ /**
55
+ * The timer runs until the actor is deactivated (or you manually stop it).
56
+ */
57
+ registerTimer(timerName: string, callback: () => Promise<void>, dueTimeMs: number, periodMs: number) {
58
+ if (!this._active) {
59
+ this.logger?.warn(
60
+ `Cannot register timer '${timerName}' because actor is not active.`,
61
+ )
62
+ return
63
+ }
64
+
65
+ let running = false
66
+
67
+ this._semaphores.set(timerName, new Semaphore(1))
68
+
69
+ const timeoutId = setTimeout(() => {
70
+ const intervalId = setInterval(() => {
71
+ const semaphore = this._semaphores.get(timerName)
72
+ if (!this._active || !this._intervals.has(timerName) || !semaphore || running) return
73
+ if (semaphore.isLocked()) {
74
+ this.logger?.warn(
75
+ `Skipping timer '${this.name}:${timerName}' execution because previous execution is still running.`,
76
+ )
77
+ return
78
+ }
79
+ semaphore.acquire().then(([, release]) => {
80
+ const startTime = Date.now()
81
+ running = true
82
+ callback()
83
+ .then(() => {
84
+ const duration = Date.now() - startTime
85
+ if (duration > periodMs) {
86
+ this.logger?.warn(
87
+ `Timer '${this.name}:${timerName}' execution took longer (${duration}ms) than the period (${periodMs}ms).`,
88
+ )
89
+ } else if (duration > 5000) {
90
+ this.logger?.warn(
91
+ `Timer '${this.name}:${timerName}' execution took longer (${duration}ms) than 5000ms.`,
92
+ )
93
+ }
94
+ })
95
+ .catch((error) => {
96
+ this.logger?.error(`Error in timer '${this.name}:${timerName}': ${error}`)
97
+ })
98
+ .finally(() => {
99
+ release()
100
+ running = false
101
+ })
102
+ }).catch((error) => {
103
+ this.logger?.error(`Error acquiring semaphore for timer '${this.name}:${timerName}': ${error}`)
104
+ })
105
+ }, periodMs)
106
+
107
+ // store interval so we can clear it on stop()
108
+ this._intervals.set(timerName, intervalId)
109
+ }, dueTimeMs)
110
+
111
+ // store timeout so we can clear it on stop() if interval hasn't started yet
112
+ this._timeouts.set(timerName, timeoutId)
113
+
114
+ this.logger?.log(
115
+ `Timer '${this.name}:${timerName}' registered: first call after ${dueTimeMs}ms, recurring every ${periodMs}ms.`,
116
+ )
117
+ }
118
+
119
+ /**
120
+ * Called by the Orchestrator when the actor is activated.
121
+ */
122
+ override async startHandler() {
123
+ await super.startHandler()
124
+ this._active = true
125
+ this.logger?.log('Started.')
126
+ }
127
+
128
+ /**
129
+ * Called by the Orchestrator when the actor is deactivated.
130
+ * Stop all running timers.
131
+ */
132
+ override async stopHandler() {
133
+ await super.stopHandler()
134
+ this._active = false
135
+ this.logger?.log('Stopping all timers...')
136
+
137
+ // wait for all semaphores to be free and acquire them to prevent new tasks from starting
138
+ await Promise.all(
139
+ [...this._semaphores.values()].map(async (semaphore) => {
140
+ // Wait for any running tasks to complete
141
+ while (semaphore.isLocked()) {
142
+ this.logger?.log('Waiting for running timer task to complete...')
143
+ await delay(500)
144
+ }
145
+ await semaphore.acquire()
146
+ }),
147
+ )
148
+
149
+ this._semaphores.clear()
150
+
151
+ for (const [, timeoutRef] of this._timeouts.entries()) {
152
+ clearTimeout(timeoutRef)
153
+ }
154
+ this._timeouts.clear()
155
+
156
+ for (const [, intervalRef] of this._intervals.entries()) {
157
+ clearInterval(intervalRef)
158
+ }
159
+ this._intervals.clear()
160
+
161
+ this.logger?.log('Stopped.')
162
+ }
163
+ }
@@ -0,0 +1 @@
1
+ export * from './Actor.ts'
package/src/index.ts CHANGED
@@ -1,6 +1,8 @@
1
+ export * from './actor/index.ts'
1
2
  export * from './archivist/index.ts'
2
3
  export * from './bridge.ts'
3
4
  export * from './ConfigContext.ts'
4
5
  export * from './createDeclarationIntentBlock.ts'
5
6
  export * from './init/index.ts'
6
7
  export * from './manifest/index.ts'
8
+ export * from './orchestrator/index.ts'
package/src/init/index.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  export * from './initBalanceSummaryMap.ts'
2
2
  export * from './initBridgedModule.ts'
3
3
  export * from './initChainStakeViewer.ts'
4
+ export * from './initPendingBlockArchivist.ts'
5
+ export * from './initPendingTransactionArchivist.ts'
4
6
  export * from './initProducerAccount.ts'
5
7
  export * from './initSeedPhrase.ts'
6
8
  export * from './initServerNode.ts'
@@ -32,7 +32,7 @@ export async function initSimpleStakeViewer(config: Config, logger?: Logger): Pr
32
32
  return stakeChainViewer
33
33
  }
34
34
 
35
- export async function initChainStakeViewer(config: Config, logger?: Logger): Promise<StakeViewer> {
35
+ export async function initStakeViewer(config: Config, logger?: Logger): Promise<StakeViewer> {
36
36
  if (canUseEvmProvider({ config })) {
37
37
  return await initEvmChainStakeViewer(config, logger)
38
38
  } else {
@@ -0,0 +1,31 @@
1
+ import { type BaseMongoSdkPrivateConfig } from '@xylabs/mongo'
2
+ import { MemoryArchivist } from '@xyo-network/archivist-memory'
3
+ import type { ArchivistInstance } from '@xyo-network/archivist-model'
4
+ import { MongoDBArchivistV2 } from '@xyo-network/archivist-mongodb'
5
+ import { hasMongoConfig } from '@xyo-network/xl1-protocol-sdk'
6
+
7
+ import type { ConfigContext } from '../ConfigContext.ts'
8
+
9
+ export async function initPendingBlockArchivist({ config, logger }: ConfigContext): Promise<ArchivistInstance> {
10
+ const mongoConfig = config.storage?.mongo
11
+ if (hasMongoConfig(mongoConfig)) {
12
+ // Create the MongoDB SDK from the configuration
13
+ const {
14
+ connectionString: dbConnectionString, database: dbName, domain: dbDomain, password: dbPassword, username: dbUserName,
15
+ } = mongoConfig
16
+ const payloadSdkConfig: BaseMongoSdkPrivateConfig = {
17
+ dbConnectionString, dbDomain, dbName, dbPassword, dbUserName,
18
+ }
19
+
20
+ return await MongoDBArchivistV2.create({
21
+ payloadSdkConfig: {
22
+ ...payloadSdkConfig,
23
+ collection: 'pending_block_bundles',
24
+ },
25
+ logger,
26
+ })
27
+ } else {
28
+ logger?.warn('[API] Mongo configuration not found. Using MemoryArchivist for TransferSummaryMap.')
29
+ return await MemoryArchivist.create()
30
+ }
31
+ }
@@ -0,0 +1,31 @@
1
+ import { type BaseMongoSdkPrivateConfig } from '@xylabs/mongo'
2
+ import { MemoryArchivist } from '@xyo-network/archivist-memory'
3
+ import type { ArchivistInstance } from '@xyo-network/archivist-model'
4
+ import { MongoDBArchivistV2 } from '@xyo-network/archivist-mongodb'
5
+ import { hasMongoConfig } from '@xyo-network/xl1-protocol-sdk'
6
+
7
+ import type { ConfigContext } from '../ConfigContext.ts'
8
+
9
+ export async function initPendingTransactionArchivist({ config, logger }: ConfigContext): Promise<ArchivistInstance> {
10
+ const mongoConfig = config.storage?.mongo
11
+ if (hasMongoConfig(mongoConfig)) {
12
+ // Create the MongoDB SDK from the configuration
13
+ const {
14
+ connectionString: dbConnectionString, database: dbName, domain: dbDomain, password: dbPassword, username: dbUserName,
15
+ } = mongoConfig
16
+ const payloadSdkConfig: BaseMongoSdkPrivateConfig = {
17
+ dbConnectionString, dbDomain, dbName, dbPassword, dbUserName,
18
+ }
19
+
20
+ return await MongoDBArchivistV2.create({
21
+ payloadSdkConfig: {
22
+ ...payloadSdkConfig,
23
+ collection: 'pending_transaction_bundles',
24
+ },
25
+ logger,
26
+ })
27
+ } else {
28
+ logger?.warn('[API] Mongo configuration not found. Using MemoryArchivist for TransferSummaryMap.')
29
+ return await MemoryArchivist.create()
30
+ }
31
+ }
@@ -172,4 +172,4 @@
172
172
  }
173
173
  ],
174
174
  "schema": "network.xyo.manifest"
175
- }
175
+ }
@@ -22,7 +22,21 @@
22
22
  "network.xyo.storage.class": "mongodb"
23
23
  },
24
24
  "payloadSdkConfig": {
25
- "collection": "pending_bundles"
25
+ "collection": "pending_transaction_bundles"
26
+ },
27
+ "schema": "network.xyo.archivist.config"
28
+ }
29
+ },
30
+ {
31
+ "config": {
32
+ "accountPath": "2/1/2",
33
+ "name": "PendingBlocks",
34
+ "getCache": {
35
+ "enabled": true,
36
+ "maxEntries": 5000
37
+ },
38
+ "payloadSdkConfig": {
39
+ "collection": "pending_block_bundles"
26
40
  },
27
41
  "schema": "network.xyo.archivist.config"
28
42
  }
@@ -32,4 +46,4 @@
32
46
  }
33
47
  ],
34
48
  "schema": "network.xyo.manifest"
35
- }
49
+ }
@@ -94,4 +94,4 @@
94
94
  }
95
95
  ],
96
96
  "schema": "network.xyo.manifest"
97
- }
97
+ }
@@ -22,7 +22,21 @@
22
22
  "network.xyo.storage.class": "mongodb"
23
23
  },
24
24
  "payloadSdkConfig": {
25
- "collection": "pending_bundles"
25
+ "collection": "pending_transaction_bundles"
26
+ },
27
+ "schema": "network.xyo.archivist.config"
28
+ }
29
+ },
30
+ {
31
+ "config": {
32
+ "accountPath": "2/1/2",
33
+ "name": "PendingBlocks",
34
+ "getCache": {
35
+ "enabled": true,
36
+ "maxEntries": 5000
37
+ },
38
+ "payloadSdkConfig": {
39
+ "collection": "pending_block_bundles"
26
40
  },
27
41
  "schema": "network.xyo.archivist.config"
28
42
  }
@@ -32,4 +46,4 @@
32
46
  }
33
47
  ],
34
48
  "schema": "network.xyo.manifest"
35
- }
49
+ }
@@ -0,0 +1,69 @@
1
+ import type { CreatableInstance } from '@xylabs/sdk-js'
2
+ import { AbstractCreatable, creatable } from '@xylabs/sdk-js'
3
+
4
+ import type { ActorInstance } from '../actor/index.ts'
5
+
6
+ export interface OrchestratorInstance extends CreatableInstance {
7
+ registerActor(actor: ActorInstance): Promise<void>
8
+ start(): Promise<boolean>
9
+ stop(): Promise<boolean>
10
+ }
11
+
12
+ @creatable()
13
+ export class Orchestrator extends AbstractCreatable implements OrchestratorInstance {
14
+ protected actors: ActorInstance[] = []
15
+ protected keepAliveHandle: NodeJS.Timeout | null = null
16
+ protected running = false
17
+
18
+ /**
19
+ * Registers an actor.
20
+ * (We won't activate the actor until `start()` is called.)
21
+ */
22
+ async registerActor(actor: ActorInstance) {
23
+ if (this.running) {
24
+ // If the orchestrator is already running, activate the actor immediately
25
+ await actor.start()
26
+ }
27
+ this.actors.push(actor)
28
+ }
29
+
30
+ /**
31
+ * Starts the orchestrator: activates all actors.
32
+ */
33
+ override async startHandler() {
34
+ await super.startHandler()
35
+ if (this.running) {
36
+ this.logger?.warn('[Orchestrator] Already started.')
37
+ return
38
+ }
39
+
40
+ this.logger?.log('[Orchestrator] Starting...')
41
+ this.running = true
42
+ for (const actor of this.actors) {
43
+ await actor.start()
44
+ }
45
+ // This interval will fire every 24.8 days (2^31 - 1 ms), effectively never finishing
46
+ this.keepAliveHandle = setInterval(() => {
47
+ // No-op
48
+ }, 2_147_483_647)
49
+ }
50
+
51
+ /**
52
+ * Stops the orchestrator: deactivates all actors.
53
+ */
54
+ override async stopHandler() {
55
+ await super.stopHandler()
56
+ if (!this.running) {
57
+ this.logger?.log('[Orchestrator] Already stopped.')
58
+ return
59
+ }
60
+
61
+ this.logger?.log('[Orchestrator] Stopping...')
62
+ for (const actor of this.actors) {
63
+ await actor.stop()
64
+ }
65
+ this.running = false
66
+ if (this.keepAliveHandle) clearInterval(this.keepAliveHandle)
67
+ this.logger?.log('[Orchestrator] Stopped...')
68
+ }
69
+ }
@@ -0,0 +1 @@
1
+ export * from './Orchestrator.ts'