@xyo-network/chain-api 1.19.6 → 1.19.8

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"initApiParams.d.ts","sourceRoot":"","sources":["../../../src/server/initApiParams.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAW5C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAC3D,OAAO,KAAK,EACyB,MAAM,EAI1C,MAAM,sBAAsB,CAAA;AAO7B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAGpD,UAAU,iBAAiB;IACzB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,YAAY,CAAA;CACpB;AAED,wBAAsB,aAAa,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,cAAc,CAAC,CAuItF"}
@@ -1,11 +1,3 @@
1
- import type { Logger } from '@xylabs/sdk-js';
2
- import type { NodeInstance } from '@xyo-network/node-model';
3
- import type { Config } from '@xyo-network/xl1-sdk';
4
- interface GetServerContext {
5
- config: Config;
6
- logger?: Logger;
7
- node?: NodeInstance;
8
- }
9
- export declare function getServer(params: GetServerContext): Promise<import("node:http").Server<typeof import("node:http").IncomingMessage, typeof import("node:http").ServerResponse>>;
10
- export {};
1
+ import type { ApiContext } from '../ApiContext.ts';
2
+ export declare function getServer(context: ApiContext): Promise<import("node:http").Server<typeof import("node:http").IncomingMessage, typeof import("node:http").ServerResponse>>;
11
3
  //# sourceMappingURL=server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/server/server.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAQ,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAmBlD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAG3D,OAAO,KAAK,EAC6D,MAAM,EAK9E,MAAM,sBAAsB,CAAA;AAc7B,UAAU,gBAAgB;IACxB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,YAAY,CAAA;CACpB;AAED,wBAAsB,SAAS,CAAC,MAAM,EAAE,gBAAgB,8HA0NvD"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/server/server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAKlD,wBAAsB,SAAS,CAAC,OAAO,EAAE,UAAU,8HAQlD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xyo-network/chain-api",
3
- "version": "1.19.6",
3
+ "version": "1.19.8",
4
4
  "description": "XYO Layer One API",
5
5
  "homepage": "https://xylabs.com",
6
6
  "bugs": {
@@ -52,25 +52,22 @@
52
52
  "@opentelemetry/instrumentation": "~0.211.0",
53
53
  "@opentelemetry/instrumentation-express": "~0.59.0",
54
54
  "@opentelemetry/instrumentation-http": "~0.211.0",
55
- "@xylabs/express": "~5.0.65",
56
- "@xylabs/sdk-js": "~5.0.65",
55
+ "@xylabs/express": "~5.0.78",
56
+ "@xylabs/sdk-js": "~5.0.78",
57
57
  "@xyo-network/account": "~5.3.2",
58
58
  "@xyo-network/archivist-model": "~5.3.2",
59
59
  "@xyo-network/boundwitness-model": "~5.3.2",
60
- "@xyo-network/chain-ethereum": "~1.19.6",
61
- "@xyo-network/chain-orchestration": "~1.19.6",
62
- "@xyo-network/chain-services": "~1.19.6",
63
- "@xyo-network/chain-telemetry": "~1.19.6",
64
- "@xyo-network/chain-utils": "~1.19.6",
65
- "@xyo-network/chain-validation": "~1.19.6",
60
+ "@xyo-network/chain-orchestration": "~1.19.8",
61
+ "@xyo-network/chain-services": "~1.19.8",
62
+ "@xyo-network/chain-telemetry": "~1.19.8",
63
+ "@xyo-network/chain-utils": "~1.19.8",
64
+ "@xyo-network/chain-validation": "~1.19.8",
66
65
  "@xyo-network/module-abstract": "~5.3.2",
67
66
  "@xyo-network/module-model": "~5.3.2",
68
67
  "@xyo-network/node-model": "~5.3.2",
69
68
  "@xyo-network/payload-builder": "~5.3.2",
70
69
  "@xyo-network/payload-model": "~5.3.2",
71
- "@xyo-network/typechain": "~4.1.1",
72
- "@xyo-network/xl1-sdk": "~1.21.10",
73
- "async-mutex": "~0.5.0",
70
+ "@xyo-network/xl1-sdk": "~1.23.6",
74
71
  "compression": "~1.8.1",
75
72
  "cors": "~2.8.6",
76
73
  "ethers": "^6.16.0",
@@ -82,8 +79,8 @@
82
79
  "@types/cors": "~2.8.19",
83
80
  "@types/express": "5.0.6",
84
81
  "@types/express-serve-static-core": "~5.1.1",
85
- "@types/node": "~25.1.0",
86
- "@xylabs/sdk-js": "~5.0.65",
82
+ "@types/node": "~25.2.3",
83
+ "@xylabs/sdk-js": "~5.0.78",
87
84
  "@xylabs/ts-scripts-yarn3": "~7.3.2",
88
85
  "@xylabs/tsconfig": "~7.3.2",
89
86
  "@xyo-network/account": "~5.3.2",
@@ -91,12 +88,12 @@
91
88
  "@xyo-network/archivist-abstract": "~5.3.2",
92
89
  "@xyo-network/bios-model": "~7.2.1",
93
90
  "@xyo-network/boundwitness-builder": "~5.3.2",
94
- "@xyo-network/chain-services": "~1.19.6",
91
+ "@xyo-network/chain-services": "~1.19.8",
95
92
  "@xyo-network/module-abstract-mongodb": "~5.3.2",
96
93
  "@xyo-network/module-model-mongodb": "~5.3.2",
97
94
  "@xyo-network/node-memory": "~5.3.2",
98
- "@xyo-network/xl1-sdk": "~1.21.10",
99
- "dotenv": "~17.2.3",
95
+ "@xyo-network/xl1-sdk": "~1.23.6",
96
+ "dotenv": "~17.2.4",
100
97
  "eslint": "^9.39.2",
101
98
  "nodemon": "~3.1.11",
102
99
  "tslib": "~2.8.1",
package/src/ApiActor.ts CHANGED
@@ -1,30 +1,52 @@
1
1
  import { Server } from 'node:http'
2
2
 
3
- import { creatable } from '@xylabs/sdk-js'
3
+ import { assertEx, creatable } from '@xylabs/sdk-js'
4
4
  import { Account } from '@xyo-network/account'
5
- import { Actor, ActorParams } from '@xyo-network/xl1-sdk'
5
+ import { WithStorageMeta } from '@xyo-network/payload-model'
6
+ import {
7
+ Actor, ActorParams, BalancesStepSummary, CreatableProviderFactory,
8
+ MapType,
9
+ TransfersStepSummary,
10
+ } from '@xyo-network/xl1-sdk'
6
11
 
12
+ import { ApiContext } from './ApiContext.ts'
7
13
  import { getServer } from './server/index.ts'
8
14
 
9
15
  export type ApiActorParams = ActorParams<{
10
-
16
+ balancesSummaryMap: MapType<string, WithStorageMeta<BalancesStepSummary>>
17
+ context: ApiContext
18
+ transfersSummaryMap: MapType<string, WithStorageMeta<TransfersStepSummary>>
11
19
  }>
12
20
 
13
21
  @creatable()
14
22
  export class ApiActor extends Actor<ApiActorParams> {
15
23
  private server?: Server
16
24
 
17
- static override async paramsHandler<T extends ApiActor>(params?: Partial<T['params']>) {
25
+ protected override get context() {
26
+ return this.params.context!
27
+ }
28
+
29
+ static override defaultFactories(): CreatableProviderFactory[] {
30
+ return [
31
+ ...super.defaultFactories(),
32
+ ]
33
+ }
34
+
35
+ static override async paramsHandler<T extends ApiActor>(params: T['params']) {
18
36
  const logger = params?.context?.logger
19
37
 
20
- const account = params?.account ?? await Account.random()
38
+ let account = params?.account
39
+ if (account === undefined) {
40
+ const newAccount = await Account.random()
41
+ logger?.warn(`No account provided to ApiActor, generating random account ${newAccount.address}`)
42
+ account = newAccount
43
+ }
21
44
  logger?.info(`Running api for account ${account.address}`)
22
45
 
23
46
  return {
24
- ...await super.paramsHandler({
25
- ...params,
26
- account,
27
- }),
47
+ ...await super.paramsHandler(params),
48
+ context: params.context,
49
+ account: assertEx(account, () => 'ApiActor requires an account to run'),
28
50
  }
29
51
  }
30
52
 
@@ -44,7 +66,7 @@ export class ApiActor extends Actor<ApiActorParams> {
44
66
  }
45
67
 
46
68
  private async startServer() {
47
- this.server = await getServer({ config: this.config, logger: this.logger })
69
+ this.server = await getServer(this.context)
48
70
  }
49
71
 
50
72
  private stopServer() {
package/src/ApiContext.ts CHANGED
@@ -1,12 +1,6 @@
1
1
  import type { NodeInstance } from '@xyo-network/node-model'
2
- import type { WithStorageMeta } from '@xyo-network/payload-model'
3
- import type {
4
- BalancesStepSummary, CreatableProviderContext, MapType,
5
- TransfersStepSummary,
6
- } from '@xyo-network/xl1-sdk'
2
+ import type { CreatableProviderContext } from '@xyo-network/xl1-sdk'
7
3
 
8
4
  export interface ApiContext extends CreatableProviderContext {
9
- balancesSummaryMap: MapType<string, WithStorageMeta<BalancesStepSummary>>
10
5
  node: NodeInstance
11
- transfersSummaryMap: MapType<string, WithStorageMeta<TransfersStepSummary>>
12
6
  }
@@ -1,4 +1,3 @@
1
1
  export * from './initChainId.ts'
2
- export * from './initEvmProvider.ts'
3
2
  export * from './initInfuraProvider.ts'
4
3
  export * from './initJsonRpcProvider.ts'
package/src/runApi.ts CHANGED
@@ -1,32 +1,27 @@
1
1
  import { exists, IdLogger } from '@xylabs/sdk-js'
2
2
  import { Account } from '@xyo-network/account'
3
3
  import { type OrchestratorInstance } from '@xyo-network/chain-orchestration'
4
- import type {
5
- BaseContext, Config, ProviderFactoryLocatorInstance,
6
- } from '@xyo-network/xl1-sdk'
4
+ import { type BaseContext, type Config } from '@xyo-network/xl1-sdk'
7
5
 
8
6
  import { ApiActor } from './ApiActor.ts'
7
+ import { initApiParams } from './server/index.ts'
9
8
 
10
9
  export interface RunApiContext extends BaseContext {
11
10
  config: Config
12
- locator?: ProviderFactoryLocatorInstance
13
11
  orchestrator: OrchestratorInstance
14
12
  }
15
13
 
16
14
  export const runApi = async ({
17
- config, logger, orchestrator, locator,
15
+ config, orchestrator, ...params
18
16
  }: RunApiContext) => {
19
- const localLogger = logger ?? new IdLogger(logger ?? console, () => 'ResolveHelper [runApi]')
17
+ const logger = new IdLogger(params.logger ?? console, () => 'API')
20
18
  const account = await Account.random()
21
- localLogger.info(`Running api for account ${account.address} [random]`)
19
+ logger.info(`Running api for account ${account.address} [random]`)
20
+
21
+ const actorParams = await initApiParams({ config, logger })
22
22
 
23
23
  // Create actors
24
- const api = await ApiActor.create({
25
- logger,
26
- context: {
27
- config, locator, singletons: {}, logger, caches: {},
28
- },
29
- })
24
+ const api = await ApiActor.create(actorParams)
30
25
  const actors = [api].filter(exists)
31
26
 
32
27
  for (const actor of actors) {
@@ -1,2 +1,3 @@
1
1
  export * from './app.ts'
2
+ export * from './initApiParams.ts'
2
3
  export * from './server.ts'
@@ -0,0 +1,170 @@
1
+ /* eslint-disable max-statements */
2
+ import type { Logger } from '@xylabs/sdk-js'
3
+ import { assertEx } from '@xylabs/sdk-js'
4
+ import type { MempoolActorParams, ValidatorActorParams } from '@xyo-network/chain-orchestration'
5
+ import {
6
+ buildTelemetryConfig, initApiWallet, initBalanceSummaryMap, initEvmProvidersIfAvailable,
7
+ initFinalizationArchivistIfNeeded, initHealthEndpoints, initServerNode,
8
+ initStatusReporter, initTransferSummaryMap, MempoolActor, ValidatorActor,
9
+ } from '@xyo-network/chain-orchestration'
10
+ import { initTelemetry } from '@xyo-network/chain-telemetry'
11
+ import { startupSpanAsync } from '@xyo-network/chain-utils'
12
+ import { validateHydratedBlock, validateHydratedBlockState } from '@xyo-network/chain-validation'
13
+ import type { NodeInstance } from '@xyo-network/node-model'
14
+ import type {
15
+ AccountBalanceViewer, BlockViewer, Config,
16
+ MempoolRunner,
17
+ MempoolViewer,
18
+ XyoViewer,
19
+ } from '@xyo-network/xl1-sdk'
20
+ import {
21
+ AccountBalanceViewerMoniker, BlockViewerMoniker, buildLocalProviderLocator, DefaultMetricsScrapePorts,
22
+ MempoolRunnerMoniker, MempoolViewerMoniker, SimpleBlockValidationViewer, SimpleXyoConnection,
23
+ XyoViewerMoniker,
24
+ } from '@xyo-network/xl1-sdk'
25
+
26
+ import type { ApiActorParams } from '../ApiActor.ts'
27
+ import type { ApiContext } from '../ApiContext.ts'
28
+
29
+ interface InitServerContext {
30
+ config: Config
31
+ logger?: Logger
32
+ node?: NodeInstance
33
+ }
34
+
35
+ export async function initApiParams(params: InitServerContext): Promise<ApiActorParams> {
36
+ const { config, node: providedNode } = params
37
+
38
+ const logger = assertEx(params.logger, () => 'Logger is required to init server')
39
+
40
+ const statusReporter = initStatusReporter({ logger })
41
+
42
+ await startupSpanAsync('initHealthEndpoints', () => initHealthEndpoints({
43
+ config, logger, statusReporter,
44
+ }))
45
+
46
+ const telemetryConfig = buildTelemetryConfig(config, 'xl1-api', '1.0.0', DefaultMetricsScrapePorts.api)
47
+
48
+ const { traceProvider, meterProvider } = await startupSpanAsync('initTelemetry', () => initTelemetry(telemetryConfig))
49
+
50
+ const initContext = {
51
+ _id: 'init-context',
52
+ config,
53
+ logger,
54
+ statusReporter,
55
+ timeBudgetLimit: 1000,
56
+ meterProvider,
57
+ traceProvider,
58
+ singletons: {},
59
+ caches: {},
60
+ }
61
+
62
+ const wallet = await initApiWallet(initContext)
63
+
64
+ const balancesSummaryMap = assertEx(await initBalanceSummaryMap(initContext), () => 'Balance Summary Map not initialized')
65
+ const transfersSummaryMap = assertEx(await initTransferSummaryMap(initContext), () => 'Transfer Summary Map not initialized')
66
+
67
+ const {
68
+ node, writableChainArchivist, readonlyChainArchivist, pendingTransactionsArchivist, pendingBlocksArchivist,
69
+ } = await initServerNode({
70
+ ...initContext,
71
+ wallet,
72
+ node: providedNode,
73
+ transfersSummaryMap,
74
+ balancesSummaryMap,
75
+ })
76
+
77
+ await writableChainArchivist.start()
78
+ await readonlyChainArchivist.start()
79
+ await pendingTransactionsArchivist.start()
80
+ await pendingBlocksArchivist.start()
81
+
82
+ const [head, chainId] = await initFinalizationArchivistIfNeeded(writableChainArchivist, config, wallet)
83
+
84
+ assertEx(head.chain === chainId, () => `Chain ID does not match head block chain ID [init] [${head.chain} !== ${chainId}]`)
85
+
86
+ const mods = await node.resolve('*')
87
+ await Promise.all(mods.map((mod) => {
88
+ return mod.start?.() ?? (() => true)
89
+ }))
90
+
91
+ const locator = buildLocalProviderLocator({
92
+ context: initContext,
93
+ finalizedArchivist: writableChainArchivist,
94
+ pendingTransactionsArchivist,
95
+ pendingBlocksArchivist,
96
+ balancesSummaryMap,
97
+ transfersSummaryMap,
98
+ node,
99
+ })
100
+
101
+ await initEvmProvidersIfAvailable(locator)
102
+
103
+ locator.register(SimpleBlockValidationViewer.factory<SimpleBlockValidationViewer>(
104
+ SimpleBlockValidationViewer.dependencies,
105
+ { state: validateHydratedBlockState, protocol: validateHydratedBlock },
106
+ ))
107
+
108
+ locator.register(SimpleXyoConnection.factory<SimpleXyoConnection>(SimpleXyoConnection.dependencies, {}))
109
+
110
+ const apiContext = {
111
+ ...initContext,
112
+ ...locator.context,
113
+ _id: 'api-context',
114
+ node,
115
+ } satisfies ApiContext
116
+
117
+ const blockViewer = (await locator.getInstance<BlockViewer>(BlockViewerMoniker))
118
+ assertEx(await blockViewer.start(), () => 'Failed to start BlockViewer')
119
+
120
+ const blk = await blockViewer.currentBlock()
121
+ assertEx(blk, () => 'No blocks found after initialization')
122
+
123
+ const accountBalanceViewer = (await locator.getInstance<AccountBalanceViewer>(AccountBalanceViewerMoniker))
124
+ assertEx(await accountBalanceViewer.start(), () => 'Failed to start AccountBalanceViewer')
125
+
126
+ const xyoViewer = (await locator.getInstance<XyoViewer>(XyoViewerMoniker))
127
+ assertEx(await xyoViewer.start(), () => 'Failed to start XyoViewer')
128
+
129
+ const mempoolViewer = (await locator.getInstance<MempoolViewer>(MempoolViewerMoniker))
130
+ assertEx(await mempoolViewer.start(), () => 'Failed to start MempoolViewer')
131
+
132
+ const mempoolRunner = (await locator.getInstance<MempoolRunner>(MempoolRunnerMoniker))
133
+ assertEx(await mempoolRunner.start(), () => 'Failed to start MempoolRunner')
134
+
135
+ console.info(`[API] Current block after initialization: #${blk[0].block} (${blk[0]._hash})`)
136
+
137
+ const validatorActor = config.actors.mempool.enabled
138
+ ? undefined
139
+ : await ValidatorActor.create({
140
+ id: 'validator-mempool-server',
141
+ account: wallet,
142
+ context: locator.context,
143
+ finalizedArchivist: writableChainArchivist,
144
+ mempoolViewer,
145
+ blockViewer,
146
+ } satisfies ValidatorActorParams)
147
+
148
+ await validatorActor?.start()
149
+
150
+ const mempoolActor = config.actors.mempool.enabled
151
+ ? undefined
152
+ : await MempoolActor.create({
153
+ id: 'mempool-mempool-server',
154
+ account: wallet,
155
+ context: locator.context,
156
+ mempoolRunner,
157
+ pendingBlocksArchivist,
158
+ pendingTransactionsArchivist,
159
+ } satisfies MempoolActorParams)
160
+
161
+ await mempoolActor?.start()
162
+
163
+ return {
164
+ id: 'api-actor',
165
+ account: wallet,
166
+ context: apiContext,
167
+ transfersSummaryMap,
168
+ balancesSummaryMap,
169
+ }
170
+ }
@@ -1,267 +1,13 @@
1
- /* eslint-disable max-statements */
2
- import type { Hash, Logger } from '@xylabs/sdk-js'
3
- import {
4
- asAddress,
5
- assertEx, toEthAddress,
6
- } from '@xylabs/sdk-js'
7
- import { Account } from '@xyo-network/account'
8
- import {
9
- EvmChainContractViewer,
10
- EvmStakeEventsViewer, EvmStakeViewer,
11
- } from '@xyo-network/chain-ethereum'
12
- import type { MempoolActorParams, ValidatorActorParams } from '@xyo-network/chain-orchestration'
13
- import {
14
- buildTelemetryConfig, canUseEvmProvider, initApiWallet, initBalanceSummaryMap, initEvmProvider, initHealthEndpoints, initServerNode,
15
- initStatusReporter, initTransferSummaryMap, MempoolActor, ValidatorActor,
16
- } from '@xyo-network/chain-orchestration'
17
- import { createBootstrapHead } from '@xyo-network/chain-services'
18
- import { initTelemetry } from '@xyo-network/chain-telemetry'
19
- import { startupSpanAsync } from '@xyo-network/chain-utils'
20
- import { validateHydratedBlock, validateHydratedBlockState } from '@xyo-network/chain-validation'
21
- import type { NodeInstance } from '@xyo-network/node-model'
22
- import type { Payload, WithStorageMeta } from '@xyo-network/payload-model'
23
- import { IStakedXyoChain__factory } from '@xyo-network/typechain'
24
- import type {
25
- AccountBalanceViewer, BalanceStepSummaryContext, BlockViewer, ChainId, Config,
26
- MempoolRunner,
27
- MempoolViewer,
28
- TransfersStepSummaryContext,
29
- XyoViewer,
30
- } from '@xyo-network/xl1-sdk'
31
- import {
32
- AccountBalanceViewerMoniker, asAttoXL1, BlockViewerMoniker, buildLocalProviderLocator, DefaultMetricsScrapePorts, findMostRecentBlock, flattenHydratedBlock,
33
- MempoolRunnerMoniker, MempoolViewerMoniker, payloadMapFromStore, SimpleBlockValidationViewer, SimpleTimeSyncViewer, StepSizes,
34
- XyoViewerMoniker,
35
- } from '@xyo-network/xl1-sdk'
36
- import { Semaphore } from 'async-mutex'
37
-
38
1
  import type { ApiContext } from '../ApiContext.ts'
39
2
  import { getApp } from './app.ts'
40
3
 
41
4
  const hostname = '::'
42
- // const hostname = '0.0.0.0'
43
-
44
- interface GetServerContext {
45
- config: Config
46
- logger?: Logger
47
- node?: NodeInstance
48
- }
49
-
50
- export async function getServer(params: GetServerContext) {
51
- const { config, node: providedNode } = params
52
- const { port } = params.config.api
53
- const { id: configuredChainId } = config.chain
54
-
55
- const logger = assertEx(params.logger, () => 'Logger is required to init server')
56
-
57
- const statusReporter = initStatusReporter({ logger })
58
-
59
- await startupSpanAsync('initHealthEndpoints', () => initHealthEndpoints({
60
- config, logger, statusReporter,
61
- }))
62
-
63
- const telemetryConfig = buildTelemetryConfig(config, 'xl1-api', '1.0.0', DefaultMetricsScrapePorts.api)
64
-
65
- const { traceProvider, meterProvider } = await startupSpanAsync('initTelemetry', () => initTelemetry(telemetryConfig))
66
-
67
- const initContext = {
68
- _id: 'init-context',
69
- config,
70
- logger,
71
- statusReporter,
72
- timeBudgetLimit: 1000,
73
- meterProvider,
74
- traceProvider,
75
- singletons: {},
76
- caches: {},
77
- }
78
-
79
- const wallet = await initApiWallet(initContext)
80
-
81
- const balancesSummaryMap = assertEx(await initBalanceSummaryMap(initContext), () => 'Balance Summary Map not initialized')
82
- const transfersSummaryMap = assertEx(await initTransferSummaryMap(initContext), () => 'Transfer Summary Map not initialized')
83
-
84
- const {
85
- node, writableChainArchivist, readonlyChainArchivist, pendingTransactionsArchivist, pendingBlocksArchivist,
86
- } = await initServerNode({
87
- ...initContext,
88
- wallet,
89
- node: providedNode,
90
- transfersSummaryMap,
91
- balancesSummaryMap,
92
- })
93
-
94
- await writableChainArchivist.start()
95
- await readonlyChainArchivist.start()
96
- await pendingTransactionsArchivist.start()
97
- await pendingBlocksArchivist.start()
98
-
99
- const possibleHead = await findMostRecentBlock(readonlyChainArchivist)
100
- if (configuredChainId && possibleHead && possibleHead.chain !== configuredChainId) {
101
- throw new Error(`Configured chain ID (${configuredChainId}) does not match the existing chain ID (${possibleHead.chain})`)
102
- }
103
-
104
- let possibleChainId: ChainId | undefined = configuredChainId
105
-
106
- // if there is no configured chain ID and no head, create a new chain
107
- if (!possibleHead) {
108
- possibleChainId = possibleChainId ?? (await Account.random()).address
109
- // If there is no head, create one
110
- const chain = await createBootstrapHead(
111
- wallet,
112
- possibleChainId,
113
- asAttoXL1(20_000_000_000_000_000_000_000n),
114
- config.chain.genesisRewardAddress ?? wallet.address,
115
- )
116
- const payloads = chain.flatMap(block => flattenHydratedBlock(block))
117
- await writableChainArchivist.insert(payloads)
118
- }
119
-
120
- const head = possibleHead ?? assertEx(await findMostRecentBlock(readonlyChainArchivist), () => 'No blocks found in chain archivist')
121
- const chainId = assertEx(possibleChainId, () => 'Chain ID could not be determined')
122
- assertEx(head.chain === chainId, () => 'Chain ID does not match head block chain ID [init]')
123
-
124
- const mods = await node.resolve('*')
125
- await Promise.all(mods.map((mod) => {
126
- return mod.start?.() ?? (() => true)
127
- }))
128
-
129
- const chainMap = payloadMapFromStore<WithStorageMeta<Payload>>(writableChainArchivist)
130
-
131
- const balanceSummaryContext = {
132
- ...initContext,
133
- stepSemaphores: StepSizes.map(() => new Semaphore(20)),
134
- summaryMap: balancesSummaryMap,
135
- head: async function (): Promise<[Hash, number]> {
136
- const head = assertEx(await findMostRecentBlock(writableChainArchivist))
137
- assertEx(head.chain === chainId, () => 'Chain ID does not match head block chain ID [balanceSummaryContext]')
138
- return [head._hash, head.block]
139
- },
140
- store: { chainMap },
141
- chainId,
142
- } satisfies BalanceStepSummaryContext
143
-
144
- const transfersSummaryContext = {
145
- ...initContext,
146
- stepSemaphores: StepSizes.map(() => new Semaphore(20)),
147
- summaryMap: transfersSummaryMap,
148
- head: async function (): Promise<[Hash, number]> {
149
- const head = assertEx(await findMostRecentBlock(writableChainArchivist))
150
- assertEx(head.chain === chainId, () => 'Chain ID does not match head block chain ID [transfersSummaryContext]')
151
- return [head._hash, head.block]
152
- },
153
- store: { chainMap },
154
- chainId,
155
- } satisfies TransfersStepSummaryContext
156
-
157
- const locator = buildLocalProviderLocator({
158
- context: initContext,
159
- finalizedArchivist: writableChainArchivist,
160
- pendingTransactionsArchivist,
161
- pendingBlocksArchivist,
162
- balanceSummaryContext,
163
- transfersSummaryContext,
164
- node,
165
- chainId,
166
- })
167
-
168
- locator.register(SimpleBlockValidationViewer.factory<SimpleBlockValidationViewer>(
169
- SimpleBlockValidationViewer.dependencies,
170
- { state: validateHydratedBlockState, protocol: validateHydratedBlock },
171
- ))
172
-
173
- // Conditionally register ETH viewers if enabled in config
174
- if (canUseEvmProvider({ config })) {
175
- const provider = await initEvmProvider({ config, logger })
176
- const contractAddress = assertEx(config.chain.id, () => 'Missing config.chain.chainId') as string
177
- // Connect to the contract
178
- const contract = IStakedXyoChain__factory.connect(toEthAddress(contractAddress), provider)
179
-
180
- // Register the contract events viewer
181
- locator.register(EvmStakeEventsViewer.factory<EvmStakeEventsViewer>(
182
- EvmStakeEventsViewer.dependencies,
183
- { contract },
184
- ))
185
-
186
- // Get an instance of the events viewer to pass to the stake viewer
187
- const stakeEventsViewer = (await locator.getInstance<EvmStakeEventsViewer>(EvmStakeEventsViewer.defaultMoniker))
188
- assertEx(await stakeEventsViewer.start(), () => 'Failed to start EvmStakeEventsViewer')
189
-
190
- // Register the stake viewer
191
- locator.register(EvmStakeViewer.factory<EvmStakeViewer>(
192
- EvmStakeViewer.dependencies,
193
- { contract, stakeEventsViewer },
194
- ))
195
-
196
- // Register the contract viewer
197
- locator.register(EvmChainContractViewer.factory<EvmChainContractViewer>(
198
- EvmChainContractViewer.dependencies,
199
- { address: asAddress(contractAddress, true), runner: provider },
200
- ))
201
-
202
- // Register the contract viewer
203
- locator.register(SimpleTimeSyncViewer.factory<SimpleTimeSyncViewer>(
204
- SimpleTimeSyncViewer.dependencies,
205
- { ethProvider: provider },
206
- ))
207
- }
208
-
209
- const apiContext = {
210
- ...initContext,
211
- node,
212
- transfersSummaryMap,
213
- balancesSummaryMap,
214
- ...locator.context,
215
- _id: 'api-context',
216
- } satisfies ApiContext
217
-
218
- const blockViewer = (await locator.getInstance<BlockViewer>(BlockViewerMoniker))
219
- assertEx(await blockViewer.start(), () => 'Failed to start BlockViewer')
220
-
221
- const blk = await blockViewer.currentBlock()
222
- assertEx(blk, () => 'No blocks found after initialization')
223
-
224
- const accountBalanceViewer = (await locator.getInstance<AccountBalanceViewer>(AccountBalanceViewerMoniker))
225
- assertEx(await accountBalanceViewer.start(), () => 'Failed to start AccountBalanceViewer')
226
-
227
- const xyoViewer = (await locator.getInstance<XyoViewer>(XyoViewerMoniker))
228
- assertEx(await xyoViewer.start(), () => 'Failed to start XyoViewer')
229
-
230
- const mempoolViewer = (await locator.getInstance<MempoolViewer>(MempoolViewerMoniker))
231
- assertEx(await mempoolViewer.start(), () => 'Failed to start MempoolViewer')
232
-
233
- const mempoolRunner = (await locator.getInstance<MempoolRunner>(MempoolRunnerMoniker))
234
- assertEx(await mempoolRunner.start(), () => 'Failed to start MempoolRunner')
235
-
236
- console.info(`[API] Current block after initialization: #${blk[0].block} (${blk[0]._hash})`)
237
-
238
- const validatorActor = config.mempool.enabled
239
- ? undefined
240
- : await ValidatorActor.create({
241
- id: 'validator-mempool-server',
242
- account: wallet,
243
- context: locator.context,
244
- finalizedArchivist: writableChainArchivist,
245
- mempoolViewer,
246
- blockViewer,
247
- } satisfies ValidatorActorParams)
248
-
249
- await validatorActor?.start()
250
-
251
- const mempoolActor = config.mempool.enabled
252
- ? undefined
253
- : await MempoolActor.create({
254
- id: 'mempool-mempool-server',
255
- account: wallet,
256
- context: locator.context,
257
- mempoolRunner,
258
- pendingBlocksArchivist,
259
- pendingTransactionsArchivist,
260
- } satisfies MempoolActorParams)
261
5
 
262
- await mempoolActor?.start()
6
+ export async function getServer(context: ApiContext) {
7
+ const { logger } = context
8
+ const { port } = context.config.actors.api
263
9
 
264
- const app = await getApp(apiContext)
10
+ const app = await getApp(context)
265
11
  const server = app.listen(port, hostname, () => logger?.log(`[API] Server listening at http://${hostname}:${port}`))
266
12
  server.setTimeout(20_000)
267
13
  return server