@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.
- package/dist/node/ApiActor.d.ts +13 -5
- package/dist/node/ApiActor.d.ts.map +1 -1
- package/dist/node/ApiContext.d.ts +1 -4
- package/dist/node/ApiContext.d.ts.map +1 -1
- package/dist/node/helpers/index.d.ts +0 -1
- package/dist/node/helpers/index.d.ts.map +1 -1
- package/dist/node/index.mjs +62 -124
- package/dist/node/index.mjs.map +1 -1
- package/dist/node/runApi.d.ts +2 -3
- package/dist/node/runApi.d.ts.map +1 -1
- package/dist/node/server/index.d.ts +1 -0
- package/dist/node/server/index.d.ts.map +1 -1
- package/dist/node/server/initApiParams.d.ts +12 -0
- package/dist/node/server/initApiParams.d.ts.map +1 -0
- package/dist/node/server/server.d.ts +2 -10
- package/dist/node/server/server.d.ts.map +1 -1
- package/package.json +14 -17
- package/src/ApiActor.ts +32 -10
- package/src/ApiContext.ts +1 -7
- package/src/helpers/index.ts +0 -1
- package/src/runApi.ts +8 -13
- package/src/server/index.ts +1 -0
- package/src/server/initApiParams.ts +170 -0
- package/src/server/server.ts +4 -258
- package/dist/node/helpers/initEvmProvider.d.ts +0 -11
- package/dist/node/helpers/initEvmProvider.d.ts.map +0 -1
- package/src/helpers/initEvmProvider.ts +0 -23
|
@@ -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 {
|
|
2
|
-
|
|
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":"
|
|
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.
|
|
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.
|
|
56
|
-
"@xylabs/sdk-js": "~5.0.
|
|
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-
|
|
61
|
-
"@xyo-network/chain-
|
|
62
|
-
"@xyo-network/chain-
|
|
63
|
-
"@xyo-network/chain-
|
|
64
|
-
"@xyo-network/chain-
|
|
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/
|
|
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.
|
|
86
|
-
"@xylabs/sdk-js": "~5.0.
|
|
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.
|
|
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.
|
|
99
|
-
"dotenv": "~17.2.
|
|
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 {
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
26
|
-
|
|
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(
|
|
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 {
|
|
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
|
}
|
package/src/helpers/index.ts
CHANGED
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,
|
|
15
|
+
config, orchestrator, ...params
|
|
18
16
|
}: RunApiContext) => {
|
|
19
|
-
const
|
|
17
|
+
const logger = new IdLogger(params.logger ?? console, () => 'API')
|
|
20
18
|
const account = await Account.random()
|
|
21
|
-
|
|
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) {
|
package/src/server/index.ts
CHANGED
|
@@ -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
|
+
}
|
package/src/server/server.ts
CHANGED
|
@@ -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
|
-
|
|
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(
|
|
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
|