@xyo-network/xl1-cli 3.0.1 → 3.0.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.
- package/README.md +906 -120
- package/dist/cli-min.mjs +30202 -29693
- package/dist/cli-min.mjs.map +1 -1
- package/package.json +51 -51
package/README.md
CHANGED
|
@@ -76,50 +76,51 @@ Starts only the Producer Node, which is responsible for block production.
|
|
|
76
76
|
|
|
77
77
|
Use `xl1 --help` for available options and configuration flags.
|
|
78
78
|
|
|
79
|
-
|
|
79
|
+
## Configuration
|
|
80
80
|
|
|
81
|
-
|
|
81
|
+
You can configure `xl1` using CLI flags, environment variables, or a configuration file. CLI flags override environment variables, which override config file values.
|
|
82
82
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
Configuration
|
|
86
|
-
|
|
87
|
-
You can configure xl1 using CLI flags, environment variables, or a configuration file. All methods are optional and can be combined—CLI flags override environment variables, which override config file values.
|
|
88
|
-
|
|
89
|
-
#### CLI Flags
|
|
90
|
-
|
|
91
|
-
Pass options directly when running a command. For example:
|
|
83
|
+
### CLI flags
|
|
92
84
|
|
|
93
85
|
```sh
|
|
94
|
-
xl1 --logLevel=info
|
|
86
|
+
xl1 --log.logLevel=info start api
|
|
95
87
|
```
|
|
96
88
|
|
|
97
|
-
|
|
89
|
+
### Environment variables
|
|
98
90
|
|
|
99
|
-
|
|
91
|
+
`XL1_*` variables map to the config shape with double-underscore nesting (`XL1_CONNECTIONS__LOCAL_STORE__ROOT`, etc.; see `.env.example`).
|
|
100
92
|
|
|
101
93
|
```sh
|
|
102
|
-
export
|
|
103
|
-
export
|
|
104
|
-
|
|
94
|
+
export XL1_LOG__LOG_LEVEL=info
|
|
95
|
+
export XL1_ACTORS__0__NAME=api
|
|
96
|
+
export XL1_ACTORS__0__PORT=8080
|
|
97
|
+
xl1 start api
|
|
105
98
|
```
|
|
106
99
|
|
|
107
|
-
|
|
100
|
+
### Config file
|
|
108
101
|
|
|
109
|
-
Create a `xyo.config.json` (
|
|
102
|
+
Create a `xyo.config.json` (cosmiconfig also accepts `xyo.yaml`, `xyo.toml`, `xyo.js`, etc.) with an `xl1` section. Omit `-c` to search the current directory, or pass `-c <path>` explicitly.
|
|
110
103
|
|
|
111
104
|
```json
|
|
112
105
|
{
|
|
113
|
-
"
|
|
114
|
-
|
|
115
|
-
|
|
106
|
+
"xl1": {
|
|
107
|
+
"connections": {
|
|
108
|
+
"local-store": { "type": "lmdb", "root": ".store" }
|
|
109
|
+
},
|
|
110
|
+
"actors": [
|
|
111
|
+
{ "name": "api", "host": "localhost", "port": 8080 },
|
|
112
|
+
{ "name": "producer" },
|
|
113
|
+
{ "name": "finalizer" }
|
|
114
|
+
]
|
|
116
115
|
}
|
|
117
116
|
}
|
|
118
117
|
```
|
|
119
118
|
|
|
120
|
-
|
|
119
|
+
Runnable `xyo.json`-style configs for XL1 3.0 declare every backing store, RPC endpoint, EVM RPC, and S3 bucket under `connections`. The pre-3.0 `storage`, `remote`, `transports`, and `evm.jsonRpc` / `evm.infura` fields are no longer supported. A remote API is reached with a `default-rpc` connection of `type: "rpc"`, not the old `remote.rpc`.
|
|
121
120
|
|
|
122
|
-
|
|
121
|
+
## Deployment guide
|
|
122
|
+
|
|
123
|
+
`xl1` actors can be assembled into many physical layouts: one process running everything, one process per actor, or grouped processes sharing one config.
|
|
123
124
|
|
|
124
125
|
### Actors
|
|
125
126
|
|
|
@@ -137,125 +138,458 @@ Create a `xyo.config.json` (or .js, .yaml) file in the working directory to defi
|
|
|
137
138
|
|
|
138
139
|
### Dimensions
|
|
139
140
|
|
|
140
|
-
You make four independent choices when deploying:
|
|
141
|
-
|
|
142
141
|
1. **Process layout** — mono (everything in one process), split (one actor per process), or grouped (custom).
|
|
143
142
|
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).
|
|
144
143
|
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 a global `default-rpc` connection is configured; otherwise it picks `simple` when the backing is available.
|
|
145
144
|
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.
|
|
146
145
|
|
|
147
|
-
###
|
|
146
|
+
### Launch patterns
|
|
148
147
|
|
|
149
|
-
|
|
148
|
+
Copy any example from [Development examples](#development-examples) or [Per-actor production deployment](#per-actor-production-deployment) into `xyo.json`, then:
|
|
150
149
|
|
|
151
|
-
|
|
150
|
+
```sh
|
|
151
|
+
# Single process
|
|
152
|
+
xl1 -c ./xyo.json start api producer finalizer mempool
|
|
152
153
|
|
|
153
|
-
|
|
154
|
+
# Multi-process (one OS process per actor, same config file)
|
|
155
|
+
xl1 -c ./xyo.json start api
|
|
156
|
+
xl1 -c ./xyo.json start producer
|
|
157
|
+
xl1 -c ./xyo.json start finalizer
|
|
158
|
+
xl1 -c ./xyo.json start mempool
|
|
159
|
+
|
|
160
|
+
# One config file per process
|
|
161
|
+
xl1 -c ./xyo.api.json start api
|
|
162
|
+
xl1 -c ./xyo.producer.json start producer
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
```sh
|
|
166
|
+
# Inspect resolved config (secrets redacted)
|
|
167
|
+
xl1 --dump-config -c ./xyo.json start api producer finalizer
|
|
168
|
+
|
|
169
|
+
# Inspect provider wiring without starting actors
|
|
170
|
+
xl1 --dump-providers -c ./xyo.json start api producer finalizer
|
|
171
|
+
|
|
172
|
+
# Non-interactive dev boot (skip insecure-mnemonic prompt)
|
|
173
|
+
xl1 --skip-insecure-confirm -c ./xyo.json start
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## Connections model
|
|
177
|
+
|
|
178
|
+
Named **connections** describe where providers read/write state:
|
|
179
|
+
|
|
180
|
+
| Connection | Type | Purpose |
|
|
181
|
+
|------------|------|---------|
|
|
182
|
+
| `local-store` | `lmdb` | On-disk LMDB chain authority store |
|
|
183
|
+
| `chain-mongo` | `mongo` | MongoDB chain authority store |
|
|
184
|
+
| `dlq-store` | `lmdb` / `mongo` | Dead-letter queue backing (dev: aliases to chain store when omitted) |
|
|
185
|
+
| `mempool-store` | `lmdb` / `mongo` | Mempool backing (dev: aliases to chain store when omitted) |
|
|
186
|
+
| `indexer-store` | `lmdb` / `mongo` | Indexer-local store when split from chain authority |
|
|
187
|
+
| `default-rpc` | `rpc` | HTTP JSON-RPC to another XL1 API |
|
|
188
|
+
| `default-evm-rpc` | `evm-rpc` | EVM JSON-RPC for staking/contracts |
|
|
189
|
+
| `s3-finalized` / `s3-chain-state` / `s3-index` | `s3` | Object storage publish targets |
|
|
190
|
+
| `rest-finalized` / `rest-chain-state` / `rest-index` | `rest` | CDN / HTTP read URLs for published static files |
|
|
191
|
+
| `memory` | `memory` | In-process stubs (injected at boot) |
|
|
192
|
+
|
|
193
|
+
**providerBindings** map each provider moniker to a connection. When omitted, bindings are synthesized per connection name (chain monikers → `local-store` / `chain-mongo`, DLQ → `dlq-store` or dev-aliased chain store, mempool → `mempool-store` or dev-aliased chain store, viewers → `default-rpc` when present, EVM monikers → `default-evm-rpc` when declared, otherwise memory fallback at plan time).
|
|
194
|
+
|
|
195
|
+
**S3 write + REST read:** The finalizer writes finalized blocks and the chain-state head to S3 (`BlockPublishRunner`, `ChainStatePublishRunner`). The indexer reads the published head and blocks over REST (`ChainStateViewer`, `BlockViewer`) and writes the index bucket via `IndexPublishRunner` → `s3-index`. Because `BlockViewer` must stay on the authority store for finalization, use split per-actor configs ([Finalizer](#finalizer-per-actor) + [Indexer](#indexer-per-actor)) or override `providerBindings` explicitly as in [S3 write + REST read](#s3-write--rest-read).
|
|
196
|
+
|
|
197
|
+
## Development examples
|
|
198
|
+
|
|
199
|
+
### In-memory dev
|
|
200
|
+
|
|
201
|
+
Single process, ephemeral in-memory chain (fastest local dev). Omits `connections` — the boot preset injects an in-memory store.
|
|
154
202
|
|
|
155
|
-
`xyo.json`:
|
|
156
203
|
```json
|
|
157
204
|
{
|
|
158
205
|
"xl1": {
|
|
159
206
|
"actors": [
|
|
160
|
-
{
|
|
161
|
-
|
|
162
|
-
|
|
207
|
+
{
|
|
208
|
+
"name": "api",
|
|
209
|
+
"host": "localhost",
|
|
210
|
+
"port": 8080
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
"name": "producer",
|
|
214
|
+
"blockProductionCheckInterval": 100,
|
|
215
|
+
"heartbeatInterval": 100
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
"name": "finalizer",
|
|
219
|
+
"finalizationCheckInterval": 50,
|
|
220
|
+
"minCandidates": 1
|
|
221
|
+
}
|
|
163
222
|
]
|
|
164
223
|
}
|
|
165
224
|
}
|
|
166
225
|
```
|
|
167
226
|
|
|
168
|
-
|
|
169
|
-
|
|
227
|
+
### LMDB local
|
|
228
|
+
|
|
229
|
+
Single process with on-disk LMDB at `.store`.
|
|
230
|
+
|
|
231
|
+
```json
|
|
232
|
+
{
|
|
233
|
+
"xl1": {
|
|
234
|
+
"connections": {
|
|
235
|
+
"local-store": {
|
|
236
|
+
"type": "lmdb",
|
|
237
|
+
"root": ".store"
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
"actors": [
|
|
241
|
+
{
|
|
242
|
+
"name": "api",
|
|
243
|
+
"host": "localhost",
|
|
244
|
+
"port": 8080
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
"name": "producer",
|
|
248
|
+
"heartbeatInterval": 1000
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
"name": "finalizer"
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
"name": "mempool"
|
|
255
|
+
}
|
|
256
|
+
]
|
|
257
|
+
}
|
|
258
|
+
}
|
|
170
259
|
```
|
|
171
260
|
|
|
172
|
-
|
|
261
|
+
### LMDB + EVM JSON-RPC
|
|
262
|
+
|
|
263
|
+
LMDB plus contract-backed chain via `default-evm-rpc` (local Hardhat/Ganache).
|
|
264
|
+
|
|
265
|
+
```json
|
|
266
|
+
{
|
|
267
|
+
"xl1": {
|
|
268
|
+
"connections": {
|
|
269
|
+
"local-store": {
|
|
270
|
+
"type": "lmdb",
|
|
271
|
+
"root": ".store"
|
|
272
|
+
},
|
|
273
|
+
"default-evm-rpc": {
|
|
274
|
+
"type": "evm-rpc",
|
|
275
|
+
"url": "http://127.0.0.1:8545",
|
|
276
|
+
"chainId": "0xaa36a7"
|
|
277
|
+
}
|
|
278
|
+
},
|
|
279
|
+
"chain": {
|
|
280
|
+
"id": "dd381fbb392c85160d8b0453e446757b12384046"
|
|
281
|
+
},
|
|
282
|
+
"actors": [
|
|
283
|
+
{
|
|
284
|
+
"name": "api",
|
|
285
|
+
"host": "localhost",
|
|
286
|
+
"port": 8080
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
"name": "producer",
|
|
290
|
+
"heartbeatInterval": 1000
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
"name": "finalizer"
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
"name": "mempool"
|
|
297
|
+
}
|
|
298
|
+
]
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
```
|
|
173
302
|
|
|
174
|
-
|
|
303
|
+
### LMDB + EVM Infura
|
|
175
304
|
|
|
176
|
-
|
|
305
|
+
LMDB plus Sepolia EVM RPC URL.
|
|
177
306
|
|
|
178
|
-
`xyo.json`:
|
|
179
307
|
```json
|
|
180
308
|
{
|
|
181
309
|
"xl1": {
|
|
182
|
-
"connections": {
|
|
310
|
+
"connections": {
|
|
311
|
+
"local-store": {
|
|
312
|
+
"type": "lmdb",
|
|
313
|
+
"root": ".store"
|
|
314
|
+
},
|
|
315
|
+
"default-evm-rpc": {
|
|
316
|
+
"type": "evm-rpc",
|
|
317
|
+
"url": "https://sepolia.infura.io/v3/YOUR_INFURA_PROJECT_ID",
|
|
318
|
+
"chainId": "0xaa36a7"
|
|
319
|
+
}
|
|
320
|
+
},
|
|
321
|
+
"chain": {
|
|
322
|
+
"id": "dd381fbb392c85160d8b0453e446757b12384046"
|
|
323
|
+
},
|
|
183
324
|
"actors": [
|
|
184
|
-
{
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
325
|
+
{
|
|
326
|
+
"name": "api",
|
|
327
|
+
"host": "localhost",
|
|
328
|
+
"port": 8080
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
"name": "producer",
|
|
332
|
+
"heartbeatInterval": 1000
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
"name": "finalizer"
|
|
336
|
+
}
|
|
188
337
|
]
|
|
189
338
|
}
|
|
190
339
|
}
|
|
191
340
|
```
|
|
192
341
|
|
|
193
|
-
|
|
194
|
-
|
|
342
|
+
### Explicit connections
|
|
343
|
+
|
|
344
|
+
Explicit `connections` + `providerBindings` overrides.
|
|
345
|
+
|
|
346
|
+
```json
|
|
347
|
+
{
|
|
348
|
+
"xl1": {
|
|
349
|
+
"connections": {
|
|
350
|
+
"local-store": {
|
|
351
|
+
"type": "lmdb",
|
|
352
|
+
"root": ".store"
|
|
353
|
+
},
|
|
354
|
+
"default-evm-rpc": {
|
|
355
|
+
"type": "evm-rpc",
|
|
356
|
+
"url": "http://127.0.0.1:8545",
|
|
357
|
+
"chainId": "0xaa36a7"
|
|
358
|
+
}
|
|
359
|
+
},
|
|
360
|
+
"providerBindings": {
|
|
361
|
+
"BlockViewer": {
|
|
362
|
+
"connection": "local-store"
|
|
363
|
+
},
|
|
364
|
+
"MempoolRunner": {
|
|
365
|
+
"connection": "local-store"
|
|
366
|
+
},
|
|
367
|
+
"ChainContractViewer": {
|
|
368
|
+
"connection": "default-evm-rpc"
|
|
369
|
+
},
|
|
370
|
+
"StakeViewer": {
|
|
371
|
+
"connection": "default-evm-rpc"
|
|
372
|
+
}
|
|
373
|
+
},
|
|
374
|
+
"chain": {
|
|
375
|
+
"id": "dd381fbb392c85160d8b0453e446757b12384046"
|
|
376
|
+
},
|
|
377
|
+
"actors": [
|
|
378
|
+
{
|
|
379
|
+
"name": "api",
|
|
380
|
+
"host": "localhost",
|
|
381
|
+
"port": 8080
|
|
382
|
+
},
|
|
383
|
+
{
|
|
384
|
+
"name": "producer",
|
|
385
|
+
"heartbeatInterval": 1000
|
|
386
|
+
},
|
|
387
|
+
{
|
|
388
|
+
"name": "finalizer"
|
|
389
|
+
}
|
|
390
|
+
]
|
|
391
|
+
}
|
|
392
|
+
}
|
|
195
393
|
```
|
|
196
394
|
|
|
197
|
-
|
|
395
|
+
### Stateless API
|
|
198
396
|
|
|
199
|
-
|
|
397
|
+
Read-only API proxying a remote chain RPC.
|
|
398
|
+
|
|
399
|
+
```json
|
|
400
|
+
{
|
|
401
|
+
"xl1": {
|
|
402
|
+
"connections": {
|
|
403
|
+
"default-rpc": {
|
|
404
|
+
"type": "rpc",
|
|
405
|
+
"protocol": "https",
|
|
406
|
+
"url": "https://chain.example.com/rpc"
|
|
407
|
+
}
|
|
408
|
+
},
|
|
409
|
+
"actors": [
|
|
410
|
+
{
|
|
411
|
+
"name": "api",
|
|
412
|
+
"host": "0.0.0.0",
|
|
413
|
+
"port": 8080,
|
|
414
|
+
"stateless": true
|
|
415
|
+
}
|
|
416
|
+
]
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
### MongoDB
|
|
422
|
+
|
|
423
|
+
MongoDB-backed archivist via `chain-mongo`.
|
|
200
424
|
|
|
201
|
-
`xyo.json`:
|
|
202
425
|
```json
|
|
203
426
|
{
|
|
204
427
|
"xl1": {
|
|
205
428
|
"connections": {
|
|
206
429
|
"chain-mongo": {
|
|
207
430
|
"type": "mongo",
|
|
208
|
-
"connectionString": "mongodb://
|
|
209
|
-
"database": "
|
|
210
|
-
"domain": "
|
|
431
|
+
"connectionString": "mongodb://root:example@localhost:27017/?retryWrites=true&w=majority",
|
|
432
|
+
"database": "chain",
|
|
433
|
+
"domain": "localhost",
|
|
434
|
+
"username": "root",
|
|
435
|
+
"password": "example"
|
|
211
436
|
}
|
|
212
437
|
},
|
|
213
438
|
"actors": [
|
|
214
|
-
{
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
439
|
+
{
|
|
440
|
+
"name": "api",
|
|
441
|
+
"host": "localhost",
|
|
442
|
+
"port": 8080
|
|
443
|
+
},
|
|
444
|
+
{
|
|
445
|
+
"name": "producer",
|
|
446
|
+
"heartbeatInterval": 1000
|
|
447
|
+
},
|
|
448
|
+
{
|
|
449
|
+
"name": "finalizer"
|
|
450
|
+
},
|
|
451
|
+
{
|
|
452
|
+
"name": "mempool"
|
|
453
|
+
}
|
|
218
454
|
]
|
|
219
455
|
}
|
|
220
456
|
}
|
|
221
457
|
```
|
|
222
458
|
|
|
223
|
-
|
|
224
|
-
|
|
459
|
+
### Multi-process LMDB
|
|
460
|
+
|
|
461
|
+
Shared LMDB; run one process per `xl1 start <actor>`.
|
|
462
|
+
|
|
463
|
+
```json
|
|
464
|
+
{
|
|
465
|
+
"xl1": {
|
|
466
|
+
"connections": {
|
|
467
|
+
"local-store": {
|
|
468
|
+
"type": "lmdb",
|
|
469
|
+
"root": ".store"
|
|
470
|
+
}
|
|
471
|
+
},
|
|
472
|
+
"actors": [
|
|
473
|
+
{
|
|
474
|
+
"name": "api",
|
|
475
|
+
"host": "localhost",
|
|
476
|
+
"port": 8080
|
|
477
|
+
},
|
|
478
|
+
{
|
|
479
|
+
"name": "producer",
|
|
480
|
+
"heartbeatInterval": 1000
|
|
481
|
+
},
|
|
482
|
+
{
|
|
483
|
+
"name": "finalizer"
|
|
484
|
+
},
|
|
485
|
+
{
|
|
486
|
+
"name": "mempool",
|
|
487
|
+
"host": "localhost",
|
|
488
|
+
"port": 8081
|
|
489
|
+
}
|
|
490
|
+
]
|
|
491
|
+
}
|
|
492
|
+
}
|
|
225
493
|
```
|
|
226
494
|
|
|
227
|
-
|
|
495
|
+
### Mempool remote API
|
|
228
496
|
|
|
229
|
-
|
|
497
|
+
Standalone mempool over JsonRpc to a remote API.
|
|
230
498
|
|
|
231
|
-
`xyo.json` (single file, all processes load it):
|
|
232
499
|
```json
|
|
233
500
|
{
|
|
234
501
|
"xl1": {
|
|
235
|
-
"connections": {
|
|
502
|
+
"connections": {
|
|
503
|
+
"default-rpc": {
|
|
504
|
+
"type": "rpc",
|
|
505
|
+
"protocol": "http",
|
|
506
|
+
"url": "http://localhost:8080/rpc"
|
|
507
|
+
}
|
|
508
|
+
},
|
|
509
|
+
"providerBindings": {
|
|
510
|
+
"MempoolRunner": {
|
|
511
|
+
"connection": "default-rpc"
|
|
512
|
+
},
|
|
513
|
+
"MempoolViewer": {
|
|
514
|
+
"connection": "default-rpc"
|
|
515
|
+
},
|
|
516
|
+
"BlockViewer": {
|
|
517
|
+
"connection": "default-rpc"
|
|
518
|
+
},
|
|
519
|
+
"WindowedBlockViewer": {
|
|
520
|
+
"connection": "default-rpc"
|
|
521
|
+
},
|
|
522
|
+
"TransactionValidationViewer": {
|
|
523
|
+
"connection": "default-rpc"
|
|
524
|
+
}
|
|
525
|
+
},
|
|
236
526
|
"actors": [
|
|
237
|
-
{
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
527
|
+
{
|
|
528
|
+
"name": "mempool",
|
|
529
|
+
"host": "localhost",
|
|
530
|
+
"port": 8081
|
|
531
|
+
}
|
|
241
532
|
]
|
|
242
533
|
}
|
|
243
534
|
}
|
|
244
535
|
```
|
|
245
536
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
537
|
+
### Mixed local + remote
|
|
538
|
+
|
|
539
|
+
Local LMDB runners + JsonRpc viewers.
|
|
540
|
+
|
|
541
|
+
```json
|
|
542
|
+
{
|
|
543
|
+
"xl1": {
|
|
544
|
+
"connections": {
|
|
545
|
+
"local-store": {
|
|
546
|
+
"type": "lmdb",
|
|
547
|
+
"root": ".store"
|
|
548
|
+
},
|
|
549
|
+
"default-rpc": {
|
|
550
|
+
"type": "rpc",
|
|
551
|
+
"protocol": "http",
|
|
552
|
+
"url": "http://localhost:8080/rpc"
|
|
553
|
+
}
|
|
554
|
+
},
|
|
555
|
+
"providerBindings": {
|
|
556
|
+
"MempoolRunner": {
|
|
557
|
+
"connection": "local-store"
|
|
558
|
+
},
|
|
559
|
+
"BlockViewer": {
|
|
560
|
+
"connection": "default-rpc"
|
|
561
|
+
},
|
|
562
|
+
"MempoolViewer": {
|
|
563
|
+
"connection": "default-rpc"
|
|
564
|
+
},
|
|
565
|
+
"FinalizationViewer": {
|
|
566
|
+
"connection": "default-rpc"
|
|
567
|
+
},
|
|
568
|
+
"TransactionViewer": {
|
|
569
|
+
"connection": "default-rpc"
|
|
570
|
+
},
|
|
571
|
+
"AccountBalanceViewer": {
|
|
572
|
+
"connection": "default-rpc"
|
|
573
|
+
}
|
|
574
|
+
},
|
|
575
|
+
"actors": [
|
|
576
|
+
{
|
|
577
|
+
"name": "api",
|
|
578
|
+
"host": "localhost",
|
|
579
|
+
"port": 8080
|
|
580
|
+
},
|
|
581
|
+
{
|
|
582
|
+
"name": "mempool"
|
|
583
|
+
}
|
|
584
|
+
]
|
|
585
|
+
}
|
|
586
|
+
}
|
|
252
587
|
```
|
|
253
588
|
|
|
254
|
-
|
|
589
|
+
### Finalizer + indexer S3
|
|
255
590
|
|
|
256
|
-
|
|
591
|
+
Mongo store plus S3 publish connections for finalizer and indexer in one process.
|
|
257
592
|
|
|
258
|
-
`xyo.json`:
|
|
259
593
|
```json
|
|
260
594
|
{
|
|
261
595
|
"xl1": {
|
|
@@ -265,87 +599,539 @@ Same as above but with MongoDB as the shared store. Now each process can run on
|
|
|
265
599
|
"connectionString": "mongodb://user:pass@db.internal:27017",
|
|
266
600
|
"database": "xl1",
|
|
267
601
|
"domain": "internal"
|
|
602
|
+
},
|
|
603
|
+
"s3-finalized": {
|
|
604
|
+
"type": "s3",
|
|
605
|
+
"accountId": "YOUR_R2_ACCOUNT_ID",
|
|
606
|
+
"accessKeyId": "YOUR_ACCESS_KEY_ID",
|
|
607
|
+
"secretAccessKey": "YOUR_SECRET_ACCESS_KEY",
|
|
608
|
+
"prefix": "xl1/",
|
|
609
|
+
"bucket": "xl1-chain",
|
|
610
|
+
"readUrl": "https://chain.xl1.example"
|
|
611
|
+
},
|
|
612
|
+
"s3-chain-state": {
|
|
613
|
+
"type": "s3",
|
|
614
|
+
"accountId": "YOUR_R2_ACCOUNT_ID",
|
|
615
|
+
"accessKeyId": "YOUR_ACCESS_KEY_ID",
|
|
616
|
+
"secretAccessKey": "YOUR_SECRET_ACCESS_KEY",
|
|
617
|
+
"prefix": "xl1/",
|
|
618
|
+
"bucket": "xl1-chain-state",
|
|
619
|
+
"readUrl": "https://chain-state.xl1.example"
|
|
620
|
+
},
|
|
621
|
+
"s3-index": {
|
|
622
|
+
"type": "s3",
|
|
623
|
+
"accountId": "YOUR_R2_ACCOUNT_ID",
|
|
624
|
+
"accessKeyId": "YOUR_ACCESS_KEY_ID",
|
|
625
|
+
"secretAccessKey": "YOUR_SECRET_ACCESS_KEY",
|
|
626
|
+
"prefix": "xl1/",
|
|
627
|
+
"bucket": "xl1-index",
|
|
628
|
+
"readUrl": "https://index.xl1.example"
|
|
268
629
|
}
|
|
269
630
|
},
|
|
270
631
|
"actors": [
|
|
271
|
-
{
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
632
|
+
{
|
|
633
|
+
"name": "producer",
|
|
634
|
+
"heartbeatInterval": 1000
|
|
635
|
+
},
|
|
636
|
+
{
|
|
637
|
+
"name": "finalizer",
|
|
638
|
+
"publishOnFinalize": true,
|
|
639
|
+
"publishContentEncoding": "br",
|
|
640
|
+
"publishProgressInterval": 100
|
|
641
|
+
},
|
|
642
|
+
{
|
|
643
|
+
"name": "indexer",
|
|
644
|
+
"publishSyncInterval": 5000,
|
|
645
|
+
"publishContentEncoding": "br",
|
|
646
|
+
"publishProgressInterval": 100
|
|
647
|
+
}
|
|
275
648
|
]
|
|
276
649
|
}
|
|
277
650
|
}
|
|
278
651
|
```
|
|
279
652
|
|
|
280
|
-
|
|
281
|
-
# On host A
|
|
282
|
-
xl1 start api
|
|
653
|
+
### S3 write + REST read
|
|
283
654
|
|
|
284
|
-
|
|
285
|
-
xl1 start producer
|
|
655
|
+
Indexer: `s3-index` publish + REST CDN viewers.
|
|
286
656
|
|
|
287
|
-
|
|
288
|
-
|
|
657
|
+
```json
|
|
658
|
+
{
|
|
659
|
+
"xl1": {
|
|
660
|
+
"connections": {
|
|
661
|
+
"s3-index": {
|
|
662
|
+
"type": "s3",
|
|
663
|
+
"accountId": "YOUR_R2_ACCOUNT_ID",
|
|
664
|
+
"accessKeyId": "YOUR_ACCESS_KEY_ID",
|
|
665
|
+
"secretAccessKey": "YOUR_SECRET_ACCESS_KEY",
|
|
666
|
+
"prefix": "xl1/",
|
|
667
|
+
"bucket": "xl1-index",
|
|
668
|
+
"readUrl": "https://index.xl1.example"
|
|
669
|
+
},
|
|
670
|
+
"rest-finalized": {
|
|
671
|
+
"type": "rest",
|
|
672
|
+
"baseUrl": "https://chain.xl1.example"
|
|
673
|
+
},
|
|
674
|
+
"rest-chain-state": {
|
|
675
|
+
"type": "rest",
|
|
676
|
+
"baseUrl": "https://chain-state.xl1.example"
|
|
677
|
+
},
|
|
678
|
+
"rest-index": {
|
|
679
|
+
"type": "rest",
|
|
680
|
+
"baseUrl": "https://index.xl1.example"
|
|
681
|
+
}
|
|
682
|
+
},
|
|
683
|
+
"providerBindings": {
|
|
684
|
+
"BlockViewer": {
|
|
685
|
+
"connection": "rest-finalized"
|
|
686
|
+
},
|
|
687
|
+
"ChainStateViewer": {
|
|
688
|
+
"connection": "rest-chain-state"
|
|
689
|
+
},
|
|
690
|
+
"IndexViewer": {
|
|
691
|
+
"connection": "rest-index"
|
|
692
|
+
},
|
|
693
|
+
"IndexPublishRunner": {
|
|
694
|
+
"connection": "s3-index"
|
|
695
|
+
}
|
|
696
|
+
},
|
|
697
|
+
"actors": [
|
|
698
|
+
{
|
|
699
|
+
"name": "indexer",
|
|
700
|
+
"publishSyncInterval": 5000,
|
|
701
|
+
"publishContentEncoding": "br",
|
|
702
|
+
"publishProgressInterval": 100
|
|
703
|
+
}
|
|
704
|
+
]
|
|
705
|
+
}
|
|
706
|
+
}
|
|
289
707
|
```
|
|
290
708
|
|
|
291
|
-
|
|
709
|
+
## Per-actor production deployment
|
|
292
710
|
|
|
293
|
-
|
|
711
|
+
One config per actor **process** — the shape a real multi-host deployment runs, where each actor is its own container/pod (see `.k8s/` and the `deploy-prod-*` workflows). The read layer is served from S3/R2 object storage behind a CDN, so only the finalizer and indexer write to S3; everyone else reads the published blocks / chain-state / index over REST and keeps MongoDB only for the authority/write path.
|
|
712
|
+
|
|
713
|
+
| Actor | Backing connections | Writes to S3 | Reads |
|
|
714
|
+
|-------|---------------------|--------------|-------|
|
|
715
|
+
| `api` | `chain-mongo` (mempool + tx submission) | — | blocks / state / index over REST |
|
|
716
|
+
| `producer` | `chain-mongo` authority + `default-evm-rpc` + `producer-wallet` | — | authority store + EVM staking contract |
|
|
717
|
+
| `finalizer` | `chain-mongo` authority | `s3-finalized` (blocks), `s3-chain-state` (head) | authority store |
|
|
718
|
+
| `indexer` | none (reads over REST) | `s3-index` | finalized blocks + chain-state over REST |
|
|
719
|
+
| `mempool` | `chain-mongo` | — | authority store |
|
|
720
|
+
| `bridge` | `chain-mongo` + `default-evm-rpc` + `bridge-wallet` + Redis | — | authority store + remote EVM chain |
|
|
721
|
+
| `rewardRedemption` | `chain-mongo` + `default-evm-rpc` + `rewardRedemption-wallet` | — | authority store + EVM staking contract |
|
|
722
|
+
|
|
723
|
+
- **One writer per bucket.** The finalizer owns `s3-finalized` + `s3-chain-state`; the indexer owns `s3-index`. No other actor writes object storage.
|
|
724
|
+
- **`BlockViewer` is not auto-bound to REST.** When a process declares a local store, `BlockViewer` defaults to it, so the API and indexer configs bind `BlockViewer → rest-finalized` explicitly to read finalized blocks from the CDN. `ChainStateViewer` / `IndexViewer` bind to their REST connections automatically when those connections are declared (the explicit bindings here are for clarity).
|
|
725
|
+
- **Staking.** `chain.id` (the staking contract address on the backing EVM) plus `evm.chainId` and a `default-evm-rpc` connection enable the EVM-backed stake/contract viewers. Actors that only read published data (`api`, `indexer`) omit them; the stake viewers fall back to their chain-state-derived implementations.
|
|
726
|
+
- **Wallets.** Wallet connections (`<actor>-wallet`) and the `XyoSigner` binding are auto-synthesized for signing actors (`producer`, `bridge`, `rewardRedemption`); they are shown explicitly here for clarity. `bridge` and `rewardRedemption` cannot be co-located in one process (they share `XyoSigner`).
|
|
727
|
+
- **Secrets.** `YOUR_*` placeholders (R2 keys, Mongo credentials, Infura project id) and wallet mnemonics should be supplied via `XL1_*` env vars / your secret store in production — do not commit real credentials.
|
|
728
|
+
|
|
729
|
+
### API (per-actor)
|
|
294
730
|
|
|
295
|
-
`xyo.json`:
|
|
296
731
|
```json
|
|
297
732
|
{
|
|
298
733
|
"xl1": {
|
|
299
734
|
"connections": {
|
|
300
|
-
"
|
|
735
|
+
"chain-mongo": {
|
|
736
|
+
"type": "mongo",
|
|
737
|
+
"connectionString": "mongodb://YOUR_MONGO_USER:YOUR_MONGO_PASSWORD@db.internal:27017/?retryWrites=true&w=majority",
|
|
738
|
+
"database": "xl1",
|
|
739
|
+
"domain": "internal"
|
|
740
|
+
},
|
|
741
|
+
"rest-finalized": {
|
|
742
|
+
"type": "rest",
|
|
743
|
+
"baseUrl": "https://chain.xl1.example"
|
|
744
|
+
},
|
|
745
|
+
"rest-chain-state": {
|
|
746
|
+
"type": "rest",
|
|
747
|
+
"baseUrl": "https://chain-state.xl1.example"
|
|
748
|
+
},
|
|
749
|
+
"rest-index": {
|
|
750
|
+
"type": "rest",
|
|
751
|
+
"baseUrl": "https://index.xl1.example"
|
|
752
|
+
}
|
|
753
|
+
},
|
|
754
|
+
"providerBindings": {
|
|
755
|
+
"AccountBalanceViewer": { "connection": "chain-mongo" },
|
|
756
|
+
"BlockRunner": { "connection": "chain-mongo" },
|
|
757
|
+
"BlockValidationViewer": { "connection": "chain-mongo" },
|
|
758
|
+
"BlockViewer": { "connection": "rest-finalized" },
|
|
759
|
+
"ChainStateViewer": { "connection": "rest-chain-state" },
|
|
760
|
+
"DeadLetterQueueRunner": { "connection": "chain-mongo" },
|
|
761
|
+
"DeadLetterQueueViewer": { "connection": "chain-mongo" },
|
|
762
|
+
"FinalizationRunner": { "connection": "chain-mongo" },
|
|
763
|
+
"FinalizationViewer": { "connection": "chain-mongo" },
|
|
764
|
+
"IndexViewer": { "connection": "rest-index" },
|
|
765
|
+
"MempoolRunner": { "connection": "chain-mongo" },
|
|
766
|
+
"MempoolViewer": { "connection": "chain-mongo" },
|
|
767
|
+
"TransactionValidationViewer": { "connection": "chain-mongo" },
|
|
768
|
+
"TransactionViewer": { "connection": "chain-mongo" },
|
|
769
|
+
"WindowedBlockViewer": { "connection": "chain-mongo" },
|
|
770
|
+
"XyoConnection": { "connection": "chain-mongo" },
|
|
771
|
+
"XyoGateway": { "connection": "chain-mongo" },
|
|
772
|
+
"XyoGatewayRunner": { "connection": "chain-mongo" },
|
|
773
|
+
"XyoRunner": { "connection": "chain-mongo" },
|
|
774
|
+
"XyoViewer": { "connection": "chain-mongo" }
|
|
301
775
|
},
|
|
302
776
|
"actors": [
|
|
303
|
-
{
|
|
777
|
+
{
|
|
778
|
+
"name": "api",
|
|
779
|
+
"host": "0.0.0.0",
|
|
780
|
+
"port": 8080
|
|
781
|
+
}
|
|
304
782
|
]
|
|
305
783
|
}
|
|
306
784
|
}
|
|
307
785
|
```
|
|
308
786
|
|
|
309
|
-
|
|
310
|
-
xl1 start api
|
|
311
|
-
```
|
|
787
|
+
### Producer (per-actor)
|
|
312
788
|
|
|
313
|
-
|
|
789
|
+
```json
|
|
790
|
+
{
|
|
791
|
+
"xl1": {
|
|
792
|
+
"connections": {
|
|
793
|
+
"chain-mongo": {
|
|
794
|
+
"type": "mongo",
|
|
795
|
+
"connectionString": "mongodb://YOUR_MONGO_USER:YOUR_MONGO_PASSWORD@db.internal:27017/?retryWrites=true&w=majority",
|
|
796
|
+
"database": "xl1",
|
|
797
|
+
"domain": "internal"
|
|
798
|
+
},
|
|
799
|
+
"default-evm-rpc": {
|
|
800
|
+
"type": "evm-rpc",
|
|
801
|
+
"url": "https://sepolia.infura.io/v3/YOUR_INFURA_PROJECT_ID",
|
|
802
|
+
"chainId": "0xaa36a7"
|
|
803
|
+
},
|
|
804
|
+
"producer-wallet": {
|
|
805
|
+
"type": "wallet",
|
|
806
|
+
"accountPath": "0"
|
|
807
|
+
}
|
|
808
|
+
},
|
|
809
|
+
"chain": {
|
|
810
|
+
"id": "dd381fbb392c85160d8b0453e446757b12384046"
|
|
811
|
+
},
|
|
812
|
+
"providerBindings": {
|
|
813
|
+
"AccountBalanceViewer": { "connection": "chain-mongo" },
|
|
814
|
+
"BlockRunner": { "connection": "chain-mongo" },
|
|
815
|
+
"BlockValidationViewer": { "connection": "chain-mongo" },
|
|
816
|
+
"BlockViewer": { "connection": "chain-mongo" },
|
|
817
|
+
"ChainContractViewer": { "connection": "default-evm-rpc" },
|
|
818
|
+
"DeadLetterQueueRunner": { "connection": "chain-mongo" },
|
|
819
|
+
"DeadLetterQueueViewer": { "connection": "chain-mongo" },
|
|
820
|
+
"FinalizationRunner": { "connection": "chain-mongo" },
|
|
821
|
+
"FinalizationViewer": { "connection": "chain-mongo" },
|
|
822
|
+
"MempoolRunner": { "connection": "chain-mongo" },
|
|
823
|
+
"MempoolViewer": { "connection": "chain-mongo" },
|
|
824
|
+
"StakeEventsViewer": { "connection": "default-evm-rpc" },
|
|
825
|
+
"StakeTotalsViewer": { "connection": "default-evm-rpc" },
|
|
826
|
+
"StakeViewer": { "connection": "default-evm-rpc" },
|
|
827
|
+
"TimeSyncViewer": { "connection": "default-evm-rpc" },
|
|
828
|
+
"TransactionValidationViewer": { "connection": "chain-mongo" },
|
|
829
|
+
"TransactionViewer": { "connection": "chain-mongo" },
|
|
830
|
+
"WindowedBlockViewer": { "connection": "chain-mongo" },
|
|
831
|
+
"XyoConnection": { "connection": "chain-mongo" },
|
|
832
|
+
"XyoGateway": { "connection": "chain-mongo" },
|
|
833
|
+
"XyoGatewayRunner": { "connection": "chain-mongo" },
|
|
834
|
+
"XyoRunner": { "connection": "chain-mongo" },
|
|
835
|
+
"XyoViewer": { "connection": "chain-mongo" }
|
|
836
|
+
},
|
|
837
|
+
"actors": [
|
|
838
|
+
{
|
|
839
|
+
"name": "producer",
|
|
840
|
+
"heartbeatInterval": 1000
|
|
841
|
+
}
|
|
842
|
+
]
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
```
|
|
314
846
|
|
|
315
|
-
|
|
847
|
+
### Finalizer (per-actor)
|
|
316
848
|
|
|
317
|
-
```
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
849
|
+
```json
|
|
850
|
+
{
|
|
851
|
+
"xl1": {
|
|
852
|
+
"connections": {
|
|
853
|
+
"chain-mongo": {
|
|
854
|
+
"type": "mongo",
|
|
855
|
+
"connectionString": "mongodb://YOUR_MONGO_USER:YOUR_MONGO_PASSWORD@db.internal:27017/?retryWrites=true&w=majority",
|
|
856
|
+
"database": "xl1",
|
|
857
|
+
"domain": "internal"
|
|
858
|
+
},
|
|
859
|
+
"s3-finalized": {
|
|
860
|
+
"type": "s3",
|
|
861
|
+
"accountId": "YOUR_R2_ACCOUNT_ID",
|
|
862
|
+
"accessKeyId": "YOUR_ACCESS_KEY_ID",
|
|
863
|
+
"secretAccessKey": "YOUR_SECRET_ACCESS_KEY",
|
|
864
|
+
"prefix": "xl1/",
|
|
865
|
+
"bucket": "xl1-chain",
|
|
866
|
+
"readUrl": "https://chain.xl1.example"
|
|
867
|
+
},
|
|
868
|
+
"s3-chain-state": {
|
|
869
|
+
"type": "s3",
|
|
870
|
+
"accountId": "YOUR_R2_ACCOUNT_ID",
|
|
871
|
+
"accessKeyId": "YOUR_ACCESS_KEY_ID",
|
|
872
|
+
"secretAccessKey": "YOUR_SECRET_ACCESS_KEY",
|
|
873
|
+
"prefix": "xl1/",
|
|
874
|
+
"bucket": "xl1-chain-state",
|
|
875
|
+
"readUrl": "https://chain-state.xl1.example"
|
|
876
|
+
}
|
|
877
|
+
},
|
|
878
|
+
"providerBindings": {
|
|
879
|
+
"AccountBalanceViewer": { "connection": "chain-mongo" },
|
|
880
|
+
"BlockPublishRunner": { "connection": "s3-finalized" },
|
|
881
|
+
"BlockRunner": { "connection": "chain-mongo" },
|
|
882
|
+
"BlockValidationViewer": { "connection": "chain-mongo" },
|
|
883
|
+
"BlockViewer": { "connection": "chain-mongo" },
|
|
884
|
+
"ChainStatePublishRunner": { "connection": "s3-chain-state" },
|
|
885
|
+
"ChainStateViewer": { "connection": "s3-chain-state" },
|
|
886
|
+
"DeadLetterQueueRunner": { "connection": "chain-mongo" },
|
|
887
|
+
"DeadLetterQueueViewer": { "connection": "chain-mongo" },
|
|
888
|
+
"FinalizationRunner": { "connection": "chain-mongo" },
|
|
889
|
+
"FinalizationViewer": { "connection": "chain-mongo" },
|
|
890
|
+
"MempoolRunner": { "connection": "chain-mongo" },
|
|
891
|
+
"MempoolViewer": { "connection": "chain-mongo" },
|
|
892
|
+
"TransactionValidationViewer": { "connection": "chain-mongo" },
|
|
893
|
+
"TransactionViewer": { "connection": "chain-mongo" },
|
|
894
|
+
"WindowedBlockViewer": { "connection": "chain-mongo" },
|
|
895
|
+
"XyoConnection": { "connection": "chain-mongo" },
|
|
896
|
+
"XyoGateway": { "connection": "chain-mongo" },
|
|
897
|
+
"XyoGatewayRunner": { "connection": "chain-mongo" },
|
|
898
|
+
"XyoRunner": { "connection": "chain-mongo" },
|
|
899
|
+
"XyoViewer": { "connection": "chain-mongo" }
|
|
900
|
+
},
|
|
901
|
+
"actors": [
|
|
902
|
+
{
|
|
903
|
+
"name": "finalizer",
|
|
904
|
+
"finalizationCheckInterval": 500,
|
|
905
|
+
"publishOnFinalize": true,
|
|
906
|
+
"publishContentEncoding": "br",
|
|
907
|
+
"publishProgressInterval": 100
|
|
908
|
+
}
|
|
909
|
+
]
|
|
910
|
+
}
|
|
911
|
+
}
|
|
327
912
|
```
|
|
328
913
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
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`.
|
|
914
|
+
### Indexer (per-actor)
|
|
332
915
|
|
|
333
|
-
`xyo.api.json`:
|
|
334
916
|
```json
|
|
335
|
-
{
|
|
917
|
+
{
|
|
918
|
+
"xl1": {
|
|
919
|
+
"connections": {
|
|
920
|
+
"rest-finalized": {
|
|
921
|
+
"type": "rest",
|
|
922
|
+
"baseUrl": "https://chain.xl1.example"
|
|
923
|
+
},
|
|
924
|
+
"rest-chain-state": {
|
|
925
|
+
"type": "rest",
|
|
926
|
+
"baseUrl": "https://chain-state.xl1.example"
|
|
927
|
+
},
|
|
928
|
+
"rest-index": {
|
|
929
|
+
"type": "rest",
|
|
930
|
+
"baseUrl": "https://index.xl1.example"
|
|
931
|
+
},
|
|
932
|
+
"s3-index": {
|
|
933
|
+
"type": "s3",
|
|
934
|
+
"accountId": "YOUR_R2_ACCOUNT_ID",
|
|
935
|
+
"accessKeyId": "YOUR_ACCESS_KEY_ID",
|
|
936
|
+
"secretAccessKey": "YOUR_SECRET_ACCESS_KEY",
|
|
937
|
+
"prefix": "xl1/",
|
|
938
|
+
"bucket": "xl1-index",
|
|
939
|
+
"readUrl": "https://index.xl1.example"
|
|
940
|
+
}
|
|
941
|
+
},
|
|
942
|
+
"providerBindings": {
|
|
943
|
+
"BlockViewer": {
|
|
944
|
+
"connection": "rest-finalized"
|
|
945
|
+
},
|
|
946
|
+
"ChainStateViewer": {
|
|
947
|
+
"connection": "rest-chain-state"
|
|
948
|
+
},
|
|
949
|
+
"IndexViewer": {
|
|
950
|
+
"connection": "rest-index"
|
|
951
|
+
},
|
|
952
|
+
"IndexPublishRunner": {
|
|
953
|
+
"connection": "s3-index"
|
|
954
|
+
}
|
|
955
|
+
},
|
|
956
|
+
"actors": [
|
|
957
|
+
{
|
|
958
|
+
"name": "indexer",
|
|
959
|
+
"publishSyncInterval": 5000,
|
|
960
|
+
"publishContentEncoding": "br",
|
|
961
|
+
"publishProgressInterval": 100
|
|
962
|
+
}
|
|
963
|
+
]
|
|
964
|
+
}
|
|
965
|
+
}
|
|
336
966
|
```
|
|
337
967
|
|
|
338
|
-
|
|
968
|
+
### Mempool (per-actor)
|
|
969
|
+
|
|
339
970
|
```json
|
|
340
|
-
{
|
|
971
|
+
{
|
|
972
|
+
"xl1": {
|
|
973
|
+
"connections": {
|
|
974
|
+
"chain-mongo": {
|
|
975
|
+
"type": "mongo",
|
|
976
|
+
"connectionString": "mongodb://YOUR_MONGO_USER:YOUR_MONGO_PASSWORD@db.internal:27017/?retryWrites=true&w=majority",
|
|
977
|
+
"database": "xl1",
|
|
978
|
+
"domain": "internal"
|
|
979
|
+
}
|
|
980
|
+
},
|
|
981
|
+
"providerBindings": {
|
|
982
|
+
"AccountBalanceViewer": { "connection": "chain-mongo" },
|
|
983
|
+
"BlockRunner": { "connection": "chain-mongo" },
|
|
984
|
+
"BlockValidationViewer": { "connection": "chain-mongo" },
|
|
985
|
+
"BlockViewer": { "connection": "chain-mongo" },
|
|
986
|
+
"DeadLetterQueueRunner": { "connection": "chain-mongo" },
|
|
987
|
+
"DeadLetterQueueViewer": { "connection": "chain-mongo" },
|
|
988
|
+
"FinalizationRunner": { "connection": "chain-mongo" },
|
|
989
|
+
"FinalizationViewer": { "connection": "chain-mongo" },
|
|
990
|
+
"MempoolRunner": { "connection": "chain-mongo" },
|
|
991
|
+
"MempoolViewer": { "connection": "chain-mongo" },
|
|
992
|
+
"TransactionValidationViewer": { "connection": "chain-mongo" },
|
|
993
|
+
"TransactionViewer": { "connection": "chain-mongo" },
|
|
994
|
+
"WindowedBlockViewer": { "connection": "chain-mongo" },
|
|
995
|
+
"XyoConnection": { "connection": "chain-mongo" },
|
|
996
|
+
"XyoGateway": { "connection": "chain-mongo" },
|
|
997
|
+
"XyoGatewayRunner": { "connection": "chain-mongo" },
|
|
998
|
+
"XyoRunner": { "connection": "chain-mongo" },
|
|
999
|
+
"XyoViewer": { "connection": "chain-mongo" }
|
|
1000
|
+
},
|
|
1001
|
+
"actors": [
|
|
1002
|
+
{
|
|
1003
|
+
"name": "mempool",
|
|
1004
|
+
"host": "0.0.0.0",
|
|
1005
|
+
"port": 8081
|
|
1006
|
+
}
|
|
1007
|
+
]
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
341
1010
|
```
|
|
342
1011
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
1012
|
+
### Bridge (per-actor)
|
|
1013
|
+
|
|
1014
|
+
```json
|
|
1015
|
+
{
|
|
1016
|
+
"xl1": {
|
|
1017
|
+
"connections": {
|
|
1018
|
+
"chain-mongo": {
|
|
1019
|
+
"type": "mongo",
|
|
1020
|
+
"connectionString": "mongodb://YOUR_MONGO_USER:YOUR_MONGO_PASSWORD@db.internal:27017/?retryWrites=true&w=majority",
|
|
1021
|
+
"database": "xl1",
|
|
1022
|
+
"domain": "internal"
|
|
1023
|
+
},
|
|
1024
|
+
"default-evm-rpc": {
|
|
1025
|
+
"type": "evm-rpc",
|
|
1026
|
+
"url": "https://sepolia.infura.io/v3/YOUR_INFURA_PROJECT_ID",
|
|
1027
|
+
"chainId": "0xaa36a7"
|
|
1028
|
+
},
|
|
1029
|
+
"rest-datalake": {
|
|
1030
|
+
"type": "rest",
|
|
1031
|
+
"baseUrl": "https://api.archivist.xyo.network/dataLake"
|
|
1032
|
+
}
|
|
1033
|
+
},
|
|
1034
|
+
"chain": {
|
|
1035
|
+
"id": "dd381fbb392c85160d8b0453e446757b12384046"
|
|
1036
|
+
},
|
|
1037
|
+
"providerBindings": {
|
|
1038
|
+
"AccountBalanceViewer": { "connection": "chain-mongo" },
|
|
1039
|
+
"BlockRunner": { "connection": "chain-mongo" },
|
|
1040
|
+
"BlockValidationViewer": { "connection": "chain-mongo" },
|
|
1041
|
+
"BlockViewer": { "connection": "chain-mongo" },
|
|
1042
|
+
"ChainContractViewer": { "connection": "default-evm-rpc" },
|
|
1043
|
+
"DataLakeRunner": { "connection": "rest-datalake" },
|
|
1044
|
+
"DataLakeViewer": { "connection": "rest-datalake" },
|
|
1045
|
+
"DeadLetterQueueRunner": { "connection": "chain-mongo" },
|
|
1046
|
+
"DeadLetterQueueViewer": { "connection": "chain-mongo" },
|
|
1047
|
+
"FinalizationRunner": { "connection": "chain-mongo" },
|
|
1048
|
+
"FinalizationViewer": { "connection": "chain-mongo" },
|
|
1049
|
+
"MempoolRunner": { "connection": "chain-mongo" },
|
|
1050
|
+
"MempoolViewer": { "connection": "chain-mongo" },
|
|
1051
|
+
"StakeEventsViewer": { "connection": "default-evm-rpc" },
|
|
1052
|
+
"StakeTotalsViewer": { "connection": "default-evm-rpc" },
|
|
1053
|
+
"StakeViewer": { "connection": "default-evm-rpc" },
|
|
1054
|
+
"TimeSyncViewer": { "connection": "default-evm-rpc" },
|
|
1055
|
+
"TransactionValidationViewer": { "connection": "chain-mongo" },
|
|
1056
|
+
"TransactionViewer": { "connection": "chain-mongo" },
|
|
1057
|
+
"WindowedBlockViewer": { "connection": "chain-mongo" },
|
|
1058
|
+
"XyoConnection": { "connection": "chain-mongo" },
|
|
1059
|
+
"XyoGateway": { "connection": "chain-mongo" },
|
|
1060
|
+
"XyoGatewayRunner": { "connection": "chain-mongo" },
|
|
1061
|
+
"XyoRunner": { "connection": "chain-mongo" },
|
|
1062
|
+
"XyoViewer": { "connection": "chain-mongo" }
|
|
1063
|
+
},
|
|
1064
|
+
"actors": [
|
|
1065
|
+
{
|
|
1066
|
+
"name": "bridge",
|
|
1067
|
+
"accountPath": "0",
|
|
1068
|
+
"redisHost": "redis.internal",
|
|
1069
|
+
"redisPort": 6379,
|
|
1070
|
+
"scannerIntervalMs": 30000
|
|
1071
|
+
}
|
|
1072
|
+
]
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
346
1075
|
```
|
|
347
1076
|
|
|
348
|
-
###
|
|
1077
|
+
### Reward redemption (per-actor)
|
|
1078
|
+
|
|
1079
|
+
```json
|
|
1080
|
+
{
|
|
1081
|
+
"xl1": {
|
|
1082
|
+
"connections": {
|
|
1083
|
+
"chain-mongo": {
|
|
1084
|
+
"type": "mongo",
|
|
1085
|
+
"connectionString": "mongodb://YOUR_MONGO_USER:YOUR_MONGO_PASSWORD@db.internal:27017/?retryWrites=true&w=majority",
|
|
1086
|
+
"database": "xl1",
|
|
1087
|
+
"domain": "internal"
|
|
1088
|
+
},
|
|
1089
|
+
"default-evm-rpc": {
|
|
1090
|
+
"type": "evm-rpc",
|
|
1091
|
+
"url": "https://sepolia.infura.io/v3/YOUR_INFURA_PROJECT_ID",
|
|
1092
|
+
"chainId": "0xaa36a7"
|
|
1093
|
+
}
|
|
1094
|
+
},
|
|
1095
|
+
"chain": {
|
|
1096
|
+
"id": "dd381fbb392c85160d8b0453e446757b12384046"
|
|
1097
|
+
},
|
|
1098
|
+
"providerBindings": {
|
|
1099
|
+
"AccountBalanceViewer": { "connection": "chain-mongo" },
|
|
1100
|
+
"BlockRunner": { "connection": "chain-mongo" },
|
|
1101
|
+
"BlockValidationViewer": { "connection": "chain-mongo" },
|
|
1102
|
+
"BlockViewer": { "connection": "chain-mongo" },
|
|
1103
|
+
"ChainContractViewer": { "connection": "default-evm-rpc" },
|
|
1104
|
+
"DeadLetterQueueRunner": { "connection": "chain-mongo" },
|
|
1105
|
+
"DeadLetterQueueViewer": { "connection": "chain-mongo" },
|
|
1106
|
+
"FinalizationRunner": { "connection": "chain-mongo" },
|
|
1107
|
+
"FinalizationViewer": { "connection": "chain-mongo" },
|
|
1108
|
+
"MempoolRunner": { "connection": "chain-mongo" },
|
|
1109
|
+
"MempoolViewer": { "connection": "chain-mongo" },
|
|
1110
|
+
"StakeEventsViewer": { "connection": "default-evm-rpc" },
|
|
1111
|
+
"StakeTotalsViewer": { "connection": "default-evm-rpc" },
|
|
1112
|
+
"StakeViewer": { "connection": "default-evm-rpc" },
|
|
1113
|
+
"TimeSyncViewer": { "connection": "default-evm-rpc" },
|
|
1114
|
+
"TransactionValidationViewer": { "connection": "chain-mongo" },
|
|
1115
|
+
"TransactionViewer": { "connection": "chain-mongo" },
|
|
1116
|
+
"WindowedBlockViewer": { "connection": "chain-mongo" },
|
|
1117
|
+
"XyoConnection": { "connection": "chain-mongo" },
|
|
1118
|
+
"XyoGateway": { "connection": "chain-mongo" },
|
|
1119
|
+
"XyoGatewayRunner": { "connection": "chain-mongo" },
|
|
1120
|
+
"XyoRunner": { "connection": "chain-mongo" },
|
|
1121
|
+
"XyoViewer": { "connection": "chain-mongo" }
|
|
1122
|
+
},
|
|
1123
|
+
"actors": [
|
|
1124
|
+
{
|
|
1125
|
+
"name": "rewardRedemption",
|
|
1126
|
+
"accountPath": "0",
|
|
1127
|
+
"host": "0.0.0.0",
|
|
1128
|
+
"port": 8082
|
|
1129
|
+
}
|
|
1130
|
+
]
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1133
|
+
```
|
|
1134
|
+
## S3 object storage (finalized / chain-state / index publishing)
|
|
349
1135
|
|
|
350
1136
|
Beyond the authority store (`lmdb` / `mongodb`), the chain can publish a static, HTTP-servable copy of itself to S3-compatible object storage (e.g. Cloudflare R2). This is what serves cheap, CDN-cached reads to [`@xyo-network/xl1-rest-block-viewer`](https://www.npmjs.com/package/@xyo-network/xl1-rest-block-viewer) and the wallet / explorer clients — no RPC server in the read path. It layers on top of any backing; it does not replace it.
|
|
351
1137
|
|
|
@@ -411,7 +1197,7 @@ export XL1_ACTORS__1__PUBLISH_ON_FINALIZE=true
|
|
|
411
1197
|
export XL1_ACTORS__2__PUBLISH_SYNC_INTERVAL=5000
|
|
412
1198
|
```
|
|
413
1199
|
|
|
414
|
-
|
|
1200
|
+
## Mnemonics & wallets
|
|
415
1201
|
|
|
416
1202
|
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.
|
|
417
1203
|
|
|
@@ -429,7 +1215,7 @@ The root `mnemonic` field (or `XL1_MNEMONIC`) defines the wallet from which ever
|
|
|
429
1215
|
|
|
430
1216
|
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.
|
|
431
1217
|
|
|
432
|
-
|
|
1218
|
+
## Inspecting a configuration
|
|
433
1219
|
|
|
434
1220
|
Two CLI flags help you verify what the chain *would* do without actually starting it:
|
|
435
1221
|
|