@tokamak-private-dapps/private-state-cli 0.1.1 → 0.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 +5 -0
- package/README.md +10 -0
- package/package.json +1 -1
- package/private-state-bridge-cli.mjs +278 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.2 - 2026-04-28
|
|
4
|
+
|
|
5
|
+
- Added `private-state-cli --doctor` to report CLI and install-time dependency versions through `tokamak-l2js`.
|
|
6
|
+
- Reported Tokamak zk-EVM runtime install mode, Docker mode, and CUDA runtime metadata.
|
|
7
|
+
|
|
3
8
|
## 0.1.1 - 2026-04-28
|
|
4
9
|
|
|
5
10
|
- Updated channel balance proof generation to use the fixed Groth16 runtime workspace proof paths.
|
package/README.md
CHANGED
|
@@ -27,6 +27,12 @@ Run the CLI with:
|
|
|
27
27
|
private-state-cli <command> ...
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
+
Check the installed package and runtime state with:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
private-state-cli --doctor
|
|
34
|
+
```
|
|
35
|
+
|
|
30
36
|
## Commands
|
|
31
37
|
|
|
32
38
|
The normal private-state flow is:
|
|
@@ -44,6 +50,10 @@ The normal private-state flow is:
|
|
|
44
50
|
|
|
45
51
|
Use `private-state-cli --help` for the full command list and required options.
|
|
46
52
|
|
|
53
|
+
`private-state-cli --doctor` reports the CLI package version, dependency versions recorded by the last
|
|
54
|
+
`private-state-cli --install`, current dependency versions through `tokamak-l2js`, and Tokamak zk-EVM runtime
|
|
55
|
+
install mode, Docker mode, and CUDA runtime metadata.
|
|
56
|
+
|
|
47
57
|
## Workspace
|
|
48
58
|
|
|
49
59
|
The CLI stores user workspaces under:
|
package/package.json
CHANGED
|
@@ -5,6 +5,7 @@ import os from "node:os";
|
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import process from "node:process";
|
|
7
7
|
import { spawnSync } from "node:child_process";
|
|
8
|
+
import { createRequire } from "node:module";
|
|
8
9
|
import {
|
|
9
10
|
createCipheriv,
|
|
10
11
|
createDecipheriv,
|
|
@@ -46,6 +47,7 @@ import { deriveRpcUrl, resolveCliNetwork } from "@tokamak-private-dapps/common-l
|
|
|
46
47
|
import {
|
|
47
48
|
buildTokamakCliInvocation,
|
|
48
49
|
resolveTokamakBlockInputConfig,
|
|
50
|
+
resolveTokamakCliPackageRoot,
|
|
49
51
|
resolveTokamakCliResourceDir,
|
|
50
52
|
resolveTokamakCliRuntimeRoot,
|
|
51
53
|
} from "@tokamak-private-dapps/common-library/tokamak-runtime-paths";
|
|
@@ -80,7 +82,9 @@ import {
|
|
|
80
82
|
walletNameForChannelAndAddress,
|
|
81
83
|
} from "./lib/private-state-cli-shared.mjs";
|
|
82
84
|
|
|
85
|
+
const require = createRequire(import.meta.url);
|
|
83
86
|
const defaultCommandCwd = process.cwd();
|
|
87
|
+
const privateStateCliPackageRoot = path.dirname(require.resolve("./package.json"));
|
|
84
88
|
const workspaceRoot = path.resolve(os.homedir(), "tokamak-private-channels", "workspace");
|
|
85
89
|
const tokamakCliInvocation = buildTokamakCliInvocation();
|
|
86
90
|
const tokamakCliCommand = tokamakCliInvocation.command;
|
|
@@ -221,6 +225,12 @@ async function main() {
|
|
|
221
225
|
return;
|
|
222
226
|
}
|
|
223
227
|
|
|
228
|
+
if (args.command === "--doctor") {
|
|
229
|
+
assertDoctorArgs(args);
|
|
230
|
+
await handleDoctor({ args });
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
|
|
224
234
|
const walletCommandHandlers = {
|
|
225
235
|
"mint-notes": {
|
|
226
236
|
assert: assertMintNotesArgs,
|
|
@@ -937,6 +947,12 @@ async function handleInstallZkEvm({ args }) {
|
|
|
937
947
|
dappName: PRIVATE_STATE_DAPP_LABEL,
|
|
938
948
|
localDeploymentBaseRoot,
|
|
939
949
|
});
|
|
950
|
+
const installManifest = writePrivateStateCliInstallManifest({
|
|
951
|
+
dockerRequested: Boolean(args.docker),
|
|
952
|
+
includeLocalArtifacts: Boolean(args.includeLocalArtifacts),
|
|
953
|
+
localDeploymentBaseRoot,
|
|
954
|
+
deploymentArtifacts,
|
|
955
|
+
});
|
|
940
956
|
printJson({
|
|
941
957
|
action: "install",
|
|
942
958
|
tokamakCli: tokamakCliBaseArgs[0],
|
|
@@ -953,6 +969,7 @@ async function handleInstallZkEvm({ args }) {
|
|
|
953
969
|
dappTimestamp: entry.dappTimestamp,
|
|
954
970
|
artifactDir: entry.artifactDir,
|
|
955
971
|
})),
|
|
972
|
+
installManifestPath: installManifest.manifestPath,
|
|
956
973
|
});
|
|
957
974
|
}
|
|
958
975
|
|
|
@@ -972,6 +989,14 @@ async function handleUninstallZkEvm() {
|
|
|
972
989
|
});
|
|
973
990
|
}
|
|
974
991
|
|
|
992
|
+
async function handleDoctor() {
|
|
993
|
+
const report = buildDoctorReport();
|
|
994
|
+
printJson(report);
|
|
995
|
+
if (!report.ok) {
|
|
996
|
+
process.exitCode = 1;
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
|
|
975
1000
|
async function handleGetMyAddress({ args, provider }) {
|
|
976
1001
|
const { wallet, walletMetadata } = loadUnlockedWalletWithMetadata(args);
|
|
977
1002
|
const { signer, l2Identity } = restoreWalletParticipant(wallet, provider);
|
|
@@ -4217,6 +4242,10 @@ function parseArgs(argv) {
|
|
|
4217
4242
|
parsed.command = "--install";
|
|
4218
4243
|
parsed.positional = ["--install"];
|
|
4219
4244
|
}
|
|
4245
|
+
if (!parsed.command && parsed.doctor === true) {
|
|
4246
|
+
parsed.command = "--doctor";
|
|
4247
|
+
parsed.positional = ["--doctor"];
|
|
4248
|
+
}
|
|
4220
4249
|
return parsed;
|
|
4221
4250
|
}
|
|
4222
4251
|
|
|
@@ -4421,6 +4450,10 @@ function assertUninstallZkEvmArgs(args) {
|
|
|
4421
4450
|
assertAllowedCommandKeys(args, "uninstall-zk-evm", new Set(["command", "positional"]), "no options");
|
|
4422
4451
|
}
|
|
4423
4452
|
|
|
4453
|
+
function assertDoctorArgs(args) {
|
|
4454
|
+
assertAllowedCommandKeys(args, "--doctor", new Set(["command", "positional", "doctor"]), "no options");
|
|
4455
|
+
}
|
|
4456
|
+
|
|
4424
4457
|
function assertMintNotesArgs(args) {
|
|
4425
4458
|
requireArg(args.amounts, "--amounts");
|
|
4426
4459
|
assertWalletPasswordArgs(args, "mint-notes", ["amounts"], "--wallet, --password, --network, and --amounts");
|
|
@@ -4603,6 +4636,9 @@ Commands:
|
|
|
4603
4636
|
uninstall-zk-evm
|
|
4604
4637
|
Remove the Tokamak zk-EVM CLI runtime workspace
|
|
4605
4638
|
|
|
4639
|
+
--doctor
|
|
4640
|
+
Check private-state CLI package versions, runtime install state, Docker mode, CUDA mode, and deployment artifacts
|
|
4641
|
+
|
|
4606
4642
|
create-channel --channel-name <NAME> --join-fee <TOKENS> --network <NAME> --private-key <HEX> --alchemy-api-key <KEY>
|
|
4607
4643
|
Create a bridge channel and initialize its workspace
|
|
4608
4644
|
|
|
@@ -4882,6 +4918,248 @@ function privateStateCliArtifactPaths(cacheBaseRoot = resolveArtifactCacheBaseRo
|
|
|
4882
4918
|
};
|
|
4883
4919
|
}
|
|
4884
4920
|
|
|
4921
|
+
function privateStateCliInstallManifestPath(cacheBaseRoot = resolveArtifactCacheBaseRoot()) {
|
|
4922
|
+
return path.join(privateStateCliArtifactRoot(cacheBaseRoot), "install-manifest.json");
|
|
4923
|
+
}
|
|
4924
|
+
|
|
4925
|
+
function writePrivateStateCliInstallManifest({
|
|
4926
|
+
dockerRequested,
|
|
4927
|
+
includeLocalArtifacts,
|
|
4928
|
+
localDeploymentBaseRoot,
|
|
4929
|
+
deploymentArtifacts,
|
|
4930
|
+
}) {
|
|
4931
|
+
const manifestPath = privateStateCliInstallManifestPath(deploymentArtifacts.cacheBaseRoot);
|
|
4932
|
+
const manifest = {
|
|
4933
|
+
installedAt: new Date().toISOString(),
|
|
4934
|
+
package: summarizePackageReport(readPackageReport({
|
|
4935
|
+
name: "@tokamak-private-dapps/private-state-cli",
|
|
4936
|
+
packageJsonPath: path.join(privateStateCliPackageRoot, "package.json"),
|
|
4937
|
+
})),
|
|
4938
|
+
dependencies: collectDependencyPackageReports().map(summarizePackageReport),
|
|
4939
|
+
install: {
|
|
4940
|
+
dockerRequested,
|
|
4941
|
+
includeLocalArtifacts,
|
|
4942
|
+
localDeploymentBaseRoot,
|
|
4943
|
+
artifactCacheRoot: deploymentArtifacts.cacheBaseRoot,
|
|
4944
|
+
installedDeploymentArtifacts: deploymentArtifacts.installed.map((entry) => ({
|
|
4945
|
+
chainId: entry.chainId,
|
|
4946
|
+
source: entry.source,
|
|
4947
|
+
bridgeTimestamp: entry.bridgeTimestamp,
|
|
4948
|
+
dappTimestamp: entry.dappTimestamp,
|
|
4949
|
+
})),
|
|
4950
|
+
},
|
|
4951
|
+
};
|
|
4952
|
+
writeJson(manifestPath, manifest);
|
|
4953
|
+
return { manifestPath, manifest };
|
|
4954
|
+
}
|
|
4955
|
+
|
|
4956
|
+
function summarizePackageReport(report) {
|
|
4957
|
+
return {
|
|
4958
|
+
name: report.name,
|
|
4959
|
+
version: report.version,
|
|
4960
|
+
};
|
|
4961
|
+
}
|
|
4962
|
+
|
|
4963
|
+
function buildDoctorReport() {
|
|
4964
|
+
const cacheBaseRoot = resolveArtifactCacheBaseRoot();
|
|
4965
|
+
const installManifestPath = privateStateCliInstallManifestPath(cacheBaseRoot);
|
|
4966
|
+
const installManifest = readJsonIfExists(installManifestPath);
|
|
4967
|
+
const dependencyReports = collectDependencyPackageReports(installManifest);
|
|
4968
|
+
const tokamakCli = inspectTokamakCliRuntime();
|
|
4969
|
+
const checks = [
|
|
4970
|
+
{
|
|
4971
|
+
name: "dependency package versions",
|
|
4972
|
+
ok: dependencyReports.every((entry) => entry.ok),
|
|
4973
|
+
details: dependencyReports.map((entry) => ({
|
|
4974
|
+
name: entry.name,
|
|
4975
|
+
currentVersion: entry.version,
|
|
4976
|
+
installVersion: entry.installVersion,
|
|
4977
|
+
ok: entry.ok,
|
|
4978
|
+
error: entry.error,
|
|
4979
|
+
})),
|
|
4980
|
+
},
|
|
4981
|
+
{
|
|
4982
|
+
name: "tokamak zk-evm runtime",
|
|
4983
|
+
ok: tokamakCli.installed,
|
|
4984
|
+
details: {
|
|
4985
|
+
doctorStatus: tokamakCli.doctor.status,
|
|
4986
|
+
runtimeRoot: tokamakCli.runtimeRoot,
|
|
4987
|
+
installations: tokamakCli.installations.map(({ platform, installMode, packageVersion, docker }) => ({
|
|
4988
|
+
platform,
|
|
4989
|
+
installMode,
|
|
4990
|
+
packageVersion,
|
|
4991
|
+
dockerEnvironment: docker?.dockerEnvironment ?? null,
|
|
4992
|
+
useGpus: docker?.useGpus ?? null,
|
|
4993
|
+
})),
|
|
4994
|
+
},
|
|
4995
|
+
},
|
|
4996
|
+
];
|
|
4997
|
+
|
|
4998
|
+
return {
|
|
4999
|
+
action: "doctor",
|
|
5000
|
+
ok: checks.every((check) => check.ok),
|
|
5001
|
+
generatedAt: new Date().toISOString(),
|
|
5002
|
+
package: readPackageReport({
|
|
5003
|
+
name: "@tokamak-private-dapps/private-state-cli",
|
|
5004
|
+
packageJsonPath: path.join(privateStateCliPackageRoot, "package.json"),
|
|
5005
|
+
}),
|
|
5006
|
+
installManifest: {
|
|
5007
|
+
path: installManifestPath,
|
|
5008
|
+
exists: Boolean(installManifest),
|
|
5009
|
+
installedAt: installManifest?.installedAt ?? null,
|
|
5010
|
+
dockerRequested: installManifest?.install?.dockerRequested ?? null,
|
|
5011
|
+
includeLocalArtifacts: installManifest?.install?.includeLocalArtifacts ?? null,
|
|
5012
|
+
},
|
|
5013
|
+
dependencies: dependencyReports,
|
|
5014
|
+
tokamakCli,
|
|
5015
|
+
checks,
|
|
5016
|
+
};
|
|
5017
|
+
}
|
|
5018
|
+
|
|
5019
|
+
function collectDependencyPackageReports(installManifest = null) {
|
|
5020
|
+
const installVersions = new Map(
|
|
5021
|
+
Array.isArray(installManifest?.dependencies)
|
|
5022
|
+
? installManifest.dependencies.map((entry) => [entry.name, entry.version])
|
|
5023
|
+
: [],
|
|
5024
|
+
);
|
|
5025
|
+
const targets = [
|
|
5026
|
+
{
|
|
5027
|
+
name: "@tokamak-zk-evm/cli",
|
|
5028
|
+
packageJsonPath: path.join(resolveTokamakCliPackageRoot(), "package.json"),
|
|
5029
|
+
},
|
|
5030
|
+
{
|
|
5031
|
+
name: "@tokamak-private-dapps/groth16",
|
|
5032
|
+
resolveTarget: "@tokamak-private-dapps/groth16/public-drive-crs",
|
|
5033
|
+
},
|
|
5034
|
+
{
|
|
5035
|
+
name: "@tokamak-private-dapps/common-library",
|
|
5036
|
+
resolveTarget: "@tokamak-private-dapps/common-library/artifact-cache",
|
|
5037
|
+
},
|
|
5038
|
+
{ name: "tokamak-l2js", resolveTarget: "tokamak-l2js" },
|
|
5039
|
+
];
|
|
5040
|
+
|
|
5041
|
+
return targets.map((target) => {
|
|
5042
|
+
const report = readPackageReport(target);
|
|
5043
|
+
const installVersion = installVersions.get(report.name) ?? null;
|
|
5044
|
+
return {
|
|
5045
|
+
...report,
|
|
5046
|
+
installVersion,
|
|
5047
|
+
ok: Boolean(report.version) && (installVersion === null || installVersion === report.version),
|
|
5048
|
+
};
|
|
5049
|
+
});
|
|
5050
|
+
}
|
|
5051
|
+
|
|
5052
|
+
function readPackageReport({ name, packageJsonPath = null, resolveTarget = null }) {
|
|
5053
|
+
try {
|
|
5054
|
+
const resolvedPackageJsonPath = packageJsonPath
|
|
5055
|
+
? path.resolve(packageJsonPath)
|
|
5056
|
+
: findPackageJsonForName(path.dirname(require.resolve(resolveTarget ?? name)), name);
|
|
5057
|
+
const packageJson = readJson(resolvedPackageJsonPath);
|
|
5058
|
+
return {
|
|
5059
|
+
name: packageJson.name ?? name,
|
|
5060
|
+
version: packageJson.version ?? null,
|
|
5061
|
+
packageRoot: path.dirname(resolvedPackageJsonPath),
|
|
5062
|
+
error: null,
|
|
5063
|
+
};
|
|
5064
|
+
} catch (error) {
|
|
5065
|
+
return {
|
|
5066
|
+
name,
|
|
5067
|
+
version: null,
|
|
5068
|
+
packageRoot: null,
|
|
5069
|
+
error: error.message,
|
|
5070
|
+
ok: false,
|
|
5071
|
+
};
|
|
5072
|
+
}
|
|
5073
|
+
}
|
|
5074
|
+
|
|
5075
|
+
function findPackageJsonForName(startDir, expectedName) {
|
|
5076
|
+
let current = path.resolve(startDir);
|
|
5077
|
+
while (current !== path.dirname(current)) {
|
|
5078
|
+
const candidate = path.join(current, "package.json");
|
|
5079
|
+
if (fs.existsSync(candidate)) {
|
|
5080
|
+
const packageJson = readJson(candidate);
|
|
5081
|
+
if (packageJson.name === expectedName) {
|
|
5082
|
+
return candidate;
|
|
5083
|
+
}
|
|
5084
|
+
}
|
|
5085
|
+
current = path.dirname(current);
|
|
5086
|
+
}
|
|
5087
|
+
throw new Error(`Cannot locate package.json for ${expectedName} above ${startDir}.`);
|
|
5088
|
+
}
|
|
5089
|
+
|
|
5090
|
+
function inspectTokamakCliRuntime() {
|
|
5091
|
+
const doctor = runCaptured(tokamakCliCommand, [...tokamakCliBaseArgs, "--doctor"], {
|
|
5092
|
+
cwd: resolveTokamakCliPackageRoot(),
|
|
5093
|
+
});
|
|
5094
|
+
const doctorOutput = stripAnsi(`${doctor.stdout}${doctor.stderr}`);
|
|
5095
|
+
const runtimeRoot = parseRuntimeRootFromTokamakDoctorOutput(doctorOutput);
|
|
5096
|
+
const cacheRoot = resolveTokamakCliCacheRoot();
|
|
5097
|
+
const installations = readTokamakCliInstallations(cacheRoot);
|
|
5098
|
+
const dockerModeInstalled = installations.some((entry) => entry.installMode === "docker" || entry.docker);
|
|
5099
|
+
const cudaCompatible = installations.some((entry) => entry.docker?.useGpus === true);
|
|
5100
|
+
|
|
5101
|
+
return {
|
|
5102
|
+
installed: doctor.status === 0 || installations.length > 0,
|
|
5103
|
+
packageRoot: resolveTokamakCliPackageRoot(),
|
|
5104
|
+
cacheRoot,
|
|
5105
|
+
runtimeRoot,
|
|
5106
|
+
packageVersion: readPackageReport({
|
|
5107
|
+
name: "@tokamak-zk-evm/cli",
|
|
5108
|
+
packageJsonPath: path.join(resolveTokamakCliPackageRoot(), "package.json"),
|
|
5109
|
+
}).version,
|
|
5110
|
+
dockerModeInstalled,
|
|
5111
|
+
cudaCompatible,
|
|
5112
|
+
doctor: {
|
|
5113
|
+
status: doctor.status,
|
|
5114
|
+
stdout: stripAnsi(doctor.stdout).trim(),
|
|
5115
|
+
stderr: stripAnsi(doctor.stderr).trim(),
|
|
5116
|
+
},
|
|
5117
|
+
installations,
|
|
5118
|
+
};
|
|
5119
|
+
}
|
|
5120
|
+
|
|
5121
|
+
function resolveTokamakCliCacheRoot() {
|
|
5122
|
+
return path.resolve(process.env.TOKAMAK_ZKEVM_CLI_CACHE_DIR ?? path.join(os.homedir(), ".tokamak-zk-evm"));
|
|
5123
|
+
}
|
|
5124
|
+
|
|
5125
|
+
function readTokamakCliInstallations(cacheRoot) {
|
|
5126
|
+
if (!fs.existsSync(cacheRoot)) {
|
|
5127
|
+
return [];
|
|
5128
|
+
}
|
|
5129
|
+
return fs.readdirSync(cacheRoot, { withFileTypes: true })
|
|
5130
|
+
.filter((entry) => entry.isDirectory())
|
|
5131
|
+
.map((entry) => {
|
|
5132
|
+
const platformDir = path.join(cacheRoot, entry.name);
|
|
5133
|
+
const statePath = path.join(platformDir, "installation.json");
|
|
5134
|
+
if (!fs.existsSync(statePath)) {
|
|
5135
|
+
return null;
|
|
5136
|
+
}
|
|
5137
|
+
const state = readJsonIfExists(statePath);
|
|
5138
|
+
const dockerBootstrapPath = path.join(platformDir, "docker", "bootstrap.json");
|
|
5139
|
+
const docker = readJsonIfExists(dockerBootstrapPath);
|
|
5140
|
+
return {
|
|
5141
|
+
platform: entry.name,
|
|
5142
|
+
statePath,
|
|
5143
|
+
runtimeRoot: path.join(platformDir, "runtime"),
|
|
5144
|
+
installMode: state?.installMode ?? (docker ? "docker" : null),
|
|
5145
|
+
packageVersion: state?.packageVersion ?? docker?.packageVersion ?? null,
|
|
5146
|
+
installedAt: state?.installedAt ?? null,
|
|
5147
|
+
dockerBootstrapPath,
|
|
5148
|
+
docker,
|
|
5149
|
+
};
|
|
5150
|
+
})
|
|
5151
|
+
.filter(Boolean);
|
|
5152
|
+
}
|
|
5153
|
+
|
|
5154
|
+
function parseRuntimeRootFromTokamakDoctorOutput(output) {
|
|
5155
|
+
const match = String(output ?? "").match(/^\[ ok \] Runtime workspace:\s*(.+)$/m);
|
|
5156
|
+
return match ? path.resolve(match[1].trim()) : null;
|
|
5157
|
+
}
|
|
5158
|
+
|
|
5159
|
+
function stripAnsi(value) {
|
|
5160
|
+
return String(value ?? "").replace(/\u001b\[[0-9;]*m/g, "");
|
|
5161
|
+
}
|
|
5162
|
+
|
|
4885
5163
|
async function installPrivateStateCliArtifacts({
|
|
4886
5164
|
dappName,
|
|
4887
5165
|
indexFileId = process.env.PRIVATE_STATE_DRIVE_ARTIFACT_INDEX_FILE_ID
|