@onekeyfe/hwk-trezor-connector-webusb 1.1.27-alpha.100
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +133 -0
- package/dist/index.d.ts +133 -0
- package/dist/index.js +333 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +297 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +58 -0
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { TrezorConnectorBase, TrezorConnectorBaseOptions, TrezorConnectorByteTransport } from '@onekeyfe/hwk-trezor-connector';
|
|
2
|
+
import { ConnectorDevice } from '@onekeyfe/hwk-adapter-core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Descriptor returned by scan(). Lightweight — the actual USBDevice is held
|
|
6
|
+
* internally until connect() is called.
|
|
7
|
+
*/
|
|
8
|
+
interface TrezorWebUsbDescriptor {
|
|
9
|
+
/** Stable id used as connectId. Prefers serialNumber; falls back to a synthesized id. */
|
|
10
|
+
connectId: string;
|
|
11
|
+
serialNumber?: string;
|
|
12
|
+
vendorId: number;
|
|
13
|
+
productId: number;
|
|
14
|
+
productName?: string;
|
|
15
|
+
manufacturerName?: string;
|
|
16
|
+
isBootloader: boolean;
|
|
17
|
+
/** USB spec version this device implements (Window USBDevice fields). */
|
|
18
|
+
usbVersionMajor?: number;
|
|
19
|
+
usbVersionMinor?: number;
|
|
20
|
+
usbVersionSubminor?: number;
|
|
21
|
+
/** Device-class triple from the USB descriptor. */
|
|
22
|
+
deviceClass?: number;
|
|
23
|
+
deviceSubclass?: number;
|
|
24
|
+
deviceProtocol?: number;
|
|
25
|
+
/** Firmware-reported device version (DIFFERENT from THP-handshake firmware version). */
|
|
26
|
+
deviceVersionMajor?: number;
|
|
27
|
+
deviceVersionMinor?: number;
|
|
28
|
+
deviceVersionSubminor?: number;
|
|
29
|
+
/** Whether the host has previously opened this device handle. */
|
|
30
|
+
opened?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Catch-all blob for fields we haven't promoted to the typed surface yet.
|
|
33
|
+
* Currently includes:
|
|
34
|
+
* - configurations: minimal summary of USBConfiguration[] (number + alt count)
|
|
35
|
+
* Treat as informational only — anything actually used should be promoted
|
|
36
|
+
* to a typed field above.
|
|
37
|
+
*/
|
|
38
|
+
raw?: Record<string, unknown>;
|
|
39
|
+
}
|
|
40
|
+
interface TrezorWebUsbTransportOptions {
|
|
41
|
+
/** Override navigator.usb (mainly for tests). */
|
|
42
|
+
usb?: USB;
|
|
43
|
+
logger?: (entry: {
|
|
44
|
+
level: 'debug' | 'info' | 'warn' | 'error';
|
|
45
|
+
scope: string;
|
|
46
|
+
event: string;
|
|
47
|
+
data?: Record<string, unknown>;
|
|
48
|
+
}) => void;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Thin wrapper around `navigator.usb` providing the same scan/connect/read/
|
|
52
|
+
* write/onDisconnect surface that TrezorRnBleConnector's transport exposes,
|
|
53
|
+
* so TrezorWebUsbConnector can be a one-page subclass of TrezorConnectorBase.
|
|
54
|
+
*
|
|
55
|
+
* NOT responsible for the WebUSB permission prompt — that needs a user
|
|
56
|
+
* gesture, which callers must trigger themselves via `requestDevice()`.
|
|
57
|
+
*/
|
|
58
|
+
declare class TrezorWebUsbTransport {
|
|
59
|
+
private readonly _usb;
|
|
60
|
+
private readonly _logger?;
|
|
61
|
+
private readonly _connected;
|
|
62
|
+
private readonly _disconnectHandlers;
|
|
63
|
+
private readonly _globalDisconnectListener;
|
|
64
|
+
constructor(options?: TrezorWebUsbTransportOptions);
|
|
65
|
+
/**
|
|
66
|
+
* Trigger the browser's WebUSB permission picker. Must be called from a
|
|
67
|
+
* user gesture (click handler). Adds the picked device to the
|
|
68
|
+
* authorized list so subsequent scan() calls include it.
|
|
69
|
+
*/
|
|
70
|
+
requestDevice(): Promise<TrezorWebUsbDescriptor>;
|
|
71
|
+
/** List previously-authorized Trezor devices (no permission prompt). */
|
|
72
|
+
scan(): Promise<TrezorWebUsbDescriptor[]>;
|
|
73
|
+
connect(connectId: string): Promise<USBDevice>;
|
|
74
|
+
disconnect(connectId: string): Promise<void>;
|
|
75
|
+
write(connectId: string, data: Uint8Array): Promise<void>;
|
|
76
|
+
read(connectId: string): Promise<Uint8Array>;
|
|
77
|
+
onDisconnect(connectId: string, handler: () => void): () => void;
|
|
78
|
+
reset(): void;
|
|
79
|
+
private _ensureConnected;
|
|
80
|
+
private _toDescriptor;
|
|
81
|
+
private _handlePhysicalDisconnect;
|
|
82
|
+
private _log;
|
|
83
|
+
}
|
|
84
|
+
declare function createTrezorWebUsbTransport(options?: TrezorWebUsbTransportOptions): Promise<TrezorWebUsbTransport>;
|
|
85
|
+
|
|
86
|
+
interface TrezorWebUsbConnectorOptions {
|
|
87
|
+
/** Pre-built transport (optional). If omitted, one is created lazily on first use. */
|
|
88
|
+
transport?: TrezorWebUsbTransport;
|
|
89
|
+
/** Options forwarded to a lazily-created transport. Ignored if `transport` is supplied. */
|
|
90
|
+
transportOptions?: TrezorWebUsbTransportOptions;
|
|
91
|
+
thp?: TrezorConnectorBaseOptions['thp'];
|
|
92
|
+
deviceSessionFactory?: TrezorConnectorBaseOptions['deviceSessionFactory'];
|
|
93
|
+
}
|
|
94
|
+
declare class TrezorWebUsbConnector extends TrezorConnectorBase {
|
|
95
|
+
private _transport;
|
|
96
|
+
private readonly _transportOptions?;
|
|
97
|
+
constructor(options?: TrezorWebUsbConnectorOptions);
|
|
98
|
+
/**
|
|
99
|
+
* Trigger the browser's WebUSB permission picker. Must be called from a
|
|
100
|
+
* user-gesture event handler. Returns the chosen device's descriptor; the
|
|
101
|
+
* connector remembers it so subsequent searchDevices() picks it up.
|
|
102
|
+
*/
|
|
103
|
+
requestDevice(): Promise<ConnectorDevice>;
|
|
104
|
+
protected enumerateDevices(): Promise<ConnectorDevice[]>;
|
|
105
|
+
protected createByteTransport(device: ConnectorDevice): Promise<TrezorConnectorByteTransport>;
|
|
106
|
+
reset(): void;
|
|
107
|
+
private _ensureTransport;
|
|
108
|
+
}
|
|
109
|
+
declare function createTrezorWebUsbConnector(options?: TrezorWebUsbConnectorOptions): TrezorWebUsbConnector;
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* USB constants for Trezor devices.
|
|
113
|
+
*
|
|
114
|
+
* Matches @trezor/transport src/constants.ts. T1 HID (vendor 0x534c) is NOT
|
|
115
|
+
* WebUSB-accessible — it uses the HID class which navigator.usb can't claim;
|
|
116
|
+
* users with T1 need the bridge daemon. We only expose 0x1209 (WebUSB-class)
|
|
117
|
+
* here.
|
|
118
|
+
*/
|
|
119
|
+
declare const TREZOR_WEBUSB_VENDOR_ID = 4617;
|
|
120
|
+
/** Trezor firmware (Model T / Safe 5 / Safe 3) running normally */
|
|
121
|
+
declare const TREZOR_WEBUSB_FIRMWARE_PRODUCT = 21441;
|
|
122
|
+
/** Trezor firmware in bootloader mode (firmware update / wipe) */
|
|
123
|
+
declare const TREZOR_WEBUSB_BOOTLOADER_PRODUCT = 21440;
|
|
124
|
+
/** Standard WebUSB filters that show only WebUSB-accessible Trezor devices in the picker. */
|
|
125
|
+
declare const TREZOR_WEBUSB_FILTERS: USBDeviceFilter[];
|
|
126
|
+
/** Trezor's standard USB layout — configuration 1, interface 0, endpoint 1. */
|
|
127
|
+
declare const TREZOR_USB_CONFIGURATION_ID = 1;
|
|
128
|
+
declare const TREZOR_USB_INTERFACE_ID = 0;
|
|
129
|
+
declare const TREZOR_USB_ENDPOINT_ID = 1;
|
|
130
|
+
/** Trezor wire packet size on USB. */
|
|
131
|
+
declare const TREZOR_USB_PACKET_SIZE = 64;
|
|
132
|
+
|
|
133
|
+
export { TREZOR_USB_CONFIGURATION_ID, TREZOR_USB_ENDPOINT_ID, TREZOR_USB_INTERFACE_ID, TREZOR_USB_PACKET_SIZE, TREZOR_WEBUSB_BOOTLOADER_PRODUCT, TREZOR_WEBUSB_FILTERS, TREZOR_WEBUSB_FIRMWARE_PRODUCT, TREZOR_WEBUSB_VENDOR_ID, TrezorWebUsbConnector, type TrezorWebUsbConnectorOptions, type TrezorWebUsbDescriptor, TrezorWebUsbTransport, type TrezorWebUsbTransportOptions, createTrezorWebUsbConnector, createTrezorWebUsbTransport };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { TrezorConnectorBase, TrezorConnectorBaseOptions, TrezorConnectorByteTransport } from '@onekeyfe/hwk-trezor-connector';
|
|
2
|
+
import { ConnectorDevice } from '@onekeyfe/hwk-adapter-core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Descriptor returned by scan(). Lightweight — the actual USBDevice is held
|
|
6
|
+
* internally until connect() is called.
|
|
7
|
+
*/
|
|
8
|
+
interface TrezorWebUsbDescriptor {
|
|
9
|
+
/** Stable id used as connectId. Prefers serialNumber; falls back to a synthesized id. */
|
|
10
|
+
connectId: string;
|
|
11
|
+
serialNumber?: string;
|
|
12
|
+
vendorId: number;
|
|
13
|
+
productId: number;
|
|
14
|
+
productName?: string;
|
|
15
|
+
manufacturerName?: string;
|
|
16
|
+
isBootloader: boolean;
|
|
17
|
+
/** USB spec version this device implements (Window USBDevice fields). */
|
|
18
|
+
usbVersionMajor?: number;
|
|
19
|
+
usbVersionMinor?: number;
|
|
20
|
+
usbVersionSubminor?: number;
|
|
21
|
+
/** Device-class triple from the USB descriptor. */
|
|
22
|
+
deviceClass?: number;
|
|
23
|
+
deviceSubclass?: number;
|
|
24
|
+
deviceProtocol?: number;
|
|
25
|
+
/** Firmware-reported device version (DIFFERENT from THP-handshake firmware version). */
|
|
26
|
+
deviceVersionMajor?: number;
|
|
27
|
+
deviceVersionMinor?: number;
|
|
28
|
+
deviceVersionSubminor?: number;
|
|
29
|
+
/** Whether the host has previously opened this device handle. */
|
|
30
|
+
opened?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Catch-all blob for fields we haven't promoted to the typed surface yet.
|
|
33
|
+
* Currently includes:
|
|
34
|
+
* - configurations: minimal summary of USBConfiguration[] (number + alt count)
|
|
35
|
+
* Treat as informational only — anything actually used should be promoted
|
|
36
|
+
* to a typed field above.
|
|
37
|
+
*/
|
|
38
|
+
raw?: Record<string, unknown>;
|
|
39
|
+
}
|
|
40
|
+
interface TrezorWebUsbTransportOptions {
|
|
41
|
+
/** Override navigator.usb (mainly for tests). */
|
|
42
|
+
usb?: USB;
|
|
43
|
+
logger?: (entry: {
|
|
44
|
+
level: 'debug' | 'info' | 'warn' | 'error';
|
|
45
|
+
scope: string;
|
|
46
|
+
event: string;
|
|
47
|
+
data?: Record<string, unknown>;
|
|
48
|
+
}) => void;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Thin wrapper around `navigator.usb` providing the same scan/connect/read/
|
|
52
|
+
* write/onDisconnect surface that TrezorRnBleConnector's transport exposes,
|
|
53
|
+
* so TrezorWebUsbConnector can be a one-page subclass of TrezorConnectorBase.
|
|
54
|
+
*
|
|
55
|
+
* NOT responsible for the WebUSB permission prompt — that needs a user
|
|
56
|
+
* gesture, which callers must trigger themselves via `requestDevice()`.
|
|
57
|
+
*/
|
|
58
|
+
declare class TrezorWebUsbTransport {
|
|
59
|
+
private readonly _usb;
|
|
60
|
+
private readonly _logger?;
|
|
61
|
+
private readonly _connected;
|
|
62
|
+
private readonly _disconnectHandlers;
|
|
63
|
+
private readonly _globalDisconnectListener;
|
|
64
|
+
constructor(options?: TrezorWebUsbTransportOptions);
|
|
65
|
+
/**
|
|
66
|
+
* Trigger the browser's WebUSB permission picker. Must be called from a
|
|
67
|
+
* user gesture (click handler). Adds the picked device to the
|
|
68
|
+
* authorized list so subsequent scan() calls include it.
|
|
69
|
+
*/
|
|
70
|
+
requestDevice(): Promise<TrezorWebUsbDescriptor>;
|
|
71
|
+
/** List previously-authorized Trezor devices (no permission prompt). */
|
|
72
|
+
scan(): Promise<TrezorWebUsbDescriptor[]>;
|
|
73
|
+
connect(connectId: string): Promise<USBDevice>;
|
|
74
|
+
disconnect(connectId: string): Promise<void>;
|
|
75
|
+
write(connectId: string, data: Uint8Array): Promise<void>;
|
|
76
|
+
read(connectId: string): Promise<Uint8Array>;
|
|
77
|
+
onDisconnect(connectId: string, handler: () => void): () => void;
|
|
78
|
+
reset(): void;
|
|
79
|
+
private _ensureConnected;
|
|
80
|
+
private _toDescriptor;
|
|
81
|
+
private _handlePhysicalDisconnect;
|
|
82
|
+
private _log;
|
|
83
|
+
}
|
|
84
|
+
declare function createTrezorWebUsbTransport(options?: TrezorWebUsbTransportOptions): Promise<TrezorWebUsbTransport>;
|
|
85
|
+
|
|
86
|
+
interface TrezorWebUsbConnectorOptions {
|
|
87
|
+
/** Pre-built transport (optional). If omitted, one is created lazily on first use. */
|
|
88
|
+
transport?: TrezorWebUsbTransport;
|
|
89
|
+
/** Options forwarded to a lazily-created transport. Ignored if `transport` is supplied. */
|
|
90
|
+
transportOptions?: TrezorWebUsbTransportOptions;
|
|
91
|
+
thp?: TrezorConnectorBaseOptions['thp'];
|
|
92
|
+
deviceSessionFactory?: TrezorConnectorBaseOptions['deviceSessionFactory'];
|
|
93
|
+
}
|
|
94
|
+
declare class TrezorWebUsbConnector extends TrezorConnectorBase {
|
|
95
|
+
private _transport;
|
|
96
|
+
private readonly _transportOptions?;
|
|
97
|
+
constructor(options?: TrezorWebUsbConnectorOptions);
|
|
98
|
+
/**
|
|
99
|
+
* Trigger the browser's WebUSB permission picker. Must be called from a
|
|
100
|
+
* user-gesture event handler. Returns the chosen device's descriptor; the
|
|
101
|
+
* connector remembers it so subsequent searchDevices() picks it up.
|
|
102
|
+
*/
|
|
103
|
+
requestDevice(): Promise<ConnectorDevice>;
|
|
104
|
+
protected enumerateDevices(): Promise<ConnectorDevice[]>;
|
|
105
|
+
protected createByteTransport(device: ConnectorDevice): Promise<TrezorConnectorByteTransport>;
|
|
106
|
+
reset(): void;
|
|
107
|
+
private _ensureTransport;
|
|
108
|
+
}
|
|
109
|
+
declare function createTrezorWebUsbConnector(options?: TrezorWebUsbConnectorOptions): TrezorWebUsbConnector;
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* USB constants for Trezor devices.
|
|
113
|
+
*
|
|
114
|
+
* Matches @trezor/transport src/constants.ts. T1 HID (vendor 0x534c) is NOT
|
|
115
|
+
* WebUSB-accessible — it uses the HID class which navigator.usb can't claim;
|
|
116
|
+
* users with T1 need the bridge daemon. We only expose 0x1209 (WebUSB-class)
|
|
117
|
+
* here.
|
|
118
|
+
*/
|
|
119
|
+
declare const TREZOR_WEBUSB_VENDOR_ID = 4617;
|
|
120
|
+
/** Trezor firmware (Model T / Safe 5 / Safe 3) running normally */
|
|
121
|
+
declare const TREZOR_WEBUSB_FIRMWARE_PRODUCT = 21441;
|
|
122
|
+
/** Trezor firmware in bootloader mode (firmware update / wipe) */
|
|
123
|
+
declare const TREZOR_WEBUSB_BOOTLOADER_PRODUCT = 21440;
|
|
124
|
+
/** Standard WebUSB filters that show only WebUSB-accessible Trezor devices in the picker. */
|
|
125
|
+
declare const TREZOR_WEBUSB_FILTERS: USBDeviceFilter[];
|
|
126
|
+
/** Trezor's standard USB layout — configuration 1, interface 0, endpoint 1. */
|
|
127
|
+
declare const TREZOR_USB_CONFIGURATION_ID = 1;
|
|
128
|
+
declare const TREZOR_USB_INTERFACE_ID = 0;
|
|
129
|
+
declare const TREZOR_USB_ENDPOINT_ID = 1;
|
|
130
|
+
/** Trezor wire packet size on USB. */
|
|
131
|
+
declare const TREZOR_USB_PACKET_SIZE = 64;
|
|
132
|
+
|
|
133
|
+
export { TREZOR_USB_CONFIGURATION_ID, TREZOR_USB_ENDPOINT_ID, TREZOR_USB_INTERFACE_ID, TREZOR_USB_PACKET_SIZE, TREZOR_WEBUSB_BOOTLOADER_PRODUCT, TREZOR_WEBUSB_FILTERS, TREZOR_WEBUSB_FIRMWARE_PRODUCT, TREZOR_WEBUSB_VENDOR_ID, TrezorWebUsbConnector, type TrezorWebUsbConnectorOptions, type TrezorWebUsbDescriptor, TrezorWebUsbTransport, type TrezorWebUsbTransportOptions, createTrezorWebUsbConnector, createTrezorWebUsbTransport };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
TREZOR_USB_CONFIGURATION_ID: () => TREZOR_USB_CONFIGURATION_ID,
|
|
24
|
+
TREZOR_USB_ENDPOINT_ID: () => TREZOR_USB_ENDPOINT_ID,
|
|
25
|
+
TREZOR_USB_INTERFACE_ID: () => TREZOR_USB_INTERFACE_ID,
|
|
26
|
+
TREZOR_USB_PACKET_SIZE: () => TREZOR_USB_PACKET_SIZE,
|
|
27
|
+
TREZOR_WEBUSB_BOOTLOADER_PRODUCT: () => TREZOR_WEBUSB_BOOTLOADER_PRODUCT,
|
|
28
|
+
TREZOR_WEBUSB_FILTERS: () => TREZOR_WEBUSB_FILTERS,
|
|
29
|
+
TREZOR_WEBUSB_FIRMWARE_PRODUCT: () => TREZOR_WEBUSB_FIRMWARE_PRODUCT,
|
|
30
|
+
TREZOR_WEBUSB_VENDOR_ID: () => TREZOR_WEBUSB_VENDOR_ID,
|
|
31
|
+
TrezorWebUsbConnector: () => TrezorWebUsbConnector,
|
|
32
|
+
TrezorWebUsbTransport: () => TrezorWebUsbTransport,
|
|
33
|
+
createTrezorWebUsbConnector: () => createTrezorWebUsbConnector,
|
|
34
|
+
createTrezorWebUsbTransport: () => createTrezorWebUsbTransport
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(index_exports);
|
|
37
|
+
|
|
38
|
+
// src/TrezorWebUsbConnector.ts
|
|
39
|
+
var import_buffer = require("buffer");
|
|
40
|
+
var import_hwk_trezor_connector = require("@onekeyfe/hwk-trezor-connector");
|
|
41
|
+
|
|
42
|
+
// src/constants.ts
|
|
43
|
+
var TREZOR_WEBUSB_VENDOR_ID = 4617;
|
|
44
|
+
var TREZOR_WEBUSB_FIRMWARE_PRODUCT = 21441;
|
|
45
|
+
var TREZOR_WEBUSB_BOOTLOADER_PRODUCT = 21440;
|
|
46
|
+
var TREZOR_WEBUSB_FILTERS = [
|
|
47
|
+
{ vendorId: TREZOR_WEBUSB_VENDOR_ID, productId: TREZOR_WEBUSB_FIRMWARE_PRODUCT },
|
|
48
|
+
{ vendorId: TREZOR_WEBUSB_VENDOR_ID, productId: TREZOR_WEBUSB_BOOTLOADER_PRODUCT }
|
|
49
|
+
];
|
|
50
|
+
var TREZOR_USB_CONFIGURATION_ID = 1;
|
|
51
|
+
var TREZOR_USB_INTERFACE_ID = 0;
|
|
52
|
+
var TREZOR_USB_ENDPOINT_ID = 1;
|
|
53
|
+
var TREZOR_USB_PACKET_SIZE = 64;
|
|
54
|
+
|
|
55
|
+
// src/TrezorWebUsbTransport.ts
|
|
56
|
+
var import_hwk_adapter_core = require("@onekeyfe/hwk-adapter-core");
|
|
57
|
+
var disconnectError = (message) => Object.assign(new Error(message), { code: import_hwk_adapter_core.HardwareErrorCode.DeviceDisconnected });
|
|
58
|
+
var notConnectedError = (connectId) => disconnectError(`Trezor WebUSB device is not connected: ${connectId}`);
|
|
59
|
+
var resolveConnectId = (device, index) => {
|
|
60
|
+
if (device.serialNumber && device.serialNumber.length > 0) return device.serialNumber;
|
|
61
|
+
return `trezor-webusb-${device.vendorId.toString(16)}-${device.productId.toString(16)}-${index}`;
|
|
62
|
+
};
|
|
63
|
+
var isTrezorDevice = (device) => device.vendorId === TREZOR_WEBUSB_VENDOR_ID && (device.productId === TREZOR_WEBUSB_FIRMWARE_PRODUCT || device.productId === TREZOR_WEBUSB_BOOTLOADER_PRODUCT);
|
|
64
|
+
var TrezorWebUsbTransport = class {
|
|
65
|
+
constructor(options = {}) {
|
|
66
|
+
this._connected = /* @__PURE__ */ new Map();
|
|
67
|
+
this._disconnectHandlers = /* @__PURE__ */ new Map();
|
|
68
|
+
if (!options.usb && typeof navigator === "undefined") {
|
|
69
|
+
throw new Error(
|
|
70
|
+
"TrezorWebUsbTransport: navigator.usb is not available \u2014 pass `usb` explicitly or run in a WebUSB-capable environment"
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
this._usb = options.usb ?? navigator.usb;
|
|
74
|
+
this._logger = options.logger;
|
|
75
|
+
this._globalDisconnectListener = (event) => {
|
|
76
|
+
this._handlePhysicalDisconnect(event.device);
|
|
77
|
+
};
|
|
78
|
+
this._usb.addEventListener?.("disconnect", this._globalDisconnectListener);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Trigger the browser's WebUSB permission picker. Must be called from a
|
|
82
|
+
* user gesture (click handler). Adds the picked device to the
|
|
83
|
+
* authorized list so subsequent scan() calls include it.
|
|
84
|
+
*/
|
|
85
|
+
async requestDevice() {
|
|
86
|
+
const device = await this._usb.requestDevice({ filters: TREZOR_WEBUSB_FILTERS });
|
|
87
|
+
return this._toDescriptor(device, 0);
|
|
88
|
+
}
|
|
89
|
+
/** List previously-authorized Trezor devices (no permission prompt). */
|
|
90
|
+
async scan() {
|
|
91
|
+
const devices = await this._usb.getDevices();
|
|
92
|
+
return devices.filter(isTrezorDevice).map((device, index) => this._toDescriptor(device, index));
|
|
93
|
+
}
|
|
94
|
+
async connect(connectId) {
|
|
95
|
+
const existing = this._connected.get(connectId);
|
|
96
|
+
if (existing) return existing;
|
|
97
|
+
const devices = await this._usb.getDevices();
|
|
98
|
+
const device = devices.find(
|
|
99
|
+
(d, index) => isTrezorDevice(d) && resolveConnectId(d, index) === connectId
|
|
100
|
+
);
|
|
101
|
+
if (!device) {
|
|
102
|
+
throw Object.assign(new Error(`Trezor WebUSB device not found: ${connectId}`), {
|
|
103
|
+
code: import_hwk_adapter_core.HardwareErrorCode.DeviceNotFound
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
if (!device.opened) {
|
|
107
|
+
await device.open();
|
|
108
|
+
}
|
|
109
|
+
if (device.configuration?.configurationValue !== TREZOR_USB_CONFIGURATION_ID) {
|
|
110
|
+
await device.selectConfiguration(TREZOR_USB_CONFIGURATION_ID);
|
|
111
|
+
}
|
|
112
|
+
await device.claimInterface(TREZOR_USB_INTERFACE_ID);
|
|
113
|
+
this._connected.set(connectId, device);
|
|
114
|
+
this._log("info", "webusb.connect.done", {
|
|
115
|
+
connectId,
|
|
116
|
+
productId: device.productId,
|
|
117
|
+
serial: device.serialNumber
|
|
118
|
+
});
|
|
119
|
+
return device;
|
|
120
|
+
}
|
|
121
|
+
async disconnect(connectId) {
|
|
122
|
+
const device = this._connected.get(connectId);
|
|
123
|
+
this._connected.delete(connectId);
|
|
124
|
+
if (!device) return;
|
|
125
|
+
try {
|
|
126
|
+
await device.releaseInterface(TREZOR_USB_INTERFACE_ID);
|
|
127
|
+
} catch (error) {
|
|
128
|
+
this._log("warn", "webusb.disconnect.releaseInterface.error", { connectId, error: String(error) });
|
|
129
|
+
}
|
|
130
|
+
try {
|
|
131
|
+
if (device.opened) await device.close();
|
|
132
|
+
} catch (error) {
|
|
133
|
+
this._log("warn", "webusb.disconnect.close.error", { connectId, error: String(error) });
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
async write(connectId, data) {
|
|
137
|
+
const device = this._ensureConnected(connectId);
|
|
138
|
+
for (let offset = 0; offset < data.length; offset += TREZOR_USB_PACKET_SIZE) {
|
|
139
|
+
const chunk = data.slice(offset, offset + TREZOR_USB_PACKET_SIZE);
|
|
140
|
+
const frame = chunk.length === TREZOR_USB_PACKET_SIZE ? chunk : (() => {
|
|
141
|
+
const padded = new Uint8Array(TREZOR_USB_PACKET_SIZE);
|
|
142
|
+
padded.set(chunk);
|
|
143
|
+
return padded;
|
|
144
|
+
})();
|
|
145
|
+
const result = await device.transferOut(TREZOR_USB_ENDPOINT_ID, frame);
|
|
146
|
+
if (result.status !== "ok") {
|
|
147
|
+
throw new Error(`Trezor WebUSB transferOut failed: ${result.status}`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
async read(connectId) {
|
|
152
|
+
const device = this._ensureConnected(connectId);
|
|
153
|
+
const result = await device.transferIn(TREZOR_USB_ENDPOINT_ID, TREZOR_USB_PACKET_SIZE);
|
|
154
|
+
if (result.status !== "ok") {
|
|
155
|
+
throw new Error(`Trezor WebUSB transferIn failed: ${result.status}`);
|
|
156
|
+
}
|
|
157
|
+
if (!result.data) {
|
|
158
|
+
throw new Error("Trezor WebUSB transferIn returned no data");
|
|
159
|
+
}
|
|
160
|
+
return new Uint8Array(
|
|
161
|
+
result.data.buffer,
|
|
162
|
+
result.data.byteOffset,
|
|
163
|
+
result.data.byteLength
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
onDisconnect(connectId, handler) {
|
|
167
|
+
const handlers = this._disconnectHandlers.get(connectId) ?? /* @__PURE__ */ new Set();
|
|
168
|
+
handlers.add(handler);
|
|
169
|
+
this._disconnectHandlers.set(connectId, handlers);
|
|
170
|
+
return () => {
|
|
171
|
+
handlers.delete(handler);
|
|
172
|
+
if (handlers.size === 0) {
|
|
173
|
+
this._disconnectHandlers.delete(connectId);
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
reset() {
|
|
178
|
+
this._usb.removeEventListener?.("disconnect", this._globalDisconnectListener);
|
|
179
|
+
this._connected.clear();
|
|
180
|
+
this._disconnectHandlers.clear();
|
|
181
|
+
}
|
|
182
|
+
_ensureConnected(connectId) {
|
|
183
|
+
const device = this._connected.get(connectId);
|
|
184
|
+
if (!device) throw notConnectedError(connectId);
|
|
185
|
+
return device;
|
|
186
|
+
}
|
|
187
|
+
_toDescriptor(device, index) {
|
|
188
|
+
const configurations = device.configurations?.map((config) => ({
|
|
189
|
+
configurationValue: config.configurationValue,
|
|
190
|
+
configurationName: config.configurationName,
|
|
191
|
+
interfaceCount: config.interfaces?.length ?? 0
|
|
192
|
+
}));
|
|
193
|
+
return {
|
|
194
|
+
connectId: resolveConnectId(device, index),
|
|
195
|
+
serialNumber: device.serialNumber || void 0,
|
|
196
|
+
vendorId: device.vendorId,
|
|
197
|
+
productId: device.productId,
|
|
198
|
+
productName: device.productName || void 0,
|
|
199
|
+
manufacturerName: device.manufacturerName || void 0,
|
|
200
|
+
isBootloader: device.productId === TREZOR_WEBUSB_BOOTLOADER_PRODUCT,
|
|
201
|
+
usbVersionMajor: device.usbVersionMajor,
|
|
202
|
+
usbVersionMinor: device.usbVersionMinor,
|
|
203
|
+
usbVersionSubminor: device.usbVersionSubminor,
|
|
204
|
+
deviceClass: device.deviceClass,
|
|
205
|
+
deviceSubclass: device.deviceSubclass,
|
|
206
|
+
deviceProtocol: device.deviceProtocol,
|
|
207
|
+
deviceVersionMajor: device.deviceVersionMajor,
|
|
208
|
+
deviceVersionMinor: device.deviceVersionMinor,
|
|
209
|
+
deviceVersionSubminor: device.deviceVersionSubminor,
|
|
210
|
+
opened: device.opened,
|
|
211
|
+
raw: {
|
|
212
|
+
configurations
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
_handlePhysicalDisconnect(device) {
|
|
217
|
+
for (const [connectId, connected] of this._connected) {
|
|
218
|
+
if (connected === device) {
|
|
219
|
+
this._connected.delete(connectId);
|
|
220
|
+
this._log("warn", "webusb.disconnect.event", { connectId });
|
|
221
|
+
this._disconnectHandlers.get(connectId)?.forEach((handler) => {
|
|
222
|
+
try {
|
|
223
|
+
handler();
|
|
224
|
+
} catch (error) {
|
|
225
|
+
this._log("error", "webusb.disconnect.handler.threw", {
|
|
226
|
+
connectId,
|
|
227
|
+
error: String(error)
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
_log(level, event, data) {
|
|
236
|
+
this._logger?.({ level, scope: "trezor-webusb", event, data });
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
async function createTrezorWebUsbTransport(options) {
|
|
240
|
+
return new TrezorWebUsbTransport(options);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// src/TrezorWebUsbConnector.ts
|
|
244
|
+
var productLabel = (descriptor) => {
|
|
245
|
+
if (descriptor.isBootloader) return "Trezor (bootloader)";
|
|
246
|
+
return descriptor.productName ?? "Trezor";
|
|
247
|
+
};
|
|
248
|
+
var TrezorWebUsbConnector = class extends import_hwk_trezor_connector.TrezorConnectorBase {
|
|
249
|
+
constructor(options) {
|
|
250
|
+
super({
|
|
251
|
+
connectionType: "usb",
|
|
252
|
+
chunkSize: TREZOR_USB_PACKET_SIZE,
|
|
253
|
+
thp: options?.thp,
|
|
254
|
+
deviceSessionFactory: options?.deviceSessionFactory
|
|
255
|
+
});
|
|
256
|
+
this._transport = options?.transport;
|
|
257
|
+
this._transportOptions = options?.transportOptions;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Trigger the browser's WebUSB permission picker. Must be called from a
|
|
261
|
+
* user-gesture event handler. Returns the chosen device's descriptor; the
|
|
262
|
+
* connector remembers it so subsequent searchDevices() picks it up.
|
|
263
|
+
*/
|
|
264
|
+
async requestDevice() {
|
|
265
|
+
const transport = this._ensureTransport();
|
|
266
|
+
const descriptor = await transport.requestDevice();
|
|
267
|
+
return descriptorToConnectorDevice(descriptor);
|
|
268
|
+
}
|
|
269
|
+
async enumerateDevices() {
|
|
270
|
+
const transport = this._ensureTransport();
|
|
271
|
+
const descriptors = await transport.scan();
|
|
272
|
+
return descriptors.map(descriptorToConnectorDevice);
|
|
273
|
+
}
|
|
274
|
+
async createByteTransport(device) {
|
|
275
|
+
const transport = this._ensureTransport();
|
|
276
|
+
await transport.connect(device.connectId);
|
|
277
|
+
return {
|
|
278
|
+
write: async (chunk) => {
|
|
279
|
+
await transport.write(device.connectId, Uint8Array.from(chunk));
|
|
280
|
+
},
|
|
281
|
+
read: async () => {
|
|
282
|
+
const data = await transport.read(device.connectId);
|
|
283
|
+
return import_buffer.Buffer.from(data);
|
|
284
|
+
},
|
|
285
|
+
close: () => transport.disconnect(device.connectId),
|
|
286
|
+
onDisconnect: (handler) => transport.onDisconnect(device.connectId, handler)
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
reset() {
|
|
290
|
+
super.reset();
|
|
291
|
+
this._transport?.reset();
|
|
292
|
+
this._transport = void 0;
|
|
293
|
+
}
|
|
294
|
+
_ensureTransport() {
|
|
295
|
+
if (!this._transport) {
|
|
296
|
+
this._transport = new TrezorWebUsbTransport(this._transportOptions);
|
|
297
|
+
}
|
|
298
|
+
return this._transport;
|
|
299
|
+
}
|
|
300
|
+
};
|
|
301
|
+
function descriptorToConnectorDevice(descriptor) {
|
|
302
|
+
return {
|
|
303
|
+
connectId: descriptor.connectId,
|
|
304
|
+
deviceId: descriptor.serialNumber ?? descriptor.connectId,
|
|
305
|
+
name: productLabel(descriptor),
|
|
306
|
+
model: "unknown",
|
|
307
|
+
serialNumber: descriptor.serialNumber,
|
|
308
|
+
capabilities: { persistentDeviceIdentity: !!descriptor.serialNumber },
|
|
309
|
+
raw: {
|
|
310
|
+
transport: "webusb",
|
|
311
|
+
descriptor
|
|
312
|
+
}
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
function createTrezorWebUsbConnector(options) {
|
|
316
|
+
return new TrezorWebUsbConnector(options);
|
|
317
|
+
}
|
|
318
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
319
|
+
0 && (module.exports = {
|
|
320
|
+
TREZOR_USB_CONFIGURATION_ID,
|
|
321
|
+
TREZOR_USB_ENDPOINT_ID,
|
|
322
|
+
TREZOR_USB_INTERFACE_ID,
|
|
323
|
+
TREZOR_USB_PACKET_SIZE,
|
|
324
|
+
TREZOR_WEBUSB_BOOTLOADER_PRODUCT,
|
|
325
|
+
TREZOR_WEBUSB_FILTERS,
|
|
326
|
+
TREZOR_WEBUSB_FIRMWARE_PRODUCT,
|
|
327
|
+
TREZOR_WEBUSB_VENDOR_ID,
|
|
328
|
+
TrezorWebUsbConnector,
|
|
329
|
+
TrezorWebUsbTransport,
|
|
330
|
+
createTrezorWebUsbConnector,
|
|
331
|
+
createTrezorWebUsbTransport
|
|
332
|
+
});
|
|
333
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/TrezorWebUsbConnector.ts","../src/constants.ts","../src/TrezorWebUsbTransport.ts"],"sourcesContent":["export {\n TrezorWebUsbConnector,\n createTrezorWebUsbConnector,\n} from './TrezorWebUsbConnector';\nexport type { TrezorWebUsbConnectorOptions } from './TrezorWebUsbConnector';\n\nexport {\n TrezorWebUsbTransport,\n createTrezorWebUsbTransport,\n} from './TrezorWebUsbTransport';\nexport type {\n TrezorWebUsbDescriptor,\n TrezorWebUsbTransportOptions,\n} from './TrezorWebUsbTransport';\n\nexport {\n TREZOR_USB_CONFIGURATION_ID,\n TREZOR_USB_ENDPOINT_ID,\n TREZOR_USB_INTERFACE_ID,\n TREZOR_USB_PACKET_SIZE,\n TREZOR_WEBUSB_BOOTLOADER_PRODUCT,\n TREZOR_WEBUSB_FILTERS,\n TREZOR_WEBUSB_FIRMWARE_PRODUCT,\n TREZOR_WEBUSB_VENDOR_ID,\n} from './constants';\n","import { Buffer } from 'buffer';\n\nimport {\n TrezorConnectorBase,\n type TrezorConnectorBaseOptions,\n type TrezorConnectorByteTransport,\n} from '@onekeyfe/hwk-trezor-connector';\n\nimport { TREZOR_USB_PACKET_SIZE } from './constants';\nimport {\n TrezorWebUsbTransport,\n type TrezorWebUsbDescriptor,\n type TrezorWebUsbTransportOptions,\n} from './TrezorWebUsbTransport';\n\nimport type { ConnectorDevice } from '@onekeyfe/hwk-adapter-core';\n\nexport interface TrezorWebUsbConnectorOptions {\n /** Pre-built transport (optional). If omitted, one is created lazily on first use. */\n transport?: TrezorWebUsbTransport;\n /** Options forwarded to a lazily-created transport. Ignored if `transport` is supplied. */\n transportOptions?: TrezorWebUsbTransportOptions;\n thp?: TrezorConnectorBaseOptions['thp'];\n deviceSessionFactory?: TrezorConnectorBaseOptions['deviceSessionFactory'];\n}\n\nconst productLabel = (descriptor: TrezorWebUsbDescriptor): string => {\n if (descriptor.isBootloader) return 'Trezor (bootloader)';\n return descriptor.productName ?? 'Trezor';\n};\n\nexport class TrezorWebUsbConnector extends TrezorConnectorBase {\n private _transport: TrezorWebUsbTransport | undefined;\n\n private readonly _transportOptions?: TrezorWebUsbTransportOptions;\n\n constructor(options?: TrezorWebUsbConnectorOptions) {\n super({\n connectionType: 'usb',\n chunkSize: TREZOR_USB_PACKET_SIZE,\n thp: options?.thp,\n deviceSessionFactory: options?.deviceSessionFactory,\n });\n this._transport = options?.transport;\n this._transportOptions = options?.transportOptions;\n }\n\n /**\n * Trigger the browser's WebUSB permission picker. Must be called from a\n * user-gesture event handler. Returns the chosen device's descriptor; the\n * connector remembers it so subsequent searchDevices() picks it up.\n */\n async requestDevice(): Promise<ConnectorDevice> {\n const transport = this._ensureTransport();\n const descriptor = await transport.requestDevice();\n return descriptorToConnectorDevice(descriptor);\n }\n\n protected async enumerateDevices(): Promise<ConnectorDevice[]> {\n const transport = this._ensureTransport();\n const descriptors = await transport.scan();\n return descriptors.map(descriptorToConnectorDevice);\n }\n\n protected async createByteTransport(\n device: ConnectorDevice\n ): Promise<TrezorConnectorByteTransport> {\n const transport = this._ensureTransport();\n await transport.connect(device.connectId);\n\n return {\n write: async (chunk: Buffer) => {\n await transport.write(device.connectId, Uint8Array.from(chunk));\n },\n read: async () => {\n const data = await transport.read(device.connectId);\n return Buffer.from(data);\n },\n close: () => transport.disconnect(device.connectId),\n onDisconnect: (handler: () => void) => transport.onDisconnect(device.connectId, handler),\n };\n }\n\n reset(): void {\n super.reset();\n this._transport?.reset();\n this._transport = undefined;\n }\n\n private _ensureTransport(): TrezorWebUsbTransport {\n if (!this._transport) {\n this._transport = new TrezorWebUsbTransport(this._transportOptions);\n }\n return this._transport;\n }\n}\n\nfunction descriptorToConnectorDevice(descriptor: TrezorWebUsbDescriptor): ConnectorDevice {\n // The full WebUSB descriptor goes into `raw` so the app layer (search-\n // devices UI / DB / debug logs) can see everything the host kernel\n // exposed. Promote any field we consume by name onto the typed surface.\n return {\n connectId: descriptor.connectId,\n deviceId: descriptor.serialNumber ?? descriptor.connectId,\n name: productLabel(descriptor),\n model: 'unknown',\n serialNumber: descriptor.serialNumber,\n capabilities: { persistentDeviceIdentity: !!descriptor.serialNumber },\n raw: {\n transport: 'webusb',\n descriptor,\n },\n };\n}\n\nexport function createTrezorWebUsbConnector(\n options?: TrezorWebUsbConnectorOptions\n): TrezorWebUsbConnector {\n return new TrezorWebUsbConnector(options);\n}\n","/**\n * USB constants for Trezor devices.\n *\n * Matches @trezor/transport src/constants.ts. T1 HID (vendor 0x534c) is NOT\n * WebUSB-accessible — it uses the HID class which navigator.usb can't claim;\n * users with T1 need the bridge daemon. We only expose 0x1209 (WebUSB-class)\n * here.\n */\nexport const TREZOR_WEBUSB_VENDOR_ID = 0x1209;\n\n/** Trezor firmware (Model T / Safe 5 / Safe 3) running normally */\nexport const TREZOR_WEBUSB_FIRMWARE_PRODUCT = 0x53c1;\n\n/** Trezor firmware in bootloader mode (firmware update / wipe) */\nexport const TREZOR_WEBUSB_BOOTLOADER_PRODUCT = 0x53c0;\n\n/** Standard WebUSB filters that show only WebUSB-accessible Trezor devices in the picker. */\nexport const TREZOR_WEBUSB_FILTERS: USBDeviceFilter[] = [\n { vendorId: TREZOR_WEBUSB_VENDOR_ID, productId: TREZOR_WEBUSB_FIRMWARE_PRODUCT },\n { vendorId: TREZOR_WEBUSB_VENDOR_ID, productId: TREZOR_WEBUSB_BOOTLOADER_PRODUCT },\n];\n\n/** Trezor's standard USB layout — configuration 1, interface 0, endpoint 1. */\nexport const TREZOR_USB_CONFIGURATION_ID = 1;\nexport const TREZOR_USB_INTERFACE_ID = 0;\nexport const TREZOR_USB_ENDPOINT_ID = 1;\n\n/** Trezor wire packet size on USB. */\nexport const TREZOR_USB_PACKET_SIZE = 64;\n","import { HardwareErrorCode } from '@onekeyfe/hwk-adapter-core';\n\nimport {\n TREZOR_USB_CONFIGURATION_ID,\n TREZOR_USB_ENDPOINT_ID,\n TREZOR_USB_INTERFACE_ID,\n TREZOR_USB_PACKET_SIZE,\n TREZOR_WEBUSB_BOOTLOADER_PRODUCT,\n TREZOR_WEBUSB_FILTERS,\n TREZOR_WEBUSB_FIRMWARE_PRODUCT,\n TREZOR_WEBUSB_VENDOR_ID,\n} from './constants';\n\n/**\n * Descriptor returned by scan(). Lightweight — the actual USBDevice is held\n * internally until connect() is called.\n */\nexport interface TrezorWebUsbDescriptor {\n /** Stable id used as connectId. Prefers serialNumber; falls back to a synthesized id. */\n connectId: string;\n serialNumber?: string;\n vendorId: number;\n productId: number;\n productName?: string;\n manufacturerName?: string;\n isBootloader: boolean;\n\n /** USB spec version this device implements (Window USBDevice fields). */\n usbVersionMajor?: number;\n usbVersionMinor?: number;\n usbVersionSubminor?: number;\n\n /** Device-class triple from the USB descriptor. */\n deviceClass?: number;\n deviceSubclass?: number;\n deviceProtocol?: number;\n\n /** Firmware-reported device version (DIFFERENT from THP-handshake firmware version). */\n deviceVersionMajor?: number;\n deviceVersionMinor?: number;\n deviceVersionSubminor?: number;\n\n /** Whether the host has previously opened this device handle. */\n opened?: boolean;\n\n /**\n * Catch-all blob for fields we haven't promoted to the typed surface yet.\n * Currently includes:\n * - configurations: minimal summary of USBConfiguration[] (number + alt count)\n * Treat as informational only — anything actually used should be promoted\n * to a typed field above.\n */\n raw?: Record<string, unknown>;\n}\n\nexport interface TrezorWebUsbTransportOptions {\n /** Override navigator.usb (mainly for tests). */\n usb?: USB;\n logger?: (entry: {\n level: 'debug' | 'info' | 'warn' | 'error';\n scope: string;\n event: string;\n data?: Record<string, unknown>;\n }) => void;\n}\n\nconst disconnectError = (message: string): Error =>\n Object.assign(new Error(message), { code: HardwareErrorCode.DeviceDisconnected });\n\nconst notConnectedError = (connectId: string): Error =>\n disconnectError(`Trezor WebUSB device is not connected: ${connectId}`);\n\nconst resolveConnectId = (device: USBDevice, index: number): string => {\n if (device.serialNumber && device.serialNumber.length > 0) return device.serialNumber;\n return `trezor-webusb-${device.vendorId.toString(16)}-${device.productId.toString(16)}-${index}`;\n};\n\nconst isTrezorDevice = (device: USBDevice): boolean =>\n device.vendorId === TREZOR_WEBUSB_VENDOR_ID &&\n (device.productId === TREZOR_WEBUSB_FIRMWARE_PRODUCT ||\n device.productId === TREZOR_WEBUSB_BOOTLOADER_PRODUCT);\n\n/**\n * Thin wrapper around `navigator.usb` providing the same scan/connect/read/\n * write/onDisconnect surface that TrezorRnBleConnector's transport exposes,\n * so TrezorWebUsbConnector can be a one-page subclass of TrezorConnectorBase.\n *\n * NOT responsible for the WebUSB permission prompt — that needs a user\n * gesture, which callers must trigger themselves via `requestDevice()`.\n */\nexport class TrezorWebUsbTransport {\n private readonly _usb: USB;\n\n private readonly _logger?: NonNullable<TrezorWebUsbTransportOptions['logger']>;\n\n private readonly _connected = new Map<string, USBDevice>();\n\n private readonly _disconnectHandlers = new Map<string, Set<() => void>>();\n\n private readonly _globalDisconnectListener: (event: USBConnectionEvent) => void;\n\n constructor(options: TrezorWebUsbTransportOptions = {}) {\n if (!options.usb && typeof navigator === 'undefined') {\n throw new Error(\n 'TrezorWebUsbTransport: navigator.usb is not available — pass `usb` explicitly or run in a WebUSB-capable environment'\n );\n }\n this._usb = options.usb ?? navigator.usb;\n this._logger = options.logger;\n\n this._globalDisconnectListener = (event: USBConnectionEvent) => {\n this._handlePhysicalDisconnect(event.device);\n };\n this._usb.addEventListener?.('disconnect', this._globalDisconnectListener);\n }\n\n /**\n * Trigger the browser's WebUSB permission picker. Must be called from a\n * user gesture (click handler). Adds the picked device to the\n * authorized list so subsequent scan() calls include it.\n */\n async requestDevice(): Promise<TrezorWebUsbDescriptor> {\n const device = await this._usb.requestDevice({ filters: TREZOR_WEBUSB_FILTERS });\n return this._toDescriptor(device, 0);\n }\n\n /** List previously-authorized Trezor devices (no permission prompt). */\n async scan(): Promise<TrezorWebUsbDescriptor[]> {\n const devices = await this._usb.getDevices();\n return devices.filter(isTrezorDevice).map((device, index) => this._toDescriptor(device, index));\n }\n\n async connect(connectId: string): Promise<USBDevice> {\n const existing = this._connected.get(connectId);\n if (existing) return existing;\n\n const devices = await this._usb.getDevices();\n const device = devices.find(\n (d, index) => isTrezorDevice(d) && resolveConnectId(d, index) === connectId\n );\n if (!device) {\n throw Object.assign(new Error(`Trezor WebUSB device not found: ${connectId}`), {\n code: HardwareErrorCode.DeviceNotFound,\n });\n }\n\n if (!device.opened) {\n await device.open();\n }\n if (device.configuration?.configurationValue !== TREZOR_USB_CONFIGURATION_ID) {\n await device.selectConfiguration(TREZOR_USB_CONFIGURATION_ID);\n }\n await device.claimInterface(TREZOR_USB_INTERFACE_ID);\n\n this._connected.set(connectId, device);\n this._log('info', 'webusb.connect.done', {\n connectId,\n productId: device.productId,\n serial: device.serialNumber,\n });\n return device;\n }\n\n async disconnect(connectId: string): Promise<void> {\n const device = this._connected.get(connectId);\n this._connected.delete(connectId);\n if (!device) return;\n try {\n await device.releaseInterface(TREZOR_USB_INTERFACE_ID);\n } catch (error) {\n this._log('warn', 'webusb.disconnect.releaseInterface.error', { connectId, error: String(error) });\n }\n try {\n if (device.opened) await device.close();\n } catch (error) {\n this._log('warn', 'webusb.disconnect.close.error', { connectId, error: String(error) });\n }\n }\n\n async write(connectId: string, data: Uint8Array): Promise<void> {\n const device = this._ensureConnected(connectId);\n for (let offset = 0; offset < data.length; offset += TREZOR_USB_PACKET_SIZE) {\n const chunk = data.slice(offset, offset + TREZOR_USB_PACKET_SIZE);\n // Trezor expects fixed 64-byte frames; pad with zeros if the last chunk is short.\n const frame =\n chunk.length === TREZOR_USB_PACKET_SIZE\n ? chunk\n : (() => {\n const padded = new Uint8Array(TREZOR_USB_PACKET_SIZE);\n padded.set(chunk);\n return padded;\n })();\n const result = await device.transferOut(TREZOR_USB_ENDPOINT_ID, frame);\n if (result.status !== 'ok') {\n throw new Error(`Trezor WebUSB transferOut failed: ${result.status}`);\n }\n }\n }\n\n async read(connectId: string): Promise<Uint8Array> {\n const device = this._ensureConnected(connectId);\n const result = await device.transferIn(TREZOR_USB_ENDPOINT_ID, TREZOR_USB_PACKET_SIZE);\n if (result.status !== 'ok') {\n throw new Error(`Trezor WebUSB transferIn failed: ${result.status}`);\n }\n if (!result.data) {\n throw new Error('Trezor WebUSB transferIn returned no data');\n }\n return new Uint8Array(\n result.data.buffer,\n result.data.byteOffset,\n result.data.byteLength\n );\n }\n\n onDisconnect(connectId: string, handler: () => void): () => void {\n const handlers = this._disconnectHandlers.get(connectId) ?? new Set<() => void>();\n handlers.add(handler);\n this._disconnectHandlers.set(connectId, handlers);\n return () => {\n handlers.delete(handler);\n if (handlers.size === 0) {\n this._disconnectHandlers.delete(connectId);\n }\n };\n }\n\n reset(): void {\n this._usb.removeEventListener?.('disconnect', this._globalDisconnectListener);\n this._connected.clear();\n this._disconnectHandlers.clear();\n }\n\n private _ensureConnected(connectId: string): USBDevice {\n const device = this._connected.get(connectId);\n if (!device) throw notConnectedError(connectId);\n return device;\n }\n\n private _toDescriptor(device: USBDevice, index: number): TrezorWebUsbDescriptor {\n // Summarize USBConfiguration[] without dragging in DataView refs etc.\n // The full live USBDevice is held internally — this is only the\n // serializable shadow the connector / UI sees.\n const configurations = device.configurations?.map(config => ({\n configurationValue: config.configurationValue,\n configurationName: config.configurationName,\n interfaceCount: config.interfaces?.length ?? 0,\n }));\n return {\n connectId: resolveConnectId(device, index),\n serialNumber: device.serialNumber || undefined,\n vendorId: device.vendorId,\n productId: device.productId,\n productName: device.productName || undefined,\n manufacturerName: device.manufacturerName || undefined,\n isBootloader: device.productId === TREZOR_WEBUSB_BOOTLOADER_PRODUCT,\n usbVersionMajor: device.usbVersionMajor,\n usbVersionMinor: device.usbVersionMinor,\n usbVersionSubminor: device.usbVersionSubminor,\n deviceClass: device.deviceClass,\n deviceSubclass: device.deviceSubclass,\n deviceProtocol: device.deviceProtocol,\n deviceVersionMajor: device.deviceVersionMajor,\n deviceVersionMinor: device.deviceVersionMinor,\n deviceVersionSubminor: device.deviceVersionSubminor,\n opened: device.opened,\n raw: {\n configurations,\n },\n };\n }\n\n private _handlePhysicalDisconnect(device: USBDevice): void {\n // Find which connectId this corresponds to.\n for (const [connectId, connected] of this._connected) {\n if (connected === device) {\n this._connected.delete(connectId);\n this._log('warn', 'webusb.disconnect.event', { connectId });\n this._disconnectHandlers.get(connectId)?.forEach(handler => {\n try {\n handler();\n } catch (error) {\n this._log('error', 'webusb.disconnect.handler.threw', {\n connectId,\n error: String(error),\n });\n }\n });\n return;\n }\n }\n }\n\n private _log(\n level: 'debug' | 'info' | 'warn' | 'error',\n event: string,\n data?: Record<string, unknown>\n ): void {\n this._logger?.({ level, scope: 'trezor-webusb', event, data });\n }\n}\n\nexport async function createTrezorWebUsbTransport(\n options?: TrezorWebUsbTransportOptions\n): Promise<TrezorWebUsbTransport> {\n return new TrezorWebUsbTransport(options);\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
// src/TrezorWebUsbConnector.ts
|
|
2
|
+
import { Buffer } from "buffer";
|
|
3
|
+
import {
|
|
4
|
+
TrezorConnectorBase
|
|
5
|
+
} from "@onekeyfe/hwk-trezor-connector";
|
|
6
|
+
|
|
7
|
+
// src/constants.ts
|
|
8
|
+
var TREZOR_WEBUSB_VENDOR_ID = 4617;
|
|
9
|
+
var TREZOR_WEBUSB_FIRMWARE_PRODUCT = 21441;
|
|
10
|
+
var TREZOR_WEBUSB_BOOTLOADER_PRODUCT = 21440;
|
|
11
|
+
var TREZOR_WEBUSB_FILTERS = [
|
|
12
|
+
{ vendorId: TREZOR_WEBUSB_VENDOR_ID, productId: TREZOR_WEBUSB_FIRMWARE_PRODUCT },
|
|
13
|
+
{ vendorId: TREZOR_WEBUSB_VENDOR_ID, productId: TREZOR_WEBUSB_BOOTLOADER_PRODUCT }
|
|
14
|
+
];
|
|
15
|
+
var TREZOR_USB_CONFIGURATION_ID = 1;
|
|
16
|
+
var TREZOR_USB_INTERFACE_ID = 0;
|
|
17
|
+
var TREZOR_USB_ENDPOINT_ID = 1;
|
|
18
|
+
var TREZOR_USB_PACKET_SIZE = 64;
|
|
19
|
+
|
|
20
|
+
// src/TrezorWebUsbTransport.ts
|
|
21
|
+
import { HardwareErrorCode } from "@onekeyfe/hwk-adapter-core";
|
|
22
|
+
var disconnectError = (message) => Object.assign(new Error(message), { code: HardwareErrorCode.DeviceDisconnected });
|
|
23
|
+
var notConnectedError = (connectId) => disconnectError(`Trezor WebUSB device is not connected: ${connectId}`);
|
|
24
|
+
var resolveConnectId = (device, index) => {
|
|
25
|
+
if (device.serialNumber && device.serialNumber.length > 0) return device.serialNumber;
|
|
26
|
+
return `trezor-webusb-${device.vendorId.toString(16)}-${device.productId.toString(16)}-${index}`;
|
|
27
|
+
};
|
|
28
|
+
var isTrezorDevice = (device) => device.vendorId === TREZOR_WEBUSB_VENDOR_ID && (device.productId === TREZOR_WEBUSB_FIRMWARE_PRODUCT || device.productId === TREZOR_WEBUSB_BOOTLOADER_PRODUCT);
|
|
29
|
+
var TrezorWebUsbTransport = class {
|
|
30
|
+
constructor(options = {}) {
|
|
31
|
+
this._connected = /* @__PURE__ */ new Map();
|
|
32
|
+
this._disconnectHandlers = /* @__PURE__ */ new Map();
|
|
33
|
+
if (!options.usb && typeof navigator === "undefined") {
|
|
34
|
+
throw new Error(
|
|
35
|
+
"TrezorWebUsbTransport: navigator.usb is not available \u2014 pass `usb` explicitly or run in a WebUSB-capable environment"
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
this._usb = options.usb ?? navigator.usb;
|
|
39
|
+
this._logger = options.logger;
|
|
40
|
+
this._globalDisconnectListener = (event) => {
|
|
41
|
+
this._handlePhysicalDisconnect(event.device);
|
|
42
|
+
};
|
|
43
|
+
this._usb.addEventListener?.("disconnect", this._globalDisconnectListener);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Trigger the browser's WebUSB permission picker. Must be called from a
|
|
47
|
+
* user gesture (click handler). Adds the picked device to the
|
|
48
|
+
* authorized list so subsequent scan() calls include it.
|
|
49
|
+
*/
|
|
50
|
+
async requestDevice() {
|
|
51
|
+
const device = await this._usb.requestDevice({ filters: TREZOR_WEBUSB_FILTERS });
|
|
52
|
+
return this._toDescriptor(device, 0);
|
|
53
|
+
}
|
|
54
|
+
/** List previously-authorized Trezor devices (no permission prompt). */
|
|
55
|
+
async scan() {
|
|
56
|
+
const devices = await this._usb.getDevices();
|
|
57
|
+
return devices.filter(isTrezorDevice).map((device, index) => this._toDescriptor(device, index));
|
|
58
|
+
}
|
|
59
|
+
async connect(connectId) {
|
|
60
|
+
const existing = this._connected.get(connectId);
|
|
61
|
+
if (existing) return existing;
|
|
62
|
+
const devices = await this._usb.getDevices();
|
|
63
|
+
const device = devices.find(
|
|
64
|
+
(d, index) => isTrezorDevice(d) && resolveConnectId(d, index) === connectId
|
|
65
|
+
);
|
|
66
|
+
if (!device) {
|
|
67
|
+
throw Object.assign(new Error(`Trezor WebUSB device not found: ${connectId}`), {
|
|
68
|
+
code: HardwareErrorCode.DeviceNotFound
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
if (!device.opened) {
|
|
72
|
+
await device.open();
|
|
73
|
+
}
|
|
74
|
+
if (device.configuration?.configurationValue !== TREZOR_USB_CONFIGURATION_ID) {
|
|
75
|
+
await device.selectConfiguration(TREZOR_USB_CONFIGURATION_ID);
|
|
76
|
+
}
|
|
77
|
+
await device.claimInterface(TREZOR_USB_INTERFACE_ID);
|
|
78
|
+
this._connected.set(connectId, device);
|
|
79
|
+
this._log("info", "webusb.connect.done", {
|
|
80
|
+
connectId,
|
|
81
|
+
productId: device.productId,
|
|
82
|
+
serial: device.serialNumber
|
|
83
|
+
});
|
|
84
|
+
return device;
|
|
85
|
+
}
|
|
86
|
+
async disconnect(connectId) {
|
|
87
|
+
const device = this._connected.get(connectId);
|
|
88
|
+
this._connected.delete(connectId);
|
|
89
|
+
if (!device) return;
|
|
90
|
+
try {
|
|
91
|
+
await device.releaseInterface(TREZOR_USB_INTERFACE_ID);
|
|
92
|
+
} catch (error) {
|
|
93
|
+
this._log("warn", "webusb.disconnect.releaseInterface.error", { connectId, error: String(error) });
|
|
94
|
+
}
|
|
95
|
+
try {
|
|
96
|
+
if (device.opened) await device.close();
|
|
97
|
+
} catch (error) {
|
|
98
|
+
this._log("warn", "webusb.disconnect.close.error", { connectId, error: String(error) });
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
async write(connectId, data) {
|
|
102
|
+
const device = this._ensureConnected(connectId);
|
|
103
|
+
for (let offset = 0; offset < data.length; offset += TREZOR_USB_PACKET_SIZE) {
|
|
104
|
+
const chunk = data.slice(offset, offset + TREZOR_USB_PACKET_SIZE);
|
|
105
|
+
const frame = chunk.length === TREZOR_USB_PACKET_SIZE ? chunk : (() => {
|
|
106
|
+
const padded = new Uint8Array(TREZOR_USB_PACKET_SIZE);
|
|
107
|
+
padded.set(chunk);
|
|
108
|
+
return padded;
|
|
109
|
+
})();
|
|
110
|
+
const result = await device.transferOut(TREZOR_USB_ENDPOINT_ID, frame);
|
|
111
|
+
if (result.status !== "ok") {
|
|
112
|
+
throw new Error(`Trezor WebUSB transferOut failed: ${result.status}`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
async read(connectId) {
|
|
117
|
+
const device = this._ensureConnected(connectId);
|
|
118
|
+
const result = await device.transferIn(TREZOR_USB_ENDPOINT_ID, TREZOR_USB_PACKET_SIZE);
|
|
119
|
+
if (result.status !== "ok") {
|
|
120
|
+
throw new Error(`Trezor WebUSB transferIn failed: ${result.status}`);
|
|
121
|
+
}
|
|
122
|
+
if (!result.data) {
|
|
123
|
+
throw new Error("Trezor WebUSB transferIn returned no data");
|
|
124
|
+
}
|
|
125
|
+
return new Uint8Array(
|
|
126
|
+
result.data.buffer,
|
|
127
|
+
result.data.byteOffset,
|
|
128
|
+
result.data.byteLength
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
onDisconnect(connectId, handler) {
|
|
132
|
+
const handlers = this._disconnectHandlers.get(connectId) ?? /* @__PURE__ */ new Set();
|
|
133
|
+
handlers.add(handler);
|
|
134
|
+
this._disconnectHandlers.set(connectId, handlers);
|
|
135
|
+
return () => {
|
|
136
|
+
handlers.delete(handler);
|
|
137
|
+
if (handlers.size === 0) {
|
|
138
|
+
this._disconnectHandlers.delete(connectId);
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
reset() {
|
|
143
|
+
this._usb.removeEventListener?.("disconnect", this._globalDisconnectListener);
|
|
144
|
+
this._connected.clear();
|
|
145
|
+
this._disconnectHandlers.clear();
|
|
146
|
+
}
|
|
147
|
+
_ensureConnected(connectId) {
|
|
148
|
+
const device = this._connected.get(connectId);
|
|
149
|
+
if (!device) throw notConnectedError(connectId);
|
|
150
|
+
return device;
|
|
151
|
+
}
|
|
152
|
+
_toDescriptor(device, index) {
|
|
153
|
+
const configurations = device.configurations?.map((config) => ({
|
|
154
|
+
configurationValue: config.configurationValue,
|
|
155
|
+
configurationName: config.configurationName,
|
|
156
|
+
interfaceCount: config.interfaces?.length ?? 0
|
|
157
|
+
}));
|
|
158
|
+
return {
|
|
159
|
+
connectId: resolveConnectId(device, index),
|
|
160
|
+
serialNumber: device.serialNumber || void 0,
|
|
161
|
+
vendorId: device.vendorId,
|
|
162
|
+
productId: device.productId,
|
|
163
|
+
productName: device.productName || void 0,
|
|
164
|
+
manufacturerName: device.manufacturerName || void 0,
|
|
165
|
+
isBootloader: device.productId === TREZOR_WEBUSB_BOOTLOADER_PRODUCT,
|
|
166
|
+
usbVersionMajor: device.usbVersionMajor,
|
|
167
|
+
usbVersionMinor: device.usbVersionMinor,
|
|
168
|
+
usbVersionSubminor: device.usbVersionSubminor,
|
|
169
|
+
deviceClass: device.deviceClass,
|
|
170
|
+
deviceSubclass: device.deviceSubclass,
|
|
171
|
+
deviceProtocol: device.deviceProtocol,
|
|
172
|
+
deviceVersionMajor: device.deviceVersionMajor,
|
|
173
|
+
deviceVersionMinor: device.deviceVersionMinor,
|
|
174
|
+
deviceVersionSubminor: device.deviceVersionSubminor,
|
|
175
|
+
opened: device.opened,
|
|
176
|
+
raw: {
|
|
177
|
+
configurations
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
_handlePhysicalDisconnect(device) {
|
|
182
|
+
for (const [connectId, connected] of this._connected) {
|
|
183
|
+
if (connected === device) {
|
|
184
|
+
this._connected.delete(connectId);
|
|
185
|
+
this._log("warn", "webusb.disconnect.event", { connectId });
|
|
186
|
+
this._disconnectHandlers.get(connectId)?.forEach((handler) => {
|
|
187
|
+
try {
|
|
188
|
+
handler();
|
|
189
|
+
} catch (error) {
|
|
190
|
+
this._log("error", "webusb.disconnect.handler.threw", {
|
|
191
|
+
connectId,
|
|
192
|
+
error: String(error)
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
_log(level, event, data) {
|
|
201
|
+
this._logger?.({ level, scope: "trezor-webusb", event, data });
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
async function createTrezorWebUsbTransport(options) {
|
|
205
|
+
return new TrezorWebUsbTransport(options);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// src/TrezorWebUsbConnector.ts
|
|
209
|
+
var productLabel = (descriptor) => {
|
|
210
|
+
if (descriptor.isBootloader) return "Trezor (bootloader)";
|
|
211
|
+
return descriptor.productName ?? "Trezor";
|
|
212
|
+
};
|
|
213
|
+
var TrezorWebUsbConnector = class extends TrezorConnectorBase {
|
|
214
|
+
constructor(options) {
|
|
215
|
+
super({
|
|
216
|
+
connectionType: "usb",
|
|
217
|
+
chunkSize: TREZOR_USB_PACKET_SIZE,
|
|
218
|
+
thp: options?.thp,
|
|
219
|
+
deviceSessionFactory: options?.deviceSessionFactory
|
|
220
|
+
});
|
|
221
|
+
this._transport = options?.transport;
|
|
222
|
+
this._transportOptions = options?.transportOptions;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Trigger the browser's WebUSB permission picker. Must be called from a
|
|
226
|
+
* user-gesture event handler. Returns the chosen device's descriptor; the
|
|
227
|
+
* connector remembers it so subsequent searchDevices() picks it up.
|
|
228
|
+
*/
|
|
229
|
+
async requestDevice() {
|
|
230
|
+
const transport = this._ensureTransport();
|
|
231
|
+
const descriptor = await transport.requestDevice();
|
|
232
|
+
return descriptorToConnectorDevice(descriptor);
|
|
233
|
+
}
|
|
234
|
+
async enumerateDevices() {
|
|
235
|
+
const transport = this._ensureTransport();
|
|
236
|
+
const descriptors = await transport.scan();
|
|
237
|
+
return descriptors.map(descriptorToConnectorDevice);
|
|
238
|
+
}
|
|
239
|
+
async createByteTransport(device) {
|
|
240
|
+
const transport = this._ensureTransport();
|
|
241
|
+
await transport.connect(device.connectId);
|
|
242
|
+
return {
|
|
243
|
+
write: async (chunk) => {
|
|
244
|
+
await transport.write(device.connectId, Uint8Array.from(chunk));
|
|
245
|
+
},
|
|
246
|
+
read: async () => {
|
|
247
|
+
const data = await transport.read(device.connectId);
|
|
248
|
+
return Buffer.from(data);
|
|
249
|
+
},
|
|
250
|
+
close: () => transport.disconnect(device.connectId),
|
|
251
|
+
onDisconnect: (handler) => transport.onDisconnect(device.connectId, handler)
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
reset() {
|
|
255
|
+
super.reset();
|
|
256
|
+
this._transport?.reset();
|
|
257
|
+
this._transport = void 0;
|
|
258
|
+
}
|
|
259
|
+
_ensureTransport() {
|
|
260
|
+
if (!this._transport) {
|
|
261
|
+
this._transport = new TrezorWebUsbTransport(this._transportOptions);
|
|
262
|
+
}
|
|
263
|
+
return this._transport;
|
|
264
|
+
}
|
|
265
|
+
};
|
|
266
|
+
function descriptorToConnectorDevice(descriptor) {
|
|
267
|
+
return {
|
|
268
|
+
connectId: descriptor.connectId,
|
|
269
|
+
deviceId: descriptor.serialNumber ?? descriptor.connectId,
|
|
270
|
+
name: productLabel(descriptor),
|
|
271
|
+
model: "unknown",
|
|
272
|
+
serialNumber: descriptor.serialNumber,
|
|
273
|
+
capabilities: { persistentDeviceIdentity: !!descriptor.serialNumber },
|
|
274
|
+
raw: {
|
|
275
|
+
transport: "webusb",
|
|
276
|
+
descriptor
|
|
277
|
+
}
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
function createTrezorWebUsbConnector(options) {
|
|
281
|
+
return new TrezorWebUsbConnector(options);
|
|
282
|
+
}
|
|
283
|
+
export {
|
|
284
|
+
TREZOR_USB_CONFIGURATION_ID,
|
|
285
|
+
TREZOR_USB_ENDPOINT_ID,
|
|
286
|
+
TREZOR_USB_INTERFACE_ID,
|
|
287
|
+
TREZOR_USB_PACKET_SIZE,
|
|
288
|
+
TREZOR_WEBUSB_BOOTLOADER_PRODUCT,
|
|
289
|
+
TREZOR_WEBUSB_FILTERS,
|
|
290
|
+
TREZOR_WEBUSB_FIRMWARE_PRODUCT,
|
|
291
|
+
TREZOR_WEBUSB_VENDOR_ID,
|
|
292
|
+
TrezorWebUsbConnector,
|
|
293
|
+
TrezorWebUsbTransport,
|
|
294
|
+
createTrezorWebUsbConnector,
|
|
295
|
+
createTrezorWebUsbTransport
|
|
296
|
+
};
|
|
297
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/TrezorWebUsbConnector.ts","../src/constants.ts","../src/TrezorWebUsbTransport.ts"],"sourcesContent":["import { Buffer } from 'buffer';\n\nimport {\n TrezorConnectorBase,\n type TrezorConnectorBaseOptions,\n type TrezorConnectorByteTransport,\n} from '@onekeyfe/hwk-trezor-connector';\n\nimport { TREZOR_USB_PACKET_SIZE } from './constants';\nimport {\n TrezorWebUsbTransport,\n type TrezorWebUsbDescriptor,\n type TrezorWebUsbTransportOptions,\n} from './TrezorWebUsbTransport';\n\nimport type { ConnectorDevice } from '@onekeyfe/hwk-adapter-core';\n\nexport interface TrezorWebUsbConnectorOptions {\n /** Pre-built transport (optional). If omitted, one is created lazily on first use. */\n transport?: TrezorWebUsbTransport;\n /** Options forwarded to a lazily-created transport. Ignored if `transport` is supplied. */\n transportOptions?: TrezorWebUsbTransportOptions;\n thp?: TrezorConnectorBaseOptions['thp'];\n deviceSessionFactory?: TrezorConnectorBaseOptions['deviceSessionFactory'];\n}\n\nconst productLabel = (descriptor: TrezorWebUsbDescriptor): string => {\n if (descriptor.isBootloader) return 'Trezor (bootloader)';\n return descriptor.productName ?? 'Trezor';\n};\n\nexport class TrezorWebUsbConnector extends TrezorConnectorBase {\n private _transport: TrezorWebUsbTransport | undefined;\n\n private readonly _transportOptions?: TrezorWebUsbTransportOptions;\n\n constructor(options?: TrezorWebUsbConnectorOptions) {\n super({\n connectionType: 'usb',\n chunkSize: TREZOR_USB_PACKET_SIZE,\n thp: options?.thp,\n deviceSessionFactory: options?.deviceSessionFactory,\n });\n this._transport = options?.transport;\n this._transportOptions = options?.transportOptions;\n }\n\n /**\n * Trigger the browser's WebUSB permission picker. Must be called from a\n * user-gesture event handler. Returns the chosen device's descriptor; the\n * connector remembers it so subsequent searchDevices() picks it up.\n */\n async requestDevice(): Promise<ConnectorDevice> {\n const transport = this._ensureTransport();\n const descriptor = await transport.requestDevice();\n return descriptorToConnectorDevice(descriptor);\n }\n\n protected async enumerateDevices(): Promise<ConnectorDevice[]> {\n const transport = this._ensureTransport();\n const descriptors = await transport.scan();\n return descriptors.map(descriptorToConnectorDevice);\n }\n\n protected async createByteTransport(\n device: ConnectorDevice\n ): Promise<TrezorConnectorByteTransport> {\n const transport = this._ensureTransport();\n await transport.connect(device.connectId);\n\n return {\n write: async (chunk: Buffer) => {\n await transport.write(device.connectId, Uint8Array.from(chunk));\n },\n read: async () => {\n const data = await transport.read(device.connectId);\n return Buffer.from(data);\n },\n close: () => transport.disconnect(device.connectId),\n onDisconnect: (handler: () => void) => transport.onDisconnect(device.connectId, handler),\n };\n }\n\n reset(): void {\n super.reset();\n this._transport?.reset();\n this._transport = undefined;\n }\n\n private _ensureTransport(): TrezorWebUsbTransport {\n if (!this._transport) {\n this._transport = new TrezorWebUsbTransport(this._transportOptions);\n }\n return this._transport;\n }\n}\n\nfunction descriptorToConnectorDevice(descriptor: TrezorWebUsbDescriptor): ConnectorDevice {\n // The full WebUSB descriptor goes into `raw` so the app layer (search-\n // devices UI / DB / debug logs) can see everything the host kernel\n // exposed. Promote any field we consume by name onto the typed surface.\n return {\n connectId: descriptor.connectId,\n deviceId: descriptor.serialNumber ?? descriptor.connectId,\n name: productLabel(descriptor),\n model: 'unknown',\n serialNumber: descriptor.serialNumber,\n capabilities: { persistentDeviceIdentity: !!descriptor.serialNumber },\n raw: {\n transport: 'webusb',\n descriptor,\n },\n };\n}\n\nexport function createTrezorWebUsbConnector(\n options?: TrezorWebUsbConnectorOptions\n): TrezorWebUsbConnector {\n return new TrezorWebUsbConnector(options);\n}\n","/**\n * USB constants for Trezor devices.\n *\n * Matches @trezor/transport src/constants.ts. T1 HID (vendor 0x534c) is NOT\n * WebUSB-accessible — it uses the HID class which navigator.usb can't claim;\n * users with T1 need the bridge daemon. We only expose 0x1209 (WebUSB-class)\n * here.\n */\nexport const TREZOR_WEBUSB_VENDOR_ID = 0x1209;\n\n/** Trezor firmware (Model T / Safe 5 / Safe 3) running normally */\nexport const TREZOR_WEBUSB_FIRMWARE_PRODUCT = 0x53c1;\n\n/** Trezor firmware in bootloader mode (firmware update / wipe) */\nexport const TREZOR_WEBUSB_BOOTLOADER_PRODUCT = 0x53c0;\n\n/** Standard WebUSB filters that show only WebUSB-accessible Trezor devices in the picker. */\nexport const TREZOR_WEBUSB_FILTERS: USBDeviceFilter[] = [\n { vendorId: TREZOR_WEBUSB_VENDOR_ID, productId: TREZOR_WEBUSB_FIRMWARE_PRODUCT },\n { vendorId: TREZOR_WEBUSB_VENDOR_ID, productId: TREZOR_WEBUSB_BOOTLOADER_PRODUCT },\n];\n\n/** Trezor's standard USB layout — configuration 1, interface 0, endpoint 1. */\nexport const TREZOR_USB_CONFIGURATION_ID = 1;\nexport const TREZOR_USB_INTERFACE_ID = 0;\nexport const TREZOR_USB_ENDPOINT_ID = 1;\n\n/** Trezor wire packet size on USB. */\nexport const TREZOR_USB_PACKET_SIZE = 64;\n","import { HardwareErrorCode } from '@onekeyfe/hwk-adapter-core';\n\nimport {\n TREZOR_USB_CONFIGURATION_ID,\n TREZOR_USB_ENDPOINT_ID,\n TREZOR_USB_INTERFACE_ID,\n TREZOR_USB_PACKET_SIZE,\n TREZOR_WEBUSB_BOOTLOADER_PRODUCT,\n TREZOR_WEBUSB_FILTERS,\n TREZOR_WEBUSB_FIRMWARE_PRODUCT,\n TREZOR_WEBUSB_VENDOR_ID,\n} from './constants';\n\n/**\n * Descriptor returned by scan(). Lightweight — the actual USBDevice is held\n * internally until connect() is called.\n */\nexport interface TrezorWebUsbDescriptor {\n /** Stable id used as connectId. Prefers serialNumber; falls back to a synthesized id. */\n connectId: string;\n serialNumber?: string;\n vendorId: number;\n productId: number;\n productName?: string;\n manufacturerName?: string;\n isBootloader: boolean;\n\n /** USB spec version this device implements (Window USBDevice fields). */\n usbVersionMajor?: number;\n usbVersionMinor?: number;\n usbVersionSubminor?: number;\n\n /** Device-class triple from the USB descriptor. */\n deviceClass?: number;\n deviceSubclass?: number;\n deviceProtocol?: number;\n\n /** Firmware-reported device version (DIFFERENT from THP-handshake firmware version). */\n deviceVersionMajor?: number;\n deviceVersionMinor?: number;\n deviceVersionSubminor?: number;\n\n /** Whether the host has previously opened this device handle. */\n opened?: boolean;\n\n /**\n * Catch-all blob for fields we haven't promoted to the typed surface yet.\n * Currently includes:\n * - configurations: minimal summary of USBConfiguration[] (number + alt count)\n * Treat as informational only — anything actually used should be promoted\n * to a typed field above.\n */\n raw?: Record<string, unknown>;\n}\n\nexport interface TrezorWebUsbTransportOptions {\n /** Override navigator.usb (mainly for tests). */\n usb?: USB;\n logger?: (entry: {\n level: 'debug' | 'info' | 'warn' | 'error';\n scope: string;\n event: string;\n data?: Record<string, unknown>;\n }) => void;\n}\n\nconst disconnectError = (message: string): Error =>\n Object.assign(new Error(message), { code: HardwareErrorCode.DeviceDisconnected });\n\nconst notConnectedError = (connectId: string): Error =>\n disconnectError(`Trezor WebUSB device is not connected: ${connectId}`);\n\nconst resolveConnectId = (device: USBDevice, index: number): string => {\n if (device.serialNumber && device.serialNumber.length > 0) return device.serialNumber;\n return `trezor-webusb-${device.vendorId.toString(16)}-${device.productId.toString(16)}-${index}`;\n};\n\nconst isTrezorDevice = (device: USBDevice): boolean =>\n device.vendorId === TREZOR_WEBUSB_VENDOR_ID &&\n (device.productId === TREZOR_WEBUSB_FIRMWARE_PRODUCT ||\n device.productId === TREZOR_WEBUSB_BOOTLOADER_PRODUCT);\n\n/**\n * Thin wrapper around `navigator.usb` providing the same scan/connect/read/\n * write/onDisconnect surface that TrezorRnBleConnector's transport exposes,\n * so TrezorWebUsbConnector can be a one-page subclass of TrezorConnectorBase.\n *\n * NOT responsible for the WebUSB permission prompt — that needs a user\n * gesture, which callers must trigger themselves via `requestDevice()`.\n */\nexport class TrezorWebUsbTransport {\n private readonly _usb: USB;\n\n private readonly _logger?: NonNullable<TrezorWebUsbTransportOptions['logger']>;\n\n private readonly _connected = new Map<string, USBDevice>();\n\n private readonly _disconnectHandlers = new Map<string, Set<() => void>>();\n\n private readonly _globalDisconnectListener: (event: USBConnectionEvent) => void;\n\n constructor(options: TrezorWebUsbTransportOptions = {}) {\n if (!options.usb && typeof navigator === 'undefined') {\n throw new Error(\n 'TrezorWebUsbTransport: navigator.usb is not available — pass `usb` explicitly or run in a WebUSB-capable environment'\n );\n }\n this._usb = options.usb ?? navigator.usb;\n this._logger = options.logger;\n\n this._globalDisconnectListener = (event: USBConnectionEvent) => {\n this._handlePhysicalDisconnect(event.device);\n };\n this._usb.addEventListener?.('disconnect', this._globalDisconnectListener);\n }\n\n /**\n * Trigger the browser's WebUSB permission picker. Must be called from a\n * user gesture (click handler). Adds the picked device to the\n * authorized list so subsequent scan() calls include it.\n */\n async requestDevice(): Promise<TrezorWebUsbDescriptor> {\n const device = await this._usb.requestDevice({ filters: TREZOR_WEBUSB_FILTERS });\n return this._toDescriptor(device, 0);\n }\n\n /** List previously-authorized Trezor devices (no permission prompt). */\n async scan(): Promise<TrezorWebUsbDescriptor[]> {\n const devices = await this._usb.getDevices();\n return devices.filter(isTrezorDevice).map((device, index) => this._toDescriptor(device, index));\n }\n\n async connect(connectId: string): Promise<USBDevice> {\n const existing = this._connected.get(connectId);\n if (existing) return existing;\n\n const devices = await this._usb.getDevices();\n const device = devices.find(\n (d, index) => isTrezorDevice(d) && resolveConnectId(d, index) === connectId\n );\n if (!device) {\n throw Object.assign(new Error(`Trezor WebUSB device not found: ${connectId}`), {\n code: HardwareErrorCode.DeviceNotFound,\n });\n }\n\n if (!device.opened) {\n await device.open();\n }\n if (device.configuration?.configurationValue !== TREZOR_USB_CONFIGURATION_ID) {\n await device.selectConfiguration(TREZOR_USB_CONFIGURATION_ID);\n }\n await device.claimInterface(TREZOR_USB_INTERFACE_ID);\n\n this._connected.set(connectId, device);\n this._log('info', 'webusb.connect.done', {\n connectId,\n productId: device.productId,\n serial: device.serialNumber,\n });\n return device;\n }\n\n async disconnect(connectId: string): Promise<void> {\n const device = this._connected.get(connectId);\n this._connected.delete(connectId);\n if (!device) return;\n try {\n await device.releaseInterface(TREZOR_USB_INTERFACE_ID);\n } catch (error) {\n this._log('warn', 'webusb.disconnect.releaseInterface.error', { connectId, error: String(error) });\n }\n try {\n if (device.opened) await device.close();\n } catch (error) {\n this._log('warn', 'webusb.disconnect.close.error', { connectId, error: String(error) });\n }\n }\n\n async write(connectId: string, data: Uint8Array): Promise<void> {\n const device = this._ensureConnected(connectId);\n for (let offset = 0; offset < data.length; offset += TREZOR_USB_PACKET_SIZE) {\n const chunk = data.slice(offset, offset + TREZOR_USB_PACKET_SIZE);\n // Trezor expects fixed 64-byte frames; pad with zeros if the last chunk is short.\n const frame =\n chunk.length === TREZOR_USB_PACKET_SIZE\n ? chunk\n : (() => {\n const padded = new Uint8Array(TREZOR_USB_PACKET_SIZE);\n padded.set(chunk);\n return padded;\n })();\n const result = await device.transferOut(TREZOR_USB_ENDPOINT_ID, frame);\n if (result.status !== 'ok') {\n throw new Error(`Trezor WebUSB transferOut failed: ${result.status}`);\n }\n }\n }\n\n async read(connectId: string): Promise<Uint8Array> {\n const device = this._ensureConnected(connectId);\n const result = await device.transferIn(TREZOR_USB_ENDPOINT_ID, TREZOR_USB_PACKET_SIZE);\n if (result.status !== 'ok') {\n throw new Error(`Trezor WebUSB transferIn failed: ${result.status}`);\n }\n if (!result.data) {\n throw new Error('Trezor WebUSB transferIn returned no data');\n }\n return new Uint8Array(\n result.data.buffer,\n result.data.byteOffset,\n result.data.byteLength\n );\n }\n\n onDisconnect(connectId: string, handler: () => void): () => void {\n const handlers = this._disconnectHandlers.get(connectId) ?? new Set<() => void>();\n handlers.add(handler);\n this._disconnectHandlers.set(connectId, handlers);\n return () => {\n handlers.delete(handler);\n if (handlers.size === 0) {\n this._disconnectHandlers.delete(connectId);\n }\n };\n }\n\n reset(): void {\n this._usb.removeEventListener?.('disconnect', this._globalDisconnectListener);\n this._connected.clear();\n this._disconnectHandlers.clear();\n }\n\n private _ensureConnected(connectId: string): USBDevice {\n const device = this._connected.get(connectId);\n if (!device) throw notConnectedError(connectId);\n return device;\n }\n\n private _toDescriptor(device: USBDevice, index: number): TrezorWebUsbDescriptor {\n // Summarize USBConfiguration[] without dragging in DataView refs etc.\n // The full live USBDevice is held internally — this is only the\n // serializable shadow the connector / UI sees.\n const configurations = device.configurations?.map(config => ({\n configurationValue: config.configurationValue,\n configurationName: config.configurationName,\n interfaceCount: config.interfaces?.length ?? 0,\n }));\n return {\n connectId: resolveConnectId(device, index),\n serialNumber: device.serialNumber || undefined,\n vendorId: device.vendorId,\n productId: device.productId,\n productName: device.productName || undefined,\n manufacturerName: device.manufacturerName || undefined,\n isBootloader: device.productId === TREZOR_WEBUSB_BOOTLOADER_PRODUCT,\n usbVersionMajor: device.usbVersionMajor,\n usbVersionMinor: device.usbVersionMinor,\n usbVersionSubminor: device.usbVersionSubminor,\n deviceClass: device.deviceClass,\n deviceSubclass: device.deviceSubclass,\n deviceProtocol: device.deviceProtocol,\n deviceVersionMajor: device.deviceVersionMajor,\n deviceVersionMinor: device.deviceVersionMinor,\n deviceVersionSubminor: device.deviceVersionSubminor,\n opened: device.opened,\n raw: {\n configurations,\n },\n };\n }\n\n private _handlePhysicalDisconnect(device: USBDevice): void {\n // Find which connectId this corresponds to.\n for (const [connectId, connected] of this._connected) {\n if (connected === device) {\n this._connected.delete(connectId);\n this._log('warn', 'webusb.disconnect.event', { connectId });\n this._disconnectHandlers.get(connectId)?.forEach(handler => {\n try {\n handler();\n } catch (error) {\n this._log('error', 'webusb.disconnect.handler.threw', {\n connectId,\n error: String(error),\n });\n }\n });\n return;\n }\n }\n }\n\n private _log(\n level: 'debug' | 'info' | 'warn' | 'error',\n event: string,\n data?: Record<string, unknown>\n ): void {\n this._logger?.({ level, scope: 'trezor-webusb', event, data });\n }\n}\n\nexport async function createTrezorWebUsbTransport(\n options?: TrezorWebUsbTransportOptions\n): Promise<TrezorWebUsbTransport> {\n return new TrezorWebUsbTransport(options);\n}\n"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@onekeyfe/hwk-trezor-connector-webusb",
|
|
3
|
+
"version": "1.1.27-alpha.100",
|
|
4
|
+
"description": "IConnector implementation for Trezor hardware wallets via WebUSB",
|
|
5
|
+
"author": "OneKey",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"main": "dist/index.js",
|
|
8
|
+
"module": "dist/index.mjs",
|
|
9
|
+
"types": "dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"import": {
|
|
13
|
+
"types": "./dist/index.d.mts",
|
|
14
|
+
"default": "./dist/index.mjs"
|
|
15
|
+
},
|
|
16
|
+
"require": {
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"default": "./dist/index.js"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist"
|
|
24
|
+
],
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build": "tsup",
|
|
27
|
+
"dev": "tsup --watch",
|
|
28
|
+
"clean": "rimraf dist",
|
|
29
|
+
"test": "jest"
|
|
30
|
+
},
|
|
31
|
+
"publishConfig": {
|
|
32
|
+
"access": "public"
|
|
33
|
+
},
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "git+https://github.com/OneKeyHQ/hardware-js-sdk.git",
|
|
37
|
+
"directory": "packages/hwk-trezor-connector-webusb"
|
|
38
|
+
},
|
|
39
|
+
"keywords": [
|
|
40
|
+
"trezor",
|
|
41
|
+
"webusb",
|
|
42
|
+
"usb",
|
|
43
|
+
"hardware-wallet",
|
|
44
|
+
"onekey",
|
|
45
|
+
"connector"
|
|
46
|
+
],
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"@onekeyfe/hwk-adapter-core": "1.1.27-alpha.100",
|
|
49
|
+
"@onekeyfe/hwk-trezor-connector": "1.1.27-alpha.100",
|
|
50
|
+
"buffer": "^6.0.3"
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"rimraf": "^5.0.0",
|
|
54
|
+
"tsup": "^8.0.0",
|
|
55
|
+
"typescript": "5.1.6"
|
|
56
|
+
},
|
|
57
|
+
"gitHead": "d67fe1a72b9fce9755ecb96172311c7e29738e95"
|
|
58
|
+
}
|