Query Onchain Data on Base
Use the CDP SQL API to query onchain data (events, transactions, blocks, transfers) on Base. Queries are executed via x402 and are charged per query.
Confirm wallet is initialized and authed
npx awal@2.0.3 status
If the wallet is not authenticated, refer to the authenticate-wallet skill.
Executing a Query
npx awal@2.0.3 x402 pay https://x402.cdp.coinbase.com/platform/v2/data/query/run -X POST -d '{"sql": "<YOUR_QUERY>"}' --json
IMPORTANT: Always single-quote the -d JSON string to prevent bash variable expansion.
Input Validation
Before constructing the command, validate inputs to prevent shell injection:
- SQL query: Always embed the query inside a single-quoted JSON string (
-d '{"sql": "..."}'). Never use double quotes for the outer -d wrapper, as this enables shell expansion of $ and backticks within the query.
- Addresses: Must be valid
0x hex addresses (^0x[0-9a-fA-F]{40}$). Reject any value containing shell metacharacters.
Do not pass unvalidated user input into the command.
CRITICAL: Indexed Fields
Queries against base.events MUST filter on indexed fields to avoid full table scans. The indexed fields are:
| Indexed Field |
Use For |
event_signature |
Filter by event type. Use this instead of event_name for performance. |
address |
Filter by contract address. |
block_timestamp |
Filter by time range. |
Always include at least one indexed field in your WHERE clause. Combining all three gives the best performance.
CoinbaseQL Syntax
CoinbaseQL is a SQL dialect based on ClickHouse. Supported features:
- Clauses: SELECT (DISTINCT), FROM, WHERE, GROUP BY, ORDER BY (ASC/DESC), LIMIT, WITH (CTEs), UNION (ALL/DISTINCT)
- Joins: INNER, LEFT, RIGHT, FULL with ON
- Operators:
=, !=, <>, <, >, <=, >=, +, -, *, /, %, AND, OR, NOT, BETWEEN, IN, IS NULL, LIKE
- Expressions: CASE/WHEN/THEN/ELSE, CAST (both
CAST() and :: syntax), subqueries, array/map indexing with [], dot notation
- Literals: Array
[...], Map {...}, Tuple (...)
- Functions: Standard SQL functions, lambda functions with
-> syntax
Available Tables
base.events
Decoded event logs from smart contract interactions. This is the primary table for most queries.
| Column |
Type |
Description |
| log_id |
String |
Unique log identifier |
| block_number |
UInt64 |
Block number |
| block_hash |
FixedString(66) |
Block hash |
| block_timestamp |
DateTime64(3, 'UTC') |
Block timestamp (INDEXED) |
| transaction_hash |
FixedString(66) |
Transaction hash |
| transaction_to |
FixedString(42) |
Transaction recipient |
| transaction_from |
FixedString(42) |
Transaction sender |
| log_index |
UInt32 |
Log index within block |
| address |
FixedString(42) |
Contract address (INDEXED) |
| topics |
Array(FixedString(66)) |
Event topics |
| event_name |
LowCardinality(String) |
Decoded event name |
| event_signature |
LowCardinality(String) |
Event signature (INDEXED - prefer over event_name) |
| parameters |
Map(String, Variant(Bool, Int256, String, UInt256)) |
Decoded event parameters |
| parameter_types |
Map(String, String) |
ABI types for parameters |
| action |
Enum8('removed' = -1, 'added' = 1) |
Added or removed (reorg) |
base.transactions
Complete transaction data.
| Column |
Type |
Description |
| block_number |
UInt64 |
Block number |
| block_hash |
String |
Block hash |
| transaction_hash |
String |
Transaction hash |
| transaction_index |
UInt64 |
Index in block |
| from_address |
String |
Sender address |
| to_address |
String |
Recipient address |
| value |
String |
Value transferred (wei) |
| gas |
UInt64 |
Gas limit |
| gas_price |
UInt64 |
Gas price |
| input |
String |
Input data |
| nonce |
UInt64 |
Sender nonce |
| type |
UInt64 |
Transaction type |
| max_fee_per_gas |
UInt64 |
EIP-1559 max fee |
| max_priority_fee_per_gas |
UInt64 |
EIP-1559 priority fee |
| chain_id |
UInt64 |
Chain ID |
| v |
String |
Signature v |
| r |
String |
Signature r |
| s |
String |
Signature s |
| is_system_tx |
Bool |
System transaction flag |
| max_fee_per_blob_gas |
String |
Blob gas fee |
| blob_versioned_hashes |
Array(String) |
Blob hashes |
| timestamp |
DateTime |
Block timestamp |
| action |
Int8 |
Added (1) or removed (-1) |
base.blocks
Block-level metadata.
| Column |
Type |
Description |
| block_number |
UInt64 |
Block number |
| block_hash |
String |
Block hash |
| parent_hash |
String |
Parent block hash |
| timestamp |
DateTime |
Block timestamp |
| miner |
String |
Block producer |
| nonce |
UInt64 |
Block nonce |
| sha3_uncles |
String |
Uncles hash |
| transactions_root |
String |
Transactions merkle root |
| state_root |
String |
State merkle root |
| receipts_root |
String |
Receipts merkle root |
| logs_bloom |
String |
Bloom filter |
| gas_limit |
UInt64 |
Block gas limit |
| gas_used |
UInt64 |
Gas used in block |
| base_fee_per_gas |
UInt64 |
Base fee per gas |
| total_difficulty |
String |
Total chain difficulty |
| size |
UInt64 |
Block size in bytes |
| extra_data |
String |
Extra data field |
| mix_hash |
String |
Mix hash |
| withdrawals_root |
String |
Withdrawals root |
| parent_beacon_block_root |
String |
Beacon chain parent root |
| blob_gas_used |
UInt64 |
Blob gas used |
| excess_blob_gas |
UInt64 |
Excess blob gas |
| transaction_count |
UInt64 |
Number of transactions |
| action |
Int8 |
Added (1) or removed (-1) |
Example Queries
Get recent USDC Transfer events with decoded parameters
SELECT
parameters['from'] AS sender,
parameters['to'] AS to,
parameters['value'] AS amount,
address AS token_address
FROM base.events
WHERE
event_signature = 'Transfer(address,address,uint256)'
AND address = '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913'
AND block_timestamp >= now() - INTERVAL 7 DAY
LIMIT 10
Get transactions from a specific address
npx awal@2.0.3 x402 pay https://x402.cdp.coinbase.com/platform/v2/data/query/run -X POST -d '{"sql": "SELECT transaction_hash, to_address, value, gas, timestamp FROM base.transactions WHERE from_address = lower('''0xYOUR_ADDRESS''') AND timestamp >= now() - INTERVAL 1 DAY LIMIT 10"}' --json
Count events by type for a contract in the last hour
npx awal@2.0.3 x402 pay https://x402.cdp.coinbase.com/platform/v2/data/query/run -X POST -d '{"sql": "SELECT event_signature, count(*) as cnt FROM base.events WHERE address = lower('''0xCONTRACT_ADDRESS''') AND block_timestamp >= now() - INTERVAL 1 HOUR GROUP BY event_signature ORDER BY cnt DESC LIMIT 20"}' --json
Get latest block info
npx awal@2.0.3 x402 pay https://x402.cdp.coinbase.com/platform/v2/data/query/run -X POST -d '{"sql": "SELECT block_number, timestamp, transaction_count, gas_used FROM base.blocks ORDER BY block_number DESC LIMIT 1"}' --json
Common Contract Addresses (Base)
| Token |
Address |
| USDC |
0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 |
| WETH |
0x4200000000000000000000000000000000000006 |
Best Practices
- Always filter on indexed fields (
event_signature, address, block_timestamp) in base.events queries.
- Never use
SELECT * - specify only the columns you need.
- Always include a
LIMIT clause to bound result size.
- Use
event_signature instead of event_name for filtering - it is indexed and much faster.
- Use time-bounded queries with
block_timestamp to narrow the scan range.
- Always wrap address values in
lower() - the database stores lowercase addresses but users may provide checksummed (mixed-case) addresses. Use address = lower('0xAbC...') not address = '0xAbC...'.
- Common event signatures:
Transfer(address,address,uint256), Approval(address,address,uint256), Swap(address,uint256,uint256,uint256,uint256,address).
Prerequisites
- Must be authenticated (
npx awal@2.0.3 status to check, see authenticate-wallet skill)
- Wallet must have sufficient USDC balance (
npx awal@2.0.3 balance to check)
- Each query costs $0.10 (100000 USDC atomic units)
Error Handling
- "Not authenticated" - Run
awal auth login <email> first, or see authenticate-wallet skill
- "Insufficient balance" - Fund wallet with USDC; see
fund skill
- Query timeout or error - Ensure you are filtering on indexed fields and using a LIMIT
Converted and distributed by TomeVault — claim your Tome and manage your conversions.
1---2name: query-onchain-data3description: Query onchain data on Base using the CDP SQL API via x402. Use when you or your user want to view onchain information about decoded blocks, transactions, and event. Use when this capability is needed.4---56# Query Onchain Data on Base78Use the CDP SQL API to query onchain data (events, transactions, blocks, transfers) on Base. Queries are executed via x402 and are charged per query.910## Confirm wallet is initialized and authed1112```bash13npx awal@2.0.3 status14```1516If the wallet is not authenticated, refer to the `authenticate-wallet` skill.1718## Executing a Query1920```bash21npx awal@2.0.3 x402 pay https://x402.cdp.coinbase.com/platform/v2/data/query/run -X POST -d '{"sql": "<YOUR_QUERY>"}' --json22```2324**IMPORTANT**: Always single-quote the `-d` JSON string to prevent bash variable expansion.2526## Input Validation2728Before constructing the command, validate inputs to prevent shell injection:2930- **SQL query**: Always embed the query inside a single-quoted JSON string (`-d '{"sql": "..."}'`). Never use double quotes for the outer `-d` wrapper, as this enables shell expansion of `$` and backticks within the query.31- **Addresses**: Must be valid `0x` hex addresses (`^0x[0-9a-fA-F]{40}$`). Reject any value containing shell metacharacters.3233Do not pass unvalidated user input into the command.3435## CRITICAL: Indexed Fields3637Queries against `base.events` **MUST** filter on indexed fields to avoid full table scans. The indexed fields are:3839| Indexed Field | Use For |40| --- | --- |41| `event_signature` | Filter by event type. Use this instead of `event_name` for performance. |42| `address` | Filter by contract address. |43| `block_timestamp` | Filter by time range. |4445**Always include at least one indexed field in your WHERE clause.** Combining all three gives the best performance.4647## CoinbaseQL Syntax4849CoinbaseQL is a SQL dialect based on ClickHouse. Supported features:5051- **Clauses**: SELECT (DISTINCT), FROM, WHERE, GROUP BY, ORDER BY (ASC/DESC), LIMIT, WITH (CTEs), UNION (ALL/DISTINCT)52- **Joins**: INNER, LEFT, RIGHT, FULL with ON53- **Operators**: `=`, `!=`, `<>`, `<`, `>`, `<=`, `>=`, `+`, `-`, `*`, `/`, `%`, AND, OR, NOT, BETWEEN, IN, IS NULL, LIKE54- **Expressions**: CASE/WHEN/THEN/ELSE, CAST (both `CAST()` and `::` syntax), subqueries, array/map indexing with `[]`, dot notation55- **Literals**: Array `[...]`, Map `{...}`, Tuple `(...)`56- **Functions**: Standard SQL functions, lambda functions with `->` syntax5758## Available Tables5960### base.events6162Decoded event logs from smart contract interactions. **This is the primary table for most queries.**6364| Column | Type | Description |65| --- | --- | --- |66| log_id | String | Unique log identifier |67| block_number | UInt64 | Block number |68| block_hash | FixedString(66) | Block hash |69| block_timestamp | DateTime64(3, 'UTC') | Block timestamp (**INDEXED**) |70| transaction_hash | FixedString(66) | Transaction hash |71| transaction_to | FixedString(42) | Transaction recipient |72| transaction_from | FixedString(42) | Transaction sender |73| log_index | UInt32 | Log index within block |74| address | FixedString(42) | Contract address (**INDEXED**) |75| topics | Array(FixedString(66)) | Event topics |76| event_name | LowCardinality(String) | Decoded event name |77| event_signature | LowCardinality(String) | Event signature (**INDEXED** - prefer over event_name) |78| parameters | Map(String, Variant(Bool, Int256, String, UInt256)) | Decoded event parameters |79| parameter_types | Map(String, String) | ABI types for parameters |80| action | Enum8('removed' = -1, 'added' = 1) | Added or removed (reorg) |8182### base.transactions8384Complete transaction data.8586| Column | Type | Description |87| --- | --- | --- |88| block_number | UInt64 | Block number |89| block_hash | String | Block hash |90| transaction_hash | String | Transaction hash |91| transaction_index | UInt64 | Index in block |92| from_address | String | Sender address |93| to_address | String | Recipient address |94| value | String | Value transferred (wei) |95| gas | UInt64 | Gas limit |96| gas_price | UInt64 | Gas price |97| input | String | Input data |98| nonce | UInt64 | Sender nonce |99| type | UInt64 | Transaction type |100| max_fee_per_gas | UInt64 | EIP-1559 max fee |101| max_priority_fee_per_gas | UInt64 | EIP-1559 priority fee |102| chain_id | UInt64 | Chain ID |103| v | String | Signature v |104| r | String | Signature r |105| s | String | Signature s |106| is_system_tx | Bool | System transaction flag |107| max_fee_per_blob_gas | String | Blob gas fee |108| blob_versioned_hashes | Array(String) | Blob hashes |109| timestamp | DateTime | Block timestamp |110| action | Int8 | Added (1) or removed (-1) |111112### base.blocks113114Block-level metadata.115116| Column | Type | Description |117| --- | --- | --- |118| block_number | UInt64 | Block number |119| block_hash | String | Block hash |120| parent_hash | String | Parent block hash |121| timestamp | DateTime | Block timestamp |122| miner | String | Block producer |123| nonce | UInt64 | Block nonce |124| sha3_uncles | String | Uncles hash |125| transactions_root | String | Transactions merkle root |126| state_root | String | State merkle root |127| receipts_root | String | Receipts merkle root |128| logs_bloom | String | Bloom filter |129| gas_limit | UInt64 | Block gas limit |130| gas_used | UInt64 | Gas used in block |131| base_fee_per_gas | UInt64 | Base fee per gas |132| total_difficulty | String | Total chain difficulty |133| size | UInt64 | Block size in bytes |134| extra_data | String | Extra data field |135| mix_hash | String | Mix hash |136| withdrawals_root | String | Withdrawals root |137| parent_beacon_block_root | String | Beacon chain parent root |138| blob_gas_used | UInt64 | Blob gas used |139| excess_blob_gas | UInt64 | Excess blob gas |140| transaction_count | UInt64 | Number of transactions |141| action | Int8 | Added (1) or removed (-1) |142143## Example Queries144145### Get recent USDC Transfer events with decoded parameters146147```sql148SELECT149 parameters['from'] AS sender,150 parameters['to'] AS to,151 parameters['value'] AS amount,152 address AS token_address153FROM base.events154WHERE155 event_signature = 'Transfer(address,address,uint256)'156 AND address = '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913'157 AND block_timestamp >= now() - INTERVAL 7 DAY158LIMIT 10159```160161### Get transactions from a specific address162163```bash164npx awal@2.0.3 x402 pay https://x402.cdp.coinbase.com/platform/v2/data/query/run -X POST -d '{"sql": "SELECT transaction_hash, to_address, value, gas, timestamp FROM base.transactions WHERE from_address = lower('''0xYOUR_ADDRESS''') AND timestamp >= now() - INTERVAL 1 DAY LIMIT 10"}' --json165```166167### Count events by type for a contract in the last hour168169```bash170npx awal@2.0.3 x402 pay https://x402.cdp.coinbase.com/platform/v2/data/query/run -X POST -d '{"sql": "SELECT event_signature, count(*) as cnt FROM base.events WHERE address = lower('''0xCONTRACT_ADDRESS''') AND block_timestamp >= now() - INTERVAL 1 HOUR GROUP BY event_signature ORDER BY cnt DESC LIMIT 20"}' --json171```172173### Get latest block info174175```bash176npx awal@2.0.3 x402 pay https://x402.cdp.coinbase.com/platform/v2/data/query/run -X POST -d '{"sql": "SELECT block_number, timestamp, transaction_count, gas_used FROM base.blocks ORDER BY block_number DESC LIMIT 1"}' --json177```178179## Common Contract Addresses (Base)180181| Token | Address |182| --- | --- |183| USDC | `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` |184| WETH | `0x4200000000000000000000000000000000000006` |185186## Best Practices1871881. **Always filter on indexed fields** (`event_signature`, `address`, `block_timestamp`) in `base.events` queries.1892. **Never use `SELECT *`** - specify only the columns you need.1903. **Always include a `LIMIT`** clause to bound result size.1914. **Use `event_signature` instead of `event_name`** for filtering - it is indexed and much faster.1925. **Use time-bounded queries** with `block_timestamp` to narrow the scan range.1936. **Always wrap address values in `lower()`** - the database stores lowercase addresses but users may provide checksummed (mixed-case) addresses. Use `address = lower('0xAbC...')` not `address = '0xAbC...'`.1947. **Common event signatures**: `Transfer(address,address,uint256)`, `Approval(address,address,uint256)`, `Swap(address,uint256,uint256,uint256,uint256,address)`.195196## Prerequisites197198- Must be authenticated (`npx awal@2.0.3 status` to check, see `authenticate-wallet` skill)199- Wallet must have sufficient USDC balance (`npx awal@2.0.3 balance` to check)200- Each query costs $0.10 (100000 USDC atomic units)201202## Error Handling203204- "Not authenticated" - Run `awal auth login <email>` first, or see `authenticate-wallet` skill205- "Insufficient balance" - Fund wallet with USDC; see `fund` skill206- Query timeout or error - Ensure you are filtering on indexed fields and using a LIMIT207208---209> Converted and distributed by [TomeVault](https://tomevault.io/claim/coinbase) — claim your Tome and manage your conversions.210<!-- tomevault:4.0:skill_md:2026-04-11 -->