Block Operations
Overview
The provider exposes methods for retrieving and analyzing block data from the OP_NET network. Blocks can be fetched individually by number, hash, or checksum, or in batches for efficient multi-block queries. Each block contains height, timestamp, transaction data, and network metadata, enabling applications to track blockchain state, analyze historical data, and monitor for new blocks.
Fetching Blocks
Getting Current Block Number
The getBlockNumber() method returns the latest block height on the network. This is useful for tracking chain progress, calculating confirmations, and determining the current state of the blockchain.
import { JSONRpcProvider } from 'opnet';
import { networks } from '@btc-vision/bitcoin';
const network = networks.regtest;
const provider = new JSONRpcProvider({ url: 'https://regtest.opnet.org', network });
const blockNumber = await provider.getBlockNumber();
console.log('Current block:', blockNumber);Getting Block by Number
The getBlock() method retrieves a block by its height.
const block = await provider.getBlock(123456);
console.log('Block info:');
console.log(' Height:', block.height);
console.log(' Hash:', block.hash);
console.log(' Time:', new Date(block.time * 1000));
console.log(' TX count:', block.txCount);Getting Block by Hash
Blocks can also be retrieved by their hash using the getBlockByHash() method. This is useful when referencing a specific block from transaction receipts or external data sources.
const block = await provider.getBlockByHash(
'00000000000000000001a2b3c4d5e6f...'
);
console.log('Block height:', block.height);Getting Block by Checksum
The getBlockByChecksum() method retrieves a block using its OP_NET checksum. Checksums provide an additional verification mechanism specific to the OP_NET protocol, ensuring block integrity beyond the standard Bitcoin block hash.
const block = await provider.getBlockByChecksum(
'0xabcdef123456...'
);
console.log('Block:', block.height);Getting Block with Transactions
By default, block retrieval returns only metadata without transaction details. Setting the prefetchTxs parameter to true includes the full transaction data in the response, enabling immediate access to all transactions within the block without additional queries.
// Prefetch transactions for faster access
const block = await provider.getBlock(123456, true);
console.log('Transactions:', block.transactions.length);
for (const tx of block.transactions) {
console.log(' TX:', tx.hash);
}Fetching Multiple Blocks
The getBlocks() method retrieves multiple blocks in a single request, accepting an array of block numbers or hashes. This approach significantly reduces network overhead compared to fetching blocks individually, making it ideal for batch processing and historical data analysis.
const blockNumbers = [100, 101, 102, 103, 104];
const blocks = await provider.getBlocks(blockNumbers);
for (const block of blocks) {
console.log(`Block ${block.height}: ${block.txCount} transactions`);
}Working with Block Data
Getting Deployed Contracts in Block
Each block contains a list of contracts deployed during that block's execution. The deployments property provides an array of contract addresses, enabling applications to track new deployments and index contract creation events across the network.
async function getDeploymentsInBlock(
provider: JSONRpcProvider,
blockNumber: number
): Promise<Address[]> {
const block = await provider.getBlock(blockNumber, true);
return block.deployments;
}
// Usage
const deployments = await getDeploymentsInBlock(provider, 123456);
console.log('Deployed contracts:', deployments.length);
for (const addr of deployments) {
console.log(' Contract:', addr.toHex());
}Analyze Block Gas Usage
Each block contains gas metrics that provide insight into network utilization and fee dynamics. The gasUsed property indicates the total gas consumed by all transactions in the block, while baseGas reflects the minimum gas price for inclusion. The ema (exponential moving average) tracks gas usage trends over time, useful for fee estimation and network congestion analysis.
async function analyzeBlockGas(
provider: JSONRpcProvider,
blockNumber: number
): Promise<{
gasUsed: bigint;
baseGas: bigint;
ema: bigint;
}> {
const block = await provider.getBlock(blockNumber);
return {
gasUsed: block.gasUsed,
baseGas: block.baseGas,
ema: block.ema,
};
}
// Usage
const gasInfo = await analyzeBlockGas(provider, 123456);
console.log('Gas used:', gasInfo.gasUsed);
console.log('Base gas:', gasInfo.baseGas);
console.log('EMA:', gasInfo.ema);Find Block by Time
The provider does not offer a direct method to retrieve a block by timestamp. However, a binary search algorithm can efficiently locate the block closest to a target time by comparing block timestamps. This approach is useful for historical analysis, event correlation, and time-based data retrieval.
async function findBlockByTime(
provider: JSONRpcProvider,
targetTime: Date
): Promise<Block | null> {
const targetTimestamp = Math.floor(targetTime.getTime() / 1000);
const currentBlock = await provider.getBlockNumber();
// Binary search for block
let low = 1n;
let high = currentBlock;
while (low <= high) {
const mid = (low + high) / 2n;
const block = await provider.getBlock(mid);
if (block.time === targetTimestamp) {
return block;
} else if (block.time < targetTimestamp) {
low = mid + 1n;
} else {
high = mid - 1n;
}
}
// Return closest block
return provider.getBlock(low);
}Block Monitoring
For near real-time block monitoring, use the polling approach. The getBlockNumber() method can be called periodically to detect new blocks and fetch them as they arrive.
async function monitorBlocks(
provider: JSONRpcProvider,
callback: (block: Block) => void,
intervalMs: number = 10000
): Promise<() => void> {
let lastBlock = await provider.getBlockNumber();
const intervalId = setInterval(async () => {
try {
const currentBlock = await provider.getBlockNumber();
if (currentBlock > lastBlock) {
// Fetch new blocks
for (let i = lastBlock + 1n; i <= currentBlock; i++) {
const block = await provider.getBlock(i);
callback(block);
}
lastBlock = currentBlock;
}
} catch (error) {
console.error('Error monitoring blocks:', error);
}
}, intervalMs);
return () => clearInterval(intervalId);
}
// Usage
const stopMonitoring = await monitorBlocks(provider, (block) => {
console.log(`New block: ${block.height} with ${block.txCount} transactions`);
});
// Later: stop monitoring
// stopMonitoring();Complete Block Service
class BlockService {
private provider: JSONRpcProvider;
private blockCache: Map<string, Block> = new Map();
constructor(provider: JSONRpcProvider) {
this.provider = provider;
}
async getCurrentHeight(): Promise<bigint> {
return this.provider.getBlockNumber();
}
async getBlock(blockNumberOrHash: number | string): Promise<Block> {
const cacheKey = String(blockNumberOrHash);
if (this.blockCache.has(cacheKey)) {
return this.blockCache.get(cacheKey)!;
}
const block = await this.provider.getBlock(blockNumberOrHash);
this.blockCache.set(cacheKey, block);
this.blockCache.set(block.hash, block);
return block;
}
async getBlocksInRange(
start: number,
end: number
): Promise<Block[]> {
const numbers: number[] = [];
for (let i = start; i <= end; i++) {
numbers.push(i);
}
return this.provider.getBlocks(numbers);
}
async getLatestBlocks(count: number): Promise<Block[]> {
const current = await this.getCurrentHeight();
const start = Number(current) - count + 1;
return this.getBlocksInRange(Math.max(1, start), Number(current));
}
async getBlockTransactions(
blockNumber: number
): Promise<TransactionBase[]> {
const block = await this.provider.getBlock(blockNumber, true);
return block.transactions;
}
async getBlockDeployments(blockNumber: number): Promise<Address[]> {
const block = await this.provider.getBlock(blockNumber, true);
return block.deployments;
}
clearCache(): void {
this.blockCache.clear();
}
}
// Usage
const blockService = new BlockService(provider);
const height = await blockService.getCurrentHeight();
console.log('Current height:', height);
const latestBlocks = await blockService.getLatestBlocks(10);
console.log('Latest 10 blocks:', latestBlocks.map(b => b.height));
const deployments = await blockService.getBlockDeployments(123456);
console.log('Deployments:', deployments.length);