Nethereum.EIP6963WalletInterop 5.8.0

Prefix Reserved
dotnet add package Nethereum.EIP6963WalletInterop --version 5.8.0
                    
NuGet\Install-Package Nethereum.EIP6963WalletInterop -Version 5.8.0
                    
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.EIP6963WalletInterop" Version="5.8.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Nethereum.EIP6963WalletInterop" Version="5.8.0" />
                    
Directory.Packages.props
<PackageReference Include="Nethereum.EIP6963WalletInterop" />
                    
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.EIP6963WalletInterop --version 5.8.0
                    
#r "nuget: Nethereum.EIP6963WalletInterop, 5.8.0"
                    
#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.EIP6963WalletInterop@5.8.0
                    
#: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.EIP6963WalletInterop&version=5.8.0
                    
Install as a Cake Addin
#tool nuget:?package=Nethereum.EIP6963WalletInterop&version=5.8.0
                    
Install as a Cake Tool

Nethereum.EIP6963WalletInterop

Core abstraction layer for implementing EIP-6963 Multi-Wallet Discovery Standard across multiple platforms.

Overview

Nethereum.EIP6963WalletInterop provides the foundational interfaces and base classes for integrating with browser wallet extensions using the EIP-6963 standard. This package enables applications to discover and interact with multiple installed wallet extensions simultaneously, rather than being limited to a single provider at window.ethereum.

What is EIP-6963?

EIP-6963 is an Ethereum Improvement Proposal that standardizes how wallet providers announce themselves to dApps. Before EIP-6963, applications could only access one wallet at a time via window.ethereum, causing conflicts when multiple wallets were installed. EIP-6963 solves this by having each wallet broadcast an eip6963:announceProvider event containing metadata (name, icon, UUID, reverse DNS) and its provider instance.

Key Benefits:

  • Multi-wallet discovery - discover all installed browser wallet extensions
  • Wallet metadata - name, icon, UUID, and reverse DNS identifier
  • Platform abstraction - implement once, use across Blazor, Unity, desktop applications
  • Standard interfaces - IEIP6963WalletInterop and IEthereumHostProvider
  • Request interception - automatic routing of signing requests through selected wallet
  • Event subscriptions - account and network change notifications
  • Type-safe RPC - EIP6963RpcRequestMessage includes "from" address field

Platform Implementations:

  • Nethereum.Blazor - Blazor WebAssembly and Server via IJSRuntime
  • Nethereum.Unity.EIP6963 - Unity3D WebGL builds via jslib

Installation

dotnet add package Nethereum.EIP6963WalletInterop

Or via Package Manager Console:

Install-Package Nethereum.EIP6963WalletInterop

Dependencies

Project References:

  • Nethereum.UI
  • Nethereum.Web3

Target Frameworks:

  • netstandard2.0
  • net472
  • net6.0
  • net7.0
  • net8.0

Architecture

                     ┌──────────────────────────────┐
                     │  Your Application            │
                     │  (Blazor, Unity, Desktop)    │
                     └──────────────────────────────┘
                                  │
                                  │ uses
                                  ▼
┌────────────────────────────────────────────────────────────┐
│         EIP6963WalletHostProvider                          │
│         implements IEthereumHostProvider                   │
│                                                            │
│  - GetWeb3Async()                                         │
│  - EnableProviderAsync()                                  │
│  - GetAvailableWalletsAsync()                             │
│  - SelectWalletAsync(uuid)                                │
│  - Events: SelectedAccountChanged, NetworkChanged         │
└────────────────────────────────────────────────────────────┘
                                  │
                    ┌─────────────┴─────────────┐
                    │                           │
                    ▼                           ▼
    ┌───────────────────────────┐   ┌──────────────────────┐
    │ EIP6963WalletInterceptor  │   │ IEIP6963WalletInterop│
    │  (Request Routing)        │   │  (Platform Bridge)   │
    │                           │   │                      │
    │ - Intercepts RPC calls    │   │ - EnableEthereumAsync│
    │ - Routes signing to wallet│   │ - SendAsync          │
    │ - Auto-fills "from"       │   │ - GetAvailableWallets│
    └───────────────────────────┘   │ - SelectWalletAsync  │
                                    └──────────────────────┘
                                                │
                                Platform-specific implementation
                                                │
                        ┌───────────────────────┴──────────────────┐
                        │                                          │
                        ▼                                          ▼
            ┌────────────────────────┐              ┌──────────────────────┐
            │ EIP6963WalletBlazer-   │              │ EIP6963WebglInterop  │
            │ Interop (Blazor)       │              │ (Unity WebGL)        │
            │                        │              │                      │
            │ Uses IJSRuntime to     │              │ Uses DllImport for   │
            │ call JavaScript        │              │ jslib calls          │
            └────────────────────────┘              └──────────────────────┘
                        │                                          │
                        └───────────────────┬──────────────────────┘
                                            │
                                            ▼
                            ┌───────────────────────────┐
                            │  Browser JavaScript       │
                            │  NethereumEIP6963Interop  │
                            │                           │
                            │  - Listen for EIP-6963    │
                            │    announceProvider events│
                            │  - Store wallet metadata  │
                            │  - Route requests to      │
                            │    selected wallet        │
                            └───────────────────────────┘
                                            │
                                            ▼
                        ┌───────────────────────────────────┐
                        │  Browser Wallet Extensions        │
                        │  (MetaMask, Coinbase, Rabby, etc.)│
                        └───────────────────────────────────┘

Key Concepts

EIP-6963 Discovery Flow

  1. Application Loads: JavaScript listens for eip6963:announceProvider events
  2. Request Providers: Dispatches eip6963:requestProvider event
  3. Wallets Announce: Each installed wallet broadcasts its metadata via eip6963:announceProvider
  4. Store Providers: Application stores all discovered wallet providers
  5. User Selection: User selects which wallet to use from discovered list
  6. Enable Connection: Call EnableProviderAsync() to request account access
  7. Transaction Signing: All signing requests route through selected wallet provider

IEIP6963WalletInterop Interface

Platform-specific implementations must implement this interface to bridge C# code to JavaScript:

public interface IEIP6963WalletInterop
{
    // Connection Management
    ValueTask<string> EnableEthereumAsync();
    ValueTask<bool> CheckAvailabilityAsync();
    ValueTask<string> GetSelectedAddress();

    // RPC Communication
    ValueTask<RpcResponseMessage> SendAsync(RpcRequestMessage rpcRequestMessage);
    ValueTask<RpcResponseMessage> SendTransactionAsync(EIP6963RpcRequestMessage rpcRequestMessage);
    ValueTask<string> SignAsync(string utf8Hex);

    // Multi-Wallet Discovery
    ValueTask<EIP6963WalletInfo[]> GetAvailableWalletsAsync();
    ValueTask SelectWalletAsync(string walletId);
    ValueTask<string> GetWalletIconAsync(string walletId);
}

EIP6963WalletInfo

Wallet metadata returned by the discovery process:

public class EIP6963WalletInfo
{
    public string Uuid { get; set; }    // Unique identifier (e.g., "c436f8d0-...")
    public string Name { get; set; }    // Human-readable name (e.g., "MetaMask")
    public string Icon { get; set; }    // Base64 data URI or HTTPS URL
    public string Rdns { get; set; }    // Reverse DNS (e.g., "io.metamask")
}

Request Interception

EIP6963WalletInterceptor automatically routes specific methods through the wallet:

Always Intercepted (Wallet-Only Methods):

  • eth_sendTransaction
  • eth_signTransaction
  • eth_sign
  • personal_sign
  • eth_signTypedData
  • eth_signTypedData_v3
  • eth_signTypedData_v4
  • wallet_watchAsset
  • wallet_addEthereumChain
  • wallet_switchEthereumChain

Optional Interception:

  • eth_call (fills "from" if not provided)
  • eth_estimateGas (fills "from" if not provided)

All other methods can optionally pass through an RPC endpoint if configured.

MultipleWalletsProvider Support

The host provider exposes MultipleWalletsProvider property:

public bool MultipleWalletsProvider => true;  // EIP-6963 supports multiple wallets
public bool MultipleWalletSelected { get; private set; }  // Set after SelectWalletAsync

This distinguishes EIP-6963 providers from single-wallet providers like MetaMask extension.

Quick Start

For Platform Implementers

If you're creating a new platform integration (e.g., MAUI, Avalonia), implement IEIP6963WalletInterop:

using Nethereum.EIP6963WalletInterop;
using Nethereum.JsonRpc.Client.RpcMessages;

public class MyPlatformEIP6963Interop : IEIP6963WalletInterop
{
    public async ValueTask<EIP6963WalletInfo[]> GetAvailableWalletsAsync()
    {
        // Call platform-specific JavaScript bridge
        var walletsJson = await CallJavaScriptAsync("NethereumEIP6963Interop.getAvailableWallets");
        return JsonConvert.DeserializeObject<EIP6963WalletInfo[]>(walletsJson);
    }

    public async ValueTask SelectWalletAsync(string walletId)
    {
        await CallJavaScriptAsync("NethereumEIP6963Interop.selectWallet", walletId);
    }

    public async ValueTask<string> EnableEthereumAsync()
    {
        return await CallJavaScriptAsync("NethereumEIP6963Interop.enableEthereum");
    }

    public async ValueTask<RpcResponseMessage> SendAsync(RpcRequestMessage rpcRequestMessage)
    {
        var json = JsonConvert.SerializeObject(rpcRequestMessage);
        var responseJson = await CallJavaScriptAsync("NethereumEIP6963Interop.request", json);
        return JsonConvert.DeserializeObject<RpcResponseMessage>(responseJson);
    }

    // Implement remaining interface methods...
}

For Application Developers

Use the platform-specific implementation (Blazor example):

using Nethereum.Blazor.EIP6963WalletInterop;
using Nethereum.EIP6963WalletInterop;

// In your Blazor component or service
@inject IJSRuntime JSRuntime

private EIP6963WalletHostProvider walletProvider;
private EIP6963WalletInfo[] availableWallets;

protected override async Task OnInitializedAsync()
{
    // Create platform-specific interop
    var walletInterop = new EIP6963WalletBlazorInterop(JSRuntime);

    // Create host provider
    walletProvider = new EIP6963WalletHostProvider(walletInterop);

    // Discover available wallets
    availableWallets = await walletProvider.GetAvailableWalletsAsync();
}

private async Task ConnectWallet(string walletUuid)
{
    // Select wallet
    await walletProvider.SelectWalletAsync(walletUuid);

    // Enable and get account
    var account = await walletProvider.EnableProviderAsync();

    // Get Web3 instance
    var web3 = await walletProvider.GetWeb3Async();

    // Use web3...
    var balance = await web3.Eth.GetBalance.SendRequestAsync(account);
}

Usage Examples

Example 1: Complete Wallet Discovery and Selection

using Nethereum.EIP6963WalletInterop;
using System;
using System.Threading.Tasks;

public class WalletManager
{
    private readonly EIP6963WalletHostProvider _provider;
    private IEIP6963WalletInterop _walletInterop;

    public WalletManager(IEIP6963WalletInterop walletInterop)
    {
        _walletInterop = walletInterop;
        _provider = new EIP6963WalletHostProvider(walletInterop);

        // Subscribe to events
        _provider.SelectedAccountChanged += OnAccountChanged;
        _provider.NetworkChanged += OnNetworkChanged;
        _provider.AvailabilityChanged += OnAvailabilityChanged;
    }

    public async Task<EIP6963WalletInfo[]> DiscoverWalletsAsync()
    {
        await Task.Delay(100); // Wait for wallet announcements
        var wallets = await _provider.GetAvailableWalletsAsync();

        Console.WriteLine($"Found {wallets.Length} wallets:");
        foreach (var wallet in wallets)
        {
            Console.WriteLine($"  - {wallet.Name} ({wallet.Rdns})");
            Console.WriteLine($"    UUID: {wallet.Uuid}");
            Console.WriteLine($"    Icon: {wallet.Icon.Substring(0, 50)}...");
        }

        return wallets;
    }

    public async Task<string> ConnectToWalletAsync(string walletUuid)
    {
        // Select the wallet
        await _provider.SelectWalletAsync(walletUuid);

        // Enable and request accounts
        var selectedAccount = await _provider.EnableProviderAsync();

        Console.WriteLine($"Connected to: {selectedAccount}");
        Console.WriteLine($"Chain ID: {_provider.SelectedNetworkChainId}");

        return selectedAccount;
    }

    private async Task OnAccountChanged(string newAccount)
    {
        Console.WriteLine($"Account changed to: {newAccount}");
    }

    private async Task OnNetworkChanged(long newChainId)
    {
        Console.WriteLine($"Network changed to: {newChainId}");
    }

    private async Task OnAvailabilityChanged(bool available)
    {
        Console.WriteLine($"Wallet availability changed: {available}");
    }
}

Example 2: Using Web3 with Selected Wallet

using Nethereum.EIP6963WalletInterop;
using Nethereum.Web3;
using Nethereum.Hex.HexTypes;

public async Task SendTransactionAsync(string walletUuid, string toAddress, decimal amount)
{
    // Setup (assuming walletInterop already created)
    var provider = new EIP6963WalletHostProvider(walletInterop);

    // Select and connect
    await provider.SelectWalletAsync(walletUuid);
    var account = await provider.EnableProviderAsync();

    // Get Web3 with interceptor configured
    var web3 = await provider.GetWeb3Async();

    // Send transaction - automatically routed through wallet for signing
    var txInput = new Nethereum.RPC.Eth.DTOs.TransactionInput
    {
        From = account,  // Will be set automatically by interceptor
        To = toAddress,
        Value = new HexBigInteger(Web3.Convert.ToWei(amount))
    };

    var txHash = await web3.Eth.TransactionManager.SendTransactionAsync(txInput);
    Console.WriteLine($"Transaction sent: {txHash}");

    // Wait for receipt
    var receipt = await web3.Eth.TransactionManager
        .TransactionReceiptService
        .PollForReceiptAsync(txHash);

    Console.WriteLine($"Transaction mined in block: {receipt.BlockNumber}");
}

Example 3: Personal Sign with EIP-6963

using Nethereum.EIP6963WalletInterop;
using Nethereum.Hex.HexConvertors.Extensions;
using Nethereum.Signer;

public async Task<string> SignMessageAsync(string walletUuid, string message)
{
    var provider = new EIP6963WalletHostProvider(walletInterop);

    await provider.SelectWalletAsync(walletUuid);
    var account = await provider.EnableProviderAsync();

    // Sign message (routes through wallet)
    var signature = await provider.SignMessageAsync(message);

    // Verify signature
    var signer = new EthereumMessageSigner();
    var recoveredAddress = signer.EncodeUTF8AndEcRecover(message, signature);

    if (recoveredAddress.ToLower() == account.ToLower())
    {
        Console.WriteLine("Signature verified!");
    }

    return signature;
}

Example 4: EIP-712 Typed Data Signing

using Nethereum.EIP6963WalletInterop;
using Nethereum.ABI.FunctionEncoding.Attributes;
using Nethereum.Signer.EIP712;

[Struct("Person")]
public class Person
{
    [Parameter("string", "name", 1)]
    public string Name { get; set; }

    [Parameter("address", "wallet", 2)]
    public string Wallet { get; set; }
}

[Struct("Mail")]
public class Mail
{
    [Parameter("tuple", "from", 1)]
    public Person From { get; set; }

    [Parameter("tuple", "to", 2)]
    public Person To { get; set; }

    [Parameter("string", "contents", 3)]
    public string Contents { get; set; }
}

public async Task<string> SignTypedDataAsync(string walletUuid)
{
    var provider = new EIP6963WalletHostProvider(walletInterop);
    await provider.SelectWalletAsync(walletUuid);
    await provider.EnableProviderAsync();

    var web3 = await provider.GetWeb3Async();

    // Create typed data
    var typedData = new TypedData<Domain>
    {
        Domain = new Domain
        {
            Name = "Ether Mail",
            Version = "1",
            ChainId = 1,
            VerifyingContract = "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC"
        },
        Types = MemberDescriptionFactory.GetTypesMemberDescription(
            typeof(Domain), typeof(Mail), typeof(Person)),
        PrimaryType = nameof(Mail)
    };

    var mail = new Mail
    {
        From = new Person { Name = "Alice", Wallet = "0x..." },
        To = new Person { Name = "Bob", Wallet = "0x..." },
        Contents = "Hello Bob!"
    };

    typedData.SetMessage(mail);

    // Sign (routes through wallet)
    var signature = await web3.Eth.AccountSigning.SignTypedDataV4
        .SendRequestAsync(typedData.ToJson());

    return signature;
}

Example 5: Switching Chains via Wallet

using Nethereum.EIP6963WalletInterop;
using Nethereum.RPC.Eth.DTOs;
using Nethereum.Hex.HexTypes;

public async Task SwitchToPolygonAsync(string walletUuid)
{
    var provider = new EIP6963WalletHostProvider(walletInterop);
    await provider.SelectWalletAsync(walletUuid);
    await provider.EnableProviderAsync();

    var web3 = await provider.GetWeb3Async();

    try
    {
        // Try to switch to Polygon (chain ID 137)
        await web3.Eth.HostWallet.SwitchEthereumChain.SendRequestAsync(
            new SwitchEthereumChainParameter
            {
                ChainId = new HexBigInteger(137)
            });
    }
    catch
    {
        // Chain not added yet, add it
        await web3.Eth.HostWallet.AddEthereumChain.SendRequestAsync(
            new AddEthereumChainParameter
            {
                ChainId = new HexBigInteger(137),
                ChainName = "Polygon Mainnet",
                RpcUrls = new[] { "https://polygon-rpc.com" },
                NativeCurrency = new NativeCurrency
                {
                    Name = "MATIC",
                    Symbol = "MATIC",
                    Decimals = 18
                },
                BlockExplorerUrls = new[] { "https://polygonscan.com" }
            });
    }
}

Example 6: Hybrid Mode with Custom RPC

using Nethereum.EIP6963WalletInterop;
using Nethereum.JsonRpc.Client;

public async Task UseHybridModeAsync(string walletUuid)
{
    // Provide custom RPC client for queries
    var rpcClient = new RpcClient(new Uri("https://mainnet.infura.io/v3/YOUR-KEY"));

    // Create provider with custom client
    var provider = new EIP6963WalletHostProvider(walletInterop, rpcClient);

    await provider.SelectWalletAsync(walletUuid);
    await provider.EnableProviderAsync();

    var web3 = await provider.GetWeb3Async();

    // eth_call goes through Infura (faster, no wallet popup)
    var balance = await web3.Eth.GetBalance.SendRequestAsync("0x...");

    // eth_sendTransaction goes through wallet (requires signature)
    var txHash = await web3.Eth.GetEtherTransferService()
        .TransferEtherAsync("0x...", 0.1m);
}

API Reference

EIP6963WalletHostProvider

Implementation of IEthereumHostProvider for EIP-6963 wallets.

public class EIP6963WalletHostProvider : IEthereumHostProvider
{
    // Constructors
    public EIP6963WalletHostProvider(
        IEIP6963WalletInterop walletInterop,
        IClient client = null,
        bool useOnlySigningWalletTransactionMethods = false);

    // Properties
    public static EIP6963WalletHostProvider Current { get; }
    public string Name { get; }  // "EIP6963 Standard"
    public bool MultipleWalletsProvider { get; }  // true
    public bool MultipleWalletSelected { get; }
    public bool Available { get; }
    public string SelectedAccount { get; }
    public long SelectedNetworkChainId { get; }
    public bool Enabled { get; }
    public IClient Client { get; }

    // Events
    public event Func<string, Task> SelectedAccountChanged;
    public event Func<long, Task> NetworkChanged;
    public event Func<bool, Task> AvailabilityChanged;
    public event Func<bool, Task> EnabledChanged;

    // Multi-Wallet Methods
    public Task<EIP6963WalletInfo[]> GetAvailableWalletsAsync();
    public Task SelectWalletAsync(string walletuuid);

    // IEthereumHostProvider Methods
    public Task<bool> CheckProviderAvailabilityAsync();
    public Task<IWeb3> GetWeb3Async();
    public Task<string> EnableProviderAsync();
    public Task<string> GetProviderSelectedAccountAsync();
    public Task<string> SignMessageAsync(string message);

    // Change Notification Methods
    public Task ChangeSelectedAccountAsync(string selectedAccount);
    public Task ChangeSelectedNetworkAsync(long chainId);
    public Task ChangeWalletAvailableAsync(bool available);
    public Task ChangeWalletEnabledAsync(bool enabled);
}

EIP6963WalletInterceptor

Request interceptor for routing methods through the wallet.

public class EIP6963WalletInterceptor : RequestInterceptor
{
    // Constructor
    public EIP6963WalletInterceptor(
        IEIP6963WalletInterop walletInterop,
        bool useOnlySigningWalletTransactionMethods = false);

    // Properties
    public static List<string> SigningWalletTransactionsMethods { get; }
    public string SelectedAccount { get; set; }

    // Methods Automatically Intercepted:
    // - eth_sendTransaction (fills "from" with SelectedAccount)
    // - eth_signTransaction
    // - eth_sign
    // - personal_sign (reorders params: [message, account])
    // - eth_signTypedData / v3 / v4 (reorders params: [account, data])
    // - wallet_watchAsset
    // - wallet_addEthereumChain
    // - wallet_switchEthereumChain
    // - eth_call (fills "from" if not provided)
    // - eth_estimateGas (fills "from" if not provided)
}

EIP6963RpcRequestMessage

Extended RPC request message with "from" field.

public class EIP6963RpcRequestMessage : RpcRequestMessage
{
    public EIP6963RpcRequestMessage(
        object id,
        string method,
        string from,
        params object[] parameterList);

    public string From { get; }
}

EIP6963WalletInfo

Wallet metadata structure.

public class EIP6963WalletInfo
{
    public string Uuid { get; set; }    // Unique identifier
    public string Name { get; set; }    // Display name
    public string Icon { get; set; }    // Data URI or HTTPS URL
    public string Rdns { get; set; }    // Reverse DNS (e.g., "io.metamask")
}

JavaScript Integration

Browser-Side Implementation

Platform implementations should include JavaScript similar to:

window.NethereumEIP6963Interop = {
    ethereumProviders: [],
    selectedEthereumProvider: null,

    init: function() {
        // Listen for wallet announcements
        window.addEventListener("eip6963:announceProvider", (event) => {
            const provider = event.detail;
            if (!this.ethereumProviders.some(p => p.info.uuid === provider.info.uuid)) {
                this.ethereumProviders.push(provider);
            }
        });

        // Request wallets to announce themselves
        window.dispatchEvent(new Event("eip6963:requestProvider"));
    },

    getAvailableWallets: function() {
        return this.ethereumProviders.map(provider => ({
            name: provider.info.name,
            uuid: provider.info.uuid,
            icon: provider.info.icon,
            rdns: provider.info.rdns
        }));
    },

    selectWallet: async function(uuid) {
        const provider = this.ethereumProviders.find(p => p.info.uuid === uuid);
        if (provider) {
            this.selectedEthereumProvider = provider.provider;
            await this.enableEthereum();
        }
    },

    enableEthereum: async function() {
        // Setup event listeners
        this.selectedEthereumProvider.on("accountsChanged", (accounts) => {
            // Call back to C#
            DotNet.invokeMethodAsync('YourAssembly', 'EIP6963SelectedAccountChanged', accounts[0]);
        });

        this.selectedEthereumProvider.on("chainChanged", (chainId) => {
            DotNet.invokeMethodAsync('YourAssembly', 'EIP6963SelectedNetworkChanged', chainId);
        });
    },

    request: async function(message) {
        const parsedMessage = JSON.parse(message);
        const response = await this.selectedEthereumProvider.request(parsedMessage);
        return JSON.stringify({ jsonrpc: "2.0", result: response, id: parsedMessage.id });
    }
};

window.addEventListener("load", () => {
    window.NethereumEIP6963Interop.init();
});

Important Notes

Wait for Wallet Announcements

EIP-6963 wallet announcements are asynchronous. Add a small delay after page load before calling GetAvailableWalletsAsync():

await Task.Delay(100);  // Allow time for wallets to announce
var wallets = await provider.GetAvailableWalletsAsync();

Event Subscription Pattern

Platform implementations should use [JSInvokable] static methods to receive JavaScript callbacks:

[JSInvokable()]
public static async Task EIP6963SelectedAccountChanged(string selectedAccount)
{
    await EIP6963WalletHostProvider.Current.ChangeSelectedAccountAsync(selectedAccount);
}

UseOnlySigningWalletTransactionMethods Parameter

Controls whether all requests go through the wallet or only signing methods:

// All requests through wallet
var provider = new EIP6963WalletHostProvider(walletInterop, useOnlySigningWalletTransactionMethods: false);

// Only signing requests through wallet (requires custom RPC client)
var provider = new EIP6963WalletHostProvider(walletInterop, rpcClient, useOnlySigningWalletTransactionMethods: true);

Wallet Icon Handling

Wallet icons are typically base64-encoded data URIs:

data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzAiIGhlaWdodD0iMzAiIHZpZXdCb3g9IjAgMCAz...

Display directly in <img> tags without additional processing.

Reverse DNS (RDNS) Identifier

The RDNS field provides a stable identifier for wallets:

io.metamask         // MetaMask
com.coinbase.wallet // Coinbase Wallet
io.rabby            // Rabby

Use this for consistent wallet identification across sessions.

Platform Implementations

  • Nethereum.Blazor - EIP6963WalletBlazorInterop for Blazor applications
  • Nethereum.Unity.EIP6963 - EIP6963WebglInterop for Unity WebGL builds

Dependencies

  • Nethereum.UI - IEthereumHostProvider interface and SIWE authentication
  • Nethereum.Web3 - Web3 client, transaction management, and RPC types

Alternative Wallet Integration

  • Nethereum.Metamask - MetaMask-specific integration (legacy window.ethereum approach)
  • Nethereum.WalletConnect - Mobile wallet connectivity via QR code pairing

EIP-6963 Standard

For the complete EIP-6963 specification, see:

Product 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Nethereum.EIP6963WalletInterop:

Package Downloads
Nethereum.Blazor

Nethereum.Blazor Nethereum integration with Blazor including EIP6963WalletInterop and EthereumAuthenticationProvider

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
5.8.0 259 1/6/2026
5.0.0 879 5/28/2025
4.29.0 208 2/10/2025