@tokamak-private-dapps/private-state-cli 2.1.0 → 2.1.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/CHANGELOG.md +51 -0
- package/README.md +96 -34
- package/cli-assistant.html +11 -5
- package/commands/account.mjs +43 -0
- package/commands/channel.mjs +66 -0
- package/commands/index.mjs +62 -0
- package/commands/investigator.mjs +11 -0
- package/commands/notes.mjs +39 -0
- package/commands/system.mjs +49 -0
- package/commands/wallet.mjs +86 -0
- package/investigator/README.md +16 -6
- package/investigator/app.js +612 -17
- package/investigator/index.html +153 -90
- package/investigator/styles.css +277 -28
- package/lib/private-state-cli-command-registry.mjs +71 -28
- package/lib/private-state-note-delivery.mjs +7 -14
- package/lib/private-state-runtime-management.mjs +0 -1
- package/lib/runtime.mjs +11531 -0
- package/package.json +3 -2
- package/private-state-bridge-cli.mjs +2 -11053
- package/lib/private-state-tokamak-helpers.mjs +0 -184
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,57 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 2.1.2 - 2026-05-15
|
|
6
|
+
|
|
7
|
+
- Fixed wallet lifecycle recovery log lookups so account-specific registration and exit event scans
|
|
8
|
+
use the same chunked `eth_getLogs` path as the rest of RPC workspace recovery.
|
|
9
|
+
- Removed synthetic wallet lifecycle epoch fallback creation; wallet recovery now requires
|
|
10
|
+
lifecycle registration events to be found in RPC log history instead of fabricating epochs from
|
|
11
|
+
current registration state.
|
|
12
|
+
- Fixed RPC log request pacing so every `eth_getLogs` call passes through a shared async limiter
|
|
13
|
+
instead of relying on a race-prone timestamp throttle during concurrent scans.
|
|
14
|
+
- Added progress output for the wallet lifecycle registered/exited event scans that run before
|
|
15
|
+
note-delivery recovery in `wallet recover-workspace`.
|
|
16
|
+
- Added `set rpc` for per-network RPC configuration with built-in `eth_getLogs` scan-limit tables
|
|
17
|
+
for Ankr, Chainstack, Chainnodes, QuickNode, and Alchemy, using 90% of the provider reference
|
|
18
|
+
request-rate values.
|
|
19
|
+
- Simplified note-mutating command post-processing so accepted note transactions wait for the
|
|
20
|
+
receipt block, then refresh channel and wallet workspaces from their recovery indexes instead of
|
|
21
|
+
manually applying note lifecycle metadata.
|
|
22
|
+
- Extended wallet recovery to persist public creation/spend linkage from commitment and
|
|
23
|
+
nullifier storage observations so raw evidence export can package stored metadata without
|
|
24
|
+
running its own log scan.
|
|
25
|
+
- Fixed raw evidence spend linkage so nullifier observation transactions are used as the spend
|
|
26
|
+
transition references and included with their transaction, receipt, and event evidence.
|
|
27
|
+
- Redesigned the bundled investigator GUI around purpose-first disclosure requests, an interactive
|
|
28
|
+
SVG note-linkage graph, node detail overlays, and Markdown ASCII-art linkage report export.
|
|
29
|
+
- Updated private-state documentation to reflect `set rpc` as the only CLI RPC configuration path
|
|
30
|
+
for ordinary bridge-facing and wallet commands.
|
|
31
|
+
- Split the CLI entrypoint into command dispatch modules and moved the shared runtime implementation
|
|
32
|
+
under `lib/runtime.mjs`; the published package now includes the `commands/` modules.
|
|
33
|
+
- Removed the `channel get-meta` workspace mirror lookup fallback so contract lookup errors surface
|
|
34
|
+
directly instead of being hidden behind `null` metadata.
|
|
35
|
+
- Changed `channel join` to derive the wallet lifecycle epoch from the accepted join receipt instead
|
|
36
|
+
of rescanning full account registration and exit history.
|
|
37
|
+
- Changed investigator numeric block filters to reject invalid values instead of silently treating
|
|
38
|
+
them as absent filters.
|
|
39
|
+
|
|
40
|
+
## 2.1.1 - 2026-05-14
|
|
41
|
+
|
|
42
|
+
- Changed `channel recover-workspace --from-genesis` to move any existing local channel workspace
|
|
43
|
+
to `workspace-rebuild-backups/` before writing the current-format workspace. The clean rebuild
|
|
44
|
+
path is limited to workspace files and preserves local account and wallet key secrets under
|
|
45
|
+
`secrets/`.
|
|
46
|
+
- Added channel workspace recovery checkpointing at the existing RPC log chunk boundary so
|
|
47
|
+
interrupted RPC recovery can resume from the last completed chunk.
|
|
48
|
+
- Changed mirror recovery to fall back to a newer verified full mirror checkpoint when no matching
|
|
49
|
+
delta bundle exists for the local recovery index.
|
|
50
|
+
- Changed `wallet recover-workspace` to use the same bounded channel-workspace freshness preflight
|
|
51
|
+
as other wallet commands. `wallet recover-workspace --from-genesis` now restarts received-note
|
|
52
|
+
scanning from channel genesis but does not rebuild the channel workspace from genesis.
|
|
53
|
+
- Added received-note recovery checkpointing at the existing RPC log chunk boundary so ordinary
|
|
54
|
+
`wallet recover-workspace` resumes from the last completed chunk after an interruption.
|
|
55
|
+
|
|
5
56
|
## 2.1.0 - 2026-05-14
|
|
6
57
|
|
|
7
58
|
- Required current epoch-aware wallet workspaces for wallet commands and backup imports. Local
|
package/README.md
CHANGED
|
@@ -151,16 +151,25 @@ Static warning scope:
|
|
|
151
151
|
centralized-exchange controlled address as a self-custody bridge source or as the direct bridge withdrawal target
|
|
152
152
|
unless the user explicitly understands the compliance implications. Prefer a self-custody L1 wallet.
|
|
153
153
|
|
|
154
|
-
Workspace recovery commands use
|
|
155
|
-
does not contain a usable index, `channel recover-workspace`
|
|
156
|
-
silently replaying logs from channel genesis. Use
|
|
157
|
-
rebuild channel workspace state from the channel creation block:
|
|
154
|
+
Workspace recovery commands use saved recovery indexes by default. If the local channel workspace is missing,
|
|
155
|
+
corrupted, or does not contain a usable index, `channel recover-workspace` stops with an explicit error instead of
|
|
156
|
+
silently replaying logs from channel genesis. Use `channel recover-workspace --source rpc --from-genesis` only when
|
|
157
|
+
you intentionally want to rebuild channel workspace state from the channel creation block:
|
|
158
158
|
|
|
159
159
|
```bash
|
|
160
160
|
private-state-cli channel recover-workspace --channel-name <CHANNEL> --network mainnet --source rpc --from-genesis
|
|
161
|
-
private-state-cli wallet recover-workspace --channel-name <CHANNEL> --network mainnet --account <ACCOUNT> --from-genesis
|
|
162
161
|
```
|
|
163
162
|
|
|
163
|
+
When `channel recover-workspace --from-genesis` is used, the CLI treats the local channel workspace as a clean rebuild target.
|
|
164
|
+
If `~/tokamak-private-channels/workspace/<network>/<channel>` already exists, it is moved under
|
|
165
|
+
`~/tokamak-private-channels/workspace-rebuild-backups/` before the current-format workspace is
|
|
166
|
+
created. This backup step is workspace-only; files under `~/tokamak-private-channels/secrets/`,
|
|
167
|
+
including account private keys and wallet viewing/spending key files, are not removed.
|
|
168
|
+
During RPC recovery, the CLI writes a usable channel workspace checkpoint after each RPC log chunk. If an RPC recovery
|
|
169
|
+
run is interrupted, the next non-`--from-genesis` RPC recovery resumes from the last completed chunk. Mirror recovery
|
|
170
|
+
can also start from that local checkpoint: it uses a matching delta bundle when one is available, otherwise a newer
|
|
171
|
+
verified full mirror checkpoint replaces the local checkpoint before RPC catch-up.
|
|
172
|
+
|
|
164
173
|
`channel create` is the exception: after the channel is created on-chain, the CLI initializes that new local workspace
|
|
165
174
|
by replaying from the channel's genesis block because no prior recovery index can exist for a new channel.
|
|
166
175
|
|
|
@@ -169,12 +178,18 @@ registration transaction. For a channel that was created elsewhere, run `channel
|
|
|
169
178
|
once before joining, or recover from a registered workspace mirror; later joins and wallet commands resume from the
|
|
170
179
|
saved index instead of silently replaying from genesis.
|
|
171
180
|
|
|
172
|
-
Wallet
|
|
173
|
-
`wallet get-notes`, refresh stale local workspaces through saved recovery
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
181
|
+
Wallet commands that need channel state, including `wallet recover-workspace`, `wallet get-meta`,
|
|
182
|
+
`wallet get-channel-fund`, and `wallet get-notes`, refresh stale local channel workspaces through saved recovery
|
|
183
|
+
indexes before reading state. `wallet get-notes` and `wallet recover-workspace` also refresh received-note logs
|
|
184
|
+
through the saved wallet note recovery index. Automatic refresh never replays from channel genesis and only runs when
|
|
185
|
+
the recovery delta fits within the 7,200-block pre-command budget. If a saved index is missing, unusable, or too far
|
|
186
|
+
behind, the command stops and asks the user to run the appropriate recovery command first.
|
|
187
|
+
|
|
188
|
+
Wallet note-delivery recovery checkpoints after each RPC log chunk by updating
|
|
189
|
+
`noteReceiveLastScannedBlock`. If an ordinary `wallet recover-workspace` run is interrupted during note recovery, the
|
|
190
|
+
next run resumes from the last completed chunk. This does not add a special resume path for
|
|
191
|
+
`wallet recover-workspace --from-genesis`; that command intentionally starts received-note scanning from channel
|
|
192
|
+
genesis after the channel workspace has passed the same freshness preflight used by other wallet commands.
|
|
178
193
|
|
|
179
194
|
Local wallet workspaces are epoch-aware. Each successful channel registration creates a wallet epoch under the
|
|
180
195
|
canonical wallet directory. `channel exit` does not delete the local wallet workspace; it marks the active epoch as
|
|
@@ -249,8 +264,11 @@ private-state-cli investigator
|
|
|
249
264
|
```
|
|
250
265
|
|
|
251
266
|
The command prints the bundled investigator HTML path and file URL, then opens the static browser GUI. Load the raw
|
|
252
|
-
evidence ZIP in that GUI,
|
|
253
|
-
|
|
267
|
+
evidence ZIP in that GUI, choose the disclosure request type, inspect the interactive note-linkage graph, and export a
|
|
268
|
+
narrower user-consent disclosure ZIP. The graph view renders every matched note as a node and shows creation, spend,
|
|
269
|
+
and local note-to-note linkage edges when the raw bundle contains enough local evidence. The GUI can also export a
|
|
270
|
+
Markdown ASCII-art linkage report with a compact graph section and per-note detail sections. The GUI runs locally in the
|
|
271
|
+
browser and does not send files over the network.
|
|
254
272
|
|
|
255
273
|
The investigator accepts current epoch-aware evidence bundles only. If a bundle was generated by an older CLI, rebuild
|
|
256
274
|
the wallet workspace with `wallet recover-workspace` and export a new bundle with `wallet get-notes --export-evidence`.
|
|
@@ -258,7 +276,7 @@ the wallet workspace with `wallet recover-workspace` and export a new bundle wit
|
|
|
258
276
|
Estimate live transaction costs before sending commands with:
|
|
259
277
|
|
|
260
278
|
```bash
|
|
261
|
-
private-state-cli help transaction-fees --network mainnet
|
|
279
|
+
private-state-cli help transaction-fees --network mainnet
|
|
262
280
|
```
|
|
263
281
|
|
|
264
282
|
`help transaction-fees` uses the measured gas data packaged in `assets/tx-fees.json`, the selected network's live fee data,
|
|
@@ -351,8 +369,9 @@ note-delivery events and rebuild the user's readable note view. Sharing it gives
|
|
|
351
369
|
registered note-receive public key, but not spending authority.
|
|
352
370
|
|
|
353
371
|
The spending key is the channel-bound L2 private key. It authorizes proof-backed use of the wallet identity. Commands
|
|
354
|
-
that consume
|
|
355
|
-
the
|
|
372
|
+
that create or consume notes, such as `wallet mint-notes`, `wallet transfer-notes`, and `wallet redeem-notes`, need both
|
|
373
|
+
the viewing key and the spending key because the CLI refreshes the readable note workspace after accepted note
|
|
374
|
+
transactions and then proves authorized note use when inputs are consumed.
|
|
356
375
|
|
|
357
376
|
Key recovery is intentionally split. Recreating the viewing key requires the original L1 private key and the same channel
|
|
358
377
|
context. Recreating the spending key requires the original L1 private key, the same channel context, and the same wallet
|
|
@@ -375,11 +394,40 @@ The CLI stores user workspaces under:
|
|
|
375
394
|
Wallet backup metadata lives under the channel workspace. Viewing and spending private keys live as separate protected
|
|
376
395
|
key files under `~/tokamak-private-channels/secrets/<network>/wallets/<wallet>/`.
|
|
377
396
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
397
|
+
Configure the network RPC endpoint before bridge-facing or wallet recovery commands:
|
|
398
|
+
|
|
399
|
+
```bash
|
|
400
|
+
private-state-cli set rpc --network mainnet --rpc-url <RPC_URL> --provider alchemy
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
The CLI writes `~/tokamak-private-channels/workspace/<network>/rpc-config.env` and later commands read `RPC_URL`,
|
|
404
|
+
`LOG_CHUNK_SIZE`, `LOG_REQUESTS_PER_SECOND`, and `RPC_BLOCK_RANGE_CAP` from that file. Built-in provider limits are
|
|
405
|
+
set to 90% of the provider reference values: Ankr `27 calls/s, 3000 blocks`; Chainstack `22.5 calls/s, 100 blocks`;
|
|
406
|
+
Chainnodes `22.5 calls/s, 20000 blocks`; QuickNode `13.5 calls/s, 5 blocks`; Alchemy `7.497 calls/s, 10 blocks`.
|
|
407
|
+
If the provider is not listed, use
|
|
408
|
+
`--log-requests-per-second <N>` and `--block-range-cap <N>` instead of `--provider`.
|
|
409
|
+
|
|
410
|
+
### Slow Workspace Recovery
|
|
411
|
+
|
|
412
|
+
`channel recover-workspace` and `wallet recover-workspace` scan on-chain logs with `eth_getLogs`. If recovery is
|
|
413
|
+
unexpectedly slow, first check the RPC scan limits saved by `set rpc`. The main speed factors are the provider's
|
|
414
|
+
`eth_getLogs` block range cap and the allowed log request rate. A small block range cap can turn the same channel scan
|
|
415
|
+
into thousands of RPC calls.
|
|
416
|
+
|
|
417
|
+
For example, an Alchemy free-tier-style cap of `10` blocks is much slower for long recovery scans than Ankr's built-in
|
|
418
|
+
`3000` block setting or Chainnodes' built-in `20000` block setting. When recovery is too slow, re-run `set rpc` with a
|
|
419
|
+
provider that supports a larger `eth_getLogs` block range cap, or provide explicit values:
|
|
420
|
+
|
|
421
|
+
```bash
|
|
422
|
+
private-state-cli set rpc --network mainnet --rpc-url <RPC_URL> --provider ankr
|
|
423
|
+
private-state-cli set rpc --network mainnet --rpc-url <RPC_URL> --log-requests-per-second <N> --block-range-cap <N>
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
If an RPC provider rejects the configured range or rate during recovery, run `set rpc` again with limits that match the
|
|
427
|
+
provider's documented `eth_getLogs` policy, then retry the recovery command.
|
|
428
|
+
|
|
429
|
+
Canonical CLI secrets are checked on read: macOS/Linux uses `0600`, while Windows uses ACL repair and inspection when
|
|
430
|
+
possible.
|
|
383
431
|
|
|
384
432
|
## LLM Agent Guidance
|
|
385
433
|
|
|
@@ -414,28 +462,42 @@ Operating rules:
|
|
|
414
462
|
- A viewing key decrypts encrypted note-delivery events for the registered note-receive public key. A spending key is
|
|
415
463
|
the channel-bound L2 private key used to authorize note use. Do not describe either key as interchangeable with the
|
|
416
464
|
other.
|
|
417
|
-
- The network RPC URL is the endpoint used to read and write chain state. It
|
|
418
|
-
|
|
465
|
+
- The network RPC URL is the endpoint used to read and write chain state. It must be configured once with
|
|
466
|
+
`private-state-cli set rpc --network <NETWORK> --rpc-url <URL> --provider <PROVIDER>`, or with explicit
|
|
467
|
+
`--log-requests-per-second` and `--block-range-cap` values when the provider is not built in.
|
|
419
468
|
- A workspace recovery index is the saved block pointer and state-root hash that lets the CLI resume log scanning
|
|
420
469
|
without replaying the channel from its creation block. If it is missing, explain `--from-genesis` before using it
|
|
421
470
|
because genesis replay can take much longer.
|
|
471
|
+
- Before guiding a user to run `channel recover-workspace --source rpc --from-genesis`, explain that RPC genesis
|
|
472
|
+
recovery can be very slow because it scans channel logs from the creation block. If a channel workspace mirror is
|
|
473
|
+
available, try mirror-based recovery first, and use RPC genesis replay only when mirror recovery is unavailable or
|
|
474
|
+
unsuitable.
|
|
475
|
+
- When `channel recover-workspace` or `wallet recover-workspace` is unexpectedly slow, first inspect the RPC provider
|
|
476
|
+
configured by `set rpc`. Explain that recovery speed is dominated by `eth_getLogs` block range cap and log request
|
|
477
|
+
rate. Suggest re-running `set rpc` with a provider that supports a larger block range cap, such as Ankr or Chainnodes
|
|
478
|
+
when appropriate, or with explicit `--log-requests-per-second` and `--block-range-cap` values from the provider's
|
|
479
|
+
documentation.
|
|
480
|
+
- When a CLI command fails, read the error message and any printed `Try:` hints first. Prefer the corrective action
|
|
481
|
+
suggested by the CLI before inventing a different recovery sequence.
|
|
422
482
|
- When the user does not have a network RPC URL yet, explain that they need an Ethereum JSON-RPC endpoint for the
|
|
423
|
-
selected network. They can obtain one from an infrastructure provider such as Alchemy,
|
|
424
|
-
their own node. Ask the user to create or select the endpoint in that provider's UI, then paste only
|
|
425
|
-
|
|
426
|
-
private keys, or wallet secrets.
|
|
483
|
+
selected network. They can obtain one from an infrastructure provider such as Alchemy, Ankr, Chainstack, Chainnodes,
|
|
484
|
+
QuickNode, or from their own node. Ask the user to create or select the endpoint in that provider's UI, then paste only
|
|
485
|
+
the endpoint URL into `private-state-cli set rpc`; do not ask for provider account passwords, API dashboards, seed
|
|
486
|
+
phrases, private keys, or wallet secrets.
|
|
427
487
|
- When a user wants to join a channel, do not jump straight to `channel join`. Walk them through:
|
|
428
488
|
1. choose the network and channel name
|
|
429
489
|
2. run `private-state-cli install`
|
|
430
490
|
3. run `private-state-cli help doctor`
|
|
431
491
|
4. obtain or confirm a network RPC URL for the selected network
|
|
432
|
-
5.
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
492
|
+
5. run `set rpc --network <NETWORK> --rpc-url <URL> --provider <PROVIDER>`, or use explicit scan limits for an
|
|
493
|
+
unlisted provider
|
|
494
|
+
6. prepare a private key source file locally, without pasting the key into chat
|
|
495
|
+
7. run `account import --account <NAME> --network <NETWORK> --private-key-file <PATH>`
|
|
496
|
+
8. prepare a wallet secret source file locally, for example with `openssl rand -hex 32 > ./wallet-secret.txt`
|
|
497
|
+
9. inspect the channel with `channel get-meta` if it already exists, or create it with `channel create` if the user is
|
|
436
498
|
the channel creator
|
|
437
|
-
|
|
438
|
-
|
|
499
|
+
10. explain the immutable policy warning printed by the CLI
|
|
500
|
+
11. run `channel join --channel-name <CHANNEL> --network <NETWORK> --account <ACCOUNT> --wallet-secret-path <PATH> --acknowledge-action-impact`
|
|
439
501
|
- Before executing any command for a user that requires an `--acknowledge-*` option, strongly warn the user in plain
|
|
440
502
|
language about what that acknowledgement means and ask for explicit confirmation. Do not add
|
|
441
503
|
`--acknowledge-action-impact` or `--acknowledge-full-note-plaintext-export` on the user's behalf until they confirm.
|
|
@@ -481,7 +543,7 @@ Suggested interaction flow:
|
|
|
481
543
|
`wallet mint-notes`.
|
|
482
544
|
7. For a confidential note transfer, select available note IDs from `wallet get-notes`, find the recipient L2 address from
|
|
483
545
|
`wallet get-meta`, then build `wallet transfer-notes`.
|
|
484
|
-
8. After transfer, guide the recipient to run `wallet get-notes`; it refreshes received notes from the saved recovery index when the delta fits the 7,200-block pre-command budget. If the index is missing or too far behind, explain `wallet recover-workspace
|
|
546
|
+
8. After transfer, guide the recipient to run `wallet get-notes`; it refreshes received notes from the saved recovery index when the delta fits the 7,200-block pre-command budget. If the index is missing or too far behind, explain `wallet recover-workspace`.
|
|
485
547
|
|
|
486
548
|
Example onboarding explanation for `channel join`:
|
|
487
549
|
|
package/cli-assistant.html
CHANGED
|
@@ -413,16 +413,22 @@
|
|
|
413
413
|
<h2>Command Guide</h2>
|
|
414
414
|
<div class="box">
|
|
415
415
|
<ol class="guide-list">
|
|
416
|
+
<li>
|
|
417
|
+
<span class="guide-label">Configure RPC:</span> <code>set rpc</code>
|
|
418
|
+
<div class="guide-example">
|
|
419
|
+
<code>set rpc --network 'sepolia' --rpc-url '__RPC_URL__' --provider 'alchemy'</code>
|
|
420
|
+
</div>
|
|
421
|
+
</li>
|
|
416
422
|
<li>
|
|
417
423
|
<span class="guide-label">Join a channel:</span> <code>channel join</code>
|
|
418
424
|
<div class="guide-example">
|
|
419
|
-
<code>channel join --channel-name 'my-private-channel' --network 'sepolia' --account 'my-account' --wallet-secret-path '/path/to/wallet-secret'
|
|
425
|
+
<code>channel join --channel-name 'my-private-channel' --network 'sepolia' --account 'my-account' --wallet-secret-path '/path/to/wallet-secret'</code>
|
|
420
426
|
</div>
|
|
421
427
|
</li>
|
|
422
428
|
<li>
|
|
423
429
|
<span class="guide-label">Create notes:</span> <code>account deposit-bridge</code> -> <code>wallet deposit-channel</code> -> <code>wallet mint-notes</code>
|
|
424
430
|
<div class="guide-example">
|
|
425
|
-
<code>account deposit-bridge --amount '100' --network 'sepolia' --account 'my-account'
|
|
431
|
+
<code>account deposit-bridge --amount '100' --network 'sepolia' --account 'my-account'</code><br />
|
|
426
432
|
<code>wallet deposit-channel --wallet 'my-private-channel-0xYourL1Address' --network 'sepolia' --amount '100'</code><br />
|
|
427
433
|
<code>wallet mint-notes --wallet 'my-private-channel-0xYourL1Address' --network 'sepolia' --amounts '["50","50","0"]'</code>
|
|
428
434
|
</div>
|
|
@@ -438,7 +444,7 @@
|
|
|
438
444
|
<div class="guide-example">
|
|
439
445
|
<code>wallet redeem-notes --wallet 'my-private-channel-0xYourL1Address' --network 'sepolia' --note-ids '["0xNoteIdA"]'</code><br />
|
|
440
446
|
<code>wallet withdraw-channel --wallet 'my-private-channel-0xYourL1Address' --network 'sepolia' --amount '25'</code><br />
|
|
441
|
-
<code>account withdraw-bridge --amount '25' --network 'sepolia' --account 'my-account'
|
|
447
|
+
<code>account withdraw-bridge --amount '25' --network 'sepolia' --account 'my-account'</code>
|
|
442
448
|
</div>
|
|
443
449
|
</li>
|
|
444
450
|
</ol>
|
|
@@ -1420,7 +1426,7 @@
|
|
|
1420
1426
|
].forEach((fieldKey) => {
|
|
1421
1427
|
memoryFieldsEl.appendChild(createField(fieldKey));
|
|
1422
1428
|
});
|
|
1423
|
-
memoryStatusEl.textContent = "Use account import --private-key-file before signing commands.
|
|
1429
|
+
memoryStatusEl.textContent = "Use set rpc once before bridge-facing commands, then use account import --private-key-file before signing commands.";
|
|
1424
1430
|
}
|
|
1425
1431
|
|
|
1426
1432
|
function renderCommandSelect() {
|
|
@@ -1480,7 +1486,7 @@
|
|
|
1480
1486
|
: "",
|
|
1481
1487
|
].join("");
|
|
1482
1488
|
warningEl.textContent = missing.length === 0
|
|
1483
|
-
? `Ready.
|
|
1489
|
+
? `Ready. Bridge-facing commands use the saved network RPC configuration.${workspaceWarnings}`
|
|
1484
1490
|
: `Missing inputs: ${missing.map((fieldKey) => fieldCatalog[fieldKey].label).join(", ")}.${workspaceWarnings}`;
|
|
1485
1491
|
}
|
|
1486
1492
|
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import {
|
|
2
|
+
assertAccountGetBridgeFundArgs,
|
|
3
|
+
assertAccountGetL1AddressArgs,
|
|
4
|
+
assertAccountImportArgs,
|
|
5
|
+
assertDepositBridgeArgs,
|
|
6
|
+
assertWithdrawBridgeArgs,
|
|
7
|
+
handleAccountGetBridgeFund,
|
|
8
|
+
handleAccountGetL1Address,
|
|
9
|
+
handleAccountImport,
|
|
10
|
+
handleDepositBridge,
|
|
11
|
+
handleWithdrawBridge,
|
|
12
|
+
loadExplicitCommandRuntime,
|
|
13
|
+
prepareDeploymentArtifacts,
|
|
14
|
+
} from "../lib/runtime.mjs";
|
|
15
|
+
|
|
16
|
+
export const accountCommands = Object.freeze({
|
|
17
|
+
"account-get-l1-address": async (args) => {
|
|
18
|
+
assertAccountGetL1AddressArgs(args);
|
|
19
|
+
handleAccountGetL1Address({ args });
|
|
20
|
+
},
|
|
21
|
+
"account-import": async (args) => {
|
|
22
|
+
assertAccountImportArgs(args);
|
|
23
|
+
handleAccountImport({ args });
|
|
24
|
+
},
|
|
25
|
+
"account-get-bridge-fund": async (args) => {
|
|
26
|
+
assertAccountGetBridgeFundArgs(args);
|
|
27
|
+
const { network, provider } = loadExplicitCommandRuntime(args);
|
|
28
|
+
await prepareDeploymentArtifacts(network.chainId);
|
|
29
|
+
await handleAccountGetBridgeFund({ args, provider });
|
|
30
|
+
},
|
|
31
|
+
"account-deposit-bridge": async (args) => {
|
|
32
|
+
assertDepositBridgeArgs(args);
|
|
33
|
+
const { network, provider } = loadExplicitCommandRuntime(args);
|
|
34
|
+
await prepareDeploymentArtifacts(network.chainId);
|
|
35
|
+
await handleDepositBridge({ args, network, provider });
|
|
36
|
+
},
|
|
37
|
+
"account-withdraw-bridge": async (args) => {
|
|
38
|
+
assertWithdrawBridgeArgs(args);
|
|
39
|
+
const { network, provider } = loadExplicitCommandRuntime(args);
|
|
40
|
+
await prepareDeploymentArtifacts(network.chainId);
|
|
41
|
+
await handleWithdrawBridge({ args, network, provider });
|
|
42
|
+
},
|
|
43
|
+
});
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import {
|
|
2
|
+
assertCreateChannelArgs,
|
|
3
|
+
assertExitChannelArgs,
|
|
4
|
+
assertGetChannelArgs,
|
|
5
|
+
assertJoinChannelArgs,
|
|
6
|
+
assertProviderChainIdMatchesNetwork,
|
|
7
|
+
assertPublishWorkspaceMirrorArgs,
|
|
8
|
+
assertRecoverWorkspaceArgs,
|
|
9
|
+
assertSetWorkspaceMirrorArgs,
|
|
10
|
+
handleChannelCreate,
|
|
11
|
+
handleExitChannel,
|
|
12
|
+
handleGetChannel,
|
|
13
|
+
handleJoinChannel,
|
|
14
|
+
handlePublishChannelWorkspaceMirror,
|
|
15
|
+
handleSetChannelWorkspaceMirror,
|
|
16
|
+
handleWorkspaceInit,
|
|
17
|
+
loadExplicitCommandRuntime,
|
|
18
|
+
loadWalletCommandRuntime,
|
|
19
|
+
prepareDeploymentArtifacts,
|
|
20
|
+
} from "../lib/runtime.mjs";
|
|
21
|
+
|
|
22
|
+
export const channelCommands = Object.freeze({
|
|
23
|
+
"channel-create": async (args) => {
|
|
24
|
+
assertCreateChannelArgs(args);
|
|
25
|
+
const { network, provider } = loadExplicitCommandRuntime(args);
|
|
26
|
+
await prepareDeploymentArtifacts(network.chainId);
|
|
27
|
+
await handleChannelCreate({ args, network, provider });
|
|
28
|
+
},
|
|
29
|
+
"channel-recover-workspace": async (args) => {
|
|
30
|
+
assertRecoverWorkspaceArgs(args);
|
|
31
|
+
const { network, provider, rpcUrl } = loadExplicitCommandRuntime(args, { staticNetwork: true });
|
|
32
|
+
await assertProviderChainIdMatchesNetwork({ provider, network, rpcUrl });
|
|
33
|
+
await prepareDeploymentArtifacts(network.chainId);
|
|
34
|
+
await handleWorkspaceInit({ args, network, provider });
|
|
35
|
+
},
|
|
36
|
+
"channel-get-meta": async (args) => {
|
|
37
|
+
assertGetChannelArgs(args);
|
|
38
|
+
const { network, provider } = loadExplicitCommandRuntime(args);
|
|
39
|
+
await prepareDeploymentArtifacts(network.chainId);
|
|
40
|
+
await handleGetChannel({ args, network, provider });
|
|
41
|
+
},
|
|
42
|
+
"channel-set-workspace-mirror": async (args) => {
|
|
43
|
+
assertSetWorkspaceMirrorArgs(args);
|
|
44
|
+
const { network, provider } = loadExplicitCommandRuntime(args);
|
|
45
|
+
await prepareDeploymentArtifacts(network.chainId);
|
|
46
|
+
await handleSetChannelWorkspaceMirror({ args, network, provider });
|
|
47
|
+
},
|
|
48
|
+
"channel-publish-workspace-mirror": async (args) => {
|
|
49
|
+
assertPublishWorkspaceMirrorArgs(args);
|
|
50
|
+
const { network, provider } = loadExplicitCommandRuntime(args);
|
|
51
|
+
await prepareDeploymentArtifacts(network.chainId);
|
|
52
|
+
await handlePublishChannelWorkspaceMirror({ args, network, provider });
|
|
53
|
+
},
|
|
54
|
+
"channel-join": async (args) => {
|
|
55
|
+
assertJoinChannelArgs(args);
|
|
56
|
+
const { network, provider, rpcUrl } = loadExplicitCommandRuntime(args);
|
|
57
|
+
await prepareDeploymentArtifacts(network.chainId);
|
|
58
|
+
await handleJoinChannel({ args, network, provider, rpcUrl });
|
|
59
|
+
},
|
|
60
|
+
"channel-exit": async (args) => {
|
|
61
|
+
assertExitChannelArgs(args);
|
|
62
|
+
const { network, provider } = loadWalletCommandRuntime(args);
|
|
63
|
+
await prepareDeploymentArtifacts(network.chainId);
|
|
64
|
+
await handleExitChannel({ args, provider });
|
|
65
|
+
},
|
|
66
|
+
});
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import {
|
|
2
|
+
assertHelpCommandsArgs,
|
|
3
|
+
assertVersionArgs,
|
|
4
|
+
configureOutput,
|
|
5
|
+
formatCliErrorForDisplay,
|
|
6
|
+
parseArgs,
|
|
7
|
+
printHelp,
|
|
8
|
+
printVersion,
|
|
9
|
+
} from "../lib/runtime.mjs";
|
|
10
|
+
import { accountCommands } from "./account.mjs";
|
|
11
|
+
import { channelCommands } from "./channel.mjs";
|
|
12
|
+
import { investigatorCommands } from "./investigator.mjs";
|
|
13
|
+
import { notesCommands } from "./notes.mjs";
|
|
14
|
+
import { systemCommands } from "./system.mjs";
|
|
15
|
+
import { walletCommands } from "./wallet.mjs";
|
|
16
|
+
|
|
17
|
+
const COMMANDS = Object.freeze({
|
|
18
|
+
...systemCommands,
|
|
19
|
+
...investigatorCommands,
|
|
20
|
+
...accountCommands,
|
|
21
|
+
...channelCommands,
|
|
22
|
+
...walletCommands,
|
|
23
|
+
...notesCommands,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
export async function runPrivateStateCli(argv) {
|
|
27
|
+
let args = {};
|
|
28
|
+
try {
|
|
29
|
+
args = parseArgs(argv);
|
|
30
|
+
configureOutput(args);
|
|
31
|
+
|
|
32
|
+
if (args.version !== undefined) {
|
|
33
|
+
assertVersionArgs(args);
|
|
34
|
+
printVersion();
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (args.help || !args.command) {
|
|
39
|
+
printHelp();
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (args.command === "help-commands") {
|
|
44
|
+
assertHelpCommandsArgs(args);
|
|
45
|
+
printHelp();
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const command = COMMANDS[args.command];
|
|
50
|
+
if (!command) {
|
|
51
|
+
throw new Error(`Unsupported command: ${args.command}`);
|
|
52
|
+
}
|
|
53
|
+
await command(args);
|
|
54
|
+
} catch (error) {
|
|
55
|
+
console.error(formatCliErrorForDisplay(error, args));
|
|
56
|
+
process.exitCode = 1;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function privateStateCliDispatchTable() {
|
|
61
|
+
return COMMANDS;
|
|
62
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import {
|
|
2
|
+
assertMintNotesArgs,
|
|
3
|
+
assertRedeemNotesArgs,
|
|
4
|
+
assertTransferNotesArgs,
|
|
5
|
+
assertWalletGetNotesArgs,
|
|
6
|
+
handleMintNotes,
|
|
7
|
+
handleRedeemNotes,
|
|
8
|
+
handleTransferNotes,
|
|
9
|
+
handleWalletGetNotes,
|
|
10
|
+
loadWalletCommandRuntime,
|
|
11
|
+
prepareDeploymentArtifacts,
|
|
12
|
+
} from "../lib/runtime.mjs";
|
|
13
|
+
|
|
14
|
+
export const notesCommands = Object.freeze({
|
|
15
|
+
"wallet-mint-notes": async (args) => {
|
|
16
|
+
assertMintNotesArgs(args);
|
|
17
|
+
const { network, provider } = loadWalletCommandRuntime(args);
|
|
18
|
+
await prepareDeploymentArtifacts(network.chainId);
|
|
19
|
+
await handleMintNotes({ args, provider });
|
|
20
|
+
},
|
|
21
|
+
"wallet-redeem-notes": async (args) => {
|
|
22
|
+
assertRedeemNotesArgs(args);
|
|
23
|
+
const { network, provider } = loadWalletCommandRuntime(args);
|
|
24
|
+
await prepareDeploymentArtifacts(network.chainId);
|
|
25
|
+
await handleRedeemNotes({ args, provider });
|
|
26
|
+
},
|
|
27
|
+
"wallet-get-notes": async (args) => {
|
|
28
|
+
assertWalletGetNotesArgs(args);
|
|
29
|
+
const { network, provider } = loadWalletCommandRuntime(args);
|
|
30
|
+
await prepareDeploymentArtifacts(network.chainId);
|
|
31
|
+
await handleWalletGetNotes({ args, provider });
|
|
32
|
+
},
|
|
33
|
+
"wallet-transfer-notes": async (args) => {
|
|
34
|
+
assertTransferNotesArgs(args);
|
|
35
|
+
const { network, provider } = loadWalletCommandRuntime(args);
|
|
36
|
+
await prepareDeploymentArtifacts(network.chainId);
|
|
37
|
+
await handleTransferNotes({ args, provider });
|
|
38
|
+
},
|
|
39
|
+
});
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import {
|
|
2
|
+
assertDoctorArgs,
|
|
3
|
+
assertGuideArgs,
|
|
4
|
+
assertInstallZkEvmArgs,
|
|
5
|
+
assertSetRpcArgs,
|
|
6
|
+
assertTransactionFeesArgs,
|
|
7
|
+
assertUninstallArgs,
|
|
8
|
+
assertUpdateArgs,
|
|
9
|
+
handleDoctor,
|
|
10
|
+
handleGuide,
|
|
11
|
+
handleInstallZkEvm,
|
|
12
|
+
handleSetRpc,
|
|
13
|
+
handleTransactionFees,
|
|
14
|
+
handleUninstall,
|
|
15
|
+
handleUpdate,
|
|
16
|
+
loadExplicitCommandRuntime,
|
|
17
|
+
} from "../lib/runtime.mjs";
|
|
18
|
+
|
|
19
|
+
export const systemCommands = Object.freeze({
|
|
20
|
+
install: async (args) => {
|
|
21
|
+
assertInstallZkEvmArgs(args);
|
|
22
|
+
await handleInstallZkEvm({ args });
|
|
23
|
+
},
|
|
24
|
+
uninstall: async (args) => {
|
|
25
|
+
assertUninstallArgs(args);
|
|
26
|
+
await handleUninstall();
|
|
27
|
+
},
|
|
28
|
+
"set-rpc": async (args) => {
|
|
29
|
+
assertSetRpcArgs(args);
|
|
30
|
+
await handleSetRpc({ args });
|
|
31
|
+
},
|
|
32
|
+
"help-update": async (args) => {
|
|
33
|
+
assertUpdateArgs(args);
|
|
34
|
+
await handleUpdate();
|
|
35
|
+
},
|
|
36
|
+
"help-doctor": async (args) => {
|
|
37
|
+
assertDoctorArgs(args);
|
|
38
|
+
await handleDoctor({ args });
|
|
39
|
+
},
|
|
40
|
+
"help-guide": async (args) => {
|
|
41
|
+
assertGuideArgs(args);
|
|
42
|
+
await handleGuide({ args });
|
|
43
|
+
},
|
|
44
|
+
"help-transaction-fees": async (args) => {
|
|
45
|
+
assertTransactionFeesArgs(args);
|
|
46
|
+
const { network, provider, rpcUrl } = loadExplicitCommandRuntime(args);
|
|
47
|
+
await handleTransactionFees({ network, provider, rpcUrl });
|
|
48
|
+
},
|
|
49
|
+
});
|