|
| 1 | +# Plan: Extend gnd with graph-cli functionality |
| 2 | + |
| 3 | +## Overview |
| 4 | + |
| 5 | +Extend the existing `gnd` (Graph Node Dev) CLI to be a **drop-in replacement** for the TypeScript-based `graph-cli`. The goal is identical CLI behavior, flags, output format, and byte-for-byte identical AssemblyScript code generation. |
| 6 | + |
| 7 | +**Spec document**: `docs/specs/gnd-cli-expansion.md` |
| 8 | + |
| 9 | +**Scope**: |
| 10 | + |
| 11 | +- Ethereum protocol only (other protocols are future work) |
| 12 | +- All graph-cli commands except `local` and `node` subcommand |
| 13 | +- Match latest graph-cli version (0.98.x) |
| 14 | + |
| 15 | +**Current state of gnd** (`~/code/graph-node/gnd/`): |
| 16 | + |
| 17 | +- ~700 lines of Rust across 3 files |
| 18 | +- Single command with flags (no subcommands) |
| 19 | +- Already uses clap, imports graph crates |
| 20 | +- Runs graph-node in dev mode with file watching |
| 21 | + |
| 22 | +## Status Summary (Updated 2026-01-19) |
| 23 | + |
| 24 | +**Overall Progress**: ~95% complete (implementation done, testing/docs remaining) |
| 25 | + |
| 26 | +| Phase | Status | Notes | |
| 27 | +|-------|--------|-------| |
| 28 | +| Phase 1: CLI Restructure | ✅ Complete | | |
| 29 | +| Phase 2: Infrastructure | ✅ Complete | | |
| 30 | +| Phase 3: Simple Commands | ✅ Complete | | |
| 31 | +| Phase 4: Code Generation | ✅ Complete | 11 verification fixtures passing | |
| 32 | +| Phase 5: Migrations | ✅ Complete | | |
| 33 | +| Phase 6: Build Command | 🟡 Needs Testing | Manual end-to-end verification | |
| 34 | +| Phase 7: Deploy Command | 🟡 Needs Testing | Manual Graph Node test | |
| 35 | +| Phase 8: Init Command | 🟡 Needs Testing | Implemented, manual verification pending | |
| 36 | +| Phase 9: Add Command | ✅ Complete | | |
| 37 | +| Phase 10: Publish Command | 🟡 Needs Testing | Manual end-to-end verification | |
| 38 | +| Phase 11: Test Command | 🟡 Needs Testing | Manual Matchstick test | |
| 39 | +| Phase 12: Testing & Polish | 🟡 In Progress | Port TS CLI tests, write docs | |
| 40 | + |
| 41 | +**Total LOC**: ~15,000 lines of Rust (158 unit tests, 12 verification tests passing) |
| 42 | + |
| 43 | +## Git Workflow |
| 44 | + |
| 45 | +**Branch**: All work should be committed to the `gnd-cli` branch. |
| 46 | + |
| 47 | +**Commit discipline**: |
| 48 | + |
| 49 | +- Commit work in small, reviewable chunks |
| 50 | +- Each commit should be self-contained and pass all checks |
| 51 | +- Prefer many small commits over few large ones |
| 52 | +- Each commit message should clearly describe what it does |
| 53 | + |
| 54 | +**Before each commit**: |
| 55 | + |
| 56 | +```bash |
| 57 | +just format |
| 58 | +just lint |
| 59 | +just test-unit # only run the tests in gnd/ |
| 60 | +``` |
| 61 | + |
| 62 | +- MANDATORY: Work must be committed, a task is only done when work is committed |
| 63 | +- MANDATORY: Make sure to follow the commit discipline above |
| 64 | + |
| 65 | +## Commands |
| 66 | + |
| 67 | +| Command | Description | Complexity | |
| 68 | +| ------------- | ----------------------------------- | ----------------------- | |
| 69 | +| `gnd dev` | Existing gnd functionality | Done (restructure only) | |
| 70 | +| `gnd codegen` | Generate AssemblyScript types | High | |
| 71 | +| `gnd build` | Compile to WASM | Medium | |
| 72 | +| `gnd deploy` | Deploy to Graph Node | Medium | |
| 73 | +| `gnd init` | Scaffold new subgraph | High | |
| 74 | +| `gnd add` | Add datasource to existing subgraph | Medium | |
| 75 | +| `gnd create` | Register subgraph name | Low | |
| 76 | +| `gnd remove` | Unregister subgraph name | Low | |
| 77 | +| `gnd auth` | Set deploy key | Low | |
| 78 | +| `gnd publish` | Publish to decentralized network | Medium | |
| 79 | +| `gnd test` | Run Matchstick tests | Low (shell out) | |
| 80 | +| `gnd clean` | Remove build artifacts | Low | |
| 81 | + |
| 82 | +**Not implemented** (documented differences): |
| 83 | + |
| 84 | +- `gnd local` - Use existing test infrastructure |
| 85 | +- `gnd node` - Use graphman for node management |
| 86 | +- `--uncrashable` flag - Float Capital third-party feature |
| 87 | + |
| 88 | +## Reusable from graph-node |
| 89 | + |
| 90 | +| Feature | Location | Status | |
| 91 | +| ------------------- | ------------------------------------- | ---------------------------- | |
| 92 | +| Manifest parsing | `graph/src/data/subgraph/mod.rs` | Ready | |
| 93 | +| Manifest validation | `graph/src/data/subgraph/mod.rs` | Ready (may need refactoring) | |
| 94 | +| GraphQL schema | `graph/src/schema/input/` | Ready | |
| 95 | +| ABI parsing | `ethabi` + chain/ethereum wrappers | Ready | |
| 96 | +| IPFS client | `graph/src/ipfs/` | Ready | |
| 97 | +| Link resolution | `graph/src/components/link_resolver/` | Ready | |
| 98 | +| File watching | `gnd/src/watcher.rs` | Ready | |
| 99 | +| CLI framework | `clap` (already in gnd) | Ready | |
| 100 | + |
| 101 | +## Module Structure |
| 102 | + |
| 103 | +``` |
| 104 | +gnd/src/ |
| 105 | +├── main.rs # Entry point, clap setup |
| 106 | +├── lib.rs |
| 107 | +├── commands/ |
| 108 | +│ ├── mod.rs |
| 109 | +│ ├── dev.rs # Existing gnd functionality |
| 110 | +│ ├── codegen.rs |
| 111 | +│ ├── build.rs |
| 112 | +│ ├── deploy.rs |
| 113 | +│ ├── init.rs |
| 114 | +│ ├── add.rs |
| 115 | +│ ├── create.rs |
| 116 | +│ ├── remove.rs |
| 117 | +│ ├── auth.rs |
| 118 | +│ ├── publish.rs |
| 119 | +│ ├── test.rs |
| 120 | +│ └── clean.rs |
| 121 | +├── codegen/ |
| 122 | +│ ├── mod.rs |
| 123 | +│ ├── schema.rs # Entity class generation |
| 124 | +│ ├── abi.rs # ABI binding generation |
| 125 | +│ └── template.rs # Template binding generation |
| 126 | +├── scaffold/ |
| 127 | +│ ├── mod.rs |
| 128 | +│ ├── manifest.rs # Generate subgraph.yaml |
| 129 | +│ ├── schema.rs # Generate schema.graphql |
| 130 | +│ └── mapping.rs # Generate mapping.ts |
| 131 | +├── migrations/ |
| 132 | +│ ├── mod.rs |
| 133 | +│ └── ... # One module per migration version |
| 134 | +├── compiler/ |
| 135 | +│ ├── mod.rs |
| 136 | +│ └── asc.rs # Shell out to asc |
| 137 | +├── services/ |
| 138 | +│ ├── mod.rs |
| 139 | +│ ├── etherscan.rs # Etherscan API client |
| 140 | +│ ├── sourcify.rs # Sourcify API client |
| 141 | +│ ├── registry.rs # Network registry client |
| 142 | +│ └── graph_node.rs # Graph Node JSON-RPC client |
| 143 | +├── config/ |
| 144 | +│ ├── mod.rs |
| 145 | +│ ├── auth.rs # ~/.graphprotocol/ management |
| 146 | +│ └── networks.rs # networks.json handling |
| 147 | +├── output/ |
| 148 | +│ ├── mod.rs |
| 149 | +│ └── spinner.rs # Progress/spinner output (match TS CLI exactly) |
| 150 | +└── watcher.rs # Existing file watcher |
| 151 | +``` |
| 152 | + |
| 153 | +## Dependencies to Add |
| 154 | + |
| 155 | +| Crate | Purpose | |
| 156 | +| ----------- | ------------------------------------------- | |
| 157 | +| `inquire` | Interactive prompts (init) | |
| 158 | +| `minijinja` | Template rendering (scaffold) | |
| 159 | +| `indicatif` | Progress bars and spinners | |
| 160 | +| `reqwest` | HTTP client (Etherscan, Sourcify, registry) | |
| 161 | + |
| 162 | +## TODO List |
| 163 | + |
| 164 | +### Phase 1: CLI Restructure |
| 165 | + |
| 166 | +- [x] Create `gnd-cli` branch |
| 167 | +- [x] Restructure main.rs with clap subcommands |
| 168 | +- [x] Move existing gnd logic to `commands/dev.rs` |
| 169 | +- [x] Add empty command stubs for all commands |
| 170 | +- [x] Verify `gnd dev` works exactly as before |
| 171 | +- [x] Add `--version` output showing both gnd and graph-cli versions |
| 172 | + |
| 173 | +### Phase 2: Infrastructure |
| 174 | + |
| 175 | +- [x] Implement `output/spinner.rs` matching TS CLI output format exactly |
| 176 | +- [x] Implement `config/auth.rs` for `~/.graph-cli.json` management (in commands/auth.rs) |
| 177 | +- [x] Implement `config/networks.rs` for networks.json parsing |
| 178 | +- [x] Add reqwest dependency and basic HTTP client setup (in services/graph_node.rs) |
| 179 | +- [x] Implement `services/registry.rs` for @pinax/graph-networks-registry (implemented as `NetworksRegistry` in services/contract.rs) |
| 180 | + |
| 181 | +### Phase 3: Simple Commands |
| 182 | + |
| 183 | +- [x] Implement `gnd clean` command |
| 184 | +- [x] Implement `gnd auth` command |
| 185 | +- [x] Implement `gnd create` command |
| 186 | +- [x] Implement `gnd remove` command |
| 187 | +- [x] Add tests for simple commands |
| 188 | + |
| 189 | +### Phase 4: Code Generation (High Priority, High Risk) |
| 190 | + |
| 191 | +- [x] Study TS CLI codegen output in detail |
| 192 | +- [x] Implement `codegen/schema.rs` - entity classes from GraphQL |
| 193 | +- [x] Implement `codegen/typescript.rs` - AST builders for TypeScript/AssemblyScript |
| 194 | +- [x] Implement `codegen/types.rs` - type conversion utilities |
| 195 | +- [x] Implement `codegen/abi.rs` - ABI bindings |
| 196 | +- [x] Implement `codegen/template.rs` - template bindings |
| 197 | +- [x] Integrate prettier formatting (shell out) |
| 198 | +- [x] Implement `commands/codegen.rs` with all flags |
| 199 | +- [x] Implement `--watch` mode using existing file watcher |
| 200 | +- [x] Create snapshot tests comparing output to TS CLI (11 fixtures from graph-cli validation tests) |
| 201 | +- [x] Verify byte-for-byte identical output - tests pass with documented known differences: |
| 202 | + - Int8 import always included (gnd simplicity) |
| 203 | + - Trailing commas in multi-line constructs (gnd style) |
| 204 | + - 2D array accessors use correct `toStringMatrix()` (gnd fixes graph-cli bug) |
| 205 | + |
| 206 | +### Phase 5: Migrations |
| 207 | + |
| 208 | +- [x] Study TS CLI migrations in `/packages/cli/src/migrations/` |
| 209 | +- [x] Implement migration framework in `migrations/mod.rs` |
| 210 | +- [x] Implement each migration version (0.0.1 → current) |
| 211 | +- [x] Add `--skip-migrations` flag support |
| 212 | +- [x] Test migrations with old manifest versions |
| 213 | + |
| 214 | +### Phase 6: Build Command |
| 215 | + |
| 216 | +- [x] Implement `compiler/asc.rs` - shell out to asc |
| 217 | +- [x] Implement `commands/build.rs` with all flags (~1084 lines, full build pipeline) |
| 218 | +- [x] Handle network file resolution |
| 219 | +- [x] Implement `--watch` mode |
| 220 | +- [x] Implement optional IPFS upload with deduplication |
| 221 | +- [ ] Test build output matches TS CLI (NEEDS HUMAN: manual end-to-end verification) |
| 222 | + |
| 223 | +### Phase 7: Deploy Command |
| 224 | + |
| 225 | +- [x] Implement `services/graph_node.rs` - JSON-RPC client (~258 lines, create/remove/deploy) |
| 226 | +- [x] Implement `commands/deploy.rs` with all flags (~239 lines) |
| 227 | +- [x] Support all deploy targets (local, studio, hosted service) - defaults to Subgraph Studio |
| 228 | +- [x] Handle access token / deploy key authentication |
| 229 | +- [ ] Test deployment to local Graph Node (NEEDS HUMAN: run services + manual test) |
| 230 | + |
| 231 | +### Phase 8: Init Command |
| 232 | + |
| 233 | +- [x] Add `inquire` dependency for interactive prompts |
| 234 | +- [x] Implement `services/contract.rs` - ABI fetching (Etherscan, Blockscout, Sourcify) (~730 lines) |
| 235 | +- [x] Implement networks registry loading |
| 236 | +- [x] Implement `scaffold/manifest.rs` (~271 lines) |
| 237 | +- [x] Implement `scaffold/schema.rs` (~206 lines) |
| 238 | +- [x] Implement `scaffold/mapping.rs` (~205 lines) |
| 239 | +- [x] Implement `commands/init.rs` with all flags (~1060 lines including --from-subgraph) |
| 240 | +- [x] Implement --from-example mode |
| 241 | +- [x] Implement --from-contract mode (uses ContractService for ABI fetching) |
| 242 | +- [x] Add interactive prompts when required options are missing |
| 243 | +- [x] Implement --from-subgraph mode (fetches manifest from IPFS, extracts immutable entities) |
| 244 | +- [ ] Test scaffold output matches TS CLI (NEEDS HUMAN: manual end-to-end verification) |
| 245 | + |
| 246 | +### Phase 9: Add Command |
| 247 | + |
| 248 | +- [x] Implement `commands/add.rs` (~773 lines, fully functional) |
| 249 | +- [x] Reuse scaffold components for actual implementation |
| 250 | +- [x] ABI validation, entity generation, mapping creation, manifest updates |
| 251 | +- [x] Test adding datasource to existing subgraph (unit tests for helper functions) |
| 252 | +- [x] Comprehensive error handling |
| 253 | + |
| 254 | +### Phase 10: Publish Command |
| 255 | + |
| 256 | +- [x] Implement `commands/publish.rs` (~230 lines, fully functional) |
| 257 | +- [x] Build subgraph and upload to IPFS (reuses build command) |
| 258 | +- [x] Open browser to webapp URL with query params (same approach as graph-cli) |
| 259 | +- [x] Support --ipfs-hash flag to skip build |
| 260 | +- [x] Support --subgraph-id, --api-key for updating existing subgraphs |
| 261 | +- [x] Support --protocol-network (arbitrum-one, arbitrum-sepolia) |
| 262 | +- [x] Interactive prompt before opening browser |
| 263 | +- [ ] Test publish workflow (NEEDS HUMAN: manual end-to-end verification) |
| 264 | + |
| 265 | +### Phase 11: Test Command |
| 266 | + |
| 267 | +- [x] Implement Matchstick binary download/detection |
| 268 | +- [x] Implement `commands/test.rs` (~254 lines, shell out to Matchstick) |
| 269 | +- [x] Handle Docker mode (Dockerfile generation on demand) |
| 270 | +- [x] Recompilation flag support |
| 271 | +- [ ] Test with actual Matchstick tests (NEEDS HUMAN: install matchstick + run end-to-end) |
| 272 | + |
| 273 | +### Phase 12: Testing & Polish |
| 274 | + |
| 275 | +- [ ] Port all tests from TS CLI test suite not already covered by gnd tests |
| 276 | + - Location: `/home/lutter/code/subgraphs/graph-cli/packages/cli/tests/` |
| 277 | + - Review existing coverage and identify gaps |
| 278 | +- [x] Add snapshot tests for code generation scenarios (11 fixtures from graph-cli validation tests) |
| 279 | +- [x] Add tests for overloaded events/functions in ABI codegen (disambiguation) |
| 280 | +- [x] Add tests for simple array fields in schema codegen |
| 281 | +- [x] Add tests for nested array types (`[[String]]` etc.) - schema codegen refactored to track list depth |
| 282 | +- [x] Add tests for tuple/struct types in ABI codegen (functions, events, nested, arrays) |
| 283 | +- [x] Add tests for array types in ABI codegen (array params in events, 2D matrices) |
| 284 | +- [x] Codegen verification test framework (gnd/tests/codegen_verification.rs) |
| 285 | +- [x] Add comprehensive tests for prompt module (network completer, source type) |
| 286 | +- [x] Add comprehensive tests for init command (interactive mode detection) |
| 287 | +- [ ] Ensure all edge cases are covered (ongoing) |
| 288 | +- [ ] Documentation: |
| 289 | + - [ ] CLI usage docs (README with command reference, examples, common workflows) |
| 290 | + - [ ] Migration guide from graph-cli to gnd (differences, compatibility notes) |
| 291 | +- [x] Shell completions (bash, elvish, fish, powershell, zsh via clap_complete) |
| 292 | + |
| 293 | +## Key Decisions |
| 294 | + |
| 295 | +| Decision | Choice | Rationale | |
| 296 | +| ---------------- | ---------------------------- | ------------------------------------------- | |
| 297 | +| Binary name | `gnd` | Existing name, avoid confusion with `graph` | |
| 298 | +| Protocol support | Ethereum only | Simplify initial scope | |
| 299 | +| Compatibility | Drop-in replacement | Same flags, output, exit codes | |
| 300 | +| Code generation | Byte-for-byte identical | Snapshot testable, no surprises | |
| 301 | +| Formatting | Shell out to prettier | Guarantees identical output | |
| 302 | +| Compilation | Shell out to asc | Same as TS CLI | |
| 303 | +| Testing | Shell out to Matchstick | Same as TS CLI | |
| 304 | +| Debug logging | RUST_LOG | Rust standard, not DEBUG env var | |
| 305 | +| Validation | Use graph-node's | Refactor if needed, single source of truth | |
| 306 | +| Network registry | Fetch at runtime | Registry contents change over time | |
| 307 | +| Error messages | Same info, format may differ | Convey same information | |
| 308 | +| TS CLI bugs | Fix them | Don't replicate bugs | |
| 309 | + |
| 310 | +## Risk Assessment |
| 311 | + |
| 312 | +| Risk | Severity | Mitigation | |
| 313 | +| --------------------------- | -------- | ------------------------------------ | |
| 314 | +| Code generation fidelity | High | Snapshot tests against TS CLI output | |
| 315 | +| Migration correctness | High | Test with real old manifests | |
| 316 | +| Breaking existing gnd users | Medium | Keep `gnd dev` behavior identical | |
| 317 | +| `asc` version compat | Medium | Version detection, clear errors | |
| 318 | +| Network API changes | Low | Error handling, clear messages | |
| 319 | + |
| 320 | +## TS CLI References |
| 321 | + |
| 322 | +Key files to study in `/home/lutter/code/subgraphs/graph-cli/packages/cli/src/`: |
| 323 | + |
| 324 | +| Feature | TS CLI Location | |
| 325 | +| ---------------- | ----------------------------------- | |
| 326 | +| Commands | `commands/*.ts` | |
| 327 | +| Type generator | `type-generator.ts` | |
| 328 | +| Schema codegen | `codegen/schema.ts` | |
| 329 | +| ABI codegen | `protocols/ethereum/codegen/abi.ts` | |
| 330 | +| Template codegen | `codegen/template.ts` | |
| 331 | +| Compiler | `compiler/index.ts` | |
| 332 | +| Migrations | `migrations/` | |
| 333 | +| Scaffold | `scaffold/` | |
| 334 | +| Spinner/output | `command-helpers/spinner.ts` | |
| 335 | +| Auth | `command-helpers/auth.ts` | |
| 336 | +| Network config | `command-helpers/network.ts` | |
| 337 | +| Tests | `../tests/cli/` | |
| 338 | + |
| 339 | +## Effort Estimate |
| 340 | + |
| 341 | +**~3-4 person-months** for full implementation because: |
| 342 | + |
| 343 | +- Code generation must be byte-for-byte identical (requires careful study) |
| 344 | +- All migrations must be implemented |
| 345 | +- Full test coverage needed |
| 346 | +- But we reuse: manifest parsing, validation, IPFS client, file watching, CLI framework |
0 commit comments