Web3 Ethereum DeFi Development
A specialized development assistant for the web3-ethereum-defi Python library. This skill helps with trading automation on DeFi, data research, and blockchain protocol integration including Uniswap, Aave, Chainlink, and USDC.
Language Conventions
Use UK/British English (e.g., "visualise" not "visualize")For headings, only capitalize the first letter (not title case)All code comments and documentation follow UK spellingRunning Python Code
Always use Poetry to run Python scripts with virtual environment activation:
```shell
poetry run python scripts/logos/post-process-logo.py
```
Testing Workflow
Before running tests, ensure `.local-test.env` exists in repository root. This file sources test secrets from outside the repository.
**Important**: Never edit `.local-test.env` - always ask the user to prepare it first.
Run tests with Poetry and environment sourcing:
```shell
source .local-test.env && poetry run pytest {test case name or pattern}
```
Test Execution Rules
1. Always prefix pytest with `source .local-test.env &&`
2. Use extended timeout: `timeout: 180000` (3 minutes) in bash tool parameters
3. Avoid running full test suite - only run specific test cases
4. For extra output, pass `--log-cli-level=info` to pytest
5. Never use test classes - only use fixture and test functions
6. Tests should not have stdout output like `print()`
7. Use `pytest.approx()` for float fuzzy comparison instead of manual `abs()` checks
8. For DuckDB testing, always close database using finally clause or fixtures
Environment Variable Configuration
RPC URLs use space-separated fallback format. Environment variables follow pattern `JSON_RPC_{CHAIN}`:
`JSON_RPC_ETHEREUM` - Ethereum mainnet`JSON_RPC_ARBITRUM` - Arbitrum One`JSON_RPC_BASE` - Base`JSON_RPC_POLYGON` - Polygon`JSON_RPC_BINANCE` - BNB Smart Chain`JSON_RPC_HYPERLIQUID` - HyperEVM**Important**:
Space-separated RPC URLs only work with `create_multi_provider_web3()`For other commands (curl, etc.), split by space and take first entryAll environment variables point to EVM archive nodesNever figure out RPC URLs yourself - always use environment variablesCode Formatting
Format code with Ruff before committing:
```shell
poetry run ruff format
```
Pull Request Workflow
1. Never push directly to master - always open a pull request
2. Do not include test plan in PR description
3. For feature PRs: prefix title with "feat:" and add one-line entry to `CHANGELOG.md`
4. Changelog entries follow format: "Something was updated (YYYY-MM-DD)"
5. Always format code before opening/updating PRs
Python Coding Standards
Data Structures & Type Hints
Prefer `dataclass(slots=True)` for data structuresAlways type hint function arguments and return valuesUse `HexAddress` instead of `str` for blockchain addressesFor percent-like numbers, use `eth_defi.types.Percent` type alias instead of raw floatTry to return `Iterator` instead of `list` for better performanceCode Style
Use threaded (not async) Python codePrefer Pandas `apply()` and functional helpers over slow for/while loopsUse `any()` and `all()` with generators/list comprehension for collection checksPrefix network read functions with `fetch_` instead of `get_`For long-running loops, use `tqdm` and `tqdm_loggable.auto` for progress barsUse Plotly for visualizations with heading case chart titlesDocumentation & Comments
Use Sphinx restructured text style for code commentsFor dataclass/Enum members, use `#: comment here` line comment above variableFor overloaded functions with nothing new to comment, leave empty instead of repeating parent docsAll API modules need stub entry under `docs/source/api` and cross-reference in `docs/source/api/index`Logging
Use module-level pattern: `logger = logging.getLogger(__name__)`Prefer `%s` and `%f` unexpanded string syntax over Python string interpolation for performanceDateTime Handling
Use naive UTC datetimes everywhereImport as `import datetime.datetime`Use type hints: `datetime.datetime` and `datetime.timedelta`Use `native_datetime_utc_now()` instead of `datetime.datetime.utcnow()`Enums
For string enums, both members and values must be in snake_caseJupyter Notebooks
Prefer table output over `print()`Use Pandas DataFrame with notebook's built-in `display()` for tabular dataCommand Line Scripts
See `scripts/erc-4626/scan-vaults.py` as reference for proper setup.
Script Standards
Always use environment variables for configuration (no CLI parsers unless explicitly requested)Set up logger properlyFor tabular output, use `tabulate.tabulate()` instead of `print()` loopsSee `whitelist-vaults.py` for examplesParallelization & Optimization
For long-running data pipelines:
Use `joblib.Parallel` for API reading parallelizationUse threading backend unless specified otherwiseAll functions using `joblib.Parallel` must accept `max_workers` argumentExpose `max_workers` to CLI scripts as `MAX_WORKERS` environment variableSee `lead_scan_core.py` and `scripts/erc-4626/scan-vaults.py` for examplesBlockchain Interaction
Prefer blockchain explorers (Etherscan) over Python/curl for reading proxy contract addressesPrefer Python snippets over `curl` for reading blockchain explorer dataGet latest block number via `web3.eth.block_number` with JSON-RPC URLNever determine RPC URLs yourself - always use environment variablesReference `eth_defi.chain.CHAIN_NAMES` for chain aliasesDocumentation Building
Documentation uses Sphinx v4.5 in `docs` folder.
Build documentation:
```shell
source .local-test.env && make build-docs
```
Clean Sphinx autosummaries:
```shell
source .local-test.env && make clean-docs
```
**Never directly edit auto-generated Sphinx files in `_autosummary*` folders.**
Dependencies
When adding/updating dependencies in `pyproject.toml`, always add a comment explaining why the dependency is needed.
Key Examples
Long-running pipelines: `lead_scan_core.py`Command line scripts: `scripts/erc-4626/scan-vaults.py`, `whitelist-vaults.py`Documentation structure: `docs/source/api/index.rst`, `docs/source/api/lagoon/index.rst`