Nethereum.UI
5.8.0
Prefix Reserved
dotnet add package Nethereum.UI --version 5.8.0
NuGet\Install-Package Nethereum.UI -Version 5.8.0
<PackageReference Include="Nethereum.UI" Version="5.8.0" />
<PackageVersion Include="Nethereum.UI" Version="5.8.0" />
<PackageReference Include="Nethereum.UI" />
paket add Nethereum.UI --version 5.8.0
#r "nuget: Nethereum.UI, 5.8.0"
#:package Nethereum.UI@5.8.0
#addin nuget:?package=Nethereum.UI&version=5.8.0
#tool nuget:?package=Nethereum.UI&version=5.8.0
Nethereum.UI
Common UI services and abstractions for building Ethereum frontend applications with Nethereum.
Overview
Nethereum.UI provides infrastructure components for building Ethereum-enabled user interfaces across web, desktop, and mobile platforms. It defines standard abstractions for wallet providers, authentication, and input validation that work consistently across Blazor, MAUI, Avalonia, Unity, and other .NET UI frameworks.
Key Features:
- Wallet provider abstraction (
IEthereumHostProvider) - Provider selection service with change notifications
- Sign-In with Ethereum (SIWE) authentication
- FluentValidation rules for Ethereum addresses and data
- Built-in provider implementation for testing/development
- Event-driven account and network change tracking
Use Cases:
- Building multi-wallet support in dApps
- Implementing Sign-In with Ethereum authentication
- Validating user input (addresses, private keys, hex data)
- Managing wallet connections across UI frameworks
- Creating wallet selection interfaces
Installation
dotnet add package Nethereum.UI
Dependencies
- FluentValidation (9.3.0) - Input validation framework
- Nethereum.Siwe.Core
- Nethereum.Siwe
Core Components
IEthereumHostProvider
Standard interface for Ethereum wallet providers (MetaMask, WalletConnect, built-in wallets, etc.):
public interface IEthereumHostProvider
{
// Provider metadata
string Name { get; }
bool Available { get; }
bool Enabled { get; }
// Selected account/network
string SelectedAccount { get; }
long SelectedNetworkChainId { get; }
// Multi-wallet support
bool MultipleWalletsProvider { get; }
bool MultipleWalletSelected { get; }
// Change events
event Func<string, Task> SelectedAccountChanged;
event Func<long, Task> NetworkChanged;
event Func<bool, Task> AvailabilityChanged;
event Func<bool, Task> EnabledChanged;
// Provider operations
Task<bool> CheckProviderAvailabilityAsync();
Task<IWeb3> GetWeb3Async();
Task<string> EnableProviderAsync();
Task<string> GetProviderSelectedAccountAsync();
Task<string> SignMessageAsync(string message);
}
SelectedEthereumHostProviderService
Service for managing the currently selected wallet provider:
public class SelectedEthereumHostProviderService
{
public IEthereumHostProvider SelectedHost { get; }
public event Func<IEthereumHostProvider, Task> SelectedHostProviderChanged;
Task SetSelectedEthereumHostProvider(IEthereumHostProvider provider);
Task ClearSelectedEthereumHostProvider();
}
NethereumSiweAuthenticatorService
SIWE authentication service integrating with wallet providers:
public class NethereumSiweAuthenticatorService
{
public NethereumSiweAuthenticatorService(
SelectedEthereumHostProviderService selectedEthereumHostProviderService,
ISessionStorage sessionStorage);
string GenerateNewSiweMessage(SiweMessage siweMessage);
Task<SiweMessage> AuthenticateAsync(SiweMessage siweMessage);
void LogOut(SiweMessage siweMessage);
}
Usage Examples
Example 1: Using Built-In Provider for Testing
using Nethereum.UI;
using Nethereum.Web3.Accounts;
// Create built-in provider with private key
var provider = new NethereumHostProvider();
// Set RPC URL and detect chain ID
await provider.SetUrl("https://mainnet.infura.io/v3/YOUR-PROJECT-ID");
// Set account
var account = new Account("0xYOUR_PRIVATE_KEY");
provider.SetSelectedAccount(account);
// Get Web3 instance
var web3 = await provider.GetWeb3Async();
var balance = await web3.Eth.GetBalance.SendRequestAsync(provider.SelectedAccount);
Example 2: Provider Selection Service
using Nethereum.UI;
// Create selection service
var selectionService = new SelectedEthereumHostProviderService();
// Subscribe to provider changes
selectionService.SelectedHostProviderChanged += async (provider) =>
{
if (provider != null)
{
Console.WriteLine($"Provider changed to: {provider.Name}");
Console.WriteLine($"Account: {provider.SelectedAccount}");
Console.WriteLine($"Chain ID: {provider.SelectedNetworkChainId}");
}
else
{
Console.WriteLine("Provider disconnected");
}
};
// Set provider
await selectionService.SetSelectedEthereumHostProvider(metamaskProvider);
// Later: switch providers
await selectionService.SetSelectedEthereumHostProvider(walletConnectProvider);
// Disconnect
await selectionService.ClearSelectedEthereumHostProvider();
Example 3: Listening to Account Changes
using Nethereum.UI;
var provider = new NethereumHostProvider();
// Subscribe to account changes
provider.SelectedAccountChanged += async (address) =>
{
Console.WriteLine($"Account changed to: {address}");
// Update UI, reload balances, etc.
var web3 = await provider.GetWeb3Async();
var balance = await web3.Eth.GetBalance.SendRequestAsync(address);
Console.WriteLine($"New account balance: {Web3.Convert.FromWei(balance)} ETH");
};
// Subscribe to network changes
provider.NetworkChanged += async (chainId) =>
{
Console.WriteLine($"Network changed to chain ID: {chainId}");
// Update UI, warn user, etc.
if (chainId != 1)
{
Console.WriteLine("Warning: Not connected to Ethereum mainnet");
}
};
// Set account (triggers event)
provider.SetSelectedAccount("0xPRIVATE_KEY");
// Change network (triggers event)
await provider.SetUrl("https://polygon-rpc.com");
Example 4: SIWE Authentication Flow
using Nethereum.UI;
using Nethereum.Siwe.Core;
// Setup services
var providerService = new SelectedEthereumHostProviderService();
var authService = new NethereumSiweAuthenticatorService(
providerService,
sessionStorage);
// Set provider (MetaMask, WalletConnect, etc.)
await providerService.SetSelectedEthereumHostProvider(metamaskProvider);
// Create SIWE message
var siweMessage = new SiweMessage
{
Domain = "example.com",
Address = providerService.SelectedHost.SelectedAccount,
Uri = "https://example.com/login",
Version = "1",
ChainId = providerService.SelectedHost.SelectedNetworkChainId,
Nonce = Guid.NewGuid().ToString(),
IssuedAt = DateTime.UtcNow.ToString("o")
};
try
{
// Authenticate (prompts wallet to sign)
var authenticatedMessage = await authService.AuthenticateAsync(siweMessage);
Console.WriteLine("Authentication successful!");
Console.WriteLine($"Authenticated address: {authenticatedMessage.Address}");
// User is now authenticated
}
catch (Exception ex)
{
Console.WriteLine($"Authentication failed: {ex.Message}");
}
// Later: log out
authService.LogOut(siweMessage);
Example 5: FluentValidation for Ethereum Data
using FluentValidation;
using Nethereum.UI.Validation;
public class TransferRequest
{
public string ToAddress { get; set; }
public string Amount { get; set; }
public string PrivateKey { get; set; }
}
public class TransferRequestValidator : AbstractValidator<TransferRequest>
{
public TransferRequestValidator()
{
RuleFor(x => x.ToAddress)
.NotEmpty()
.IsEthereumAddress(); // Custom Ethereum address validation
RuleFor(x => x.Amount)
.NotEmpty()
.Must(BeValidNumber)
.WithMessage("Invalid amount");
RuleFor(x => x.PrivateKey)
.IsEthereumPrivateKey(); // Validates hex format and length (66 chars)
}
private bool BeValidNumber(string value)
{
return decimal.TryParse(value, out _);
}
}
// Usage
var validator = new TransferRequestValidator();
var request = new TransferRequest
{
ToAddress = "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
Amount = "0.5",
PrivateKey = "0x..." // 64 hex chars
};
var result = validator.Validate(request);
if (!result.IsValid)
{
foreach (var error in result.Errors)
{
Console.WriteLine($"{error.PropertyName}: {error.ErrorMessage}");
}
}
Example 6: Data Annotation Validation (.NET Core 3.1+)
using System.ComponentModel.DataAnnotations;
using Nethereum.UI.Validation.Attributes;
public class WalletConnectionForm
{
[Required]
[EthereumAddress]
public string WalletAddress { get; set; }
[Required]
[Url]
public string RpcUrl { get; set; }
}
// Usage in ASP.NET Core / Blazor
var form = new WalletConnectionForm
{
WalletAddress = "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
RpcUrl = "https://mainnet.infura.io/v3/YOUR-PROJECT-ID"
};
var context = new ValidationContext(form);
var results = new List<ValidationResult>();
if (Validator.TryValidateObject(form, context, results, true))
{
Console.WriteLine("Form is valid");
}
else
{
foreach (var error in results)
{
Console.WriteLine(error.ErrorMessage);
}
}
Example 7: Custom Provider Implementation
using Nethereum.UI;
using System.Threading.Tasks;
public class MyCustomWalletProvider : IEthereumHostProvider
{
public string Name => "My Custom Wallet";
public bool Available { get; private set; }
public string SelectedAccount { get; private set; }
public long SelectedNetworkChainId { get; private set; }
public bool Enabled => Available && SelectedAccount != null;
public bool MultipleWalletsProvider => false;
public bool MultipleWalletSelected => false;
public event Func<string, Task> SelectedAccountChanged;
public event Func<long, Task> NetworkChanged;
public event Func<bool, Task> AvailabilityChanged;
public event Func<bool, Task> EnabledChanged;
public async Task<bool> CheckProviderAvailabilityAsync()
{
// Check if your wallet extension/app is available
Available = await CheckIfWalletIsInstalled();
await AvailabilityChanged?.Invoke(Available);
return Available;
}
public async Task<string> EnableProviderAsync()
{
// Request user permission to connect
SelectedAccount = await RequestAccountAccess();
await SelectedAccountChanged?.Invoke(SelectedAccount);
await EnabledChanged?.Invoke(true);
return SelectedAccount;
}
public Task<IWeb3> GetWeb3Async()
{
// Return Web3 instance connected to your wallet
return Task.FromResult(myWalletWeb3Instance);
}
public Task<string> GetProviderSelectedAccountAsync()
{
return Task.FromResult(SelectedAccount);
}
public async Task<string> SignMessageAsync(string message)
{
// Call your wallet's signing method
return await myWallet.SignMessageAsync(message);
}
private async Task<bool> CheckIfWalletIsInstalled() { /* ... */ }
private async Task<string> RequestAccountAccess() { /* ... */ }
}
Example 8: Hex and URI Validation
using FluentValidation;
using Nethereum.UI.Validation;
public class ContractInteractionForm
{
public string ContractAddress { get; set; }
public string FunctionData { get; set; }
public string RpcEndpoint { get; set; }
}
public class ContractInteractionValidator : AbstractValidator<ContractInteractionForm>
{
public ContractInteractionValidator()
{
RuleFor(x => x.ContractAddress)
.IsEthereumAddress()
.WithMessage("Please provide a valid Ethereum contract address");
RuleFor(x => x.FunctionData)
.IsHex()
.WithMessage("Function data must be valid hexadecimal with 0x prefix");
RuleFor(x => x.RpcEndpoint)
.IsUri()
.WithMessage("Please provide a valid RPC endpoint URL");
}
}
Available Validation Rules
FluentValidation Extensions
using Nethereum.UI.Validation;
// Ethereum address validation
RuleFor(x => x.Address).IsEthereumAddress();
// Hexadecimal data validation (must have 0x prefix)
RuleFor(x => x.Data).IsHex();
// Private key validation (0x + 64 hex chars = 66 total)
RuleFor(x => x.PrivateKey).IsEthereumPrivateKey();
// URI validation
RuleFor(x => x.Url).IsUri();
Data Annotation Attributes (.NET Core 3.1+)
using Nethereum.UI.Validation.Attributes;
[EthereumAddress]
public string Address { get; set; }
[Hex]
public string Data { get; set; }
API Reference
IEthereumHostProvider
public interface IEthereumHostProvider
{
// Properties
string Name { get; }
bool Available { get; }
string SelectedAccount { get; }
long SelectedNetworkChainId { get; }
bool Enabled { get; }
bool MultipleWalletsProvider { get; }
bool MultipleWalletSelected { get; }
// Events
event Func<string, Task> SelectedAccountChanged;
event Func<long, Task> NetworkChanged;
event Func<bool, Task> AvailabilityChanged;
event Func<bool, Task> EnabledChanged;
// Methods
Task<bool> CheckProviderAvailabilityAsync();
Task<IWeb3> GetWeb3Async();
Task<string> EnableProviderAsync();
Task<string> GetProviderSelectedAccountAsync();
Task<string> SignMessageAsync(string message);
}
NethereumHostProvider
Built-in provider for testing and development:
public class NethereumHostProvider : IEthereumHostProvider
{
void SetSelectedAccount(string privateKey);
void SetSelectedAccount(Account account);
Task<bool> SetUrl(string url);
}
SelectedEthereumHostProviderService
public class SelectedEthereumHostProviderService
{
public IEthereumHostProvider SelectedHost { get; }
public event Func<IEthereumHostProvider, Task> SelectedHostProviderChanged;
public Task SetSelectedEthereumHostProvider(IEthereumHostProvider provider);
public Task ClearSelectedEthereumHostProvider();
}
NethereumSiweAuthenticatorService
public class NethereumSiweAuthenticatorService
{
public NethereumSiweAuthenticatorService(
SelectedEthereumHostProviderService selectedEthereumHostProviderService,
ISessionStorage sessionStorage);
public string GenerateNewSiweMessage(SiweMessage siweMessage);
public Task<SiweMessage> AuthenticateAsync(SiweMessage siweMessage);
public void LogOut(SiweMessage siweMessage);
}
Important Notes
Provider Lifecycle
The IEthereumHostProvider interface follows this lifecycle:
- Check Availability:
CheckProviderAvailabilityAsync()- Check if wallet is installed/available - Enable Provider:
EnableProviderAsync()- Request user permission to connect - Get Account: Provider sets
SelectedAccountand firesSelectedAccountChangedevent - Get Web3:
GetWeb3Async()returns configured Web3 instance - Sign Messages:
SignMessageAsync()for SIWE and other signature requests
Event Handling
All provider change events are async:
provider.SelectedAccountChanged += async (account) =>
{
// Async operations allowed
await UpdateUserInterface(account);
};
Multi-Wallet Support
Some providers (like WalletConnect with multiple sessions) support multiple simultaneous wallet connections:
if (provider.MultipleWalletsProvider)
{
Console.WriteLine("This provider supports multiple wallets");
if (provider.MultipleWalletSelected)
{
Console.WriteLine("Multiple wallets are currently connected");
}
}
Validation Framework Support
Nethereum.UI provides validation through two approaches:
- FluentValidation - Full framework support across all .NET versions
- Data Annotations - Available in .NET Core 3.1+ only (conditional compilation)
Choose based on your target framework and preferences.
SIWE Authentication
SIWE authentication requires:
- Selected wallet provider with signing capability
- Session storage implementation (
ISessionStorage) - Valid SIWE message with all required fields
Related Packages
Implementations
- Nethereum.Metamask - MetaMask provider implementation
- Nethereum.Metamask.Blazor - Blazor-specific MetaMask provider
- Nethereum.WalletConnect - WalletConnect provider
- Nethereum.Reown.AppKit.Blazor - Reown AppKit provider for Blazor
- Nethereum.EIP6963WalletInterop - Multi-wallet discovery (EIP-6963)
UI Frameworks
- Nethereum.Blazor - Blazor components and services
- Nethereum.Wallet.UI.Components - Shared UI components
- Nethereum.Wallet.UI.Components.Blazor - Blazor wallet UI
- Nethereum.Wallet.UI.Components.Avalonia - Avalonia wallet UI
- Nethereum.Wallet.UI.Components.Maui - MAUI wallet UI
Dependencies
- Nethereum.Siwe - Sign-In with Ethereum
- Nethereum.Siwe.Core - SIWE core types
- FluentValidation - Validation framework
Additional Resources
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. 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. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 is compatible. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETFramework 4.7.2
- FluentValidation (>= 9.3.0)
- Nethereum.Siwe (>= 5.8.0)
- Nethereum.Siwe.Core (>= 5.8.0)
- Newtonsoft.Json (>= 11.0.2 && < 14.0.0)
-
.NETStandard 2.0
- FluentValidation (>= 9.3.0)
- Nethereum.Siwe (>= 5.8.0)
- Nethereum.Siwe.Core (>= 5.8.0)
- NETStandard.Library (>= 2.0.3)
- Newtonsoft.Json (>= 11.0.2 && < 14.0.0)
-
net6.0
- FluentValidation (>= 9.3.0)
- Nethereum.Siwe (>= 5.8.0)
- Nethereum.Siwe.Core (>= 5.8.0)
- Newtonsoft.Json (>= 11.0.2 && < 14.0.0)
-
net8.0
- FluentValidation (>= 9.3.0)
- Nethereum.Siwe (>= 5.8.0)
- Nethereum.Siwe.Core (>= 5.8.0)
- Newtonsoft.Json (>= 11.0.2 && < 14.0.0)
-
net9.0
- FluentValidation (>= 9.3.0)
- Nethereum.Siwe (>= 5.8.0)
- Nethereum.Siwe.Core (>= 5.8.0)
- Newtonsoft.Json (>= 11.0.2 && < 14.0.0)
NuGet packages (6)
Showing the top 5 NuGet packages that depend on Nethereum.UI:
| Package | Downloads |
|---|---|
|
Nethereum.Metamask
Nethereum.Metamask Nethereum Metamask core integration |
|
|
Nethereum.WalletConnect
Nethereum.WalletConnect Nethereum WalletConnect integration |
|
|
Nethereum.EIP6963WalletInterop
Nethereum.EIP6963WalletInterop Nethereum EIP6963 Browser Wallet Extension Interop, core components to integrate with browser extensions like Metamask, Coinbase, Brave, Rabby, Rainbow, and many more see https://eips.ethereum.org/EIPS/eip-6963 and https://eip6963.org/ |
|
|
Nethereum.Reown.AppKit.Blazor
Nethereum.Reown.AppKit.Blazor Nethereum Reown AppKit integration with Blazor |
|
|
Nethereum.MudBlazorComponents
Nethereum.MudBlazorComponents Nethereum MudBlazor Components to dynamically generate Deploy, Transact and Query smart contracts user interfaces using Deployment and Function Typed Messages or Nethereum Services. Mud.dev Table components to query and upsert data using TableServices. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 5.8.0 | 669 | 1/6/2026 |
| 5.0.0 | 1,197 | 5/28/2025 |
| 4.29.0 | 652 | 2/10/2025 |
| 4.28.0 | 464 | 1/7/2025 |
| 4.27.1 | 358 | 12/24/2024 |
| 4.27.0 | 335 | 12/24/2024 |
| 4.26.0 | 558 | 10/1/2024 |
| 4.25.0 | 433 | 9/19/2024 |
| 4.21.4 | 1,387 | 8/9/2024 |
| 4.21.3 | 516 | 7/22/2024 |
| 4.21.2 | 615 | 6/26/2024 |
| 4.21.1 | 359 | 6/26/2024 |
| 4.21.0 | 757 | 6/18/2024 |
| 4.20.0 | 1,892 | 3/28/2024 |
| 4.19.0 | 733 | 2/16/2024 |
| 4.18.0 | 828 | 11/21/2023 |
| 4.17.1 | 566 | 9/28/2023 |
| 4.17.0 | 394 | 9/27/2023 |
| 4.16.0 | 430 | 8/14/2023 |
| 4.15.2 | 552 | 7/11/2023 |