API-Based Stateless Transaction
Stateless Transaction Lookup API
Query any on-chain transaction by its hash — without persisting anything to the database. The API fetches the transaction directly from the blockchain RPC, parses it into a structured format with sub-transactions, balance changes, and enriched asset metadata, and returns it in a single GraphQL call.
GraphQL Endpoint
POST /graphql
Query
query GetStatelessTransaction($txHash: String!, $platform: Platform!) { getStatelessTransaction(txHash: $txHash, platform: $platform) { identifier platform fromAddress toAddress blockNumber timestamp success methodId decodedFunctionName subTransactions { typeId sender recipient assetIdentifier asset { identifier symbol name decimals } amount type balanceFactor timestamp } balanceChanges { account assetIdentifier asset { identifier symbol name decimals } balanceBefore balanceAfter diff } } }
Variables
Variable | Type | Required | Description |
|---|---|---|---|
|
| Yes | The transaction hash (e.g. |
|
| Yes | The blockchain network enum (e.g. |
Example Request
{ "query": "query($txHash: String!, $platform: Platform!) { getStatelessTransaction(txHash: $txHash, platform: $platform) { identifier platform fromAddress toAddress blockNumber timestamp success methodId decodedFunctionName subTransactions { typeId sender recipient assetIdentifier asset { identifier symbol name decimals } amount type balanceFactor } balanceChanges { account assetIdentifier asset { identifier symbol name decimals } balanceBefore balanceAfter diff } } }", "variables": { "txHash": "0x1a2c1d615f1812def157f57cbe2a050ea0b610d60b27bad0ea60e3e47d206030", "platform": "ETHEREUM" } }
Example Response
{ "data": { "getStatelessTransaction": { "identifier": "0x1a2c1d615f1812def157f57cbe2a050ea0b610d60b27bad0ea60e3e47d206030", "platform": "ETHEREUM", "fromAddress": "0xabc...123", "toAddress": "0xdef...456", "blockNumber": 18500000, "timestamp": "2024-10-28T12:34:56+00:00", "success": true, "methodId": "0xa9059cbb", "decodedFunctionName": "transfer", "subTransactions": [ { "typeId": "log_0", "sender": "0xabc...123", "recipient": "0xdef...456", "assetIdentifier": "0xdac17f958d2ee523a2206206994597c13d831ec7", "asset": { "identifier": "0xdac17f958d2ee523a2206206994597c13d831ec7", "symbol": "USDT", "name": "Tether USD", "decimals": 6 }, "amount": "1000.50", "type": "TOKEN_TRANSFER", "balanceFactor": -1 }, { "typeId": "gas", "sender": "0xabc...123", "recipient": "0x0000000000000000000000000000000000000000", "assetIdentifier": "native", "asset": { "identifier": "native", "symbol": "ETH", "name": null, "decimals": 18 }, "amount": "0.002145", "type": "GAS", "balanceFactor": -1 } ], "balanceChanges": [ { "account": "0xabc...123", "assetIdentifier": "0xdac17f958d2ee523a2206206994597c13d831ec7", "asset": { "identifier": "0xdac17f958d2ee523a2206206994597c13d831ec7", "symbol": "USDT", "name": "Tether USD", "decimals": 6 }, "balanceBefore": "5000.00", "balanceAfter": "3999.50", "diff": "-1000.50" } ] } } }
Response Fields
Transaction (top level)
Field | Type | Description |
|---|---|---|
|
| The transaction hash |
|
| The blockchain network |
|
| Transaction sender address |
|
| Transaction recipient / contract address |
|
| Block number the transaction was included in |
|
| Block timestamp (UTC) |
|
| Whether the transaction succeeded (reverted = |
|
| First 4 bytes of the input data (e.g. |
|
| Human-readable function name (e.g. |
|
| Parsed value movements within the transaction |
|
| On-chain balance snapshots before and after the transaction |
SubTransaction
Each sub-transaction represents a single value movement (native transfer, token transfer, or gas fee).
Field | Type | Description |
|---|---|---|
|
| Identifier: |
|
| Address sending the value |
|
| Address receiving the value |
|
|
|
|
| Enriched asset metadata (see below) |
|
| Transfer amount, adjusted by decimals (human-readable units) |
|
| One of: |
|
|
|
BalanceChange
Shows the on-chain balance of each account+asset pair immediately before and after the transaction.
Field | Type | Description |
|---|---|---|
|
| Wallet address |
|
|
|
|
| Enriched asset metadata |
|
| Balance at |
|
| Balance at |
|
|
|
AssetInfo
Field | Type | Description |
|---|---|---|
|
|
|
|
| Token symbol (e.g. |
|
| Token name (e.g. |
|
| Token decimals (fetched from DB, or from RPC if unavailable) |
Supported Networks
All EVM-compatible blockchains are supported. Pass the network name as the platform variable.
Network | Platform Value | Network | Platform Value |
|---|---|---|---|
Ethereum |
| Polygon |
|
Arbitrum |
| Optimism |
|
Base |
| Avalanche C-Chain |
|
BNB Smart Chain |
| zkSync Era |
|
Linea |
| Scroll |
|
Fantom |
| Gnosis Chain |
|
Cronos |
| Celo |
|
Moonbeam |
| Mantle |
|
Blast |
| Mode |
|
Manta Pacific |
| Polygon zkEVM |
|
Ronin |
| Sonic |
|
Berachain |
| Unichain |
|
Story |
| World Chain |
|
Soneium |
| Fraxtal |
|
Flare |
| Kaia |
|
Immutable zkEVM |
| Ink |
|
Abstract |
| Hyperliquid |
|
The full list includes 100+ EVM networks. Any chain listed under the
Platformenum with EVM support will work. If a network is missing, contact us.
How It Works
Fetch — The transaction and its receipt are fetched from the chain's RPC node.
Parse — Native transfers, ERC-20 token transfers (from event logs), and gas fees are extracted into sub-transactions.
Balance snapshots — For each account+asset involved, the on-chain balance is queried at
blockNumber - 1(before) andblockNumber(after).Asset enrichment — Each asset is enriched with symbol, name, and decimals from our database. If an asset is unknown, decimals are fetched directly from the token contract's RPC.
Function decoding — The method ID is resolved to a human-readable function name using the contract's ABI (if available) or a signature database.
Limitations
Limitation | Details |
|---|---|
EVM only | Non-EVM chains (Solana, Bitcoin, Cosmos, Substrate, etc.) are not yet supported. |
Read-only | The transaction is not persisted to the database. Each call fetches fresh data from the RPC. |
No internal transactions | Internal (trace-level) calls are not parsed. Only top-level native transfers and ERC-20/ERC-721 |
Balance changes depend on the onchain service | If the onchain balance service is unavailable or the token is not indexed, |
Balance changes are raw values |
|
Asset metadata may be partial | If a token is not in our database, |
decodedFunctionName may be null | Function decoding relies on known contract ABIs and a signature database. Uncommon or custom functions may not be decoded. |
Timeout | The query has a 100-second timeout. Complex transactions with many balance-change lookups may approach this limit. |
Authentication required | A valid JWT Bearer token is required in the |
Error Handling
Scenario | Response |
|---|---|
Invalid or non-existent tx hash |
|
Unsupported platform (non-EVM) |
|
RPC unreachable or rate-limited |
|
Timeout (>100s) |
|
Missing auth token | HTTP 401 with |
All errors are logged server-side. If you consistently get null for a valid transaction, contact support.
Testing with cURL
curl -X POST https://<your-bff-host>/graphql \\\\ -H "Content-Type: application/json" \\\\ -H "Authorization: Bearer <your-jwt-token>" \\\\ -d '{ "query": "query($txHash: String!, $platform: Platform!) { getStatelessTransaction(txHash: $txHash, platform: $platform) { identifier platform fromAddress toAddress blockNumber timestamp success methodId decodedFunctionName subTransactions { typeId sender recipient assetIdentifier asset { identifier symbol name decimals } amount type balanceFactor } balanceChanges { account assetIdentifier asset { identifier symbol name decimals } balanceBefore balanceAfter diff } } }", "variables": { "txHash": "0x1a2c1d615f1812def157f57cbe2a050ea0b610d60b27bad0ea60e3e47d206030", "platform": "ETHEREUM" } }'
Testing with Postman
Set the request to POST
https://<your-bff-host>/graphqlUnder Headers, add:
Content-Type:application/jsonAuthorization:Bearer <your-jwt-token>
Under Body (raw JSON), paste the query and variables from the example above
Click Send
Testing with GraphiQL
If you have access to the BFF's GraphiQL interface (/graphql in a browser), you can paste the query directly and provide the variables in the Variables panel. Note that GraphiQL requests from localhost may bypass authentication for introspection, but the actual query still requires a valid token in the Authorization header.