@tokamak-private-dapps/private-state-cli 2.4.3 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -436,11 +436,50 @@ function readPrivateStateCliInstallManifest(cacheBaseRoot = resolveArtifactCache
436
436
  return readJsonIfExists(privateStateCliInstallManifestPath(cacheBaseRoot));
437
437
  }
438
438
 
439
+ function privateStateCliTermsAcceptancePath(cacheBaseRoot = resolveArtifactCacheBaseRoot()) {
440
+ return path.join(privateStateCliArtifactRoot(cacheBaseRoot), "terms-acceptance.json");
441
+ }
442
+
443
+ function readPrivateStateCliTermsAcceptance(cacheBaseRoot = resolveArtifactCacheBaseRoot()) {
444
+ const installManifest = readPrivateStateCliInstallManifest(cacheBaseRoot);
445
+ return installManifest?.install?.termsAcceptance
446
+ ?? readJsonIfExists(privateStateCliTermsAcceptancePath(cacheBaseRoot))?.termsAcceptance
447
+ ?? null;
448
+ }
449
+
450
+ function writePrivateStateCliTermsAcceptance({
451
+ termsAcceptance,
452
+ cacheBaseRoot = resolveArtifactCacheBaseRoot(),
453
+ }) {
454
+ const manifestPath = privateStateCliInstallManifestPath(cacheBaseRoot);
455
+ const installManifest = readJsonIfExists(manifestPath);
456
+ if (installManifest) {
457
+ installManifest.install = {
458
+ ...(installManifest.install ?? {}),
459
+ termsAcceptance,
460
+ };
461
+ writeJson(manifestPath, installManifest);
462
+ return {
463
+ path: manifestPath,
464
+ location: "install-manifest",
465
+ termsAcceptance,
466
+ };
467
+ }
468
+ const acceptancePath = privateStateCliTermsAcceptancePath(cacheBaseRoot);
469
+ writeJson(acceptancePath, { termsAcceptance });
470
+ return {
471
+ path: acceptancePath,
472
+ location: "terms-acceptance",
473
+ termsAcceptance,
474
+ };
475
+ }
476
+
439
477
  function writePrivateStateCliInstallManifest({
440
478
  installMode = PRIVATE_STATE_INSTALL_MODES.FULL,
441
479
  dockerRequested,
442
480
  includeLocalArtifacts,
443
481
  localDeploymentBaseRoot,
482
+ termsAcceptance,
444
483
  deploymentArtifacts,
445
484
  selectedVersions,
446
485
  tokamakCliRuntime,
@@ -459,6 +498,7 @@ function writePrivateStateCliInstallManifest({
459
498
  mode: normalizeInstallMode(installMode),
460
499
  includeLocalArtifacts,
461
500
  localDeploymentBaseRoot,
501
+ termsAcceptance: termsAcceptance ?? null,
462
502
  artifactCacheRoot: deploymentArtifacts.cacheBaseRoot,
463
503
  selectedVersions,
464
504
  tokamakCliRuntime,
@@ -594,6 +634,7 @@ function buildDoctorReport({ probeGpu = false } = {}) {
594
634
  mode: installMode,
595
635
  dockerRequested: installManifest?.install?.dockerRequested ?? null,
596
636
  includeLocalArtifacts: installManifest?.install?.includeLocalArtifacts ?? null,
637
+ termsAcceptance: installManifest?.install?.termsAcceptance ?? null,
597
638
  selectedVersions: installManifest?.install?.selectedVersions ?? null,
598
639
  tokamakCliRuntime: installManifest?.install?.tokamakCliRuntime ?? null,
599
640
  groth16Runtime: installManifest?.install?.groth16Runtime ?? null,
@@ -773,7 +814,7 @@ async function installTokamakCliRuntimeForPrivateState({ version, docker }) {
773
814
  if (docker) {
774
815
  installArgs.push("--docker");
775
816
  }
776
- run(invocation.command, installArgs, { cwd: packageInstall.packageRoot });
817
+ run(invocation.command, installArgs, { cwd: packageInstall.packageRoot, quiet: true });
777
818
  const doctor = runCaptured(invocation.command, [...invocation.args, "--doctor"], {
778
819
  cwd: packageInstall.packageRoot,
779
820
  });
@@ -807,7 +848,7 @@ async function installGroth16RuntimeForPrivateState({ version, docker }) {
807
848
  if (docker) {
808
849
  args.push("--docker");
809
850
  }
810
- run(process.execPath, args, { cwd: packageRoot });
851
+ run(process.execPath, args, { cwd: packageRoot, quiet: true });
811
852
  const compatibleBackendVersion = readGroth16PackageCompatibleBackendVersion(packageRoot);
812
853
  const crsInstall = await installGroth16CrsForPrivateStateVersion(compatibleBackendVersion);
813
854
  const runtime = inspectGroth16Runtime({ packageRoot });
@@ -940,7 +981,7 @@ function installManagedNpmPackage({ packageName, version, cacheBaseRoot = resolv
940
981
  "--no-audit",
941
982
  "--fund=false",
942
983
  `${normalizedPackageName}@${normalizedVersion}`,
943
- ]);
984
+ ], { quiet: true });
944
985
  const packageRoot = path.join(installPrefix, "node_modules", ...normalizedPackageName.split("/"));
945
986
  const packageJsonPath = path.join(packageRoot, "package.json");
946
987
  const packageJson = readJson(packageJsonPath);
@@ -1326,7 +1367,8 @@ async function installPrivateStateCliArtifacts({
1326
1367
  ?? DEFAULT_PUBLIC_ARTIFACT_INDEX_FILE_ID,
1327
1368
  cacheBaseRoot,
1328
1369
  localDeploymentBaseRoot,
1329
- localChainIds = [31337],
1370
+ chainIds = null,
1371
+ localChainIds = null,
1330
1372
  groth16CrsVersion,
1331
1373
  } = {}) {
1332
1374
  const normalizedDappName = requireNonEmptyString(dappName, "dappName");
@@ -1335,15 +1377,21 @@ async function installPrivateStateCliArtifacts({
1335
1377
  const normalizedLocalDeploymentBaseRoot = localDeploymentBaseRoot
1336
1378
  ? path.resolve(localDeploymentBaseRoot)
1337
1379
  : null;
1380
+ const selectedChainIds = chainIds === null
1381
+ ? null
1382
+ : new Set(chainIds.map((chainId) => String(requireChainId(chainId))));
1338
1383
  const index = await fetchPublicArtifactIndex(indexFileId);
1339
- const installed = [];
1384
+ const installedByChainId = new Map();
1340
1385
 
1341
1386
  for (const chainId of Object.keys(index.chains).sort(compareChainIds)) {
1387
+ if (selectedChainIds !== null && !selectedChainIds.has(String(requireChainId(chainId)))) {
1388
+ continue;
1389
+ }
1342
1390
  const chain = index.chains[chainId];
1343
1391
  if (!chain?.bridge?.timestamp || !chain?.bridge?.files || !chain.dapps?.[normalizedDappName]) {
1344
1392
  continue;
1345
1393
  }
1346
- installed.push(await materializePrivateStateCliDeployment({
1394
+ const installed = await materializePrivateStateCliDeployment({
1347
1395
  index,
1348
1396
  chainId,
1349
1397
  dappName: normalizedDappName,
@@ -1351,22 +1399,34 @@ async function installPrivateStateCliArtifacts({
1351
1399
  cacheBaseRoot: normalizedCacheBaseRoot,
1352
1400
  source: "drive",
1353
1401
  groth16CrsVersion,
1354
- }));
1402
+ });
1403
+ installedByChainId.set(String(installed.chainId), installed);
1355
1404
  }
1356
1405
 
1357
1406
  if (normalizedLocalDeploymentBaseRoot) {
1358
- for (const chainId of localChainIds) {
1359
- installed.push(await materializeLocalPrivateStateCliDeployment({
1407
+ const discoveredLocalChainIds = (localChainIds ?? discoverLocalPrivateStateDeploymentChainIds({
1408
+ localDeploymentBaseRoot: normalizedLocalDeploymentBaseRoot,
1409
+ dappName: normalizedDappName,
1410
+ })).filter((chainId) => selectedChainIds === null || selectedChainIds.has(String(requireChainId(chainId))));
1411
+ if (discoveredLocalChainIds.length === 0) {
1412
+ throw new Error(
1413
+ `No local ${normalizedDappName} deployment artifacts found under ${normalizedLocalDeploymentBaseRoot}.`,
1414
+ );
1415
+ }
1416
+ for (const chainId of discoveredLocalChainIds) {
1417
+ const installed = await materializeLocalPrivateStateCliDeployment({
1360
1418
  chainId,
1361
1419
  dappName: normalizedDappName,
1362
1420
  installMode: normalizedInstallMode,
1363
1421
  cacheBaseRoot: normalizedCacheBaseRoot,
1364
1422
  localDeploymentBaseRoot: normalizedLocalDeploymentBaseRoot,
1365
1423
  groth16CrsVersion,
1366
- }));
1424
+ });
1425
+ installedByChainId.set(String(installed.chainId), installed);
1367
1426
  }
1368
1427
  }
1369
1428
 
1429
+ const installed = [...installedByChainId.values()].sort((left, right) => compareChainIds(left.chainId, right.chainId));
1370
1430
  if (installed.length === 0) {
1371
1431
  throw new Error(`No installable artifacts found for ${normalizedDappName}.`);
1372
1432
  }
@@ -1378,6 +1438,23 @@ async function installPrivateStateCliArtifacts({
1378
1438
  };
1379
1439
  }
1380
1440
 
1441
+ function discoverLocalPrivateStateDeploymentChainIds({ localDeploymentBaseRoot, dappName }) {
1442
+ const deploymentRoot = path.join(localDeploymentBaseRoot, "deployment");
1443
+ if (!fs.existsSync(deploymentRoot)) {
1444
+ return [];
1445
+ }
1446
+ return fs.readdirSync(deploymentRoot, { withFileTypes: true })
1447
+ .filter((entry) => entry.isDirectory())
1448
+ .map((entry) => /^chain-id-(\d+)$/u.exec(entry.name)?.[1] ?? null)
1449
+ .filter((chainId) => chainId !== null)
1450
+ .filter((chainId) => {
1451
+ const bridgeRoot = path.join(deploymentRoot, `chain-id-${chainId}`, "bridge");
1452
+ const dappRoot = path.join(deploymentRoot, `chain-id-${chainId}`, "dapps", dappName);
1453
+ return fs.existsSync(bridgeRoot) && fs.existsSync(dappRoot);
1454
+ })
1455
+ .sort(compareChainIds);
1456
+ }
1457
+
1381
1458
  async function materializePrivateStateCliDeployment({
1382
1459
  index,
1383
1460
  chainId,
@@ -1559,7 +1636,9 @@ export {
1559
1636
  installTokamakCliRuntimeForPrivateState,
1560
1637
  installGroth16RuntimeForPrivateState,
1561
1638
  installPrivateStateCliArtifacts,
1639
+ readPrivateStateCliTermsAcceptance,
1562
1640
  writePrivateStateCliInstallManifest,
1641
+ writePrivateStateCliTermsAcceptance,
1563
1642
  parseJsonReport,
1564
1643
  resolveArtifactCacheBaseRoot,
1565
1644
  privateStateCliArtifactPaths,
@@ -1573,4 +1652,5 @@ export {
1573
1652
  readTokamakCliPackageReport,
1574
1653
  requireActiveTokamakCliRuntimeRoot,
1575
1654
  resolveTokamakCliResourceDirForRuntimeRoot,
1655
+ resolveTokamakCliCacheRoot,
1576
1656
  };
@@ -0,0 +1,35 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { createHash } from "node:crypto";
4
+ import { fileURLToPath } from "node:url";
5
+
6
+ export const PRIVATE_STATE_TERMS_VERSION = "2026-06-12";
7
+ export const PRIVATE_STATE_TERMS_HASH_ALGORITHM = "sha256";
8
+ export const PRIVATE_STATE_TERMS_PACKAGE_PATH = "assets/service-terms.md";
9
+ export const PRIVATE_STATE_TERMS_PUBLIC_PATH = "docs/dapps/private-state/terms.md";
10
+
11
+ const privateStateCliPackageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
12
+ const privateStateTermsAssetPath = path.join(privateStateCliPackageRoot, PRIVATE_STATE_TERMS_PACKAGE_PATH);
13
+
14
+ export function readPrivateStateTermsText() {
15
+ return fs.readFileSync(privateStateTermsAssetPath, "utf8");
16
+ }
17
+
18
+ export function computePrivateStateTermsHash(termsText = readPrivateStateTermsText()) {
19
+ return `${PRIVATE_STATE_TERMS_HASH_ALGORITHM}:${createHash(PRIVATE_STATE_TERMS_HASH_ALGORITHM)
20
+ .update(termsText, "utf8")
21
+ .digest("hex")}`;
22
+ }
23
+
24
+ export function readPrivateStateTermsMetadata() {
25
+ const termsText = readPrivateStateTermsText();
26
+ return {
27
+ termsVersion: PRIVATE_STATE_TERMS_VERSION,
28
+ termsHash: computePrivateStateTermsHash(termsText),
29
+ termsHashAlgorithm: PRIVATE_STATE_TERMS_HASH_ALGORITHM,
30
+ termsPackagePath: PRIVATE_STATE_TERMS_PACKAGE_PATH,
31
+ termsPublicPath: PRIVATE_STATE_TERMS_PUBLIC_PATH,
32
+ termsHashInput: "exact UTF-8 bytes of the packaged Service Terms Markdown",
33
+ termsContentBytes: Buffer.byteLength(termsText, "utf8"),
34
+ };
35
+ }