![]() |
VOOZH | about |
dotnet add package Nethereum.Signer.Trezor --version 6.1.0
NuGet\Install-Package Nethereum.Signer.Trezor -Version 6.1.0
<PackageReference Include="Nethereum.Signer.Trezor" Version="6.1.0" />
<PackageVersion Include="Nethereum.Signer.Trezor" Version="6.1.0" />Directory.Packages.props
<PackageReference Include="Nethereum.Signer.Trezor" />Project file
paket add Nethereum.Signer.Trezor --version 6.1.0
#r "nuget: Nethereum.Signer.Trezor, 6.1.0"
#:package Nethereum.Signer.Trezor@6.1.0
#addin nuget:?package=Nethereum.Signer.Trezor&version=6.1.0Install as a Cake Addin
#tool nuget:?package=Nethereum.Signer.Trezor&version=6.1.0Install as a Cake Tool
TREZOR hardware wallet integration for Ethereum transaction and message signing with Nethereum.
Nethereum.Signer.Trezor provides external signing capability for Ethereum transactions and messages using TREZOR One, TREZOR Model T, and TREZOR Safe 3 hardware wallets. This allows secure transaction signing where private keys never leave the hardware device, with full support for EIP-712 typed data signing and interactive user confirmations.
Key Features:
Use Cases:
dotnet add package Nethereum.Signer.Trezor
Platform-Specific Setup:
libusb and udev ruleslibusb (install via Homebrew: brew install libusb)External:
Note: TREZOR communication protocol implementation is built internally. The external Trezor.Net library is no longer used.
Nethereum:
using Nethereum.Signer.Trezor;
using Nethereum.Web3.Accounts;
using Microsoft.Extensions.Logging;
// Create logger factory
var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole());
// Create prompt handler for PIN/passphrase
var promptHandler = new ConsoleTrezorPromptHandler();
// Initialize TREZOR connection (Windows)
var trezorBroker = NethereumTrezorManagerBrokerFactory.Create(
promptHandler,
loggerFactory
);
// Wait for TREZOR device
var trezorManager = await trezorBroker.WaitForFirstDeviceAsync();
// Create external signer (account index 0)
var trezorSigner = new TrezorExternalSigner(trezorManager, index: 0);
// Create external account
var account = new ExternalAccount(trezorSigner, chainId: 1);
await account.InitialiseAsync();
// Use with Web3
var web3 = new Web3.Web3(account, "https://mainnet.infura.io/v3/YOUR-PROJECT-ID");
Console.WriteLine($"TREZOR Address: {account.Address}");
Before using this library:
using Nethereum.Signer.Trezor;
using Nethereum.Signer.Trezor.Abstractions;
using Nethereum.Web3.Accounts;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;
// Implement prompt handler for PIN/passphrase
public class ConsoleTrezorPromptHandler : ITrezorPromptHandler
{
public Task<string> GetPinAsync()
{
Console.WriteLine("Enter PIN (use numpad layout 789/456/123):");
return Task.FromResult(Console.ReadLine());
}
public Task<string> GetPassphraseAsync()
{
Console.WriteLine("Enter passphrase (leave empty if none):");
return Task.FromResult(Console.ReadLine());
}
}
// Create connection
var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole());
var promptHandler = new ConsoleTrezorPromptHandler();
var trezorBroker = NethereumTrezorManagerBrokerFactory.Create(
promptHandler,
loggerFactory,
pollInterval: 2000
);
Console.WriteLine("Waiting for TREZOR device...");
var trezorManager = await trezorBroker.WaitForFirstDeviceAsync();
Console.WriteLine("TREZOR connected!");
// Create signer for account 0 (m/44'/60'/0'/0/0)
var trezorSigner = new TrezorExternalSigner(
trezorManager,
index: 0
);
var account = new ExternalAccount(trezorSigner, chainId: 1);
await account.InitialiseAsync();
Console.WriteLine($"Address: {account.Address}");
// Matches TREZOR Suite "Ethereum #1" account
using Nethereum.Signer.Trezor;
using Nethereum.Web3;
using Nethereum.Web3.Accounts;
using Nethereum.RPC.Eth.DTOs;
using Nethereum.Hex.HexTypes;
// Connect to TREZOR (see Example 1)
var trezorBroker = NethereumTrezorManagerBrokerFactory.Create(promptHandler, loggerFactory);
var trezorManager = await trezorBroker.WaitForFirstDeviceAsync();
var externalAccount = new ExternalAccount(
new TrezorExternalSigner(trezorManager, index: 0),
chainId: 1
);
await externalAccount.InitialiseAsync();
// Create Web3 instance
var web3 = new Web3(externalAccount, "https://mainnet.infura.io/v3/YOUR-PROJECT-ID");
// Create transaction
var transactionInput = new TransactionInput
{
From = externalAccount.Address,
To = "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
Value = new HexBigInteger(1000000000000000), // 0.001 ETH
Gas = new HexBigInteger(21000),
GasPrice = new HexBigInteger(20000000000) // 20 gwei
};
// User must approve on TREZOR device
Console.WriteLine("Approve transaction on TREZOR device...");
var receipt = await web3.Eth.TransactionManager
.SendTransactionAndWaitForReceiptAsync(transactionInput);
Console.WriteLine($"Transaction mined! Hash: {receipt.TransactionHash}");
using Nethereum.Signer.Trezor;
using Nethereum.Web3.Accounts;
using Nethereum.RPC.Eth.DTOs;
using Nethereum.Hex.HexTypes;
var trezorBroker = NethereumTrezorManagerBrokerFactory.Create(promptHandler, loggerFactory);
var trezorManager = await trezorBroker.WaitForFirstDeviceAsync();
var externalAccount = new ExternalAccount(
new TrezorExternalSigner(trezorManager, index: 0),
chainId: 1
);
await externalAccount.InitialiseAsync();
// EIP-1559 transaction with priority fee
var transactionInput = new TransactionInput
{
From = externalAccount.Address,
To = "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
Value = new HexBigInteger(1000000000000000), // 0.001 ETH
Gas = new HexBigInteger(21000),
MaxFeePerGas = new HexBigInteger(50000000000), // 50 gwei
MaxPriorityFeePerGas = new HexBigInteger(2000000000) // 2 gwei (tip)
};
Console.WriteLine("Approve EIP-1559 transaction on TREZOR...");
var signedTx = await externalAccount.TransactionManager
.SignTransactionAsync(transactionInput);
Console.WriteLine($"Signed EIP-1559 TX: {signedTx}");
using Nethereum.Signer.Trezor;
using Nethereum.Web3;
using Nethereum.Web3.Accounts;
using Nethereum.Contracts;
using Nethereum.ABI.FunctionEncoding.Attributes;
using System.Numerics;
// ERC-20 Transfer function
[Function("transfer", "bool")]
public class TransferFunction : FunctionMessage
{
[Parameter("address", "_to", 1)]
public string To { get; set; }
[Parameter("uint256", "_value", 2)]
public BigInteger Value { get; set; }
}
// Connect to TREZOR
var trezorBroker = NethereumTrezorManagerBrokerFactory.Create(promptHandler, loggerFactory);
var trezorManager = await trezorBroker.WaitForFirstDeviceAsync();
var externalAccount = new ExternalAccount(
new TrezorExternalSigner(trezorManager, index: 0),
chainId: 1
);
await externalAccount.InitialiseAsync();
var web3 = new Web3(externalAccount, "https://mainnet.infura.io/v3/YOUR-PROJECT-ID");
// Create transfer function
var transfer = new TransferFunction
{
To = "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
Value = BigInteger.Parse("1000000000000000000"), // 1 token
FromAddress = externalAccount.Address
};
// Get contract
var tokenAddress = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"; // USDC
var contract = web3.Eth.GetContract(
"[{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"type\":\"function\"}]",
tokenAddress
);
// User approves contract data on TREZOR
Console.WriteLine("Approve contract call on TREZOR...");
var transferHandler = contract.GetFunction("transfer");
var receipt = await transferHandler.SendTransactionAndWaitForReceiptAsync(
externalAccount.Address,
null,
null,
transfer.To,
transfer.Value
);
Console.WriteLine($"Transfer complete! Hash: {receipt.TransactionHash}");
using Nethereum.Signer.Trezor;
using Nethereum.Signer.EIP712;
using Nethereum.ABI.EIP712;
using Nethereum.Hex.HexConvertors.Extensions;
using System.Numerics;
// ERC-2612 Permit domain and message
public class EIP712Domain
{
public string Name { get; set; }
public string Version { get; set; }
public BigInteger ChainId { get; set; }
public string VerifyingContract { get; set; }
}
public class Permit
{
public string Owner { get; set; }
public string Spender { get; set; }
public BigInteger Value { get; set; }
public BigInteger Nonce { get; set; }
public BigInteger Deadline { get; set; }
}
// Connect to TREZOR
var trezorBroker = NethereumTrezorManagerBrokerFactory.Create(promptHandler, loggerFactory);
var trezorManager = await trezorBroker.WaitForFirstDeviceAsync();
var trezorSigner = new TrezorExternalSigner(trezorManager, index: 0);
await trezorSigner.GetAddressAsync();
// Create typed data
var typedData = new TypedData<EIP712Domain>
{
Domain = new EIP712Domain
{
Name = "USD Coin",
Version = "2",
ChainId = 1,
VerifyingContract = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
},
Types = new Dictionary<string, MemberDescription[]>
{
["EIP712Domain"] = new[]
{
new MemberDescription { Name = "name", Type = "string" },
new MemberDescription { Name = "version", Type = "string" },
new MemberDescription { Name = "chainId", Type = "uint256" },
new MemberDescription { Name = "verifyingContract", Type = "address" }
},
["Permit"] = new[]
{
new MemberDescription { Name = "owner", Type = "address" },
new MemberDescription { Name = "spender", Type = "address" },
new MemberDescription { Name = "value", Type = "uint256" },
new MemberDescription { Name = "nonce", Type = "uint256" },
new MemberDescription { Name = "deadline", Type = "uint256" }
}
},
PrimaryType = "Permit",
Message = new[]
{
new MemberValue { TypeName = "address", Value = await trezorSigner.GetAddressAsync() },
new MemberValue { TypeName = "address", Value = "0x1234567890123456789012345678901234567890" },
new MemberValue { TypeName = "uint256", Value = new BigInteger(1000000000000) },
new MemberValue { TypeName = "uint256", Value = BigInteger.Zero },
new MemberValue { TypeName = "uint256", Value = new BigInteger(1735689600) }
}
};
// TREZOR shows full typed data on device for user confirmation
Console.WriteLine("Review and approve typed data on TREZOR...");
var signature = await trezorSigner.SignTypedDataAsync(typedData);
Console.WriteLine($"EIP-712 Signature: {signature.CreateStringSignature()}");
// User sees: "Permit owner to spender" with all details on device
using Nethereum.Signer.Trezor;
using Nethereum.Signer;
using Nethereum.Hex.HexConvertors.Extensions;
using System.Text;
var trezorBroker = NethereumTrezorManagerBrokerFactory.Create(promptHandler, loggerFactory);
var trezorManager = await trezorBroker.WaitForFirstDeviceAsync();
var trezorSigner = new TrezorExternalSigner(trezorManager, index: 0);
var address = await trezorSigner.GetAddressAsync();
// Message to sign
string message = "Sign this message to authenticate with our dApp!";
byte[] messageBytes = Encoding.UTF8.GetBytes(message);
// TREZOR displays message on device for confirmation
Console.WriteLine("Review and approve message on TREZOR...");
var signature = await trezorSigner.SignEthereumMessageAsync(messageBytes);
Console.WriteLine($"Message: {message}");
Console.WriteLine($"Signature: {signature.CreateStringSignature()}");
// Verify signature
var messageSigner = new EthereumMessageSigner();
var recoveredAddress = messageSigner.EncodeUTF8AndEcRecover(message, signature.CreateStringSignature());
Console.WriteLine($"Signer address: {address}");
Console.WriteLine($"Recovered address: {recoveredAddress}");
Console.WriteLine($"Match: {address.Equals(recoveredAddress, StringComparison.OrdinalIgnoreCase)}");
using Nethereum.Signer.Trezor;
using Nethereum.Web3.Accounts;
var trezorBroker = NethereumTrezorManagerBrokerFactory.Create(promptHandler, loggerFactory);
var trezorManager = await trezorBroker.WaitForFirstDeviceAsync();
// Account 0 (Ethereum #1 in TREZOR Suite)
var account0 = new ExternalAccount(
new TrezorExternalSigner(trezorManager, index: 0),
chainId: 1
);
await account0.InitialiseAsync();
Console.WriteLine($"Account 0: {account0.Address}");
// Account 1 (Ethereum #2 in TREZOR Suite)
var account1 = new ExternalAccount(
new TrezorExternalSigner(trezorManager, index: 1),
chainId: 1
);
await account1.InitialiseAsync();
Console.WriteLine($"Account 1: {account1.Address}");
// Account 5 (Ethereum #6 in TREZOR Suite)
var account5 = new ExternalAccount(
new TrezorExternalSigner(trezorManager, index: 5),
chainId: 1
);
await account5.InitialiseAsync();
Console.WriteLine($"Account 5: {account5.Address}");
using Nethereum.Signer.Trezor;
using Nethereum.Web3.Accounts;
var trezorBroker = NethereumTrezorManagerBrokerFactory.Create(promptHandler, loggerFactory);
var trezorManager = await trezorBroker.WaitForFirstDeviceAsync();
// Custom path for account 1 instead of 0
string customPath = "m/44'/60'/1'/0"; // Will derive m/44'/60'/1'/0/3
var trezorSigner = new TrezorExternalSigner(
trezorManager,
customPath: customPath,
index: 3
);
var account = new ExternalAccount(trezorSigner, chainId: 1);
await account.InitialiseAsync();
Console.WriteLine($"Custom path address: {account.Address}");
using Nethereum.Signer.Trezor;
using Microsoft.Extensions.Logging;
using System.Runtime.InteropServices;
var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole());
var promptHandler = new ConsoleTrezorPromptHandler();
// Auto-detect platform and use appropriate device factory
var trezorBroker = NethereumTrezorManagerBrokerFactory.CreateDefault(
promptHandler,
loggerFactory,
platformProviders: new NethereumTrezorManagerBrokerFactory.PlatformDeviceFactoryProviders
{
WindowsProvider = new WindowsHidUsbDeviceFactoryProvider(),
LinuxProvider = new LibUsbDeviceFactoryProvider(),
MacProvider = new LibUsbDeviceFactoryProvider()
}
);
Console.WriteLine($"Platform: {RuntimeInformation.OSDescription}");
Console.WriteLine("Waiting for TREZOR device...");
var trezorManager = await trezorBroker.WaitForFirstDeviceAsync();
Console.WriteLine("TREZOR connected!");
// Linux users: Ensure udev rules are configured
// Create file: /etc/udev/rules.d/51-trezor.rules
// Content: SUBSYSTEM=="usb", ATTR{idVendor}=="534c", MODE="0660", GROUP="plugdev"
// Run: sudo udevadm control --reload-rules && sudo udevadm trigger
External signer implementation for TREZOR hardware wallets.
public class TrezorExternalSigner : EthExternalSignerBase
{
// Constructors
public TrezorExternalSigner(TrezorManagerBase<MessageType> trezorManager, uint index, string knownAddress = null, ILogger<TrezorExternalSigner> logger = null);
public TrezorExternalSigner(TrezorManagerBase<MessageType> trezorManager, string customPath, uint index, string knownAddress = null, ILogger<TrezorExternalSigner> logger = null);
// Properties
public TrezorManagerBase<MessageType> TrezorManager { get; }
public override bool CalculatesV { get; } = true;
public override ExternalSignerTransactionFormat ExternalSignerTransactionFormat { get; } = ExternalSignerTransactionFormat.Transaction;
public override bool Supported1559 { get; } = true;
// Methods
public override Task<string> GetAddressAsync();
public Task<string> RefreshAddressFromDeviceAsync();
public override Task<EthECDSASignature> SignEthereumMessageAsync(byte[] rawBytes);
public override Task<EthECDSASignature> SignTypedDataAsync<TDomain>(TypedData<TDomain> typedData);
public Task<EthECDSASignature> SignTypedDataAsync<TDomain>(TypedData<TDomain> typedData, byte[] encodedNetwork);
public Task<EthECDSASignature> SignTypedDataHashAsync(byte[] domainSeparatorHash, byte[] messageHash, byte[] encodedNetwork, byte[] typedDataHash);
public override Task SignAsync(LegacyTransactionChainId transaction);
public override Task SignAsync(Transaction1559 transaction);
public uint[] GetPath();
}
Factory for creating TREZOR device connections.
public class NethereumTrezorManagerBrokerFactory
{
public static NethereumTrezorManagerBroker Create(ITrezorPromptHandler promptHandler, ILoggerFactory loggerFactory, int? pollInterval = 2000);
public static NethereumTrezorManagerBroker CreateWindowsHidUsb(EnterPinArgs enterPinCallback, EnterPinArgs enterPassPhrase, ILoggerFactory loggerFactory, int? pollInterval = 2000);
public static NethereumTrezorManagerBroker CreateDefault(ITrezorPromptHandler promptHandler, ILoggerFactory loggerFactory, PlatformDeviceFactoryProviders platformProviders = null, int? pollInterval = 2000);
}
Interface for handling PIN and passphrase prompts.
public interface ITrezorPromptHandler
{
Task<string> GetPinAsync();
Task<string> GetPassphraseAsync();
}
TREZOR PIN is entered using numpad layout:
7 8 9
4 5 6
1 2 3
Device shows positions, you enter numbers on computer.
Example: Device shows [• • •], you type "789" for top row.
// Same seed + different passphrase = different addresses
// Passphrase acts as 25th word (like Ledger/HDWallet)
// No passphrase = standard wallet
// "secret123" = hidden wallet #1
// "different" = hidden wallet #2
Enables plausible deniability - can reveal standard wallet under duress.
| Type | Supported | Notes |
|---|---|---|
| Legacy | Yes | EIP-155 with chain ID (requires chain ID, no raw Legacy) |
| EIP-1559 (Type 2) | Yes | MaxFeePerGas, MaxPriorityFeePerGas |
| EIP-2930 (Type 1) | No | Access lists not supported |
| EIP-7702 (Type 4) | No | Not yet implemented |
TREZOR provides interactive EIP-712 signing - the device displays:
This is more secure than "blind signing" hash-only approaches.
Supports all TREZOR devices with latest firmware. All Ethereum features (transactions, EIP-712, message signing) work across all models.
| Platform | Connection Method | Setup Required |
|---|---|---|
| Windows | USB HID | None (plug and play) |
| Linux | LibUSB | udev rules required |
| macOS | LibUSB | brew install libusb |
| Android | Custom provider | Platform-specific implementation |
using hw.trezor.messages.common;
try
{
var signature = await externalAccount.TransactionManager
.SignTransactionAsync(transactionInput);
}
catch (FailureException<Failure> ex)
{
// User rejected on device, or device error
Console.WriteLine($"TREZOR error: {ex.Failure?.Message}");
}
catch (Exception ex)
{
Console.WriteLine($"Signing error: {ex.Message}");
}
Common errors:
using Microsoft.Extensions.Logging;
var loggerFactory = LoggerFactory.Create(builder =>
{
builder.SetMinimumLevel(LogLevel.Debug);
builder.AddConsole();
});
// Detailed logs for debugging TREZOR communication
var trezorBroker = NethereumTrezorManagerBrokerFactory.Create(
promptHandler,
loggerFactory
);
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 net5.0 is compatible. net5.0-windows net5.0-windows was computed. net6.0 net6.0 was computed. net6.0-android net6.0-android was computed. net6.0-ios net6.0-ios was computed. net6.0-maccatalyst net6.0-maccatalyst was computed. net6.0-macos net6.0-macos was computed. net6.0-tvos net6.0-tvos was computed. net6.0-windows net6.0-windows was computed. net7.0 net7.0 was computed. net7.0-android net7.0-android was computed. net7.0-ios net7.0-ios was computed. net7.0-maccatalyst net7.0-maccatalyst was computed. net7.0-macos net7.0-macos was computed. net7.0-tvos net7.0-tvos was computed. net7.0-windows net7.0-windows was computed. net8.0 net8.0 was computed. net8.0-android net8.0-android was computed. net8.0-browser net8.0-browser was computed. net8.0-ios net8.0-ios was computed. net8.0-maccatalyst net8.0-maccatalyst was computed. net8.0-macos net8.0-macos was computed. net8.0-tvos net8.0-tvos was computed. net8.0-windows net8.0-windows was computed. net9.0 net9.0 was computed. net9.0-android net9.0-android was computed. net9.0-browser net9.0-browser was computed. net9.0-ios net9.0-ios was computed. net9.0-maccatalyst net9.0-maccatalyst was computed. net9.0-macos net9.0-macos was computed. net9.0-tvos net9.0-tvos was computed. net9.0-windows net9.0-windows was computed. net10.0 net10.0 was computed. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 netcoreapp2.0 was computed. netcoreapp2.1 netcoreapp2.1 was computed. netcoreapp2.2 netcoreapp2.2 was computed. netcoreapp3.0 netcoreapp3.0 was computed. netcoreapp3.1 netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 netstandard2.0 is compatible. netstandard2.1 netstandard2.1 was computed. |
| .NET Framework | net461 net461 was computed. net462 net462 was computed. net463 net463 was computed. net47 net47 was computed. net471 net471 was computed. net472 net472 was computed. net48 net48 was computed. net481 net481 was computed. |
| MonoAndroid | monoandroid monoandroid was computed. |
| MonoMac | monomac monomac was computed. |
| MonoTouch | monotouch monotouch was computed. |
| Tizen | tizen40 tizen40 was computed. tizen60 tizen60 was computed. |
| Xamarin.iOS | xamarinios xamarinios was computed. |
| Xamarin.Mac | xamarinmac xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos xamarinwatchos was computed. |
Showing the top 1 NuGet packages that depend on Nethereum.Signer.Trezor:
| Package | Downloads |
|---|---|
|
Nethereum.Wallet.Trezor
Trezor hardware wallet integration for the Nethereum wallet services. |
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 6.1.0 | 803 | 3/25/2026 |
| 6.0.4 | 206 | 3/18/2026 |
| 6.0.3 | 164 | 3/18/2026 |
| 6.0.1 | 188 | 3/17/2026 |
| 6.0.0 | 191 | 3/16/2026 |
| 5.8.0 | 227 | 1/6/2026 |
| 5.0.0 | 361 | 5/28/2025 |
| 4.29.0 | 305 | 2/10/2025 |
| 4.28.0 | 287 | 1/7/2025 |
| 4.27.1 | 313 | 12/24/2024 |
| 4.27.0 | 295 | 12/24/2024 |
| 4.26.0 | 324 | 10/1/2024 |
| 4.25.0 | 285 | 9/19/2024 |
| 4.21.4 | 313 | 8/9/2024 |
| 4.21.3 | 344 | 7/22/2024 |
| 4.21.2 | 312 | 6/26/2024 |
| 4.21.1 | 303 | 6/26/2024 |
| 4.21.0 | 312 | 6/18/2024 |
| 4.20.0 | 339 | 3/28/2024 |
| 4.19.0 | 338 | 2/16/2024 |