Trezor Wallet Integration
Trezor is the second most popular hardware wallet after Ledger, with a fundamentally different communication architecture. While Ledger uses native WebHID/WebUSB, Trezor works through its own bridge — Trezor Suite Bridge or WebUSB transport. This affects how you build integration and which scenarios to handle.
Communication Architecture
The Trezor Connect SDK (@trezor/connect-web) works through an iframe with the domain connect.trezor.io. This means: your code doesn't communicate with the device directly — the request goes to the iframe, which communicates with Trezor Suite Bridge (native app) or via WebUSB, gets the response, and returns it via postMessage.
This approach provides security (keys don't leave Trezor's controlled domain) and convenience (no need to install additional software with WebUSB), but creates a dependency on Trezor's infrastructure.
For applications needing full autonomy, there's @trezor/connect (without iframe) — used in Trezor Suite directly. But for web integration, @trezor/connect-web is the standard choice.
Basic Integration
Initialization:
import TrezorConnect from "@trezor/connect-web";
await TrezorConnect.init({
lazyLoad: true,
manifest: {
email: "[email protected]",
appUrl: "https://yourproject.com",
},
});
Manifest is mandatory — Trezor uses it to identify the application and display it to the user on the device screen.
Getting an address:
const result = await TrezorConnect.ethereumGetAddress({
path: "m/44'/60'/0'/0/0",
showOnTrezor: true,
});
if (result.success) {
console.log(result.payload.address);
} else {
console.error(result.payload.error);
}
Transaction signature via TrezorConnect.ethereumSignTransaction. Unlike Ledger, Trezor accepts not RLP, but an object with fields:
const result = await TrezorConnect.ethereumSignTransaction({
path: "m/44'/60'/0'/0/0",
transaction: {
to: "0xRecipient",
value: "0xDE0B6B3A7640000", // 1 ETH in hex
data: "0x",
chainId: 1,
nonce: "0x5",
gasLimit: "0x5208",
maxFeePerGas: "0x...", // EIP-1559
maxPriorityFeePerGas: "0x...",
},
});
EIP-712 Signature
Trezor supports ethereumSignTypedData starting from firmware 2.4.3 (Model T) and 1.10.5 (Model One). Important nuance: Model One has a limited screen and cannot display complex structures — for it, use metamask_v4_compat: true mode with hashing on the host side.
const result = await TrezorConnect.ethereumSignTypedData({
path: "m/44'/60'/0'/0/0",
data: typedData, // standard EIP-712 object
metamask_v4_compat: true,
});
Common Issues
Bridge is not running. If the user hasn't installed Trezor Suite Bridge and the browser doesn't support WebUSB — the SDK won't find the device. Solution: in UI, direct to installation page, detect via TrezorConnect.getFeatures().
Popup is blocked. @trezor/connect-web opens a popup to display permissions. Browser popup blockers can prevent this. You need to initiate calls only from user gesture (click).
Firmware version. Old firmware doesn't support EIP-1559 transactions. Recommended to check version via TrezorConnect.getFeatures() and show an update warning.
Differences from Ledger in Implementation
| Aspect | Ledger | Trezor |
|---|---|---|
| Transport | WebHID/WebUSB directly | iframe + Bridge/WebUSB |
| Infrastructure dependency | No | connect.trezor.io |
| Transaction format | RLP-encoded | Object with fields |
| Offline usage | Yes | Limited |
| EIP-712 on budget models | Limited | metamask_v4_compat |
Basic integration with Trezor (address + signing transactions + EIP-712) — 1–2 weeks including testing on Model T and Model One and handling all edge cases.







