@tokamak-private-dapps/private-state-cli 2.1.2 → 2.2.1
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 +16 -0
- package/README.md +52 -16
- package/commands/account.mjs +3 -7
- package/commands/channel.mjs +7 -15
- package/commands/notes.mjs +4 -9
- package/commands/wallet.mjs +5 -11
- package/lib/private-state-cli-command-registry.mjs +51 -10
- package/lib/private-state-runtime-management.mjs +299 -35
- package/lib/runtime.mjs +357 -121
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 2.2.1 - 2026-05-18
|
|
6
|
+
|
|
7
|
+
- Added `channel recover-workspace --source rpc --output-raw` to append raw JSON-RPC request and response history
|
|
8
|
+
to method-specific JSON files under the channel workspace `rpcCallHistory/` directory, with `eth_getLogs` split by event.
|
|
9
|
+
Indexed recovery appends to existing history; `--from-genesis` overwrites it with one full genesis-to-latest scan.
|
|
10
|
+
|
|
11
|
+
## 2.2.0 - 2026-05-18
|
|
12
|
+
|
|
13
|
+
- Added `install --read-only` for channel-state read commands and commands that do not depend on channel state. This
|
|
14
|
+
mode installs only the bridge deployment, bridge ABI manifest, DApp deployment, and storage layout artifacts.
|
|
15
|
+
- Kept default `install` as full mode for proof-backed and channel-mutating commands, and made deployment artifact
|
|
16
|
+
validation mode-aware before command execution.
|
|
17
|
+
- Extended `help doctor` with per-command availability so read-only installs clearly report which commands are usable
|
|
18
|
+
and which commands still require full install.
|
|
19
|
+
- Added private-state CLI E2E coverage for the read-only install mode before the full install flow.
|
|
20
|
+
|
|
5
21
|
## 2.1.2 - 2026-05-15
|
|
6
22
|
|
|
7
23
|
- Fixed wallet lifecycle recovery log lookups so account-specific registration and exit event scans
|
package/README.md
CHANGED
|
@@ -4,16 +4,16 @@ Command-line client for the Tokamak private-state DApp.
|
|
|
4
4
|
|
|
5
5
|
The full private-state DApp documentation is published with the repository:
|
|
6
6
|
|
|
7
|
-
- https://github.com/tokamak-network/Tokamak-zk-EVM-contracts/tree/main/
|
|
7
|
+
- https://github.com/tokamak-network/Tokamak-zk-EVM-contracts/tree/main/docs/dapps/private-state
|
|
8
8
|
|
|
9
|
-
## Terminology And
|
|
9
|
+
## Terminology And Exchange Boundary
|
|
10
10
|
|
|
11
11
|
This npm README uses the same terminology as the repository README:
|
|
12
12
|
|
|
13
13
|
- `Tokamak Private App Channels`: Ethereum-settled, validity-proven execution domains for bridge-coupled DApps.
|
|
14
14
|
- `private-state DApp`: the current reference DApp that programs confidential application state inside a channel.
|
|
15
15
|
- `canonical Tokamak Network Token`: the L1 asset whose custody remains anchored on Ethereum.
|
|
16
|
-
- `self-custody L1 wallet`: a user-controlled L1 account, not
|
|
16
|
+
- `self-custody L1 wallet`: a user-controlled L1 account, not an exchange deposit address.
|
|
17
17
|
- `L1-transparent bridge edge`: public bridge deposit and withdrawal transactions involving the canonical token.
|
|
18
18
|
- `channel-local accounting balance`: liquid application balance inside a channel before or after note use.
|
|
19
19
|
- `private-state note`: a channel-local application note, not an exchange-supported token or deposit asset.
|
|
@@ -22,10 +22,20 @@ This npm README uses the same terminology as the repository README:
|
|
|
22
22
|
- `viewing key`: the note-receive private key used to decrypt note-delivery events for the registered note-receive public key.
|
|
23
23
|
- `spending key`: the channel-bound L2 private key used to authorize proof-backed note use.
|
|
24
24
|
|
|
25
|
-
Tokamak Private App Channels are not
|
|
25
|
+
Tokamak Private App Channels are not an exchange deposit network. Exchange-facing token transfers and bridge
|
|
26
26
|
entry or exit remain public L1 activity. Internal private-state note counterparty relationships and note provenance are
|
|
27
27
|
not public by default and are not reconstructed by Tokamak on a user's behalf.
|
|
28
28
|
|
|
29
|
+
## Address And Key-Safety Warnings
|
|
30
|
+
|
|
31
|
+
Do not use an exchange deposit address as a private-state wallet address. Private-state notes are not
|
|
32
|
+
supported exchange assets. Always withdraw TON to a self-custody L1 wallet before using a channel.
|
|
33
|
+
|
|
34
|
+
Bridge deposits and withdrawals are public L1 events. Internal note transfers are private by design and are not
|
|
35
|
+
automatically reconstructible by Tokamak, exchanges, or public observers.
|
|
36
|
+
|
|
37
|
+
This CLI does not send your spending key, wallet secret, or private note plaintext to Tokamak.
|
|
38
|
+
|
|
29
39
|
## Tokamak-Operated Mainnet Channels
|
|
30
40
|
|
|
31
41
|
The table below lists private-state mainnet channels directly opened by Tokamak Network. Dates are
|
|
@@ -41,8 +51,8 @@ UTC.
|
|
|
41
51
|
npm install -g @tokamak-private-dapps/private-state-cli
|
|
42
52
|
```
|
|
43
53
|
|
|
44
|
-
Install the local Tokamak zk-EVM runtime workspace, Groth16 runtime workspace, and public private-state deployment
|
|
45
|
-
artifacts:
|
|
54
|
+
Install the full local Tokamak zk-EVM runtime workspace, Groth16 runtime workspace, and public private-state deployment
|
|
55
|
+
artifacts needed by transaction-sending channel commands:
|
|
46
56
|
|
|
47
57
|
```bash
|
|
48
58
|
private-state-cli install
|
|
@@ -61,6 +71,18 @@ selected Groth16 CLI package version.
|
|
|
61
71
|
The Tokamak zk-EVM installer requires the selected CLI package to declare
|
|
62
72
|
`tokamakZkEvm.compatibleBackendVersion` as a canonical major.minor version matching the selected package version.
|
|
63
73
|
|
|
74
|
+
For read-only channel recovery, channel metadata lookup, wallet recovery, wallet metadata lookup, bridge balance
|
|
75
|
+
lookup, bridge deposit, bridge withdrawal, and local helper commands, install only the read-only artifact subset:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
private-state-cli install --read-only
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Read-only install materializes only `bridge.<chainId>.json`, `bridge-abi-manifest.<chainId>.json`,
|
|
82
|
+
`deployment.<chainId>.latest.json`, and `storage-layout.<chainId>.latest.json`. It does not install the Tokamak
|
|
83
|
+
zk-EVM runtime, Groth16 runtime, Groth16 zkey, callable DApp ABI, or DApp registration artifact, so commands that
|
|
84
|
+
create or mutate channel state require a later full `private-state-cli install`.
|
|
85
|
+
|
|
64
86
|
`install` downloads public deployment artifacts from the configured artifact index. It does not read repository-local
|
|
65
87
|
`deployment/` outputs by default. Repository development workflows that need local anvil artifacts can opt in explicitly:
|
|
66
88
|
|
|
@@ -147,8 +169,8 @@ Static warning scope:
|
|
|
147
169
|
| `wallet redeem-notes` | L1 submitter, input nullifier, accounting update, root update | Consumes notes | Prior path by which the note was received |
|
|
148
170
|
| `wallet withdraw-channel` | L1 submitter, registered L2 address, amount, channel id, accounting update | No direct note spend | Prior private-state note path behind the liquid balance |
|
|
149
171
|
|
|
150
|
-
`account deposit-bridge` and `account withdraw-bridge` also print
|
|
151
|
-
|
|
172
|
+
`account deposit-bridge` and `account withdraw-bridge` also print an exchange-controlled address warning. Do not use an
|
|
173
|
+
exchange-controlled address as a self-custody bridge source or as the direct bridge withdrawal target
|
|
152
174
|
unless the user explicitly understands the compliance implications. Prefer a self-custody L1 wallet.
|
|
153
175
|
|
|
154
176
|
Workspace recovery commands use saved recovery indexes by default. If the local channel workspace is missing,
|
|
@@ -170,6 +192,12 @@ run is interrupted, the next non-`--from-genesis` RPC recovery resumes from the
|
|
|
170
192
|
can also start from that local checkpoint: it uses a matching delta bundle when one is available, otherwise a newer
|
|
171
193
|
verified full mirror checkpoint replaces the local checkpoint before RPC catch-up.
|
|
172
194
|
|
|
195
|
+
Use `channel recover-workspace --source rpc --output-raw` when you need to preserve the raw JSON-RPC request and
|
|
196
|
+
response history for inspection. The CLI appends calls to method-specific JSON files, and splits `eth_getLogs` into
|
|
197
|
+
event-specific files such as `eth_getLogs.CurrentRootVectorObserved.json`, under
|
|
198
|
+
`~/tokamak-private-channels/workspace/<network>/<channel>/channel/rpcCallHistory/`. Indexed recovery appends to the
|
|
199
|
+
existing history, while `--from-genesis` overwrites it with one full genesis-to-latest scan.
|
|
200
|
+
|
|
173
201
|
`channel create` is the exception: after the channel is created on-chain, the CLI initializes that new local workspace
|
|
174
202
|
by replaying from the channel's genesis block because no prior recovery index can exist for a new channel.
|
|
175
203
|
|
|
@@ -208,7 +236,7 @@ already exists. The channel leader can build the static mirror files with
|
|
|
208
236
|
host. If the existing mirror manifest is unreadable or invalid, the leader can use
|
|
209
237
|
`channel publish-workspace-mirror --force` to write a full checkpoint without trusting that remote
|
|
210
238
|
manifest as a delta base. The CLI protocol is documented at
|
|
211
|
-
https://github.com/tokamak-network/Tokamak-zk-EVM-contracts/blob/main/
|
|
239
|
+
https://github.com/tokamak-network/Tokamak-zk-EVM-contracts/blob/main/docs/dapps/private-state/channel-workspace-mirror-protocol.md.
|
|
212
240
|
|
|
213
241
|
Back up a local wallet with:
|
|
214
242
|
|
|
@@ -309,9 +337,11 @@ Channel policy warning:
|
|
|
309
337
|
a new channel; it does not rewrite the policy of an already-created channel.
|
|
310
338
|
|
|
311
339
|
`private-state-cli help doctor` reports the CLI package version, dependency versions recorded by the last
|
|
312
|
-
`private-state-cli install`, selected proof backend runtime versions
|
|
313
|
-
install mode, Docker mode, CUDA runtime metadata, live
|
|
314
|
-
|
|
340
|
+
`private-state-cli install`, selected proof backend runtime versions when full mode was installed, current dependency
|
|
341
|
+
versions through `tokamak-l2js`, Tokamak zk-EVM runtime install mode, Docker mode, CUDA runtime metadata, live
|
|
342
|
+
`nvidia-smi` and Docker GPU probe results, Groth16 runtime health, deployment artifact readiness, and per-command
|
|
343
|
+
availability. In read-only install mode, proof runtime checks are skipped and proof-backed or channel-mutating
|
|
344
|
+
commands are reported unavailable until full install is completed.
|
|
315
345
|
|
|
316
346
|
Local helper commands:
|
|
317
347
|
|
|
@@ -561,8 +591,9 @@ command.
|
|
|
561
591
|
|
|
562
592
|
## Artifacts
|
|
563
593
|
|
|
564
|
-
Proof-backed commands require installed bridge, DApp, and Groth16 artifacts. Run
|
|
565
|
-
|
|
594
|
+
Proof-backed and channel-mutating commands require full installed bridge, DApp, and Groth16 artifacts. Run
|
|
595
|
+
`private-state-cli install` before creating, joining, exiting, or mutating channels on a new machine. Channel-state read
|
|
596
|
+
commands and commands unrelated to channel state can run after `private-state-cli install --read-only`.
|
|
566
597
|
|
|
567
598
|
Channel balance commands such as `wallet deposit-channel` and `wallet withdraw-channel` use the installed Groth16 runtime workspace
|
|
568
599
|
directly. Proof generation writes to the fixed workspace paths under `~/tokamak-private-channels/groth16/proof`; the CLI
|
|
@@ -579,11 +610,16 @@ Release order matters for npm publication. `@tokamak-private-dapps/common-librar
|
|
|
579
610
|
|
|
580
611
|
It installs the `private-state-cli` terminal command and the local files needed by that command.
|
|
581
612
|
It does not install bridge contracts, app contracts, or local deployment outputs. The `private-state-cli install`
|
|
582
|
-
command provisions
|
|
613
|
+
command defaults to full mode, which provisions local Tokamak zk-EVM and Groth16 runtime workspaces used by
|
|
614
|
+
proof-backed commands. `private-state-cli install --read-only` installs only the public bridge and private-state DApp
|
|
615
|
+
artifacts needed by channel-state read commands and commands that do not depend on channel state.
|
|
583
616
|
|
|
584
617
|
### When should I run `private-state-cli install`?
|
|
585
618
|
|
|
586
|
-
Run
|
|
619
|
+
Run full install once on a machine that will create, join, exit, or mutate channels. Run read-only install on a machine
|
|
620
|
+
that only needs channel recovery, wallet recovery, metadata lookup, bridge balance lookup, bridge deposit or withdrawal,
|
|
621
|
+
and local import/export/helper commands. Re-run the relevant mode after public bridge, DApp, Groth16, or Tokamak zk-EVM
|
|
622
|
+
runtime artifacts are updated.
|
|
587
623
|
|
|
588
624
|
### Does this package publish private user data?
|
|
589
625
|
|
package/commands/account.mjs
CHANGED
|
@@ -10,7 +10,6 @@ import {
|
|
|
10
10
|
handleDepositBridge,
|
|
11
11
|
handleWithdrawBridge,
|
|
12
12
|
loadExplicitCommandRuntime,
|
|
13
|
-
prepareDeploymentArtifacts,
|
|
14
13
|
} from "../lib/runtime.mjs";
|
|
15
14
|
|
|
16
15
|
export const accountCommands = Object.freeze({
|
|
@@ -24,20 +23,17 @@ export const accountCommands = Object.freeze({
|
|
|
24
23
|
},
|
|
25
24
|
"account-get-bridge-fund": async (args) => {
|
|
26
25
|
assertAccountGetBridgeFundArgs(args);
|
|
27
|
-
const {
|
|
28
|
-
await prepareDeploymentArtifacts(network.chainId);
|
|
26
|
+
const { provider } = loadExplicitCommandRuntime(args, { prepareArtifacts: true });
|
|
29
27
|
await handleAccountGetBridgeFund({ args, provider });
|
|
30
28
|
},
|
|
31
29
|
"account-deposit-bridge": async (args) => {
|
|
32
30
|
assertDepositBridgeArgs(args);
|
|
33
|
-
const { network, provider } = loadExplicitCommandRuntime(args);
|
|
34
|
-
await prepareDeploymentArtifacts(network.chainId);
|
|
31
|
+
const { network, provider } = loadExplicitCommandRuntime(args, { prepareArtifacts: true });
|
|
35
32
|
await handleDepositBridge({ args, network, provider });
|
|
36
33
|
},
|
|
37
34
|
"account-withdraw-bridge": async (args) => {
|
|
38
35
|
assertWithdrawBridgeArgs(args);
|
|
39
|
-
const { network, provider } = loadExplicitCommandRuntime(args);
|
|
40
|
-
await prepareDeploymentArtifacts(network.chainId);
|
|
36
|
+
const { network, provider } = loadExplicitCommandRuntime(args, { prepareArtifacts: true });
|
|
41
37
|
await handleWithdrawBridge({ args, network, provider });
|
|
42
38
|
},
|
|
43
39
|
});
|
package/commands/channel.mjs
CHANGED
|
@@ -16,51 +16,43 @@ import {
|
|
|
16
16
|
handleWorkspaceInit,
|
|
17
17
|
loadExplicitCommandRuntime,
|
|
18
18
|
loadWalletCommandRuntime,
|
|
19
|
-
prepareDeploymentArtifacts,
|
|
20
19
|
} from "../lib/runtime.mjs";
|
|
21
20
|
|
|
22
21
|
export const channelCommands = Object.freeze({
|
|
23
22
|
"channel-create": async (args) => {
|
|
24
23
|
assertCreateChannelArgs(args);
|
|
25
|
-
const { network, provider } = loadExplicitCommandRuntime(args);
|
|
26
|
-
await prepareDeploymentArtifacts(network.chainId);
|
|
24
|
+
const { network, provider } = loadExplicitCommandRuntime(args, { prepareArtifacts: true });
|
|
27
25
|
await handleChannelCreate({ args, network, provider });
|
|
28
26
|
},
|
|
29
27
|
"channel-recover-workspace": async (args) => {
|
|
30
28
|
assertRecoverWorkspaceArgs(args);
|
|
31
|
-
const { network, provider, rpcUrl } = loadExplicitCommandRuntime(args, { staticNetwork: true });
|
|
29
|
+
const { network, provider, rpcUrl } = loadExplicitCommandRuntime(args, { staticNetwork: true, prepareArtifacts: true });
|
|
32
30
|
await assertProviderChainIdMatchesNetwork({ provider, network, rpcUrl });
|
|
33
|
-
await prepareDeploymentArtifacts(network.chainId);
|
|
34
31
|
await handleWorkspaceInit({ args, network, provider });
|
|
35
32
|
},
|
|
36
33
|
"channel-get-meta": async (args) => {
|
|
37
34
|
assertGetChannelArgs(args);
|
|
38
|
-
const { network, provider } = loadExplicitCommandRuntime(args);
|
|
39
|
-
await prepareDeploymentArtifacts(network.chainId);
|
|
35
|
+
const { network, provider } = loadExplicitCommandRuntime(args, { prepareArtifacts: true });
|
|
40
36
|
await handleGetChannel({ args, network, provider });
|
|
41
37
|
},
|
|
42
38
|
"channel-set-workspace-mirror": async (args) => {
|
|
43
39
|
assertSetWorkspaceMirrorArgs(args);
|
|
44
|
-
const { network, provider } = loadExplicitCommandRuntime(args);
|
|
45
|
-
await prepareDeploymentArtifacts(network.chainId);
|
|
40
|
+
const { network, provider } = loadExplicitCommandRuntime(args, { prepareArtifacts: true });
|
|
46
41
|
await handleSetChannelWorkspaceMirror({ args, network, provider });
|
|
47
42
|
},
|
|
48
43
|
"channel-publish-workspace-mirror": async (args) => {
|
|
49
44
|
assertPublishWorkspaceMirrorArgs(args);
|
|
50
|
-
const { network, provider } = loadExplicitCommandRuntime(args);
|
|
51
|
-
await prepareDeploymentArtifacts(network.chainId);
|
|
45
|
+
const { network, provider } = loadExplicitCommandRuntime(args, { prepareArtifacts: true });
|
|
52
46
|
await handlePublishChannelWorkspaceMirror({ args, network, provider });
|
|
53
47
|
},
|
|
54
48
|
"channel-join": async (args) => {
|
|
55
49
|
assertJoinChannelArgs(args);
|
|
56
|
-
const { network, provider, rpcUrl } = loadExplicitCommandRuntime(args);
|
|
57
|
-
await prepareDeploymentArtifacts(network.chainId);
|
|
50
|
+
const { network, provider, rpcUrl } = loadExplicitCommandRuntime(args, { prepareArtifacts: true });
|
|
58
51
|
await handleJoinChannel({ args, network, provider, rpcUrl });
|
|
59
52
|
},
|
|
60
53
|
"channel-exit": async (args) => {
|
|
61
54
|
assertExitChannelArgs(args);
|
|
62
|
-
const {
|
|
63
|
-
await prepareDeploymentArtifacts(network.chainId);
|
|
55
|
+
const { provider } = loadWalletCommandRuntime(args, { prepareArtifacts: true });
|
|
64
56
|
await handleExitChannel({ args, provider });
|
|
65
57
|
},
|
|
66
58
|
});
|
package/commands/notes.mjs
CHANGED
|
@@ -8,32 +8,27 @@ import {
|
|
|
8
8
|
handleTransferNotes,
|
|
9
9
|
handleWalletGetNotes,
|
|
10
10
|
loadWalletCommandRuntime,
|
|
11
|
-
prepareDeploymentArtifacts,
|
|
12
11
|
} from "../lib/runtime.mjs";
|
|
13
12
|
|
|
14
13
|
export const notesCommands = Object.freeze({
|
|
15
14
|
"wallet-mint-notes": async (args) => {
|
|
16
15
|
assertMintNotesArgs(args);
|
|
17
|
-
const {
|
|
18
|
-
await prepareDeploymentArtifacts(network.chainId);
|
|
16
|
+
const { provider } = loadWalletCommandRuntime(args, { prepareArtifacts: true });
|
|
19
17
|
await handleMintNotes({ args, provider });
|
|
20
18
|
},
|
|
21
19
|
"wallet-redeem-notes": async (args) => {
|
|
22
20
|
assertRedeemNotesArgs(args);
|
|
23
|
-
const {
|
|
24
|
-
await prepareDeploymentArtifacts(network.chainId);
|
|
21
|
+
const { provider } = loadWalletCommandRuntime(args, { prepareArtifacts: true });
|
|
25
22
|
await handleRedeemNotes({ args, provider });
|
|
26
23
|
},
|
|
27
24
|
"wallet-get-notes": async (args) => {
|
|
28
25
|
assertWalletGetNotesArgs(args);
|
|
29
|
-
const {
|
|
30
|
-
await prepareDeploymentArtifacts(network.chainId);
|
|
26
|
+
const { provider } = loadWalletCommandRuntime(args, { prepareArtifacts: true });
|
|
31
27
|
await handleWalletGetNotes({ args, provider });
|
|
32
28
|
},
|
|
33
29
|
"wallet-transfer-notes": async (args) => {
|
|
34
30
|
assertTransferNotesArgs(args);
|
|
35
|
-
const {
|
|
36
|
-
await prepareDeploymentArtifacts(network.chainId);
|
|
31
|
+
const { provider } = loadWalletCommandRuntime(args, { prepareArtifacts: true });
|
|
37
32
|
await handleTransferNotes({ args, provider });
|
|
38
33
|
},
|
|
39
34
|
});
|
package/commands/wallet.mjs
CHANGED
|
@@ -20,7 +20,6 @@ import {
|
|
|
20
20
|
handleWalletImportKey,
|
|
21
21
|
loadExplicitCommandRuntime,
|
|
22
22
|
loadWalletCommandRuntime,
|
|
23
|
-
prepareDeploymentArtifacts,
|
|
24
23
|
} from "../lib/runtime.mjs";
|
|
25
24
|
|
|
26
25
|
export const walletCommands = Object.freeze({
|
|
@@ -54,33 +53,28 @@ export const walletCommands = Object.freeze({
|
|
|
54
53
|
},
|
|
55
54
|
"wallet-recover-workspace": async (args) => {
|
|
56
55
|
assertRecoverWalletArgs(args);
|
|
57
|
-
const { network, provider, rpcUrl } = loadExplicitCommandRuntime(args, { staticNetwork: true });
|
|
56
|
+
const { network, provider, rpcUrl } = loadExplicitCommandRuntime(args, { staticNetwork: true, prepareArtifacts: true });
|
|
58
57
|
await assertProviderChainIdMatchesNetwork({ provider, network, rpcUrl });
|
|
59
|
-
await prepareDeploymentArtifacts(network.chainId);
|
|
60
58
|
await handleRecoverWallet({ args, network, provider, rpcUrl });
|
|
61
59
|
},
|
|
62
60
|
"wallet-get-meta": async (args) => {
|
|
63
61
|
assertWalletGetMetaArgs(args);
|
|
64
|
-
const {
|
|
65
|
-
await prepareDeploymentArtifacts(network.chainId);
|
|
62
|
+
const { provider } = loadWalletCommandRuntime(args, { prepareArtifacts: true });
|
|
66
63
|
await handleWalletGetMeta({ args, provider });
|
|
67
64
|
},
|
|
68
65
|
"wallet-get-channel-fund": async (args) => {
|
|
69
66
|
assertWalletGetChannelFundArgs(args);
|
|
70
|
-
const {
|
|
71
|
-
await prepareDeploymentArtifacts(network.chainId);
|
|
67
|
+
const { provider } = loadWalletCommandRuntime(args, { prepareArtifacts: true });
|
|
72
68
|
await handleWalletGetChannelFund({ args, provider });
|
|
73
69
|
},
|
|
74
70
|
"wallet-deposit-channel": async (args) => {
|
|
75
71
|
assertWalletChannelMoveArgs(args, "wallet-deposit-channel");
|
|
76
|
-
const {
|
|
77
|
-
await prepareDeploymentArtifacts(network.chainId);
|
|
72
|
+
const { provider } = loadWalletCommandRuntime(args, { prepareArtifacts: true });
|
|
78
73
|
await handleGrothVaultMove({ args, provider, direction: "deposit" });
|
|
79
74
|
},
|
|
80
75
|
"wallet-withdraw-channel": async (args) => {
|
|
81
76
|
assertWalletChannelMoveArgs(args, "wallet-withdraw-channel");
|
|
82
|
-
const {
|
|
83
|
-
await prepareDeploymentArtifacts(network.chainId);
|
|
77
|
+
const { provider } = loadWalletCommandRuntime(args, { prepareArtifacts: true });
|
|
84
78
|
await handleGrothVaultMove({ args, provider, direction: "withdraw" });
|
|
85
79
|
},
|
|
86
80
|
});
|
|
@@ -188,6 +188,13 @@ export const PRIVATE_STATE_CLI_FIELD_CATALOG = Object.freeze({
|
|
|
188
188
|
valueLabel: "<VERSION>",
|
|
189
189
|
optional: true,
|
|
190
190
|
},
|
|
191
|
+
readOnly: {
|
|
192
|
+
label: "Read-Only Install",
|
|
193
|
+
type: "checkbox",
|
|
194
|
+
hint: "Install only artifacts needed by channel-state read commands and commands that do not depend on channel state.",
|
|
195
|
+
option: "--read-only",
|
|
196
|
+
optional: true,
|
|
197
|
+
},
|
|
191
198
|
fromGenesis: {
|
|
192
199
|
label: "Scan From Genesis",
|
|
193
200
|
type: "checkbox",
|
|
@@ -195,6 +202,13 @@ export const PRIVATE_STATE_CLI_FIELD_CATALOG = Object.freeze({
|
|
|
195
202
|
option: "--from-genesis",
|
|
196
203
|
optional: true,
|
|
197
204
|
},
|
|
205
|
+
outputRaw: {
|
|
206
|
+
label: "Output Raw RPC History",
|
|
207
|
+
type: "checkbox",
|
|
208
|
+
hint: "With channel recover-workspace --source rpc, preserve raw JSON-RPC request and response history under the channel workspace.",
|
|
209
|
+
option: "--output-raw",
|
|
210
|
+
optional: true,
|
|
211
|
+
},
|
|
198
212
|
source: {
|
|
199
213
|
label: "Recovery Source",
|
|
200
214
|
type: "select",
|
|
@@ -239,7 +253,7 @@ const ACTION_IMPACT_HELP = Object.freeze({
|
|
|
239
253
|
acknowledgement: "Requires --acknowledge-action-impact after the user reviews the action-impact warning.",
|
|
240
254
|
illegalUse: "The command must not be used for money laundering, sanctions evasion, terrorist financing, illegal gambling, criminal-proceeds concealment, or regulatory evasion.",
|
|
241
255
|
secretRecovery: "Losing wallet secrets, viewing keys, or spending keys can prevent note discovery or note use; the CLI cannot recover lost secrets.",
|
|
242
|
-
|
|
256
|
+
exchangeControlledAddress: "Do not use an exchange-controlled address as a self-custody bridge source or direct bridge withdrawal target.",
|
|
243
257
|
policy: "The user must review the channel policy snapshot before accepting channel-bound actions.",
|
|
244
258
|
provenance: "Public observers cannot reconstruct private note counterparty relationships or note provenance from public contract state alone.",
|
|
245
259
|
});
|
|
@@ -247,10 +261,12 @@ const ACTION_IMPACT_HELP = Object.freeze({
|
|
|
247
261
|
export const PRIVATE_STATE_CLI_COMMANDS = Object.freeze([
|
|
248
262
|
{
|
|
249
263
|
id: "install",
|
|
250
|
-
description: "Install
|
|
251
|
-
fields: ["docker", "includeLocalArtifacts", "groth16CliVersion", "tokamakZkEvmCliVersion"],
|
|
252
|
-
usage: "optional --docker, --include-local-artifacts, --groth16-cli-version, and --tokamak-zk-evm-cli-version",
|
|
264
|
+
description: "Install private-state CLI runtime artifacts in full or read-only mode.",
|
|
265
|
+
fields: ["readOnly", "docker", "includeLocalArtifacts", "groth16CliVersion", "tokamakZkEvmCliVersion"],
|
|
266
|
+
usage: "optional --read-only, --docker, --include-local-artifacts, --groth16-cli-version, and --tokamak-zk-evm-cli-version",
|
|
253
267
|
help: [
|
|
268
|
+
"Default full mode installs proof runtimes and all deployment artifacts needed by transaction-sending commands",
|
|
269
|
+
"--read-only installs only artifacts needed by channel-state read commands and commands unrelated to channel state",
|
|
254
270
|
"Version options install exact CLI package versions; omitted versions resolve to npm registry latest",
|
|
255
271
|
"Use --docker on Linux to forward Docker mode to the Tokamak zk-EVM and Groth16 runtimes",
|
|
256
272
|
"Use --include-local-artifacts to also install local deployment/ artifacts from the current working directory",
|
|
@@ -295,11 +311,12 @@ export const PRIVATE_STATE_CLI_COMMANDS = Object.freeze([
|
|
|
295
311
|
{
|
|
296
312
|
id: "help-doctor",
|
|
297
313
|
display: "help doctor",
|
|
298
|
-
description: "Check private-state CLI package versions,
|
|
314
|
+
description: "Check private-state CLI package versions, install state, deployment artifacts, and command availability.",
|
|
299
315
|
fields: ["gpu", "json"],
|
|
300
316
|
usage: "optional --gpu and optional --json",
|
|
301
317
|
help: [
|
|
302
318
|
"Prints a concise human-readable table by default; use --json for the full machine-readable report",
|
|
319
|
+
"Reports whether each command is usable with the current read-only or full install state",
|
|
303
320
|
"Use --gpu to run live NVIDIA/Docker GPU probes",
|
|
304
321
|
],
|
|
305
322
|
},
|
|
@@ -352,6 +369,7 @@ export const PRIVATE_STATE_CLI_COMMANDS = Object.freeze([
|
|
|
352
369
|
id: "account-get-bridge-fund",
|
|
353
370
|
display: "account get-bridge-fund",
|
|
354
371
|
description: "Read the local account's current shared bridge vault balance.",
|
|
372
|
+
installMode: "read-only",
|
|
355
373
|
fields: ["network", "account"],
|
|
356
374
|
usage: "--network, --account",
|
|
357
375
|
},
|
|
@@ -359,6 +377,7 @@ export const PRIVATE_STATE_CLI_COMMANDS = Object.freeze([
|
|
|
359
377
|
id: "channel-create",
|
|
360
378
|
display: "channel create",
|
|
361
379
|
description: "Create a bridge channel and initialize its workspace.",
|
|
380
|
+
installMode: "full",
|
|
362
381
|
fields: ["channelName", "joinToll", "network", "account"],
|
|
363
382
|
usage: "--channel-name, --join-toll, --network, --account",
|
|
364
383
|
help: [
|
|
@@ -370,8 +389,9 @@ export const PRIVATE_STATE_CLI_COMMANDS = Object.freeze([
|
|
|
370
389
|
id: "channel-recover-workspace",
|
|
371
390
|
display: "channel recover-workspace",
|
|
372
391
|
description: "Rebuild the local channel workspace from bridge state.",
|
|
373
|
-
|
|
374
|
-
|
|
392
|
+
installMode: "read-only",
|
|
393
|
+
fields: ["channelName", "network", "source", "fromGenesis", "outputRaw"],
|
|
394
|
+
usage: "--channel-name, --network, optional --source, optional --from-genesis, optional --output-raw",
|
|
375
395
|
help: [
|
|
376
396
|
"By default, --source rpc resumes RPC log scanning from the workspace recovery index when available",
|
|
377
397
|
"--source mirror validates the channel leader's registered checkpoint manifest, downloads only the needed checkpoint or delta bundle, and then replays RPC logs to latest",
|
|
@@ -379,6 +399,7 @@ export const PRIVATE_STATE_CLI_COMMANDS = Object.freeze([
|
|
|
379
399
|
"Mirror recovery uses a matching delta bundle when available; otherwise a newer verified full checkpoint replaces the local checkpoint before RPC catch-up",
|
|
380
400
|
"Fails instead of falling back to genesis when no usable recovery index exists",
|
|
381
401
|
"Use --source rpc --from-genesis to ignore the recovery index and replay logs from channel genesis",
|
|
402
|
+
"--output-raw with --source rpc appends raw JSON-RPC request and response history to method-specific JSON files under the channel workspace rpcCallHistory directory; eth_getLogs is split by event",
|
|
382
403
|
"--from-genesis moves the existing local channel workspace to workspace-rebuild-backups before writing the current-format workspace; local secrets are preserved",
|
|
383
404
|
"Prints RPC log scan progress while rebuilding the workspace",
|
|
384
405
|
],
|
|
@@ -387,6 +408,7 @@ export const PRIVATE_STATE_CLI_COMMANDS = Object.freeze([
|
|
|
387
408
|
id: "channel-set-workspace-mirror",
|
|
388
409
|
display: "channel set-workspace-mirror",
|
|
389
410
|
description: "Register or update the channel leader's workspace mirror base URL.",
|
|
411
|
+
installMode: "full",
|
|
390
412
|
fields: ["channelName", "network", "account", "url"],
|
|
391
413
|
usage: "--channel-name, --network, --account, --url",
|
|
392
414
|
help: [
|
|
@@ -398,6 +420,7 @@ export const PRIVATE_STATE_CLI_COMMANDS = Object.freeze([
|
|
|
398
420
|
id: "channel-publish-workspace-mirror",
|
|
399
421
|
display: "channel publish-workspace-mirror",
|
|
400
422
|
description: "Build static workspace mirror files for the registered mirror URL.",
|
|
423
|
+
installMode: "read-only",
|
|
401
424
|
fields: ["channelName", "network", "account", "output", "force"],
|
|
402
425
|
usage: "--channel-name, --network, --account, --output, optional --force",
|
|
403
426
|
help: [
|
|
@@ -411,6 +434,7 @@ export const PRIVATE_STATE_CLI_COMMANDS = Object.freeze([
|
|
|
411
434
|
id: "channel-get-meta",
|
|
412
435
|
display: "channel get-meta",
|
|
413
436
|
description: "Read channel existence, manager, vault, toll, refund schedule, and immutable policy snapshot.",
|
|
437
|
+
installMode: "read-only",
|
|
414
438
|
fields: ["channelName", "network"],
|
|
415
439
|
usage: "--channel-name, --network",
|
|
416
440
|
},
|
|
@@ -418,12 +442,13 @@ export const PRIVATE_STATE_CLI_COMMANDS = Object.freeze([
|
|
|
418
442
|
id: "account-deposit-bridge",
|
|
419
443
|
display: "account deposit-bridge",
|
|
420
444
|
description: "Deposit canonical tokens into the shared bridge vault.",
|
|
445
|
+
installMode: "read-only",
|
|
421
446
|
fields: ["amount", "network", "account", "acknowledgeActionImpact"],
|
|
422
447
|
usage: "--amount, --network, --account, --acknowledge-action-impact",
|
|
423
448
|
help: [
|
|
424
449
|
"Action impact: emits public L1 approval and bridge funding events that expose the local L1 account, bridge vault, amount, and transaction hashes.",
|
|
425
450
|
"Private note state is not changed by this command.",
|
|
426
|
-
ACTION_IMPACT_HELP.
|
|
451
|
+
ACTION_IMPACT_HELP.exchangeControlledAddress,
|
|
427
452
|
ACTION_IMPACT_HELP.illegalUse,
|
|
428
453
|
ACTION_IMPACT_HELP.acknowledgement,
|
|
429
454
|
],
|
|
@@ -432,12 +457,13 @@ export const PRIVATE_STATE_CLI_COMMANDS = Object.freeze([
|
|
|
432
457
|
id: "account-withdraw-bridge",
|
|
433
458
|
display: "account withdraw-bridge",
|
|
434
459
|
description: "Withdraw tokens from the shared bridge vault back to the wallet.",
|
|
460
|
+
installMode: "read-only",
|
|
435
461
|
fields: ["amount", "network", "account", "acknowledgeActionImpact"],
|
|
436
462
|
usage: "--amount, --network, --account, --acknowledge-action-impact",
|
|
437
463
|
help: [
|
|
438
464
|
"Action impact: emits a public L1 bridge withdrawal event that exposes the local L1 recipient, bridge vault, amount, and transaction hash.",
|
|
439
465
|
"Private note state is not changed by this command; prior note provenance is not public by default.",
|
|
440
|
-
ACTION_IMPACT_HELP.
|
|
466
|
+
ACTION_IMPACT_HELP.exchangeControlledAddress,
|
|
441
467
|
ACTION_IMPACT_HELP.illegalUse,
|
|
442
468
|
ACTION_IMPACT_HELP.acknowledgement,
|
|
443
469
|
],
|
|
@@ -446,6 +472,7 @@ export const PRIVATE_STATE_CLI_COMMANDS = Object.freeze([
|
|
|
446
472
|
id: "wallet-recover-workspace",
|
|
447
473
|
display: "wallet recover-workspace",
|
|
448
474
|
description: "Rebuild a recoverable local wallet from on-chain channel state.",
|
|
475
|
+
installMode: "read-only",
|
|
449
476
|
fields: ["channelName", "network", "account", "fromGenesis"],
|
|
450
477
|
usage: "--channel-name, --network, --account, optional --from-genesis",
|
|
451
478
|
help: [
|
|
@@ -462,6 +489,7 @@ export const PRIVATE_STATE_CLI_COMMANDS = Object.freeze([
|
|
|
462
489
|
id: "channel-join",
|
|
463
490
|
display: "channel join",
|
|
464
491
|
description: "Pay the channel join toll and bind a wallet to a channel-specific L2 identity.",
|
|
492
|
+
installMode: "full",
|
|
465
493
|
fields: ["channelName", "network", "account", "walletSecretPath", "acknowledgeActionImpact"],
|
|
466
494
|
usage: "--channel-name, --network, --account, --wallet-secret-path, --acknowledge-action-impact",
|
|
467
495
|
help: [
|
|
@@ -481,6 +509,7 @@ export const PRIVATE_STATE_CLI_COMMANDS = Object.freeze([
|
|
|
481
509
|
id: "wallet-get-meta",
|
|
482
510
|
display: "wallet get-meta",
|
|
483
511
|
description: "Check whether a wallet matches the on-chain channel registration.",
|
|
512
|
+
installMode: "read-only",
|
|
484
513
|
fields: ["wallet", "network"],
|
|
485
514
|
usage: "--wallet and --network",
|
|
486
515
|
help: [
|
|
@@ -550,6 +579,7 @@ export const PRIVATE_STATE_CLI_COMMANDS = Object.freeze([
|
|
|
550
579
|
id: "wallet-deposit-channel",
|
|
551
580
|
display: "wallet deposit-channel",
|
|
552
581
|
description: "Move bridged funds into the channel L2 accounting balance.",
|
|
582
|
+
installMode: "full",
|
|
553
583
|
fields: ["wallet", "network", "amount", "acknowledgeActionImpact"],
|
|
554
584
|
usage: "--wallet, --network, --amount, and --acknowledge-action-impact",
|
|
555
585
|
help: [
|
|
@@ -566,6 +596,7 @@ export const PRIVATE_STATE_CLI_COMMANDS = Object.freeze([
|
|
|
566
596
|
id: "wallet-withdraw-channel",
|
|
567
597
|
display: "wallet withdraw-channel",
|
|
568
598
|
description: "Move channel L2 balance back into the shared bridge vault.",
|
|
599
|
+
installMode: "full",
|
|
569
600
|
fields: ["wallet", "network", "amount", "acknowledgeActionImpact"],
|
|
570
601
|
usage: "--wallet, --network, --amount, and --acknowledge-action-impact",
|
|
571
602
|
help: [
|
|
@@ -583,6 +614,7 @@ export const PRIVATE_STATE_CLI_COMMANDS = Object.freeze([
|
|
|
583
614
|
id: "wallet-get-channel-fund",
|
|
584
615
|
display: "wallet get-channel-fund",
|
|
585
616
|
description: "Read the current channel L2 accounting balance.",
|
|
617
|
+
installMode: "read-only",
|
|
586
618
|
fields: ["wallet", "network"],
|
|
587
619
|
usage: "--wallet and --network",
|
|
588
620
|
help: ["Refreshes the local channel workspace through the saved recovery index before reading the L2 accounting balance when the scan fits the 10 second pre-command budget"],
|
|
@@ -591,6 +623,7 @@ export const PRIVATE_STATE_CLI_COMMANDS = Object.freeze([
|
|
|
591
623
|
id: "channel-exit",
|
|
592
624
|
display: "channel exit",
|
|
593
625
|
description: "Exit a channel. Both the CLI and bridge contract require a zero channel balance.",
|
|
626
|
+
installMode: "full",
|
|
594
627
|
fields: ["wallet", "network"],
|
|
595
628
|
usage: "--wallet and --network",
|
|
596
629
|
help: [
|
|
@@ -602,6 +635,7 @@ export const PRIVATE_STATE_CLI_COMMANDS = Object.freeze([
|
|
|
602
635
|
id: "wallet-mint-notes",
|
|
603
636
|
display: "wallet mint-notes",
|
|
604
637
|
description: "Mint one or two private-state notes from the wallet's channel balance.",
|
|
638
|
+
installMode: "full",
|
|
605
639
|
fields: ["wallet", "network", "amounts", "acknowledgeActionImpact", "txSubmitter"],
|
|
606
640
|
usage: "--wallet, --network, --amounts, --acknowledge-action-impact, and optional --tx-submitter",
|
|
607
641
|
help: [
|
|
@@ -621,6 +655,7 @@ export const PRIVATE_STATE_CLI_COMMANDS = Object.freeze([
|
|
|
621
655
|
id: "wallet-transfer-notes",
|
|
622
656
|
display: "wallet transfer-notes",
|
|
623
657
|
description: "Spend input notes into the registered 1->1, 1->2, or 2->1 private transfer shapes.",
|
|
658
|
+
installMode: "full",
|
|
624
659
|
fields: ["wallet", "network", "noteIds", "recipients", "amounts", "acknowledgeActionImpact", "txSubmitter"],
|
|
625
660
|
usage: "--wallet, --network, --note-ids, --recipients, --amounts, --acknowledge-action-impact, and optional --tx-submitter",
|
|
626
661
|
help: [
|
|
@@ -639,6 +674,7 @@ export const PRIVATE_STATE_CLI_COMMANDS = Object.freeze([
|
|
|
639
674
|
id: "wallet-redeem-notes",
|
|
640
675
|
display: "wallet redeem-notes",
|
|
641
676
|
description: "Redeem one tracked note back into the wallet's channel balance.",
|
|
677
|
+
installMode: "full",
|
|
642
678
|
fields: ["wallet", "network", "noteIds", "acknowledgeActionImpact", "txSubmitter"],
|
|
643
679
|
usage: "--wallet, --network, --note-ids, --acknowledge-action-impact, and optional --tx-submitter",
|
|
644
680
|
help: [
|
|
@@ -657,6 +693,7 @@ export const PRIVATE_STATE_CLI_COMMANDS = Object.freeze([
|
|
|
657
693
|
id: "wallet-get-notes",
|
|
658
694
|
display: "wallet get-notes",
|
|
659
695
|
description: "Refresh received notes when the saved recovery index is recent, then show tracked note state.",
|
|
696
|
+
installMode: "read-only",
|
|
660
697
|
fields: ["wallet", "network", "exportEvidence", "acknowledgeFullNotePlaintextExport"],
|
|
661
698
|
usage: "--wallet, --network, optional --export-evidence, and optional --acknowledge-full-note-plaintext-export",
|
|
662
699
|
help: [
|
|
@@ -669,6 +706,10 @@ export const PRIVATE_STATE_CLI_COMMANDS = Object.freeze([
|
|
|
669
706
|
},
|
|
670
707
|
]);
|
|
671
708
|
|
|
709
|
+
export function privateStateCliCommandInstallMode(command) {
|
|
710
|
+
return command.installMode ?? "none";
|
|
711
|
+
}
|
|
712
|
+
|
|
672
713
|
export function privateStateCliCommandDisplay(command) {
|
|
673
714
|
return command.display ?? command.id;
|
|
674
715
|
}
|
|
@@ -698,7 +739,7 @@ export function privateStateCliCommandSynopsis(command) {
|
|
|
698
739
|
return null;
|
|
699
740
|
}
|
|
700
741
|
const valueLabel = field.valueLabel ?? field.placeholderLabel ?? `<${field.label?.toUpperCase().replace(/\s+/g, "_") ?? "VALUE"}>`;
|
|
701
|
-
const option = field.type === "checkbox"
|
|
742
|
+
const option = field.type === "checkbox"
|
|
702
743
|
? field.option
|
|
703
744
|
: `${field.option} ${valueLabel}`;
|
|
704
745
|
return field.optional || optionalFields.has(fieldKey) ? `[${option}]` : option;
|