MEV Analytics API
Trade Context Analysis Documentation
Endpoints
1. Analyze Trade Context
Analyzes all transactions that touched a specific account (market) within ±4 slots (blocks) of your transaction. Shows PoH tick offsets to understand who traded before/after you.
2. Backfill Transaction
Backfills transaction data for a given signature and account into the analytics database. Useful for ensuring specific transactions are tracked and analyzed within a specified slot range. The backfill runs asynchronously and returns immediately with a request ID for tracking.
3. Get Transaction Details
Retrieves detailed information about a specific transaction including slot, timestamp, success status, fee, tokens involved, and market information with human-readable labels and tags.
4. Fetch Wallet Signatures
Fetches transaction signatures for a wallet with intelligent caching, pagination, and time filtering. Features 5-minute cache TTL, custom time windows (within 7 days), and efficient RPC batching. Returns lightweight signature data that can be enhanced with other endpoints.
5. Enhance Transaction Metadata
Fetches detailed transaction metadata from Solana RPC including fees, error status, and balance changes. Complements /analyze-trade by providing financial details for each transaction signature. Shows SOL/token balance changes, fees, and success/failure status focused exclusively on the transaction signer.
Request Format
Headers
Content-Type: application/json
Body Parameters - Analyze Trade
| Parameter | Type | Required | Description |
|---|---|---|---|
| signature | string | Yes | Your transaction signature (base58, 87-88 chars) |
| account_id | string | Yes | The market/account ID you were trading on (base58, 32-44 chars) |
| slot_range | integer | No | Number of slots before/after to search (default: 4, max: 100) |
| start_time | integer | No | Unix timestamp - start of time window to search for original transaction (optional filter) |
| end_time | integer | No | Unix timestamp - end of time window to search for original transaction (optional filter) |
Body Parameters - Backfill Transaction
| Parameter | Type | Required | Description |
|---|---|---|---|
| signature | string | Yes | Transaction signature to backfill (base58, 87-88 chars) |
| account | string | Yes | The market/account ID to analyze (base58, 32-44 chars) |
| slotRange | integer | No | Number of slots before/after to analyze (default: 2) |
URL Parameters - Get Transaction Details
| Parameter | Type | Required | Description |
|---|---|---|---|
| signature | string | Yes | Transaction signature (base58, 87-88 chars) |
URL Parameters - Fetch Wallet Signatures
| Parameter | Type | Required | Description |
|---|---|---|---|
| address | string | Yes | Wallet address (base58) |
Body Parameters - Fetch Wallet Signatures
| Parameter | Type | Required | Description |
|---|---|---|---|
| limit | integer | No | Signatures to return per page (default: 100, max: 1000) |
| before | string | No | Signature to paginate from (for subsequent pages) |
| start_time | integer | No | Unix timestamp - start of time window (must be within 7 days) |
| end_time | integer | No | Unix timestamp - end of time window (must be within 7 days) |
| hint_signature | string | No | Signature to start RPC fetching from (optimization hint) |
Body Parameters - Enhance Metadata
| Parameter | Type | Required | Description |
|---|---|---|---|
| signature | string | Yes | Transaction signature to enhance (base58, 87-88 chars) |
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| page | integer | 1 | Page number for pagination |
| limit | integer | 100 | Results per page (max: 1000) |
Example Request - Analyze Trade
# Basic request curl -X POST https://api.soltop.sh/analyze-trade \ -H "Content-Type: application/json" \ -d '{ "signature": "pHXgUjY4cVvi5orXuK3b66MBhF2W3MpXruRGKodqTWze7354iVQ66k1rWCzyWTU7UDeebojPTpW9ZmVv9Dn12cg", "account_id": "FnmStvzQ27Pm4U8r3M6gPD7mnk6ST6HwraPsoNmYpump", "slot_range": 4 }'
Example Request - Backfill Transaction
# Basic request curl -X POST https://api.soltop.sh/backfill-transaction \ -H "Content-Type: application/json" \ -d '{ "signature": "pHXgUjY4cVvi5orXuK3b66MBhF2W3MpXruRGKodqTWze7354iVQ66k1rWCzyWTU7UDeebojPTpW9ZmVv9Dn12cg", "account": "FnmStvzQ27Pm4U8r3M6gPD7mnk6ST6HwraPsoNmYpump", "slotRange": 2 }'
Example Request - Get Transaction Details
# Basic request
curl -X GET https://api.soltop.sh/transaction/pHXgUjY4cVvi5orXuK3b66MBhF2W3MpXruRGKodqTWze7354iVQ66k1rWCzyWTU7UDeebojPTpW9ZmVv9Dn12cg
Example Request - Fetch Wallet Signatures
# Basic request curl -X POST https://api.soltop.sh/wallet/FnmStvzQ27Pm4U8r3M6gPD7mnk6ST6HwraPsoNmYpump/signatures \ -H "Content-Type: application/json" \ -d '{}' # Request with pagination and time filtering curl -X POST https://api.soltop.sh/wallet/FnmStvzQ27Pm4U8r3M6gPD7mnk6ST6HwraPsoNmYpump/signatures \ -H "Content-Type: application/json" \ -d '{ "limit": 50, "start_time": 1729368000, "end_time": 1729371600, "hint_signature": "5BSi6GG6BYes..." }' # Pagination request (second page) curl -X POST https://api.soltop.sh/wallet/FnmStvzQ27Pm4U8r3M6gPD7mnk6ST6HwraPsoNmYpump/signatures \ -H "Content-Type: application/json" \ -d '{ "limit": 50, "before": "3AQ8vVrkH5FAG1GV8Ak1rEUc7eKgNuRGEmpUT5TfixZ9..." }'
Example Request - Enhance Metadata
# Basic request curl -X POST https://api.soltop.sh/enhance-metadata \ -H "Content-Type: application/json" \ -d '{ "signature": "5Pj5fCupXLUePYn18JkY8SrRaWFiUctuDTRwvUy2ML9yvkENLb1QMYbcBGcBXRrSVDjp7RjUwk9a3rLC6gpvtYpZ" }' # Integration example: Get signatures from analyze-trade, then enhance each one # Step 1: Get all transactions around a trade curl -X POST https://api.soltop.sh/analyze-trade \ -H "Content-Type: application/json" \ -d '{ "signature": "myTradeSignature...", "account_id": "marketAddress..." }' # Step 2: For each signature in results_by_slot, get detailed metadata curl -X POST https://api.soltop.sh/enhance-metadata \ -H "Content-Type: application/json" \ -d '{ "signature": "competitorSignatureFromStep1..." }'
Response Format
Analyze Trade Response
{
"success": true,
"data": {
"original_transaction": {
"signature": "pHXgUjY4cVvi5orXuK3b66MBhF2W3MpXruRGKodqTWze...",
"signer": "FnmStvzQ27Pm4U8r3M6gPD7mnk6ST6HwraPsoNmYpump",
"slot": 370537741,
"poh_tick": 23714415424,
"entry_index": 2,
"tx_index": 0,
"timestamp": "2025-10-01 19:22:33",
"is_vote": 0,
"accounts_read_count": 22,
"accounts_written_count": 35
},
"slot_range": {
"from": 370537737,
"to": 370537745,
"range": 4
},
"results_by_slot": [
{
"slot": 370537737,
"slot_offset": -4,
"transactions": [
{
"signature": "abc123...",
"signer": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU",
"poh_tick": 23714000000,
"poh_tick_offset": -415424,
"entry_index": 1,
"tx_index": 5,
"timestamp": "2025-10-01 19:22:30",
"matched_in_read": true,
"matched_in_written": false,
"is_original": false
}
],
"transaction_count": 1
}
],
"summary": {
"total_matching_transactions": 25,
"displayed_in_page": 25,
"slots_with_activity": 6,
"earliest_poh_tick_offset": -500000,
"latest_poh_tick_offset": 450000
}
},
"pagination": {
"current_page": 1,
"total_items": 25,
"has_next_page": false
}
}
Backfill Transaction Response
{
"success": true,
"data": {
"status": "Backfill started",
"query_info": {
"signature": "pHXgUjY4cVvi5orXuK3b66MBhF2W3...",
"account": "FnmStvzQ27Pm4U8r3M6gPD7mnk6ST6HwraPsoNmYpump",
"slot_range": 2,
"request_id": "abc123xyz"
},
"message": "Backfill initiated. Check logs for completion status."
}
}
Get Transaction Details Response
{
"success": true,
"data": {
"signature": "pHXgUjY4cVvi5orXuK3b66MBhF2W3MpXruRGKodqTWze7354iVQ66k1rWCzyWTU7UDeebojPTpW9ZmVv9Dn12cg",
"slot": 374243733,
"blockTime": 1760814534,
"success": true,
"fee": 5000,
"tokens": ["EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", "So11111111111111111111111111111111111111112"],
"leader": "5ZWgXcyqrrNpQHCme5SdC5hCeYb2o3fEJhF7Gok3bTVN",
"client": "jito-solana",
"clientVersion": "1.18.15",
"validatorName": "Jito Validator",
"markets": [
{
"poolAddress": "8sLbNZoA1cfnvMJLPfp98ZLAnFSYCFApfJKMbiXNLwxj",
"account_label": "Pump.fun AMM (Percolator-WSOL) Market",
"account_tags": ["pump.fun amm", "market"]
}
]
}
}
Fetch Wallet Signatures Response
{
"success": true,
"data": {
"signatures": [
{
"signature": "pHXgUjY4cVvi5orXuK3b66MBhF2W3MpXruRGKodqTWze7354iVQ66k1rWCzyWTU7UDeebojPTpW9ZmVv9Dn12cg",
"slot": 374243733,
"blockTime": 1760814534,
"success": true
}
],
"pagination": {
"has_more": true,
"next_before": "5BSi6GG6BYes...",
"returned": 100,
"total_in_window": 1000,
"from_cache": true
},
"metadata": {
"time_window_hours": 168,
"time_window_start": 1729368000,
"time_window_end": 1729371600,
"wallet_address": "FnmStvzQ27Pm4U8r3M6gPD7mnk6ST6HwraPsoNmYpump",
"processing_time_ms": 245,
"cache_key": "wallet|start|end|hint"
}
}
}
Enhance Metadata Response
{
"success": true,
"data": {
"signature": "5Pj5fCupXLUePYn18JkY8SrRaWFiUctuDTRwvUy2ML9yvkENLb1QMYbcBGcBXRrSVDjp7RjUwk9a3rLC6gpvtYpZ",
"slot": 378917547,
"blockTime": 1746479684,
"metadata": {
"fee": 5000,
"err": null,
"compute_units_consumed": 150,
"signer": "7BvfixZx7Rwywf6EJFgRW6acEQ2FLSFJr4n3kLLVeEes",
"leader": "5ZWgXcyqrrNpQHCme5SdC5hCeYb2o3fEJhF7Gok3bTVN",
"client": "jito-solana",
"client_version": "1.18.15",
"validator_name": "Jito Validator",
"balance_changes": {
"spl_token_deltas": [
{
"owner": "7BvfixZx7Rwywf6EJFgRW6acEQ2FLSFJr4n3kLLVeEes",
"mint": "So11111111111111111111111111111111111111112",
"delta_base": "1000000000",
"decimals": 9,
"delta_ui": 1.0,
"account_index": 2
}
],
"sol_deltas": [
{
"pubkey": "7BvfixZx7Rwywf6EJFgRW6acEQ2FLSFJr4n3kLLVeEes",
"delta_lamports": "-10005000",
"delta_sol": -0.010005,
"account_index": 0
}
],
"fee_lamports": 5000,
"summary": {
"total_spl_changes": 1,
"total_sol_changes": 1
}
},
"signer_pre_balance": 1000000000,
"signer_post_balance": 989995000,
"signer_pre_token_balances": [],
"signer_post_token_balances": [
{
"accountIndex": 2,
"mint": "So11111111111111111111111111111111111111112",
"owner": "7BvfixZx7Rwywf6EJFgRW6acEQ2FLSFJr4n3kLLVeEes",
"uiTokenAmount": {
"amount": "1000000000",
"decimals": 9,
"uiAmount": 1.0
}
}
]
},
"processing_time_ms": 123
}
}
Understanding the Response
Enhance Metadata Response Fields
- signature: The transaction signature that was enhanced
- slot/blockTime: When the transaction was processed
- fee: Transaction fee in lamports
- err: Error object if transaction failed, null if successful
- compute_units_consumed: Computational resources used
- signer: The wallet that initiated and signed the transaction
- leader: The validator pubkey that produced the block for this slot
- client: Validator client type (e.g., jito-solana, agave), fetched from Trillium API
- client_version: Version of the validator client software
- validator_name: Human-readable name of the validator
Balance Changes (Signer-Only)
- spl_token_deltas: SPL token balance changes for the signer
- sol_deltas: Native SOL balance changes for the signer
- delta_base: Raw token amount change (string for precision)
- delta_ui: Human-readable amount change (includes decimals)
- delta_lamports/delta_sol: SOL changes in lamports and SOL
- Important: All balance data is filtered to show ONLY the signer's changes
Integration with /analyze-trade
Step 2: For each signature in results_by_slot, call /enhance-metadata
Step 3: Analyze fees, success rates, and balance flows of competitors
• Who traded before/after you and their financial impact
• Transaction fees paid by each participant
• Success/failure rates of competing transactions
• Complete SOL/token flow analysis around your trade
Get Transaction Details Response Fields
- signature: Base58 transaction signature
- slot: Solana slot number when transaction was processed
- blockTime: Unix timestamp of the block
- success: Whether the transaction succeeded (true) or failed (false)
- fee: Transaction fee in lamports
- tokens: Array of token mint addresses involved in the transaction
- leader: The validator pubkey that produced the block for this slot
- client: Validator client type (e.g., jito-solana, agave), fetched from Trillium API
- clientVersion: Version of the validator client software
- validatorName: Human-readable name of the validator
- markets: Array of market/pool information with human-readable labels and tags
Fetch Wallet Signatures Response Fields
- signatures: Array of transaction signatures from the wallet
- signature: Base58 transaction signature
- slot/blockTime: When the transaction was processed
- success: Whether the transaction succeeded or failed
Pagination Fields
- has_more: Whether there are more transactions available
- next_before: Signature to use for the next page (use as "before" parameter)
- returned: Number of transactions returned in this response
- total_in_window: Total number of transactions in the time window
- from_cache: Whether this data came from cache (true) or fresh RPC call (false)
Metadata Fields
- time_window_hours: Search window in hours (always 168, which is 7 days)
- time_window_start/end: Unix timestamps of the actual time window used
- clickhouse_enriched: Number of transactions enriched with ClickHouse data
- missing_from_clickhouse_count: Number of transactions not found in ClickHouse
- cache_key: Internal cache key used for this request
Caching Strategy
The wallet transactions endpoint uses intelligent caching with a 5-minute TTL:
- First request: Fetches all transactions from RPC, caches them, returns first page
- Subsequent requests: Uses cached data (no RPC calls), enriches requested page
- Cache key: Based on wallet_address + time window + hint_signature
- TTL: 5 minutes - after expiration, fresh RPC fetch is performed
poh_tick_offset (Trade Analysis)
- Negative value: Transaction happened BEFORE yours (potential front-runner)
- Zero: Your original transaction
- Positive value: Transaction happened AFTER yours (potential back-runner)
slot_offset (Trade Analysis)
- Negative: Earlier block/slot
- Zero: Same block/slot as your transaction
- Positive: Later block/slot
matched_in_read / matched_in_written (Trade Analysis)
Shows whether the account_id appeared in the transaction's read or write accounts. Both can be true if the account was both read from and written to.
Error Responses
{
"error": "Validation failed",
"details": ["signature format is invalid (expected base58, 87-88 chars)"],
"timestamp": "2025-10-02T15:30:45.123Z"
}
{
"error": "Transaction not found",
"details": "No transaction found with signature: abc123...",
"timestamp": "2025-10-02T15:30:45.123Z"
}
{
"error": "Too many requests",
"message": "Rate limit: 6 requests per minute. Please try again later.",
"retry_after_seconds": 45,
"timestamp": "2025-10-02T15:30:45.123Z"
}
{
"error": "ClickHouse not available",
"details": "Database connection not established",
"timestamp": "2025-10-02T15:30:45.123Z"
}
Use Cases
• slot_offset === 0 (same slot)
• poh_tick_offset < 0 (happened before)
• Sort by poh_tick_offset descending to see closest trades
to understand market activity density.
and tx_index compared to others.
these are likely competing MEV bots.
• How much SOL/tokens each trader gained/lost
• Transaction fees paid by each participant
• Success/failure rates of different strategies
• Complete value flow around your transaction
2. Find transactions with poh_tick_offset > 0 (after yours)
3. Use /enhance-metadata to check if same signer appears before AND after
4. Analyze their balance changes to confirm sandwich profit
Performance Notes
- Average response time: 20-100ms depending on data density
- Data retention: 15 days for detailed transaction data
- Pagination recommended: For active markets, use limit=100 to keep responses fast
Code Examples
JavaScript/Node.js
// MEV Analytics API client const analyzeTradeContext = async (signature, accountId) => { const response = await fetch("https://api.soltop.sh/analyze-trade", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ signature, account_id: accountId, slot_range: 4, }), }); if (!response.ok) { throw new Error(`API error: ${response.status}`); } return await response.json(); }; // Get transaction details client const getTransactionDetails = async (signature) => { const response = await fetch(`https://api.soltop.sh/transaction/${signature}`, { method: "GET", }); if (!response.ok) { throw new Error(`API error: ${response.status}`); } return await response.json(); }; // Fetch wallet signatures client const getWalletSignatures = async (walletAddress, options = {}) => { const response = await fetch(`https://api.soltop.sh/wallet/${walletAddress}/signatures`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(options), }); if (!response.ok) { throw new Error(`API error: ${response.status}`); } return await response.json(); }; // Usage examples const tradeResult = await analyzeTradeContext( "pHXgUjY4cVvi5orXuK3b66MBhF2W3MpXruRGKodqTWze7354iVQ66k1rWCzyWTU7UDeebojPTpW9ZmVv9Dn12cg", "FnmStvzQ27Pm4U8r3M6gPD7mnk6ST6HwraPsoNmYpump" ); const walletSignatures = await getWalletSignatures( "FnmStvzQ27Pm4U8r3M6gPD7mnk6ST6HwraPsoNmYpump" ); const transactionDetails = await getTransactionDetails( "pHXgUjY4cVvi5orXuK3b66MBhF2W3MpXruRGKodqTWze7354iVQ66k1rWCzyWTU7UDeebojPTpW9ZmVv9Dn12cg" ); console.log( `Found ${tradeResult.data.summary.total_matching_transactions} competing transactions` ); console.log( `Wallet has ${walletSignatures.data.metadata.total_in_window} signatures in time window` ); console.log( `Transaction fee: ${transactionDetails.data.fee} lamports` ); // Enhance metadata client const enhanceMetadata = async (signature) => { const response = await fetch("https://api.soltop.sh/enhance-metadata", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ signature, }), }); if (!response.ok) { throw new Error(`API error: ${response.status}`); } return await response.json(); }; // Complete workflow: analyze trade + enhance each competitor const analyzeTradeWithMetadata = async (signature, accountId) => { // Step 1: Get all transactions around the trade const tradeAnalysis = await analyzeTradeContext(signature, accountId); // Step 2: Enhance metadata for each competitor transaction const enhancedTransactions = []; for (const slotGroup of tradeAnalysis.data.results_by_slot) { for (const tx of slotGroup.transactions) { if (!tx.is_original) { // Skip our own transaction const enhanced = await enhanceMetadata(tx.signature); enhancedTransactions.push({ ...tx, metadata: enhanced.data.metadata }); } } } return { tradeAnalysis, enhancedTransactions }; }; // Usage const fullAnalysis = await analyzeTradeWithMetadata( "myTradeSignature...", "marketAddress..." ); console.log(`Found ${fullAnalysis.enhancedTransactions.length} competitor transactions`); fullAnalysis.enhancedTransactions.forEach(tx => { console.log(`${tx.signer}: fee=${tx.metadata.fee}, success=${!tx.metadata.err}`); });
Python
# MEV Analytics API client import requests def analyze_trade_context(signature, account_id, slot_range=4): url = "https://api.soltop.sh/analyze-trade" payload = { "signature": signature, "account_id": account_id, "slot_range": slot_range } response = requests.post(url, json=payload) response.raise_for_status() return response.json() def get_transaction_details(signature): url = f"https://api.soltop.sh/transaction/{signature}" response = requests.get(url) response.raise_for_status() return response.json() def get_wallet_signatures(wallet_address, options=None): url = f"https://api.soltop.sh/wallet/{wallet_address}/signatures" payload = options or {} response = requests.post(url, json=payload) response.raise_for_status() return response.json() # Usage examples trade_result = analyze_trade_context( signature="pHXgUjY4cVvi5orXuK3b66MBhF2W3MpXruRGKodqTWze7354iVQ66k1rWCzyWTU7UDeebojPTpW9ZmVv9Dn12cg", account_id="FnmStvzQ27Pm4U8r3M6gPD7mnk6ST6HwraPsoNmYpump" ) wallet_signatures = get_wallet_signatures( wallet_address="FnmStvzQ27Pm4U8r3M6gPD7mnk6ST6HwraPsoNmYpump" ) transaction_details = get_transaction_details( signature="pHXgUjY4cVvi5orXuK3b66MBhF2W3MpXruRGKodqTWze7354iVQ66k1rWCzyWTU7UDeebojPTpW9ZmVv9Dn12cg" ) print(f"Found {trade_result['data']['summary']['total_matching_transactions']} competing transactions") print(f"Wallet has {wallet_signatures['data']['metadata']['total_in_window']} signatures in time window") print(f"Transaction fee: {transaction_details['data']['fee']} lamports") def enhance_metadata(signature): url = "https://api.soltop.sh/enhance-metadata" payload = {"signature": signature} response = requests.post(url, json=payload) response.raise_for_status() return response.json() # Complete workflow: analyze trade + enhance each competitor def analyze_trade_with_metadata(signature, account_id): # Step 1: Get all transactions around the trade trade_analysis = analyze_trade_context(signature, account_id) # Step 2: Enhance metadata for each competitor transaction enhanced_transactions = [] for slot_group in trade_analysis['data']['results_by_slot']: for tx in slot_group['transactions']: if not tx['is_original']: # Skip our own transaction enhanced = enhance_metadata(tx['signature']) enhanced_transactions.append({ **tx, 'metadata': enhanced['data']['metadata'] }) return {'trade_analysis': trade_analysis, 'enhanced_transactions': enhanced_transactions} # Usage full_analysis = analyze_trade_with_metadata( signature="myTradeSignature...", account_id="marketAddress..." ) print(f"Found {len(full_analysis['enhanced_transactions'])} competitor transactions") for tx in full_analysis['enhanced_transactions']: signer = tx['signer'] fee = tx['metadata']['fee'] success = tx['metadata']['err'] is None print(f"{signer}: fee={fee}, success={success}")
Support
For issues or questions, check:
- Server logs for detailed error messages
- /health endpoint for system status
- /metrics endpoint for database connectivity