Overview
Device management in TrezorConnect involves handling device connections, monitoring state changes, managing passphrases, and coordinating multiple devices. The SDK provides comprehensive tools for device lifecycle management.
Device Discovery
TrezorConnect automatically discovers and manages connected devices:
import TrezorConnect , { DEVICE_EVENT , DEVICE } from '@trezor/connect' ;
// Listen for device connections
TrezorConnect . on ( DEVICE_EVENT , ( event ) => {
if ( event . type === DEVICE . CONNECT ) {
console . log ( 'Device connected:' , event . payload );
handleNewDevice ( event . payload );
}
});
Device Object
Each device is represented by a Device object:
interface Device {
path : string ; // Unique device path
label : string ; // Device label
state ?: string ; // Device state (passphrase dependent)
status : DeviceStatus ; // 'available' | 'occupied' | 'used'
mode : DeviceMode ; // 'normal' | 'bootloader' | 'initialize' | 'seedless'
firmware : DeviceFirmwareStatus ; // Firmware status
features ?: Features ; // Device features
unavailableCapabilities ?: UnavailableCapabilities ;
}
Device Features
Access device capabilities and information:
Get Features
Features Object
const result = await TrezorConnect . getFeatures ();
if ( result . success ) {
const { features } = result . payload ;
console . log ( 'Model:' , features . model );
console . log ( 'Firmware version:' , features . fw_version );
console . log ( 'Label:' , features . label );
console . log ( 'Initialized:' , features . initialized );
console . log ( 'Passphrase protection:' , features . passphrase_protection );
console . log ( 'PIN protection:' , features . pin_protection );
}
Device Status
Monitor device availability:
Available
Occupied
Used Elsewhere
Device is ready for operations: TrezorConnect . on ( DEVICE_EVENT , ( event ) => {
if ( event . type === DEVICE . CONNECT ) {
if ( event . payload . status === 'available' ) {
console . log ( 'Device ready' );
// Can start operations
}
}
});
Device is busy with another operation: if ( device . status === 'occupied' ) {
console . log ( 'Device busy, waiting...' );
// Wait for device to become available
}
Device is used by another application: TrezorConnect . on ( DEVICE_EVENT , ( event ) => {
if ( event . type === DEVICE . CONNECT_UNACQUIRED ) {
console . warn ( 'Device used by another app' );
showWarning ( 'Please close other apps using Trezor' );
}
});
Device Modes
Devices can operate in different modes:
Standard operational mode: if ( device . mode === 'normal' && device . features ?. initialized ) {
// Device ready for transactions
await performTransaction ();
}
Firmware update mode: TrezorConnect . on ( UI_EVENT , ( event ) => {
if ( event . type === UI_REQUEST . BOOTLOADER ) {
console . log ( 'Device in bootloader mode' );
// Can perform firmware update
await TrezorConnect . firmwareUpdate ();
}
});
Device needs initialization: TrezorConnect . on ( UI_EVENT , ( event ) => {
if ( event . type === UI_REQUEST . INITIALIZE ) {
// Device not initialized
const shouldSetup = await confirmSetup ();
if ( shouldSetup ) {
await TrezorConnect . resetDevice ({
strength: 256 ,
label: 'My Trezor'
});
}
}
});
Device without seed (backup missing): if ( device . mode === 'seedless' || device . features ?. needs_backup ) {
showWarning ( 'Please backup your device!' );
await TrezorConnect . backupDevice ();
}
Device State Management
Passphrase and Device State
Device state changes with different passphrases:
// Get device state (derives from passphrase)
const result = await TrezorConnect . getDeviceState ();
if ( result . success ) {
const state = result . payload . state ;
console . log ( 'Device state:' , state );
// State is a hash derived from:
// - Device session
// - Passphrase (if enabled)
// Used to identify different "wallets" on same device
}
State Validation
Device state validation prevents passphrase-related errors. Always validate state before sensitive operations.
// Store state after first successful operation
let expectedState : string ;
const firstResult = await TrezorConnect . getAddress ({
path: "m/49'/0'/0'/0/0" ,
coin: 'btc'
});
if ( firstResult . success && firstResult . device ) {
expectedState = firstResult . device . state ! ;
}
// Later, validate state matches
const secondResult = await TrezorConnect . signTransaction ({
// ... transaction params
});
if ( secondResult . success && secondResult . device ) {
if ( secondResult . device . state !== expectedState ) {
// Different passphrase was used!
throw new Error ( 'Device state mismatch - wrong passphrase?' );
}
}
Session Management
TrezorConnect manages device sessions automatically:
// Sessions are acquired automatically when calling methods
const result = await TrezorConnect . getAddress ({
path: "m/49'/0'/0'/0/0" ,
coin: 'btc'
});
// Session is released after method completes
// For multiple operations, sessions are reused when possible
await TrezorConnect . getAddress ({ path: "m/49'/0'/0'/0/0" , coin: 'btc' });
await TrezorConnect . getAddress ({ path: "m/49'/0'/0'/0/1" , coin: 'btc' });
// Same session used if device state matches
Firmware Management
Check Firmware Status
Firmware Version
Firmware Update
Firmware Hash
const result = await TrezorConnect . getFeatures ();
if ( result . success ) {
const { fw_version , bootloader_mode } = result . payload ;
console . log ( 'Firmware:' , fw_version . join ( '.' ));
console . log ( 'Bootloader mode:' , bootloader_mode );
}
Firmware Events
Monitor firmware update progress:
TrezorConnect . on ( UI_EVENT , ( event ) => {
if ( event . type === UI_REQUEST . FIRMWARE_PROGRESS ) {
const { operation , progress } = event . payload ;
switch ( operation ) {
case 'downloading' :
updateUI ( `Downloading firmware: ${ progress } %` );
break ;
case 'start-flashing' :
updateUI ( 'Starting firmware installation...' );
break ;
case 'flashing' :
updateUI ( `Installing firmware: ${ progress } %` );
break ;
}
}
if ( event . type === UI_REQUEST . FIRMWARE_RECONNECT ) {
const { disconnected , method , target } = event . payload ;
if ( disconnected ) {
showMessage ( `Please reconnect device in ${ target } mode` );
}
}
});
Device Configuration
Apply Settings
Change Label
Enable Passphrase
Auto-lock Timeout
Display Settings
await TrezorConnect . applySettings ({
label: 'My Trezor Wallet'
});
PIN Management
Change PIN
Remove PIN
Wipe Code
const result = await TrezorConnect . changePin ();
// Handle PIN requests via UI events
TrezorConnect . on ( UI_EVENT , async ( event ) => {
if ( event . type === UI_REQUEST . REQUEST_PIN ) {
const pin = await getUserInput ( 'Enter new PIN:' );
TrezorConnect . uiResponse ({
type: UI_REQUEST . RECEIVE_PIN ,
payload: pin
});
}
});
// Set empty PIN to remove protection
await TrezorConnect . changePin ({ remove: true });
// Set wipe code (alternative PIN that wipes device)
await TrezorConnect . changeWipeCode ();
Device Initialization
New Device Setup
Reset Device
Initialize a new device with seed generation: const result = await TrezorConnect . resetDevice ({
strength: 256 , // 256-bit entropy (24 words)
label: 'My Trezor' ,
passphrase_protection: true ,
pin_protection: true ,
skip_backup: false
});
Backup Device
Backup the seed phrase: const result = await TrezorConnect . backupDevice ();
// User will write down seed words on device
Verify Setup
Check device is properly initialized: const features = await TrezorConnect . getFeatures ();
if ( features . success ) {
const { initialized , needs_backup , pin_protection } = features . payload ;
if ( initialized && ! needs_backup && pin_protection ) {
console . log ( 'Device setup complete!' );
}
}
Device Recovery
Recover device from seed phrase:
const result = await TrezorConnect . recoveryDevice ({
word_count: 24 ,
passphrase_protection: true ,
pin_protection: true ,
label: 'Recovered Trezor'
});
// Handle word requests
TrezorConnect . on ( UI_EVENT , async ( event ) => {
if ( event . type === UI_REQUEST . REQUEST_WORD ) {
const word = await promptForSeedWord ( event . payload . type );
TrezorConnect . uiResponse ({
type: UI_REQUEST . RECEIVE_WORD ,
payload: word
});
}
});
Multiple Devices
Most TrezorConnect methods don’t support multiple devices simultaneously. Ensure only one device is connected or use device filtering.
Device Path Filtering
// Track connected devices
const devices = new Map < string , Device >();
TrezorConnect . on ( DEVICE_EVENT , ( event ) => {
if ( event . type === DEVICE . CONNECT ) {
devices . set ( event . payload . path , event . payload );
}
if ( event . type === DEVICE . DISCONNECT ) {
devices . delete ( event . payload . path );
}
});
// Use specific device by path
const devicePath = Array . from ( devices . keys ())[ 0 ];
const result = await TrezorConnect . getAddress ({
path: "m/49'/0'/0'/0/0" ,
coin: 'btc' ,
device: { path: devicePath } // Specify device
});
Advanced Features
THP (Trezor Host Protocol)
Manage THP credentials for enhanced security:
Get Credentials
Remove Credentials
THP Pairing
const result = await TrezorConnect . thpGetCredentials ();
if ( result . success ) {
console . log ( 'THP credentials:' , result . payload . credentials );
// Store credentials securely
}
Device Authentication
const result = await TrezorConnect . authenticateDevice ({
challenge_hidden: 'random-challenge' ,
challenge_visual: 'Confirm authentication'
});
if ( result . success ) {
console . log ( 'Device authenticated' );
console . log ( 'Signature:' , result . payload . signature );
}
Bluetooth Management
// Unpair Bluetooth device
const result = await TrezorConnect . bleUnpair ();
if ( result . success ) {
console . log ( 'Bluetooth device unpaired' );
}
Best Practices
Always handle disconnections - Listen for DEVICE.DISCONNECT and gracefully handle device removal
Validate device state - Check state consistency for passphrase-protected devices
Monitor firmware status - Warn users about outdated firmware
Handle errors gracefully - Device can disconnect during operations
Clean up listeners - Remove event listeners when components unmount
Never cache sensitive data (PINs, passphrases) in your application. Always prompt users when needed.
Complete Example
import TrezorConnect , { DEVICE_EVENT , DEVICE , UI_EVENT , UI_REQUEST } from '@trezor/connect' ;
class DeviceManager {
private currentDevice : Device | null = null ;
private deviceState : string | null = null ;
async initialize () {
await TrezorConnect . init ({
manifest: {
email: '[email protected] ' ,
appUrl: 'https://example.com'
}
});
// Monitor device connections
TrezorConnect . on ( DEVICE_EVENT , this . handleDeviceEvent );
TrezorConnect . on ( UI_EVENT , this . handleUIEvent );
}
handleDeviceEvent = ( event ) => {
switch ( event . type ) {
case DEVICE . CONNECT :
this . currentDevice = event . payload ;
this . checkDeviceStatus ( event . payload );
break ;
case DEVICE . DISCONNECT :
if ( this . currentDevice ?. path === event . payload . path ) {
this . currentDevice = null ;
this . deviceState = null ;
}
break ;
case DEVICE . CHANGED :
this . currentDevice = event . payload ;
break ;
}
};
async checkDeviceStatus ( device : Device ) {
if ( ! device . features ?. initialized ) {
console . warn ( 'Device not initialized' );
return ;
}
if ( device . features . needs_backup ) {
console . warn ( 'Device needs backup!' );
}
if ( device . firmware === 'outdated' ) {
console . warn ( 'Firmware update available' );
}
}
handleUIEvent = async ( event ) => {
if ( event . type === UI_REQUEST . REQUEST_PIN ) {
const pin = await this . promptPin ();
TrezorConnect . uiResponse ({
type: UI_REQUEST . RECEIVE_PIN ,
payload: pin
});
}
};
async performOperation () {
if ( ! this . currentDevice ) {
throw new Error ( 'No device connected' );
}
const result = await TrezorConnect . getAddress ({
path: "m/49'/0'/0'/0/0" ,
coin: 'btc'
});
if ( result . success && result . device ) {
// Store state for validation
this . deviceState = result . device . state ! ;
return result . payload ;
}
throw result . error ;
}
cleanup () {
TrezorConnect . off ( DEVICE_EVENT , this . handleDeviceEvent );
TrezorConnect . off ( UI_EVENT , this . handleUIEvent );
}
}
Next Steps
Methods Explore TrezorConnect methods
Events Learn about event handling
Error Handling Handle errors effectively