Nethereum.Wallet.UI.Components
5.8.0
Prefix Reserved
dotnet add package Nethereum.Wallet.UI.Components --version 5.8.0
NuGet\Install-Package Nethereum.Wallet.UI.Components -Version 5.8.0
<PackageReference Include="Nethereum.Wallet.UI.Components" Version="5.8.0" />
<PackageVersion Include="Nethereum.Wallet.UI.Components" Version="5.8.0" />
<PackageReference Include="Nethereum.Wallet.UI.Components" />
paket add Nethereum.Wallet.UI.Components --version 5.8.0
#r "nuget: Nethereum.Wallet.UI.Components, 5.8.0"
#:package Nethereum.Wallet.UI.Components@5.8.0
#addin nuget:?package=Nethereum.Wallet.UI.Components&version=5.8.0
#tool nuget:?package=Nethereum.Wallet.UI.Components&version=5.8.0
Nethereum.Wallet.UI.Components
Platform-agnostic wallet UI components, view models, and services for Nethereum applications. Provides MVVM-based ViewModels and business logic that can be consumed by any UI framework (Blazor, Avalonia, MAUI, etc.).
Installation
dotnet add package Nethereum.Wallet.UI.Components
Target Framework
- net9.0
Dependencies
NuGet Packages
- CommunityToolkit.Mvvm 8.4.0 - MVVM framework
- Microsoft.AspNetCore.Components.WebAssembly 9.0.0 - Razor component support
- Microsoft.Extensions.Hosting.Abstractions 9.0.0 - Hosted service abstractions
Nethereum Packages
- Nethereum.DataServices - Chain data and 4Byte directory services
- Nethereum.RPC - RPC client functionality
- Nethereum.Wallet - Core wallet types and services
Source: Nethereum.Wallet.UI.Components.csproj:16-26
Architecture
This package implements a platform-agnostic MVVM architecture using registry patterns for extensibility. UI framework-specific packages (Blazor, Avalonia, MAUI) consume these ViewModels and provide platform-specific UI components.
Core Design Patterns
1. Registry Pattern for Extensibility
IComponentRegistry - Maps ViewModels to UI components
public interface IComponentRegistry
{
void Register<TViewModel, TComponent>()
where TViewModel : class
where TComponent : class;
Type? GetComponentType<TViewModel>() where TViewModel : class;
IEnumerable<Type> GetRegisteredViewModelTypes();
}
Source: Core/Registry/IComponentRegistry.cs:6-15
Implementation uses ConcurrentDictionary<Type, Type> for thread-safe registration.
Source: Core/Registry/ComponentRegistry.cs:9
2. Account Type Registry System
IAccountCreationRegistry - Manages account creation ViewModels
public interface IAccountCreationRegistry
{
void Register<TViewModel, TComponent>()
where TViewModel : class, IAccountCreationViewModel
where TComponent : class;
IEnumerable<IAccountCreationViewModel> GetAvailableAccountTypes();
Type? GetComponentType(IAccountCreationViewModel viewModel);
}
Source: WalletAccounts/IAccountCreationRegistry.cs:6-14
Returns ViewModels filtered by IsVisible and ordered by SortOrder:
Source: WalletAccounts/AccountCreationRegistry.cs:32-34
IAccountTypeMetadataRegistry - Provides account type metadata
public interface IAccountTypeMetadataRegistry
{
IAccountTypeMetadata? GetMetadata(string accountType);
IEnumerable<IAccountTypeMetadata> GetAllMetadata();
IEnumerable<IAccountTypeMetadata> GetVisibleMetadata();
bool HasMetadata(string accountType);
}
Source: WalletAccounts/IAccountTypeMetadataRegistry.cs:5-11
Performs case-insensitive TypeName matching. Source: WalletAccounts/AccountTypeMetadataRegistry.cs:24-25
3. Dashboard Plugin System
IDashboardPluginRegistry - Manages dashboard plugins
public interface IDashboardPluginRegistry
{
IEnumerable<IDashboardPluginViewModel> GetAvailablePlugins();
IDashboardPluginViewModel? GetPlugin(string pluginId);
Type? GetComponentType(IDashboardPluginViewModel viewModel);
}
Source: Dashboard/IDashboardPluginRegistry.cs:6-12
Returns plugins filtered by IsVisible && IsEnabled && IsAvailable() and ordered by SortOrder.
Source: Dashboard/DashboardPluginRegistry.cs:26
IDashboardPluginViewModel interface:
public interface IDashboardPluginViewModel
{
string PluginId { get; }
string DisplayName { get; }
string Description { get; }
string Icon { get; }
int SortOrder { get; }
bool IsVisible { get; }
bool IsEnabled { get; }
bool IsAvailable();
}
Source: Dashboard/IDashboardPluginViewModel.cs:5-16
4. Account Details Registry
IAccountDetailsRegistry - Maps account types to detail ViewModels
public interface IAccountDetailsRegistry
{
void Register<TViewModel, TComponent>()
where TViewModel : class, IAccountDetailsViewModel
where TComponent : class;
Type? GetViewModelType(IWalletAccount account);
Type? GetComponentType(Type viewModelType);
}
Source: AccountDetails/IAccountDetailsRegistry.cs:7-17
Iterates ViewModels calling CanHandle(account) to find appropriate ViewModel.
Source: AccountDetails/AccountDetailsRegistry.cs:53-60
5. Group Details Registry
GroupDetailsRegistry - Manages group detail views (e.g., Trezor device groups)
public Type? GetViewModelType(string groupId, IReadOnlyList<IWalletAccount> groupAccounts)
{
var availableViewModels = GetAvailableGroupDetailTypes();
foreach (var viewModel in availableViewModels)
{
if (viewModel.CanHandle(groupId, groupAccounts))
{
return viewModel.GetType();
}
}
return null;
}
Source: AccountDetails/GroupDetailsRegistry.cs:48-61
6. Registry Contributor Pattern
IWalletUIRegistryContributor - Allows external packages to register UI components
public interface IWalletUIRegistryContributor
{
void Configure(IServiceProvider serviceProvider);
}
Source: WalletAccounts/IWalletUIRegistryContributor.cs:9-12
Enables packages like Nethereum.Wallet.UI.Components.Trezor to register their ViewModels and components into the registry during startup.
Account Type System
Built-in Account Types
1. Mnemonic (HD Wallet)
MnemonicAccountCreationViewModel - Create/import HD wallet accounts
Properties:
string Mnemonic { get; set; } // BIP-39 mnemonic phrase
string MnemonicLabel { get; set; } // User-friendly name
string MnemonicPassphrase { get; set; } // Optional BIP-39 passphrase
bool IsRevealed { get; set; } // Show/hide mnemonic
bool IsBackedUp { get; set; } // User confirmed backup
bool IsGenerateMode { get; set; } // true = generate, false = import
int WordCount { get; set; } // 12 or 24 words
Source: WalletAccounts/Mnemonic/MnemonicAccountCreationViewModel.cs:22-50
Commands:
GenerateMnemonicAsync()- Generates 12-word mnemonicGenerateMnemonic24Async()- Generates 24-word mnemonicToggleRevealAsync()- Show/hide mnemonicConfirmBackupAsync()- Mark as backed upSwitchToImportModeAsync()/SwitchToGenerateModeAsync()- Toggle mode
Source: WalletAccounts/Mnemonic/MnemonicAccountCreationViewModel.cs:66-147
Mnemonic Validation:
public (bool IsValid, string Message) ValidateMnemonic()
{
if (string.IsNullOrWhiteSpace(Mnemonic))
return (false, "Mnemonic phrase is required");
var words = Mnemonic.Trim().Split(' ', StringSplitOptions.RemoveEmptyEntries);
if (words.Length != 12 && words.Length != 24)
return (false, $"Mnemonic must be 12 or 24 words (found {words.Length})");
try
{
var hdWallet = new MinimalHDWallet(Mnemonic, MnemonicPassphrase);
var account = hdWallet.GetAccount(0);
return (true, "Valid mnemonic phrase");
}
catch
{
return (false, "Invalid mnemonic phrase");
}
}
Source: WalletAccounts/Mnemonic/MnemonicAccountCreationViewModel.cs:180-210
Account Creation:
public override IWalletAccount CreateAccount(WalletVault vault)
{
var hdWallet = new MinimalHDWallet(Mnemonic, MnemonicPassphrase);
var mnemonicAccount = new MnemonicWalletAccount
{
MnemonicId = Guid.NewGuid().ToString(),
Name = MnemonicLabel,
EncryptedMnemonic = vault.EncryptData(Mnemonic),
EncryptedPassphrase = string.IsNullOrEmpty(MnemonicPassphrase)
? null
: vault.EncryptData(MnemonicPassphrase),
CreatedAt = DateTime.UtcNow
};
var account = hdWallet.GetAccount(0);
var walletAccount = new MnemonicWalletAccountItem
{
Id = Guid.NewGuid().ToString(),
Name = $"{MnemonicLabel} - Account 1",
Address = account.Address,
Index = 0,
MnemonicId = mnemonicAccount.MnemonicId,
// ...
};
return walletAccount;
}
Source: WalletAccounts/Mnemonic/MnemonicAccountCreationViewModel.cs:224-257
MnemonicAccountDetailsViewModel - View/manage HD wallet account details
Commands:
RemoveAccountAsync()- Delete account with confirmationSaveAccountNameAsync()- Update account nameRevealPrivateKeyAsync(password)- Show private key with password confirmation
Source: WalletAccounts/Mnemonic/MnemonicAccountDetailsViewModel.cs:88-254
Derivation Path:
public string GetDerivationPath()
{
var index = GetAccountIndex();
return $"m/44'/60'/0'/0/{index}"; // BIP-44 Ethereum path
}
Source: WalletAccounts/Mnemonic/MnemonicAccountDetailsViewModel.cs:262-269
VaultMnemonicAccountViewModel - Create account from existing vault mnemonic
Form Steps:
public enum FormStep
{
SelectMnemonic, // Choose from vault mnemonics
Configure, // Set account index
Confirm // Review and create
}
Source: WalletAccounts/Mnemonic/VaultMnemonicAccountViewModel.cs:28-33
Properties:
string SelectedMnemonicId { get; set; }
int AccountIndex { get; set; } // Derivation index
string DerivedAddress { get; set; } // Preview address
List<MnemonicInfo> AvailableMnemonics { get; set; }
Source: WalletAccounts/Mnemonic/VaultMnemonicAccountViewModel.cs:35-40
MnemonicListViewModel - Manage vault mnemonics
Commands:
LoadMnemonicsAsync()- Load all mnemonics from vaultDeleteMnemonicAsync(MnemonicItemViewModel)- Delete mnemonic with validation
Source: WalletAccounts/Mnemonic/MnemonicListViewModel.cs:51-148
Validates that no accounts reference the mnemonic before deletion. Source: WalletAccounts/Mnemonic/MnemonicListViewModel.cs:113-130
2. Private Key
PrivateKeyAccountCreationViewModel - Import account from private key
Properties:
string PrivateKey { get; set; } // 64 hex characters
string Label { get; set; } // Account name
bool IsRevealed { get; set; } // Show/hide private key
string DerivedAddress { get; set; } // Calculated address
bool IsValidPrivateKey { get; set; } // Validation result
string PrivateKeyFormat { get; set; } // Format description
Source: WalletAccounts/PrivateKey/PrivateKeyAccountCreationViewModel.cs:40-48
Validation:
public (bool IsValid, string Message) ValidatePrivateKey()
{
if (string.IsNullOrWhiteSpace(PrivateKey))
return (false, "Private key is required");
var cleanKey = CleanPrivateKey(PrivateKey);
if (cleanKey.Length != 64)
return (false, $"Private key must be 64 hexadecimal characters (found {cleanKey.Length})");
if (!System.Text.RegularExpressions.Regex.IsMatch(cleanKey, "^[0-9a-fA-F]{64}$"))
return (false, "Private key must contain only hexadecimal characters (0-9, a-f, A-F)");
if (cleanKey.All(c => c == '0'))
return (false, "Private key cannot be all zeros");
try
{
var key = new EthECKey(cleanKey);
DerivedAddress = key.GetPublicAddress();
return (true, "Valid private key");
}
catch
{
return (false, "Invalid private key format");
}
}
Source: WalletAccounts/PrivateKey/PrivateKeyAccountCreationViewModel.cs:93-120
Cleans input by removing "0x" prefix. Source: WalletAccounts/PrivateKey/PrivateKeyAccountCreationViewModel.cs:122-133
PrivateKeyAccountDetailsViewModel - View/manage private key account
Commands:
SaveAccountName()- Update account nameRevealPrivateKey(password)- Show private key with password protectionRemoveAccount()- Delete account
Source: WalletAccounts/PrivateKey/PrivateKeyAccountDetailsViewModel.cs:82-231
3. View-Only
ViewOnlyAccountCreationViewModel - Watch-only account
Properties:
string ViewOnlyAddress { get; set; } // Ethereum address to watch
string Label { get; set; } // Account name
Source: WalletAccounts/ViewOnly/ViewOnlyAccountCreationViewModel.cs:18-19
Validation:
- Address must start with "0x"
- Address must be 42 characters (20 bytes)
Source: WalletAccounts/ViewOnly/ViewOnlyAccountCreationViewModel.cs:32-34
Creates ViewOnlyWalletAccount with no private key operations.
Source: WalletAccounts/ViewOnly/ViewOnlyAccountCreationViewModel.cs:46
ViewOnlyAccountDetailsViewModel - Read-only account operations
No private key or signing operations available. Can only view balances and transaction history. Source: WalletAccounts/ViewOnly/ViewOnlyAccountDetailsViewModel.cs:14-185
4. Smart Contract (Account Abstraction)
SmartContractAccountCreationViewModel - ERC-4337 account abstraction
Properties:
string Address { get; set; } // Smart contract address
string Label { get; set; } // Account name
Source: WalletAccounts/SmartContract/SmartContractAccountCreationViewModel.cs:18-19
Supports ERC-4337, Safe, and Argent wallet contracts. Source: WalletAccounts/SmartContract/SmartContractAccountMetadataViewModel.cs
Account Type Extensibility
IAccountCreationViewModel interface:
public interface IAccountCreationViewModel
{
string DisplayName { get; }
string Description { get; }
string Icon { get; }
int SortOrder { get; }
bool IsVisible { get; }
bool CanCreateAccount { get; }
IWalletAccount CreateAccount(WalletVault vault);
void Reset();
}
Source: WalletAccounts/IAccountCreationViewModel.cs:5-15
IAccountTypeMetadata interface:
public interface IAccountTypeMetadata
{
string TypeName { get; }
string DisplayName { get; }
string Description { get; }
string Icon { get; }
string ColorTheme { get; }
int SortOrder { get; }
bool IsVisible { get; }
}
Source: WalletAccounts/IAccountTypeMetadata.cs:3-13
IAccountDetailsViewModel interface:
public interface IAccountDetailsViewModel
{
string AccountType { get; }
bool CanHandle(IWalletAccount account);
Task InitializeAsync(IWalletAccount account);
}
Source: AccountDetails/IAccountDetailsViewModel.cs
Custom account types can be added by implementing these interfaces and registering via IWalletUIRegistryContributor.
Network Management
Add Custom Network
AddCustomNetworkViewModel - Configure custom EVM networks
Dependencies:
private readonly IChainManagementService _chainManagement;
private readonly IRpcEndpointService _rpcEndpointService;
Source: Networks/AddCustomNetworkViewModel.cs:14-15
Properties:
NetworkConfiguration Network { get; set; }
bool IsFormValid { get; }
Source: Networks/AddCustomNetworkViewModel.cs:17-25
Commands:
SaveNetworkAsync() // Add/update network
TestRpcEndpointAsync(RpcEndpointInfo) // Test RPC connectivity
AddRpcEndpoint() // Add RPC URL
RemoveRpcEndpoint(RpcEndpointInfo) // Remove RPC URL
AddBlockExplorer() // Add explorer URL
RemoveBlockExplorer(BlockExplorerInfo) // Remove explorer URL
Source: Networks/AddCustomNetworkViewModel.cs:38-141
NetworkConfiguration model:
public class NetworkConfiguration
{
public BigInteger ChainId { get; set; }
public string ChainName { get; set; }
public string CurrencySymbol { get; set; }
public string CurrencyName { get; set; }
public int CurrencyDecimals { get; set; }
public List<RpcEndpointInfo> RpcEndpoints { get; set; }
public List<BlockExplorerInfo> BlockExplorers { get; set; }
public bool IsTestnet { get; set; }
public string? IconUrl { get; set; }
}
Source: Networks/Models/NetworkConfiguration.cs
RpcEndpointInfo model:
public class RpcEndpointInfo
{
public string Url { get; set; }
public bool IsWebSocket { get; set; }
public bool IsEnabled { get; set; }
public bool IsHealthy { get; set; }
public string? TestResult { get; set; }
public bool IsTesting { get; set; }
public bool IsCustom { get; set; }
// Display properties
public string TypeDisplayName => IsWebSocket ? "WebSocket" : "HTTP";
public string StatusDisplayName => IsEnabled ? "Active" : "Inactive";
public string HealthDisplayName => IsHealthy ? "Healthy" : "Unhealthy";
}
Source: Networks/Models/RpcEndpointInfo.cs:5-25
NetworkManagementPluginViewModel - Dashboard plugin for network management
Implements IDashboardPluginViewModel.
Source: Networks/NetworkManagementPluginViewModel.cs:12-36
Network Provider Service
INetworkProviderService - Default network configuration
public interface INetworkProviderService
{
Task<List<ChainFeature>> GetDefaultNetworksAsync();
}
Source: Abstractions/INetworkProviderService.cs:7-10
Transaction Management
Native Token Transfer
TokenNativeTransferModel - Native cryptocurrency transfer model
Validation Attributes:
[EthereumAddress]
public string RecipientAddress { get; set; }
[Required]
public string Amount { get; set; }
[Hex]
public string TransactionData { get; set; }
Source: SendTransaction/Models/TokenNativeTransferModel.cs:28-49
Properties:
BigInteger AvailableBalance { get; set; }
string TokenSymbol { get; set; } // e.g., "ETH"
int TokenDecimals { get; set; } // e.g., 18
string Nonce { get; set; }
Source: SendTransaction/Models/TokenNativeTransferModel.cs:36-49
Methods:
BigInteger GetTransferAmountInSmallestUnit()
{
return UnitConversion.Convert.ToWei(decimal.Parse(Amount), TokenDecimals);
}
Source: SendTransaction/Models/TokenNativeTransferModel.cs:53-54
public string FormattedAvailableBalance
{
get
{
if (AvailableBalance == 0) return "0";
var balance = UnitConversion.Convert.FromWei(AvailableBalance, TokenDecimals);
// Format based on size
if (balance >= 1000000m) return $"{balance / 1000000m:N2}M";
if (balance >= 1000m) return $"{balance / 1000m:N2}K";
if (balance >= 1m) return $"{balance:N4}";
if (balance >= 0.0001m) return $"{balance:N6}";
return $"{balance:N8}";
}
}
Source: SendTransaction/Models/TokenNativeTransferModel.cs:56-74
public (bool IsValid, string Message) ValidateAmountBalance()
{
if (!decimal.TryParse(Amount, out var amount))
return (false, "Invalid amount format");
if (amount <= 0)
return (false, "Amount must be greater than zero");
var transferAmount = GetTransferAmountInSmallestUnit();
if (transferAmount > AvailableBalance)
return (false, $"Insufficient balance. Available: {FormattedAvailableBalance} {TokenSymbol}");
return (true, string.Empty);
}
Source: SendTransaction/Models/TokenNativeTransferModel.cs:153-167
public void SetMaxAmount()
{
var maxBalance = UnitConversion.Convert.FromWei(AvailableBalance, TokenDecimals);
Amount = maxBalance.ToString("F18").TrimEnd('0').TrimEnd('.');
}
Source: SendTransaction/Models/TokenNativeTransferModel.cs:181-188
Gas Strategy
GasStrategy enum:
public enum GasStrategy
{
Slow,
Normal,
Fast,
Custom
}
Source: SendTransaction/Models/GasStrategy.cs:3-9
GasStrategyDisplay - Gas estimation data:
public class GasStrategyDisplay
{
public GasStrategy Strategy { get; set; }
public string? EstimatedTime { get; set; }
public string? EstimatedCost { get; set; }
public BigInteger? MaxFee { get; set; } // EIP-1559
public BigInteger? PriorityFee { get; set; } // EIP-1559
public BigInteger? GasPrice { get; set; } // Legacy
}
Source: SendTransaction/Models/GasStrategyDisplay.cs:5-14
GasMultiplierOption - Pre-defined gas multipliers:
public static GasMultiplierOption Economy = new()
{
Multiplier = 0.8m,
DisplayName = "Economy",
Description = "Lower fees, slower confirmation",
Icon = "savings"
};
public static GasMultiplierOption Standard = new()
{
Multiplier = 1.0m,
DisplayName = "Standard",
Description = "Recommended for most transactions",
Icon = "check_circle",
IsRecommended = true
};
public static GasMultiplierOption Priority = new()
{
Multiplier = 1.2m,
DisplayName = "Priority",
Description = "Higher fees, faster confirmation",
Icon = "bolt"
};
Source: SendTransaction/Models/GasMultiplierOption.cs:11-34
Transaction Monitoring
TransactionMonitoringService - Background transaction monitoring
Implements IHostedService:
public class TransactionMonitoringService : IHostedService, IDisposable
{
private readonly IPendingTransactionService _pendingTransactionService;
public async Task StartAsync(CancellationToken cancellationToken)
{
await _pendingTransactionService.StartMonitoring();
}
public async Task StopAsync(CancellationToken cancellationToken)
{
await _pendingTransactionService.StopMonitoring();
}
}
Source: Transactions/TransactionMonitoringService.cs:10-41
Registered via AddTransactionServices() extension.
Source: Transactions/TransactionServiceCollectionExtensions.cs:19
Transaction Steps
SendTransactionStep enum:
public enum SendTransactionStep
{
Input, // Enter recipient and amount
Configure, // Gas configuration
Confirm, // Review transaction
Processing, // Submitting transaction
Complete // Transaction submitted
}
Source: SendTransaction/Models/SendTransactionStep.cs
Configuration System
Base Configuration
BaseWalletConfiguration - Abstract base for component configuration
Properties:
string ComponentId { get; set; } // Unique ID
WalletFlowMode FlowMode { get; set; } // Simple/Advanced/Custom
WalletTextConfiguration Text { get; set; }
WalletBehaviorConfiguration Behavior { get; set; }
WalletSecurityConfiguration Security { get; set; }
Source: Core/Configuration/BaseWalletConfiguration.cs:5-11
WalletFlowMode enum:
public enum WalletFlowMode
{
Simple, // Simplified UI for basic users
Advanced, // Full feature set
Custom // Fully customizable
}
Source: Core/Configuration/BaseWalletConfiguration.cs:35-40
WalletTextConfiguration - UI text customization:
public class WalletTextConfiguration
{
public string LoginTitle { get; set; } = "Welcome Back";
public string LoginSubtitle { get; set; } = "Enter your password to unlock your wallet";
public string LoginButtonText { get; set; } = "Unlock Wallet";
public string CreateTitle { get; set; } = "Create New Wallet";
public string CreateSubtitle { get; set; } = "Set up a new wallet vault to securely store your accounts";
public string CreateButtonText { get; set; } = "Create Wallet";
public string PasswordLabel { get; set; } = "Password";
public string CreatePasswordLabel { get; set; } = "Create Password";
public string ConfirmPasswordLabel { get; set; } = "Confirm Password";
public string PasswordHelperText { get; set; } = "Choose a strong password to protect your wallet";
// ... additional properties
}
Source: Core/Configuration/BaseWalletConfiguration.cs:41-67
WalletBehaviorConfiguration - Feature toggles:
public class WalletBehaviorConfiguration
{
public bool EnableWalletReset { get; set; } = false;
public bool AutoFocusPasswordField { get; set; } = true;
public bool ShowPasswordStrengthIndicator { get; set; } = true;
public bool EnablePasswordVisibilityToggle { get; set; } = true;
public bool AutoSaveProgress { get; set; } = true;
public int AutoSaveIntervalSeconds { get; set; } = 30;
public bool ValidatePasswordStrength { get; set; } = true;
public bool EnableFormValidation { get; set; } = true;
public bool ShowLoadingIndicators { get; set; } = true;
public int OperationTimeoutSeconds { get; set; } = 60;
}
Source: Core/Configuration/BaseWalletConfiguration.cs:68-80
WalletSecurityConfiguration - Security settings:
public class WalletSecurityConfiguration
{
public int MinPasswordLength { get; set; } = 8;
public int MaxPasswordLength { get; set; } = 128;
public bool RequireUppercasePassword { get; set; } = true;
public bool RequireLowercasePassword { get; set; } = true;
public bool RequireNumericPassword { get; set; } = true;
public bool RequireSpecialCharacterPassword { get; set; } = true;
public bool EnableRateLimiting { get; set; } = false;
public int MaxLoginAttempts { get; set; } = 5;
public int RateLimitWindowMinutes { get; set; } = 15;
public bool EnableSessionTimeout { get; set; } = true;
public int SessionTimeoutMinutes { get; set; } = 30;
public bool RequirePasswordConfirmation { get; set; } = true;
public bool EnableSecurityLogging { get; set; } = true;
}
Source: Core/Configuration/BaseWalletConfiguration.cs:81-96
Configuration Builder Pattern
BaseWalletConfigurationBuilder - Fluent API for configuration:
public abstract class BaseWalletConfigurationBuilder<TConfiguration, TBuilder>
where TConfiguration : BaseWalletConfiguration, new()
where TBuilder : BaseWalletConfigurationBuilder<TConfiguration, TBuilder>
{
public TBuilder UseSimpleFlow() { ... }
public TBuilder UseAdvancedFlow() { ... }
public TBuilder WithTitle(string title) { ... }
public TBuilder EnableWalletReset(bool enable = true) { ... }
public TBuilder WithMinPasswordLength(int length) { ... }
public TBuilder ConfigureText(Action<WalletTextConfiguration> configure) { ... }
public TBuilder ConfigureBehavior(Action<WalletBehaviorConfiguration> configure) { ... }
public TBuilder ConfigureSecurity(Action<WalletSecurityConfiguration> configure) { ... }
public TConfiguration Build() => _config;
}
Source: Core/Configuration/BaseWalletConfiguration.cs:97-168
Component-Specific Configurations
AccountListConfiguration:
public class AccountListConfiguration : BaseWalletConfiguration
{
public bool ShowBalances { get; set; } = true;
public bool AllowAccountDeletion { get; set; } = true;
public bool AllowAccountEditing { get; set; } = true;
public int AccountsPerPage { get; set; } = 10;
}
Source: AccountList/AccountListConfiguration.cs:5-13
WalletOverviewConfiguration:
public class WalletOverviewConfiguration : BaseWalletConfiguration
{
public bool ShowBalance { get; set; } = true;
public bool ShowFiatBalance { get; set; } = false;
public bool ShowQuickActions { get; set; } = true;
public bool AutoRefreshBalance { get; set; } = false;
public int AutoRefreshIntervalSeconds { get; set; } = 30;
}
Source: WalletOverview/WalletOverviewConfiguration.cs:5-14
CreateAccountConfiguration:
public class CreateAccountConfiguration : BaseWalletConfiguration
{
public bool ShowAdvancedOptions { get; set; } = false;
}
Source: CreateAccount/CreateAccountConfiguration.cs:5-11
NethereumWalletConfiguration:
public class NethereumWalletConfiguration : BaseWalletConfiguration
{
public bool ShowProgressIndicators { get; set; } = true;
public bool EnableKeyboardShortcuts { get; set; } = true;
public int PasswordMinimumStrength { get; set; } = 1;
public bool AllowPasswordVisibilityToggle { get; set; } = true;
public bool ShowPasswordStrengthIndicator { get; set; } = true;
}
Source: NethereumWallet/NethereumWalletConfiguration.cs:7-15
Localization System
Localization Service
IWalletLocalizationService - Multi-language support
public interface IWalletLocalizationService
{
string CurrentLanguage { get; }
CultureInfo CurrentCulture { get; }
IReadOnlyList<LanguageInfo> AvailableLanguages { get; }
event Action<string> LanguageChanged;
Task SetLanguageAsync(string languageCode);
Task<string> DetectAndSetLanguageAsync();
void RegisterTranslations(string componentName, string language, Dictionary<string, string> translations);
void OverrideTranslation(string componentName, string language, string key, string value);
string GetTranslation(string componentName, string language, string key);
string GetTranslation(string componentName, string language, string key, params object[] args);
IComponentLocalizer<T> GetLocalizer<T>();
void RegisterLocalizer<T>(IComponentLocalizer<T> localizer);
}
Source: Core/Localization/IWalletLocalizationService.cs:8-26
LanguageInfo model:
public class LanguageInfo
{
public string Code { get; set; } // e.g., "en"
public string Name { get; set; } // e.g., "English"
public string NativeName { get; set; } // e.g., "English"
public bool IsRTL { get; set; } // Right-to-left support
public string Culture { get; set; } // e.g., "en-US"
}
Source: Core/Localization/IWalletLocalizationService.cs:27-34
WalletLocalizationService implementation:
Supported Languages (default):
public IReadOnlyList<LanguageInfo> AvailableLanguages { get; } = new List<LanguageInfo>
{
new LanguageInfo { Code = "en", Name = "English", NativeName = "English", Culture = "en-US" },
new LanguageInfo { Code = "es", Name = "Spanish", NativeName = "Español", Culture = "es-ES" }
};
Source: Core/Localization/WalletLocalizationService.cs:20-24
Translation Lookup Algorithm:
- Try exact culture match (e.g., "es-ES")
- Try language default mapping (e.g., "es" → "es-ES")
- Fallback to default language
- Return key if not found
Source: Core/Localization/WalletLocalizationService.cs:98-129
Storage Providers
ILocalizationStorageProvider - Platform abstraction:
public interface ILocalizationStorageProvider
{
Task<string?> GetStoredLanguageAsync();
Task SetStoredLanguageAsync(string languageCode);
Task<string?> GetSystemLanguageAsync();
}
Source: Core/Localization/ILocalizationStorageProvider.cs:5-10
BrowserLocalizationStorageProvider - Browser localStorage:
public class BrowserLocalizationStorageProvider : ILocalizationStorageProvider
{
private readonly IJSRuntime _jsRuntime;
private const string StorageKey = "wallet-ui-language";
public async Task<string?> GetStoredLanguageAsync()
{
return await _jsRuntime.InvokeAsync<string>("localStorage.getItem", StorageKey);
}
public async Task SetStoredLanguageAsync(string languageCode)
{
await _jsRuntime.InvokeVoidAsync("localStorage.setItem", StorageKey, languageCode);
}
public async Task<string?> GetSystemLanguageAsync()
{
return await _jsRuntime.InvokeAsync<string>("eval", "navigator.language || navigator.userLanguage");
}
}
Source: Core/Localization/BrowserLocalizationStorageProvider.cs:7-51
SystemLocalizationStorageProvider - File-based storage:
public class SystemLocalizationStorageProvider : ILocalizationStorageProvider
{
private string GetLanguageFilePath()
{
var appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
var walletPath = Path.Combine(appDataPath, "NethereumWallet");
Directory.CreateDirectory(walletPath);
return Path.Combine(walletPath, "language.txt");
}
public async Task<string?> GetSystemLanguageAsync()
{
return CultureInfo.CurrentUICulture.Name;
}
}
Source: Core/Localization/SystemLocalizationStorageProvider.cs:8-53
Component Localizer
ComponentLocalizerBase<T> - Type-safe localization:
public abstract class ComponentLocalizerBase<T>
{
protected readonly IWalletLocalizationService LocalizationService;
protected ComponentLocalizerBase(IWalletLocalizationService localizationService)
{
LocalizationService = localizationService;
RegisterTranslations();
}
public string GetString(string key)
{
return LocalizationService.GetTranslation(typeof(T).Name, LocalizationService.CurrentLanguage, key);
}
public string GetString(string key, params object[] args)
{
return LocalizationService.GetTranslation(typeof(T).Name, LocalizationService.CurrentLanguage, key, args);
}
protected abstract void RegisterTranslations();
}
Source: Core/Localization/ComponentLocalizerBase.cs:5-28
Dashboard Navigation
IDashboardNavigationService - Plugin navigation
public interface IDashboardNavigationService
{
event NavigationRequestedHandler? NavigationRequested;
string? CurrentPluginId { get; }
object? CurrentPluginComponent { get; }
Task NavigateToPluginAsync(string pluginId, Dictionary<string, object>? parameters = null);
Task NavigateCurrentPluginAsync(Dictionary<string, object> parameters);
void RegisterActivePlugin(string pluginId, object? pluginComponent);
}
Source: Dashboard/Services/IDashboardNavigationService.cs:6-26
DashboardNavigationService implementation:
public async Task NavigateToPluginAsync(string pluginId, Dictionary<string, object>? parameters = null)
{
CurrentPluginId = pluginId;
NavigationRequested?.Invoke(pluginId, parameters ?? new Dictionary<string, object>());
}
Source: Dashboard/Services/DashboardNavigationService.cs:13-30
INavigatablePlugin - Plugin parameter handling:
public interface INavigatablePlugin
{
Task NavigateWithParametersAsync(Dictionary<string, object> parameters);
}
Source: Dashboard/INavigatablePlugin.cs:6-9
Services
Prompt Overlay Service
IPromptOverlayService - DApp interaction prompts
public interface IPromptOverlayService
{
bool IsOverlayVisible { get; }
PromptRequest? CurrentPrompt { get; }
int CurrentIndex { get; }
Task ShowPromptAsync(PromptRequest request);
Task ShowPromptByIdAsync(string promptId);
Task ShowNextPromptAsync();
Task ShowPreviousPromptAsync();
void HideOverlay();
void MinimizeOverlay();
event EventHandler<OverlayStateChangedEventArgs>? OverlayStateChanged;
}
Source: Services/IPromptOverlayService.cs:6-27
PromptOverlayService implementation:
Dependencies: IPromptQueueService
Source: Services/PromptOverlayService.cs:10
Commands:
public async Task ShowPromptAsync(PromptRequest request)
{
CurrentPrompt = request;
IsOverlayVisible = true;
if (request.Status == PromptStatus.Pending)
{
request.Status = PromptStatus.InProgress;
}
OverlayStateChanged?.Invoke(this, new OverlayStateChangedEventArgs(true, CurrentPrompt));
}
Source: Services/PromptOverlayService.cs:23-40
public void HideOverlay()
{
IsOverlayVisible = false;
var previousPrompt = CurrentPrompt;
CurrentPrompt = null;
CurrentIndex = 0;
OverlayStateChanged?.Invoke(this, new OverlayStateChangedEventArgs(false, previousPrompt));
}
Source: Services/PromptOverlayService.cs:76-86
public void MinimizeOverlay()
{
IsOverlayVisible = false;
// CurrentPrompt remains set
OverlayStateChanged?.Invoke(this, new OverlayStateChangedEventArgs(false, CurrentPrompt));
}
Source: Services/PromptOverlayService.cs:88-97
Platform Abstraction Interfaces
IWalletNotificationService - Toast notifications
public interface IWalletNotificationService
{
void ShowNotification(string message, NotificationSeverity severity = NotificationSeverity.Info);
void ShowSuccess(string message);
void ShowError(string message);
void ShowWarning(string message);
void ShowInfo(string message);
void ShowNotificationWithAction(string message, NotificationSeverity severity, Action action);
}
public enum NotificationSeverity
{
Success,
Info,
Warning,
Error
}
Source: Abstractions/GenericInterfaces.cs:8-33
IWalletDialogService - Modal dialogs
public interface IWalletDialogService
{
Task<bool> ShowConfirmationAsync(string title, string message);
Task ShowMessageAsync(string title, string message);
Task<T?> ShowDialogAsync<T>(Dictionary<string, object> parameters);
Task<bool> ShowWarningConfirmationAsync(string title, string message, string confirmText = "Confirm");
Task ShowErrorAsync(string title, string message);
Task ShowSuccessAsync(string title, string message);
}
Source: Abstractions/GenericInterfaces.cs:35-43
IWalletNavigationService - Route navigation
public interface IWalletNavigationService
{
Task GoToAsync(string route);
}
Source: Abstractions/GenericInterfaces.cs:45-48
IWalletLoadingService - Loading indicators
public interface IWalletLoadingService
{
bool IsLoading { get; }
string? LoadingMessage { get; }
double Progress { get; }
void SetLoading(bool isLoading, string? message = null);
void ShowProgress(double percentage, string? message = null);
}
Source: Abstractions/GenericInterfaces.cs:50-58
Utilities
Identicon Generator
IdenticonGenerator - Address visualization
public static class IdenticonGenerator
{
public static string GetIdenticonText(string address)
{
if (string.IsNullOrEmpty(address) || address.Length < 4)
return "??";
return address.Substring(2, 2).ToUpper();
}
public static string GetNetworkIdenticonText(string networkName)
{
if (string.IsNullOrEmpty(networkName))
return "??";
var words = networkName.Split(' ', StringSplitOptions.RemoveEmptyEntries);
if (words.Length >= 2)
return $"{words[0][0]}{words[1][0]}".ToUpper();
return networkName.Length >= 2
? networkName.Substring(0, 2).ToUpper()
: networkName.ToUpper();
}
public static string GetIdenticonStyle(string address)
{
if (string.IsNullOrEmpty(address))
return "background: #cccccc;";
var hash = address.GetHashCode();
var hue = Math.Abs(hash % 360);
var saturation = 65 + Math.Abs(hash % 20);
var lightness = 45 + Math.Abs(hash % 20);
return $"background: hsl({hue}, {saturation}%, {lightness}%);";
}
}
Source: Utils/IdenticonGenerator.cs:5-47
Network Icon Repository
INetworkIconProvider - Network icon abstraction
public interface INetworkIconProvider
{
string? GetNetworkIcon(BigInteger chainId);
bool HasNetworkIcon(BigInteger chainId);
}
Source: Utils/NetworkIconRepository.cs:5-9
DefaultNetworkIconProvider - Placeholder implementation
public class DefaultNetworkIconProvider : INetworkIconProvider
{
public string? GetNetworkIcon(BigInteger chainId) => null;
public bool HasNetworkIcon(BigInteger chainId) => false;
}
Source: Utils/NetworkIconRepository.cs:10-14
Service Registration
Transaction Services
TransactionServiceCollectionExtensions:
public static IServiceCollection AddTransactionServices(this IServiceCollection services)
{
services.AddScoped<IPendingTransactionService, PendingTransactionService>();
services.AddTransient<TransactionHistoryViewModel>();
services.AddSingleton<TransactionHistoryLocalizer>();
services.AddSingleton<PendingTransactionServiceLocalizer>();
services.AddSingleton<PendingTransactionNotificationLocalizer>();
services.AddHostedService<TransactionMonitoringService>();
return services;
}
Source: Transactions/TransactionServiceCollectionExtensions.cs:10-24
Token Transfer Services
TokenTransferServiceCollectionExtensions:
public static IServiceCollection AddTokenTransferServices(this IServiceCollection services)
{
services.AddSingleton<FourByteDirectoryService>();
services.AddScoped<ITransactionDataDecodingService, TransactionDataDecodingService>();
services.AddScoped<IGasPriceProvider, DefaultGasPriceProvider>();
services.AddScoped<IGasConfigurationPersistenceService, InMemoryGasConfigurationPersistence>();
services.AddTransient<TokenNativeTransferModel>();
services.AddTransient<TokenERC20TransferModel>();
services.AddTransient<TokenERC721TransferModel>();
services.AddTransient<TokenERC1155TransferModel>();
services.AddTransient<NativeTokenTransferViewModel>();
// Localizers
services.AddSingleton<SendNativeTokenLocalizer>();
services.AddSingleton<SendERC20TokenLocalizer>();
services.AddSingleton<SendERC721TokenLocalizer>();
services.AddSingleton<SendERC1155TokenLocalizer>();
services.AddSingleton<TokenTransferLocalizer>();
services.AddSingleton<TransactionInputLocalizer>();
services.AddSingleton<TransactionConfirmationLocalizer>();
services.AddSingleton<TransactionStatusLocalizer>();
return services;
}
Source: SendTransaction/TokenTransferServiceCollectionExtensions.cs:14-59
Related Packages
Platform-Specific UI Packages
- Nethereum.Wallet.UI.Components.Blazor - Blazor components (Razor, CSS)
- Nethereum.Wallet.UI.Components.Maui - MAUI platform integration
- Nethereum.Wallet.UI.Components.Avalonia - Avalonia desktop UI (skipped per user request)
Hardware Wallet Support
- Nethereum.Wallet.UI.Components.Trezor - Trezor ViewModels (platform-agnostic)
- Nethereum.Wallet.UI.Components.Blazor.Trezor - Trezor Blazor components
Core Dependencies
- Nethereum.Wallet - Wallet accounts, vault, services
- Nethereum.RPC - RPC client functionality
- Nethereum.DataServices - Chain data services
- Nethereum.UI - Base UI abstractions
Additional Resources
| Product | Versions 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. |
-
net9.0
- CommunityToolkit.Mvvm (>= 8.4.0)
- Microsoft.AspNetCore.Components.WebAssembly (>= 9.0.0)
- Microsoft.Extensions.Hosting.Abstractions (>= 9.0.0)
- Nethereum.DataServices (>= 5.8.0)
- Nethereum.RPC (>= 5.8.0)
- Nethereum.Wallet (>= 5.8.0)
- Newtonsoft.Json (>= 11.0.2 && < 14.0.0)
NuGet packages (3)
Showing the top 3 NuGet packages that depend on Nethereum.Wallet.UI.Components:
| Package | Downloads |
|---|---|
|
Nethereum.Wallet.UI.Components.Blazor
Blazor components and layouts for building Nethereum-powered wallets. |
|
|
Nethereum.Wallet.UI.Components.Trezor
Shared view models and helpers for integrating Trezor devices into Nethereum wallet UIs. |
|
|
Nethereum.Wallet.UI.Components.Maui
MAUI helpers and Blazor WebView integration for hosting Nethereum wallet components on mobile and desktop. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 5.8.0 | 43 | 1/6/2026 |