Skip to main content
Glama

Bitquery: Crypto & Blockchain Data

Ada Transfers Raw Sql

ada_transfers_raw_sql
Read-only

LAST RESORT — arbitrary READ-ONLY SQL against the Cardano databases (cardano, cardano_flow). The ada_* tools are the PRIORITY; use this ONLY when none can answer. No query optimizer here: filter on the per-key tables and NEVER JOIN big tables (use IN (SELECT …)); never GLOBAL IN (it reads the whole table). Runs read-only ClickHouse SQL. SQL reference: https://clickhouse.com/docs/reference/home This data runs on an older release of the engine: some functions and syntax in that reference (map() and toJSONString() among them) do not exist here — when a statement is refused for an unknown function or setting, use the forms shown in this description. DATA MODEL: UTXO model with native tokens — EVERY table has ONE ROW PER ASSET: currency_id (native ADA = 7029218, token_index = -1) and value UInt64 in RAW units. ALWAYS group by currency_id and divide by dictGetFloat64('currency','divider',toUInt64(currency_id)) (1e6 for ADA; 1, i.e. raw units, for a token without registered decimals and for an unknown id); a plain sum(value) adds lovelace to token units and is meaningless, and sum() of large token values can overflow — sum toFloat64(value). TOKENS: token identity via the currency dict: 'symbol' / 'name' (a ticker or the hex asset name; '-' for an unknown id), 'asset_id' (fingerprint asset1…), 'decimals', 'properties' (YAML text; policy id = extract(dictGetString('currency','properties',toUInt64(currency_id)), 'policyId: ([0-9a-f]{56})')). Tickers are not unique — match tokens by fingerprint or policy id. A dictGet in WHERE runs for EVERY row read (no short-circuit), so filter by address / tx / currency_id first. Addresses are plain strings (addr1… bech32 lowercase, stake1… reward accounts, Byron base58 Ae2… / Ddz… case-sensitive); a script reward account (stake17… on explorers) is mostly recorded in its stake1u… spelling, whose checksum differs — look such an account up with ada_address_profile or ada_sent_from_address, which match both spellings. stake_key = the staking credential of a base address — on enterprise addresses (addr1v… / addr1w…) the column holds the payment credential re-encoded as stake1u…, which is NOT a staking key. Tx id: tx_id_bin = unhex('<64hex>'), output hex(tx_id_bin). Time = tx_time. Date-times come back as 'YYYY-MM-DD hh:mm:ss' UTC; select formatDateTime(tx_time, '%FT%TZ') for ISO-8601 (2026-09-21T15:04:18Z), the shape the other tools return. TABLES: db cardano, partitioned by month on tx_date (add a plain tx_date bound whenever you can — inside … OR … it prunes nothing): inputs_by_address / outputs_by_address (key address; inputs carry output_tx_id_bin / output_index of the spent output and source Enum input/withdrawal/stake_deregistration; outputs carry direction — only not_change / unknown on ordinary outputs: change is NEVER labeled, so not_change includes change back to the payer), inputs_by_tx / outputs_by_tx / transactions (fee_value, deposit_value, metadata) / mints (key tx_id_bin — pass (tx_date, tx_id_bin) IN (…) when the date is known, otherwise every month is probed; to reuse one lookup in several UNION ALL branches write (tx_date, tx_id_bin) IN identity((SELECT groupArray((tx_date, tx_id_bin)) FROM cardano.transactions WHERE tx_id_bin IN (…))), which runs once; toInt64(value) is negative for a burn), blocks (key block). Deposits are already rows: a stake registration is an output to the stake1… address (direction stake_registration), other protocol deposits an output with an empty address (deposit), a refund an input (stake_deregistration) — per transaction ADA inputs = outputs + fee_value and, per token, inputs + mints = outputs; do not add deposit_value on top. db cardano_flow: tx_inputs / tx_outputs keyed (block, tx_index), not partitioned — the cheap way to expand many transactions: (block, tx_index) IN (SELECT block, tx_index FROM cardano.inputs_by_address WHERE address = '…') (output_type commission / spend — never change; the commission row has an empty address). This copy is INCOMPLETE: it misses some transactions (a few hours of blocks in March 2023 among them) and most outputs of a token minted in the same transaction — use cardano.*_by_tx for exact per-transaction totals. address_transfers (AggregateFunction columns → -Merge; its amount columns ADD ALL ASSETS together and its stake_key is empty — use it for counts only). Address labels: none in this data — use labels_for_addresses(chain='cardano'). LIMITS: read-only; returns the rows of your query. 64-bit integers come back as JSON numbers, exact only up to 2^53: return a hash such as cityHash64(...) or any other 64-bit id as toString(x). A result of more than 25,000 rows is not cut off - the whole query fails with an error - so aggregate (GROUP BY, count) or add a LIMIT of at most 25,000.

Tool call template

Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {
      "sql": "<sql>"
    },
    "name": "ada_transfers_raw_sql"
  }
}

Input Schema

NameRequiredDescriptionDefault
sqlYesA single read-only SELECT. Filter on the indexed *_by_address / *_by_tx tables or on cardano_flow.tx_inputs / tx_outputs by (block, tx_index); group amounts by currency_id; no JOINs over big tables.
formatNoShape of the returned data. "rows" (the default) returns one item per row. "columnar" returns a single item, {"columns":[...],"rows":[[value,...],...]}, naming the columns once and listing each row's values in that order; it is more compact for large results and carries the same values.rows

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • addedInput schema / properties / format
      Added value: +{
      +  "default": "rows",
      +  "description": "Shape of the returned data. \"rows\" (the default) returns one item per row. \"columnar\" returns a single item, {\"columns\":[...],\"rows\":[[value,...],...]}, naming the columns once and listing each row's values in that order; it is more compact for large results and carries the same values.",
      +  "type": "string"
      +}
  2. First observed

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, but the description adds substantial behavioral context beyond them: the engine is older and lacks some functions, queries over 25,000 rows fail rather than truncate, the cardano_flow copy is incomplete, and 64-bit integers may lose precision in JSON. It does not contradict the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but front-loaded with the essential 'LAST RESORT' framing and priority rule. For a raw SQL tool over a complex UTXO data model, nearly every section earns its place, though the density is near the upper practical limit.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, but the description explains the return shape (rows of the query), row-limit behavior, and 64-bit integer caveats. It provides the table layout, token model, address quirks, and known data gaps needed to invoke the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema itself documents both parameters thoroughly. The description adds meaningful semantics for the sql parameter by explaining required aggregation by currency_id, avoiding JOINs, partition pruning with tx_date, and safely handling 64-bit integers — guidance that is not in the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'arbitrary READ-ONLY SQL against the Cardano databases (`cardano`, `cardano_flow`)'. It also distinguishes itself from siblings by declaring the ada_* tools the priority and positioning itself as a LAST RESORT.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly states when to use this tool ('use this ONLY when none [of the ada_* tools] can answer') and when not to. It also gives practical query-shaping guidance such as filtering on per-key tables and avoiding big joins.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.