Block Data
Description
Section titled “Description”This example demonstrates how to retrieve block information using the AlgodClient methods: block(), blockHash(), and blockTxIds().
Prerequisites
Section titled “Prerequisites”- LocalNet running (via
algokit localnet start)
Run This Example
Section titled “Run This Example”From the repository root:
cd examplesnpm run example algod_client/08-block-data.ts/** * Example: Block Data * * This example demonstrates how to retrieve block information using * the AlgodClient methods: block(), blockHash(), and blockTxIds(). * * Prerequisites: * - LocalNet running (via `algokit localnet start`) */
import { algo } from '@algorandfoundation/algokit-utils';import { createAlgodClient, createAlgorandClient, formatMicroAlgo, getFundedAccount, printHeader, printInfo, printStep, printSuccess, shortenAddress,} from '../shared/utils.js';
/** * Format a Unix timestamp to a human-readable date string */function formatTimestamp(timestamp: bigint): string { const date = new Date(Number(timestamp) * 1000); return date.toISOString();}
/** * Format bytes as a hex string */function bytesToHex(bytes: Uint8Array): string { return Buffer.from(bytes).toString('hex');}
async function main() { printHeader('Block Data Example');
// Create an Algod client connected to LocalNet const algod = createAlgodClient(); const algorand = createAlgorandClient();
// ========================================================================= // Step 1: Get the latest round from status() // ========================================================================= printStep(1, 'Getting current node status to find the latest round');
const nodeStatus = await algod.status(); let latestRound = nodeStatus.lastRound;
printSuccess(`Current node status retrieved`); printInfo(` - Latest round: ${latestRound}`);
// On LocalNet dev mode, lastRound may be 0 if no transactions have been submitted // Let's submit a transaction to create a block with transactions if (latestRound === 0n) { printInfo('Round is 0 (LocalNet dev mode). Submitting a transaction to create a block...');
const sender = await getFundedAccount(algorand); const receiver = algorand.account.random();
await algorand.send.payment({ sender: sender.addr, receiver: receiver.addr, amount: algo(1), // 1 ALGO });
// Get updated status const updatedStatus = await algod.status(); latestRound = updatedStatus.lastRound; printSuccess(`Transaction submitted. New latest round: ${latestRound}`); }
// ========================================================================= // Step 2: Get full block data with block(round) // ========================================================================= printStep(2, `Getting full block data for round ${latestRound} with block()`);
const blockResponse = await algod.block(latestRound); const block = blockResponse.block;
printSuccess('Block data retrieved successfully!'); printInfo(''); printInfo('Block Header Fields:'); printInfo(` - Round: ${block.header.round}`); printInfo( ` - Timestamp: ${formatTimestamp(block.header.timestamp)} (${block.header.timestamp})`, ); printInfo( ` - Previous Block Hash: ${bytesToHex(block.header.previousBlockHash).substring(0, 16)}...`, ); printInfo(` - Seed: ${bytesToHex(block.header.seed).substring(0, 16)}...`); printInfo(` - Genesis ID: ${block.header.genesisId}`); printInfo(` - Genesis Hash: ${bytesToHex(block.header.genesisHash).substring(0, 16)}...`);
if (block.header.proposer) { printInfo(` - Proposer: ${shortenAddress(block.header.proposer.toString())}`); }
if (block.header.feesCollected !== undefined) { printInfo(` - Fees Collected: ${formatMicroAlgo(block.header.feesCollected)}`); }
if (block.header.txnCounter !== undefined) { printInfo(` - Transaction Counter: ${block.header.txnCounter}`); }
// Display transaction commitment hashes printInfo(''); printInfo('Transaction Commitments:'); printInfo( ` - SHA512/256: ${bytesToHex(block.header.txnCommitments.nativeSha512_256Commitment).substring(0, 32)}...`, ); if (block.header.txnCommitments.sha256Commitment) { printInfo( ` - SHA256: ${bytesToHex(block.header.txnCommitments.sha256Commitment).substring(0, 32)}...`, ); }
// Display reward state printInfo(''); printInfo('Reward State:'); printInfo(` - Fee Sink: ${shortenAddress(block.header.rewardState.feeSink.toString())}`); printInfo(` - Rewards Pool: ${shortenAddress(block.header.rewardState.rewardsPool.toString())}`); printInfo(` - Rewards Level: ${block.header.rewardState.rewardsLevel}`); printInfo(` - Rewards Rate: ${block.header.rewardState.rewardsRate}`);
// Display upgrade state printInfo(''); printInfo('Upgrade State:'); printInfo(` - Current Protocol: ${block.header.upgradeState.currentProtocol}`); if (block.header.upgradeState.nextProtocol) { printInfo(` - Next Protocol: ${block.header.upgradeState.nextProtocol}`); }
// ========================================================================= // Step 3: Explore transactions in the block (payset) // ========================================================================= printStep(3, 'Exploring transactions in the block (payset)');
const transactions = block.payset; printInfo(`Number of transactions in block: ${transactions.length}`);
if (transactions.length > 0) { printInfo(''); printInfo('Transaction Details:');
for (let i = 0; i < Math.min(transactions.length, 5); i++) { const txnInBlock = transactions[i]; const signedTxn = txnInBlock.signedTxn.signedTxn; const txn = signedTxn.txn;
printInfo(''); printInfo(` Transaction ${i + 1}:`); printInfo(` - Type: ${txn.type}`); printInfo(` - Sender: ${shortenAddress(txn.sender.toString())}`); printInfo(` - Fee: ${formatMicroAlgo(txn.fee ?? 0n)}`); printInfo(` - First Valid: ${txn.firstValid}`); printInfo(` - Last Valid: ${txn.lastValid}`);
// Show payment-specific fields if (txn.type === 'pay' && txn.payment) { printInfo(` - Receiver: ${shortenAddress(txn.payment.receiver.toString())}`); printInfo(` - Amount: ${formatMicroAlgo(txn.payment.amount)}`); }
// Show apply data if available const applyData = txnInBlock.signedTxn.applyData; if (applyData) { if (applyData.senderRewards !== undefined && applyData.senderRewards > 0n) { printInfo(` - Sender Rewards: ${formatMicroAlgo(applyData.senderRewards)}`); } if (applyData.receiverRewards !== undefined && applyData.receiverRewards > 0n) { printInfo(` - Receiver Rewards: ${formatMicroAlgo(applyData.receiverRewards)}`); } }
// Show hasGenesisId and hasGenesisHash flags printInfo(` - Has Genesis ID: ${txnInBlock.hasGenesisId ?? 'not set'}`); printInfo(` - Has Genesis Hash: ${txnInBlock.hasGenesisHash ?? 'not set'}`); }
if (transactions.length > 5) { printInfo(` ... and ${transactions.length - 5} more transactions`); } } else { printInfo('This block contains no transactions.'); printInfo('On LocalNet in dev mode, blocks are only created when transactions are submitted.'); }
// ========================================================================= // Step 4: Get block hash with blockHash(round) // ========================================================================= printStep(4, `Getting block hash for round ${latestRound} with blockHash()`);
const blockHashResponse = await algod.blockHash(latestRound);
printSuccess('Block hash retrieved successfully!'); printInfo(` - Block Hash: ${blockHashResponse.blockHash}`); printInfo('The block hash is a base64-encoded SHA256 hash of the block header.'); printInfo('It uniquely identifies this block and is used for cryptographic verification.');
// ========================================================================= // Step 5: Get transaction IDs in block with blockTxIds(round) // ========================================================================= printStep(5, `Getting transaction IDs for round ${latestRound} with blockTxIds()`);
const blockTxIdsResponse = await algod.blockTxIds(latestRound); const txIds = blockTxIdsResponse.blockTxIds;
printSuccess(`Transaction IDs retrieved successfully!`); printInfo(` - Number of transactions: ${txIds.length}`);
if (txIds.length > 0) { printInfo(''); printInfo('Transaction IDs:'); for (let i = 0; i < Math.min(txIds.length, 5); i++) { printInfo(` ${i + 1}. ${txIds[i]}`); } if (txIds.length > 5) { printInfo(` ... and ${txIds.length - 5} more`); } printInfo('Transaction IDs can be used with pendingTransactionInformation() to get details.'); } else { printInfo('This block contains no transactions.'); }
// ========================================================================= // Step 6: Demonstrate header-only mode // ========================================================================= printStep(6, 'Getting block header only (without transactions)');
const headerOnlyResponse = await algod.block(latestRound, { headerOnly: true });
printSuccess('Block header retrieved (header-only mode)!'); printInfo(` - Round: ${headerOnlyResponse.block.header.round}`); printInfo(` - Timestamp: ${formatTimestamp(headerOnlyResponse.block.header.timestamp)}`); printInfo(` - Transactions in payset: ${headerOnlyResponse.block.payset.length}`); printInfo('With headerOnly=true, the payset is empty, reducing response size.'); printInfo('Use this when you only need block metadata, not transaction details.');
// ========================================================================= // Step 7: Compare blocks across rounds (if multiple rounds exist) // ========================================================================= if (latestRound > 1n) { printStep(7, 'Comparing blocks across multiple rounds');
const previousRound = latestRound - 1n; const previousBlockResponse = await algod.block(previousRound); const previousBlock = previousBlockResponse.block;
printInfo('Comparing consecutive blocks:'); printInfo(''); printInfo(` Round ${previousRound}:`); printInfo(` - Timestamp: ${formatTimestamp(previousBlock.header.timestamp)}`); printInfo(` - Transactions: ${previousBlock.payset.length}`); printInfo( ` - Block Hash: ${bytesToHex(previousBlock.header.txnCommitments.nativeSha512_256Commitment).substring(0, 16)}...`, ); printInfo(''); printInfo(` Round ${latestRound}:`); printInfo(` - Timestamp: ${formatTimestamp(block.header.timestamp)}`); printInfo(` - Transactions: ${block.payset.length}`); printInfo( ` - Previous Block Hash: ${bytesToHex(block.header.previousBlockHash).substring(0, 16)}...`, );
// Verify chain linkage printInfo('Each block contains the hash of the previous block, forming a chain.'); }
// ========================================================================= // Summary // ========================================================================= printHeader('Summary'); printInfo('This example demonstrated:'); printInfo(' 1. status() - Get the latest round number'); printInfo(' 2. block(round) - Get full block data including header and transactions'); printInfo(' 3. blockHash(round) - Get just the block hash for verification'); printInfo(' 4. blockTxIds(round) - Get transaction IDs without full transaction data'); printInfo(' 5. block(round, { headerOnly: true }) - Get header without transactions'); printInfo(''); printInfo('Key block structure:'); printInfo(' - BlockResponse.block.header - Block metadata (round, timestamp, hashes, etc.)'); printInfo(' - BlockResponse.block.payset - Array of SignedTxnInBlock'); printInfo(' - BlockHashResponse.blockHash - Base64-encoded block hash'); printInfo(' - BlockTxidsResponse.blockTxIds - Array of transaction IDs'); printInfo(''); printInfo('Important header fields:'); printInfo(' - round: Block number'); printInfo(' - timestamp: Unix timestamp (seconds since epoch)'); printInfo(' - previousBlockHash: Links to prior block (chain integrity)'); printInfo(' - seed: VRF seed for sortition'); printInfo(' - txnCommitments: Merkle root of transactions'); printInfo(' - rewardState: Fee sink, rewards pool, and reward rates'); printInfo(' - upgradeState: Current and pending protocol versions');}
main().catch(error => { console.error('Fatal error:', error); process.exit(1);});Other examples in Algod Client
Section titled “Other examples in Algod Client”- Node Health and Status
- Version and Genesis Information
- Ledger Supply Information
- Account Information
- Transaction Parameters
- Send and Confirm Transaction
- Pending Transactions
- Block Data
- Asset Information
- Application Information
- Application Boxes
- TEAL Compile and Disassemble
- Transaction Simulation
- Ledger State Deltas
- Transaction Proof
- Light Block Header Proof
- State Proof
- DevMode Timestamp Offset
- Sync Round Management