From 133b0c79532e76e2633021a2fcfff2657e17768a Mon Sep 17 00:00:00 2001 From: stanlou Date: Mon, 9 Mar 2026 12:45:11 -0300 Subject: [PATCH 1/7] feat(cli): add explorer stop command --- .../cli/src/commands/explorer/explorer.ts | 2 + .../cli/src/commands/explorer/explorerStop.ts | 17 +++++++++ packages/cli/src/scripts/explorer/start.ts | 12 +++++- packages/cli/src/scripts/explorer/stop.ts | 37 +++++++++++++++++++ 4 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 packages/cli/src/commands/explorer/explorerStop.ts create mode 100644 packages/cli/src/scripts/explorer/stop.ts diff --git a/packages/cli/src/commands/explorer/explorer.ts b/packages/cli/src/commands/explorer/explorer.ts index 037163de4..4dd8c01fc 100644 --- a/packages/cli/src/commands/explorer/explorer.ts +++ b/packages/cli/src/commands/explorer/explorer.ts @@ -5,9 +5,11 @@ export const explorerCommand: CommandModule = { describe: "Explorer commands", builder: async (yargs) => { const { explorerStartCommand } = await import("./explorerStart"); + const { explorerStopCommand } = await import("./explorerStop"); return yargs .command(explorerStartCommand) + .command(explorerStopCommand) .demandCommand( 1, "You must specify a subcommand. Use --help to see available options." diff --git a/packages/cli/src/commands/explorer/explorerStop.ts b/packages/cli/src/commands/explorer/explorerStop.ts new file mode 100644 index 000000000..3655e0cc9 --- /dev/null +++ b/packages/cli/src/commands/explorer/explorerStop.ts @@ -0,0 +1,17 @@ +import { CommandModule } from "yargs"; + +export const explorerStopCommand: CommandModule = { + command: "stop", + describe: "Stop the explorer UI", + handler: async () => { + try { + const { default: explorerStop } = + await import("../../scripts/explorer/stop"); + await explorerStop(); + process.exit(0); + } catch (error) { + console.error("Failed to stop explorer:", error); + process.exit(1); + } + }, +}; diff --git a/packages/cli/src/scripts/explorer/start.ts b/packages/cli/src/scripts/explorer/start.ts index b84105c93..d843d427a 100644 --- a/packages/cli/src/scripts/explorer/start.ts +++ b/packages/cli/src/scripts/explorer/start.ts @@ -35,8 +35,16 @@ async function runDockerContainer(args: { const { port = 5003, explorerImage } = args; console.log(`\nExplorer is running at http://localhost:${port}\n`); - const dockerArgs = ["run", "--rm", "-p", `${port}:3000`]; - + const dockerArgs = [ + "run", + "-d", + "--rm", + "--name", + "protokit-explorer", + "-p", + `${port}:3000`, + ]; + if (args.indexerUrl !== undefined) { dockerArgs.push("-e", `NEXT_PUBLIC_INDEXER_URL=${args.indexerUrl}`); } diff --git a/packages/cli/src/scripts/explorer/stop.ts b/packages/cli/src/scripts/explorer/stop.ts new file mode 100644 index 000000000..cc0c46aa3 --- /dev/null +++ b/packages/cli/src/scripts/explorer/stop.ts @@ -0,0 +1,37 @@ +import { spawn } from "child_process"; + +const CONTAINER_NAME = "protokit-explorer"; + +async function stopDockerContainer(): Promise { + return await new Promise((resolve, reject) => { + console.log(`Stopping explorer container...`); + const child = spawn("docker", ["stop", CONTAINER_NAME], { + stdio: "inherit", + }); + + child.on("error", (error) => { + console.error("Failed to stop explorer container:", error); + reject(error); + }); + + child.on("exit", (code) => { + if (code !== null && code !== 0) { + reject( + new Error(`Failed to stop explorer container (exit code ${code})`) + ); + } else { + console.log("Explorer container stopped successfully"); + resolve(); + } + }); + }); +} + +export default async function (): Promise { + try { + await stopDockerContainer(); + } catch (error) { + console.error("Failed to stop explorer:", error); + throw error; + } +} From 6c4994e32fec650b24f145ea8466e3618cc65dd1 Mon Sep 17 00:00:00 2001 From: stanlou Date: Mon, 9 Mar 2026 13:14:05 -0300 Subject: [PATCH 2/7] fix lint --- packages/cli/src/scripts/explorer/start.ts | 2 +- packages/cli/src/scripts/explorer/stop.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cli/src/scripts/explorer/start.ts b/packages/cli/src/scripts/explorer/start.ts index d843d427a..a9e129ef3 100644 --- a/packages/cli/src/scripts/explorer/start.ts +++ b/packages/cli/src/scripts/explorer/start.ts @@ -44,7 +44,7 @@ async function runDockerContainer(args: { "-p", `${port}:3000`, ]; - + if (args.indexerUrl !== undefined) { dockerArgs.push("-e", `NEXT_PUBLIC_INDEXER_URL=${args.indexerUrl}`); } diff --git a/packages/cli/src/scripts/explorer/stop.ts b/packages/cli/src/scripts/explorer/stop.ts index cc0c46aa3..db2294076 100644 --- a/packages/cli/src/scripts/explorer/stop.ts +++ b/packages/cli/src/scripts/explorer/stop.ts @@ -4,7 +4,7 @@ const CONTAINER_NAME = "protokit-explorer"; async function stopDockerContainer(): Promise { return await new Promise((resolve, reject) => { - console.log(`Stopping explorer container...`); + console.log("Stopping explorer container..."); const child = spawn("docker", ["stop", CONTAINER_NAME], { stdio: "inherit", }); From cf11098ced7fe60f95dfeafe90d12483b4f6e24f Mon Sep 17 00:00:00 2001 From: stanlou Date: Wed, 11 Mar 2026 01:11:50 -0300 Subject: [PATCH 3/7] refactor(cli): centralize explorer Docker container name as exported constant --- packages/cli/src/scripts/explorer/start.ts | 3 ++- packages/cli/src/scripts/explorer/stop.ts | 5 ++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/cli/src/scripts/explorer/start.ts b/packages/cli/src/scripts/explorer/start.ts index a9e129ef3..37f5941ef 100644 --- a/packages/cli/src/scripts/explorer/start.ts +++ b/packages/cli/src/scripts/explorer/start.ts @@ -1,5 +1,6 @@ import { spawn } from "child_process"; +export const EXPLORER_CONTAINER_NAME = "protokit-explorer"; const DEFAULT_EXPLORER_IMAGE = "ghcr.io/proto-kit/explorer:latest"; async function pullDockerImage(image: string): Promise { @@ -40,7 +41,7 @@ async function runDockerContainer(args: { "-d", "--rm", "--name", - "protokit-explorer", + EXPLORER_CONTAINER_NAME, "-p", `${port}:3000`, ]; diff --git a/packages/cli/src/scripts/explorer/stop.ts b/packages/cli/src/scripts/explorer/stop.ts index db2294076..133b33c33 100644 --- a/packages/cli/src/scripts/explorer/stop.ts +++ b/packages/cli/src/scripts/explorer/stop.ts @@ -1,11 +1,10 @@ import { spawn } from "child_process"; - -const CONTAINER_NAME = "protokit-explorer"; +import { EXPLORER_CONTAINER_NAME } from "./start"; async function stopDockerContainer(): Promise { return await new Promise((resolve, reject) => { console.log("Stopping explorer container..."); - const child = spawn("docker", ["stop", CONTAINER_NAME], { + const child = spawn("docker", ["stop", EXPLORER_CONTAINER_NAME], { stdio: "inherit", }); From 59e348773656b0eb2216caebcae93e9a5d96b848 Mon Sep 17 00:00:00 2001 From: stanlou Date: Wed, 11 Mar 2026 09:21:35 -0300 Subject: [PATCH 4/7] fix lint --- packages/cli/src/scripts/explorer/stop.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/cli/src/scripts/explorer/stop.ts b/packages/cli/src/scripts/explorer/stop.ts index 133b33c33..7fd2d947c 100644 --- a/packages/cli/src/scripts/explorer/stop.ts +++ b/packages/cli/src/scripts/explorer/stop.ts @@ -1,4 +1,5 @@ import { spawn } from "child_process"; + import { EXPLORER_CONTAINER_NAME } from "./start"; async function stopDockerContainer(): Promise { From 0b800f8edf70fbfe25bdcc502bfabb457dbc1e02 Mon Sep 17 00:00:00 2001 From: stanlou Date: Tue, 17 Mar 2026 11:22:43 -0300 Subject: [PATCH 5/7] feat(cli): analyze runtime and protocol circuit sizes --- package-lock.json | 1 + packages/cli/package.json | 1 + packages/cli/src/commands/circuitSummary.ts | 19 +++++ packages/cli/src/index.ts | 2 + packages/cli/src/scripts/circuitSummary.ts | 90 +++++++++++++++++++++ 5 files changed, 113 insertions(+) create mode 100644 packages/cli/src/commands/circuitSummary.ts create mode 100644 packages/cli/src/scripts/circuitSummary.ts diff --git a/package-lock.json b/package-lock.json index 1d57189ac..8c0b7475a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28984,6 +28984,7 @@ "dotenv": "^17.2.3", "inquirer": "^9.3.0", "kleur": "^4.1.5", + "loglevel": "^1.8.1", "mina-fungible-token": "^1.1.0", "reflect-metadata": "^0.1.13", "spectaql": "3.0.5", diff --git a/packages/cli/package.json b/packages/cli/package.json index 3f30a7a27..d82d43526 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -25,6 +25,7 @@ "dotenv": "^17.2.3", "inquirer": "^9.3.0", "kleur": "^4.1.5", + "loglevel": "^1.8.1", "mina-fungible-token": "^1.1.0", "reflect-metadata": "^0.1.13", "spectaql": "3.0.5", diff --git a/packages/cli/src/commands/circuitSummary.ts b/packages/cli/src/commands/circuitSummary.ts new file mode 100644 index 000000000..306f657fd --- /dev/null +++ b/packages/cli/src/commands/circuitSummary.ts @@ -0,0 +1,19 @@ +import { CommandModule } from "yargs"; + +export const circuitSummaryCommand: CommandModule = { + command: "summary", + describe: + "Print a summary of the circuit sizes of runtime and protocol circuits", + builder: (yarg) => yarg, + handler: async () => { + try { + const { default: circuitSummary } = + await import("../scripts/circuitSummary"); + await circuitSummary(); + process.exit(0); + } catch (error) { + console.error("Failed to generate circuit summary:", error); + process.exit(1); + } + }, +}; diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index 7f60b14b9..eece25a14 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -10,6 +10,7 @@ import { wizardCommand } from "./commands/wizard"; import { settlementCommand } from "./commands/settlement/settlement"; import { lightnetCommand } from "./commands/lightnet/lightnet"; import { bridgeCommand } from "./commands/bridge/bridge"; +import { circuitSummaryCommand } from "./commands/circuitSummary"; process.removeAllListeners("warning"); process.env.NODE_NO_WARNINGS = "1"; @@ -25,6 +26,7 @@ await yargs(hideBin(process.argv)) .command(settlementCommand) .command(lightnetCommand) .command(bridgeCommand) + .command(circuitSummaryCommand) .demandCommand( 1, "You must specify a command. Use --help to see available commands." diff --git a/packages/cli/src/scripts/circuitSummary.ts b/packages/cli/src/scripts/circuitSummary.ts new file mode 100644 index 000000000..e6505df8a --- /dev/null +++ b/packages/cli/src/scripts/circuitSummary.ts @@ -0,0 +1,90 @@ +import "reflect-metadata"; +import { container } from "tsyringe"; +import loglevel from "loglevel"; + +import { loadUserModules } from "../utils/loadUserModules"; + +export default async function (): Promise { + console.log("Analyzing circuit sizes..."); + const { PrivateKey } = await import("o1js"); + process.env.PROTOKIT_TRANSACTION_FEE_RECIPIENT_PUBLIC_KEY = + PrivateKey.random().toPublicKey().toBase58(); + + const { Runtime } = await import("@proto-kit/module"); + const { Protocol, RuntimeVerificationKeyRootService, ContractArgsRegistry } = + await import("@proto-kit/protocol"); + const { AppChain, Sequencer, CircuitAnalysisModule } = + await import("@proto-kit/sequencer"); + const { + CompileRegistry, + ChildVerificationKeyService, + MOCK_VERIFICATION_KEY, + } = await import("@proto-kit/common"); + + const { runtime, protocol } = await loadUserModules(); + + const appChain = AppChain.from({ + Runtime: Runtime.from(runtime.modules), + Protocol: Protocol.from({ + ...protocol.modules, + ...protocol.settlementModules, + }), + Sequencer: Sequencer.from({}), + }); + + appChain.configure({ + Runtime: runtime.config, + Protocol: { + ...protocol.config, + ...protocol.settlementModulesConfig, + }, + Sequencer: {}, + }); + + loglevel.setLevel("SILENT"); + + const chainContainer = container.createChildContainer(); + await appChain.start(false, chainContainer); + + appChain.protocol.dependencyContainer + .resolve(RuntimeVerificationKeyRootService) + .setRoot(0n); + + if (protocol.settlementModules !== undefined) { + const { SignedSettlementPermissions } = + await import("@proto-kit/sequencer"); + + const compileRegistry = + appChain.protocol.dependencyContainer.resolve(CompileRegistry); + const dummyVk = MOCK_VERIFICATION_KEY; + compileRegistry.addArtifactsRaw({ + BlockProver: { verificationKey: dummyVk }, + BridgeContract: { verificationKey: dummyVk }, + }); + + const childVkService = appChain.protocol.dependencyContainer.resolve( + ChildVerificationKeyService + ); + childVkService.setCompileRegistry(compileRegistry); + + const permissions = new SignedSettlementPermissions(); + const argsRegistry = + appChain.protocol.dependencyContainer.resolve(ContractArgsRegistry); + argsRegistry.addArgs("SettlementContract", { + signedSettlements: true, + BridgeContractPermissions: permissions.bridgeContractMina(), + }); + } + try { + const analysisModule = appChain.protocol.dependencyContainer.resolve( + CircuitAnalysisModule + ); + + loglevel.setLevel("INFO"); + await analysisModule.printSummary(); + } finally { + loglevel.setLevel("SILENT"); + await appChain.close(); + loglevel.setLevel("INFO"); + } +} From ce6bb333adf04002a452bd66c977453910e37e15 Mon Sep 17 00:00:00 2001 From: stanlou Date: Tue, 17 Mar 2026 11:23:16 -0300 Subject: [PATCH 6/7] fix lint --- packages/cli/src/scripts/circuitSummary.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/src/scripts/circuitSummary.ts b/packages/cli/src/scripts/circuitSummary.ts index e6505df8a..cd3aa81e6 100644 --- a/packages/cli/src/scripts/circuitSummary.ts +++ b/packages/cli/src/scripts/circuitSummary.ts @@ -40,7 +40,7 @@ export default async function (): Promise { }, Sequencer: {}, }); - + loglevel.setLevel("SILENT"); const chainContainer = container.createChildContainer(); From b0838c3a997bca4c5d7a39e92ae03c6c9123f47d Mon Sep 17 00:00:00 2001 From: stanlou Date: Mon, 23 Mar 2026 06:12:44 +0300 Subject: [PATCH 7/7] rebase on develop --- .../cli/src/commands/explorer/explorer.ts | 2 - .../cli/src/commands/explorer/explorerStop.ts | 17 --------- packages/cli/src/scripts/explorer/start.ts | 1 - packages/cli/src/scripts/explorer/stop.ts | 37 ------------------- 4 files changed, 57 deletions(-) delete mode 100644 packages/cli/src/commands/explorer/explorerStop.ts delete mode 100644 packages/cli/src/scripts/explorer/stop.ts diff --git a/packages/cli/src/commands/explorer/explorer.ts b/packages/cli/src/commands/explorer/explorer.ts index 4dd8c01fc..037163de4 100644 --- a/packages/cli/src/commands/explorer/explorer.ts +++ b/packages/cli/src/commands/explorer/explorer.ts @@ -5,11 +5,9 @@ export const explorerCommand: CommandModule = { describe: "Explorer commands", builder: async (yargs) => { const { explorerStartCommand } = await import("./explorerStart"); - const { explorerStopCommand } = await import("./explorerStop"); return yargs .command(explorerStartCommand) - .command(explorerStopCommand) .demandCommand( 1, "You must specify a subcommand. Use --help to see available options." diff --git a/packages/cli/src/commands/explorer/explorerStop.ts b/packages/cli/src/commands/explorer/explorerStop.ts deleted file mode 100644 index 3655e0cc9..000000000 --- a/packages/cli/src/commands/explorer/explorerStop.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { CommandModule } from "yargs"; - -export const explorerStopCommand: CommandModule = { - command: "stop", - describe: "Stop the explorer UI", - handler: async () => { - try { - const { default: explorerStop } = - await import("../../scripts/explorer/stop"); - await explorerStop(); - process.exit(0); - } catch (error) { - console.error("Failed to stop explorer:", error); - process.exit(1); - } - }, -}; diff --git a/packages/cli/src/scripts/explorer/start.ts b/packages/cli/src/scripts/explorer/start.ts index 37f5941ef..d07e0785f 100644 --- a/packages/cli/src/scripts/explorer/start.ts +++ b/packages/cli/src/scripts/explorer/start.ts @@ -38,7 +38,6 @@ async function runDockerContainer(args: { const dockerArgs = [ "run", - "-d", "--rm", "--name", EXPLORER_CONTAINER_NAME, diff --git a/packages/cli/src/scripts/explorer/stop.ts b/packages/cli/src/scripts/explorer/stop.ts deleted file mode 100644 index 7fd2d947c..000000000 --- a/packages/cli/src/scripts/explorer/stop.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { spawn } from "child_process"; - -import { EXPLORER_CONTAINER_NAME } from "./start"; - -async function stopDockerContainer(): Promise { - return await new Promise((resolve, reject) => { - console.log("Stopping explorer container..."); - const child = spawn("docker", ["stop", EXPLORER_CONTAINER_NAME], { - stdio: "inherit", - }); - - child.on("error", (error) => { - console.error("Failed to stop explorer container:", error); - reject(error); - }); - - child.on("exit", (code) => { - if (code !== null && code !== 0) { - reject( - new Error(`Failed to stop explorer container (exit code ${code})`) - ); - } else { - console.log("Explorer container stopped successfully"); - resolve(); - } - }); - }); -} - -export default async function (): Promise { - try { - await stopDockerContainer(); - } catch (error) { - console.error("Failed to stop explorer:", error); - throw error; - } -}