@net-protocol/cli 0.1.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.
- package/README.md +339 -0
- package/dist/cli/index.mjs +1291 -0
- package/dist/cli/index.mjs.map +1 -0
- package/package.json +65 -0
package/README.md
ADDED
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
# @net-protocol/cli
|
|
2
|
+
|
|
3
|
+
A command-line tool for interacting with Net Protocol. Supports storage uploads and more.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Global install
|
|
9
|
+
npm install -g @net-protocol/cli
|
|
10
|
+
|
|
11
|
+
# Or with yarn
|
|
12
|
+
yarn global add @net-protocol/cli
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
The CLI uses a subcommand pattern. Each command is isolated and has its own options:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
netp <command> [options]
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Available Commands
|
|
24
|
+
|
|
25
|
+
#### Storage Command
|
|
26
|
+
|
|
27
|
+
Storage operations for Net Protocol. The `storage` command is a command group with subcommands for different operations.
|
|
28
|
+
|
|
29
|
+
**Available Subcommands:**
|
|
30
|
+
|
|
31
|
+
- `storage upload` - Upload files to Net Storage
|
|
32
|
+
- `storage preview` - Preview storage upload without submitting transactions
|
|
33
|
+
|
|
34
|
+
##### Storage Upload
|
|
35
|
+
|
|
36
|
+
Upload files to Net Storage using either normal storage (for files ≤ 20KB) or XML storage (for files > 20KB or containing XML references).
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
netp storage upload \
|
|
40
|
+
--file <path> \
|
|
41
|
+
--key <storage-key> \
|
|
42
|
+
--text <description> \
|
|
43
|
+
[--private-key <0x...>] \
|
|
44
|
+
--chain-id <8453|1|...> \
|
|
45
|
+
[--rpc-url <custom-rpc>]
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**Storage Upload Arguments:**
|
|
49
|
+
|
|
50
|
+
- `--file` (required): Path to file to upload
|
|
51
|
+
- `--key` (required): Storage key (filename/identifier)
|
|
52
|
+
- `--text` (required): Text description/filename
|
|
53
|
+
- `--private-key` (optional): Private key (0x-prefixed hex, 66 characters). Can also be set via `NET_PRIVATE_KEY` or `PRIVATE_KEY` environment variable
|
|
54
|
+
- `--chain-id` (optional): Chain ID (8453 for Base, 1 for Ethereum, etc.). Can also be set via `NET_CHAIN_ID` environment variable
|
|
55
|
+
- `--rpc-url` (optional): Custom RPC URL. Can also be set via `NET_RPC_URL` environment variable
|
|
56
|
+
|
|
57
|
+
**Examples:**
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
# Using command-line flags
|
|
61
|
+
netp storage upload \
|
|
62
|
+
--file ./example.txt \
|
|
63
|
+
--key "my-file" \
|
|
64
|
+
--text "Example file" \
|
|
65
|
+
--private-key 0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef \
|
|
66
|
+
--chain-id 8453
|
|
67
|
+
|
|
68
|
+
# Using environment variables (recommended)
|
|
69
|
+
export NET_PRIVATE_KEY=0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef
|
|
70
|
+
export NET_CHAIN_ID=8453
|
|
71
|
+
netp storage upload \
|
|
72
|
+
--file ./example.txt \
|
|
73
|
+
--key "my-file" \
|
|
74
|
+
--text "Example file"
|
|
75
|
+
|
|
76
|
+
# Using .env file
|
|
77
|
+
# Create .env file with:
|
|
78
|
+
# NET_PRIVATE_KEY=0x...
|
|
79
|
+
# NET_CHAIN_ID=8453
|
|
80
|
+
# NET_RPC_URL=https://base-mainnet.public.blastapi.io # optional
|
|
81
|
+
netp storage upload --file ./example.txt --key "my-file" --text "Example file"
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
##### Storage Preview
|
|
85
|
+
|
|
86
|
+
Preview what would be uploaded without actually submitting transactions. Shows statistics about chunks, transactions, and what's already stored.
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
netp storage preview \
|
|
90
|
+
--file <path> \
|
|
91
|
+
--key <storage-key> \
|
|
92
|
+
--text <description> \
|
|
93
|
+
[--private-key <0x...>] \
|
|
94
|
+
--chain-id <8453|1|...> \
|
|
95
|
+
[--rpc-url <custom-rpc>]
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**Storage Preview Arguments:**
|
|
99
|
+
|
|
100
|
+
Same as `storage upload` - see above.
|
|
101
|
+
|
|
102
|
+
**Example:**
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
netp storage preview \
|
|
106
|
+
--file ./example.txt \
|
|
107
|
+
--key "my-file" \
|
|
108
|
+
--text "Example file" \
|
|
109
|
+
--chain-id 8453
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**Output:**
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
📁 Reading file: ./example.txt
|
|
116
|
+
|
|
117
|
+
📊 Storage Preview:
|
|
118
|
+
Storage Key: my-file
|
|
119
|
+
Storage Type: Normal
|
|
120
|
+
Total Chunks: 1
|
|
121
|
+
Already Stored: 0
|
|
122
|
+
Need to Store: 1
|
|
123
|
+
Total Transactions: 1
|
|
124
|
+
Transactions to Send: 1
|
|
125
|
+
Transactions Skipped: 0
|
|
126
|
+
Operator Address: 0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf
|
|
127
|
+
|
|
128
|
+
⚠ 1 transaction(s) would be sent
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Storage Types
|
|
132
|
+
|
|
133
|
+
### Normal Storage
|
|
134
|
+
|
|
135
|
+
For files up to 20KB, the tool uses normal storage:
|
|
136
|
+
|
|
137
|
+
- Stores data directly in `Storage.sol`
|
|
138
|
+
- Single transaction
|
|
139
|
+
- Simple key-value storage
|
|
140
|
+
|
|
141
|
+
### XML Storage
|
|
142
|
+
|
|
143
|
+
For files larger than 20KB or containing XML references, the tool uses XML storage:
|
|
144
|
+
|
|
145
|
+
- Breaks file into 80KB XML chunks
|
|
146
|
+
- Each XML chunk is stored in ChunkedStorage (compressed and chunked into 20KB pieces)
|
|
147
|
+
- XML metadata references all chunks
|
|
148
|
+
- Multiple sequential transactions (metadata first, then chunks)
|
|
149
|
+
|
|
150
|
+
## Idempotency
|
|
151
|
+
|
|
152
|
+
The storage command includes built-in idempotency checks:
|
|
153
|
+
|
|
154
|
+
1. **Pre-flight Checks**: Before uploading, checks if data already exists
|
|
155
|
+
2. **Content Comparison**: For normal storage, compares file content with stored content
|
|
156
|
+
3. **Chunk-Level Deduplication**: For XML storage, checks each chunk individually
|
|
157
|
+
4. **Per-Transaction Checks**: Before sending each transaction, verifies data doesn't already exist
|
|
158
|
+
|
|
159
|
+
### Retry Behavior
|
|
160
|
+
|
|
161
|
+
If an upload fails mid-way:
|
|
162
|
+
|
|
163
|
+
- Retry the same command
|
|
164
|
+
- The tool will check which chunks already exist
|
|
165
|
+
- Only missing chunks will be uploaded
|
|
166
|
+
- Safe to retry multiple times
|
|
167
|
+
|
|
168
|
+
### Example: Upload Same File Twice
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
# First upload
|
|
172
|
+
netp storage upload --file example.txt --key "test" --text "Test" --chain-id 8453
|
|
173
|
+
# Output: ✓ File uploaded successfully!
|
|
174
|
+
|
|
175
|
+
# Second upload (same file, same key)
|
|
176
|
+
netp storage upload --file example.txt --key "test" --text "Test" --chain-id 8453
|
|
177
|
+
# Output: ✓ All data already stored - skipping upload
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Architecture
|
|
181
|
+
|
|
182
|
+
The CLI is organized into a modular, extensible architecture:
|
|
183
|
+
|
|
184
|
+
```
|
|
185
|
+
src/
|
|
186
|
+
├── cli/
|
|
187
|
+
│ ├── index.ts # Main entry point, sets up commander program
|
|
188
|
+
│ └── shared.ts # Shared option parsing and validation
|
|
189
|
+
├── commands/
|
|
190
|
+
│ └── storage/ # Storage command module
|
|
191
|
+
│ ├── index.ts # Storage command definition
|
|
192
|
+
│ ├── core/ # Upload and preview logic
|
|
193
|
+
│ ├── storage/ # Storage operations
|
|
194
|
+
│ ├── transactions/ # Transaction handling
|
|
195
|
+
│ ├── utils.ts # Storage-specific utilities
|
|
196
|
+
│ └── types.ts # Storage-specific types
|
|
197
|
+
└── shared/ # Shared utilities across commands
|
|
198
|
+
└── types.ts # Common types (CommonOptions, etc.)
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Key Components
|
|
202
|
+
|
|
203
|
+
- **`cli/index.ts`**: Main CLI entry point that sets up the commander program and registers all commands
|
|
204
|
+
- **`cli/shared.ts`**: Shared utilities for parsing common options (private-key, chain-id, rpc-url) that are available to all commands
|
|
205
|
+
- **`commands/{name}/index.ts`**: Each command module exports a `register{Name}Command()` function that defines the command's options and behavior
|
|
206
|
+
- **`shared/types.ts`**: Common types shared across commands (e.g., `CommonOptions`)
|
|
207
|
+
|
|
208
|
+
### Command Structure
|
|
209
|
+
|
|
210
|
+
Each command can have its own internal structure:
|
|
211
|
+
|
|
212
|
+
- **`core/`**: Core business logic for the command
|
|
213
|
+
- **`storage/`**: Storage-specific operations (if applicable)
|
|
214
|
+
- **`transactions/`**: Transaction preparation, filtering, and sending
|
|
215
|
+
- **`utils.ts`**: Command-specific utility functions
|
|
216
|
+
- **`types.ts`**: Command-specific types
|
|
217
|
+
|
|
218
|
+
## Extensibility
|
|
219
|
+
|
|
220
|
+
### Adding a New Command
|
|
221
|
+
|
|
222
|
+
To add a new top-level command:
|
|
223
|
+
|
|
224
|
+
1. **Create command directory**: `src/commands/{name}/`
|
|
225
|
+
2. **Create command index**: `src/commands/{name}/index.ts` with a `register{Name}Command(program: Command)` function
|
|
226
|
+
3. **Register in main CLI**: Import and call `register{Name}Command(program)` in `src/cli/index.ts`
|
|
227
|
+
4. **Add command-specific code**: Create subdirectories as needed (core/, storage/, transactions/, etc.)
|
|
228
|
+
|
|
229
|
+
### Adding a Storage Subcommand
|
|
230
|
+
|
|
231
|
+
To add a new subcommand to the `storage` command group:
|
|
232
|
+
|
|
233
|
+
1. **Create subcommand**: Use `new Command("subcommand-name")` in `src/commands/storage/index.ts`
|
|
234
|
+
2. **Add options**: Use `.requiredOption()` or `.option()` to define subcommand options
|
|
235
|
+
3. **Add action**: Use `.action()` to define the subcommand behavior
|
|
236
|
+
4. **Register**: Use `storageCommand.addCommand(subcommand)` to register it
|
|
237
|
+
|
|
238
|
+
**Example:**
|
|
239
|
+
|
|
240
|
+
```typescript
|
|
241
|
+
// In src/commands/storage/index.ts
|
|
242
|
+
const verifyCommand = new Command("verify")
|
|
243
|
+
.description("Verify storage integrity")
|
|
244
|
+
.requiredOption("--key <key>", "Storage key to verify")
|
|
245
|
+
.action(async (options) => {
|
|
246
|
+
// Implementation
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
storageCommand.addCommand(verifyCommand);
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### Example: Adding a New Command
|
|
253
|
+
|
|
254
|
+
```typescript
|
|
255
|
+
// src/commands/mycommand/index.ts
|
|
256
|
+
import { Command } from "commander";
|
|
257
|
+
import { parseCommonOptions } from "../../cli/shared";
|
|
258
|
+
|
|
259
|
+
export function registerMyCommand(program: Command): void {
|
|
260
|
+
program
|
|
261
|
+
.command("mycommand")
|
|
262
|
+
.description("Description of my command")
|
|
263
|
+
.option("--my-option <value>", "My option")
|
|
264
|
+
.action(async (options) => {
|
|
265
|
+
const commonOptions = parseCommonOptions({
|
|
266
|
+
privateKey: options.privateKey,
|
|
267
|
+
chainId: options.chainId,
|
|
268
|
+
rpcUrl: options.rpcUrl,
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
// Command logic here
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// src/cli/index.ts
|
|
276
|
+
import { registerMyCommand } from "../commands/mycommand";
|
|
277
|
+
|
|
278
|
+
// ... existing code ...
|
|
279
|
+
registerMyCommand(program);
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### Shared Options
|
|
283
|
+
|
|
284
|
+
All commands automatically have access to common options:
|
|
285
|
+
|
|
286
|
+
- `--private-key` (or `NET_PRIVATE_KEY` env var)
|
|
287
|
+
- `--chain-id` (or `NET_CHAIN_ID` env var)
|
|
288
|
+
- `--rpc-url` (or `NET_RPC_URL` env var)
|
|
289
|
+
|
|
290
|
+
These are parsed and validated by `parseCommonOptions()` from `cli/shared.ts`.
|
|
291
|
+
|
|
292
|
+
## Security & Environment Variables
|
|
293
|
+
|
|
294
|
+
⚠️ **Warning**: Private keys are sensitive. Always use environment variables instead of passing the private key via command line:
|
|
295
|
+
|
|
296
|
+
```bash
|
|
297
|
+
# Set environment variable
|
|
298
|
+
export NET_PRIVATE_KEY=0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef
|
|
299
|
+
|
|
300
|
+
# Run without --private-key flag (it will use the env var)
|
|
301
|
+
netp storage upload \
|
|
302
|
+
--file ./example.txt \
|
|
303
|
+
--key "my-file" \
|
|
304
|
+
--text "Example file" \
|
|
305
|
+
--chain-id 8453
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
The tool supports both `NET_PRIVATE_KEY` and `PRIVATE_KEY` environment variables. If neither is set, you must provide `--private-key` flag.
|
|
309
|
+
|
|
310
|
+
## Development
|
|
311
|
+
|
|
312
|
+
```bash
|
|
313
|
+
# Install dependencies (from repo root)
|
|
314
|
+
yarn install
|
|
315
|
+
|
|
316
|
+
# Build
|
|
317
|
+
yarn workspace @net-protocol/cli build
|
|
318
|
+
|
|
319
|
+
# Run in dev mode
|
|
320
|
+
yarn workspace @net-protocol/cli start storage upload --file example.txt --key "test" --text "Test" --chain-id 8453
|
|
321
|
+
|
|
322
|
+
# Watch mode
|
|
323
|
+
yarn workspace @net-protocol/cli dev
|
|
324
|
+
|
|
325
|
+
# Run tests
|
|
326
|
+
yarn workspace @net-protocol/cli test
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
## Error Handling
|
|
330
|
+
|
|
331
|
+
The CLI handles various error scenarios:
|
|
332
|
+
|
|
333
|
+
- Invalid private key format
|
|
334
|
+
- File not found
|
|
335
|
+
- Transaction failures (continues with remaining transactions)
|
|
336
|
+
- Network errors
|
|
337
|
+
- Storage read errors
|
|
338
|
+
|
|
339
|
+
If a transaction fails mid-upload, you can safely retry the command - it will only upload missing chunks.
|