Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
26 changes: 26 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,20 @@ The project follows a command-based architecture using Cobra framework:

- **Main Entry**: `main.go` simply calls `cmd.Execute()`
- **Command Structure**: Each command is organized in its own package under `cmd/` (e.g., `cmd/loadtest/`, `cmd/monitor/`)
- **Subcommand Structure**: Subcommands should also be in their own package (e.g., `cmd/loadtest/uniswapv3/` for `polycli loadtest uniswapv3`)
- **Bindings**: Go bindings for smart contracts are in `bindings/` (generated from Solidity contracts in `contracts/`)
- **Utilities**: Common utilities are in `util/` package

Key architectural patterns:

- Commands are self-contained with their own usage documentation (`.md` files)
- Heavy use of code generation for documentation, protobuf, contract bindings, and RPC types
- Docker-based generation workflows to ensure consistency

## Common Development Commands

### Building and Installation

```bash
# Build the binary
make build
Expand All @@ -36,6 +39,7 @@ make simplecross # Without CGO
```

### Testing

```bash
# Run all tests with coverage
make test
Expand All @@ -49,6 +53,7 @@ make geth-loadtest # Fund account and run load test
```

### Code Quality

```bash
# Run all linters (includes tidy, vet, golangci-lint)
make lint
Expand All @@ -61,6 +66,7 @@ make golangci-lint # Run golangci-lint
```

### Code Generation

```bash
# Generate everything (docs, proto, bindings, etc.)
make gen
Expand All @@ -74,6 +80,7 @@ make gen-json-rpc-types # Generate JSON RPC types
```

### Contract Development

```bash
# Work with smart contracts
cd contracts/
Expand All @@ -84,6 +91,7 @@ make gen-go-bindings # Generate Go bindings
## Adding New Features

When adding a new command:

1. Create a new package under `cmd/your-command/`
2. Add the command to `cmd/root.go` in the `NewPolycliCommand()` function
3. Create a usage documentation file (e.g., `yourCommandUsage.md`)
Expand All @@ -93,6 +101,7 @@ When adding a new command:
## CI/CD Considerations

The CI pipeline (`/.github/workflows/ci.yml`) runs:

- Linting (golangci-lint, shadow)
- Tests
- Generation checks (ensures all generated files are up-to-date)
Expand All @@ -110,6 +119,7 @@ Always run `make gen` before committing if you've changed anything that affects
## Environment Configuration

The tool supports configuration via:

- CLI flags (highest priority)
- Environment variables
- Config file (`~/.polygon-cli.yaml`)
Expand All @@ -120,16 +130,19 @@ The tool supports configuration via:
- Use zerolog for structured, performant logging throughout the project

## Development Guidelines

- Use conventional commit messages

## Development Memories

- Use `make build` to build polycli

## Code Quality Checklist

**CRITICAL**: Before writing any code, systematically check these categories to avoid rework:

### 0. Critical Thinking & Code Analysis (Meta-Level)

**MOST IMPORTANT**: Think critically before implementing any suggestion or requirement.

- **Analyze Existing Code First**: Before adding validation, checks, or features, thoroughly examine what already exists
Expand All @@ -143,12 +156,14 @@ The tool supports configuration via:
- **Evaluate Necessity**: Just because something CAN be added doesn't mean it SHOULD be. Ask: "Does this add value or just clutter?"

**Questions to ask before writing ANY code:**

1. "What validation/checks already exist in this call chain?"
2. "Is this truly adding safety, or is it redundant?"
3. "What value does this code provide?"
4. "Am I implementing this because it was suggested, or because it's actually needed?"

**Example of what NOT to do:**

```go
// Earlier in function (line 211)
if report.EndBlock == math.MaxUint64 {
Expand All @@ -163,29 +178,34 @@ if report.EndBlock == math.MaxUint64 {
}
totalBlocks := report.EndBlock - report.StartBlock + 1
```

This is pure redundancy - if the value can't be MaxUint64 (validated at line 211), checking again at line 231 adds zero value.

### 1. Security

- **HTML/Template Injection**: Always use `html.EscapeString()` for any data interpolated into HTML, even if currently from trusted sources
- **Input Validation**: Validate all user inputs at boundaries (flags, API inputs)
- **SQL Injection**: Use parameterized queries, never string concatenation
- **Command Injection**: Never pass user input directly to shell commands
- **Question to ask**: "What data is untrusted? Where does it flow? Is it escaped/validated at every output point?"

### 2. Resource Management & Performance

- **Goroutine Lifecycle**: Every goroutine must have a clear termination condition via context cancellation
- **Timer Cleanup**: Use `time.NewTimer()` + `defer timer.Stop()`, never `time.After()` in select statements (causes goroutine leaks)
- **Channel Buffers**: Use small fixed buffers (e.g., `concurrency*2`), never proportional to total dataset size
- **Memory Allocation**: Consider behavior with 10x, 100x, 1000x expected input
- **Question to ask**: "How does every goroutine, timer, and channel clean up on cancellation? What's the memory footprint at scale?"

### 3. Context Propagation

- **Never create root contexts**: Always thread `context.Context` through call chains; never use `context.Background()` in the middle of operations
- **Cancellation Flow**: Context should flow through every I/O operation, long-running task, and goroutine
- **Timeout Management**: Create child contexts with `context.WithTimeout(parentCtx, duration)`, not `context.WithTimeout(context.Background(), duration)`
- **Question to ask**: "Does context flow through all long-running operations? Will Ctrl+C immediately stop everything?"

### 4. Data Integrity & Determinism

- **Completeness**: Data collection operations must fetch ALL requested data or fail entirely - never produce partial results
- **Retry Logic**: Failed operations should retry (with backoff) before failing
- **Idempotency**: Same input parameters should produce identical output every time
Expand All @@ -194,6 +214,7 @@ This is pure redundancy - if the value can't be MaxUint64 (validated at line 211
- **Question to ask**: "If I run this twice with the same parameters, will I get identical results? What makes this non-deterministic? Am I reading from the authoritative data source?"

### 5. Error Handling & Logging

- **Error Wrapping**: Use `fmt.Errorf("context: %w", err)` to wrap errors with context
- **Single-line Messages**: Put context before `%w` in single line: `fmt.Errorf("failed after %d attempts: %w", n, err)`
- **Failure Modes**: Consider and handle all failure paths explicitly
Expand All @@ -202,6 +223,7 @@ This is pure redundancy - if the value can't be MaxUint64 (validated at line 211
- **Question to ask**: "What can fail? How is each failure mode handled? Are errors properly wrapped? Is progress logging accurate during retries/failures?"

### 6. Concurrency Patterns

- **Channel Closing**: Close channels in the correct goroutine (usually the sender); use atomic counters to coordinate
- **Channel Draining**: When using select with multiple channels and one closes, drain remaining channels to avoid missing messages
- **Worker Pools**: Use `sync.WaitGroup` to wait for workers; protect shared state with mutexes or channels
Expand All @@ -210,6 +232,7 @@ This is pure redundancy - if the value can't be MaxUint64 (validated at line 211
- **Question to ask**: "Who closes each channel? Can any goroutine block forever? Does this have race conditions? Are all channel messages guaranteed to be read?"

### 7. Testing & Validation

- **Test Coverage**: Write tests for edge cases, not just happy paths
- **Error Injection**: Test retry logic, failure modes, and error paths
- **Resource Limits**: Test with large inputs to verify scalability
Expand Down Expand Up @@ -297,6 +320,7 @@ go func() {
## Code Style

### Cobra Flags

- Flag names: lowercase with hyphens (kebab-case), e.g., `--output-file`
- Usage strings: lowercase, no ending punctuation, e.g., `"path to output file"`
- Remove unnecessary leading articles and filler words (e.g., "the", "a", "an") from usage strings
Expand All @@ -317,9 +341,11 @@ go func() {
```

### Cobra Command Arguments

- Prefer to use Cobra built-in validators (`cobra.NoArgs`, `cobra.ExactArgs(n)`, `cobra.MinimumNArgs(n)`, `cobra.MaximumNArgs(n)`, `cobra.ArbitraryArgs`) instead of custom `Args: func(cmd *cobra.Command, args []string) error` functions, and move argument parsing/validation logic to `PreRunE` hook

### Cobra Commands

- Command `Short` descriptions: sentence case with ending period, e.g., `"Generate a node list to seed a node."`
- Command `Long` descriptions: consider using embedded usage.md file via `//go:embed usage.md` pattern; when using inline strings, use sentence case with ending period for complete sentences
- Command `Short` should be brief (~50 characters or less), appears in help menus and command lists
Expand Down
Loading