Leveraging CrossFi's XFI-Scan API with Python for Blockchain Analytics
Introduction
The CrossFi ecosystem offers a robust API—known as the XFI-Scan API—that allows developers to query detailed transaction data directly from the blockchain. In this article, we’ll build an analytics dashboard using Python. We’ll fetch real transaction data using the official endpoint, process the JSON output, and visualize key metrics with Pandas and Matplotlib. Whether you’re a developer or blockchain enthusiast, this guide provides a step-by-step walkthrough with clear code examples.
Official API Reference:
For detailed API parameters and response structure, please refer to the official XFI-Scan API docs: https://docs.crossfi.org/crossfi-chain/reference/xfi-scan-api
Overview
In this guide, you will learn to:
Set up your Python environment to interact with the XFI-Scan API.
Query transactions using the correct endpoint.
Process the JSON response into a Pandas DataFrame.
Visualize transaction data (such as fees and counts) using Matplotlib.
Assemble these components into a simple, unified analytics dashboard.
Prerequisites
Before starting, ensure you have:
Python 3.7+ installed on your system.
Basic knowledge of Python programming and REST APIs.
The following Python libraries installed:
requests
(to make HTTP calls)pandas
(for data manipulation)matplotlib
(for visualization)
Install these libraries with:
pip install requests pandas matplotlib
API Details
Base URL:
https://test.xfiscan.com/
Endpoint for querying transactions:
GET /api/1.0/txs
Supported Query Parameters:
from_height (string): Block number from.
to_height (string): Block number to.
address (string): Account Address.
addresses (array): Array of account addresses.
txhash (string): Transaction hash.
txhashes (array): Array of transaction hashes.
height (string): Block height.
existsEVM (boolean):
true
for only EVM transactions,false
for Cosmos.messageType (string): Transaction message type.
page (number): Page number for pagination.
limit (number): Number of entities to return.
sort (string): Field to sort by (prefix with "-" for descending order).
A sample JSON output for a transaction query looks like this:
jsonCopyEdit{
"txhash": "fe828e6bb3ae72f9e4be6c082eb78805af0088c0e0e5630846776351cfd82b85",
"addresses": [
"0x8465de71a0c24c358b73a3869b04469706341a07",
"mx1s3jauudqcfxrtzmn5wrfkpzxjurrgxs8sg7923",
"0x06512a7eb230a8856cebe0b1d6077322fd24c01e",
"mx1qegj5l4jxz5g2m8tuzcavpmnyt7jfsq7sfsafw"
],
"auth_info": {
"signer_infos": [
{
"public_key": {
"key": "AopEGZgoDwPpernTw9Waw2InMhPdvdHuSXj+npkm/3FP",
"@type": "/ethermint.crypto.v1.ethsecp256k1.PubKey"
},
"mode_info": {
"single": {
"mode": "SIGN_MODE_DIRECT"
}
},
"sequence": "244988"
}
],
"fee": {
"amount": [
{
"denom": "mpx",
"amount": "1561680000000000000"
}
],
"gas_limit": "156168",
"payer": "",
"granter": ""
}
},
"body": {
"messages": [
{
"inputs": [
{
"address": "mx1s3jauudqcfxrtzmn5wrfkpzxjurrgxs8sg7923",
"coins": [
{
"denom": "mpx",
"amount": "1000000000000000000"
},
{
"denom": "xfi",
"amount": "10000000000000000"
}
]
}
],
"outputs": [
{
"address": "mx1qegj5l4jxz5g2m8tuzcavpmnyt7jfsq7sfsafw",
"coins": [
{
"denom": "mpx",
"amount": "1000000000000000000"
}
]
},
{
"address": "mx1qegj5l4jxz5g2m8tuzcavpmnyt7jfsq7sfsafw",
"coins": [
{
"denom": "xfi",
"amount": "10000000000000000"
}
]
}
],
"@type": "/cosmos.bank.v1beta1.MsgMultiSend"
}
],
"memo": "",
"timeout_height": "0",
"extension_options": [],
"non_critical_extension_options": []
},
"code": 0,
"codespace": "",
"gas_used": "129095",
"gas_wanted": "156168",
"height": 7665269,
"info": "",
"isEVM": false,
"logs": [
{
"msg_index": 0,
"events": [
{
"type": "coin_received",
"attributes": [
{ "key": "receiver", "value": "mx1qegj5l4jxz5g2m8tuzcavpmnyt7jfsq7sfsafw" },
{ "key": "amount", "value": "1000000000000000000mpx" },
{ "key": "receiver", "value": "mx1qegj5l4jxz5g2m8tuzcavpmnyt7jfsq7sfsafw" },
{ "key": "amount", "value": "10000000000000000xfi" }
]
}
// More event objects...
]
}
],
"signatures": [
"6rVCozu8V9USEqoefS+fOEQpMAKulStU7xCKZRd81yMfEOmuoe3D8Mu9urxDsYlRpXT7IlXZCQ2hsPUDct2v9gE="
],
"timestamp": "2025-02-23T10:50:29.194Z",
"xds": []
}
This sample illustrates the structure of each transaction record, including fields such as txhash
, addresses
, detailed auth_info
, the message body under body
, gas usage, block height, logs, signatures, and a timestamp.
Step 3: Building the API Module in Python
Let’s encapsulate our API calls in a module called xfi_scan_api.py.
xfi_scan_api.py:
import requests
# Base URL as provided in the official documentation.
BASE_URL = "https://test.xfiscan.com"
def get_transactions(limit=10, page=1, sort="-height"):
"""
Fetches recent transactions from the XFI-Scan API.
Parameters:
- limit (number): Number of transactions to return.
- page (number): Pagination page number.
- sort (string): Sorting order (e.g., '-height' for descending order).
Returns:
A list of transaction dictionaries from the API response.
"""
endpoint = f"{BASE_URL}/api/1.0/txs"
params = {
"limit": limit,
"page": page,
"sort": sort
}
try:
response = requests.get(endpoint, params=params, timeout=10)
response.raise_for_status() # Raises an error for unsuccessful HTTP status codes.
data = response.json()
return data.get("data", [])
except requests.RequestException as e:
print("Error fetching transactions:", e)
return []
def search_transactions(query, limit=10, page=1):
"""
Searches for transactions matching the given query.
Parameters:
- query (string): The query value (e.g., a transaction hash).
- limit (number): Number of transactions to return.
- page (number): Pagination page number.
Returns:
A list of matching transaction dictionaries.
"""
endpoint = f"{BASE_URL}/api/1.0/txs"
params = {
"txhash": query, # You can also search by address or other parameters.
"limit": limit,
"page": page
}
try:
response = requests.get(endpoint, params=params, timeout=10)
response.raise_for_status()
data = response.json()
return data.get("data", [])
except requests.RequestException as e:
print("Error searching transactions:", e)
return []
if __name__ == "__main__":
# Test fetching transactions
txs = get_transactions(limit=5)
print("Recent Transaction Hashes:")
for tx in txs:
print(tx.get("txhash", "No txhash provided"))
Explanation:
We define the base URL from the docs.
Two functions are provided:
get_transactions
to fetch recent transactions andsearch_transactions
to search by transaction hash (or other parameters).Running this module will print out a few transaction hashes as a test.
Step 4: Processing the JSON Data with Pandas
Next, convert the JSON transaction data into a Pandas DataFrame. Create process_data.py.
process_data.py:
import pandas as pd
from xfi_scan_api import get_transactions
def process_transactions(transactions):
"""
Converts a list of transactions into a Pandas DataFrame.
Extracts key fields: Transaction Hash, Timestamp, Fee, Sender, and Receiver.
The JSON response contains nested fields (like fee under auth_info).
For simplicity, we extract fee from the fee amount in auth_info.
"""
if not transactions:
return pd.DataFrame()
processed = []
for tx in transactions:
fee_info = tx.get("auth_info", {}).get("fee", {}).get("amount", [])
fee_amount = fee_info[0]["amount"] if fee_info else "N/A"
# For this example, we extract sender and receiver from the body messages if available.
messages = tx.get("body", {}).get("messages", [])
sender = messages[0].get("inputs", [{}])[0].get("address", "N/A") if messages else "N/A"
receiver = messages[0].get("outputs", [{}])[0].get("address", "N/A") if messages else "N/A"
processed.append({
"Tx Hash": tx.get("txhash", "N/A"),
"Timestamp": tx.get("timestamp", "N/A"),
"Fee": fee_amount,
"Sender": sender,
"Receiver": receiver,
"Block Height": tx.get("height", "N/A")
})
df = pd.DataFrame(processed)
return df
if __name__ == "__main__":
txs = get_transactions(limit=5)
df_txs = process_transactions(txs)
print("Transactions DataFrame:")
print(df_txs)
Explanation:
This script processes each transaction record.
It extracts the transaction hash, timestamp, fee (from the nested
auth_info
field), sender and receiver addresses (from the first message), and block height.Running process_data.py displays a structured DataFrame of the fetched data.
Step 5: Visualizing Data with Matplotlib
Now, let’s visualize our transaction data. Create visualize_data.py.
visualize_data.py:
import matplotlib.pyplot as plt
import pandas as pd
from process_data import process_transactions
from xfi_scan_api import get_transactions
def plot_transaction_fees(df):
"""
Plots transaction fees for each transaction.
"""
try:
df["Fee"] = pd.to_numeric(df["Fee"], errors="coerce")
except Exception as e:
print("Error converting fee data:", e)
plt.figure(figsize=(10, 6))
plt.plot(df["Tx Hash"], df["Fee"], marker="o", linestyle="--", color="green")
plt.title("Transaction Fees Over Recent Transactions")
plt.xlabel("Transaction Hash")
plt.ylabel("Fee")
plt.xticks(rotation=45, ha="right")
plt.tight_layout()
plt.show()
def plot_transaction_volume(df):
"""
Plots a simple bar chart for the total number of transactions fetched.
"""
volume = len(df)
plt.figure(figsize=(5, 5))
plt.bar(["Transaction Volume"], [volume], color="blue")
plt.title("Number of Recent Transactions")
plt.ylabel("Count")
plt.show()
if __name__ == "__main__":
txs = get_transactions(limit=10)
df_txs = process_transactions(txs)
plot_transaction_fees(df_txs)
plot_transaction_volume(df_txs)
Explanation:
plot_transaction_fees
converts fee data to numeric and plots a line chart using transaction hashes as x-axis labels.plot_transaction_volume
creates a bar chart that simply shows how many transactions were retrieved.Running visualize_data.py will display the visualizations in Matplotlib windows.
Step 6: Assembling the Dashboard
Finally, combine everything into a single dashboard script. Create dashboard.py.
from xfi_scan_api import get_transactions, search_transactions
from process_data import process_transactions
from visualize_data import plot_transaction_fees, plot_transaction_volume
def main():
print("Fetching recent transactions from the XFI-Scan API...")
transactions = get_transactions(limit=10)
# Process transactions into a DataFrame.
df_transactions = process_transactions(transactions)
if df_transactions.empty:
print("No transaction data available.")
else:
print("Transactions Data:")
print(df_transactions)
# Visualize transaction fees and transaction volume.
plot_transaction_fees(df_transactions)
plot_transaction_volume(df_transactions)
# Optional: Allow the user to search for specific transactions.
query = input("Enter a transaction hash to search for (or press Enter to skip): ")
if query:
searched_txs = search_transactions(query)
df_search = process_transactions(searched_txs)
print("Search Results:")
print(df_search)
plot_transaction_fees(df_search)
plot_transaction_volume(df_search)
if __name__ == "__main__":
main()
Explanation:
dashboard.py serves as the entry point.
It first fetches recent transactions, processes them, and prints a DataFrame.
It then visualizes transaction fees and volume.
Optionally, it prompts the user to search for specific transactions and visualizes those results.
Conclusion
In this article, we built a comprehensive Python-based analytics dashboard for the CrossFi ecosystem using the official XFI-Scan API. We:
Accessed the API:
Defined functions in xfi_scan_api.py to query transaction data using the endpointGET /api/1.0/txs
with the base URLhttps://test.xfiscan.com/
.Processed the Data:
Converted the JSON response (which includes detailed fields such astxhash
,addresses
,auth_info
,body
,gas_used
, and more) into a structured Pandas DataFrame using process_data.py.Visualized the Data:
Created visual representations of transaction fees and overall transaction volume with Matplotlib in visualize_data.py.Built a Unified Dashboard:
Integrated all components into dashboard.py, which serves as a single entry point for fetching, processing, and visualizing transaction data.
This project lays a solid foundation for more advanced blockchain analytics in the CrossFi ecosystem. With further enhancements—such as real-time updates, more refined filtering parameters, or even a web-based interface using Flask or Django—you can build a robust monitoring tool tailored to your needs.
By following these steps and leveraging the official XFI-Scan API details, you now have an accurate, working example of how to extract and visualize blockchain data from CrossFi. Happy coding!