Skip to main content

Get Blocks

Query block information on the Aptos blockchain by height or version.

Available Endpoints​

  • GET /blocks/by_height/{block_height} - Get block by height
  • GET /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​

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,
};
}

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.