Skip to content
Open
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ Bankr Skills equip builders with plug-and-play tools to build more powerful agen
| [LITCOIN](https://litcoiin.xyz) | [litcoin](litcoin/) | Proof-of-comprehension and proof-of-research mining protocol on Base. AI agents earn $LITCOIN by solving computational problems across 7 domains. Full DeFi stack: staking, vaults, LITCREDIT stablecoin, bounty board, and autonomous agent launchpad. |
| [ProductClank](https://www.productclank.com) | [productclank](productclank/) | Community-powered brand advocacy on Twitter/X. Create campaigns, discover relevant conversations, generate AI-powered replies at scale, and boost specific posts with likes and reposts. Credit-based pay-per-use with 300 free credits. |
| [Symbiosis](https://symbiosis.finance) | [symbiosis](symbiosis/) | Cross-chain token swaps across 54+ blockchains via Symbiosis protocol. Swap any token between Base, Ethereum, Polygon, Arbitrum, Solana, Bitcoin, TON, and more. Uses Bankr Submit API for on-chain execution. |
| [Coinbase CDP](https://docs.cdp.coinbase.com/data/sql-api/welcome) | [base-sql](base-sql/) | Query real-time and historical onchain data on Base using the Coinbase CDP SQL API. Token transfer history, wallet holdings, unique buyer counts, transaction verification, and any custom SQL against Base blockchain data. 1,000 free queries/month, <500ms latency. |
| [Zerion](https://zerion.io/agents) | [zerion](zerion/) | Interpreted crypto wallet data across 41+ chains. Portfolio values, token and DeFi positions, transaction history, PnL tracking, NFT holdings, gas prices, and swap quotes — enriched with USD values and protocol labels. Supports x402 pay-per-request ($0.01 USDC) and API key access. |
| [Zyfai](https://zyf.ai) | [zyfai](zyfai/) | Earn yield on any Ethereum wallet on Base, Arbitrum, and Plasma. Deploys a non-custodial Safe subaccount linked to the user's EOA with automated rebalancing across DeFi protocols. Session keys for gasless automation. |
| [Quotient](https://quotient.social) | [quotient](quotient/) | Market intelligence API with x402 micropayment and API key auth. Access onchain/social analytics, OpenAPI discovery, and pricing data via `q-api.quotient.social`. |
Expand Down
111 changes: 111 additions & 0 deletions base-sql/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
---
name: base-sql
description: >-
Query real-time and historical onchain data on Base using the Coinbase CDP
SQL API. Use when you need to look up token transfer history for a wallet,
check if a wallet has ever held a specific token, verify on-chain transaction
or fill status, count unique token holders, find swap events, or run any
custom SQL query against Base blockchain data. Triggers on: "query Base",
"check on-chain history", "has wallet ever held", "verify on-chain",
"how many holders", "token transfer history", "confirm fill on-chain",
"Base SQL", "CDP SQL".
---

# CDP Base SQL API

Query Base blockchain data via Coinbase's CDP SQL API — <500ms latency, <250ms from chain tip, 1,000 free queries/month.

## Setup

Store your CDP Client API key in one of:
- Environment variable: `CDP_CLIENT_KEY`
- File: `~/.cdp/client-key.txt` (or set `CDP_KEY_FILE` env var to a custom path)

Get a free key at: https://portal.cdp.coinbase.com/projects/api-keys/client-key

## Running Queries

```bash
# Inline query
CDP_CLIENT_KEY=your_key python3 scripts/query.py "SELECT ..."

# From file
CDP_CLIENT_KEY=your_key python3 scripts/query.py --file query.sql

# Raw JSON response
CDP_CLIENT_KEY=your_key python3 scripts/query.py --raw "SELECT ..."
```

Output: row count + execution time header, then JSON array of results.

## Schema

See `references/schema.md` for full table/column reference and query patterns.

**Quick table guide:**
- Token transfers in/out of a wallet → `base.transfers`
- Swap events, approvals, decoded logs → `base.events`
- Raw transaction data → `base.transactions`
- Block metadata → `base.blocks`

## Common Queries

**Has a wallet ever held a token?**
```sql
SELECT count(*) AS in_count
FROM base.transfers
WHERE to_address = lower('0xWALLET')
AND token_address = lower('0xTOKEN')
AND block_timestamp >= now() - INTERVAL 90 DAY
AND action = 1
```

**Recent token activity for a wallet:**
```sql
SELECT block_timestamp, token_address, from_address, to_address, value
FROM base.transfers
WHERE (from_address = lower('0xWALLET')
OR to_address = lower('0xWALLET'))
AND block_timestamp >= now() - INTERVAL 7 DAY
AND action = 1
ORDER BY block_timestamp DESC
LIMIT 25
```

**Unique buyers of a token in the last hour:**
```sql
SELECT count(DISTINCT to_address) AS unique_buyers
FROM base.transfers
WHERE token_address = lower('0xTOKEN')
AND block_timestamp >= now() - INTERVAL 1 HOUR
AND action = 1
```

**Verify a specific transaction:**
```sql
SELECT from_address, to_address, value, timestamp
FROM base.transactions
WHERE transaction_hash = lower('0xHASH')
AND action = 1
```

**ERC-20 Transfer events for a token:**
```sql
SELECT parameters['from'] AS sender, parameters['to'] AS recipient,
parameters['value'] AS amount, timestamp
FROM base.events
WHERE event_signature = 'Transfer(address,address,uint256)'
AND address = lower('0xTOKEN')
AND timestamp >= now() - INTERVAL 1 DAY
AND action = 1
ORDER BY timestamp DESC
LIMIT 20
```

## Key Rules

- Always `lower('0x...')` addresses — DB stores lowercase
- Always `AND action = 1` to exclude reorg'd data
- ⚠️ **Always include `block_timestamp >= now() - INTERVAL X DAY`** — unbounded scans exceed the 93 GiB leaf node limit and return HTTP 400
- `value` is raw token units — divide by `1e18` (most tokens) or `1e6` (USDC)
- Rate limit: 5 req/s — add `LIMIT` when scanning large ranges
160 changes: 160 additions & 0 deletions base-sql/references/schema.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
# CDP Base SQL API — Schema Reference

## Tables

| Table | Description |
|---|---|
| `base.transfers` | Token transfer events (ERC-20, native ETH) |
| `base.events` | Decoded contract event logs |
| `base.transactions` | Raw transactions |
| `base.blocks` | Block metadata |
| `base.encoded_logs` | Undecoded logs (log0 opcode etc.) |

---

## base.transfers

Best table for tracking token movements into/out of a wallet.

| Field | Type | Notes |
|---|---|---|
| `block_number` | uint64 | |
| `block_timestamp` | DateTime64 | UTC |
| `transaction_hash` | String | |
| `transaction_from` | String | tx signer |
| `transaction_to` | String | tx recipient (may differ from token recipient) |
| `log_index` | uint32 | |
| `token_address` | String | contract address of the token |
| `from_address` | String | sender of the tokens |
| `to_address` | String | receiver of the tokens |
| `value` | uint256 | raw token units (divide by 10^decimals) |
| `action` | Enum8 | 1=added, -1=reorg removed |

**Pattern — wallet token history:**
```sql
SELECT block_timestamp, token_address, from_address, to_address, value
FROM base.transfers
WHERE (from_address = lower('0xWALLET') OR to_address = lower('0xWALLET'))
AND block_timestamp >= now() - INTERVAL 7 DAY
AND action = 1
ORDER BY block_timestamp DESC
LIMIT 50
```

**Pattern — unique tokens ever held (90 day window):**
```sql
SELECT DISTINCT token_address
FROM base.transfers
WHERE to_address = lower('0xWALLET')
AND block_timestamp >= now() - INTERVAL 90 DAY
AND action = 1
```

**Pattern — did wallet ever hold this token?**
```sql
SELECT count(*) AS transfers_in
FROM base.transfers
WHERE to_address = lower('0xWALLET')
AND token_address = lower('0xTOKEN')
AND block_timestamp >= now() - INTERVAL 90 DAY
AND action = 1
```

**Pattern — batch check multiple tokens held by wallet:**
```sql
SELECT DISTINCT token_address
FROM base.transfers
WHERE to_address = lower('0xWALLET')
AND token_address IN ('0xtok1', '0xtok2', '0xtok3')
AND block_timestamp >= now() - INTERVAL 90 DAY
AND action = 1
```

---

## base.events

Decoded event logs. Best for ERC-20 Transfer confirmation, swap events, approvals.

| Field | Type | Notes |
|---|---|---|
| `block_number` | uint64 | |
| `timestamp` | DateTime64 | UTC |
| `transaction_hash` | String | |
| `transaction_from` | String | |
| `transaction_to` | String | |
| `address` | String | contract that emitted the event |
| `event_name` | String | e.g. `Transfer`, `Swap`, `Approval` |
| `event_signature` | String | e.g. `Transfer(address,address,uint256)` |
| `parameters` | Map(String, Variant) | decoded params — access via `parameters['key']` |
| `parameter_types` | Map(String, String) | ABI types |
| `action` | Int8 | 1=added, -1=reorg |

**Pattern — ERC-20 Transfer events for a token:**
```sql
SELECT parameters['from'] AS sender, parameters['to'] AS recipient,
parameters['value'] AS amount, timestamp
FROM base.events
WHERE event_signature = 'Transfer(address,address,uint256)'
AND address = lower('0xTOKEN_ADDRESS')
AND timestamp >= now() - INTERVAL 1 DAY
AND action = 1
ORDER BY timestamp DESC
LIMIT 20
```

**Pattern — swaps from a specific wallet:**
```sql
SELECT timestamp, transaction_hash, address, parameters
FROM base.events
WHERE event_name = 'Swap'
AND transaction_from = lower('0xWALLET')
AND timestamp >= now() - INTERVAL 7 DAY
AND action = 1
ORDER BY timestamp DESC
LIMIT 20
```

---

## base.transactions

| Field | Type | Notes |
|---|---|---|
| `transaction_hash` | String | |
| `from_address` | String | |
| `to_address` | String | |
| `value` | String | native ETH value in wei |
| `timestamp` | DateTime64 | |
| `action` | Int8 | 1=added |

**Pattern — verify a transaction:**
```sql
SELECT from_address, to_address, value, timestamp
FROM base.transactions
WHERE transaction_hash = lower('0xHASH')
AND action = 1
```

---

## base.blocks

| Field | Type | Notes |
|---|---|---|
| `block_number` | uint64 | |
| `timestamp` | DateTime | |
| `transaction_count` | uint64 | |
| `gas_used` | uint64 | |
| `base_fee_per_gas` | uint64 | |

---

## Important Notes

- **Addresses are lowercase** in the DB — always `lower('0x...')` when filtering
- **`action = 1`** filters out reorg'd data — always include this
- **`value` is raw units** — divide by `1e18` for ETH/18-decimal tokens, `1e6` for USDC
- **Rate limit:** 5 queries/second, 1,000 free/month then $0.0083/query
- **Latency:** <500ms query, <250ms from chain tip
- ⚠️ **Always add a `block_timestamp` filter** on `base.transfers` and `base.events` — unbounded scans exceed the 93 GiB leaf node limit and return HTTP 400. Minimum: `AND block_timestamp >= now() - INTERVAL 30 DAY`
Loading