Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
2c5bde8
feat: add default modules and configurations for sequencer presets
stanlou Jan 20, 2026
61c9abb
use default modules
stanlou Jan 24, 2026
3a05782
fix code format
stanlou Jan 24, 2026
ea5e64a
fix graphql server config
stanlou Jan 24, 2026
6438771
extend CLI with interactive setup and operational commands
stanlou Jan 28, 2026
f8b8fbf
feat: add default modules and configurations for sequencer presets
stanlou Jan 20, 2026
bd88621
use default modules
stanlou Jan 24, 2026
4f0a0b8
fix code format
stanlou Jan 24, 2026
19ad5b9
fix graphql server config
stanlou Jan 24, 2026
cfafd17
extend CLI with interactive setup and operational commands
stanlou Jan 28, 2026
c3e481b
feat: expose isSginedSettlement to SettlemntUtils
saitunc Jan 30, 2026
709adcb
refactor: update scripts and configs with new SettlementModule API
saitunc Jan 30, 2026
78092d3
Merge branch 'feat/cli-extended-functionality' into feat/cli-extended…
saitunc Jan 30, 2026
1c9b745
fix: run lint fix
saitunc Jan 30, 2026
45e28e6
Merge pull request #414 from proto-kit/feat/cli-extended-functionalit…
stanlou Jan 30, 2026
1ed0f4f
fix prismaRedisDatabase & redisTaskQueue typo
stanlou Jan 30, 2026
7b3ef58
refactor: return public keys in config token
saitunc Jan 31, 2026
491f957
fix: fix typo in prismaRedisDatabase naming
saitunc Jan 31, 2026
479bc8b
refactor cli commands
stanlou Feb 1, 2026
83bea8b
fix lint
stanlou Feb 1, 2026
9a7e941
generate worker config
stanlou Feb 2, 2026
c3e94fc
fix worker config
stanlou Feb 2, 2026
0fedc98
fix lint
stanlou Feb 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
201 changes: 168 additions & 33 deletions package-lock.json

Large diffs are not rendered by default.

18 changes: 14 additions & 4 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"type": "module",
"main": "./bin/protokit-cli.js",
"bin": {
"proto-kit": "./bin/protokit-cli.js"
"protokit": "./bin/protokit-cli.js"
},
"publishConfig": {
"access": "public"
Expand All @@ -21,21 +21,31 @@
"author": "",
"license": "ISC",
"dependencies": {
"yargs": "17.7.2",
"@inquirer/figures": "^2.0.3",
"dotenv": "^17.2.3",
"inquirer": "^9.3.0",
"kleur": "^4.1.5",
"mina-fungible-token": "^1.1.0",
"reflect-metadata": "^0.1.13",
"spectaql": "3.0.5",
"ts-node": "^10.9.1",
"spectaql": "3.0.5"
"yargs": "17.7.2"
},
"peerDependencies": {
"@proto-kit/api": "*",
"@proto-kit/common": "*",
"@proto-kit/explorer": "*",
"@proto-kit/library": "*",
"@proto-kit/module": "*",
"@proto-kit/protocol": "*",
"@proto-kit/sdk": "*",
"@proto-kit/sequencer": "*",
"o1js": "^2.10.0"
"@proto-kit/stack": "*",
"o1js": "^2.10.0",
"tsyringe": "^4.10.0"
},
"devDependencies": {
"@types/inquirer": "^9.0.9",
"@types/node": "^20.19.24",
"@types/yargs": "17.0.32"
}
Expand Down
19 changes: 19 additions & 0 deletions packages/cli/src/commands/explorer/explorer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { CommandModule } from "yargs";

export const explorerCommand: CommandModule = {
command: "explorer <subcommand>",
describe: "Explorer commands",
builder: async (yargs) => {
const { explorerStartCommand } = await import("./explorerStart");

return yargs
.command(explorerStartCommand)
.demandCommand(
1,
"You must specify a subcommand. Use --help to see available options."
);
},
handler: () => {
console.log("Use a subcommand. See --help for available options.");
},
};
52 changes: 52 additions & 0 deletions packages/cli/src/commands/explorer/explorerStart.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { CommandModule } from "yargs";

interface ExplorerStartArgs {
port: number;
"indexer-url"?: string;
"dashboard-title"?: string;
"dashboard-slogan"?: string;
}

export const explorerStartCommand: CommandModule<{}, ExplorerStartArgs> = {
command: "start",
describe: "Start the explorer UI",
builder: (yarg) =>
yarg
.option("port", {
alias: "p",
type: "number",
default: 5003,
describe: "port to run the explorer on",
})
.option("indexer-url", {
type: "string",
describe: "GraphQL endpoint URL for the indexer",
})
.option("dashboard-title", {
type: "string",
default: "Protokit Explorer",
describe: "Title for the explorer dashboard",
})
.option("dashboard-slogan", {
type: "string",
default: "Explore your Protokit AppChain",
describe: "Slogan for the explorer dashboard",
}),
handler: async (args) => {
try {
const { default: explorerStart } = await import(
"../../scripts/explorer/start"
);
await explorerStart({
port: args.port,
indexerUrl: args["indexer-url"],
dashboardTitle: args["dashboard-title"],
dashboardSlogan: args["dashboard-slogan"],
});
process.exit(0);
} catch (error) {
console.error("Failed to start explorer:", error);
process.exit(1);
}
},
};
114 changes: 40 additions & 74 deletions packages/cli/src/commands/generateGqlDocs.ts
Original file line number Diff line number Diff line change
@@ -1,78 +1,44 @@
import {
BlockStorageNetworkStateModule,
InMemoryTransactionSender,
StateServiceQueryModule,
} from "@proto-kit/sdk";
import { Protocol } from "@proto-kit/protocol";
import {
AppChain,
Sequencer,
VanillaTaskWorkerModules,
} from "@proto-kit/sequencer";
import {
InMemorySequencerModules,
VanillaProtocolModules,
VanillaRuntimeModules,
} from "@proto-kit/library";
import {
GraphqlSequencerModule,
GraphqlServer,
VanillaGraphqlModules,
} from "@proto-kit/api";
import { Runtime } from "@proto-kit/module";
import { CommandModule } from "yargs";

import { generateGqlDocs } from "../utils";

export async function generateGqlDocsCommand(args: {
empty: boolean;
interface GenerateGqlDocsArgs {
port: number;
url: string;
}) {
if (args.empty) {
const { port } = args;
console.log(`Starting AppChain on port ${port}...`);

const appChain = AppChain.from({
Runtime: Runtime.from(VanillaRuntimeModules.with({})),
Protocol: Protocol.from(VanillaProtocolModules.with({})),
Sequencer: Sequencer.from(
InMemorySequencerModules.with({
GraphqlServer: GraphqlServer,
Graphql: GraphqlSequencerModule.from(VanillaGraphqlModules.with({})),
})
),
TransactionSender: InMemoryTransactionSender,
QueryTransportModule: StateServiceQueryModule,
NetworkStateTransportModule: BlockStorageNetworkStateModule,
});

appChain.configurePartial({
Runtime: VanillaRuntimeModules.defaultConfig(),
Protocol: VanillaProtocolModules.defaultConfig(),
Sequencer: {
Database: {},
TaskQueue: {},
LocalTaskWorkerModule: VanillaTaskWorkerModules.defaultConfig(),
Mempool: {},
BlockProducerModule: {},
SequencerStartupModule: {},
BlockTrigger: { blockInterval: 5000, produceEmptyBlocks: true },
FeeStrategy: {},
BaseLayer: {},
BatchProducerModule: {},
Graphql: VanillaGraphqlModules.defaultConfig(),
GraphqlServer: { port, host: "localhost", graphiql: true },
},
});

await appChain.start();
console.log("AppChain started successfully!");

const gqlUrl = `http://localhost:${port}/graphql`;
await generateGqlDocs(gqlUrl);
await appChain.close();
} else {
console.log(`Using existing GraphQL endpoint: ${args.url}`);
await generateGqlDocs(args.url);
}
empty: boolean;
}

export const generateGqlDocsCommand: CommandModule<{}, GenerateGqlDocsArgs> = {
command: "generate-gql-docs",
describe: "Generate GraphQL docs",
builder: (yarg) =>
yarg
.option("port", {
alias: "p",
type: "number",
default: 8080,
describe: "Port for the GraphQL server if creating an AppChain",
})
.option("url", {
alias: "u",
type: "string",
default: "http://localhost:8080/graphql",
describe: "GraphQL endpoint to use if not starting AppChain",
})
.option("empty", {
alias: "e",
type: "boolean",
default: false,
describe: "Start a new AppChain instead of using existing URL",
}),
handler: async (args) => {
try {
const { default: generateGqlDocs } = await import(
"../scripts/graphqlDocs/generateGqlDocs"
);
await generateGqlDocs(args);
process.exit(0);
} catch (error) {
console.error("Failed to start AppChain or generate docs:", error);
process.exit(1);
}
},
};
36 changes: 36 additions & 0 deletions packages/cli/src/commands/run/deploy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { CommandModule } from "yargs";

interface DeployArgs {
"env-path"?: string;
env?: string[];
}

export const deployCommand: CommandModule<{}, DeployArgs> = {
command: "deploy",
describe:
"Deploy settlement contracts\n\nRequires: PROTOKIT_SETTLEMENT_CONTRACT_PRIVATE_KEY, PROTOKIT_DISPATCHER_CONTRACT_PRIVATE_KEY, PROTOKIT_MINA_BRIDGE_CONTRACT_PRIVATE_KEY",
builder: (yarg) =>
yarg
.option("env-path", { type: "string", describe: "path to .env file" })
.option("env", {
type: "string",
array: true,
describe: "environment variables as KEY=value",
}),
handler: async (args) => {
try {
const { default: deploy } = await import(
"../../scripts/settlement/deploy"
);
const { parseEnvArgs } = await import("../../utils/loadEnv");
await deploy({
envPath: args["env-path"],
envVars: parseEnvArgs(args.env ?? []),
});
process.exit(0);
} catch (error) {
console.error("Failed to deploy settlement:", error);
process.exit(1);
}
},
};
50 changes: 50 additions & 0 deletions packages/cli/src/commands/run/deposit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { CommandModule } from "yargs";

interface DepositArgs {
tokenId: string;
fromKey: string;
toKey: string;
amount: number;
"env-path"?: string;
env?: string[];
}

export const depositCommand: CommandModule<{}, DepositArgs> = {
command: "deposit <tokenId> <fromKey> <toKey> <amount>",
describe:
"Deposit tokens to the bridge\n\nRequires: PROTOKIT_CUSTOM_TOKEN_PRIVATE_KEY (for custom tokens), PROTOKIT_CUSTOM_TOKEN_BRIDGE_PRIVATE_KEY, PROTOKIT_MINA_BRIDGE_CONTRACT_PRIVATE_KEY",
builder: (yarg) =>
yarg
.positional("tokenId", { type: "string", demandOption: true })
.positional("fromKey", { type: "string", demandOption: true })
.positional("toKey", { type: "string", demandOption: true })
.positional("amount", { type: "number", demandOption: true })
.option("env-path", { type: "string", describe: "path to .env file" })
.option("env", {
type: "string",
array: true,
describe: "environment variables as KEY=value",
}),
handler: async (args) => {
try {
const { default: deposit } = await import("../../scripts/bridge/deposit");
const { parseEnvArgs } = await import("../../utils/loadEnv");
await deposit(
{
envPath: args["env-path"],
envVars: parseEnvArgs(args.env ?? []),
},
{
tokenId: args.tokenId,
fromKey: args.fromKey,
toKey: args.toKey,
amount: args.amount,
}
);
process.exit(0);
} catch (error) {
console.error("Failed to deposit to bridge:", error);
process.exit(1);
}
},
};
38 changes: 38 additions & 0 deletions packages/cli/src/commands/run/faucet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { CommandModule } from "yargs";

interface FaucetArgs {
publicKey: string;
"env-path"?: string;
env?: string[];
}

export const faucetCommand: CommandModule<{}, FaucetArgs> = {
command: "faucet <publicKey>",
describe: "Send MINA to an account from the lightnet faucet",
builder: (yarg) =>
yarg
.positional("publicKey", {
type: "string",
describe: "public key to send MINA to",
demandOption: true,
})
.option("env-path", {
type: "string",
describe: "path to .env file",
})
.option("env", {
type: "string",
array: true,
describe: "environment variables as KEY=value",
}),
handler: async (args) => {
try {
const { default: faucet } = await import("../../scripts/lightnet/faucet");
await faucet(args.publicKey);
process.exit(0);
} catch (error) {
console.error("Failed to send funds from faucet:", error);
process.exit(1);
}
},
};
26 changes: 26 additions & 0 deletions packages/cli/src/commands/run/generateKeys.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { CommandModule } from "yargs";

import type { GenerateKeysArgs } from "../../scripts/generateKeys";

export const generateKeysCommand: CommandModule<{}, GenerateKeysArgs> = {
command: "generate-keys [count]",
describe: "Generate private/public key pairs for development",
builder: (yarg) =>
yarg.positional("count", {
type: "number",
default: 1,
describe: "number of keys to generate",
}),
handler: async (args) => {
try {
const { default: generateKeys } = await import(
"../../scripts/generateKeys"
);
await generateKeys({ count: args.count });
process.exit(0);
} catch (error) {
console.error("Failed to generate keys:", error);
process.exit(1);
}
},
};
Loading