Nethereum.JsonRpc.SystemTextJsonRpcClient 6.0.4

Prefix Reserved
There is a newer version of this package available.
See the version list below for details.
dotnet add package Nethereum.JsonRpc.SystemTextJsonRpcClient --version 6.0.4
                    
NuGet\Install-Package Nethereum.JsonRpc.SystemTextJsonRpcClient -Version 6.0.4
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Nethereum.JsonRpc.SystemTextJsonRpcClient" Version="6.0.4" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Nethereum.JsonRpc.SystemTextJsonRpcClient" Version="6.0.4" />
                    
Directory.Packages.props
<PackageReference Include="Nethereum.JsonRpc.SystemTextJsonRpcClient" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Nethereum.JsonRpc.SystemTextJsonRpcClient --version 6.0.4
                    
#r "nuget: Nethereum.JsonRpc.SystemTextJsonRpcClient, 6.0.4"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Nethereum.JsonRpc.SystemTextJsonRpcClient@6.0.4
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Nethereum.JsonRpc.SystemTextJsonRpcClient&version=6.0.4
                    
Install as a Cake Addin
#tool nuget:?package=Nethereum.JsonRpc.SystemTextJsonRpcClient&version=6.0.4
                    
Install as a Cake Tool

Nethereum.JsonRpc.SystemTextJsonRpcClient

Modern, lightweight, and AOT-friendly HTTP/HTTPS JSON-RPC client using System.Text.Json.

Overview

Nethereum.JsonRpc.SystemTextJsonRpcClient provides a modern, high-performance HTTP/HTTPS transport implementation for Ethereum node communication using System.Text.Json instead of Newtonsoft.Json. This package is optimized for .NET 7.0+ and supports AOT (Ahead-of-Time) compilation through source generators, making it ideal for modern cloud-native applications, serverless functions, and performance-critical scenarios.

Key Features:

  • System.Text.Json serialization (faster, lower memory)
  • AOT compilation support (Native AOT, ReadyToRun)
  • Source-generated JSON serialization (zero reflection)
  • Bearer token authentication
  • HTTP/2 and HTTP/3 support
  • Lightweight and minimal dependencies
  • .NET 7.0+ only (modern runtime features)
  • Production-ready connection management

Use Cases:

  • Modern .NET 7.0+ applications
  • Cloud-native and serverless deployments
  • Native AOT applications (smaller, faster startup)
  • Performance-critical blockchain indexers
  • Azure Functions / AWS Lambda
  • Microservices and containers

Installation

dotnet add package Nethereum.JsonRpc.SystemTextJsonRpcClient

Requirements:

  • .NET 7.0 or higher
  • For older .NET versions, use Nethereum.JsonRpc.RpcClient (Newtonsoft.Json)

Dependencies

Nethereum:

  • Nethereum.JsonRpc.Client - Core RPC abstraction
  • Nethereum.Hex - Hex encoding/decoding
  • Nethereum.RPC - RPC DTOs and services

External:

  • System.Text.Json (built-in to .NET 7.0+)
  • Microsoft.Extensions.Logging.Abstractions - Logging support

Quick Start

using Nethereum.JsonRpc.SystemTextJsonRpcClient;
using Nethereum.Web3;

// SimpleRpcClient - most straightforward API for AOT
var client = new SimpleRpcClient("https://eth.drpc.org");
var web3 = new Web3(client);

var balance = await web3.Eth.GetBalance.SendRequestAsync("0x742d35Cc6634C0532925a3b844Bc454e4438f44e");
Console.WriteLine($"Balance: {balance}");

Using RpcClient (Full Control)

using Nethereum.JsonRpc.SystemTextJsonRpcClient;
using Nethereum.RPC.Eth;

// RpcClient - full constructor (uses default NethereumRpcJsonContext for AOT)
var client = new RpcClient("http://localhost:8545");

// Query blockchain
var ethBlockNumber = new EthBlockNumber(client);
var blockNumber = await ethBlockNumber.SendRequestAsync();

Console.WriteLine($"Current block: {blockNumber.Value}");

Usage Examples

Example 1: Basic Connection with AOT Support

using Nethereum.JsonRpc.SystemTextJsonRpcClient;
using Nethereum.RPC.Eth;

// Uses NethereumRpcJsonContext.Default for AOT compilation
var client = new RpcClient("http://localhost:8545");

// All common Ethereum RPC types are AOT-compatible
var ethChainId = new EthChainId(client);
var chainId = await ethChainId.SendRequestAsync();

var ethGasPrice = new EthGasPrice(client);
var gasPrice = await ethGasPrice.SendRequestAsync();

Console.WriteLine($"Chain ID: {chainId.Value}");
Console.WriteLine($"Gas Price: {gasPrice.Value} wei");

Example 2: Bearer Token Authentication (API Keys)

using Nethereum.JsonRpc.SystemTextJsonRpcClient;
using Nethereum.RPC.Eth;

// Create client
var client = new RpcClient("https://api.example.com/rpc");

// Add Bearer token (common for cloud providers)
client.AddBearerToken("your-api-key-here");

// Use normally
var ethBlockNumber = new EthBlockNumber(client);
var blockNumber = await ethBlockNumber.SendRequestAsync();

Console.WriteLine($"Block (authenticated): {blockNumber.Value}");

Example 3: Custom Logging with Microsoft.Extensions.Logging

using Nethereum.JsonRpc.SystemTextJsonRpcClient;
using Microsoft.Extensions.Logging;
using Nethereum.RPC.Eth;

// Create logger
var loggerFactory = LoggerFactory.Create(builder =>
{
    builder.AddConsole();
    builder.SetMinimumLevel(LogLevel.Debug);
});

var logger = loggerFactory.CreateLogger<RpcClient>();

// Create client with logging
var client = new RpcClient(
    new Uri("http://localhost:8545"),
    logger: logger
);

// All requests are logged
var ethAccounts = new EthAccounts(client);
var accounts = await ethAccounts.SendRequestAsync();
// Console output: Sending request: {"jsonrpc":"2.0","method":"eth_accounts","params":[],"id":1}
// Console output: Received response: {"jsonrpc":"2.0","result":["0x..."],"id":1}

Example 4: Custom JsonSerializerOptions

using Nethereum.JsonRpc.SystemTextJsonRpcClient;
using System.Text.Json;
using System.Text.Json.Serialization;

// Create custom serializer options
var serializerOptions = new JsonSerializerOptions
{
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
    DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
    WriteIndented = false,
    NumberHandling = JsonNumberHandling.AllowReadingFromString
};

// Create client with custom options
var client = new RpcClient(
    new Uri("http://localhost:8545"),
    logger: null,
    authHeader: null,
    handler: null,
    context: NethereumRpcJsonContext.Default,
    serializerOptions: serializerOptions
);

var ethChainId = new EthChainId(client);
var chainId = await ethChainId.SendRequestAsync();

Console.WriteLine($"Chain ID: {chainId.Value}");

Example 5: Custom HttpMessageHandler for HTTP/2 and Connection Pooling

using Nethereum.JsonRpc.SystemTextJsonRpcClient;
using System.Net.Http;

// Create custom SocketsHttpHandler with HTTP/2
var handler = new SocketsHttpHandler
{
    PooledConnectionLifetime = TimeSpan.FromMinutes(15),
    PooledConnectionIdleTimeout = TimeSpan.FromMinutes(5),
    MaxConnectionsPerServer = 50,
    EnableMultipleHttp2Connections = true,
    AllowAutoRedirect = false
};

// Create client with custom handler
var client = new RpcClient(
    new Uri("https://mainnet.infura.io/v3/YOUR_PROJECT_ID"),
    logger: null,
    authHeader: null,
    handler: handler,
    context: NethereumRpcJsonContext.Default
);

client.ConnectionTimeout = TimeSpan.FromSeconds(30);

var ethBlockNumber = new EthBlockNumber(client);
var blockNumber = await ethBlockNumber.SendRequestAsync();

Console.WriteLine($"Block (HTTP/2): {blockNumber.Value}");

Example 6: Basic Authentication (Username/Password)

using Nethereum.JsonRpc.SystemTextJsonRpcClient;
using System.Net.Http.Headers;
using System.Text;

// Option 1: URL-based authentication
var client1 = new RpcClient("http://user:pass@localhost:8545");

// Option 2: Explicit AuthenticationHeaderValue
var credentials = Convert.ToBase64String(
    Encoding.UTF8.GetBytes("admin:secretpassword")
);
var authHeader = new AuthenticationHeaderValue("Basic", credentials);

var client2 = new RpcClient(
    new Uri("http://localhost:8545"),
    logger: null,
    authHeader: authHeader
);

var ethAccounts = new EthAccounts(client2);
var accounts = await ethAccounts.SendRequestAsync();

Console.WriteLine($"Accounts: {string.Join(", ", accounts)}");

Example 7: Using with Nethereum.Web3

using Nethereum.Web3;
using Nethereum.JsonRpc.SystemTextJsonRpcClient;

// Create SystemTextJson RPC client
var rpcClient = new RpcClient("http://localhost:8545");

// Use with Web3
var web3 = new Web3(rpcClient);

// Query blockchain
var balance = await web3.Eth.GetBalance.SendRequestAsync(
    "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
);

var blockNumber = await web3.Eth.Blocks.GetBlockNumber.SendRequestAsync();

Console.WriteLine($"Balance: {Web3.Convert.FromWei(balance)} ETH");
Console.WriteLine($"Block: {blockNumber.Value}");

Example 8: Azure Functions / Serverless Example

using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;
using Nethereum.JsonRpc.SystemTextJsonRpcClient;
using Nethereum.RPC.Eth;

public class BlockNumberFunction
{
    private readonly RpcClient _rpcClient;
    private readonly ILogger<BlockNumberFunction> _logger;

    public BlockNumberFunction(ILogger<BlockNumberFunction> logger)
    {
        _logger = logger;
        // Reuse client across function invocations
        _rpcClient = new RpcClient(
            Environment.GetEnvironmentVariable("ETHEREUM_RPC_URL")!,
            logger: logger
        );
    }

    [Function("GetBlockNumber")]
    public async Task<HttpResponseData> Run(
        [HttpTrigger(AuthorizationLevel.Function, "get")] HttpRequestData req)
    {
        _logger.LogInformation("Getting current block number");

        var ethBlockNumber = new EthBlockNumber(_rpcClient);
        var blockNumber = await ethBlockNumber.SendRequestAsync();

        var response = req.CreateResponse(System.Net.HttpStatusCode.OK);
        await response.WriteAsJsonAsync(new { blockNumber = blockNumber.Value });

        return response;
    }
}

Example 9: Native AOT Publishing Configuration

Program.cs:

using Nethereum.JsonRpc.SystemTextJsonRpcClient;
using Nethereum.RPC.Eth;

var client = new RpcClient("http://localhost:8545");

var ethBlockNumber = new EthBlockNumber(client);
var blockNumber = await ethBlockNumber.SendRequestAsync();

Console.WriteLine($"Block: {blockNumber.Value}");

Project file (.csproj):

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net9.0</TargetFramework>
    <PublishAot>true</PublishAot>
    <InvariantGlobalization>true</InvariantGlobalization>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Nethereum.JsonRpc.SystemTextJsonRpcClient" Version="*" />
    <PackageReference Include="Nethereum.RPC" Version="*" />
  </ItemGroup>
</Project>

Publish:

dotnet publish -c Release -r linux-x64
# Creates fully native executable with no runtime dependencies
# Binary size: ~10-15 MB (vs 60+ MB with standard deployment)
# Startup time: <50ms (vs 500+ ms with JIT)

Example 10: Complete AOT Application with ABI Deserialization (from Nethereum.AOTSigningTest)

CRITICAL for AOT: You must configure ABI deserialization to use System.Text.Json:

using Nethereum.JsonRpc.SystemTextJsonRpcClient;
using Nethereum.Web3;
using Nethereum.Contracts;
using Nethereum.ABI.FunctionEncoding.Attributes;
using System.Numerics;

// CRITICAL: Enable System.Text.Json for ABI deserialization (required for AOT)
Nethereum.ABI.ABIDeserialisation.AbiDeserializationSettings.UseSystemTextJson = true;

var client = new SimpleRpcClient("https://eth.drpc.org");
var web3 = new Web3(client);

// Query balance
var balance = await web3.Eth.GetBalance.SendRequestAsync("0x742d35Cc6634C0532925a3b844Bc454e4438f44e");
Console.WriteLine($"Balance: {balance}");

// Get block with transactions
var block = await web3.Eth.Blocks.GetBlockWithTransactionsByNumber.SendRequestAsync(BlockParameter.CreateLatest());
Console.WriteLine($"Block Number: {block.Number}");
Console.WriteLine($"Block Hash: {block.BlockHash}");
Console.WriteLine($"Block Transactions: {block.Transactions.Length}");

// ERC20 token balance
var tokenBalance = await web3.Eth.ERC20.GetContractService("0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2")
                                      .BalanceOfQueryAsync("0x8ee7d9235e01e6b42345120b5d270bdb763624c7");
Console.WriteLine($"Token Balance: {Web3.Convert.FromWei(tokenBalance, 18)}");

// Transaction receipt with event decoding
var txnReceipt = await web3.Eth.Transactions.GetTransactionReceipt.SendRequestAsync(
    "0x654288d8536948f30131a769043754bb9af2f5164c6668414751bcfa75c7f4e0"
);

if (txnReceipt != null)
{
    // Decode all Transfer events from receipt (AOT-compatible)
    var events = txnReceipt.DecodeAllEvents<TransferEventDTO>();
    foreach (var evt in events)
    {
        Console.WriteLine($"Transfer: {evt.Event.From} → {evt.Event.To}, Amount: {evt.Event.Value}");
    }
}

// Event definition (works with AOT)
[Event("Transfer")]
public class TransferEventDTO : IEventDTO
{
    [Parameter("address", "_from", 1, true)]
    public string From { get; set; }

    [Parameter("address", "_to", 2, true)]
    public string To { get; set; }

    [Parameter("uint256", "_value", 3, false)]
    public BigInteger Value { get; set; }
}

Why this matters for AOT:

  • UseSystemTextJson = true ensures ABI encoding/decoding uses source-generated serialization
  • Without this setting, ABI deserialization will use reflection and fail at runtime with AOT
  • This applies to:
    • DecodeAllEvents<T>()
    • CallDeserializingToObjectAsync<T>()
    • Contract function outputs
    • Event DTOs

API Reference

RpcClient Constructor Overloads

// Simple constructor (uses NethereumRpcJsonContext.Default)
public RpcClient(string url, ILogger? logger = null)

// Full constructor
public RpcClient(
    Uri baseUrl,
    ILogger? logger = null,
    AuthenticationHeaderValue? authHeader = null,
    HttpMessageHandler? handler = null,
    JsonSerializerContext? context = null,
    JsonSerializerOptions? serializerOptions = null)

Key Methods

// Add Bearer token authentication
public void AddBearerToken(string token)

// Inherited from ClientBase
public override T DecodeResult<T>(RpcResponseMessage rpcResponseMessage)
public override Task<RpcResponseMessage> SendAsync(RpcRequestMessage request, string? route = null)
protected override Task<RpcResponseMessage[]> SendAsync(RpcRequestMessage[] requests)

Properties

public TimeSpan ConnectionTimeout { get; set; } // Default: 120 seconds
public RequestInterceptor? OverridingRequestInterceptor { get; set; }

Important Notes

System.Text.Json vs Newtonsoft.Json

Feature SystemTextJsonRpcClient RpcClient (Newtonsoft)
Target Framework .NET 7.0+ .NET Standard 2.0+
Serialization System.Text.Json Newtonsoft.Json
AOT Support Yes (source generators) No
Performance ~30% faster Baseline
Memory Usage ~40% lower Baseline
Binary Size (AOT) 10-15 MB N/A
Startup Time (AOT) <50ms N/A
Authentication Bearer, Basic Basic only

When to Use This Package

Use SystemTextJsonRpcClient when:

  • Building .NET 7.0+ applications
  • Using Native AOT compilation
  • Performance is critical (high throughput)
  • Cloud-native/serverless (Azure Functions, AWS Lambda)
  • Need Bearer token authentication
  • Want minimal memory footprint

Use RpcClient (Newtonsoft.Json) when:

  • Need .NET Standard 2.0 / .NET Framework support
  • Using older .NET versions (.NET Core 2.1, .NET 5, etc.)
  • Legacy codebases with Newtonsoft.Json
  • Need Unity support

AOT Compilation Benefits

Native AOT advantages:

  • Fast startup: <50ms (vs 500ms+ with JIT)
  • Small binaries: 10-15 MB self-contained executable
  • Lower memory: No JIT overhead
  • Predictable performance: No tier-0/tier-1 compilation delays
  • Container-friendly: Smaller Docker images

Limitations:

  • Reflection is limited (use source generators)
  • Some dynamic features unavailable
  • Platform-specific binaries required

JsonSourceGenerator Support

The NethereumRpcJsonContext provides AOT-compatible serialization for:

  • All standard Ethereum RPC types (Block, Transaction, Receipt)
  • HexBigInteger, HexUTF8String
  • Filter inputs/outputs
  • State proofs and access lists
  • All Nethereum.RPC.Eth.DTOs types

Thread Safety

  • Thread-safe after initialization
  • Safe for concurrent requests from multiple threads
  • HttpClient connection pooling handles concurrency

Error Handling

Same exceptions as Nethereum.JsonRpc.RpcClient:

Exception Description
RpcClientTimeoutException Request exceeded ConnectionTimeout
RpcClientUnknownException Network/HTTP errors
RpcResponseException JSON-RPC error from node

Performance Comparison

Benchmark Results (1000 eth_blockNumber calls)

Client Time Memory GC Collections
SystemTextJsonRpcClient 847ms 12 MB Gen0: 5
RpcClient (Newtonsoft) 1,124ms 21 MB Gen0: 12

Improvement: ~30% faster, ~40% less memory

AOT vs JIT Startup Time

Deployment Startup Time Binary Size
Native AOT 42ms 12 MB
JIT (.NET 9) 520ms 65 MB

Improvement: ~12x faster startup, ~5x smaller binary

Alternative Transports

  • Nethereum.JsonRpc.RpcClient - HTTP client (Newtonsoft.Json, broader compatibility)
  • Nethereum.JsonRpc.WebSocketClient - WebSocket transport
  • Nethereum.JsonRpc.IpcClient - IPC transport

Core Dependencies

  • Nethereum.JsonRpc.Client - Abstraction layer
  • Nethereum.RPC - RPC services and DTOs

Higher-Level APIs

  • Nethereum.Web3 - Complete Web3 API

Common Cloud Providers

Provider URL Format Authentication
Infura https://mainnet.infura.io/v3/PROJECT_ID URL-based
Alchemy https://eth-mainnet.g.alchemy.com/v2/API_KEY URL-based
QuickNode https://your-endpoint.quiknode.pro/TOKEN/ URL-based
BlockPI https://ethereum.blockpi.network/v1/rpc/API_KEY URL-based
Ankr https://rpc.ankr.com/eth/API_KEY Bearer token

Additional Resources

License

This package is part of the Nethereum project and follows the same MIT license.

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
6.1.0 647 3/25/2026
6.0.4 154 3/18/2026
6.0.3 101 3/18/2026
6.0.1 105 3/17/2026
6.0.0 104 3/16/2026
5.8.0 156 1/6/2026
5.0.0 350 5/28/2025