Skip to content

Commit 51e3289

Browse files
authored
Merge pull request #409 from proto-kit/feat/cli-extended-functionality
Feat/cli extended functionality
2 parents b482e94 + 7de4892 commit 51e3289

49 files changed

Lines changed: 3712 additions & 149 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

package-lock.json

Lines changed: 168 additions & 33 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/cli/README.md

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
# Proto-Kit CLI
2+
3+
A comprehensive command-line interface for managing Proto-Kit applications, environments, and blockchain interactions.
4+
5+
## Installation
6+
7+
```bash
8+
npm install @proto-kit/cli
9+
```
10+
11+
Or use with npx:
12+
13+
```bash
14+
npx @proto-kit/cli <command>
15+
```
16+
17+
## Commands Overview
18+
19+
### Environment Management
20+
21+
Creates a new environment configuration with an interactive guided wizard.
22+
23+
```bash
24+
npm protokit wizard
25+
```
26+
27+
This command walks you through setting up:
28+
- Network configuration
29+
- Key management
30+
- Environment variables
31+
- Deployment settings
32+
33+
### Bridge Operations
34+
35+
#### `bridge deposit <tokenId> <fromKey> <toKey> <amount>`
36+
Deposits tokens to the bridge contract.
37+
38+
**Parameters:**
39+
- `tokenId` - Token identifier
40+
- `fromKey` - Sender's private key (or environment variable name)
41+
- `toKey` - Recipient's public key (or environment variable name)
42+
- `amount` - Amount to deposit
43+
44+
**Example:**
45+
```bash
46+
npm protokit bridge deposit 1 SENDER_KEY RECIPIENT_KEY 100
47+
```
48+
49+
#### `bridge redeem <tokenId> <toKey> <amount>`
50+
Redeems tokens from the bridge contract.
51+
52+
**Parameters:**
53+
- `tokenId` - Token identifier
54+
- `toKey` - Recipient's public key (or environment variable name)
55+
- `amount` - Amount to redeem
56+
57+
**Example:**
58+
```bash
59+
npm protokit bridge redeem 1 RECIPIENT_KEY 100
60+
```
61+
62+
#### `bridge withdraw <tokenId> <senderKey> <amount>`
63+
Withdraws tokens from the bridge.
64+
65+
**Parameters:**
66+
- `tokenId` - Token identifier
67+
- `senderKey` - Sender's private key (or environment variable name)
68+
- `amount` - Amount to withdraw
69+
70+
**Example:**
71+
```bash
72+
npm protokit bridge withdraw 1 SENDER_KEY 100
73+
```
74+
75+
### Settlement Deployment
76+
77+
#### `settlement deploy`
78+
Deploys settlement contracts to the network.
79+
80+
```bash
81+
npm protokit settlement deploy
82+
```
83+
84+
#### `settlement token-deploy <tokenSymbol> <feepayerKey> <receiverPublicKey> [mintAmount]`
85+
Deploys custom fungible tokens for settlement operations.
86+
87+
**Parameters:**
88+
- `tokenSymbol` - Symbol for the token
89+
- `feepayerKey` - Private key for paying deployment fees
90+
- `receiverPublicKey` - Public key to receive initially minted tokens
91+
- `[mintAmount]` - Initial amount to mint (default: 0)
92+
93+
**Example:**
94+
```bash
95+
npm protokit settlement token-deploy USDC FEEPAYER_KEY RECEIVER_KEY 1000
96+
```
97+
98+
### Lightnet Utilities
99+
100+
#### `lightnet:wait-for-network`
101+
Waits for the lightnet network to be ready before proceeding with other operations.
102+
103+
```bash
104+
npm protokit lightnet wait
105+
```
106+
107+
#### `lightnet:faucet <publicKey>`
108+
Sends MINA from the lightnet faucet to the specified account.
109+
110+
**Parameters:**
111+
- `publicKey` - Destination public key (or environment variable name)
112+
113+
**Example:**
114+
```bash
115+
npm protokit lightnet:faucet B62qnzbXQcUoQFnjvF4Kog6KfNsuuSoo7LSLvomPeak2CLvEYiUqT
116+
```
117+
118+
#### `lightnet:initialize`
119+
Complete lightnet setup that performs:
120+
1. Waits for network readiness
121+
2. Funds test accounts from faucet
122+
3. Deploys settlement contracts
123+
124+
```bash
125+
npm protokit lightnet initialize
126+
```
127+
128+
### Developer Tools
129+
130+
#### `generate-keys [count]`
131+
Generates private/public key pairs for development and testing.
132+
133+
**Parameters:**
134+
- `[count]` - Number of key pairs to generate (default: 1)
135+
136+
**Example:**
137+
```bash
138+
# Generate 1 key pair
139+
npm protokit generate-keys
140+
141+
# Generate 5 key pairs
142+
npm protokit generate-keys 5
143+
```
144+
145+
**Output format:**
146+
```
147+
Key Pair 1:
148+
Private Key: EKE8...
149+
Public Key: B62q...
150+
151+
Key Pair 2:
152+
Private Key: EKF9...
153+
Public Key: B62r...
154+
```
155+
156+
#### `explorer:start`
157+
Starts the Proto-Kit explorer web interface.
158+
159+
**Options:**
160+
- `-p, --port` - Port to run on (default: 5003)
161+
- `--indexer-url` - GraphQL endpoint URL for the indexer
162+
163+
**Examples:**
164+
```bash
165+
# Start on default port 5003
166+
npm protokit explorer start
167+
168+
# Start on custom port with indexer URL
169+
npm protokit explorer start -p 3000 --indexer-url http://localhost:8081/graphql
170+
```
171+
172+
## Environment Variable Configuration
173+
174+
The CLI supports three methods for passing environment variables and configuration:
175+
176+
### Option 1: `--env-path` (File-based)
177+
Load environment variables from a `.env` file:
178+
179+
```bash
180+
npm protokit settlement deploy --env-path ./my-config/.env
181+
```
182+
183+
### Option 2: `--set KEY=value` (Inline)
184+
Pass environment variables directly as command-line arguments. Can be used multiple times:
185+
186+
```bash
187+
npm protokit settlement deploy \
188+
--set PROTOKIT_SETTLEMENT_CONTRACT_PRIVATE_KEY=EK... \
189+
MINA_NETWORK_URL=https://lightnet.lokinet.dev/graphql
190+
```
191+
192+
### Option 3: `--env {envName}` (Named Environment)
193+
Use a pre-configured environment by name:
194+
195+
```bash
196+
npm protokit settlement deploy --env sovereign
197+
```

packages/cli/bin/protokit-cli.js

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,58 @@
22
import { spawn } from "child_process";
33
import path from "path";
44
import { fileURLToPath } from "url";
5+
import { createRequire } from "module";
6+
import fs from "fs";
57
import process from "process";
68

9+
const require = createRequire(import.meta.url);
710
const __filename = fileURLToPath(import.meta.url);
811
const __dirname = path.dirname(__filename);
912

13+
function resolveTsNodeEsm() {
14+
const searchPaths = [process.cwd(), __dirname];
15+
16+
for (const base of searchPaths) {
17+
try {
18+
const pkgPath = require.resolve("ts-node/package.json", {
19+
paths: [base],
20+
});
21+
const tsNodeDir = path.dirname(pkgPath);
22+
const esmPath = path.join(tsNodeDir, "esm.mjs");
23+
if (fs.existsSync(esmPath)) return esmPath;
24+
} catch (_) {
25+
// continue
26+
}
27+
}
28+
return "ts-node/esm";
29+
}
30+
1031
const args = process.argv.slice(2);
1132

1233
if (!process.env.TS_NODE_LOADER_ACTIVE) {
1334
const env = { ...process.env };
1435
env.TS_NODE_LOADER_ACTIVE = "1";
36+
37+
// Configure ts-node for proper ESM/CJS interop
38+
env.TS_NODE_ESMODULEINTEROP = "true";
39+
env.TS_NODE_ALLOWJS = "true";
40+
env.TS_NODE_EXPERIMENTALMODULES = "true";
41+
env.TS_NODE_COMPILER_OPTIONS = JSON.stringify({
42+
module: "ESNext",
43+
moduleResolution: "node",
44+
allowSyntheticDefaultImports: true,
45+
esModuleInterop: true,
46+
allowJs: true,
47+
target: "ES2020",
48+
experimentalDecorators: true,
49+
emitDecoratorMetadata: true,
50+
strictNullChecks: true,
51+
});
52+
53+
const tsNodeEsm = resolveTsNodeEsm();
1554
env.NODE_OPTIONS = [
1655
env.NODE_OPTIONS || "",
17-
"--loader ts-node/esm",
56+
`--loader ${tsNodeEsm}`,
1857
"--experimental-vm-modules",
1958
"--experimental-wasm-modules",
2059
"--es-module-specifier-resolution=node",

packages/cli/package.json

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"type": "module",
55
"main": "./bin/protokit-cli.js",
66
"bin": {
7-
"proto-kit": "./bin/protokit-cli.js"
7+
"protokit": "./bin/protokit-cli.js"
88
},
99
"publishConfig": {
1010
"access": "public"
@@ -21,21 +21,31 @@
2121
"author": "",
2222
"license": "ISC",
2323
"dependencies": {
24-
"yargs": "17.7.2",
24+
"@inquirer/figures": "^2.0.3",
25+
"dotenv": "^17.2.3",
26+
"inquirer": "^9.3.0",
27+
"kleur": "^4.1.5",
28+
"mina-fungible-token": "^1.1.0",
29+
"reflect-metadata": "^0.1.13",
30+
"spectaql": "3.0.5",
2531
"ts-node": "^10.9.1",
26-
"spectaql": "3.0.5"
32+
"yargs": "17.7.2"
2733
},
2834
"peerDependencies": {
2935
"@proto-kit/api": "*",
3036
"@proto-kit/common": "*",
37+
"@proto-kit/explorer": "*",
3138
"@proto-kit/library": "*",
3239
"@proto-kit/module": "*",
3340
"@proto-kit/protocol": "*",
3441
"@proto-kit/sdk": "*",
3542
"@proto-kit/sequencer": "*",
36-
"o1js": "^2.10.0"
43+
"@proto-kit/stack": "*",
44+
"o1js": "^2.10.0",
45+
"tsyringe": "^4.10.0"
3746
},
3847
"devDependencies": {
48+
"@types/inquirer": "^9.0.9",
3949
"@types/node": "^20.19.24",
4050
"@types/yargs": "17.0.32"
4151
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { CommandModule } from "yargs";
2+
3+
export const bridgeCommand: CommandModule = {
4+
command: "bridge <subcommand>",
5+
describe: "Bridge operations",
6+
builder: async (yargs) => {
7+
const { depositCommand } = await import("./deposit");
8+
const { redeemCommand } = await import("./redeem");
9+
const { withdrawCommand } = await import("./withdraw");
10+
11+
return yargs
12+
.command(depositCommand)
13+
.command(redeemCommand)
14+
.command(withdrawCommand)
15+
.demandCommand(
16+
1,
17+
"You must specify a subcommand. Use --help to see available options."
18+
);
19+
},
20+
handler: () => {
21+
console.log("Use a subcommand. See --help for available options.");
22+
},
23+
};
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { CommandModule } from "yargs";
2+
3+
import { addEnvironmentOptions } from "../../utils/environmentOptions";
4+
5+
interface DepositArgs {
6+
tokenId: string;
7+
fromKey: string;
8+
toKey: string;
9+
amount: number;
10+
"env-path"?: string;
11+
env?: string;
12+
set?: string[];
13+
}
14+
15+
export const depositCommand: CommandModule<{}, DepositArgs> = {
16+
command: "deposit <tokenId> <fromKey> <toKey> <amount>",
17+
describe:
18+
"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",
19+
builder: (yarg) =>
20+
addEnvironmentOptions(
21+
yarg
22+
.positional("tokenId", { type: "string", demandOption: true })
23+
.positional("fromKey", { type: "string", demandOption: true })
24+
.positional("toKey", { type: "string", demandOption: true })
25+
.positional("amount", { type: "number", demandOption: true })
26+
),
27+
handler: async (args) => {
28+
try {
29+
const { default: deposit } = await import("../../scripts/bridge/deposit");
30+
const { parseEnvArgs } = await import("../../utils/loadEnv");
31+
await deposit(
32+
{
33+
envPath: args["env-path"],
34+
env: args.env!,
35+
envVars: parseEnvArgs(args.set ?? []),
36+
},
37+
{
38+
tokenId: args.tokenId,
39+
fromKey: args.fromKey,
40+
toKey: args.toKey,
41+
amount: args.amount,
42+
}
43+
);
44+
process.exit(0);
45+
} catch (error) {
46+
console.error("Failed to deposit to bridge:", error);
47+
process.exit(1);
48+
}
49+
},
50+
};

0 commit comments

Comments
 (0)