Overview
TrezorConnect uses an event-driven architecture to notify your application about device state changes, user interactions, blockchain updates, and transport status. Events are emitted asynchronously and can be handled using event listeners.
Event Listeners
Subscribe to events using the on method and unsubscribe with off:
import TrezorConnect , { DEVICE_EVENT , DEVICE } from '@trezor/connect' ;
// Subscribe to device events
const handleDeviceEvent = ( event ) => {
console . log ( 'Device event:' , event );
};
TrezorConnect . on ( DEVICE_EVENT , handleDeviceEvent );
// Unsubscribe when done
TrezorConnect . off ( DEVICE_EVENT , handleDeviceEvent );
// Remove all listeners
TrezorConnect . removeAllListeners ();
Event Categories
Events are organized into four main categories:
DEVICE_EVENT Device connection, disconnection, and state changes
UI_EVENT User interaction requests and firmware progress
TRANSPORT_EVENT Transport layer status and errors
BLOCKCHAIN_EVENT Blockchain connection and transaction notifications
Device Events
Monitor device connections and state changes:
Connection Events
Device Connect
Device Disconnect
Device Changed
Unacquired Device
import TrezorConnect , { DEVICE_EVENT , DEVICE } from '@trezor/connect' ;
TrezorConnect . on ( DEVICE_EVENT , ( event ) => {
if ( event . type === DEVICE . CONNECT ) {
console . log ( 'Device connected:' , event . payload );
console . log ( 'Features:' , event . payload . features );
console . log ( 'Mode:' , event . payload . mode );
console . log ( 'Path:' , event . payload . path );
}
});
Device Event Constants
export const DEVICE = {
// Device list events
CONNECT: 'device-connect' ,
CONNECT_UNACQUIRED: 'device-connect_unacquired' ,
DISCONNECT: 'device-disconnect' ,
CHANGED: 'device-changed' ,
FIRMWARE_VERSION_CHANGED: 'device-firmware_version_changed' ,
TREZOR_PUSH_NOTIFICATION: 'device-trezor_push_notification' ,
THP_CREDENTIALS_CHANGED: 'device-thp_credentials_changed' ,
// Trezor-link events (protobuf format)
BUTTON: 'button' ,
PIN: 'pin' ,
PASSPHRASE: 'passphrase' ,
PASSPHRASE_ON_DEVICE: 'passphrase_on_device' ,
WORD: 'word' ,
THP_PAIRING: 'thp_pairing' ,
THP_PAIRING_STATUS_CHANGED: 'device-thp_pairing_status_changed' ,
} as const ;
Button request events are emitted when the device requires physical confirmation.
TrezorConnect . on ( DEVICE_EVENT , ( event ) => {
if ( event . type === DEVICE . BUTTON ) {
console . log ( 'Button request code:' , event . payload . code );
// Possible codes: ButtonRequest_ConfirmOutput,
// ButtonRequest_SignTx, ButtonRequest_Address, etc.
// Show UI prompt to user
showMessage ( 'Please confirm action on your Trezor device' );
}
});
Firmware Version Changed
TrezorConnect . on ( DEVICE_EVENT , ( event ) => {
if ( event . type === DEVICE . FIRMWARE_VERSION_CHANGED ) {
console . log ( 'Old version:' , event . payload . oldVersion );
console . log ( 'New version:' , event . payload . newVersion );
console . log ( 'Device:' , event . payload . device );
}
});
UI Events
UI events request user interaction or display progress:
Request Events
Emitted when the device requires PIN entry: import { UI_EVENT , UI_REQUEST } from '@trezor/connect' ;
TrezorConnect . on ( UI_EVENT , ( event ) => {
if ( event . type === UI_REQUEST . REQUEST_PIN ) {
// Show PIN dialog
const pin = await showPinDialog ();
// Send PIN to device
TrezorConnect . uiResponse ({
type: UI_REQUEST . RECEIVE_PIN ,
payload: pin
});
}
});
Emitted when passphrase is required: TrezorConnect . on ( UI_EVENT , ( event ) => {
if ( event . type === UI_REQUEST . REQUEST_PASSPHRASE ) {
const passphrase = await showPassphraseDialog ();
TrezorConnect . uiResponse ({
type: UI_REQUEST . RECEIVE_PASSPHRASE ,
payload: {
value: passphrase ,
save: false // Don't cache passphrase
}
});
}
// Passphrase entry on device
if ( event . type === UI_REQUEST . REQUEST_PASSPHRASE_ON_DEVICE ) {
showMessage ( 'Enter passphrase on device' );
}
});
Emitted during seed recovery: TrezorConnect . on ( UI_EVENT , ( event ) => {
if ( event . type === UI_REQUEST . REQUEST_WORD ) {
console . log ( 'Word type:' , event . payload . type );
// WordRequestType_Plain, WordRequestType_Matrix9, etc.
const word = await promptForWord ();
TrezorConnect . uiResponse ({
type: UI_REQUEST . RECEIVE_WORD ,
payload: word
});
}
});
Generic confirmation requests: TrezorConnect . on ( UI_EVENT , ( event ) => {
if ( event . type === UI_REQUEST . REQUEST_CONFIRMATION ) {
const { view , label } = event . payload ;
// Possible views: 'export-xpub', 'export-address',
// 'no-backup', 'device-management', etc.
const confirmed = await showConfirmationDialog ( label );
TrezorConnect . uiResponse ({
type: UI_REQUEST . RECEIVE_CONFIRMATION ,
payload: confirmed
});
}
});
UI Event Constants
export const UI_REQUEST = {
TRANSPORT: 'ui-no_transport' ,
BOOTLOADER: 'ui-device_bootloader_mode' ,
NOT_IN_BOOTLOADER: 'ui-device_not_in_bootloader_mode' ,
INITIALIZE: 'ui-device_not_initialized' ,
SEEDLESS: 'ui-device_seedless' ,
FIRMWARE_OLD: 'ui-device_firmware_old' ,
FIRMWARE_OUTDATED: 'ui-device_firmware_outdated' ,
FIRMWARE_NOT_SUPPORTED: 'ui-device_firmware_unsupported' ,
FIRMWARE_NOT_COMPATIBLE: 'ui-device_firmware_not_compatible' ,
FIRMWARE_NOT_INSTALLED: 'ui-device_firmware_not_installed' ,
FIRMWARE_PROGRESS: 'ui-firmware-progress' ,
FIRMWARE_RECONNECT: 'ui-firmware_reconnect' ,
REQUEST_CONFIRMATION: 'ui-request_confirmation' ,
REQUEST_PIN: 'ui-request_pin' ,
INVALID_PIN: 'ui-invalid_pin' ,
REQUEST_PASSPHRASE: 'ui-request_passphrase' ,
REQUEST_PASSPHRASE_ON_DEVICE: 'ui-request_passphrase_on_device' ,
REQUEST_BUTTON: 'ui-button' ,
REQUEST_WORD: 'ui-request_word' ,
BUNDLE_PROGRESS: 'ui-bundle_progress' ,
ADDRESS_VALIDATION: 'ui-address_validation' ,
} as const ;
Firmware Progress
TrezorConnect . on ( UI_EVENT , ( event ) => {
if ( event . type === UI_REQUEST . FIRMWARE_PROGRESS ) {
const { operation , progress } = event . payload ;
// operation: 'downloading' | 'flashing' | 'start-flashing'
// progress: 0-100
updateProgressBar ( progress );
console . log ( ` ${ operation } : ${ progress } %` );
}
});
Bundle Progress
TrezorConnect . on ( UI_EVENT , ( event ) => {
if ( event . type === UI_REQUEST . BUNDLE_PROGRESS ) {
const { total , progress , response } = event . payload ;
console . log ( `Processing ${ progress + 1 } of ${ total } ` );
console . log ( 'Current response:' , response );
}
});
Transport Events
Monitor transport layer status:
Transport Start
Transport Error
import { TRANSPORT_EVENT , TRANSPORT } from '@trezor/connect' ;
TrezorConnect . on ( TRANSPORT_EVENT , ( event ) => {
if ( event . type === TRANSPORT . START ) {
console . log ( 'Transport started:' , event . payload );
console . log ( 'Type:' , event . payload . type ); // 'BridgeTransport', 'WebUsbTransport'
console . log ( 'Version:' , event . payload . version );
console . log ( 'Outdated:' , event . payload . outdated );
}
});
Transport Constants
export const TRANSPORT = {
START: 'transport-start' ,
ERROR: 'transport-error' ,
// Additional transport actions:
SET_TRANSPORTS: 'transport-set_transports' ,
DISABLE_WEBUSB: 'transport-disable_webusb' ,
REQUEST_DEVICE: 'transport-request_device' ,
GET_INFO: 'transport-get_info' ,
} as const ;
Blockchain Events
Monitor blockchain backend connections and notifications:
Connection Events
Blockchain Connect
Blockchain Error
Blockchain Reconnecting
import { BLOCKCHAIN_EVENT , BLOCKCHAIN } from '@trezor/connect' ;
TrezorConnect . on ( BLOCKCHAIN_EVENT , ( event ) => {
if ( event . type === BLOCKCHAIN . CONNECT ) {
console . log ( 'Blockchain connected:' , event . payload . coin );
console . log ( 'Block height:' , event . payload . blockHeight );
console . log ( 'Block hash:' , event . payload . blockHash );
}
});
Block and Transaction Events
New Block
Transaction Notification
Fiat Rates Update
TrezorConnect . on ( BLOCKCHAIN_EVENT , ( event ) => {
if ( event . type === BLOCKCHAIN . BLOCK ) {
console . log ( 'New block on' , event . payload . coin );
console . log ( 'Block height:' , event . payload . blockHeight );
console . log ( 'Block hash:' , event . payload . blockHash );
}
});
Blockchain Constants
export const BLOCKCHAIN = {
CONNECT: 'blockchain-connect' ,
RECONNECTING: 'blockchain-reconnecting' ,
ERROR: 'blockchain-error' ,
BLOCK: 'blockchain-block' ,
NOTIFICATION: 'blockchain-notification' ,
FIAT_RATES_UPDATE: 'fiat-rates-update' ,
} as const ;
Event Filtering
Filter specific event types:
import TrezorConnect , { DEVICE_EVENT , DEVICE } from '@trezor/connect' ;
// Listen to specific device event type
TrezorConnect . on ( DEVICE . CONNECT , ( device ) => {
console . log ( 'Device connected:' , device );
});
TrezorConnect . on ( DEVICE . DISCONNECT , ( device ) => {
console . log ( 'Device disconnected:' , device );
});
// Or filter within the event handler
TrezorConnect . on ( DEVICE_EVENT , ( event ) => {
switch ( event . type ) {
case DEVICE . CONNECT :
handleConnect ( event . payload );
break ;
case DEVICE . DISCONNECT :
handleDisconnect ( event . payload );
break ;
case DEVICE . CHANGED :
handleChanged ( event . payload );
break ;
}
});
Advanced: UI Response
Respond to UI requests using uiResponse:
import TrezorConnect , { UI_REQUEST } from '@trezor/connect' ;
// Example: Complete PIN flow
TrezorConnect . on ( UI_EVENT , async ( event ) => {
if ( event . type === UI_REQUEST . REQUEST_PIN ) {
const pin = await getUserPin ();
TrezorConnect . uiResponse ({
type: UI_REQUEST . RECEIVE_PIN ,
payload: pin
});
}
if ( event . type === UI_REQUEST . INVALID_PIN ) {
showError ( 'Invalid PIN, please try again' );
}
});
Event Payload Types
All events are fully typed in TypeScript:
import type {
DeviceEvent ,
UiEvent ,
TransportEvent ,
BlockchainEvent
} from '@trezor/connect' ;
const handleDeviceEvent = ( event : DeviceEvent ) => {
// TypeScript knows the shape of event.payload
if ( event . type === DEVICE . CONNECT ) {
const features = event . payload . features ; // typed
}
};
Best Practices
Always remove event listeners when they’re no longer needed to prevent memory leaks.
Use specific event type listeners (DEVICE.CONNECT) for cleaner code
Handle errors in event listeners to prevent unhandled promise rejections
Store listener references to properly clean them up
Test event handling for edge cases (disconnection during operation)
Complete Example
import TrezorConnect , {
DEVICE_EVENT ,
DEVICE ,
UI_EVENT ,
UI_REQUEST ,
TRANSPORT_EVENT ,
TRANSPORT
} from '@trezor/connect' ;
class TrezorManager {
private listeners : Array <() => void > = [];
initialize () {
// Device events
const deviceListener = TrezorConnect . on ( DEVICE_EVENT , this . handleDevice );
this . listeners . push (() => TrezorConnect . off ( DEVICE_EVENT , this . handleDevice ));
// UI events
const uiListener = TrezorConnect . on ( UI_EVENT , this . handleUI );
this . listeners . push (() => TrezorConnect . off ( UI_EVENT , this . handleUI ));
// Transport events
const transportListener = TrezorConnect . on ( TRANSPORT_EVENT , this . handleTransport );
this . listeners . push (() => TrezorConnect . off ( TRANSPORT_EVENT , this . handleTransport ));
}
handleDevice = ( event ) => {
switch ( event . type ) {
case DEVICE . CONNECT :
console . log ( 'Device connected' );
break ;
case DEVICE . DISCONNECT :
console . log ( 'Device disconnected' );
break ;
}
};
handleUI = async ( event ) => {
if ( event . type === UI_REQUEST . REQUEST_PIN ) {
const pin = await this . promptPin ();
TrezorConnect . uiResponse ({
type: UI_REQUEST . RECEIVE_PIN ,
payload: pin
});
}
};
handleTransport = ( event ) => {
if ( event . type === TRANSPORT . ERROR ) {
console . error ( 'Transport error:' , event . payload );
}
};
cleanup () {
this . listeners . forEach ( remove => remove ());
this . listeners = [];
}
}
Next Steps
Methods Learn about TrezorConnect methods
Device Management Manage device connections
Error Handling Handle errors effectively