Get Blocks
Query block information on the Aptos blockchain by height or version.
Available Endpoints​
GET /blocks/by_height/{block_height}
- Get block by heightGET /blocks/by_version/{version}
- Get block by version
When to Use These Methods​
Block queries are essential for:
- Block Explorers - Display block information
- Chain Monitoring - Track block production
- Transaction Verification - Find transaction block details
- Analytics - Analyze block patterns and metrics
Implementation Examples​
- TypeScript
- Python
- Rust
import { Aptos, AptosConfig, Network } from "@aptos-labs/ts-sdk";
const config = new AptosConfig({
network: Network.MAINNET,
fullnode: "https://api-aptos-mainnet.n.dwellir.com/v1/YOUR_API_KEY",
});
const aptos = new Aptos(config);
// Get block by height
async function getBlockByHeight(height: number) {
const response = await fetch(
`https://api-aptos-mainnet.n.dwellir.com/v1/YOUR_API_KEY/blocks/by_height/${height}`,
{
headers: { 'Accept': 'application/json' },
}
);
if (!response.ok) {
if (response.status === 404) {
return null; // Block not found
}
throw new Error(`Failed to get block: ${response.statusText}`);
}
const block = await response.json();
return {
blockHeight: block.block_height,
blockHash: block.block_hash,
blockTimestamp: block.block_timestamp,
firstVersion: block.first_version,
lastVersion: block.last_version,
transactions: block.transactions || [],
};
}
// Get block by version
async function getBlockByVersion(version: number) {
const response = await fetch(
`https://api-aptos-mainnet.n.dwellir.com/v1/YOUR_API_KEY/blocks/by_version/${version}`,
{
headers: { 'Accept': 'application/json' },
}
);
if (!response.ok) {
if (response.status === 404) {
return null;
}
throw new Error(`Failed to get block: ${response.statusText}`);
}
return response.json();
}
// Get latest block
async function getLatestBlock() {
// First get the latest ledger info
const ledgerResponse = await fetch(
`https://api-aptos-mainnet.n.dwellir.com/v1/YOUR_API_KEY`,
{ headers: { 'Accept': 'application/json' } }
);
const ledgerInfo = await ledgerResponse.json();
const latestHeight = ledgerInfo.block_height;
return getBlockByHeight(latestHeight);
}
// Get block range
async function getBlockRange(
startHeight: number,
endHeight: number
): Promise<any[]> {
const blocks = [];
for (let height = startHeight; height <= endHeight; height++) {
try {
const block = await getBlockByHeight(height);
if (block) {
blocks.push(block);
}
} catch (error) {
console.error(`Failed to get block ${height}:`, error);
}
}
return blocks;
}
// Get block with transactions
async function getBlockWithTransactions(height: number) {
const block = await getBlockByHeight(height);
if (!block) {
return null;
}
// Fetch full transaction details if needed
const transactions = [];
if (block.transactions && block.transactions.length > 0) {
for (const txnHash of block.transactions) {
try {
const txn = await aptos.getTransactionByHash({
transactionHash: txnHash
});
transactions.push(txn);
} catch (error) {
console.error(`Failed to get transaction ${txnHash}:`, error);
}
}
}
return {
...block,
transactionDetails: transactions,
};
}
import requests
from typing import Optional, List, Dict
import time
BASE_URL = "https://api-aptos-mainnet.n.dwellir.com/v1/YOUR_API_KEY"
def get_block_by_height(height: int) -> Optional[Dict]:
"""Get block by height"""
try:
response = requests.get(
f"{BASE_URL}/blocks/by_height/{height}",
headers={"Accept": "application/json"}
)
if response.status_code == 404:
return None
response.raise_for_status()
block = response.json()
return {
"block_height": block["block_height"],
"block_hash": block["block_hash"],
"block_timestamp": block["block_timestamp"],
"first_version": block["first_version"],
"last_version": block["last_version"],
"transactions": block.get("transactions", [])
}
except Exception as e:
print(f"Error getting block {height}: {e}")
return None
def get_block_by_version(version: int) -> Optional[Dict]:
"""Get block containing a specific version"""
try:
response = requests.get(
f"{BASE_URL}/blocks/by_version/{version}",
headers={"Accept": "application/json"}
)
if response.status_code == 404:
return None
response.raise_for_status()
return response.json()
except Exception as e:
print(f"Error getting block by version {version}: {e}")
return None
def get_latest_block() -> Optional[Dict]:
"""Get the latest block"""
# Get ledger info
response = requests.get(
BASE_URL,
headers={"Accept": "application/json"}
)
response.raise_for_status()
ledger_info = response.json()
latest_height = ledger_info["block_height"]
return get_block_by_height(latest_height)
def get_block_range(
start_height: int,
end_height: int
) -> List[Dict]:
"""Get a range of blocks"""
blocks = []
for height in range(start_height, end_height + 1):
block = get_block_by_height(height)
if block:
blocks.append(block)
time.sleep(0.1) # Rate limiting
return blocks
def monitor_new_blocks(callback, interval: int = 1):
"""Monitor for new blocks"""
last_height = None
while True:
try:
latest_block = get_latest_block()
if latest_block:
current_height = latest_block["block_height"]
if last_height and current_height > last_height:
# New blocks detected
for height in range(last_height + 1, current_height + 1):
block = get_block_by_height(height)
if block:
callback(block)
last_height = current_height
except Exception as e:
print(f"Monitor error: {e}")
time.sleep(interval)
def analyze_block_metrics(blocks: List[Dict]) -> Dict:
"""Analyze metrics for a set of blocks"""
if not blocks:
return {}
total_transactions = sum(
len(b.get("transactions", [])) for b in blocks
)
timestamps = [int(b["block_timestamp"]) for b in blocks]
time_diffs = [
timestamps[i+1] - timestamps[i]
for i in range(len(timestamps)-1)
]
avg_block_time = sum(time_diffs) / len(time_diffs) if time_diffs else 0
return {
"total_blocks": len(blocks),
"total_transactions": total_transactions,
"avg_transactions_per_block": total_transactions / len(blocks),
"avg_block_time_microseconds": avg_block_time,
"avg_block_time_seconds": avg_block_time / 1_000_000,
"first_block": blocks[0]["block_height"],
"last_block": blocks[-1]["block_height"],
"time_span_seconds": (timestamps[-1] - timestamps[0]) / 1_000_000
}
use serde::{Deserialize, Serialize};
use reqwest;
#[derive(Debug, Serialize, Deserialize)]
struct Block {
block_height: String,
block_hash: String,
block_timestamp: String,
first_version: String,
last_version: String,
transactions: Option<Vec<String>>,
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let base_url = "https://api-aptos-mainnet.n.dwellir.com/v1/YOUR_API_KEY";
// Get block by height
async fn get_block_by_height(
base_url: &str,
height: u64,
) -> Result<Option<Block>, Box<dyn std::error::Error>> {
let url = format!("{}/blocks/by_height/{}", base_url, height);
let response = reqwest::get(&url).await?;
if response.status().as_u16() == 404 {
return Ok(None);
}
let block = response.json::<Block>().await?;
Ok(Some(block))
}
// Get block by version
async fn get_block_by_version(
base_url: &str,
version: u64,
) -> Result<Option<Block>, Box<dyn std::error::Error>> {
let url = format!("{}/blocks/by_version/{}", base_url, version);
let response = reqwest::get(&url).await?;
if response.status().as_u16() == 404 {
return Ok(None);
}
let block = response.json::<Block>().await?;
Ok(Some(block))
}
// Example usage
if let Some(block) = get_block_by_height(base_url, 1000).await? {
println!("Block hash: {}", block.block_hash);
println!("Timestamp: {}", block.block_timestamp);
if let Some(txns) = block.transactions {
println!("Transactions: {}", txns.len());
}
}
Ok(())
}
Common Use Cases​
1. Block Explorer Display​
Build a block explorer interface:
interface BlockInfo {
height: string;
hash: string;
timestamp: Date;
transactionCount: number;
firstVersion: string;
lastVersion: string;
blockTime?: number;
gasUsed?: string;
}
async function getBlockInfo(height: number): Promise<BlockInfo | null> {
const block = await getBlockByHeight(height);
if (!block) {
return null;
}
// Get previous block for block time calculation
let blockTime: number | undefined;
if (height > 0) {
const prevBlock = await getBlockByHeight(height - 1);
if (prevBlock) {
blockTime = (
parseInt(block.blockTimestamp) -
parseInt(prevBlock.blockTimestamp)
) / 1_000_000; // Convert to seconds
}
}
return {
height: block.blockHeight,
hash: block.blockHash,
timestamp: new Date(parseInt(block.blockTimestamp) / 1000),
transactionCount: block.transactions?.length || 0,
firstVersion: block.firstVersion,
lastVersion: block.lastVersion,
blockTime,
};
}
async function getRecentBlocks(count: number = 10): Promise<BlockInfo[]> {
const latest = await getLatestBlock();
if (!latest) return [];
const startHeight = Math.max(0, parseInt(latest.blockHeight) - count + 1);
const endHeight = parseInt(latest.blockHeight);
const blocks = await getBlockRange(startHeight, endHeight);
return blocks.map((block, index) => {
const prevBlock = index > 0 ? blocks[index - 1] : null;
const blockTime = prevBlock ? (
parseInt(block.blockTimestamp) -
parseInt(prevBlock.blockTimestamp)
) / 1_000_000 : undefined;
return {
height: block.blockHeight,
hash: block.blockHash,
timestamp: new Date(parseInt(block.blockTimestamp) / 1000),
transactionCount: block.transactions?.length || 0,
firstVersion: block.firstVersion,
lastVersion: block.lastVersion,
blockTime,
};
}).reverse(); // Most recent first
}
2. Block Production Monitoring​
Monitor block production health:
class BlockMonitor {
private recentBlocks: any[] = [];
private maxBlocks = 100;
async checkBlockProduction(): Promise<{
healthy: boolean;
averageBlockTime: number;
missedBlocks: number[];
alerts: string[];
}> {
const alerts: string[] = [];
const latestBlock = await getLatestBlock();
if (!latestBlock) {
return {
healthy: false,
averageBlockTime: 0,
missedBlocks: [],
alerts: ["Cannot fetch latest block"],
};
}
// Get last 20 blocks
const startHeight = Math.max(
0,
parseInt(latestBlock.blockHeight) - 19
);
const blocks = await getBlockRange(
startHeight,
parseInt(latestBlock.blockHeight)
);
// Calculate block times
const blockTimes: number[] = [];
const missedBlocks: number[] = [];
for (let i = 1; i < blocks.length; i++) {
const timeDiff = (
parseInt(blocks[i].blockTimestamp) -
parseInt(blocks[i-1].blockTimestamp)
) / 1_000_000; // Convert to seconds
blockTimes.push(timeDiff);
// Check for missed blocks (> 5 seconds)
if (timeDiff > 5) {
missedBlocks.push(parseInt(blocks[i].blockHeight));
alerts.push(
`Long block time at height ${blocks[i].blockHeight}: ${timeDiff}s`
);
}
}
const averageBlockTime = blockTimes.length > 0
? blockTimes.reduce((a, b) => a + b) / blockTimes.length
: 0;
// Health check
const healthy = averageBlockTime < 2 && missedBlocks.length === 0;
if (averageBlockTime > 1.5) {
alerts.push(`High average block time: ${averageBlockTime.toFixed(2)}s`);
}
return {
healthy,
averageBlockTime,
missedBlocks,
alerts,
};
}
}
3. Transaction Finality Tracking​
Track transaction finality:
async function getTransactionFinality(txnHash: string): Promise<{
included: boolean;
blockHeight?: number;
blockHash?: string;
confirmations?: number;
finalized?: boolean;
}> {
try {
// Get transaction details
const txn = await aptos.getTransactionByHash({
transactionHash: txnHash
});
if (!txn) {
return { included: false };
}
// Get the block containing the transaction
const block = await getBlockByVersion(txn.version);
if (!block) {
return { included: false };
}
// Get current block height
const latestBlock = await getLatestBlock();
const currentHeight = parseInt(latestBlock.blockHeight);
const txnBlockHeight = parseInt(block.block_height);
const confirmations = currentHeight - txnBlockHeight;
return {
included: true,
blockHeight: txnBlockHeight,
blockHash: block.block_hash,
confirmations,
finalized: confirmations >= 10, // Consider finalized after 10 blocks
};
} catch (error) {
console.error("Error checking transaction finality:", error);
return { included: false };
}
}
4. Block Analytics​
Analyze block patterns and metrics:
async function analyzeBlockMetrics(
startHeight: number,
endHeight: number
): Promise<any> {
const blocks = await getBlockRange(startHeight, endHeight);
if (blocks.length === 0) {
return null;
}
// Calculate metrics
const metrics = {
totalBlocks: blocks.length,
timeRange: {
start: new Date(parseInt(blocks[0].blockTimestamp) / 1000),
end: new Date(parseInt(blocks[blocks.length - 1].blockTimestamp) / 1000),
},
// Transaction metrics
totalTransactions: blocks.reduce(
(sum, b) => sum + (b.transactions?.length || 0),
0
),
averageTransactionsPerBlock: 0,
maxTransactionsInBlock: 0,
minTransactionsInBlock: Infinity,
emptyBlocks: 0,
// Time metrics
averageBlockTime: 0,
maxBlockTime: 0,
minBlockTime: Infinity,
// Distribution
transactionDistribution: new Map<number, number>(),
};
// Calculate per-block metrics
const blockTimes: number[] = [];
for (let i = 0; i < blocks.length; i++) {
const block = blocks[i];
const txCount = block.transactions?.length || 0;
// Transaction metrics
metrics.maxTransactionsInBlock = Math.max(
metrics.maxTransactionsInBlock,
txCount
);
metrics.minTransactionsInBlock = Math.min(
metrics.minTransactionsInBlock,
txCount
);
if (txCount === 0) {
metrics.emptyBlocks++;
}
// Distribution
const bucket = Math.floor(txCount / 10) * 10;
metrics.transactionDistribution.set(
bucket,
(metrics.transactionDistribution.get(bucket) || 0) + 1
);
// Block time
if (i > 0) {
const blockTime = (
parseInt(block.blockTimestamp) -
parseInt(blocks[i-1].blockTimestamp)
) / 1_000_000;
blockTimes.push(blockTime);
metrics.maxBlockTime = Math.max(metrics.maxBlockTime, blockTime);
metrics.minBlockTime = Math.min(metrics.minBlockTime, blockTime);
}
}
// Calculate averages
metrics.averageTransactionsPerBlock =
metrics.totalTransactions / metrics.totalBlocks;
metrics.averageBlockTime = blockTimes.length > 0
? blockTimes.reduce((a, b) => a + b) / blockTimes.length
: 0;
return {
...metrics,
transactionDistribution: Object.fromEntries(metrics.transactionDistribution),
};
}
Real-time Block Streaming​
class BlockStream {
private lastHeight: number | null = null;
private subscribers: ((block: any) => void)[] = [];
private interval: NodeJS.Timeout | null = null;
subscribe(callback: (block: any) => void) {
this.subscribers.push(callback);
}
async start(pollInterval: number = 1000) {
this.interval = setInterval(async () => {
try {
const latest = await getLatestBlock();
if (!latest) return;
const currentHeight = parseInt(latest.blockHeight);
if (this.lastHeight === null) {
this.lastHeight = currentHeight;
} else if (currentHeight > this.lastHeight) {
// Fetch new blocks
for (let h = this.lastHeight + 1; h <= currentHeight; h++) {
const block = await getBlockByHeight(h);
if (block) {
// Notify subscribers
this.subscribers.forEach(cb => cb(block));
}
}
this.lastHeight = currentHeight;
}
} catch (error) {
console.error("Block stream error:", error);
}
}, pollInterval);
}
stop() {
if (this.interval) {
clearInterval(this.interval);
this.interval = null;
}
}
}
// Usage
const stream = new BlockStream();
stream.subscribe((block) => {
console.log(`New block: ${block.blockHeight}`);
console.log(`Transactions: ${block.transactions?.length || 0}`);
});
stream.start();
Need help? Contact our support team or check the Aptos documentation.