Skip to main content

gRPC API Reference

The Basalt gRPC API provides a high-performance, strongly-typed interface for interacting with the blockchain. Built on Protocol Buffers (Protobuf) and HTTP/2, it is designed for backend services, infrastructure tooling, and high-throughput applications that benefit from binary serialization and bidirectional streaming.

Connection

The gRPC service is hosted on the same port as the HTTP API (default: 5000). ASP.NET Core's Kestrel server multiplexes HTTP/1.1 (REST), HTTP/2 (gRPC), and WebSocket traffic on a single port.

grpc://localhost:5000

For production deployments behind a reverse proxy, ensure that HTTP/2 traffic is forwarded correctly. Envoy and Nginx both support gRPC proxying with appropriate configuration.

Service Definition

The BasaltNode service is defined in basalt.proto and exposes the following RPCs:

Transaction Operations

RPCRequestResponseDescription
SendTransactionSignedTransactionTxResponseSubmit a signed transaction to the node's mempool. Returns the transaction hash and acceptance status. The transaction is gossiped to peers and included in a future block by the leader.
GetTransactionTxHashRequestTransactionRetrieve a transaction by its BLAKE3 hash. Returns the full transaction including sender, recipient, value, data, nonce, gas parameters, and signature.
GetReceiptTxHashRequestTransactionReceiptRetrieve the execution receipt for a finalized transaction. Includes execution status, gas consumed, emitted event logs, and contract address for deployment transactions.
EstimateGasCallRequestGasEstimateEstimate gas consumption for a transaction without persisting any state changes. Useful for setting appropriate gas limits before submission.

Block Operations

RPCRequestResponseDescription
GetBlockBlockRequestBlockRetrieve a block by hash or height. The BlockRequest message includes a oneof field that accepts either a BLAKE3 hash or a numeric height.
GetLatestBlockEmptyBlockRetrieve the most recently finalized block. Equivalent to querying the chain head.
StreamBlocksStreamRequeststream BlockServer-side streaming RPC that pushes new blocks as they are finalized. The client receives a continuous stream of Block messages. The StreamRequest can optionally specify a starting height to replay historical blocks before switching to live streaming.

Account and State Operations

RPCRequestResponseDescription
GetAccountAddressRequestAccountStateRetrieve the current state of an account including balance, nonce, and code hash.
GetStorageAtStorageRequestStorageValueRead a single storage slot from a contract account. The request specifies the contract address and storage key.
CallCallRequestCallResultExecute a read-only contract call against the current state. Does not produce a transaction or modify state. Returns the call result and gas consumed.

Event Log Operations

RPCRequestResponseDescription
GetLogsLogFilterLogResponseQuery event logs matching the specified filter criteria. Supports filtering by topics, block range, and contract address. Returns a batch of matching logs.
StreamLogsLogFilterstream EventLogServer-side streaming RPC that pushes event logs matching the filter as they are emitted in real time. Useful for monitoring specific contract events without polling.

Network and Status Operations

RPCRequestResponseDescription
GetPeersEmptyPeerListRetrieve the list of currently connected peers, including their node IDs, addresses, and connection duration.
GetSyncStatusEmptySyncStatusRetrieve the node's synchronization status, including current height, highest known peer height, and sync progress percentage.
GetChainInfoEmptyChainInfoRetrieve chain metadata including chain ID, genesis hash, network name, and protocol version.

Implementation Status

The following RPCs are currently implemented in the BasaltNodeService:

RPCStatus
GetStatusImplemented
GetBlockImplemented
GetAccountImplemented
SendTransactionImplemented
StreamBlocksImplemented
GetTransactionPlanned
GetReceiptPlanned
EstimateGasPlanned
GetLatestBlockPlanned
GetStorageAtPlanned
CallPlanned
GetLogsPlanned
StreamLogsPlanned
GetPeersPlanned
GetSyncStatusPlanned
GetChainInfoPlanned

RPCs marked as "Planned" are defined in the Protobuf service definition but return an UNIMPLEMENTED status code. They will be enabled in future releases.

Message Types

Core Messages

message SignedTransaction {
bytes from = 1;
bytes to = 2;
uint64 value = 3;
uint64 nonce = 4;
uint64 gas_limit = 5;
uint64 gas_price = 6;
bytes data = 7;
bytes signature = 8;
}

message TxResponse {
bytes tx_hash = 1;
bool accepted = 2;
string error = 3;
}

message TxHashRequest {
bytes hash = 1;
}

message BlockRequest {
oneof identifier {
bytes hash = 1;
uint64 height = 2;
}
}

message Block {
BlockHeader header = 1;
repeated SignedTransaction transactions = 2;
}

message BlockHeader {
bytes parent_hash = 1;
bytes state_root = 2;
bytes transactions_root = 3;
uint64 height = 4;
uint64 timestamp = 5;
bytes proposer = 6;
bytes signature = 7;
}

message AccountState {
bytes address = 1;
uint64 balance = 2;
uint64 nonce = 3;
bytes code_hash = 4;
}

message AddressRequest {
bytes address = 1;
}

Filter and Streaming Messages

message StreamRequest {
uint64 from_height = 1;
}

message LogFilter {
repeated bytes topics = 1;
uint64 from_block = 2;
uint64 to_block = 3;
bytes address = 4;
}

message EventLog {
bytes address = 1;
repeated bytes topics = 2;
bytes data = 3;
uint64 block_height = 4;
bytes tx_hash = 5;
uint32 log_index = 6;
}

Usage Examples

.NET Client

using Grpc.Net.Client;

var channel = GrpcChannel.ForAddress("http://localhost:5000");
var client = new BasaltNode.BasaltNodeClient(channel);

// Get latest block
var block = await client.GetLatestBlockAsync(new Empty());
Console.WriteLine($"Block #{block.Header.Height}");

// Stream new blocks
using var stream = client.StreamBlocks(new StreamRequest { FromHeight = 0 });
await foreach (var newBlock in stream.ResponseStream.ReadAllAsync())
{
Console.WriteLine($"New block #{newBlock.Header.Height}");
}

Go Client

import (
"context"
pb "basalt/proto"
"google.golang.org/grpc"
)

conn, _ := grpc.Dial("localhost:5000", grpc.WithInsecure())
client := pb.NewBasaltNodeClient(conn)

// Get account state
account, _ := client.GetAccount(context.Background(), &pb.AddressRequest{
Address: addressBytes,
})
fmt.Printf("Balance: %d\n", account.Balance)

grpcurl

# List available services
grpcurl -plaintext localhost:5000 list

# Get latest block
grpcurl -plaintext localhost:5000 basalt.BasaltNode/GetLatestBlock

# Stream blocks
grpcurl -plaintext localhost:5000 basalt.BasaltNode/StreamBlocks

Performance Considerations

The gRPC API is optimized for high-throughput use cases:

  • Binary serialization: Protobuf encoding is significantly more compact and faster to parse than JSON.
  • HTTP/2 multiplexing: Multiple concurrent RPCs share a single TCP connection, reducing connection overhead.
  • Server-side streaming: StreamBlocks and StreamLogs push data to clients without polling overhead.
  • Connection reuse: gRPC channels maintain persistent HTTP/2 connections. Create a single channel and reuse it across requests.

For latency-sensitive applications, the gRPC API is preferred over REST due to lower serialization overhead and connection management costs.