@xyo-network/xl1-cli 1.22.0 → 1.23.0

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/README.md CHANGED
@@ -115,6 +115,257 @@ Create a `xyo.config.json` (or .js, .yaml) file in the working directory to defi
115
115
  }
116
116
  ```
117
117
 
118
+ ## Deployment configurations
119
+
120
+ `xl1` actors can be assembled into many physical layouts: one process running everything, one process per actor, or grouped processes sharing one config. This section covers the actors, the dimensions you choose between, and a copy-paste recipe for each supported topology.
121
+
122
+ ### Actors
123
+
124
+ | Actor | Role |
125
+ |---|---|
126
+ | `api` | JSON-RPC gateway. Serves block / balance / transaction queries and accepts transfers. |
127
+ | `producer` | Block producer. Drives heartbeat blocks and packages mempool transactions. |
128
+ | `finalizer` | Selects a chain head from competing producer candidates and writes finalizations. |
129
+ | `mempool` | Holds pending transactions until the producer pulls them. |
130
+ | `bridge` | EVM bridge — relays deposits / withdrawals between XL1 and an EVM chain. |
131
+ | `rewardRedemption` | Claims block rewards for the producer's account. |
132
+
133
+ `xl1 start <actor> [actor ...]` runs any subset in one process. With no positional args it defaults to `api producer finalizer`.
134
+
135
+ ### Dimensions
136
+
137
+ You make four independent choices when deploying:
138
+
139
+ 1. **Process layout** — mono (everything in one process), split (one actor per process), or grouped (custom).
140
+ 2. **Storage backing** — `memory` (single-process only, ephemeral), `lmdb` (single-host, persistent, multi-process safe via shared root), or `mongodb` (multi-host, persistent, multi-process safe).
141
+ 3. **Provider tier** — `simple` (in-process tier 1, requires the corresponding backing), or `jsonrpc` (tier 3 proxy to another `xl1` process). The CLI picks `jsonrpc` automatically when the global `remote.rpc` is set; otherwise it picks `simple` when the backing is available.
142
+ 4. **Config layout** — single file shared across all processes (each `xl1 start <subset>` filters which actors it activates), one file per process, or pure environment variables.
143
+
144
+ ### Recipes
145
+
146
+ Every recipe shows a JSON config file and the command(s) to launch it. Configs use `xyo.json` (cosmiconfig also accepts `xyo.yaml`, `xyo.toml`, `xyo.js`, etc.); the CLI auto-discovers a `xyo.*` file in the current directory or accepts an explicit `-c <path>`.
147
+
148
+ #### Single process, in-memory (dev)
149
+
150
+ Fastest path for local development. Everything runs in one node process; state is lost when the process exits.
151
+
152
+ `xyo.json`:
153
+ ```json
154
+ {
155
+ "xl1": {
156
+ "actors": [
157
+ { "name": "api", "host": "localhost", "port": 8080 },
158
+ { "name": "mempool" },
159
+ { "name": "finalizer" }
160
+ ]
161
+ }
162
+ }
163
+ ```
164
+
165
+ ```sh
166
+ xl1 start api mempool finalizer
167
+ ```
168
+
169
+ The `api + mempool + finalizer` subset is the canary combo: the CLI builds a single shared provider registry for the three actors so each provider is instantiated exactly once, with no cross-actor duplication.
170
+
171
+ #### Single process, LMDB (single-host persistent)
172
+
173
+ Persistent state on one machine. LMDB writes are multi-process safe via the LMDB lockfile, so you can later split actors across processes against the same `storage.root`.
174
+
175
+ `xyo.json`:
176
+ ```json
177
+ {
178
+ "xl1": {
179
+ "storage": { "root": "/var/xl1/data" },
180
+ "actors": [
181
+ { "name": "api", "host": "localhost", "port": 8080 },
182
+ { "name": "producer", "heartbeatInterval": 1000 },
183
+ { "name": "finalizer" },
184
+ { "name": "mempool" }
185
+ ]
186
+ }
187
+ }
188
+ ```
189
+
190
+ ```sh
191
+ xl1 start api producer finalizer mempool
192
+ ```
193
+
194
+ #### Single process, MongoDB (single-host with shared DB)
195
+
196
+ Same as the LMDB variant but with a MongoDB-backed archivist. Use this when state needs to outlive any one host or be shared with off-chain tooling that already speaks Mongo.
197
+
198
+ `xyo.json`:
199
+ ```json
200
+ {
201
+ "xl1": {
202
+ "storage": {
203
+ "mongo": {
204
+ "connectionString": "mongodb://user:pass@db.internal:27017",
205
+ "database": "xl1",
206
+ "domain": "internal"
207
+ }
208
+ },
209
+ "actors": [
210
+ { "name": "api", "host": "localhost", "port": 8080 },
211
+ { "name": "producer", "heartbeatInterval": 1000 },
212
+ { "name": "finalizer" },
213
+ { "name": "mempool" }
214
+ ]
215
+ }
216
+ }
217
+ ```
218
+
219
+ ```sh
220
+ xl1 start api producer finalizer mempool
221
+ ```
222
+
223
+ #### Multi-process, shared LMDB (one host, role-isolated)
224
+
225
+ Each actor runs as its own OS process. Useful when you want to restart one role independently or pin different actors to different cores. Every process loads the same config file and uses `xl1 start <name>` to activate just its slice.
226
+
227
+ `xyo.json` (single file, all processes load it):
228
+ ```json
229
+ {
230
+ "xl1": {
231
+ "storage": { "root": "/var/xl1/data" },
232
+ "actors": [
233
+ { "name": "api", "host": "localhost", "port": 8080 },
234
+ { "name": "producer", "heartbeatInterval": 1000 },
235
+ { "name": "finalizer" },
236
+ { "name": "mempool", "host": "localhost", "port": 8081 }
237
+ ]
238
+ }
239
+ }
240
+ ```
241
+
242
+ ```sh
243
+ # Each line is a separate process (e.g., one systemd unit per actor)
244
+ xl1 start api
245
+ xl1 start producer
246
+ xl1 start finalizer
247
+ xl1 start mempool
248
+ ```
249
+
250
+ #### Multi-process, shared MongoDB (multi-host, durable)
251
+
252
+ Same as above but with MongoDB as the shared store. Now each process can run on a different host, since MongoDB takes care of cross-host coordination.
253
+
254
+ `xyo.json`:
255
+ ```json
256
+ {
257
+ "xl1": {
258
+ "storage": {
259
+ "mongo": {
260
+ "connectionString": "mongodb://user:pass@db.internal:27017",
261
+ "database": "xl1",
262
+ "domain": "internal"
263
+ }
264
+ },
265
+ "actors": [
266
+ { "name": "api", "host": "0.0.0.0", "port": 8080 },
267
+ { "name": "producer", "heartbeatInterval": 1000 },
268
+ { "name": "finalizer" },
269
+ { "name": "mempool", "host": "0.0.0.0", "port": 8081 }
270
+ ]
271
+ }
272
+ }
273
+ ```
274
+
275
+ ```sh
276
+ # On host A
277
+ xl1 start api
278
+
279
+ # On host B
280
+ xl1 start producer
281
+
282
+ # On host C
283
+ xl1 start finalizer mempool
284
+ ```
285
+
286
+ #### Stateless API client (read-only proxy to a remote chain)
287
+
288
+ The API actor in `stateless: true` mode owns no local store. All viewer providers resolve to JsonRpc proxies pointed at `remote.rpc`. Run several stateless API instances behind a load balancer to scale read traffic without duplicating state.
289
+
290
+ `xyo.json`:
291
+ ```json
292
+ {
293
+ "xl1": {
294
+ "remote": { "rpc": { "protocol": "https", "url": "https://chain.example.com/rpc" } },
295
+ "actors": [
296
+ { "name": "api", "host": "0.0.0.0", "port": 8080, "stateless": true }
297
+ ]
298
+ }
299
+ }
300
+ ```
301
+
302
+ ```sh
303
+ xl1 start api
304
+ ```
305
+
306
+ #### Pure environment variables (no config file)
307
+
308
+ Every config key has a `XL1_*` env var equivalent. Use double-underscore for nested keys and numeric indices for array entries — useful in container orchestration where you'd rather not mount a file.
309
+
310
+ ```sh
311
+ export XL1_STORAGE__ROOT=/var/xl1/data
312
+ export XL1_ACTORS__0__NAME=api
313
+ export XL1_ACTORS__0__HOST=localhost
314
+ export XL1_ACTORS__0__PORT=8080
315
+ export XL1_ACTORS__1__NAME=producer
316
+ export XL1_ACTORS__1__HEARTBEAT_INTERVAL=1000
317
+ export XL1_ACTORS__2__NAME=finalizer
318
+ xl1 start api producer finalizer
319
+ ```
320
+
321
+ #### One config file per process
322
+
323
+ When per-process config needs to live in different config-management systems (Kubernetes secrets vs ConfigMaps, separate Vault paths, etc.), give each process its own file with `-c`.
324
+
325
+ `xyo.api.json`:
326
+ ```json
327
+ { "xl1": { "storage": { "root": "/var/xl1/data" }, "actors": [{ "name": "api", "host": "localhost", "port": 8080 }] } }
328
+ ```
329
+
330
+ `xyo.producer.json`:
331
+ ```json
332
+ { "xl1": { "storage": { "root": "/var/xl1/data" }, "actors": [{ "name": "producer", "heartbeatInterval": 1000 }] } }
333
+ ```
334
+
335
+ ```sh
336
+ xl1 -c ./xyo.api.json start api
337
+ xl1 -c ./xyo.producer.json start producer
338
+ ```
339
+
340
+ ### Mnemonics & wallets
341
+
342
+ The root `mnemonic` field (or `XL1_MNEMONIC`) defines the wallet from which every actor derives an account at `accountPath`. Per-actor `mnemonic` fields are rejected — use `accountPath` to give each actor a distinct derivation.
343
+
344
+ ```json
345
+ {
346
+ "xl1": {
347
+ "mnemonic": "edit hill neutral usage share kite knee abandon slim open lottery abandon",
348
+ "actors": [
349
+ { "name": "producer", "accountPath": "0" },
350
+ { "name": "finalizer", "accountPath": "1" }
351
+ ]
352
+ }
353
+ }
354
+ ```
355
+
356
+ If you omit `mnemonic` entirely, the CLI falls back to a built-in dev mnemonic and pauses for an interactive RETURN before starting. Pass `--skip-insecure-confirm` to bypass the prompt in non-interactive deployments — but never deploy production traffic against the dev mnemonic.
357
+
358
+ ### Inspecting a configuration
359
+
360
+ Two CLI flags help you verify what the chain *would* do without actually starting it:
361
+
362
+ - `xl1 --dump-config start <actors>` — prints the fully resolved config (file + env + CLI flags merged, defaults applied) to stdout, then exits. Secret-bearing fields are redacted by default; pass `--with-secrets` on a developer box to see raw values.
363
+ - `xl1 --dump-providers start <actors>` — runs the locator construction up to the point where actor runners would start, then prints a per-actor tree of every registered provider (implementation class, scope, dependencies). Cross-actor duplicates are flagged with `⚠ also in: ...`. Use this to confirm that, e.g., your stateless API actually picked the JsonRpc tier-3 viewers.
364
+
365
+ ```sh
366
+ xl1 -c ./xyo.json --dump-providers start api producer
367
+ ```
368
+
118
369
  ## License
119
370
 
120
371
  See the [LICENSE](LICENSE) file for license rights and limitations (LGPL-3.0-only).