@xyo-network/xl1-cli-lib 1.20.5 → 1.20.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/node/commands/api/apiCommand.d.ts +5 -0
- package/dist/node/commands/api/apiCommand.d.ts.map +1 -0
- package/dist/node/commands/api/index.d.ts +2 -0
- package/dist/node/commands/api/index.d.ts.map +1 -0
- package/dist/node/commands/bridge/bridgeCommand.d.ts +5 -0
- package/dist/node/commands/bridge/bridgeCommand.d.ts.map +1 -0
- package/dist/node/commands/bridge/index.d.ts +1 -0
- package/dist/node/commands/bridge/index.d.ts.map +1 -1
- package/dist/node/commands/index.d.ts +6 -0
- package/dist/node/commands/index.d.ts.map +1 -1
- package/dist/node/commands/mempool/index.d.ts +2 -0
- package/dist/node/commands/mempool/index.d.ts.map +1 -0
- package/dist/node/commands/mempool/mempoolCommand.d.ts +5 -0
- package/dist/node/commands/mempool/mempoolCommand.d.ts.map +1 -0
- package/dist/node/commands/producer/index.d.ts +2 -0
- package/dist/node/commands/producer/index.d.ts.map +1 -0
- package/dist/node/commands/producer/producerCommand.d.ts +5 -0
- package/dist/node/commands/producer/producerCommand.d.ts.map +1 -0
- package/dist/node/commands/rewardRedemption/index.d.ts +1 -0
- package/dist/node/commands/rewardRedemption/index.d.ts.map +1 -1
- package/dist/node/commands/rewardRedemption/rewardRedemptionCommand.d.ts +5 -0
- package/dist/node/commands/rewardRedemption/rewardRedemptionCommand.d.ts.map +1 -0
- package/dist/node/commands/start/index.d.ts +2 -0
- package/dist/node/commands/start/index.d.ts.map +1 -0
- package/dist/node/commands/start/startCommand.d.ts +5 -0
- package/dist/node/commands/start/startCommand.d.ts.map +1 -0
- package/dist/node/commands/types.d.ts +8 -0
- package/dist/node/commands/types.d.ts.map +1 -0
- package/dist/node/commands/withDeprecationWarning.d.ts +3 -0
- package/dist/node/commands/withDeprecationWarning.d.ts.map +1 -0
- package/dist/node/configMiddleware.d.ts +3 -0
- package/dist/node/configMiddleware.d.ts.map +1 -0
- package/dist/node/index.d.ts +1 -0
- package/dist/node/index.d.ts.map +1 -1
- package/dist/node/index.mjs +351 -176
- package/dist/node/index.mjs.map +1 -1
- package/dist/node/runCLI.d.ts.map +1 -1
- package/dist/node/xl1.mjs +350 -176
- package/dist/node/xl1.mjs.map +1 -1
- package/package.json +16 -27
- package/src/commands/api/apiCommand.ts +39 -0
- package/src/commands/api/index.ts +1 -0
- package/src/commands/bridge/bridgeCommand.ts +19 -0
- package/src/commands/bridge/index.ts +1 -0
- package/src/commands/index.ts +6 -0
- package/src/commands/mempool/index.ts +1 -0
- package/src/commands/mempool/mempoolCommand.ts +19 -0
- package/src/commands/producer/index.ts +1 -0
- package/src/commands/producer/producerCommand.ts +19 -0
- package/src/commands/rewardRedemption/index.ts +1 -0
- package/src/commands/rewardRedemption/rewardRedemptionCommand.ts +19 -0
- package/src/commands/start/index.ts +1 -0
- package/src/commands/start/startCommand.ts +127 -0
- package/src/commands/types.ts +9 -0
- package/src/commands/withDeprecationWarning.ts +17 -0
- package/src/configMiddleware.ts +55 -0
- package/src/index.ts +1 -0
- package/src/runCLI.ts +31 -142
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { createDeepMerge } from '@xylabs/sdk-js'
|
|
2
|
+
import { tryParseConfig } from '@xyo-network/chain-orchestration'
|
|
3
|
+
import type { Config } from '@xyo-network/xl1-sdk'
|
|
4
|
+
import {
|
|
5
|
+
ConfigZod, isZodError, resolveConfig,
|
|
6
|
+
} from '@xyo-network/xl1-sdk'
|
|
7
|
+
|
|
8
|
+
const deepMerge = createDeepMerge({ arrayStrategy: 'concat' })
|
|
9
|
+
|
|
10
|
+
export async function configMiddleware(argv: Record<string, unknown>, setConfiguration: (config: Config) => void): Promise<void> {
|
|
11
|
+
try {
|
|
12
|
+
// Parse the various config sources
|
|
13
|
+
const configPath = argv.config as string | undefined
|
|
14
|
+
const parsedConfigFile = await tryParseConfig({ configPath }) // Config file
|
|
15
|
+
const parsedConfigArgs = ConfigZod.safeParse(argv).data ?? {} // Command-line arguments & ENV VARs
|
|
16
|
+
const parseResult = ConfigZod.safeParse(deepMerge(parsedConfigFile, parsedConfigArgs))
|
|
17
|
+
if (!parseResult.success) {
|
|
18
|
+
throw parseResult.error
|
|
19
|
+
}
|
|
20
|
+
// Deep merge with precedence
|
|
21
|
+
// TODO: Would like precedence to be defaults < file < ENV < CLI Args
|
|
22
|
+
// but there is currently no way to determine which are defaults vs
|
|
23
|
+
// user-supplied CLI Args since we set the CLI args to the defaults
|
|
24
|
+
// and receive a flattened object. We might need to manually invoke
|
|
25
|
+
// the parser without the defaults to achieve this.
|
|
26
|
+
// const mergedConfig = deepMerge(parsedConfigArgs, parsedConfigFile)
|
|
27
|
+
const mergedConfig = parseResult.data
|
|
28
|
+
const validatedMergedConfigResult = ConfigZod.safeParse(mergedConfig)
|
|
29
|
+
if (!validatedMergedConfigResult.success) {
|
|
30
|
+
throw validatedMergedConfigResult.error
|
|
31
|
+
}
|
|
32
|
+
const resolvedConfig = resolveConfig(validatedMergedConfigResult.data)
|
|
33
|
+
// Validate the merged configuration
|
|
34
|
+
const validatedConfigResult = ConfigZod.safeParse(resolvedConfig)
|
|
35
|
+
if (!validatedConfigResult.success) {
|
|
36
|
+
throw validatedConfigResult.error
|
|
37
|
+
}
|
|
38
|
+
setConfiguration(validatedConfigResult.data)
|
|
39
|
+
|
|
40
|
+
// Check if user wants to dump config and exit
|
|
41
|
+
if (argv['dump-config']) {
|
|
42
|
+
console.log(JSON.stringify(validatedConfigResult.data, null, 2))
|
|
43
|
+
// eslint-disable-next-line unicorn/no-process-exit
|
|
44
|
+
process.exit(0)
|
|
45
|
+
}
|
|
46
|
+
} catch (err) {
|
|
47
|
+
if (isZodError(err)) {
|
|
48
|
+
console.error(`Zod error: ${err.message}`)
|
|
49
|
+
} else {
|
|
50
|
+
console.error(`Error parsing configuration: ${err}`)
|
|
51
|
+
}
|
|
52
|
+
console.error(`Stack: ${err instanceof Error ? err.stack : 'N/A'}`)
|
|
53
|
+
throw new Error('Invalid configuration')
|
|
54
|
+
}
|
|
55
|
+
}
|
package/src/index.ts
CHANGED
package/src/runCLI.ts
CHANGED
|
@@ -1,28 +1,26 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { getApiActor, runApi } from '@xyo-network/chain-api'
|
|
3
|
-
import { getMempoolActor, runMempool } from '@xyo-network/chain-mempool'
|
|
1
|
+
import { isDefined } from '@xylabs/sdk-js'
|
|
4
2
|
import {
|
|
5
|
-
|
|
6
|
-
RewardRedemptionConfigZod, tryParseConfig,
|
|
7
|
-
ValidatorConfigZod,
|
|
3
|
+
contextFromConfigWithoutLocator, locatorsFromConfig, Orchestrator,
|
|
8
4
|
} from '@xyo-network/chain-orchestration'
|
|
9
|
-
import { runProducer } from '@xyo-network/chain-producer'
|
|
10
5
|
import type { ActorConfig, Config } from '@xyo-network/xl1-sdk'
|
|
11
|
-
import {
|
|
12
|
-
ActorConfigZod, ConfigZod, isZodError,
|
|
13
|
-
resolveConfig,
|
|
14
|
-
} from '@xyo-network/xl1-sdk'
|
|
6
|
+
import { ActorConfigZod, ConfigZod } from '@xyo-network/xl1-sdk'
|
|
15
7
|
import type { Argv } from 'yargs'
|
|
16
8
|
import yargs from 'yargs'
|
|
17
9
|
import { hideBin } from 'yargs/helpers'
|
|
18
10
|
|
|
19
11
|
import {
|
|
20
|
-
|
|
12
|
+
apiCommand,
|
|
13
|
+
bridgeCommand,
|
|
14
|
+
mempoolCommand,
|
|
15
|
+
producerCommand,
|
|
16
|
+
rewardRedemptionCommand,
|
|
17
|
+
startCommand,
|
|
18
|
+
withDeprecationWarning,
|
|
21
19
|
} from './commands/index.ts'
|
|
20
|
+
import { configMiddleware } from './configMiddleware.ts'
|
|
22
21
|
import { XL1LogoColorizedAscii } from './images.ts'
|
|
23
22
|
import { initLogger } from './initLogger.ts'
|
|
24
23
|
import { optionsFromGlobalZodRegistry } from './optionsFromGlobalZodRegistry.ts'
|
|
25
|
-
import { waitForHostPort } from './waitForHostPort.ts'
|
|
26
24
|
|
|
27
25
|
/** Version string injected by Rollup at build time. */
|
|
28
26
|
declare const __VERSION__: string
|
|
@@ -36,23 +34,23 @@ let configuration: Config
|
|
|
36
34
|
|
|
37
35
|
const version = isDefined(__VERSION__) ? __VERSION__ : 'unknown'
|
|
38
36
|
|
|
39
|
-
|
|
37
|
+
function getConfiguration(): Config {
|
|
38
|
+
return configuration
|
|
39
|
+
}
|
|
40
40
|
|
|
41
41
|
async function getLocatorsFromConfig(actors: string[], configuration: Config) {
|
|
42
42
|
const actorConfigs: ActorConfig[] = []
|
|
43
43
|
for (const actorName of actors) {
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
const existingConfig = configuration.actors.find(actor => actor.name === actorName)
|
|
45
|
+
if (existingConfig) {
|
|
46
|
+
actorConfigs.push(existingConfig)
|
|
47
|
+
} else {
|
|
48
|
+
const actorConfig = ActorConfigZod.loose().parse({ name: actorName })
|
|
49
|
+
actorConfigs.push(actorConfig)
|
|
50
|
+
}
|
|
47
51
|
}
|
|
48
52
|
|
|
49
|
-
|
|
50
|
-
const config = ConfigZod.parse(deepMerge(configuration, { actors: actorConfigs }))
|
|
51
|
-
const actorList = [...new Set([...config.actors.map(actor => actor.name), ...actorConfigs.map(actor => actor.name)])]
|
|
52
|
-
config.actors = actorList.map(actorName => ActorConfigZod.loose().parse(deepMerge(
|
|
53
|
-
(config.actors.find(actor => actor.name === actorName) ?? {}),
|
|
54
|
-
(actorConfigs.find(actor => actor.name === actorName) ?? {}),
|
|
55
|
-
)))
|
|
53
|
+
const config = ConfigZod.parse({ ...configuration, actors: actorConfigs })
|
|
56
54
|
|
|
57
55
|
const logger = initLogger(configuration)
|
|
58
56
|
const orchestrator = await Orchestrator.create({ logger })
|
|
@@ -95,127 +93,18 @@ $0 <command> [options]`)
|
|
|
95
93
|
.env('XL1')
|
|
96
94
|
.scriptName('xl1')
|
|
97
95
|
.middleware(async (argv) => {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
const parsedConfigFile = await tryParseConfig({ configPath }) // Config file
|
|
102
|
-
const parsedConfigArgs = ConfigZod.safeParse(argv).data ?? {} // Command-line arguments & ENV VARs
|
|
103
|
-
const parseResult = ConfigZod.safeParse(deepMerge(parsedConfigFile, parsedConfigArgs))
|
|
104
|
-
if (!parseResult.success) {
|
|
105
|
-
throw parseResult.error
|
|
106
|
-
}
|
|
107
|
-
// Deep merge with precedence
|
|
108
|
-
// TODO: Would like precedence to be defaults < file < ENV < CLI Args
|
|
109
|
-
// but there is currently no way to determine which are defaults vs
|
|
110
|
-
// user-supplied CLI Args since we set the CLI args to the defaults
|
|
111
|
-
// and receive a flattened object. We might need to manually invoke
|
|
112
|
-
// the parser without the defaults to achieve this.
|
|
113
|
-
// const mergedConfig = deepMerge(parsedConfigArgs, parsedConfigFile)
|
|
114
|
-
const mergedConfig = parseResult.data
|
|
115
|
-
const validatedMergedConfigResult = ConfigZod.safeParse(mergedConfig)
|
|
116
|
-
if (!validatedMergedConfigResult.success) {
|
|
117
|
-
throw validatedMergedConfigResult.error
|
|
118
|
-
}
|
|
119
|
-
const resolvedConfig = resolveConfig(validatedMergedConfigResult.data)
|
|
120
|
-
// Validate the merged configuration
|
|
121
|
-
const validatedConfigResult = ConfigZod.safeParse(resolvedConfig)
|
|
122
|
-
if (!validatedConfigResult.success) {
|
|
123
|
-
throw validatedConfigResult.error
|
|
124
|
-
}
|
|
125
|
-
configuration = validatedConfigResult.data
|
|
126
|
-
|
|
127
|
-
// Check if user wants to dump config and exit
|
|
128
|
-
if (argv['dump-config']) {
|
|
129
|
-
console.log(JSON.stringify(configuration, null, 2))
|
|
130
|
-
// eslint-disable-next-line unicorn/no-process-exit
|
|
131
|
-
process.exit(0)
|
|
132
|
-
}
|
|
133
|
-
} catch (err) {
|
|
134
|
-
if (isZodError(err)) {
|
|
135
|
-
console.error(`Zod error: ${err.message}`)
|
|
136
|
-
} else {
|
|
137
|
-
console.error(`Error parsing configuration: ${err}`)
|
|
138
|
-
}
|
|
139
|
-
console.error(`Stack: ${err instanceof Error ? err.stack : 'N/A'}`)
|
|
140
|
-
throw new Error('Invalid configuration')
|
|
141
|
-
}
|
|
96
|
+
await configMiddleware(argv, (config) => {
|
|
97
|
+
configuration = config
|
|
98
|
+
})
|
|
142
99
|
})
|
|
143
100
|
.options(optionsFromGlobalZodRegistry())
|
|
144
|
-
// .commandDir('./command/commands', opts) // Not yet supported for ESM
|
|
145
101
|
.wrap(y.terminalWidth())
|
|
146
|
-
.command(
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
locators['api'],
|
|
153
|
-
), getMempoolActor(
|
|
154
|
-
MempoolConfigZod.parse(locators['mempool'].context.config),
|
|
155
|
-
locators['mempool'],
|
|
156
|
-
), getValidatorActor(
|
|
157
|
-
ValidatorConfigZod.parse(locators['validator'].context.config),
|
|
158
|
-
locators['validator'],
|
|
159
|
-
)])
|
|
160
|
-
|
|
161
|
-
for (const actor of actors) {
|
|
162
|
-
await orchestrator.registerActor(actor)
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
await orchestrator.start()
|
|
166
|
-
})
|
|
167
|
-
})
|
|
168
|
-
.command('bridge', 'Run a XL1 Bridge Node', (yargs) => {
|
|
169
|
-
return yargs
|
|
170
|
-
.command('$0', 'Run a XL1 Bridge Node', () => {}, async () => {
|
|
171
|
-
const { locators, orchestrator } = await getLocatorsFromConfig(['bridge'], configuration)
|
|
172
|
-
await runBridge(BridgeConfigZod.parse(locators['bridge'].context.config), orchestrator, locators['bridge'])
|
|
173
|
-
})
|
|
174
|
-
})
|
|
175
|
-
.command('mempool', 'Run a XL1 Mempool Node', (yargs) => {
|
|
176
|
-
return yargs
|
|
177
|
-
.command('$0', 'Run a XL1 Mempool Node', () => {}, async () => {
|
|
178
|
-
const { locators, orchestrator } = await getLocatorsFromConfig(['mempool'], configuration)
|
|
179
|
-
await runMempool(MempoolConfigZod.parse(locators['mempool'].context.config), orchestrator, locators['mempool'])
|
|
180
|
-
})
|
|
181
|
-
})
|
|
182
|
-
.command('producer', 'Run a XL1 Producer Node', (yargs) => {
|
|
183
|
-
return yargs
|
|
184
|
-
.command('$0', 'Run a XL1 Producer Node', () => {}, async () => {
|
|
185
|
-
const { locators, orchestrator } = await getLocatorsFromConfig(['producer'], configuration)
|
|
186
|
-
await runProducer(ProducerConfigZod.parse(locators['producer'].context.config), orchestrator, locators['producer'])
|
|
187
|
-
})
|
|
188
|
-
})
|
|
189
|
-
.command('reward-redemption-api', 'Run a XL1 Rewards Redemption API Node', (yargs) => {
|
|
190
|
-
return yargs
|
|
191
|
-
.command('$0', 'Run a XL1 Rewards Redemption API Node', () => {}, async () => {
|
|
192
|
-
const { locators, orchestrator } = await getLocatorsFromConfig(['rewardRedemption'], configuration)
|
|
193
|
-
await runRewardRedemptionApi(RewardRedemptionConfigZod.parse(locators['rewardRedemption'].context.config), orchestrator, locators['rewardRedemption'])
|
|
194
|
-
})
|
|
195
|
-
})
|
|
196
|
-
.command('$0', 'Run a full XL1 Node', () => {}, async () => {
|
|
197
|
-
const actors = ['producer', 'api']
|
|
198
|
-
const mempoolEnabled = configuration.actors.find(actor => actor.name === 'mempool')?.enabled
|
|
199
|
-
if (mempoolEnabled) {
|
|
200
|
-
actors.push('mempool')
|
|
201
|
-
}
|
|
202
|
-
const { locators, orchestrator } = await getLocatorsFromConfig(['api', 'producer'], configuration)
|
|
203
|
-
if (mempoolEnabled) {
|
|
204
|
-
const mempoolConfig = MempoolConfigZod.parse(locators['mempool'].context.config)
|
|
205
|
-
// Start Mempool but do not block
|
|
206
|
-
await runMempool(mempoolConfig, orchestrator, locators['mempool'])
|
|
207
|
-
// Wait for Mempool to be ready
|
|
208
|
-
await waitForHostPort(mempoolConfig.host, mempoolConfig.port)
|
|
209
|
-
}
|
|
210
|
-
// Start API but do not block
|
|
211
|
-
const apiConfig = ApiConfigZod.parse(locators['api'].context.config)
|
|
212
|
-
await runApi(apiConfig, orchestrator, locators['api'])
|
|
213
|
-
// Wait for API to be ready
|
|
214
|
-
await waitForHostPort(apiConfig.host, apiConfig.port)
|
|
215
|
-
// Start Producer and block on it
|
|
216
|
-
const producerConfig = ProducerConfigZod.parse(locators['producer'].context.config)
|
|
217
|
-
await runProducer(producerConfig, orchestrator, locators['producer'])
|
|
218
|
-
})
|
|
102
|
+
.command(withDeprecationWarning(apiCommand(getConfiguration, getLocatorsFromConfig)))
|
|
103
|
+
.command(withDeprecationWarning(bridgeCommand(getConfiguration, getLocatorsFromConfig)))
|
|
104
|
+
.command(withDeprecationWarning(mempoolCommand(getConfiguration, getLocatorsFromConfig)))
|
|
105
|
+
.command(withDeprecationWarning(producerCommand(getConfiguration, getLocatorsFromConfig)))
|
|
106
|
+
.command(withDeprecationWarning(rewardRedemptionCommand(getConfiguration, getLocatorsFromConfig)))
|
|
107
|
+
.command(startCommand(getConfiguration, getLocatorsFromConfig))
|
|
219
108
|
.options({
|
|
220
109
|
'config': {
|
|
221
110
|
type: 'string',
|