|
| 1 | +# Agent Instructions |
| 2 | + |
| 3 | +Instructions for AI coding agents working on this repository. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +**Arkiv SDK** is the official Python library for interacting with Arkiv networks—a permissioned storage system for decentralized apps supporting flexible entities with binary data, attributes, and metadata. |
| 8 | + |
| 9 | +The SDK is built on top of [Web3.py](https://github.com/ethereum/web3.py) and should feel like "web3.py + entities". |
| 10 | + |
| 11 | +## Architecture |
| 12 | + |
| 13 | +### Clients |
| 14 | + |
| 15 | +| Client | Base Class | Provider | HTTP Stack | |
| 16 | +|--------|------------|----------|------------| |
| 17 | +| `Arkiv` (sync) | `Web3` | `HTTPProvider` | `requests` | |
| 18 | +| `AsyncArkiv` (async) | `AsyncWeb3` | `AsyncHTTPProvider` | `aiohttp` | |
| 19 | + |
| 20 | +- Entity operations live under `client.arkiv.*`, following Web3's module pattern (`eth`, `net`, etc.) |
| 21 | +- Always use `async with AsyncArkiv(...)` for proper session cleanup |
| 22 | +- `AsyncArkiv` must call `_disconnect_provider()` on `__aenter__` failure to avoid aiohttp session leaks |
| 23 | + |
| 24 | +### Key Modules |
| 25 | + |
| 26 | +| Module | Purpose | |
| 27 | +|--------|---------| |
| 28 | +| `arkiv.client` | `Arkiv` and `AsyncArkiv` clients | |
| 29 | +| `arkiv.provider` | `ProviderBuilder` for HTTP/WS providers | |
| 30 | +| `arkiv.account` | `NamedAccount` for wallet/key management | |
| 31 | +| `arkiv.node` | `ArkivNode` for local containerized nodes | |
| 32 | +| `arkiv.module` / `arkiv.module_async` | Entity CRUD, queries, event watching | |
| 33 | + |
| 34 | +### ProviderBuilder |
| 35 | + |
| 36 | +Fluent API for constructing providers: |
| 37 | + |
| 38 | +```python |
| 39 | +ProviderBuilder().kaolin().build() # Kaolin testnet HTTP |
| 40 | +ProviderBuilder().localhost(8545).ws().build() # Local WebSocket |
| 41 | +ProviderBuilder().custom(url).timeout(5).async_mode().build() # Custom async with timeout |
| 42 | +``` |
| 43 | + |
| 44 | +## Coding Conventions |
| 45 | + |
| 46 | +### Test Naming |
| 47 | + |
| 48 | +- Sync tests: `test_provider_*`, `test_create_entity_*`, etc. |
| 49 | +- Async tests: `test_async_provider_*`, `test_async_create_entity_*`, etc. |
| 50 | + |
| 51 | +### Test Patterns |
| 52 | + |
| 53 | +- Use `delayed_rpc_server` fixture for deterministic timeout tests |
| 54 | +- Use invalid hostnames like `https://nonexistent.rpc-node.local` for DNS failure tests |
| 55 | +- Sync timeout: expect `requests.exceptions.ReadTimeout` |
| 56 | +- Async timeout: expect `asyncio.TimeoutError` or `aiohttp.ClientError` |
| 57 | +- Sync DNS failure: expect `requests.exceptions.ConnectionError` |
| 58 | +- Async DNS failure: expect `aiohttp.ClientConnectorDNSError` |
| 59 | + |
| 60 | +### Style |
| 61 | + |
| 62 | +- MyPy strict mode enabled |
| 63 | +- Ruff for linting and formatting (88 char lines, double quotes, trailing commas) |
| 64 | +- Use `logging` module for debug/info output in tests and library code |
| 65 | + |
| 66 | +## Quality Gates |
| 67 | + |
| 68 | +Before any commit: |
| 69 | + |
| 70 | +```bash |
| 71 | +./scripts/check-all.sh |
| 72 | +``` |
| 73 | + |
| 74 | +This runs: |
| 75 | +1. `pre-commit run --all-files` – linting, formatting, trailing whitespace |
| 76 | +2. `mypy --strict src/` – type checking |
| 77 | +3. `pytest -n auto` – all tests in parallel |
| 78 | + |
| 79 | +## Workflow for Changes |
| 80 | + |
| 81 | +Follow this workflow for any code changes: |
| 82 | + |
| 83 | +1. **Understand first** – Ensure you understand the problem and we have a shared understanding of what needs to be done or fixed. |
| 84 | + |
| 85 | +2. **Confirm before changing** – Before making changes, ensure there is a clear instruction to actually change anything. If unsure, ask. |
| 86 | + |
| 87 | +3. **Follow existing patterns** – When proposing changes, make sure you understand the coding patterns and align your changes according to the existing patterns. |
| 88 | + |
| 89 | +4. **Minimal changes only** – Before making a change, ensure that the change is minimal and only changes the item that was discussed. |
| 90 | + |
| 91 | +5. **Run relevant tests** – Before suggesting that you have completed the change, run the relevant tests to ensure that the desired new behaviour is observed. |
| 92 | + |
| 93 | +6. **Propose missing tests** – Should tests for the new feature/behaviour be missing, make a proposal for which tests you'd add. |
| 94 | + |
| 95 | +7. **Full quality check** – Once local tests confirm the changes work as intended, run `./scripts/check-all.sh` to verify the new code base does not break old tests and conforms to the coding standards. |
| 96 | + |
| 97 | +## Known Issues |
| 98 | + |
| 99 | +- `AsyncArkiv` must disconnect provider on `__aenter__` failure to avoid unclosed `aiohttp.ClientSession` warnings |
| 100 | +- WebSocket providers are always async; sync `Arkiv` client rejects them with a clear error message |
| 101 | + |
| 102 | +## Dependencies |
| 103 | + |
| 104 | +- **uv** – Package and version management |
| 105 | +- **pytest** + **pytest-asyncio** – Testing framework |
| 106 | +- **testcontainers** – Local Arkiv node containers for integration tests |
| 107 | +- **Web3.py 7.x** – Underlying Ethereum client library |
0 commit comments