Show / Hide Table of Contents

Class BlockNodeClient

Hiero Block Node Client

Inheritance
object
BlockNodeClient
Implements
IAsyncDisposable
Inherited Members
object.Equals(object)
object.Equals(object, object)
object.GetHashCode()
object.GetType()
object.ReferenceEquals(object, object)
object.ToString()
Namespace: Hiero
Assembly: Hiero.dll
Syntax
[Experimental("HIERO001", UrlFormat = "https://github.com/bugbytesinc/Hiero/blob/main/docs/blocknode-client-plan.md")]
public sealed class BlockNodeClient : IAsyncDisposable
Remarks

This client facilitates access to a Hiero Block Node: streaming blocks from the block stream in near real-time, retrieving individual blocks, querying node status, obtaining block contents proofs and state snapshot references, and (for advanced producer scenarios) publishing block streams.

The Block Node service and this client surface are experimental; the API may change in any minor release while the upstream Block Node protocol stabilizes.

Thread safety. An instance is safe for concurrent use and is intended to be shared — a singleton registered with dependency injection is the expected pattern. Each operation builds its own child context, so concurrent calls share no mutable state, and the underlying gRPC channels are pooled in a thread-safe cache.

Configure(Action<IBlockNodeContext>) is the exception. It mutates this instance's own context in place, which every in-flight operation reads through, and is meant for setup before the client is used or while it is otherwise idle. To vary settings on a live client, pass the per-call configure argument — it applies only to that one call — or take a separately configured instance with Clone(Action<IBlockNodeContext>?).

Constructors

| Edit this page View Source

BlockNodeClient(Action<IBlockNodeContext>?)

Creates a new instance of a Hiero Block Node Client.

Declaration
public BlockNodeClient(Action<IBlockNodeContext>? configure = null)
Parameters
Type Name Description
Action<IBlockNodeContext> configure

Optional configuration method that can set the location of the block node and retry behavior.

Remarks
Creating a new instance of a 
BlockNodeClient

initializes a new instance of a client. It will have a separate cache of GRPC channels to the network and will maintain a separate configuration from other clients. The constructor takes an optional callback method that configures the details on how the client should connect to the block node. See the IBlockNodeContext documentation for configuration details.

| Edit this page View Source

BlockNodeClient(Func<Uri, GrpcChannel>, Action<IBlockNodeContext>?)

Creates a new instance of a Hiero Block Node Client with a custom gRPC channel factory.

Declaration
public BlockNodeClient(Func<Uri, GrpcChannel> channelFactory, Action<IBlockNodeContext>? configure = null)
Parameters
Type Name Description
Func<Uri, GrpcChannel> channelFactory

A custom callback method returning a new channel given the target block node URI. Note, this method is only called once for each unique URI requested by the block node client (which is a function of the current context's URI parameter)

Action<IBlockNodeContext> configure

Optional configuration method that can set the location of the block node and retry behavior.

Remarks
Creating a new instance of a 
BlockNodeClient

initializes a new instance of a client. It will have a separate cache of GRPC channels to the network and will maintain a separate configuration from other clients. The constructor takes an optional callback method that configures the details on how the client should connect to the block node. See the IBlockNodeContext documentation for configuration details.

Methods

| Edit this page View Source

Clone(Action<IBlockNodeContext>?)

Creates a new instance of the block node client having a shared base configuration with its parent. Changes to the parent’s configuration will reflect in this instances configuration while changes in this instances configuration will not be reflected in the parent configuration.

Declaration
public BlockNodeClient Clone(Action<IBlockNodeContext>? configure = null)
Parameters
Type Name Description
Action<IBlockNodeContext> configure

The callback method receiving the IBlockNodeContext object providing the configuration details of this client instance. Values can be retrieved and set within the context of the method invocation.

Returns
Type Description
BlockNodeClient

A new instance of a client object.

| Edit this page View Source

Configure(Action<IBlockNodeContext>)

Updates the configuration of this instance of a block node client through implementation of the supplied IBlockNodeContext callback method.

Declaration
public void Configure(Action<IBlockNodeContext> configure)
Parameters
Type Name Description
Action<IBlockNodeContext> configure

The callback method receiving the IBlockNodeContext object providing the configuration details of this client instance. Values can be retrieved and set within the context of the method invocation.

Remarks

Mutates this client's own context in place. Every operation already in flight reads its inherited settings through that context, so calling this concurrently with active work can let a call observe a partially applied configuration. Configure before use, or while the client is idle. For a live client, prefer the per-call configure argument (scoped to that call alone) or Clone(Action<IBlockNodeContext>?) for a separately configured instance.

| Edit this page View Source

CreateBlockStreamPublisherAsync(CancellationToken, Action<IBlockNodeContext>?)

Opens a block stream publish session with the block node — the advanced, producer-side surface used by block-producing tooling, simulators and repeaters.

Declaration
public Task<BlockStreamPublisher> CreateBlockStreamPublisherAsync(CancellationToken cancellationToken = default, Action<IBlockNodeContext>? configure = null)
Parameters
Type Name Description
CancellationToken cancellationToken

An optional token that can interrupt the session; firing it aborts the underlying stream.

Action<IBlockNodeContext> configure

Optional callback method providing an opportunity to modify the execution configuration for just this session.

Returns
Type Description
Task<BlockStreamPublisher>

An open publish session.

Remarks

The returned BlockStreamPublisher exposes the publish protocol's state machine honestly: the caller writes blocks (whole or item-by-item), MUST consume the Events stream to react to skip/resend/behind directives, and awaits cumulative acknowledgements. End the session gracefully with EndStreamAsync(PublishStreamEndCode, ulong, ulong, CancellationToken); disposing without it aborts the call.

Exceptions
Type Condition
InvalidOperationException

If the block node URL configuration is missing.

| Edit this page View Source

DisposeAsync()

.NET Asynchronous dispose method.

Declaration
public ValueTask DisposeAsync()
Returns
Type Description
ValueTask

An Async Task.

Remarks
Closes any GRPC channels solely owned by this 
BlockNodeClient

instance.

| Edit this page View Source

GetBlockAsync(ulong, CancellationToken, Action<IBlockNodeContext>?)

Retrieves a single block by block number.

Declaration
public Task<Block?> GetBlockAsync(ulong blockNumber, CancellationToken cancellationToken = default, Action<IBlockNodeContext>? configure = null)
Parameters
Type Name Description
ulong blockNumber

The number of the block to retrieve.

CancellationToken cancellationToken

An optional token that can interrupt the request.

Action<IBlockNodeContext> configure

Optional callback method providing an opportunity to modify the execution configuration for just this method call.

Returns
Type Description
Task<Block>
The requested block, or 
null

when the node reports the block as not found. A block that falls outside the node's available range (pruned or not yet produced) raises a BlockNodeException with code NotAvailable instead.

Exceptions
Type Condition
InvalidOperationException

If the block node URL configuration is missing.

BlockNodeException

If the block node rejected the request or communication failed.

| Edit this page View Source

GetBlockContentsProofAsync(GetBlockContentsProofParams, CancellationToken, Action<IBlockNodeContext>?)

Retrieves a proof that a specific item is contained within a specific block: the item, the merkle sibling hashes forming the path to the block root, and the block's aggregate signature.

Declaration
public Task<BlockContentsProof?> GetBlockContentsProofAsync(GetBlockContentsProofParams proofParameters, CancellationToken cancellationToken = default, Action<IBlockNodeContext>? configure = null)
Parameters
Type Name Description
GetBlockContentsProofParams proofParameters

Identifies the block and the item of interest; the item may be specified by complete item, item hash, or item index (exactly one).

CancellationToken cancellationToken

An optional token that can interrupt the request.

Action<IBlockNodeContext> configure

Optional callback method providing an opportunity to modify the execution configuration for just this method call.

Returns
Type Description
Task<BlockContentsProof>
The proof, or 
null

when the node reports the item as not found within the block.

Exceptions
Type Condition
ArgumentNullException

If required arguments are missing.

ArgumentOutOfRangeException

If the item specifier is missing or ambiguous.

InvalidOperationException

If the block node URL configuration is missing.

BlockNodeException

If the block node rejected the request or communication failed.

| Edit this page View Source

GetLatestBlockAsync(CancellationToken, Action<IBlockNodeContext>?)

Retrieves the latest block held by the block node.

Declaration
public Task<Block> GetLatestBlockAsync(CancellationToken cancellationToken = default, Action<IBlockNodeContext>? configure = null)
Parameters
Type Name Description
CancellationToken cancellationToken

An optional token that can interrupt the request.

Action<IBlockNodeContext> configure

Optional callback method providing an opportunity to modify the execution configuration for just this method call.

Returns
Type Description
Task<Block>

The latest block held by the node.

Exceptions
Type Condition
InvalidOperationException

If the block node URL configuration is missing.

BlockNodeException

If the node holds no blocks, rejected the request, or communication failed.

| Edit this page View Source

GetLatestStateSnapshotAsync(CancellationToken, Action<IBlockNodeContext>?)

Retrieves a reference to the latest network state snapshot the block node holds.

Declaration
public Task<StateSnapshot> GetLatestStateSnapshotAsync(CancellationToken cancellationToken = default, Action<IBlockNodeContext>? configure = null)
Parameters
Type Name Description
CancellationToken cancellationToken

An optional token that can interrupt the request.

Action<IBlockNodeContext> configure

Optional callback method providing an opportunity to modify the execution configuration for just this method call.

Returns
Type Description
Task<StateSnapshot>

A reference from which the snapshot content can be retrieved.

Exceptions
Type Condition
InvalidOperationException

If the block node URL configuration is missing.

BlockNodeException

If the block node rejected the request or communication failed.

| Edit this page View Source

GetServerStatusAsync(CancellationToken, Action<IBlockNodeContext>?)

Retrieves the basic status of the block node: the span of blocks it can currently serve.

Declaration
public Task<BlockNodeStatus> GetServerStatusAsync(CancellationToken cancellationToken = default, Action<IBlockNodeContext>? configure = null)
Parameters
Type Name Description
CancellationToken cancellationToken

An optional token that can interrupt the request.

Action<IBlockNodeContext> configure

Optional callback method providing an opportunity to modify the execution configuration for just this method call.

Returns
Type Description
Task<BlockNodeStatus>

The node's available block range and state retention mode.

Exceptions
Type Condition
InvalidOperationException

If the block node URL configuration is missing.

BlockNodeException

If communication with the block node failed.

| Edit this page View Source

GetServerStatusDetailAsync(CancellationToken, Action<IBlockNodeContext>?)

Retrieves the detailed status of the block node: versions, installed plugins, available and stored block ranges, TSS verification bootstrap data and consensus address books.

Declaration
public Task<BlockNodeStatusDetail> GetServerStatusDetailAsync(CancellationToken cancellationToken = default, Action<IBlockNodeContext>? configure = null)
Parameters
Type Name Description
CancellationToken cancellationToken

An optional token that can interrupt the request.

Action<IBlockNodeContext> configure

Optional callback method providing an opportunity to modify the execution configuration for just this method call.

Returns
Type Description
Task<BlockNodeStatusDetail>

The node's detailed status information.

Exceptions
Type Condition
InvalidOperationException

If the block node URL configuration is missing.

BlockNodeException

If communication with the block node failed.

| Edit this page View Source

GetStateSnapshotAsync(ulong, CancellationToken, Action<IBlockNodeContext>?)

Retrieves a reference to the network state snapshot as of a given block number.

Declaration
public Task<StateSnapshot> GetStateSnapshotAsync(ulong lastBlockNumber, CancellationToken cancellationToken = default, Action<IBlockNodeContext>? configure = null)
Parameters
Type Name Description
ulong lastBlockNumber

The block number the snapshot must reflect.

CancellationToken cancellationToken

An optional token that can interrupt the request.

Action<IBlockNodeContext> configure

Optional callback method providing an opportunity to modify the execution configuration for just this method call.

Returns
Type Description
Task<StateSnapshot>

A reference from which the snapshot content can be retrieved.

Exceptions
Type Condition
InvalidOperationException

If the block node URL configuration is missing.

BlockNodeException

If the block node rejected the request or communication failed.

| Edit this page View Source

GetVerifiedBlockAsync(ulong, CancellationToken, Action<IBlockNodeContext>?)

Retrieves a single block by block number and checks its SHA-384 merkle root against the previous-block root hash of the following block served by the same node, populating VerifiedRootHash on success.

Declaration
public Task<Block?> GetVerifiedBlockAsync(ulong blockNumber, CancellationToken cancellationToken = default, Action<IBlockNodeContext>? configure = null)
Parameters
Type Name Description
ulong blockNumber

The number of the block to retrieve and verify.

CancellationToken cancellationToken

An optional token that can interrupt the request.

Action<IBlockNodeContext> configure

Optional callback method providing an opportunity to modify the execution configuration for just this method call.

Returns
Type Description
Task<Block>

The requested, verified block (with VerifiedRootHash populated), or

null

when the node reports the block as not found.

Remarks

Verification recomputes the block's root from its items and confirms it against the following block's previous-block root hash — so this method makes a second block request (the verification anchor) and performs the merkle recomputation, work the plain GetBlockAsync(ulong, CancellationToken, Action<IBlockNodeContext>?) does not. The anchor comes from the same node and is not itself authenticated, so this is an integrity and consistency check, not authentication: the block proof's signature is not checked. The block stream's tip cannot be verified this way because no following block exists yet; there is deliberately no verified-latest counterpart to GetLatestBlockAsync(CancellationToken, Action<IBlockNodeContext>?).

Exceptions
Type Condition
InvalidOperationException

If the block node URL configuration is missing.

BlockNodeException

If verification fails (VerificationFailed — including when the anchor block is not yet available), the block holds content this SDK cannot hash with certainty (Unverifiable), or the block node rejected the request or communication failed.

| Edit this page View Source

SubscribeBlockItemStreamAsync(SubscribeBlockItemStreamParams, Action<IBlockNodeContext>?)

Subscribes to the block node's block stream at the item level, placing each block item into the provided .NET Channel the moment its frame arrives — before the containing block is complete or verified.

Declaration
public Task SubscribeBlockItemStreamAsync(SubscribeBlockItemStreamParams subscribeParameters, Action<IBlockNodeContext>? configure = null)
Parameters
Type Name Description
SubscribeBlockItemStreamParams subscribeParameters

The details of the subscription: block range, delivery channel and gap policy.

Action<IBlockNodeContext> configure

Optional callback method providing an opportunity to modify the execution configuration for just this method call.

Returns
Type Description
Task

Returns only after one of the following conditions occur: the output channel is completed by calling code; the cancellation token provided in the params is signaled; the server ended a bounded stream; or the stream faulted beyond recovery, in which case a BlockNodeException is thrown.

Remarks

This is the low-latency mode: an item can be delivered a second or more before its block's boundary marker, which matters for consumers reacting to events (e.g. EVM contract outputs) where milliseconds count. In exchange, every safety of the assembled mode is traded away: no buffering, no duplicate dropping, no structural verification — a resent block is delivered again under the same number. See StreamedBlockItem for the reconciliation contract. Gaps in completed block numbers and transport drops are still recovered per GapPolicy, resuming from the last completed block + 1.

Examples

Observe items mid-block, before verification — the low-latency mode for event monitors that reconcile on block completion:

await using var client = new BlockNodeClient(ctx =>
{
    ctx.Uri = new Uri(blockNodeEndpoint);
    // Only for nodes serving their status API on a separate endpoint;
    // when null, status calls share Uri.
    ctx.StatusUri = statusEndpoint;
});

Console.WriteLine("Tailing live block items — delivered mid-block, before verification (Ctrl+C to stop)...");

var channel = Channel.CreateBounded<StreamedBlockItem>(256);
var completedBlocks = 0UL;

// Item-level delivery: each item arrives the moment its frame does,
// potentially a second or more before the block's proof — useful when
// reacting to events (e.g. EVM contract outputs) where milliseconds
// matter and provisional data can be reconciled later.
var subscribeTask = client.SubscribeBlockItemStreamAsync(new SubscribeBlockItemStreamParams
{
    ItemWriter = channel.Writer,
    CancellationToken = cts.Token
});

try
{
    await foreach (var streamed in channel.Reader.ReadAllAsync(cts.Token))
    {
        if (streamed.Item.Kind == BlockItemKind.TransactionOutput || streamed.Item.Kind == BlockItemKind.SignedTransaction)
        {
            Console.WriteLine($"Block {streamed.BlockNumber} (in progress): {streamed.Item.Kind} observed");
        }
        if (streamed.IsBlockComplete)
        {
            Console.WriteLine($"Block {streamed.BlockNumber} complete");
            completedBlocks++;
            if (maxBlocks > 0 && completedBlocks >= maxBlocks)
            {
                cts.Cancel();
            }
        }
    }
}
catch (OperationCanceledException)
{
    // Ctrl+C or maxBlocks reached.
}
await subscribeTask;
Exceptions
Type Condition
ArgumentNullException

If required arguments are missing.

ArgumentOutOfRangeException

If the requested block range is inverted.

InvalidOperationException

If the block node URL configuration is missing.

BlockNodeException

If the block stream faulted beyond the configured recovery policy.

| Edit this page View Source

SubscribeBlockStreamAsync(SubscribeBlockStreamParams, Action<IBlockNodeContext>?)

Subscribes to the block node's block stream, assembling item frames into whole blocks and placing each completed block into the provided .NET Channel.

Declaration
public Task SubscribeBlockStreamAsync(SubscribeBlockStreamParams subscribeParameters, Action<IBlockNodeContext>? configure = null)
Parameters
Type Name Description
SubscribeBlockStreamParams subscribeParameters

The details of the subscription: block range, delivery channel, verification level and gap policy.

Action<IBlockNodeContext> configure

Optional callback method providing an opportunity to modify the execution configuration for just this method call.

Returns
Type Description
Task

Returns only after one of the following conditions occur: the output channel is completed by calling code; the cancellation token provided in the params is signaled; the maximum number of blocks was delivered; the ending block was delivered (or the server ended the bounded stream); or the stream faulted beyond recovery, in which case a BlockNodeException is thrown.

Remarks

The block stream is forwarded by the node unverified; gaps, resends and malformed blocks are protocol-normal. This method owns those sharp edges: partial blocks superseded by a resend are discarded, duplicates are dropped, each completed block is validated per VerificationLevel, and gaps or transport drops are handled per GapPolicy — by default resubscribing from the last delivered block + 1 using the context's retry settings. Only completed blocks are ever written to the channel.

Examples

Tail live assembled blocks — reads keep pace with the incoming stream via a Channel, with gaps and reconnects handled automatically:

await using var client = new BlockNodeClient(ctx =>
{
    ctx.Uri = new Uri(blockNodeEndpoint);
    // Only for nodes serving their status API on a separate endpoint;
    // when null, status calls share Uri.
    ctx.StatusUri = statusEndpoint;
});

var status = await client.GetServerStatusAsync();
Console.WriteLine($"Block node serves blocks {status.FirstAvailableBlockNumber}..{status.LastAvailableBlockNumber}");
Console.WriteLine("Tailing live blocks (Ctrl+C to stop)...");

var channel = Channel.CreateBounded<Block>(32);

// Start the subscription in the background. Assembled blocks arrive
// via channel.Writer; gaps and reconnects are handled automatically
// (GapPolicy.Resubscribe) and each block is structurally validated
// (VerificationLevel.Structural) before delivery.
var subscribeTask = client.SubscribeBlockStreamAsync(new SubscribeBlockStreamParams
{
    BlockWriter = channel.Writer,
    MaxCount = maxBlocks,
    CancellationToken = cts.Token
});

// Read blocks as they arrive.
try
{
    await foreach (var block in channel.Reader.ReadAllAsync(cts.Token))
    {
        var transactions = block.Items.Count(i => i.Kind == BlockItemKind.SignedTransaction);
        Console.WriteLine($"Block {block.Number} @ {block.Timestamp}: {block.Items.Count} items, {transactions} transactions, proof: {block.Proof?.Kind}");
    }
}
catch (OperationCanceledException)
{
    // Ctrl+C — fall through to await the subscription's own shutdown.
}
await subscribeTask;
Exceptions
Type Condition
ArgumentNullException

If required arguments are missing.

ArgumentOutOfRangeException

If the requested block range is inverted, or if ResumeFromCheckpoint is combined with a starting block number, used with a verification level below HashChain, or carries a root hash that is not 48 bytes.

InvalidOperationException

If the block node URL configuration is missing.

BlockNodeException

If the block stream faulted beyond the configured recovery policy.

Implements

IAsyncDisposable
  • Edit this page
  • View Source
In this article
Back to top .NET Client Library for Hiero Network and Hedera Hashgraph