Skip to content

Commit 86ff48e

Browse files
committed
Rewrite README for clarity and completeness
Lead with what it does, not what it is. Show a working request/response in the quick start. Features as verbs. Routes table. Development setup separated from user-facing content. Reflects cache server, push targets, requester encoding, all auth methods, and async routes.
1 parent f2468da commit 86ff48e

1 file changed

Lines changed: 132 additions & 110 deletions

File tree

README.md

Lines changed: 132 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -1,146 +1,90 @@
11
# Airnode v2
22

3-
> **⚠️ EXPERIMENTAL — DO NOT USE IN PRODUCTION ⚠️**
4-
>
5-
> This project is under active development. The code has **not been audited**. The contracts, signature formats, and
6-
> APIs are subject to breaking changes without notice. **Do not use this software for production workloads, mainnet
7-
> deployments, or any system where security or financial loss is a concern.**
3+
> **This project is under active development. The code has not been audited. Signature formats, APIs, and contracts are
4+
> subject to breaking changes. Do not use for production workloads or mainnet deployments.**
85
9-
An HTTP server that signs API responses. API providers run it alongside their existing APIs. Clients receive signed data
10-
and can optionally submit it on-chain.
6+
Sign API responses with your private key and serve them over HTTP. Clients verify signatures off-chain or submit them to
7+
on-chain contracts. No chain scanning, no database, no coordinator — a stateless HTTP service that sits in front of your
8+
existing API.
119

12-
## What it does
10+
## How it works
1311

1412
```
15-
Client → HTTP request → Airnode → upstream API → sign response → HTTP response
13+
Client ──POST──▶ Airnode ──HTTP──▶ Upstream API
14+
│ │
15+
│◀───JSON response───┘
16+
17+
├─ Extract value (JSONPath)
18+
├─ ABI-encode (int256, uint256, ...)
19+
├─ Sign (EIP-191)
20+
21+
22+
Signed response ──▶ verify off-chain or submit on-chain
1623
```
1724

18-
The airnode never touches the chain. It calls upstream APIs, signs the responses with the operator's private key
19-
(EIP-191), and returns the signed data. Clients can verify signatures off-chain or submit them to on-chain contracts.
25+
**Pull** — client sends `POST /endpoints/{endpointId}`, gets a signed response back.
2026

21-
Two delivery paths:
22-
23-
- **Pull** — client sends `POST /endpoints/{endpointId}`, gets a signed response back immediately
24-
- **Push** — server calls APIs on a timer, stores signed data, relayers poll `GET /beacons/{beaconId}` and push on-chain
25-
26-
## Prerequisites
27-
28-
| Tool | Version | Install |
29-
| ------------------------------------- | ------- | ----------------------------------------------------------- |
30-
| [Bun](https://bun.sh) | latest | `curl -fsSL https://bun.sh/install \| bash` |
31-
| [Foundry](https://book.getfoundry.sh) | >= 1.0 | `curl -L https://foundry.paradigm.xyz \| bash && foundryup` |
32-
| [uv](https://docs.astral.sh/uv/) | latest | `curl -LsSf https://astral.sh/uv/install.sh \| sh` |
33-
34-
Python tools (Vyper, Slither, Halmos) are installed via [uv](https://docs.astral.sh/uv/):
35-
36-
```bash
37-
uv tool install vyper
38-
uv tool install slither-analyzer
39-
uv tool install halmos
40-
```
27+
**Push** — server calls APIs on a timer, signs the data, stores it as beacons. Relayers poll `GET /beacons/{beaconId}`
28+
and submit on-chain.
4129

4230
## Quick start
4331

4432
```bash
4533
bun install
46-
bun src/cli/index.ts generate-key
34+
bun airnode generate-key # prints private key + address
4735
cp examples/configs/minimal/config.yaml config.yaml
4836
cp examples/configs/minimal/.env.example .env
49-
# Edit .env with your generated private key
37+
# paste your private key into .env
5038
bun run dev
5139
```
5240

53-
Test it:
54-
55-
```bash
56-
curl http://localhost:3000/health
57-
```
58-
59-
## Scripts
60-
61-
| Script | Description |
62-
| -------------------------- | ---------------------------------------- |
63-
| `bun run dev` | Start the server with `--watch` |
64-
| `bun test` | Run unit tests (src/) |
65-
| `bun run test:integration` | Run integration tests (sequential) |
66-
| `bun run test:contracts` | Run contract tests (Foundry) |
67-
| `bun run fmt` | Format (Prettier) and lint-fix (ESLint) |
68-
| `bun run lint` | Check formatting and linting |
69-
| `bun run lint:slither` | Run Slither static analysis on contracts |
70-
71-
## Build
72-
73-
Compile to a standalone binary:
41+
Make a request (replace `{endpointId}` with the ID printed at startup):
7442

7543
```bash
76-
bun run build:osx # macOS ARM64
77-
bun run build:linux-x64 # Linux x86_64
78-
79-
./dist/airnode start # Uses config.yaml + .env
80-
./dist/airnode start -c /path/to/config.yaml # Custom config path
44+
curl -X POST http://localhost:3000/endpoints/{endpointId} \
45+
-H "Content-Type: application/json" \
46+
-d '{"parameters":{"ids":"ethereum","vs_currencies":"usd"}}'
8147
```
8248

83-
## Project structure
84-
85-
```
86-
src/
87-
cli/ CLI entry point and commands
88-
config/ Zod schema, YAML parser, validator, env interpolation
89-
api/ HTTP call building and response processing
90-
server.ts Bun.serve HTTP server (routes, CORS, rate limiting)
91-
pipeline.ts Request processing pipeline (auth → validate → cache → API call → sign)
92-
push.ts Background push loop and beacon store
93-
auth.ts Client-facing authentication (free / apiKey)
94-
cache.ts In-memory TTL response cache with periodic sweep
95-
sign.ts EIP-191 signing, request ID and beacon ID derivation
96-
endpoint.ts Specification-bound endpoint ID derivation
97-
plugins.ts Plugin loader, hook registry, budget tracking
98-
identity.ts DNS identity verification (ERC-7529)
99-
logger.ts Structured logger with AsyncLocalStorage context
100-
types.ts Shared Zod-inferred types
101-
contracts/ Vyper contracts and Foundry tests
102-
examples/
103-
configs/ Reference configurations (complete + minimal)
104-
plugins/ Example plugins (heartbeat, logger, slack-alerts, encrypted-channel)
105-
integration/ Integration tests (22 scenario files)
106-
book/ Documentation site (Docusaurus)
49+
```json
50+
{
51+
"airnode": "0x...",
52+
"endpointId": "0x...",
53+
"timestamp": 1711234567,
54+
"data": "0x0000000000000000000000000000000000000000000000a2a15d09519be00000",
55+
"signature": "0x..."
56+
}
10757
```
10858

109-
## Contracts
110-
111-
Two Vyper 0.4+ contracts targeting the **prague** EVM version:
112-
113-
| Contract | Purpose |
114-
| -------------------- | ----------------------------------------------------- |
115-
| `AirnodeVerifier.vy` | Verify signature, prevent replay, forward to callback |
116-
| `AirnodeDataFeed.vy` | Verify signature, store latest value, serve reads |
117-
118-
Both use the same signature: `keccak256(encodePacked(endpointId, timestamp, data))` with EIP-191 personal sign.
59+
## What you can do
11960

120-
See [`contracts/README.md`](contracts/README.md) for architecture docs, consumer integration examples, and the full test
121-
suite.
61+
- **Sign any API response** with your key — turn untrusted data into a verifiable attestation
62+
- **Serve data to smart contracts** — ABI-encoded responses ready for on-chain submission
63+
- **Run continuous data feeds** — push signed prices, weather, or any updating data on a timer
64+
- **Monetize access** — API keys, NFT-gated endpoints, or pay-per-request via x402
65+
- **Control encoding at request time** — clients pass `_type`, `_path`, `_times` to choose what to extract
66+
- **Deploy a cache server** — separate read layer that receives push data from multiple airnodes
67+
- **Extend with plugins** — hooks at every pipeline stage for custom logic
12268

123-
### Contract testing
69+
## Routes
12470

125-
```bash
126-
bun run test:contracts # Unit + invariant tests
127-
halmos --contract AirnodeVerifierSymbolicTest # Symbolic execution
128-
halmos --contract AirnodeDataFeedSymbolicTest
129-
bun run lint:slither # Static analysis
130-
```
71+
| Method | Path | Description |
72+
| ------ | ------------------------- | -------------------------------- |
73+
| `POST` | `/endpoints/{endpointId}` | Call an endpoint with parameters |
74+
| `GET` | `/beacons/{beaconId}` | Read latest push beacon data |
75+
| `GET` | `/beacons` | List all available beacons |
76+
| `GET` | `/requests/{requestId}` | Poll an async request for status |
77+
| `GET` | `/health` | Version and airnode address |
13178

13279
## Configuration
13380

134-
Config is YAML with 4 sections: `version`, `server`, `settings`, `apis`.
81+
YAML config with `${ENV_VAR}` interpolation. Bun loads `.env` automatically.
13582

13683
```yaml
13784
version: '1.0'
13885

13986
server:
14087
port: 3000
141-
rateLimit:
142-
window: 60000
143-
max: 100
14488

14589
settings:
14690
proof: none
@@ -165,16 +109,94 @@ apis:
165109
type: int256
166110
path: $.bitcoin.usd
167111
times: '1e18'
112+
push:
113+
interval: 10000
114+
```
115+
116+
See [`examples/configs/complete/config.yaml`](examples/configs/complete/config.yaml) for auth methods, caching, push
117+
targets, multi-value encoding, and all available fields.
118+
119+
## Contracts
120+
121+
Two Vyper 0.4+ contracts (EVM target: `prague`):
122+
123+
| Contract | Purpose |
124+
| -------------------- | ----------------------------------------------------- |
125+
| `AirnodeVerifier.vy` | Verify signature, prevent replay, forward to callback |
126+
| `AirnodeDataFeed.vy` | Verify signature, store latest value, serve reads |
127+
128+
Both verify `keccak256(encodePacked(endpointId, timestamp, data))` with EIP-191 personal sign. See
129+
[`contracts/README.md`](contracts/README.md) for integration examples.
130+
131+
## Development
132+
133+
### Prerequisites
134+
135+
| Tool | Install |
136+
| ------------------------------------- | ----------------------------------------------------------- |
137+
| [Bun](https://bun.sh) | `curl -fsSL https://bun.sh/install \| bash` |
138+
| [Foundry](https://book.getfoundry.sh) | `curl -L https://foundry.paradigm.xyz \| bash && foundryup` |
139+
| [uv](https://docs.astral.sh/uv/) | `curl -LsSf https://astral.sh/uv/install.sh \| sh` |
140+
141+
Vyper, Slither, and Halmos are installed via uv:
142+
143+
```bash
144+
uv tool install vyper
145+
uv tool install slither-analyzer
146+
uv tool install halmos
147+
```
148+
149+
### Scripts
150+
151+
| Script | Description |
152+
| -------------------------- | ---------------------------------------- |
153+
| `bun run dev` | Start the server with `--watch` |
154+
| `bun test` | Run unit tests (src/) |
155+
| `bun run test:integration` | Run integration tests (sequential) |
156+
| `bun run test:contracts` | Run contract tests (Foundry) |
157+
| `bun run fmt` | Format (Prettier) and lint-fix (ESLint) |
158+
| `bun run lint` | Check formatting and linting |
159+
| `bun run lint:slither` | Run Slither static analysis on contracts |
160+
161+
### Build
162+
163+
Compile to a standalone binary:
164+
165+
```bash
166+
bun run build:osx # macOS ARM64
167+
bun run build:linux-x64 # Linux x86_64
168+
169+
./dist/airnode start -c config.yaml
168170
```
169171

170-
See [`examples/configs/complete/config.yaml`](examples/configs/complete/config.yaml) for a full reference. Secrets use
171-
`${ENV_VAR}` interpolation — Bun loads `.env` automatically.
172+
### Project structure
173+
174+
```
175+
src/
176+
cli/ CLI commands (start, cache-server, generate-key, etc.)
177+
config/ Zod schema, YAML parser, env interpolation
178+
api/ Upstream API calls and response processing
179+
server.ts Bun.serve HTTP server
180+
pipeline.ts Request pipeline (auth → validate → cache → API → encode → sign)
181+
cache-server.ts Standalone cache server for signed beacon data
182+
push.ts Background push loop with external targets
183+
auth.ts Authentication (free, apiKey, nftKey, x402)
184+
sign.ts EIP-191 signing and signature verification
185+
endpoint.ts Specification-bound endpoint ID derivation
186+
plugins.ts Plugin hooks and budget tracking
187+
contracts/ Vyper contracts and Foundry tests
188+
examples/
189+
configs/ Reference configs (complete, minimal, cache-server)
190+
plugins/ Example plugins (heartbeat, logger, slack-alerts)
191+
book/ Documentation site (Docusaurus)
192+
```
172193
173194
## Documentation
174195
196+
Full docs at the [documentation site](book/). Run locally:
197+
175198
```bash
176-
bun run book:start # Local dev server
177-
bun run book:build # Production build
199+
bun run book:start
178200
```
179201

180202
## License

0 commit comments

Comments
 (0)