Skip to main content

Commands

Every script below is taken from the four package.json files as of 2026-10-24. Run root scripts from the repository root and contract scripts from blockchain/. The Network column says what a script reaches:

  • none: works offline (apart from installs and the first download of pinned files);
  • local: needs a local Hardhat node;
  • reads Sepolia: read only;
  • writes Sepolia: sends transactions; run only with the human's go-ahead for that run.

Root app (package.json)​

ScriptRunsNetworkWhat it does
zk:publicnode scripts/zk-public.mjsnonePlaces the circuit files for tree depths 1 to 6 in public/zk/, each checked against src/lib/zk/circuit-hashes.json
predev, prebuildnpm run zk:publicnoneRun before dev and build
devnext dev --turbopackas configuredDevelopment server on port 3000
buildnext buildnoneProduction build. Passes with no environment set; features without settings are off at run time
startnext startas configuredServes a build
linteslint .none
typechecktsc --noEmitnoneDoes not need the contracts compiled
testvitestnoneWatch mode
test:runvitest run --passWithNoTestsnoneAll unit tests once
test:coveragevitest run --coveragenoneFails under the coverage thresholds for src/services and src/lib
test:e2eplaywright testlocal (own node)Builds its own chain and app; see Local development
interop:generatevite-node ... interop/generate.tsnoneRegenerates the fixtures in interop/fixtures; CI fails if they differ from the committed ones
interopnpm --prefix interop testnoneThe independent verifier library tests (Interoperability and SDK tests)
api:keynode scripts/api-key.mjs <id>noneMakes a verification API key: prints the key once, its SHA-256 and the API_KEYS entry to add
import:checkvite-node ... scripts/import-check.ts --nonenpm run import:check -- <file> [--adapter csv|json|template] [--types "Name, Name"] [--folder <dir>]: validates a bulk import file without a wallet (Bulk import)
sdk:buildnpm --prefix packages/sdk run buildnoneCompiles the SDK
sdk:testvitest run packages/sdknoneSDK tests

Contracts (blockchain/package.json)​

Build, test and checks​

ScriptNetworkWhat it does
compilenonehardhat compile (Solidity 0.8.28)
testnonehardhat test, the whole contract suite
coveragenoneCoverage, then fails under 95% lines or 90% branches (scripts/check-coverage.ts)
sizesnoneCompiles and checks runtime sizes: 24,576 bytes (EIP-170) for the v0.2 contracts, a 20,000 byte budget for v0.3
gasnoneTests with the gas reporter, writes gas-report.txt
gas:checknoneFails if a tracked operation costs more than 10% above gas-snapshot.json
gas:snapshotnoneRewrites gas-snapshot.json; refused when CI is set
invariantsnone500 random action sequences against the reference model; INVARIANT_RUNS, INVARIANT_ACTIONS, INVARIANT_SEED change or reproduce a run
export-abisnoneCompiles and copies the ABIs into src/contracts/

Zero-knowledge checks​

ScriptNetworkWhat it does
check:zk-pinsnoneFails when a proof system package is not pinned exactly or the lock file differs from the reviewed snapshot
check:no-mock-verifiernoneFails on a mock verifier in the sources and, after compile, on an unexpected Groth16-shaped function in the ABIs
check:no-dev-keysnoneFails when a tracked file is a proving key, powers of tau file, constraint system or generated verifier
zk:artifactsdownloadsFetches the 32 pairs of circuit files (about 163 MB) into .zk-artifacts, each checked against its recorded hash
check:zk-keysnoneAfter zk:artifacts: the verification key of each of the 32 proving keys must match the pinned verifier
zk:measurenoneProof time, memory and file sizes at depths 2, 4 and 6
zk:reproducenone-- --workdir <dir> [--depth <1-32|all>]: rebuilds the proving keys from the pinned circuit source with circom and checks them against the Perpetual Powers of Tau. On demand, never in CI
accessas givenThe access tool: identity new <file>, identity show <file>, prove ..., submit ... (submit sends a transaction from ACCESS_SUBMIT_KEY). See ZK access

More detail on these checks: ZK tests.

Local deployment​

ScriptNetworkWhat it does
deploy:v03:locallocalDeploys a v0.3 set, writes src/contracts/v03/deployment.31337.json, exports ABIs. Takes GUARDIAN_ADDRESS, ADMIN_DELAY_SEC, ADD_SET, SET_LABEL, ISSUER_REGISTRY, ACTIVATE_SET
issuers:v03:locallocalISSUERS="0xAddr=Name;0xAddr=Name": registers issuers through the admin account, skipping registered ones
smoke:v03:locallocalRegisters the first account as issuer, issues a valid and a revoked credential, reads both back
deploy:access:locallocalDeploys Poseidon, the Semaphore verifier, Semaphore and the access gate; writes src/contracts/zk/deployment.31337.json
deploy:locallocalLegacy v0.2 deployment to blockchain/deployments/localhost.json

Sepolia​

Sepolia scripts load PRIVATE_KEY, INFURA_API_KEY and ETHERSCAN_API_KEY from the root .env (hardhat.config.ts reads ../.env). A deploy refuses to start when PRIVATE_KEY or INFURA_API_KEY is missing.

ScriptNetworkWhat it does
deploy:v03:sepoliawrites SepoliaDeploys a v0.3 set. With ADD_SET=1 adds it to the manifest (a public chain's manifest is never replaced otherwise)
verify:v03:sepoliaexplorer onlyVerifies a set's contracts on Etherscan (SET=<label> for a later set)
issuers:v03:sepoliawrites SepoliaRegisters issuers from the deployer key; only useful before the admin moved to the Safe
smoke:v03:sepoliawrites SepoliaThe v0.3 smoke on Sepolia
handover:v03:sepoliawrites SepoliaADMIN_MULTISIG=<Safe>: nominates the Safe as admin of both registries after preflight checks
governance:v03:sepoliareads SepoliaAdmin, pending admin, delay, pause and guardians of every registry, and the timelock roles when ADMIN_MULTISIG is set
deploy:timelock:sepoliawrites SepoliaADMIN_MULTISIG, TIMELOCK_DELAY_SEC: deploys CertichainTimelock, reads the roles back and records it in the manifest
timelock:nominate:sepoliawrites SepoliaSET=<label>: the deployer nominates the timelock on a new set's registries
timelock:handover:sepoliareads SepoliaSays which handover step is next and writes the Safe batch file for it
timelock:propose:sepoliareads SepoliaTARGET, FUNCTION, ARGS (and SET, DELAY_SEC, SALT or SIGNOFF_FILE, LABEL): writes the schedule, execute and cancel batch files for the Safe
set:ready:sepoliareads SepoliaSET=<label>: lists what blocks activating a set
set:activate:sepoliareads SepoliaRuns the readiness check, then rewrites activeSet in the manifest. Sends nothing
admission:check:sepoliareads SepoliaINSTITUTION, SIGNOFF_FILE (and FROM_BLOCK): whether that sign-off matches a scheduled, executed or cancelled admission
governance:log:checknoneChecks every entry of the governance log under docs/governance/log/
deploy:access:sepoliawrites SepoliaDeploys the access gate for the active set's credential registry
verify:access:sepoliaexplorer onlyVerifies the Semaphore verifier, Semaphore and the gate on Etherscan
network:measurenoneReplays the tracked operations on Hardhat and writes gas and calldata sizes to docs/network/operations.json
network:reportnoneCombines operations.json with dated fee readings in docs/network/fee-levels.json into docs/network/cost-report.md
deploy:sepolia, verify:sepolia, smoke:sepoliawrites SepoliaLegacy v0.2 deployment, verification and smoke (SMOKE_WRITE=true SMOKE_STUDENT_ADDRESS=0x... adds writes)

scripts/verify-timelock.ts has no npm script: npx hardhat run scripts/verify-timelock.ts --network sepolia with ADMIN_MULTISIG set. The governance scripts are explained in Governance and Contract set upgrade; the deploy scripts in Deployment and scripts.

Without an npm script​

npx ts-node scripts/verify-credential.ts <file> [--rpc <url> --registry <address>] checks a credential package, a VC or an Open Badge file offline, and on chain when both flags are given. Exit code 0 only when everything checked is valid. See Command-line tools.

SDK (packages/sdk/package.json)​

ScriptWhat it does
buildtsc -p tsconfig.build.json into dist/
prepackBuilds before packing. The package is private and unpublished

The SDK's tests run from the root (npm run sdk:test). See SDK.

Interoperability tests (interop/package.json)​

ScriptWhat it does
testnode --test over interop/test/*.test.mjs: an independent verifier library checks Certichain VCs, badges and status lists

What CI runs​

The single workflow .github/workflows/ci.yml (Node 22) has six jobs:

JobSteps
Contractscheck:zk-pins, check:no-mock-verifier, check:no-dev-keys, compile, zk:artifacts, check:zk-keys, sizes, gas:check, invariants, gas, coverage
SlitherStatic analysis of the contracts
Frontendlint, typecheck, zk:public, test:coverage, build
Interopinterop:generate (fixtures must be unchanged), interop
SDKsdk:build, sdk:test
E2Enpx playwright install --with-deps chromium, test:e2e

See Continuous integration.

Source files​

  • package.json, blockchain/package.json, packages/sdk/package.json, interop/package.json
  • scripts/zk-public.mjs, scripts/api-key.mjs, scripts/import-check.ts
  • blockchain/scripts/ (one file per script above), blockchain/scripts/lib/network-env.ts
  • .github/workflows/ci.yml
  • Handbook: docs/process/commands.md

Tests​

  • Script logic under blockchain/test/v03/: Deploy.test.ts, RecordDeployment.test.ts, Handover.test.ts, TimelockDeploy.test.ts, TimelockHandover.test.ts, TimelockProposal.test.ts, SetReadiness.test.ts, Admission.test.ts, GovernanceLog.test.ts, VerifyTargets.test.ts, VerifyCredential.test.ts, VerifyVc.test.ts
  • src/lib/import/check-cli.test.ts, e2e/support/guards.test.ts