Ripple (XRP Ledger) Data
Bitquery provides Ripple / XRP Ledger data dumps in Parquet format, designed for large-scale analytics, historical backfills, and data lake integrations. These datasets can be hosted directly in your own cloud storage (for example, AWS S3) and queried using engines like Snowflake, BigQuery, Athena, Spark, etc.
XRPL is a ledger-object chain rather than an account-and-contract chain. A transaction does not just move a balance — it creates, modifies, or deletes typed objects in the ledger: account roots, trust lines, DEX offers, escrows, checks, NFT offers. Most Bitquery topics mirror that structure, giving you one row per affected ledger object per transaction, with the transaction context attached.
Available Ripple Topics
| Topic | Grain | What it holds |
|---|---|---|
transactions_tx | one row per transaction | Transaction envelope: type, fee, sequence, result code, memos, signers |
transfers_tx | one row per value movement | Unified view of all value flow — payments, fees, trades, NFT trades, mints |
payments_tx | one row per payment | Payment transactions with full amount / delivered / send-max / deliver-min detail |
balances | one row per account per currency | Balance before and after each change, native and issued |
account_roots_tx | one row per account object change | Account root state: XRP balance, owner count, sequence, domain, transfer rate |
ripple_states_tx | one row per trust line change | Trust line (RippleState) balances between two accounts for an issued currency |
offers_tx | one row per DEX offer change | Order book offers: taker gets / taker pays, before and after |
nftoken_offers_tx | one row per NFT offer change | NFT buy and sell offers, with the NFToken and the asking price |
escrows_tx | one row per escrow change | Escrow creation, finish, and cancel, with conditions and time locks |
checks_tx | one row per check change | Checks — deferred payment authorizations |
Where a topic name ends in _tx, rows carry the transaction that caused the change. Pick transfers_tx when you want a single unified stream of value movement, and the object-level topics when you need XRPL-native state such as trust lines or order books.
Sample Ripple Cloud Dataset
You can explore schemas and validate your tooling using the public Ripple sample datasets:
GitHub reference (schemas & examples)
https://github.com/bitquery/blockchain-cloud-data-dump-sample/tree/main/ripple
Example Parquet file (public S3)
https://bitquery-blockchain-dataset.s3.us-east-1.amazonaws.com/ripple/<topic>/<block_range>.parquet
Sample Parquet downloads (public S3)
-
Transactions – Download
-
Transfers – Download
-
Payments – Download
-
Balances – Download
-
Account Roots – Download
-
Ripple States (trust lines) – Download
-
Offers – Download
-
NFToken Offers – Download
-
Escrows – Download
-
Checks – Download
Ripple Dataset Directory Structure
bitquery-blockchain-dataset/
└── ripple/
├── account_roots_tx/
│ ├── <start_block>_<end_block>.parquet
│ └── ...
├── balances/
│ ├── <start_block>_<end_block>.parquet
│ └── ...
├── checks_tx/
│ ├── <start_block>_<end_block>.parquet
│ └── ...
├── escrows_tx/
│ ├── <start_block>_<end_block>.parquet
│ └── ...
├── nftoken_offers_tx/
│ ├── <start_block>_<end_block>.parquet
│ └── ...
├── offers_tx/
│ ├── <start_block>_<end_block>.parquet
│ └── ...
├── payments_tx/
│ ├── <start_block>_<end_block>.parquet
│ └── ...
├── ripple_states_tx/
│ ├── <start_block>_<end_block>.parquet
│ └── ...
├── transactions_tx/
│ ├── <start_block>_<end_block>.parquet
│ └── ...
└── transfers_tx/
├── <start_block>_<end_block>.parquet
└── ...
Block Range Naming Convention
Each Parquet file name follows this format:
<start_block>_<end_block>.parquet
Here block is the XRP Ledger ledger index.
Range size varies by topic. Busy topics are written in 50-ledger files, while sparse object types are batched into wider ranges so files do not become tiny. In the samples above, transfers_tx and transactions_tx cover 50 ledgers (93154950_93154999), while checks_tx, escrows_tx, and nftoken_offers_tx cover 200 (93154950_93155149). Discover the files under a prefix rather than assuming a fixed stride.
Density varies enormously. Across the same 50 ledgers the sample files hold about 4,400 transactions, 7,000 transfers, 9,600 balance rows, and 2,600 offers — but Checks are so rare that a 200-ledger file contains a single row.
Common Columns
Most topics share the same transaction-context columns, which makes joining across topics straightforward:
| Column | Type | Description |
|---|---|---|
block | uint32 | Ledger index |
tx_date | date | Date partition of the ledger close time |
tx_time | datetime | Ledger close time (UTC) |
tx_hash | string | Transaction hash — the join key across every topic |
tx_index | uint32 | Position of the transaction within the ledger |
tx_sender | string | Account that submitted and signed the transaction |
tx_type | string | XRPL transaction type, e.g. Payment, OfferCreate, TrustSet |
operation | string | Ledger node change type — see below |
blockchain_id | uint32 | Bitquery network identifier |
prev_txn_id | string | Hash of the previous transaction that touched this ledger object |
prev_ledger_seq | uint32 | Ledger index of that previous change |
flags | uint32 | XRPL flag bitfield for the object or transaction |
The operation Column
On the object-level topics, operation is the XRPL AffectedNodes change type, and it tells you what happened to the ledger object:
-
CreatedNode– the object came into existence, e.g. an offer was placed or a trust line opened. "Previous" columns are zero. -
ModifiedNode– the object already existed and changed, e.g. an offer was partially filled or a balance moved. -
DeletedNode– the object was removed, e.g. an offer was fully consumed or cancelled, or an escrow was finished. The value columns hold the object's final state before removal, not zeros.
A single transaction routinely produces rows across several topics. One OfferCreate that crosses the book can create an offer row, delete counterparty offer rows, and modify two account roots and several trust lines, all sharing one tx_hash.
Correctness Notes
Four things about XRPL will silently produce wrong numbers if you treat the data like an EVM chain.
1. Use delivered_value, Not amount_value
XRPL supports partial payments, where the sender specifies a maximum Amount but the network delivers less. amount_value is the requested ceiling; delivered_value is what actually arrived. This is the exploit that historically drained exchanges that credited deposits from the wrong field.
In the 93154950_93154999 sample, 819 of 2,247 payments are flagged partial, and 346 of them delivered strictly less than the requested amount — sometimes by a factor of 10^15. Summing the wrong column is not a rounding error:
-- native XRP payments only (amount_currency_token_type = '-')
SUM(amount_value) = 13,000,403,476,694 XRP -- 130x the entire XRP supply
SUM(delivered_value) = 482,083 XRP -- correct
Always aggregate delivered_value. The partial column flags affected rows (1 = partial); when partial = 0, the two columns are identical in every row of the sample, so delivered_value is safe to use unconditionally.
2. Drops vs XRP — Units Differ by Topic
XRPL's base unit is the drop, at 1,000,000 drops per XRP. The topics are not uniform:
| Topic and column | Unit | Type |
|---|---|---|
transactions_tx.fee | drops | string |
account_roots_tx.balance, prev_balance | drops | string |
balances.balance, prev_balance | XRP | float64 |
transfers_tx.amount_from, amount_to | XRP | float64 |
payments_tx.*_value | XRP | float64 |
Both drop-denominated columns are strings, so they must be cast before arithmetic. Verified against the sample: every one of the 4,394 transactions has transactions_tx.fee exactly 1,000,000× the matching transfers_tx fee row, and all 6,466 joinable account-root rows are exactly 1,000,000× the matching balances row.
CAST(fee AS BIGINT) / 1000000.0 AS fee_xrp
3. Failed Transactions Are Included
transactions_tx contains transactions that were applied to the ledger but did not succeed — they still consume a fee and occupy a sequence number. In the sample, 304 of 4,394 (about 7%) failed, with result codes such as tecPATH_PARTIAL, tecPATH_DRY, tecUNFUNDED_OFFER, and tecINSUF_RESERVE_OFFER.
Filter on success = 1, or equivalently result = 'tesSUCCESS', before counting activity.
4. Issued Currency Codes Are Hex
XRPL supports two currency code formats. Three-character codes such as XRP, POZ, or XPM appear as-is. Longer codes are stored as the 40-character hex the ledger itself carries, so decode them to get a readable ticker:
bytes.fromhex("4D656F7752500000000000000000000000000000").rstrip(b"\x00").decode()
# 'MeowRP'
The same applies in SQL, for example in Athena or Snowflake:
SELECT
rtrim(from_utf8(from_hex(currency_symbol)), chr(0)) AS symbol,
sum(delivered_value) AS volume
FROM ripple_payments
WHERE currency_token_type = 'issued'
GROUP BY 1
ORDER BY 2 DESC
An issued token is only unique as the pair (currency code, issuer) — the same ticker can be issued by many accounts, and anyone may issue one. Filter on the issuer, or use currency_id as a single stable key. Native XRP carries currency_token_type = '-' and currency_address = '-'.
Topic Schemas
Columns listed in Common Columns are omitted below.