Skip to content

Parse blockchain history

Blockchain parsing is the workflow of iterating Layer 1 blocks or operations to build an index, audit log, monitor, synchronizer or replay tool.

@beblurt/dblurt exposes this through client.blockchain: getBlockNumbers(), getBlocks(), getBlockStream(), getOperations() and getOperationsStream().

Use this guide when your code needs more than a single blockchain query.

Choose the parsing surface

GoalUseWhy
Persist block heights onlygetBlockNumbers()smallest payload and easiest checkpointing
Inspect full blocks with transactionsgetBlocks()async iterator for block processors
Pipe blocks into Node stream toolinggetBlockStream()stream integration for existing Node pipelines
Process flattened applied operationsgetOperations()async iterator over operations in block order
Pipe operations into Node stream toolinggetOperationsStream()stream integration for operation consumers

For exact options and return types, use the API reference.

Use irreversible mode by default

Most parsers should start with irreversible blocks. Latest-head parsing can see blocks that later change during fork resolution.

ts
import { BlockchainMode, Client } from '@beblurt/dblurt';

const client = new Client(['https://rpc.blurt.blog']);
const latest = await client.blockchain.getCurrentBlockNum(BlockchainMode.Irreversible);

Use latest mode only when your application explicitly handles reorg risk.

Parse a bounded block range

Keep examples and jobs bounded unless you are building a long-running daemon.

ts
import { BlockchainMode, Client } from '@beblurt/dblurt';

const client = new Client(['https://rpc.blurt.blog']);
const irreversible = await client.blockchain.getCurrentBlockNum(BlockchainMode.Irreversible);

for await (const block of client.blockchain.getBlocks({
    from: irreversible - 3,
    to: irreversible - 1,
    mode: BlockchainMode.Irreversible
})) {
    console.log(block.witness, block.transactions.length);
}

The range is inclusive. Store the last successfully processed block number in your application so a parser can resume safely.

Parse operations instead of whole blocks

If your parser cares about actions rather than block metadata, use the operation iterator.

ts
for await (const operation of client.blockchain.getOperations({
    from: irreversible - 3,
    to: irreversible - 1,
    mode: BlockchainMode.Irreversible
})) {
    console.log(operation.op[0]);
}

Operations are yielded in block order. If your application needs transaction context, parse whole blocks and inspect transactions directly.

Use Node streams when the rest of your pipeline is stream-based

getBlockStream() and getOperationsStream() expose the same parsing model as Node readable streams.

ts
const stream = client.blockchain.getBlockStream({
    from: irreversible - 3,
    to: irreversible - 1,
    mode: BlockchainMode.Irreversible
});

stream.on('data', (block) => {
    console.log(block.block_id);
});

stream.on('error', (error) => {
    console.error(error);
});

Prefer async iterators for new code unless your application already uses Node stream composition.

Long-running parsers

A production parser should define these policies outside the SDK:

  • checkpoint storage;
  • replay window;
  • endpoint trust and failover;
  • retry/backoff behavior;
  • duplicate handling;
  • reorg policy if using latest blocks;
  • observability and alerting;
  • idempotent writes to your own index/database.

The SDK helps fetch blocks and operations. It does not own your indexer state machine.

Query retries vs broadcast retries

Blockchain parsing uses data queries, so bounded retries and endpoint failover are usually acceptable. Do not reuse parsing retry logic for broadcast operations. Broadcast failures can be ambiguous after submission.

See RPC endpoints and failover and Broadcast safely.

Validated example

The current executable example demonstrates the smallest parsing primitive, block-number streaming:

Use this guide for the higher-level block and operation parsing workflows.

API details