@bytezhang/hardware-trezor-adapter 0.0.1 → 0.0.8

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.js CHANGED
@@ -146,6 +146,31 @@ var TrezorAdapter = class {
146
146
  const sessionId = this._sessions.get(connectId) ?? connectId;
147
147
  void this.connector.cancel(sessionId);
148
148
  }
149
+ // ─── Chain fingerprint ────────────────────────────────────
150
+ /**
151
+ * For Trezor, the chain fingerprint is the hardware device_id from firmware.
152
+ * Trezor has a persistent device identity, so no address derivation is needed.
153
+ */
154
+ async getChainFingerprint(connectId, deviceId, _chain) {
155
+ await this._ensureDevicePermission(connectId, deviceId);
156
+ const cached = this._discoveredDevices.get(connectId) ?? Array.from(this._discoveredDevices.values()).find(
157
+ (d) => d.deviceId === deviceId
158
+ );
159
+ if (cached?.deviceId) {
160
+ return (0, import_hardware_wallet_core.success)(cached.deviceId);
161
+ }
162
+ try {
163
+ const result = await this.connectorCall(connectId, "getFeatures", {});
164
+ if (result.device_id) {
165
+ return (0, import_hardware_wallet_core.success)(result.device_id);
166
+ }
167
+ } catch {
168
+ }
169
+ return (0, import_hardware_wallet_core.failure)(
170
+ import_hardware_wallet_core.HardwareErrorCode.DeviceNotFound,
171
+ "Could not determine Trezor device identity. Ensure the device is connected."
172
+ );
173
+ }
149
174
  // ─── EVM methods ──────────────────────────────────────────
150
175
  async evmGetAddress(connectId, _deviceId, params) {
151
176
  await this._ensureDevicePermission(connectId, _deviceId);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/TrezorAdapter.ts","../src/TrezorProxyClient.ts"],"sourcesContent":["export { TrezorAdapter } from './TrezorAdapter';\nexport type { ConnectorCallError } from './types';\n\n// Legacy exports for backward compatibility.\n// These are used by trezor-transport-ext and trezor-transport-electron\n// which still extend TrezorProxyClient. They are NOT used by TrezorAdapter.\nexport { TrezorProxyClient } from './TrezorProxyClient';\nexport type { ITrezorConnect, TrezorConnectResponse } from './types';\n","import {\n type IHardwareWallet,\n type IUiHandler,\n type IConnector,\n type ConnectorDevice,\n type ChainCapability,\n type DeviceEventListener,\n type ConnectionType,\n type DeviceInfo,\n type TransportType,\n type Response,\n type EvmGetAddressParams,\n type EvmAddress,\n type EvmGetPublicKeyParams,\n type EvmPublicKey,\n type EvmSignTxParams,\n type EvmSignedTx,\n type EvmSignMsgParams,\n type EvmSignTypedDataParams,\n type EvmSignature,\n type ProgressCallback,\n type BtcGetAddressParams,\n type BtcAddress,\n type BtcGetPublicKeyParams,\n type BtcPublicKey,\n type BtcSignTxParams,\n type BtcSignedTx,\n type BtcSignMsgParams,\n type BtcSignature,\n type SolGetAddressParams,\n type SolAddress,\n type SolGetPublicKeyParams,\n type SolPublicKey,\n type SolSignTxParams,\n type SolSignedTx,\n type SolSignMsgParams,\n type SolSignature,\n type HardwareEventMap,\n HardwareErrorCode,\n success,\n failure,\n DEVICE,\n UI_REQUEST,\n TypedEventEmitter,\n} from '@bytezhang/hardware-wallet-core';\n\n/**\n * Trezor hardware wallet adapter that delegates to an IConnector.\n *\n * This is a thin translation layer that:\n * - Accepts a pre-configured IConnector (transport decisions are made at connector creation time)\n * - Translates IHardwareWallet method calls to connector.call() invocations\n * - Maps connector results/errors to our Response<T> format with enriched error messages\n * - Translates connector events to HardwareEventMap events\n * - Integrates with IUiHandler for interactive flows (PIN, passphrase)\n */\nexport class TrezorAdapter implements IHardwareWallet {\n readonly vendor = 'trezor' as const;\n\n private readonly connector: IConnector;\n private readonly emitter = new TypedEventEmitter<HardwareEventMap>();\n\n private _uiHandler: Partial<IUiHandler> | null = null;\n\n // Device cache: tracks discovered devices from connector events\n private _discoveredDevices = new Map<string, DeviceInfo>();\n\n // Session tracking: maps connectId -> sessionId\n private _sessions = new Map<string, string>();\n\n constructor(connector: IConnector) {\n this.connector = connector;\n this.registerEventListeners();\n }\n\n // ─── Transport ──────────────────────────────────────────\n // Transport is decided at connector creation time. These methods\n // satisfy the IHardwareWallet interface with sensible defaults.\n\n get activeTransport(): TransportType | null {\n return 'usb';\n }\n\n getAvailableTransports(): TransportType[] {\n return ['usb'];\n }\n\n async switchTransport(_type: TransportType): Promise<void> {\n // Transport is fixed at connector creation time.\n // To switch transport, create a new TrezorAdapter with a different connector.\n }\n\n // ─── UI handler ────────────────────────────────────────────\n\n setUiHandler(handler: Partial<IUiHandler>): void {\n this._uiHandler = handler;\n }\n\n // ─── Lifecycle ────────────────────────────────────────────\n\n async init(_config?: unknown): Promise<void> {\n // Connector is injected via constructor, already initialized.\n // Nothing to do here.\n }\n\n async dispose(): Promise<void> {\n this.unregisterEventListeners();\n this.connector.reset();\n this._uiHandler = null;\n this._discoveredDevices.clear();\n this._sessions.clear();\n this.emitter.removeAllListeners();\n }\n\n // ─── Device management ────────────────────────────────────\n\n async searchDevices(): Promise<DeviceInfo[]> {\n await this._ensureDevicePermission();\n\n const devices = await this.connector.searchDevices();\n\n for (const d of devices) {\n if (d.connectId && !this._discoveredDevices.has(d.connectId)) {\n this._discoveredDevices.set(d.connectId, this.connectorDeviceToDeviceInfo(d));\n }\n }\n\n // If no devices found, ensure permission (no connectId = search context)\n if (this._discoveredDevices.size === 0) {\n await this._ensureDevicePermission();\n }\n\n return Array.from(this._discoveredDevices.values());\n }\n\n async connectDevice(connectId: string): Promise<Response<string>> {\n try {\n const session = await this.connector.connect(connectId);\n this._sessions.set(connectId, session.sessionId);\n\n // Update device cache with richer info from session\n if (session.deviceInfo) {\n this._discoveredDevices.set(connectId, session.deviceInfo);\n }\n\n return success(connectId);\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async disconnectDevice(connectId: string): Promise<void> {\n const sessionId = this._sessions.get(connectId);\n if (sessionId) {\n await this.connector.disconnect(sessionId);\n this._sessions.delete(connectId);\n }\n }\n\n async getDeviceInfo(\n connectId: string,\n deviceId: string,\n ): Promise<Response<DeviceInfo>> {\n await this._ensureDevicePermission(connectId, deviceId);\n\n // Look up the device in the cache populated by event handlers / searchDevices.\n // Try connectId first (the USB path), then fall back to scanning by deviceId.\n const cached =\n this._discoveredDevices.get(connectId) ??\n Array.from(this._discoveredDevices.values()).find(\n (d) => d.deviceId === deviceId,\n );\n\n if (cached) {\n return success(cached);\n }\n\n return failure(\n HardwareErrorCode.DeviceNotFound,\n 'Device not found in cache. Call searchDevices() or wait for a device-connected event first.',\n );\n }\n\n getSupportedChains(): ChainCapability[] {\n return ['evm', 'btc', 'sol'];\n }\n\n // ─── Event handling ───────────────────────────────────────\n\n on<K extends keyof HardwareEventMap>(event: K, listener: (event: HardwareEventMap[K]) => void): void;\n on(event: string, listener: DeviceEventListener): void;\n on(event: string, listener: (event: any) => void): void {\n this.emitter.on(event, listener);\n }\n\n off<K extends keyof HardwareEventMap>(event: K, listener: (event: HardwareEventMap[K]) => void): void;\n off(event: string, listener: DeviceEventListener): void;\n off(event: string, listener: (event: any) => void): void {\n this.emitter.off(event, listener);\n }\n\n cancel(connectId: string): void {\n const sessionId = this._sessions.get(connectId) ?? connectId;\n void this.connector.cancel(sessionId);\n }\n\n // ─── EVM methods ──────────────────────────────────────────\n\n async evmGetAddress(\n connectId: string,\n _deviceId: string,\n params: EvmGetAddressParams,\n ): Promise<Response<EvmAddress>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const result = await this.connectorCall(connectId, 'evmGetAddress', {\n path: params.path,\n showOnDevice: params.showOnDevice,\n chainId: params.chainId,\n }) as { address: string; path: string };\n\n return success({\n address: result.address,\n path: params.path,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async evmGetAddresses(\n connectId: string,\n deviceId: string,\n params: EvmGetAddressParams[],\n onProgress?: ProgressCallback,\n ): Promise<Response<EvmAddress[]>> {\n return this.batchCall(\n params,\n (p) => this.evmGetAddress(connectId, deviceId, p),\n onProgress,\n );\n }\n\n async evmGetPublicKey(\n connectId: string,\n _deviceId: string,\n params: EvmGetPublicKeyParams,\n ): Promise<Response<EvmPublicKey>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const result = await this.connectorCall(connectId, 'evmGetPublicKey', {\n path: params.path,\n showOnDevice: params.showOnDevice,\n }) as { publicKey: string; path: string };\n\n return success({\n publicKey: result.publicKey,\n path: params.path,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async evmSignTransaction(\n connectId: string,\n _deviceId: string,\n params: EvmSignTxParams,\n ): Promise<Response<EvmSignedTx>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const result = await this.connectorCall(connectId, 'evmSignTransaction', {\n path: params.path,\n transaction: {\n to: params.to,\n value: params.value,\n chainId: params.chainId,\n nonce: params.nonce,\n gasLimit: params.gasLimit,\n gasPrice: params.gasPrice,\n maxFeePerGas: params.maxFeePerGas,\n maxPriorityFeePerGas: params.maxPriorityFeePerGas,\n accessList: params.accessList,\n data: params.data,\n },\n }) as { v: string; r: string; s: string; serializedTx?: string };\n\n return success({\n v: this.ensure0x(result.v),\n r: this.padHex64(result.r),\n s: this.padHex64(result.s),\n serializedTx: result.serializedTx,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async evmSignMessage(\n connectId: string,\n _deviceId: string,\n params: EvmSignMsgParams,\n ): Promise<Response<EvmSignature>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const result = await this.connectorCall(connectId, 'evmSignMessage', {\n path: params.path,\n message: params.message,\n hex: params.hex,\n }) as { signature: string; address?: string };\n\n return success({\n signature: this.ensure0x(result.signature),\n address: result.address,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async evmSignTypedData(\n connectId: string,\n _deviceId: string,\n params: EvmSignTypedDataParams,\n ): Promise<Response<EvmSignature>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const callParams: Record<string, unknown> = {\n path: params.path,\n };\n\n if (params.mode !== 'hash') {\n callParams['mode'] = params.mode ?? 'full';\n callParams['data'] = params.data;\n callParams['metamaskV4Compat'] = params.metamaskV4Compat ?? true;\n } else {\n callParams['mode'] = 'hash';\n callParams['domainSeparatorHash'] = params.domainSeparatorHash;\n callParams['messageHash'] = params.messageHash;\n }\n\n const result = await this.connectorCall(connectId, 'evmSignTypedData', callParams) as {\n signature: string;\n address?: string;\n };\n\n return success({\n signature: this.ensure0x(result.signature),\n address: result.address,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n // ─── BTC methods ──────────────────────────────────────────\n\n async btcGetAddress(\n connectId: string,\n _deviceId: string,\n params: BtcGetAddressParams,\n ): Promise<Response<BtcAddress>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const result = await this.connectorCall(connectId, 'btcGetAddress', {\n path: params.path,\n coin: params.coin,\n showOnDevice: params.showOnDevice,\n scriptType: params.scriptType,\n }) as { address: string; path: string };\n\n return success({\n address: result.address,\n path: params.path,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async btcGetAddresses(\n connectId: string,\n deviceId: string,\n params: BtcGetAddressParams[],\n onProgress?: ProgressCallback,\n ): Promise<Response<BtcAddress[]>> {\n return this.batchCall(\n params,\n (p) => this.btcGetAddress(connectId, deviceId, p),\n onProgress,\n );\n }\n\n async btcGetPublicKey(\n connectId: string,\n _deviceId: string,\n params: BtcGetPublicKeyParams,\n ): Promise<Response<BtcPublicKey>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const result = await this.connectorCall(connectId, 'btcGetPublicKey', {\n path: params.path,\n coin: params.coin,\n showOnDevice: params.showOnDevice,\n }) as {\n xpub: string;\n publicKey: string;\n fingerprint: number;\n chainCode: string;\n path: string;\n depth: number;\n };\n\n return success({\n xpub: result.xpub,\n publicKey: result.publicKey,\n fingerprint: result.fingerprint,\n chainCode: result.chainCode,\n path: params.path,\n depth: result.depth,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async btcSignTransaction(\n connectId: string,\n _deviceId: string,\n params: BtcSignTxParams,\n ): Promise<Response<BtcSignedTx>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const result = await this.connectorCall(connectId, 'btcSignTransaction', {\n inputs: params.inputs ?? [],\n outputs: params.outputs ?? [],\n refTxs: params.refTxs,\n coin: params.coin,\n locktime: params.locktime,\n version: params.version,\n }) as { signatures: string[]; serializedTx: string; txid?: string };\n\n return success({\n signatures: result.signatures,\n serializedTx: result.serializedTx,\n txid: result.txid,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async btcSignMessage(\n connectId: string,\n _deviceId: string,\n params: BtcSignMsgParams,\n ): Promise<Response<BtcSignature>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const result = await this.connectorCall(connectId, 'btcSignMessage', {\n path: params.path,\n message: params.message,\n coin: params.coin,\n }) as { signature: string; address: string };\n\n return success({\n signature: result.signature,\n address: result.address,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async btcGetMasterFingerprint(\n connectId: string,\n _deviceId: string,\n ): Promise<Response<{ masterFingerprint: string }>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n // The parent fingerprint of a child of \"m\" IS the master fingerprint.\n // Query \"m/0'\" and read its `fingerprint` field (parent key fingerprint).\n const result = await this.connectorCall(connectId, 'btcGetPublicKey', {\n path: \"m/0'\",\n }) as { fingerprint: number };\n\n const fp = (result.fingerprint) >>> 0;\n const hex = fp.toString(16).padStart(8, '0');\n return success({ masterFingerprint: hex });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n // ─── Solana methods ───────────────────────────────────────\n\n async solGetAddress(\n connectId: string,\n _deviceId: string,\n params: SolGetAddressParams,\n ): Promise<Response<SolAddress>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const result = await this.connectorCall(connectId, 'solGetAddress', {\n path: params.path,\n showOnDevice: params.showOnDevice,\n }) as { address: string; path: string };\n\n return success({\n address: result.address,\n path: params.path,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async solGetAddresses(\n connectId: string,\n deviceId: string,\n params: SolGetAddressParams[],\n onProgress?: ProgressCallback,\n ): Promise<Response<SolAddress[]>> {\n return this.batchCall(\n params,\n (p) => this.solGetAddress(connectId, deviceId, p),\n onProgress,\n );\n }\n\n async solGetPublicKey(\n connectId: string,\n _deviceId: string,\n params: SolGetPublicKeyParams,\n ): Promise<Response<SolPublicKey>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n // Solana address IS the public key\n const result = await this.connectorCall(connectId, 'solGetAddress', {\n path: params.path,\n showOnDevice: params.showOnDevice,\n }) as { address: string; path: string };\n\n return success({\n publicKey: result.address,\n path: params.path,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async solSignTransaction(\n connectId: string,\n _deviceId: string,\n params: SolSignTxParams,\n ): Promise<Response<SolSignedTx>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const result = await this.connectorCall(connectId, 'solSignTransaction', {\n path: params.path,\n serializedTx: params.serializedTx,\n additionalInfo: params.additionalInfo,\n }) as { signature: string };\n\n return success({\n signature: result.signature,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async solSignMessage(\n _connectId: string,\n _deviceId: string,\n _params: SolSignMsgParams,\n ): Promise<Response<SolSignature>> {\n return failure(\n HardwareErrorCode.MethodNotSupported,\n 'Solana signMessage is not supported by Trezor Connect',\n );\n }\n\n // ─── Private helpers ──────────────────────────────────────\n\n /**\n * Call the connector with session resolution.\n * Looks up sessionId from connectId, falls back to connectId itself.\n */\n private async connectorCall(\n connectId: string,\n method: string,\n params: unknown,\n ): Promise<unknown> {\n const sessionId = this._sessions.get(connectId) ?? connectId;\n return this.connector.call(sessionId, method, params);\n }\n\n /**\n * Ensure device permission before proceeding.\n * - No connectId (searchDevices): check environment-level permission\n * - With connectId (business methods): check device-level permission\n * If not granted, calls onDevicePermission so the consumer can request access.\n */\n private async _ensureDevicePermission(connectId?: string, deviceId?: string): Promise<void> {\n const transportType: TransportType = 'usb';\n let granted = false;\n let context: Record<string, unknown> | undefined;\n\n if (this._uiHandler?.checkDevicePermission) {\n try {\n const result = await this._uiHandler.checkDevicePermission({ transportType, connectId, deviceId });\n granted = result.granted;\n context = result.context;\n } catch {\n granted = false;\n }\n }\n\n if (!granted) {\n try {\n await this._uiHandler?.onDevicePermission?.({ transportType, context });\n } catch {\n // UI handler cancelled or failed\n }\n }\n }\n\n /**\n * Convert a thrown error to a Response failure.\n * Parses TrezorConnect error strings to map to HardwareErrorCode values.\n */\n private errorToFailure<T>(err: unknown): Response<T> {\n const message = err instanceof Error ? err.message : String(err);\n const code = this.parseErrorCode(message);\n const enriched = this.enrichErrorMessage(code, message);\n return failure(code, enriched);\n }\n\n /**\n * Parse TrezorConnect error codes from error message strings.\n * The connector throws errors with messages like \"Trezor ethereumGetAddress failed: <error>\".\n * We also check for embedded code patterns.\n */\n private parseErrorCode(message: string): HardwareErrorCode {\n // Check for known error patterns in the message\n if (message.includes('Failure_ActionCancelled') || message.includes('Failure_Cancel')) {\n return HardwareErrorCode.UserRejected;\n }\n if (message.includes('Failure_PinInvalid') || message.includes('Failure_PinMismatch')) {\n return HardwareErrorCode.PinInvalid;\n }\n if (message.includes('Failure_PinCancelled')) {\n return HardwareErrorCode.PinCancelled;\n }\n if (message.includes('Failure_PassphraseRejected')) {\n return HardwareErrorCode.PassphraseRejected;\n }\n if (message.includes('Device_UsedElsewhere')) {\n return HardwareErrorCode.DeviceBusy;\n }\n if (message.includes('Device_NotFound')) {\n return HardwareErrorCode.DeviceNotFound;\n }\n if (message.includes('Device_InvalidState')) {\n return HardwareErrorCode.DeviceNotInitialized;\n }\n if (message.includes('Transport_Missing')) {\n return HardwareErrorCode.TransportNotAvailable;\n }\n if (message.includes('Transport_DeviceDisconnected')) {\n return HardwareErrorCode.DeviceDisconnected;\n }\n if (message.includes('Failure_FirmwareError')) {\n return HardwareErrorCode.FirmwareTooOld;\n }\n if (message.includes('Method_InvalidParameter') || message.includes('Method_InvalidParams')) {\n return HardwareErrorCode.InvalidParams;\n }\n if (message.includes('Method_NotAllowed')) {\n return HardwareErrorCode.MethodNotSupported;\n }\n return HardwareErrorCode.UnknownError;\n }\n\n /**\n * Enrich error messages with actionable recovery info for the caller.\n */\n private enrichErrorMessage(code: HardwareErrorCode, originalMessage: string): string {\n switch (code) {\n case HardwareErrorCode.PinInvalid:\n return `${originalMessage}. Please re-enter your PIN.`;\n case HardwareErrorCode.PinCancelled:\n return `${originalMessage}. PIN entry was cancelled.`;\n case HardwareErrorCode.DeviceBusy:\n return `${originalMessage}. The device is in use by another application. Close other wallet apps and try again.`;\n case HardwareErrorCode.DeviceDisconnected:\n return `${originalMessage}. Please reconnect the device and try again.`;\n case HardwareErrorCode.TransportNotAvailable:\n return `${originalMessage}. Ensure Trezor Bridge is installed and running, or connect via USB.`;\n case HardwareErrorCode.FirmwareTooOld:\n return `${originalMessage}. Please update your Trezor firmware via Trezor Suite.`;\n case HardwareErrorCode.DeviceNotInitialized:\n return `${originalMessage}. The device may need to be set up first via Trezor Suite.`;\n default:\n return originalMessage;\n }\n }\n\n /**\n * Generic batch call with progress reporting.\n * If any single call fails, returns the failure immediately.\n */\n private async batchCall<TParam, TResult>(\n params: TParam[],\n callFn: (p: TParam) => Promise<Response<TResult>>,\n onProgress?: ProgressCallback,\n ): Promise<Response<TResult[]>> {\n const results: TResult[] = [];\n for (let i = 0; i < params.length; i++) {\n const result = await callFn(params[i]);\n if (!result.success) {\n return result;\n }\n results.push(result.payload);\n onProgress?.({ index: i, total: params.length });\n }\n return success(results);\n }\n\n // ─── Hex formatting ──────────────────────────────────────\n\n /** Ensure a hex string has the `0x` prefix. */\n private ensure0x(hex: string): string {\n return hex.startsWith('0x') ? hex : `0x${hex}`;\n }\n\n /** Ensure a hex string is `0x`-prefixed and zero-padded to 64 hex chars (32 bytes). */\n private padHex64(hex: string): string {\n const stripped = hex.startsWith('0x') ? hex.slice(2) : hex;\n return `0x${stripped.padStart(64, '0')}`;\n }\n\n // ─── Event translation ────────────────────────────────────\n\n private deviceConnectHandler = (data: { device: ConnectorDevice }): void => {\n const deviceInfo = this.connectorDeviceToDeviceInfo(data.device);\n this._discoveredDevices.set(deviceInfo.connectId, deviceInfo);\n this.emitter.emit(DEVICE.CONNECT, {\n type: DEVICE.CONNECT,\n payload: deviceInfo,\n });\n };\n\n private deviceDisconnectHandler = (data: { connectId: string }): void => {\n this._discoveredDevices.delete(data.connectId);\n this.emitter.emit(DEVICE.DISCONNECT, {\n type: DEVICE.DISCONNECT,\n payload: { connectId: data.connectId },\n });\n };\n\n private uiRequestHandler = (data: { type: string; payload?: unknown }): void => {\n this.handleUiEvent(data);\n };\n\n private uiEventHandler = (data: { type: string; payload?: unknown }): void => {\n this.handleUiEvent(data);\n };\n\n private registerEventListeners(): void {\n this.connector.on('device-connect', this.deviceConnectHandler);\n this.connector.on('device-disconnect', this.deviceDisconnectHandler);\n this.connector.on('ui-request', this.uiRequestHandler);\n this.connector.on('ui-event', this.uiEventHandler);\n }\n\n private unregisterEventListeners(): void {\n this.connector.off('device-connect', this.deviceConnectHandler);\n this.connector.off('device-disconnect', this.deviceDisconnectHandler);\n this.connector.off('ui-request', this.uiRequestHandler);\n this.connector.off('ui-event', this.uiEventHandler);\n }\n\n private handleUiEvent(event: { type: string; payload?: unknown }): void {\n if (!event.type) return;\n\n const payload = event.payload as Record<string, unknown> | undefined;\n const devicePayload = (payload?.['device'] as Record<string, unknown>) ?? payload;\n const deviceInfo = devicePayload ? this.extractDeviceInfoFromPayload(devicePayload) : this.unknownDevice();\n\n switch (event.type) {\n case 'ui-request_pin':\n this.emitter.emit(UI_REQUEST.REQUEST_PIN, {\n type: UI_REQUEST.REQUEST_PIN,\n payload: { device: deviceInfo },\n });\n if (this._uiHandler?.onPinRequest) {\n this._uiHandler.onPinRequest(deviceInfo).then((pin) => {\n this.connector.uiResponse({\n type: 'receive-pin',\n payload: pin,\n });\n }).catch(() => {\n // User cancelled -- no response sent\n });\n }\n break;\n case 'ui-request_passphrase':\n this.emitter.emit(UI_REQUEST.REQUEST_PASSPHRASE, {\n type: UI_REQUEST.REQUEST_PASSPHRASE,\n payload: { device: deviceInfo },\n });\n if (this._uiHandler?.onPassphraseRequest) {\n this._uiHandler.onPassphraseRequest(deviceInfo).then((result) => {\n const response = typeof result === 'string'\n ? { passphrase: result, onDevice: false }\n : result ?? { passphrase: '', onDevice: false };\n if (response.onDevice) {\n this.connector.uiResponse({\n type: 'receive-passphrase',\n payload: {\n value: '',\n passphraseOnDevice: true,\n save: false,\n },\n });\n } else {\n this.connector.uiResponse({\n type: 'receive-passphrase',\n payload: {\n value: response.passphrase,\n passphraseOnDevice: false,\n save: false,\n },\n });\n }\n }).catch(() => {\n // User cancelled -- no response sent\n });\n }\n break;\n case 'ui-request_confirmation':\n this.emitter.emit(UI_REQUEST.REQUEST_BUTTON, {\n type: UI_REQUEST.REQUEST_BUTTON,\n payload: { device: deviceInfo },\n });\n break;\n }\n }\n\n private connectorDeviceToDeviceInfo(device: ConnectorDevice): DeviceInfo {\n return {\n vendor: 'trezor',\n model: device.model ?? 'unknown',\n firmwareVersion: '',\n deviceId: device.deviceId,\n connectId: device.connectId,\n label: device.name,\n connectionType: 'usb' as ConnectionType,\n };\n }\n\n private extractDeviceInfoFromPayload(payload: Record<string, unknown>): DeviceInfo {\n const features = payload['features'] as Record<string, unknown> | undefined;\n return {\n vendor: 'trezor',\n model: (features?.['model'] as string) ?? (payload['model'] as string) ?? 'unknown',\n firmwareVersion: features\n ? `${features['major_version'] ?? 0}.${features['minor_version'] ?? 0}.${features['patch_version'] ?? 0}`\n : '',\n deviceId: (features?.['device_id'] as string) ?? (payload['id'] as string) ?? '',\n connectId: (payload['path'] as string) ?? '',\n label: (features?.['label'] as string) ?? (payload['label'] as string),\n connectionType: 'usb' as ConnectionType,\n };\n }\n\n private unknownDevice(): DeviceInfo {\n return {\n vendor: 'trezor',\n model: 'unknown',\n firmwareVersion: '',\n deviceId: '',\n connectId: '',\n connectionType: 'usb',\n };\n }\n}\n","import { AbstractProxyClient } from '@bytezhang/hardware-transport-core';\nimport type { ITrezorConnect, TrezorConnectResponse } from './types';\n\n/**\n * Trezor method stubs on top of AbstractProxyClient.\n *\n * All cross-process Trezor proxy clients (Electron IPC, Extension messaging)\n * extend this class. They only need to implement:\n * - `sendCall()` — the transport channel\n * - `dispose()` / `cancel()` / `uiResponse()` — lifecycle\n *\n * The 11 TrezorConnect method stubs are defined here once.\n */\nexport abstract class TrezorProxyClient extends AbstractProxyClient implements ITrezorConnect {\n abstract dispose(): void;\n abstract cancel(reason?: string): void;\n abstract uiResponse(response: { type: string; payload: unknown }): void;\n\n // ─── TrezorConnect method stubs — all delegate to call() ────\n ethereumGetAddress(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('ethereumGetAddress', params) as Promise<TrezorConnectResponse>;\n }\n ethereumGetPublicKey(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('ethereumGetPublicKey', params) as Promise<TrezorConnectResponse>;\n }\n ethereumSignTransaction(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('ethereumSignTransaction', params) as Promise<TrezorConnectResponse>;\n }\n ethereumSignMessage(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('ethereumSignMessage', params) as Promise<TrezorConnectResponse>;\n }\n ethereumSignTypedData(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('ethereumSignTypedData', params) as Promise<TrezorConnectResponse>;\n }\n getAddress(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('getAddress', params) as Promise<TrezorConnectResponse>;\n }\n getPublicKey(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('getPublicKey', params) as Promise<TrezorConnectResponse>;\n }\n signTransaction(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('signTransaction', params) as Promise<TrezorConnectResponse>;\n }\n signMessage(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('signMessage', params) as Promise<TrezorConnectResponse>;\n }\n solanaGetAddress(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('solanaGetAddress', params) as Promise<TrezorConnectResponse>;\n }\n solanaSignTransaction(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('solanaSignTransaction', params) as Promise<TrezorConnectResponse>;\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/TrezorAdapter.ts","../src/TrezorProxyClient.ts"],"sourcesContent":["export { TrezorAdapter } from './TrezorAdapter';\nexport type { ConnectorCallError } from './types';\n\n// Legacy exports for backward compatibility.\n// These are used by trezor-transport-ext and trezor-transport-electron\n// which still extend TrezorProxyClient. They are NOT used by TrezorAdapter.\nexport { TrezorProxyClient } from './TrezorProxyClient';\nexport type { ITrezorConnect, TrezorConnectResponse } from './types';\n","import {\n type IHardwareWallet,\n type IUiHandler,\n type IConnector,\n type ConnectorDevice,\n type ChainCapability,\n type DeviceEventListener,\n type ConnectionType,\n type DeviceInfo,\n type TransportType,\n type Response,\n type EvmGetAddressParams,\n type EvmAddress,\n type EvmGetPublicKeyParams,\n type EvmPublicKey,\n type EvmSignTxParams,\n type EvmSignedTx,\n type EvmSignMsgParams,\n type EvmSignTypedDataParams,\n type EvmSignature,\n type ProgressCallback,\n type BtcGetAddressParams,\n type BtcAddress,\n type BtcGetPublicKeyParams,\n type BtcPublicKey,\n type BtcSignTxParams,\n type BtcSignedTx,\n type BtcSignMsgParams,\n type BtcSignature,\n type SolGetAddressParams,\n type SolAddress,\n type SolGetPublicKeyParams,\n type SolPublicKey,\n type SolSignTxParams,\n type SolSignedTx,\n type SolSignMsgParams,\n type SolSignature,\n type HardwareEventMap,\n type ChainForFingerprint,\n HardwareErrorCode,\n success,\n failure,\n DEVICE,\n UI_REQUEST,\n TypedEventEmitter,\n} from '@bytezhang/hardware-wallet-core';\n\n/**\n * Trezor hardware wallet adapter that delegates to an IConnector.\n *\n * This is a thin translation layer that:\n * - Accepts a pre-configured IConnector (transport decisions are made at connector creation time)\n * - Translates IHardwareWallet method calls to connector.call() invocations\n * - Maps connector results/errors to our Response<T> format with enriched error messages\n * - Translates connector events to HardwareEventMap events\n * - Integrates with IUiHandler for interactive flows (PIN, passphrase)\n */\nexport class TrezorAdapter implements IHardwareWallet {\n readonly vendor = 'trezor' as const;\n\n private readonly connector: IConnector;\n private readonly emitter = new TypedEventEmitter<HardwareEventMap>();\n\n private _uiHandler: Partial<IUiHandler> | null = null;\n\n // Device cache: tracks discovered devices from connector events\n private _discoveredDevices = new Map<string, DeviceInfo>();\n\n // Session tracking: maps connectId -> sessionId\n private _sessions = new Map<string, string>();\n\n constructor(connector: IConnector) {\n this.connector = connector;\n this.registerEventListeners();\n }\n\n // ─── Transport ──────────────────────────────────────────\n // Transport is decided at connector creation time. These methods\n // satisfy the IHardwareWallet interface with sensible defaults.\n\n get activeTransport(): TransportType | null {\n return 'usb';\n }\n\n getAvailableTransports(): TransportType[] {\n return ['usb'];\n }\n\n async switchTransport(_type: TransportType): Promise<void> {\n // Transport is fixed at connector creation time.\n // To switch transport, create a new TrezorAdapter with a different connector.\n }\n\n // ─── UI handler ────────────────────────────────────────────\n\n setUiHandler(handler: Partial<IUiHandler>): void {\n this._uiHandler = handler;\n }\n\n // ─── Lifecycle ────────────────────────────────────────────\n\n async init(_config?: unknown): Promise<void> {\n // Connector is injected via constructor, already initialized.\n // Nothing to do here.\n }\n\n async dispose(): Promise<void> {\n this.unregisterEventListeners();\n this.connector.reset();\n this._uiHandler = null;\n this._discoveredDevices.clear();\n this._sessions.clear();\n this.emitter.removeAllListeners();\n }\n\n // ─── Device management ────────────────────────────────────\n\n async searchDevices(): Promise<DeviceInfo[]> {\n await this._ensureDevicePermission();\n\n const devices = await this.connector.searchDevices();\n\n for (const d of devices) {\n if (d.connectId && !this._discoveredDevices.has(d.connectId)) {\n this._discoveredDevices.set(d.connectId, this.connectorDeviceToDeviceInfo(d));\n }\n }\n\n // If no devices found, ensure permission (no connectId = search context)\n if (this._discoveredDevices.size === 0) {\n await this._ensureDevicePermission();\n }\n\n return Array.from(this._discoveredDevices.values());\n }\n\n async connectDevice(connectId: string): Promise<Response<string>> {\n try {\n const session = await this.connector.connect(connectId);\n this._sessions.set(connectId, session.sessionId);\n\n // Update device cache with richer info from session\n if (session.deviceInfo) {\n this._discoveredDevices.set(connectId, session.deviceInfo);\n }\n\n return success(connectId);\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async disconnectDevice(connectId: string): Promise<void> {\n const sessionId = this._sessions.get(connectId);\n if (sessionId) {\n await this.connector.disconnect(sessionId);\n this._sessions.delete(connectId);\n }\n }\n\n async getDeviceInfo(\n connectId: string,\n deviceId: string,\n ): Promise<Response<DeviceInfo>> {\n await this._ensureDevicePermission(connectId, deviceId);\n\n // Look up the device in the cache populated by event handlers / searchDevices.\n // Try connectId first (the USB path), then fall back to scanning by deviceId.\n const cached =\n this._discoveredDevices.get(connectId) ??\n Array.from(this._discoveredDevices.values()).find(\n (d) => d.deviceId === deviceId,\n );\n\n if (cached) {\n return success(cached);\n }\n\n return failure(\n HardwareErrorCode.DeviceNotFound,\n 'Device not found in cache. Call searchDevices() or wait for a device-connected event first.',\n );\n }\n\n getSupportedChains(): ChainCapability[] {\n return ['evm', 'btc', 'sol'];\n }\n\n // ─── Event handling ───────────────────────────────────────\n\n on<K extends keyof HardwareEventMap>(event: K, listener: (event: HardwareEventMap[K]) => void): void;\n on(event: string, listener: DeviceEventListener): void;\n on(event: string, listener: (event: any) => void): void {\n this.emitter.on(event, listener);\n }\n\n off<K extends keyof HardwareEventMap>(event: K, listener: (event: HardwareEventMap[K]) => void): void;\n off(event: string, listener: DeviceEventListener): void;\n off(event: string, listener: (event: any) => void): void {\n this.emitter.off(event, listener);\n }\n\n cancel(connectId: string): void {\n const sessionId = this._sessions.get(connectId) ?? connectId;\n void this.connector.cancel(sessionId);\n }\n\n // ─── Chain fingerprint ────────────────────────────────────\n\n /**\n * For Trezor, the chain fingerprint is the hardware device_id from firmware.\n * Trezor has a persistent device identity, so no address derivation is needed.\n */\n async getChainFingerprint(\n connectId: string,\n deviceId: string,\n _chain: ChainForFingerprint,\n ): Promise<Response<string>> {\n await this._ensureDevicePermission(connectId, deviceId);\n\n // Look up the device in cache to get the firmware device_id\n const cached =\n this._discoveredDevices.get(connectId) ??\n Array.from(this._discoveredDevices.values()).find(\n (d) => d.deviceId === deviceId,\n );\n\n if (cached?.deviceId) {\n return success(cached.deviceId);\n }\n\n // Fall back: try to get device info from the connector\n try {\n const result = await this.connectorCall(connectId, 'getFeatures', {}) as {\n device_id?: string;\n };\n if (result.device_id) {\n return success(result.device_id);\n }\n } catch {\n // Ignore — fall through to error\n }\n\n return failure(\n HardwareErrorCode.DeviceNotFound,\n 'Could not determine Trezor device identity. Ensure the device is connected.',\n );\n }\n\n // ─── EVM methods ──────────────────────────────────────────\n\n async evmGetAddress(\n connectId: string,\n _deviceId: string,\n params: EvmGetAddressParams,\n ): Promise<Response<EvmAddress>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const result = await this.connectorCall(connectId, 'evmGetAddress', {\n path: params.path,\n showOnDevice: params.showOnDevice,\n chainId: params.chainId,\n }) as { address: string; path: string };\n\n return success({\n address: result.address,\n path: params.path,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async evmGetAddresses(\n connectId: string,\n deviceId: string,\n params: EvmGetAddressParams[],\n onProgress?: ProgressCallback,\n ): Promise<Response<EvmAddress[]>> {\n return this.batchCall(\n params,\n (p) => this.evmGetAddress(connectId, deviceId, p),\n onProgress,\n );\n }\n\n async evmGetPublicKey(\n connectId: string,\n _deviceId: string,\n params: EvmGetPublicKeyParams,\n ): Promise<Response<EvmPublicKey>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const result = await this.connectorCall(connectId, 'evmGetPublicKey', {\n path: params.path,\n showOnDevice: params.showOnDevice,\n }) as { publicKey: string; path: string };\n\n return success({\n publicKey: result.publicKey,\n path: params.path,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async evmSignTransaction(\n connectId: string,\n _deviceId: string,\n params: EvmSignTxParams,\n ): Promise<Response<EvmSignedTx>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const result = await this.connectorCall(connectId, 'evmSignTransaction', {\n path: params.path,\n transaction: {\n to: params.to,\n value: params.value,\n chainId: params.chainId,\n nonce: params.nonce,\n gasLimit: params.gasLimit,\n gasPrice: params.gasPrice,\n maxFeePerGas: params.maxFeePerGas,\n maxPriorityFeePerGas: params.maxPriorityFeePerGas,\n accessList: params.accessList,\n data: params.data,\n },\n }) as { v: string; r: string; s: string; serializedTx?: string };\n\n return success({\n v: this.ensure0x(result.v),\n r: this.padHex64(result.r),\n s: this.padHex64(result.s),\n serializedTx: result.serializedTx,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async evmSignMessage(\n connectId: string,\n _deviceId: string,\n params: EvmSignMsgParams,\n ): Promise<Response<EvmSignature>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const result = await this.connectorCall(connectId, 'evmSignMessage', {\n path: params.path,\n message: params.message,\n hex: params.hex,\n }) as { signature: string; address?: string };\n\n return success({\n signature: this.ensure0x(result.signature),\n address: result.address,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async evmSignTypedData(\n connectId: string,\n _deviceId: string,\n params: EvmSignTypedDataParams,\n ): Promise<Response<EvmSignature>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const callParams: Record<string, unknown> = {\n path: params.path,\n };\n\n if (params.mode !== 'hash') {\n callParams['mode'] = params.mode ?? 'full';\n callParams['data'] = params.data;\n callParams['metamaskV4Compat'] = params.metamaskV4Compat ?? true;\n } else {\n callParams['mode'] = 'hash';\n callParams['domainSeparatorHash'] = params.domainSeparatorHash;\n callParams['messageHash'] = params.messageHash;\n }\n\n const result = await this.connectorCall(connectId, 'evmSignTypedData', callParams) as {\n signature: string;\n address?: string;\n };\n\n return success({\n signature: this.ensure0x(result.signature),\n address: result.address,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n // ─── BTC methods ──────────────────────────────────────────\n\n async btcGetAddress(\n connectId: string,\n _deviceId: string,\n params: BtcGetAddressParams,\n ): Promise<Response<BtcAddress>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const result = await this.connectorCall(connectId, 'btcGetAddress', {\n path: params.path,\n coin: params.coin,\n showOnDevice: params.showOnDevice,\n scriptType: params.scriptType,\n }) as { address: string; path: string };\n\n return success({\n address: result.address,\n path: params.path,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async btcGetAddresses(\n connectId: string,\n deviceId: string,\n params: BtcGetAddressParams[],\n onProgress?: ProgressCallback,\n ): Promise<Response<BtcAddress[]>> {\n return this.batchCall(\n params,\n (p) => this.btcGetAddress(connectId, deviceId, p),\n onProgress,\n );\n }\n\n async btcGetPublicKey(\n connectId: string,\n _deviceId: string,\n params: BtcGetPublicKeyParams,\n ): Promise<Response<BtcPublicKey>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const result = await this.connectorCall(connectId, 'btcGetPublicKey', {\n path: params.path,\n coin: params.coin,\n showOnDevice: params.showOnDevice,\n }) as {\n xpub: string;\n publicKey: string;\n fingerprint: number;\n chainCode: string;\n path: string;\n depth: number;\n };\n\n return success({\n xpub: result.xpub,\n publicKey: result.publicKey,\n fingerprint: result.fingerprint,\n chainCode: result.chainCode,\n path: params.path,\n depth: result.depth,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async btcSignTransaction(\n connectId: string,\n _deviceId: string,\n params: BtcSignTxParams,\n ): Promise<Response<BtcSignedTx>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const result = await this.connectorCall(connectId, 'btcSignTransaction', {\n inputs: params.inputs ?? [],\n outputs: params.outputs ?? [],\n refTxs: params.refTxs,\n coin: params.coin,\n locktime: params.locktime,\n version: params.version,\n }) as { signatures: string[]; serializedTx: string; txid?: string };\n\n return success({\n signatures: result.signatures,\n serializedTx: result.serializedTx,\n txid: result.txid,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async btcSignMessage(\n connectId: string,\n _deviceId: string,\n params: BtcSignMsgParams,\n ): Promise<Response<BtcSignature>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const result = await this.connectorCall(connectId, 'btcSignMessage', {\n path: params.path,\n message: params.message,\n coin: params.coin,\n }) as { signature: string; address: string };\n\n return success({\n signature: result.signature,\n address: result.address,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async btcGetMasterFingerprint(\n connectId: string,\n _deviceId: string,\n ): Promise<Response<{ masterFingerprint: string }>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n // The parent fingerprint of a child of \"m\" IS the master fingerprint.\n // Query \"m/0'\" and read its `fingerprint` field (parent key fingerprint).\n const result = await this.connectorCall(connectId, 'btcGetPublicKey', {\n path: \"m/0'\",\n }) as { fingerprint: number };\n\n const fp = (result.fingerprint) >>> 0;\n const hex = fp.toString(16).padStart(8, '0');\n return success({ masterFingerprint: hex });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n // ─── Solana methods ───────────────────────────────────────\n\n async solGetAddress(\n connectId: string,\n _deviceId: string,\n params: SolGetAddressParams,\n ): Promise<Response<SolAddress>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const result = await this.connectorCall(connectId, 'solGetAddress', {\n path: params.path,\n showOnDevice: params.showOnDevice,\n }) as { address: string; path: string };\n\n return success({\n address: result.address,\n path: params.path,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async solGetAddresses(\n connectId: string,\n deviceId: string,\n params: SolGetAddressParams[],\n onProgress?: ProgressCallback,\n ): Promise<Response<SolAddress[]>> {\n return this.batchCall(\n params,\n (p) => this.solGetAddress(connectId, deviceId, p),\n onProgress,\n );\n }\n\n async solGetPublicKey(\n connectId: string,\n _deviceId: string,\n params: SolGetPublicKeyParams,\n ): Promise<Response<SolPublicKey>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n // Solana address IS the public key\n const result = await this.connectorCall(connectId, 'solGetAddress', {\n path: params.path,\n showOnDevice: params.showOnDevice,\n }) as { address: string; path: string };\n\n return success({\n publicKey: result.address,\n path: params.path,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async solSignTransaction(\n connectId: string,\n _deviceId: string,\n params: SolSignTxParams,\n ): Promise<Response<SolSignedTx>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const result = await this.connectorCall(connectId, 'solSignTransaction', {\n path: params.path,\n serializedTx: params.serializedTx,\n additionalInfo: params.additionalInfo,\n }) as { signature: string };\n\n return success({\n signature: result.signature,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async solSignMessage(\n _connectId: string,\n _deviceId: string,\n _params: SolSignMsgParams,\n ): Promise<Response<SolSignature>> {\n return failure(\n HardwareErrorCode.MethodNotSupported,\n 'Solana signMessage is not supported by Trezor Connect',\n );\n }\n\n // ─── Private helpers ──────────────────────────────────────\n\n /**\n * Call the connector with session resolution.\n * Looks up sessionId from connectId, falls back to connectId itself.\n */\n private async connectorCall(\n connectId: string,\n method: string,\n params: unknown,\n ): Promise<unknown> {\n const sessionId = this._sessions.get(connectId) ?? connectId;\n return this.connector.call(sessionId, method, params);\n }\n\n /**\n * Ensure device permission before proceeding.\n * - No connectId (searchDevices): check environment-level permission\n * - With connectId (business methods): check device-level permission\n * If not granted, calls onDevicePermission so the consumer can request access.\n */\n private async _ensureDevicePermission(connectId?: string, deviceId?: string): Promise<void> {\n const transportType: TransportType = 'usb';\n let granted = false;\n let context: Record<string, unknown> | undefined;\n\n if (this._uiHandler?.checkDevicePermission) {\n try {\n const result = await this._uiHandler.checkDevicePermission({ transportType, connectId, deviceId });\n granted = result.granted;\n context = result.context;\n } catch {\n granted = false;\n }\n }\n\n if (!granted) {\n try {\n await this._uiHandler?.onDevicePermission?.({ transportType, context });\n } catch {\n // UI handler cancelled or failed\n }\n }\n }\n\n /**\n * Convert a thrown error to a Response failure.\n * Parses TrezorConnect error strings to map to HardwareErrorCode values.\n */\n private errorToFailure<T>(err: unknown): Response<T> {\n const message = err instanceof Error ? err.message : String(err);\n const code = this.parseErrorCode(message);\n const enriched = this.enrichErrorMessage(code, message);\n return failure(code, enriched);\n }\n\n /**\n * Parse TrezorConnect error codes from error message strings.\n * The connector throws errors with messages like \"Trezor ethereumGetAddress failed: <error>\".\n * We also check for embedded code patterns.\n */\n private parseErrorCode(message: string): HardwareErrorCode {\n // Check for known error patterns in the message\n if (message.includes('Failure_ActionCancelled') || message.includes('Failure_Cancel')) {\n return HardwareErrorCode.UserRejected;\n }\n if (message.includes('Failure_PinInvalid') || message.includes('Failure_PinMismatch')) {\n return HardwareErrorCode.PinInvalid;\n }\n if (message.includes('Failure_PinCancelled')) {\n return HardwareErrorCode.PinCancelled;\n }\n if (message.includes('Failure_PassphraseRejected')) {\n return HardwareErrorCode.PassphraseRejected;\n }\n if (message.includes('Device_UsedElsewhere')) {\n return HardwareErrorCode.DeviceBusy;\n }\n if (message.includes('Device_NotFound')) {\n return HardwareErrorCode.DeviceNotFound;\n }\n if (message.includes('Device_InvalidState')) {\n return HardwareErrorCode.DeviceNotInitialized;\n }\n if (message.includes('Transport_Missing')) {\n return HardwareErrorCode.TransportNotAvailable;\n }\n if (message.includes('Transport_DeviceDisconnected')) {\n return HardwareErrorCode.DeviceDisconnected;\n }\n if (message.includes('Failure_FirmwareError')) {\n return HardwareErrorCode.FirmwareTooOld;\n }\n if (message.includes('Method_InvalidParameter') || message.includes('Method_InvalidParams')) {\n return HardwareErrorCode.InvalidParams;\n }\n if (message.includes('Method_NotAllowed')) {\n return HardwareErrorCode.MethodNotSupported;\n }\n return HardwareErrorCode.UnknownError;\n }\n\n /**\n * Enrich error messages with actionable recovery info for the caller.\n */\n private enrichErrorMessage(code: HardwareErrorCode, originalMessage: string): string {\n switch (code) {\n case HardwareErrorCode.PinInvalid:\n return `${originalMessage}. Please re-enter your PIN.`;\n case HardwareErrorCode.PinCancelled:\n return `${originalMessage}. PIN entry was cancelled.`;\n case HardwareErrorCode.DeviceBusy:\n return `${originalMessage}. The device is in use by another application. Close other wallet apps and try again.`;\n case HardwareErrorCode.DeviceDisconnected:\n return `${originalMessage}. Please reconnect the device and try again.`;\n case HardwareErrorCode.TransportNotAvailable:\n return `${originalMessage}. Ensure Trezor Bridge is installed and running, or connect via USB.`;\n case HardwareErrorCode.FirmwareTooOld:\n return `${originalMessage}. Please update your Trezor firmware via Trezor Suite.`;\n case HardwareErrorCode.DeviceNotInitialized:\n return `${originalMessage}. The device may need to be set up first via Trezor Suite.`;\n default:\n return originalMessage;\n }\n }\n\n /**\n * Generic batch call with progress reporting.\n * If any single call fails, returns the failure immediately.\n */\n private async batchCall<TParam, TResult>(\n params: TParam[],\n callFn: (p: TParam) => Promise<Response<TResult>>,\n onProgress?: ProgressCallback,\n ): Promise<Response<TResult[]>> {\n const results: TResult[] = [];\n for (let i = 0; i < params.length; i++) {\n const result = await callFn(params[i]);\n if (!result.success) {\n return result;\n }\n results.push(result.payload);\n onProgress?.({ index: i, total: params.length });\n }\n return success(results);\n }\n\n // ─── Hex formatting ──────────────────────────────────────\n\n /** Ensure a hex string has the `0x` prefix. */\n private ensure0x(hex: string): string {\n return hex.startsWith('0x') ? hex : `0x${hex}`;\n }\n\n /** Ensure a hex string is `0x`-prefixed and zero-padded to 64 hex chars (32 bytes). */\n private padHex64(hex: string): string {\n const stripped = hex.startsWith('0x') ? hex.slice(2) : hex;\n return `0x${stripped.padStart(64, '0')}`;\n }\n\n // ─── Event translation ────────────────────────────────────\n\n private deviceConnectHandler = (data: { device: ConnectorDevice }): void => {\n const deviceInfo = this.connectorDeviceToDeviceInfo(data.device);\n this._discoveredDevices.set(deviceInfo.connectId, deviceInfo);\n this.emitter.emit(DEVICE.CONNECT, {\n type: DEVICE.CONNECT,\n payload: deviceInfo,\n });\n };\n\n private deviceDisconnectHandler = (data: { connectId: string }): void => {\n this._discoveredDevices.delete(data.connectId);\n this.emitter.emit(DEVICE.DISCONNECT, {\n type: DEVICE.DISCONNECT,\n payload: { connectId: data.connectId },\n });\n };\n\n private uiRequestHandler = (data: { type: string; payload?: unknown }): void => {\n this.handleUiEvent(data);\n };\n\n private uiEventHandler = (data: { type: string; payload?: unknown }): void => {\n this.handleUiEvent(data);\n };\n\n private registerEventListeners(): void {\n this.connector.on('device-connect', this.deviceConnectHandler);\n this.connector.on('device-disconnect', this.deviceDisconnectHandler);\n this.connector.on('ui-request', this.uiRequestHandler);\n this.connector.on('ui-event', this.uiEventHandler);\n }\n\n private unregisterEventListeners(): void {\n this.connector.off('device-connect', this.deviceConnectHandler);\n this.connector.off('device-disconnect', this.deviceDisconnectHandler);\n this.connector.off('ui-request', this.uiRequestHandler);\n this.connector.off('ui-event', this.uiEventHandler);\n }\n\n private handleUiEvent(event: { type: string; payload?: unknown }): void {\n if (!event.type) return;\n\n const payload = event.payload as Record<string, unknown> | undefined;\n const devicePayload = (payload?.['device'] as Record<string, unknown>) ?? payload;\n const deviceInfo = devicePayload ? this.extractDeviceInfoFromPayload(devicePayload) : this.unknownDevice();\n\n switch (event.type) {\n case 'ui-request_pin':\n this.emitter.emit(UI_REQUEST.REQUEST_PIN, {\n type: UI_REQUEST.REQUEST_PIN,\n payload: { device: deviceInfo },\n });\n if (this._uiHandler?.onPinRequest) {\n this._uiHandler.onPinRequest(deviceInfo).then((pin) => {\n this.connector.uiResponse({\n type: 'receive-pin',\n payload: pin,\n });\n }).catch(() => {\n // User cancelled -- no response sent\n });\n }\n break;\n case 'ui-request_passphrase':\n this.emitter.emit(UI_REQUEST.REQUEST_PASSPHRASE, {\n type: UI_REQUEST.REQUEST_PASSPHRASE,\n payload: { device: deviceInfo },\n });\n if (this._uiHandler?.onPassphraseRequest) {\n this._uiHandler.onPassphraseRequest(deviceInfo).then((result) => {\n const response = typeof result === 'string'\n ? { passphrase: result, onDevice: false }\n : result ?? { passphrase: '', onDevice: false };\n if (response.onDevice) {\n this.connector.uiResponse({\n type: 'receive-passphrase',\n payload: {\n value: '',\n passphraseOnDevice: true,\n save: false,\n },\n });\n } else {\n this.connector.uiResponse({\n type: 'receive-passphrase',\n payload: {\n value: response.passphrase,\n passphraseOnDevice: false,\n save: false,\n },\n });\n }\n }).catch(() => {\n // User cancelled -- no response sent\n });\n }\n break;\n case 'ui-request_confirmation':\n this.emitter.emit(UI_REQUEST.REQUEST_BUTTON, {\n type: UI_REQUEST.REQUEST_BUTTON,\n payload: { device: deviceInfo },\n });\n break;\n }\n }\n\n private connectorDeviceToDeviceInfo(device: ConnectorDevice): DeviceInfo {\n return {\n vendor: 'trezor',\n model: device.model ?? 'unknown',\n firmwareVersion: '',\n deviceId: device.deviceId,\n connectId: device.connectId,\n label: device.name,\n connectionType: 'usb' as ConnectionType,\n };\n }\n\n private extractDeviceInfoFromPayload(payload: Record<string, unknown>): DeviceInfo {\n const features = payload['features'] as Record<string, unknown> | undefined;\n return {\n vendor: 'trezor',\n model: (features?.['model'] as string) ?? (payload['model'] as string) ?? 'unknown',\n firmwareVersion: features\n ? `${features['major_version'] ?? 0}.${features['minor_version'] ?? 0}.${features['patch_version'] ?? 0}`\n : '',\n deviceId: (features?.['device_id'] as string) ?? (payload['id'] as string) ?? '',\n connectId: (payload['path'] as string) ?? '',\n label: (features?.['label'] as string) ?? (payload['label'] as string),\n connectionType: 'usb' as ConnectionType,\n };\n }\n\n private unknownDevice(): DeviceInfo {\n return {\n vendor: 'trezor',\n model: 'unknown',\n firmwareVersion: '',\n deviceId: '',\n connectId: '',\n connectionType: 'usb',\n };\n }\n}\n","import { AbstractProxyClient } from '@bytezhang/hardware-transport-core';\nimport type { ITrezorConnect, TrezorConnectResponse } from './types';\n\n/**\n * Trezor method stubs on top of AbstractProxyClient.\n *\n * All cross-process Trezor proxy clients (Electron IPC, Extension messaging)\n * extend this class. They only need to implement:\n * - `sendCall()` — the transport channel\n * - `dispose()` / `cancel()` / `uiResponse()` — lifecycle\n *\n * The 11 TrezorConnect method stubs are defined here once.\n */\nexport abstract class TrezorProxyClient extends AbstractProxyClient implements ITrezorConnect {\n abstract dispose(): void;\n abstract cancel(reason?: string): void;\n abstract uiResponse(response: { type: string; payload: unknown }): void;\n\n // ─── TrezorConnect method stubs — all delegate to call() ────\n ethereumGetAddress(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('ethereumGetAddress', params) as Promise<TrezorConnectResponse>;\n }\n ethereumGetPublicKey(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('ethereumGetPublicKey', params) as Promise<TrezorConnectResponse>;\n }\n ethereumSignTransaction(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('ethereumSignTransaction', params) as Promise<TrezorConnectResponse>;\n }\n ethereumSignMessage(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('ethereumSignMessage', params) as Promise<TrezorConnectResponse>;\n }\n ethereumSignTypedData(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('ethereumSignTypedData', params) as Promise<TrezorConnectResponse>;\n }\n getAddress(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('getAddress', params) as Promise<TrezorConnectResponse>;\n }\n getPublicKey(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('getPublicKey', params) as Promise<TrezorConnectResponse>;\n }\n signTransaction(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('signTransaction', params) as Promise<TrezorConnectResponse>;\n }\n signMessage(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('signMessage', params) as Promise<TrezorConnectResponse>;\n }\n solanaGetAddress(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('solanaGetAddress', params) as Promise<TrezorConnectResponse>;\n }\n solanaSignTransaction(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('solanaSignTransaction', params) as Promise<TrezorConnectResponse>;\n }\n}\n"],"mappings":"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","names":[]}
package/dist/index.mjs CHANGED
@@ -126,6 +126,31 @@ var TrezorAdapter = class {
126
126
  const sessionId = this._sessions.get(connectId) ?? connectId;
127
127
  void this.connector.cancel(sessionId);
128
128
  }
129
+ // ─── Chain fingerprint ────────────────────────────────────
130
+ /**
131
+ * For Trezor, the chain fingerprint is the hardware device_id from firmware.
132
+ * Trezor has a persistent device identity, so no address derivation is needed.
133
+ */
134
+ async getChainFingerprint(connectId, deviceId, _chain) {
135
+ await this._ensureDevicePermission(connectId, deviceId);
136
+ const cached = this._discoveredDevices.get(connectId) ?? Array.from(this._discoveredDevices.values()).find(
137
+ (d) => d.deviceId === deviceId
138
+ );
139
+ if (cached?.deviceId) {
140
+ return success(cached.deviceId);
141
+ }
142
+ try {
143
+ const result = await this.connectorCall(connectId, "getFeatures", {});
144
+ if (result.device_id) {
145
+ return success(result.device_id);
146
+ }
147
+ } catch {
148
+ }
149
+ return failure(
150
+ HardwareErrorCode.DeviceNotFound,
151
+ "Could not determine Trezor device identity. Ensure the device is connected."
152
+ );
153
+ }
129
154
  // ─── EVM methods ──────────────────────────────────────────
130
155
  async evmGetAddress(connectId, _deviceId, params) {
131
156
  await this._ensureDevicePermission(connectId, _deviceId);
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/TrezorAdapter.ts","../src/TrezorProxyClient.ts"],"sourcesContent":["import {\n type IHardwareWallet,\n type IUiHandler,\n type IConnector,\n type ConnectorDevice,\n type ChainCapability,\n type DeviceEventListener,\n type ConnectionType,\n type DeviceInfo,\n type TransportType,\n type Response,\n type EvmGetAddressParams,\n type EvmAddress,\n type EvmGetPublicKeyParams,\n type EvmPublicKey,\n type EvmSignTxParams,\n type EvmSignedTx,\n type EvmSignMsgParams,\n type EvmSignTypedDataParams,\n type EvmSignature,\n type ProgressCallback,\n type BtcGetAddressParams,\n type BtcAddress,\n type BtcGetPublicKeyParams,\n type BtcPublicKey,\n type BtcSignTxParams,\n type BtcSignedTx,\n type BtcSignMsgParams,\n type BtcSignature,\n type SolGetAddressParams,\n type SolAddress,\n type SolGetPublicKeyParams,\n type SolPublicKey,\n type SolSignTxParams,\n type SolSignedTx,\n type SolSignMsgParams,\n type SolSignature,\n type HardwareEventMap,\n HardwareErrorCode,\n success,\n failure,\n DEVICE,\n UI_REQUEST,\n TypedEventEmitter,\n} from '@bytezhang/hardware-wallet-core';\n\n/**\n * Trezor hardware wallet adapter that delegates to an IConnector.\n *\n * This is a thin translation layer that:\n * - Accepts a pre-configured IConnector (transport decisions are made at connector creation time)\n * - Translates IHardwareWallet method calls to connector.call() invocations\n * - Maps connector results/errors to our Response<T> format with enriched error messages\n * - Translates connector events to HardwareEventMap events\n * - Integrates with IUiHandler for interactive flows (PIN, passphrase)\n */\nexport class TrezorAdapter implements IHardwareWallet {\n readonly vendor = 'trezor' as const;\n\n private readonly connector: IConnector;\n private readonly emitter = new TypedEventEmitter<HardwareEventMap>();\n\n private _uiHandler: Partial<IUiHandler> | null = null;\n\n // Device cache: tracks discovered devices from connector events\n private _discoveredDevices = new Map<string, DeviceInfo>();\n\n // Session tracking: maps connectId -> sessionId\n private _sessions = new Map<string, string>();\n\n constructor(connector: IConnector) {\n this.connector = connector;\n this.registerEventListeners();\n }\n\n // ─── Transport ──────────────────────────────────────────\n // Transport is decided at connector creation time. These methods\n // satisfy the IHardwareWallet interface with sensible defaults.\n\n get activeTransport(): TransportType | null {\n return 'usb';\n }\n\n getAvailableTransports(): TransportType[] {\n return ['usb'];\n }\n\n async switchTransport(_type: TransportType): Promise<void> {\n // Transport is fixed at connector creation time.\n // To switch transport, create a new TrezorAdapter with a different connector.\n }\n\n // ─── UI handler ────────────────────────────────────────────\n\n setUiHandler(handler: Partial<IUiHandler>): void {\n this._uiHandler = handler;\n }\n\n // ─── Lifecycle ────────────────────────────────────────────\n\n async init(_config?: unknown): Promise<void> {\n // Connector is injected via constructor, already initialized.\n // Nothing to do here.\n }\n\n async dispose(): Promise<void> {\n this.unregisterEventListeners();\n this.connector.reset();\n this._uiHandler = null;\n this._discoveredDevices.clear();\n this._sessions.clear();\n this.emitter.removeAllListeners();\n }\n\n // ─── Device management ────────────────────────────────────\n\n async searchDevices(): Promise<DeviceInfo[]> {\n await this._ensureDevicePermission();\n\n const devices = await this.connector.searchDevices();\n\n for (const d of devices) {\n if (d.connectId && !this._discoveredDevices.has(d.connectId)) {\n this._discoveredDevices.set(d.connectId, this.connectorDeviceToDeviceInfo(d));\n }\n }\n\n // If no devices found, ensure permission (no connectId = search context)\n if (this._discoveredDevices.size === 0) {\n await this._ensureDevicePermission();\n }\n\n return Array.from(this._discoveredDevices.values());\n }\n\n async connectDevice(connectId: string): Promise<Response<string>> {\n try {\n const session = await this.connector.connect(connectId);\n this._sessions.set(connectId, session.sessionId);\n\n // Update device cache with richer info from session\n if (session.deviceInfo) {\n this._discoveredDevices.set(connectId, session.deviceInfo);\n }\n\n return success(connectId);\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async disconnectDevice(connectId: string): Promise<void> {\n const sessionId = this._sessions.get(connectId);\n if (sessionId) {\n await this.connector.disconnect(sessionId);\n this._sessions.delete(connectId);\n }\n }\n\n async getDeviceInfo(\n connectId: string,\n deviceId: string,\n ): Promise<Response<DeviceInfo>> {\n await this._ensureDevicePermission(connectId, deviceId);\n\n // Look up the device in the cache populated by event handlers / searchDevices.\n // Try connectId first (the USB path), then fall back to scanning by deviceId.\n const cached =\n this._discoveredDevices.get(connectId) ??\n Array.from(this._discoveredDevices.values()).find(\n (d) => d.deviceId === deviceId,\n );\n\n if (cached) {\n return success(cached);\n }\n\n return failure(\n HardwareErrorCode.DeviceNotFound,\n 'Device not found in cache. Call searchDevices() or wait for a device-connected event first.',\n );\n }\n\n getSupportedChains(): ChainCapability[] {\n return ['evm', 'btc', 'sol'];\n }\n\n // ─── Event handling ───────────────────────────────────────\n\n on<K extends keyof HardwareEventMap>(event: K, listener: (event: HardwareEventMap[K]) => void): void;\n on(event: string, listener: DeviceEventListener): void;\n on(event: string, listener: (event: any) => void): void {\n this.emitter.on(event, listener);\n }\n\n off<K extends keyof HardwareEventMap>(event: K, listener: (event: HardwareEventMap[K]) => void): void;\n off(event: string, listener: DeviceEventListener): void;\n off(event: string, listener: (event: any) => void): void {\n this.emitter.off(event, listener);\n }\n\n cancel(connectId: string): void {\n const sessionId = this._sessions.get(connectId) ?? connectId;\n void this.connector.cancel(sessionId);\n }\n\n // ─── EVM methods ──────────────────────────────────────────\n\n async evmGetAddress(\n connectId: string,\n _deviceId: string,\n params: EvmGetAddressParams,\n ): Promise<Response<EvmAddress>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const result = await this.connectorCall(connectId, 'evmGetAddress', {\n path: params.path,\n showOnDevice: params.showOnDevice,\n chainId: params.chainId,\n }) as { address: string; path: string };\n\n return success({\n address: result.address,\n path: params.path,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async evmGetAddresses(\n connectId: string,\n deviceId: string,\n params: EvmGetAddressParams[],\n onProgress?: ProgressCallback,\n ): Promise<Response<EvmAddress[]>> {\n return this.batchCall(\n params,\n (p) => this.evmGetAddress(connectId, deviceId, p),\n onProgress,\n );\n }\n\n async evmGetPublicKey(\n connectId: string,\n _deviceId: string,\n params: EvmGetPublicKeyParams,\n ): Promise<Response<EvmPublicKey>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const result = await this.connectorCall(connectId, 'evmGetPublicKey', {\n path: params.path,\n showOnDevice: params.showOnDevice,\n }) as { publicKey: string; path: string };\n\n return success({\n publicKey: result.publicKey,\n path: params.path,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async evmSignTransaction(\n connectId: string,\n _deviceId: string,\n params: EvmSignTxParams,\n ): Promise<Response<EvmSignedTx>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const result = await this.connectorCall(connectId, 'evmSignTransaction', {\n path: params.path,\n transaction: {\n to: params.to,\n value: params.value,\n chainId: params.chainId,\n nonce: params.nonce,\n gasLimit: params.gasLimit,\n gasPrice: params.gasPrice,\n maxFeePerGas: params.maxFeePerGas,\n maxPriorityFeePerGas: params.maxPriorityFeePerGas,\n accessList: params.accessList,\n data: params.data,\n },\n }) as { v: string; r: string; s: string; serializedTx?: string };\n\n return success({\n v: this.ensure0x(result.v),\n r: this.padHex64(result.r),\n s: this.padHex64(result.s),\n serializedTx: result.serializedTx,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async evmSignMessage(\n connectId: string,\n _deviceId: string,\n params: EvmSignMsgParams,\n ): Promise<Response<EvmSignature>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const result = await this.connectorCall(connectId, 'evmSignMessage', {\n path: params.path,\n message: params.message,\n hex: params.hex,\n }) as { signature: string; address?: string };\n\n return success({\n signature: this.ensure0x(result.signature),\n address: result.address,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async evmSignTypedData(\n connectId: string,\n _deviceId: string,\n params: EvmSignTypedDataParams,\n ): Promise<Response<EvmSignature>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const callParams: Record<string, unknown> = {\n path: params.path,\n };\n\n if (params.mode !== 'hash') {\n callParams['mode'] = params.mode ?? 'full';\n callParams['data'] = params.data;\n callParams['metamaskV4Compat'] = params.metamaskV4Compat ?? true;\n } else {\n callParams['mode'] = 'hash';\n callParams['domainSeparatorHash'] = params.domainSeparatorHash;\n callParams['messageHash'] = params.messageHash;\n }\n\n const result = await this.connectorCall(connectId, 'evmSignTypedData', callParams) as {\n signature: string;\n address?: string;\n };\n\n return success({\n signature: this.ensure0x(result.signature),\n address: result.address,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n // ─── BTC methods ──────────────────────────────────────────\n\n async btcGetAddress(\n connectId: string,\n _deviceId: string,\n params: BtcGetAddressParams,\n ): Promise<Response<BtcAddress>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const result = await this.connectorCall(connectId, 'btcGetAddress', {\n path: params.path,\n coin: params.coin,\n showOnDevice: params.showOnDevice,\n scriptType: params.scriptType,\n }) as { address: string; path: string };\n\n return success({\n address: result.address,\n path: params.path,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async btcGetAddresses(\n connectId: string,\n deviceId: string,\n params: BtcGetAddressParams[],\n onProgress?: ProgressCallback,\n ): Promise<Response<BtcAddress[]>> {\n return this.batchCall(\n params,\n (p) => this.btcGetAddress(connectId, deviceId, p),\n onProgress,\n );\n }\n\n async btcGetPublicKey(\n connectId: string,\n _deviceId: string,\n params: BtcGetPublicKeyParams,\n ): Promise<Response<BtcPublicKey>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const result = await this.connectorCall(connectId, 'btcGetPublicKey', {\n path: params.path,\n coin: params.coin,\n showOnDevice: params.showOnDevice,\n }) as {\n xpub: string;\n publicKey: string;\n fingerprint: number;\n chainCode: string;\n path: string;\n depth: number;\n };\n\n return success({\n xpub: result.xpub,\n publicKey: result.publicKey,\n fingerprint: result.fingerprint,\n chainCode: result.chainCode,\n path: params.path,\n depth: result.depth,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async btcSignTransaction(\n connectId: string,\n _deviceId: string,\n params: BtcSignTxParams,\n ): Promise<Response<BtcSignedTx>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const result = await this.connectorCall(connectId, 'btcSignTransaction', {\n inputs: params.inputs ?? [],\n outputs: params.outputs ?? [],\n refTxs: params.refTxs,\n coin: params.coin,\n locktime: params.locktime,\n version: params.version,\n }) as { signatures: string[]; serializedTx: string; txid?: string };\n\n return success({\n signatures: result.signatures,\n serializedTx: result.serializedTx,\n txid: result.txid,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async btcSignMessage(\n connectId: string,\n _deviceId: string,\n params: BtcSignMsgParams,\n ): Promise<Response<BtcSignature>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const result = await this.connectorCall(connectId, 'btcSignMessage', {\n path: params.path,\n message: params.message,\n coin: params.coin,\n }) as { signature: string; address: string };\n\n return success({\n signature: result.signature,\n address: result.address,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async btcGetMasterFingerprint(\n connectId: string,\n _deviceId: string,\n ): Promise<Response<{ masterFingerprint: string }>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n // The parent fingerprint of a child of \"m\" IS the master fingerprint.\n // Query \"m/0'\" and read its `fingerprint` field (parent key fingerprint).\n const result = await this.connectorCall(connectId, 'btcGetPublicKey', {\n path: \"m/0'\",\n }) as { fingerprint: number };\n\n const fp = (result.fingerprint) >>> 0;\n const hex = fp.toString(16).padStart(8, '0');\n return success({ masterFingerprint: hex });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n // ─── Solana methods ───────────────────────────────────────\n\n async solGetAddress(\n connectId: string,\n _deviceId: string,\n params: SolGetAddressParams,\n ): Promise<Response<SolAddress>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const result = await this.connectorCall(connectId, 'solGetAddress', {\n path: params.path,\n showOnDevice: params.showOnDevice,\n }) as { address: string; path: string };\n\n return success({\n address: result.address,\n path: params.path,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async solGetAddresses(\n connectId: string,\n deviceId: string,\n params: SolGetAddressParams[],\n onProgress?: ProgressCallback,\n ): Promise<Response<SolAddress[]>> {\n return this.batchCall(\n params,\n (p) => this.solGetAddress(connectId, deviceId, p),\n onProgress,\n );\n }\n\n async solGetPublicKey(\n connectId: string,\n _deviceId: string,\n params: SolGetPublicKeyParams,\n ): Promise<Response<SolPublicKey>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n // Solana address IS the public key\n const result = await this.connectorCall(connectId, 'solGetAddress', {\n path: params.path,\n showOnDevice: params.showOnDevice,\n }) as { address: string; path: string };\n\n return success({\n publicKey: result.address,\n path: params.path,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async solSignTransaction(\n connectId: string,\n _deviceId: string,\n params: SolSignTxParams,\n ): Promise<Response<SolSignedTx>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const result = await this.connectorCall(connectId, 'solSignTransaction', {\n path: params.path,\n serializedTx: params.serializedTx,\n additionalInfo: params.additionalInfo,\n }) as { signature: string };\n\n return success({\n signature: result.signature,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async solSignMessage(\n _connectId: string,\n _deviceId: string,\n _params: SolSignMsgParams,\n ): Promise<Response<SolSignature>> {\n return failure(\n HardwareErrorCode.MethodNotSupported,\n 'Solana signMessage is not supported by Trezor Connect',\n );\n }\n\n // ─── Private helpers ──────────────────────────────────────\n\n /**\n * Call the connector with session resolution.\n * Looks up sessionId from connectId, falls back to connectId itself.\n */\n private async connectorCall(\n connectId: string,\n method: string,\n params: unknown,\n ): Promise<unknown> {\n const sessionId = this._sessions.get(connectId) ?? connectId;\n return this.connector.call(sessionId, method, params);\n }\n\n /**\n * Ensure device permission before proceeding.\n * - No connectId (searchDevices): check environment-level permission\n * - With connectId (business methods): check device-level permission\n * If not granted, calls onDevicePermission so the consumer can request access.\n */\n private async _ensureDevicePermission(connectId?: string, deviceId?: string): Promise<void> {\n const transportType: TransportType = 'usb';\n let granted = false;\n let context: Record<string, unknown> | undefined;\n\n if (this._uiHandler?.checkDevicePermission) {\n try {\n const result = await this._uiHandler.checkDevicePermission({ transportType, connectId, deviceId });\n granted = result.granted;\n context = result.context;\n } catch {\n granted = false;\n }\n }\n\n if (!granted) {\n try {\n await this._uiHandler?.onDevicePermission?.({ transportType, context });\n } catch {\n // UI handler cancelled or failed\n }\n }\n }\n\n /**\n * Convert a thrown error to a Response failure.\n * Parses TrezorConnect error strings to map to HardwareErrorCode values.\n */\n private errorToFailure<T>(err: unknown): Response<T> {\n const message = err instanceof Error ? err.message : String(err);\n const code = this.parseErrorCode(message);\n const enriched = this.enrichErrorMessage(code, message);\n return failure(code, enriched);\n }\n\n /**\n * Parse TrezorConnect error codes from error message strings.\n * The connector throws errors with messages like \"Trezor ethereumGetAddress failed: <error>\".\n * We also check for embedded code patterns.\n */\n private parseErrorCode(message: string): HardwareErrorCode {\n // Check for known error patterns in the message\n if (message.includes('Failure_ActionCancelled') || message.includes('Failure_Cancel')) {\n return HardwareErrorCode.UserRejected;\n }\n if (message.includes('Failure_PinInvalid') || message.includes('Failure_PinMismatch')) {\n return HardwareErrorCode.PinInvalid;\n }\n if (message.includes('Failure_PinCancelled')) {\n return HardwareErrorCode.PinCancelled;\n }\n if (message.includes('Failure_PassphraseRejected')) {\n return HardwareErrorCode.PassphraseRejected;\n }\n if (message.includes('Device_UsedElsewhere')) {\n return HardwareErrorCode.DeviceBusy;\n }\n if (message.includes('Device_NotFound')) {\n return HardwareErrorCode.DeviceNotFound;\n }\n if (message.includes('Device_InvalidState')) {\n return HardwareErrorCode.DeviceNotInitialized;\n }\n if (message.includes('Transport_Missing')) {\n return HardwareErrorCode.TransportNotAvailable;\n }\n if (message.includes('Transport_DeviceDisconnected')) {\n return HardwareErrorCode.DeviceDisconnected;\n }\n if (message.includes('Failure_FirmwareError')) {\n return HardwareErrorCode.FirmwareTooOld;\n }\n if (message.includes('Method_InvalidParameter') || message.includes('Method_InvalidParams')) {\n return HardwareErrorCode.InvalidParams;\n }\n if (message.includes('Method_NotAllowed')) {\n return HardwareErrorCode.MethodNotSupported;\n }\n return HardwareErrorCode.UnknownError;\n }\n\n /**\n * Enrich error messages with actionable recovery info for the caller.\n */\n private enrichErrorMessage(code: HardwareErrorCode, originalMessage: string): string {\n switch (code) {\n case HardwareErrorCode.PinInvalid:\n return `${originalMessage}. Please re-enter your PIN.`;\n case HardwareErrorCode.PinCancelled:\n return `${originalMessage}. PIN entry was cancelled.`;\n case HardwareErrorCode.DeviceBusy:\n return `${originalMessage}. The device is in use by another application. Close other wallet apps and try again.`;\n case HardwareErrorCode.DeviceDisconnected:\n return `${originalMessage}. Please reconnect the device and try again.`;\n case HardwareErrorCode.TransportNotAvailable:\n return `${originalMessage}. Ensure Trezor Bridge is installed and running, or connect via USB.`;\n case HardwareErrorCode.FirmwareTooOld:\n return `${originalMessage}. Please update your Trezor firmware via Trezor Suite.`;\n case HardwareErrorCode.DeviceNotInitialized:\n return `${originalMessage}. The device may need to be set up first via Trezor Suite.`;\n default:\n return originalMessage;\n }\n }\n\n /**\n * Generic batch call with progress reporting.\n * If any single call fails, returns the failure immediately.\n */\n private async batchCall<TParam, TResult>(\n params: TParam[],\n callFn: (p: TParam) => Promise<Response<TResult>>,\n onProgress?: ProgressCallback,\n ): Promise<Response<TResult[]>> {\n const results: TResult[] = [];\n for (let i = 0; i < params.length; i++) {\n const result = await callFn(params[i]);\n if (!result.success) {\n return result;\n }\n results.push(result.payload);\n onProgress?.({ index: i, total: params.length });\n }\n return success(results);\n }\n\n // ─── Hex formatting ──────────────────────────────────────\n\n /** Ensure a hex string has the `0x` prefix. */\n private ensure0x(hex: string): string {\n return hex.startsWith('0x') ? hex : `0x${hex}`;\n }\n\n /** Ensure a hex string is `0x`-prefixed and zero-padded to 64 hex chars (32 bytes). */\n private padHex64(hex: string): string {\n const stripped = hex.startsWith('0x') ? hex.slice(2) : hex;\n return `0x${stripped.padStart(64, '0')}`;\n }\n\n // ─── Event translation ────────────────────────────────────\n\n private deviceConnectHandler = (data: { device: ConnectorDevice }): void => {\n const deviceInfo = this.connectorDeviceToDeviceInfo(data.device);\n this._discoveredDevices.set(deviceInfo.connectId, deviceInfo);\n this.emitter.emit(DEVICE.CONNECT, {\n type: DEVICE.CONNECT,\n payload: deviceInfo,\n });\n };\n\n private deviceDisconnectHandler = (data: { connectId: string }): void => {\n this._discoveredDevices.delete(data.connectId);\n this.emitter.emit(DEVICE.DISCONNECT, {\n type: DEVICE.DISCONNECT,\n payload: { connectId: data.connectId },\n });\n };\n\n private uiRequestHandler = (data: { type: string; payload?: unknown }): void => {\n this.handleUiEvent(data);\n };\n\n private uiEventHandler = (data: { type: string; payload?: unknown }): void => {\n this.handleUiEvent(data);\n };\n\n private registerEventListeners(): void {\n this.connector.on('device-connect', this.deviceConnectHandler);\n this.connector.on('device-disconnect', this.deviceDisconnectHandler);\n this.connector.on('ui-request', this.uiRequestHandler);\n this.connector.on('ui-event', this.uiEventHandler);\n }\n\n private unregisterEventListeners(): void {\n this.connector.off('device-connect', this.deviceConnectHandler);\n this.connector.off('device-disconnect', this.deviceDisconnectHandler);\n this.connector.off('ui-request', this.uiRequestHandler);\n this.connector.off('ui-event', this.uiEventHandler);\n }\n\n private handleUiEvent(event: { type: string; payload?: unknown }): void {\n if (!event.type) return;\n\n const payload = event.payload as Record<string, unknown> | undefined;\n const devicePayload = (payload?.['device'] as Record<string, unknown>) ?? payload;\n const deviceInfo = devicePayload ? this.extractDeviceInfoFromPayload(devicePayload) : this.unknownDevice();\n\n switch (event.type) {\n case 'ui-request_pin':\n this.emitter.emit(UI_REQUEST.REQUEST_PIN, {\n type: UI_REQUEST.REQUEST_PIN,\n payload: { device: deviceInfo },\n });\n if (this._uiHandler?.onPinRequest) {\n this._uiHandler.onPinRequest(deviceInfo).then((pin) => {\n this.connector.uiResponse({\n type: 'receive-pin',\n payload: pin,\n });\n }).catch(() => {\n // User cancelled -- no response sent\n });\n }\n break;\n case 'ui-request_passphrase':\n this.emitter.emit(UI_REQUEST.REQUEST_PASSPHRASE, {\n type: UI_REQUEST.REQUEST_PASSPHRASE,\n payload: { device: deviceInfo },\n });\n if (this._uiHandler?.onPassphraseRequest) {\n this._uiHandler.onPassphraseRequest(deviceInfo).then((result) => {\n const response = typeof result === 'string'\n ? { passphrase: result, onDevice: false }\n : result ?? { passphrase: '', onDevice: false };\n if (response.onDevice) {\n this.connector.uiResponse({\n type: 'receive-passphrase',\n payload: {\n value: '',\n passphraseOnDevice: true,\n save: false,\n },\n });\n } else {\n this.connector.uiResponse({\n type: 'receive-passphrase',\n payload: {\n value: response.passphrase,\n passphraseOnDevice: false,\n save: false,\n },\n });\n }\n }).catch(() => {\n // User cancelled -- no response sent\n });\n }\n break;\n case 'ui-request_confirmation':\n this.emitter.emit(UI_REQUEST.REQUEST_BUTTON, {\n type: UI_REQUEST.REQUEST_BUTTON,\n payload: { device: deviceInfo },\n });\n break;\n }\n }\n\n private connectorDeviceToDeviceInfo(device: ConnectorDevice): DeviceInfo {\n return {\n vendor: 'trezor',\n model: device.model ?? 'unknown',\n firmwareVersion: '',\n deviceId: device.deviceId,\n connectId: device.connectId,\n label: device.name,\n connectionType: 'usb' as ConnectionType,\n };\n }\n\n private extractDeviceInfoFromPayload(payload: Record<string, unknown>): DeviceInfo {\n const features = payload['features'] as Record<string, unknown> | undefined;\n return {\n vendor: 'trezor',\n model: (features?.['model'] as string) ?? (payload['model'] as string) ?? 'unknown',\n firmwareVersion: features\n ? `${features['major_version'] ?? 0}.${features['minor_version'] ?? 0}.${features['patch_version'] ?? 0}`\n : '',\n deviceId: (features?.['device_id'] as string) ?? (payload['id'] as string) ?? '',\n connectId: (payload['path'] as string) ?? '',\n label: (features?.['label'] as string) ?? (payload['label'] as string),\n connectionType: 'usb' as ConnectionType,\n };\n }\n\n private unknownDevice(): DeviceInfo {\n return {\n vendor: 'trezor',\n model: 'unknown',\n firmwareVersion: '',\n deviceId: '',\n connectId: '',\n connectionType: 'usb',\n };\n }\n}\n","import { AbstractProxyClient } from '@bytezhang/hardware-transport-core';\nimport type { ITrezorConnect, TrezorConnectResponse } from './types';\n\n/**\n * Trezor method stubs on top of AbstractProxyClient.\n *\n * All cross-process Trezor proxy clients (Electron IPC, Extension messaging)\n * extend this class. They only need to implement:\n * - `sendCall()` — the transport channel\n * - `dispose()` / `cancel()` / `uiResponse()` — lifecycle\n *\n * The 11 TrezorConnect method stubs are defined here once.\n */\nexport abstract class TrezorProxyClient extends AbstractProxyClient implements ITrezorConnect {\n abstract dispose(): void;\n abstract cancel(reason?: string): void;\n abstract uiResponse(response: { type: string; payload: unknown }): void;\n\n // ─── TrezorConnect method stubs — all delegate to call() ────\n ethereumGetAddress(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('ethereumGetAddress', params) as Promise<TrezorConnectResponse>;\n }\n ethereumGetPublicKey(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('ethereumGetPublicKey', params) as Promise<TrezorConnectResponse>;\n }\n ethereumSignTransaction(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('ethereumSignTransaction', params) as Promise<TrezorConnectResponse>;\n }\n ethereumSignMessage(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('ethereumSignMessage', params) as Promise<TrezorConnectResponse>;\n }\n ethereumSignTypedData(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('ethereumSignTypedData', params) as Promise<TrezorConnectResponse>;\n }\n getAddress(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('getAddress', params) as Promise<TrezorConnectResponse>;\n }\n getPublicKey(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('getPublicKey', params) as Promise<TrezorConnectResponse>;\n }\n signTransaction(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('signTransaction', params) as Promise<TrezorConnectResponse>;\n }\n signMessage(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('signMessage', params) as Promise<TrezorConnectResponse>;\n }\n solanaGetAddress(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('solanaGetAddress', params) as Promise<TrezorConnectResponse>;\n }\n solanaSignTransaction(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('solanaSignTransaction', params) as Promise<TrezorConnectResponse>;\n }\n}\n"],"mappings":";AAAA;AAAA,EAsCE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAYA,IAAM,gBAAN,MAA+C;AAAA,EAcpD,YAAY,WAAuB;AAbnC,SAAS,SAAS;AAGlB,SAAiB,UAAU,IAAI,kBAAoC;AAEnE,SAAQ,aAAyC;AAGjD;AAAA,SAAQ,qBAAqB,oBAAI,IAAwB;AAGzD;AAAA,SAAQ,YAAY,oBAAI,IAAoB;AAsqB5C;AAAA,SAAQ,uBAAuB,CAAC,SAA4C;AAC1E,YAAM,aAAa,KAAK,4BAA4B,KAAK,MAAM;AAC/D,WAAK,mBAAmB,IAAI,WAAW,WAAW,UAAU;AAC5D,WAAK,QAAQ,KAAK,OAAO,SAAS;AAAA,QAChC,MAAM,OAAO;AAAA,QACb,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAEA,SAAQ,0BAA0B,CAAC,SAAsC;AACvE,WAAK,mBAAmB,OAAO,KAAK,SAAS;AAC7C,WAAK,QAAQ,KAAK,OAAO,YAAY;AAAA,QACnC,MAAM,OAAO;AAAA,QACb,SAAS,EAAE,WAAW,KAAK,UAAU;AAAA,MACvC,CAAC;AAAA,IACH;AAEA,SAAQ,mBAAmB,CAAC,SAAoD;AAC9E,WAAK,cAAc,IAAI;AAAA,IACzB;AAEA,SAAQ,iBAAiB,CAAC,SAAoD;AAC5E,WAAK,cAAc,IAAI;AAAA,IACzB;AA1rBE,SAAK,YAAY;AACjB,SAAK,uBAAuB;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,kBAAwC;AAC1C,WAAO;AAAA,EACT;AAAA,EAEA,yBAA0C;AACxC,WAAO,CAAC,KAAK;AAAA,EACf;AAAA,EAEA,MAAM,gBAAgB,OAAqC;AAAA,EAG3D;AAAA;AAAA,EAIA,aAAa,SAAoC;AAC/C,SAAK,aAAa;AAAA,EACpB;AAAA;AAAA,EAIA,MAAM,KAAK,SAAkC;AAAA,EAG7C;AAAA,EAEA,MAAM,UAAyB;AAC7B,SAAK,yBAAyB;AAC9B,SAAK,UAAU,MAAM;AACrB,SAAK,aAAa;AAClB,SAAK,mBAAmB,MAAM;AAC9B,SAAK,UAAU,MAAM;AACrB,SAAK,QAAQ,mBAAmB;AAAA,EAClC;AAAA;AAAA,EAIA,MAAM,gBAAuC;AAC3C,UAAM,KAAK,wBAAwB;AAEnC,UAAM,UAAU,MAAM,KAAK,UAAU,cAAc;AAEnD,eAAW,KAAK,SAAS;AACvB,UAAI,EAAE,aAAa,CAAC,KAAK,mBAAmB,IAAI,EAAE,SAAS,GAAG;AAC5D,aAAK,mBAAmB,IAAI,EAAE,WAAW,KAAK,4BAA4B,CAAC,CAAC;AAAA,MAC9E;AAAA,IACF;AAGA,QAAI,KAAK,mBAAmB,SAAS,GAAG;AACtC,YAAM,KAAK,wBAAwB;AAAA,IACrC;AAEA,WAAO,MAAM,KAAK,KAAK,mBAAmB,OAAO,CAAC;AAAA,EACpD;AAAA,EAEA,MAAM,cAAc,WAA8C;AAChE,QAAI;AACF,YAAM,UAAU,MAAM,KAAK,UAAU,QAAQ,SAAS;AACtD,WAAK,UAAU,IAAI,WAAW,QAAQ,SAAS;AAG/C,UAAI,QAAQ,YAAY;AACtB,aAAK,mBAAmB,IAAI,WAAW,QAAQ,UAAU;AAAA,MAC3D;AAEA,aAAO,QAAQ,SAAS;AAAA,IAC1B,SAAS,KAAK;AACZ,aAAO,KAAK,eAAe,GAAG;AAAA,IAChC;AAAA,EACF;AAAA,EAEA,MAAM,iBAAiB,WAAkC;AACvD,UAAM,YAAY,KAAK,UAAU,IAAI,SAAS;AAC9C,QAAI,WAAW;AACb,YAAM,KAAK,UAAU,WAAW,SAAS;AACzC,WAAK,UAAU,OAAO,SAAS;AAAA,IACjC;AAAA,EACF;AAAA,EAEA,MAAM,cACJ,WACA,UAC+B;AAC/B,UAAM,KAAK,wBAAwB,WAAW,QAAQ;AAItD,UAAM,SACJ,KAAK,mBAAmB,IAAI,SAAS,KACrC,MAAM,KAAK,KAAK,mBAAmB,OAAO,CAAC,EAAE;AAAA,MAC3C,CAAC,MAAM,EAAE,aAAa;AAAA,IACxB;AAEF,QAAI,QAAQ;AACV,aAAO,QAAQ,MAAM;AAAA,IACvB;AAEA,WAAO;AAAA,MACL,kBAAkB;AAAA,MAClB;AAAA,IACF;AAAA,EACF;AAAA,EAEA,qBAAwC;AACtC,WAAO,CAAC,OAAO,OAAO,KAAK;AAAA,EAC7B;AAAA,EAMA,GAAG,OAAe,UAAsC;AACtD,SAAK,QAAQ,GAAG,OAAO,QAAQ;AAAA,EACjC;AAAA,EAIA,IAAI,OAAe,UAAsC;AACvD,SAAK,QAAQ,IAAI,OAAO,QAAQ;AAAA,EAClC;AAAA,EAEA,OAAO,WAAyB;AAC9B,UAAM,YAAY,KAAK,UAAU,IAAI,SAAS,KAAK;AACnD,SAAK,KAAK,UAAU,OAAO,SAAS;AAAA,EACtC;AAAA;AAAA,EAIA,MAAM,cACJ,WACA,WACA,QAC+B;AAC/B,UAAM,KAAK,wBAAwB,WAAW,SAAS;AACvD,QAAI;AACF,YAAM,SAAS,MAAM,KAAK,cAAc,WAAW,iBAAiB;AAAA,QAClE,MAAM,OAAO;AAAA,QACb,cAAc,OAAO;AAAA,QACrB,SAAS,OAAO;AAAA,MAClB,CAAC;AAED,aAAO,QAAQ;AAAA,QACb,SAAS,OAAO;AAAA,QAChB,MAAM,OAAO;AAAA,MACf,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,aAAO,KAAK,eAAe,GAAG;AAAA,IAChC;AAAA,EACF;AAAA,EAEA,MAAM,gBACJ,WACA,UACA,QACA,YACiC;AACjC,WAAO,KAAK;AAAA,MACV;AAAA,MACA,CAAC,MAAM,KAAK,cAAc,WAAW,UAAU,CAAC;AAAA,MAChD;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,gBACJ,WACA,WACA,QACiC;AACjC,UAAM,KAAK,wBAAwB,WAAW,SAAS;AACvD,QAAI;AACF,YAAM,SAAS,MAAM,KAAK,cAAc,WAAW,mBAAmB;AAAA,QACpE,MAAM,OAAO;AAAA,QACb,cAAc,OAAO;AAAA,MACvB,CAAC;AAED,aAAO,QAAQ;AAAA,QACb,WAAW,OAAO;AAAA,QAClB,MAAM,OAAO;AAAA,MACf,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,aAAO,KAAK,eAAe,GAAG;AAAA,IAChC;AAAA,EACF;AAAA,EAEA,MAAM,mBACJ,WACA,WACA,QACgC;AAChC,UAAM,KAAK,wBAAwB,WAAW,SAAS;AACvD,QAAI;AACF,YAAM,SAAS,MAAM,KAAK,cAAc,WAAW,sBAAsB;AAAA,QACvE,MAAM,OAAO;AAAA,QACb,aAAa;AAAA,UACX,IAAI,OAAO;AAAA,UACX,OAAO,OAAO;AAAA,UACd,SAAS,OAAO;AAAA,UAChB,OAAO,OAAO;AAAA,UACd,UAAU,OAAO;AAAA,UACjB,UAAU,OAAO;AAAA,UACjB,cAAc,OAAO;AAAA,UACrB,sBAAsB,OAAO;AAAA,UAC7B,YAAY,OAAO;AAAA,UACnB,MAAM,OAAO;AAAA,QACf;AAAA,MACF,CAAC;AAED,aAAO,QAAQ;AAAA,QACb,GAAG,KAAK,SAAS,OAAO,CAAC;AAAA,QACzB,GAAG,KAAK,SAAS,OAAO,CAAC;AAAA,QACzB,GAAG,KAAK,SAAS,OAAO,CAAC;AAAA,QACzB,cAAc,OAAO;AAAA,MACvB,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,aAAO,KAAK,eAAe,GAAG;AAAA,IAChC;AAAA,EACF;AAAA,EAEA,MAAM,eACJ,WACA,WACA,QACiC;AACjC,UAAM,KAAK,wBAAwB,WAAW,SAAS;AACvD,QAAI;AACF,YAAM,SAAS,MAAM,KAAK,cAAc,WAAW,kBAAkB;AAAA,QACnE,MAAM,OAAO;AAAA,QACb,SAAS,OAAO;AAAA,QAChB,KAAK,OAAO;AAAA,MACd,CAAC;AAED,aAAO,QAAQ;AAAA,QACb,WAAW,KAAK,SAAS,OAAO,SAAS;AAAA,QACzC,SAAS,OAAO;AAAA,MAClB,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,aAAO,KAAK,eAAe,GAAG;AAAA,IAChC;AAAA,EACF;AAAA,EAEA,MAAM,iBACJ,WACA,WACA,QACiC;AACjC,UAAM,KAAK,wBAAwB,WAAW,SAAS;AACvD,QAAI;AACF,YAAM,aAAsC;AAAA,QAC1C,MAAM,OAAO;AAAA,MACf;AAEA,UAAI,OAAO,SAAS,QAAQ;AAC1B,mBAAW,MAAM,IAAI,OAAO,QAAQ;AACpC,mBAAW,MAAM,IAAI,OAAO;AAC5B,mBAAW,kBAAkB,IAAI,OAAO,oBAAoB;AAAA,MAC9D,OAAO;AACL,mBAAW,MAAM,IAAI;AACrB,mBAAW,qBAAqB,IAAI,OAAO;AAC3C,mBAAW,aAAa,IAAI,OAAO;AAAA,MACrC;AAEA,YAAM,SAAS,MAAM,KAAK,cAAc,WAAW,oBAAoB,UAAU;AAKjF,aAAO,QAAQ;AAAA,QACb,WAAW,KAAK,SAAS,OAAO,SAAS;AAAA,QACzC,SAAS,OAAO;AAAA,MAClB,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,aAAO,KAAK,eAAe,GAAG;AAAA,IAChC;AAAA,EACF;AAAA;AAAA,EAIA,MAAM,cACJ,WACA,WACA,QAC+B;AAC/B,UAAM,KAAK,wBAAwB,WAAW,SAAS;AACvD,QAAI;AACF,YAAM,SAAS,MAAM,KAAK,cAAc,WAAW,iBAAiB;AAAA,QAClE,MAAM,OAAO;AAAA,QACb,MAAM,OAAO;AAAA,QACb,cAAc,OAAO;AAAA,QACrB,YAAY,OAAO;AAAA,MACrB,CAAC;AAED,aAAO,QAAQ;AAAA,QACb,SAAS,OAAO;AAAA,QAChB,MAAM,OAAO;AAAA,MACf,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,aAAO,KAAK,eAAe,GAAG;AAAA,IAChC;AAAA,EACF;AAAA,EAEA,MAAM,gBACJ,WACA,UACA,QACA,YACiC;AACjC,WAAO,KAAK;AAAA,MACV;AAAA,MACA,CAAC,MAAM,KAAK,cAAc,WAAW,UAAU,CAAC;AAAA,MAChD;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,gBACJ,WACA,WACA,QACiC;AACjC,UAAM,KAAK,wBAAwB,WAAW,SAAS;AACvD,QAAI;AACF,YAAM,SAAS,MAAM,KAAK,cAAc,WAAW,mBAAmB;AAAA,QACpE,MAAM,OAAO;AAAA,QACb,MAAM,OAAO;AAAA,QACb,cAAc,OAAO;AAAA,MACvB,CAAC;AASD,aAAO,QAAQ;AAAA,QACb,MAAM,OAAO;AAAA,QACb,WAAW,OAAO;AAAA,QAClB,aAAa,OAAO;AAAA,QACpB,WAAW,OAAO;AAAA,QAClB,MAAM,OAAO;AAAA,QACb,OAAO,OAAO;AAAA,MAChB,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,aAAO,KAAK,eAAe,GAAG;AAAA,IAChC;AAAA,EACF;AAAA,EAEA,MAAM,mBACJ,WACA,WACA,QACgC;AAChC,UAAM,KAAK,wBAAwB,WAAW,SAAS;AACvD,QAAI;AACF,YAAM,SAAS,MAAM,KAAK,cAAc,WAAW,sBAAsB;AAAA,QACvE,QAAQ,OAAO,UAAU,CAAC;AAAA,QAC1B,SAAS,OAAO,WAAW,CAAC;AAAA,QAC5B,QAAQ,OAAO;AAAA,QACf,MAAM,OAAO;AAAA,QACb,UAAU,OAAO;AAAA,QACjB,SAAS,OAAO;AAAA,MAClB,CAAC;AAED,aAAO,QAAQ;AAAA,QACb,YAAY,OAAO;AAAA,QACnB,cAAc,OAAO;AAAA,QACrB,MAAM,OAAO;AAAA,MACf,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,aAAO,KAAK,eAAe,GAAG;AAAA,IAChC;AAAA,EACF;AAAA,EAEA,MAAM,eACJ,WACA,WACA,QACiC;AACjC,UAAM,KAAK,wBAAwB,WAAW,SAAS;AACvD,QAAI;AACF,YAAM,SAAS,MAAM,KAAK,cAAc,WAAW,kBAAkB;AAAA,QACnE,MAAM,OAAO;AAAA,QACb,SAAS,OAAO;AAAA,QAChB,MAAM,OAAO;AAAA,MACf,CAAC;AAED,aAAO,QAAQ;AAAA,QACb,WAAW,OAAO;AAAA,QAClB,SAAS,OAAO;AAAA,MAClB,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,aAAO,KAAK,eAAe,GAAG;AAAA,IAChC;AAAA,EACF;AAAA,EAEA,MAAM,wBACJ,WACA,WACkD;AAClD,UAAM,KAAK,wBAAwB,WAAW,SAAS;AACvD,QAAI;AAGF,YAAM,SAAS,MAAM,KAAK,cAAc,WAAW,mBAAmB;AAAA,QACpE,MAAM;AAAA,MACR,CAAC;AAED,YAAM,KAAM,OAAO,gBAAiB;AACpC,YAAM,MAAM,GAAG,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG;AAC3C,aAAO,QAAQ,EAAE,mBAAmB,IAAI,CAAC;AAAA,IAC3C,SAAS,KAAK;AACZ,aAAO,KAAK,eAAe,GAAG;AAAA,IAChC;AAAA,EACF;AAAA;AAAA,EAIA,MAAM,cACJ,WACA,WACA,QAC+B;AAC/B,UAAM,KAAK,wBAAwB,WAAW,SAAS;AACvD,QAAI;AACF,YAAM,SAAS,MAAM,KAAK,cAAc,WAAW,iBAAiB;AAAA,QAClE,MAAM,OAAO;AAAA,QACb,cAAc,OAAO;AAAA,MACvB,CAAC;AAED,aAAO,QAAQ;AAAA,QACb,SAAS,OAAO;AAAA,QAChB,MAAM,OAAO;AAAA,MACf,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,aAAO,KAAK,eAAe,GAAG;AAAA,IAChC;AAAA,EACF;AAAA,EAEA,MAAM,gBACJ,WACA,UACA,QACA,YACiC;AACjC,WAAO,KAAK;AAAA,MACV;AAAA,MACA,CAAC,MAAM,KAAK,cAAc,WAAW,UAAU,CAAC;AAAA,MAChD;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,gBACJ,WACA,WACA,QACiC;AACjC,UAAM,KAAK,wBAAwB,WAAW,SAAS;AACvD,QAAI;AAEF,YAAM,SAAS,MAAM,KAAK,cAAc,WAAW,iBAAiB;AAAA,QAClE,MAAM,OAAO;AAAA,QACb,cAAc,OAAO;AAAA,MACvB,CAAC;AAED,aAAO,QAAQ;AAAA,QACb,WAAW,OAAO;AAAA,QAClB,MAAM,OAAO;AAAA,MACf,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,aAAO,KAAK,eAAe,GAAG;AAAA,IAChC;AAAA,EACF;AAAA,EAEA,MAAM,mBACJ,WACA,WACA,QACgC;AAChC,UAAM,KAAK,wBAAwB,WAAW,SAAS;AACvD,QAAI;AACF,YAAM,SAAS,MAAM,KAAK,cAAc,WAAW,sBAAsB;AAAA,QACvE,MAAM,OAAO;AAAA,QACb,cAAc,OAAO;AAAA,QACrB,gBAAgB,OAAO;AAAA,MACzB,CAAC;AAED,aAAO,QAAQ;AAAA,QACb,WAAW,OAAO;AAAA,MACpB,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,aAAO,KAAK,eAAe,GAAG;AAAA,IAChC;AAAA,EACF;AAAA,EAEA,MAAM,eACJ,YACA,WACA,SACiC;AACjC,WAAO;AAAA,MACL,kBAAkB;AAAA,MAClB;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,cACZ,WACA,QACA,QACkB;AAClB,UAAM,YAAY,KAAK,UAAU,IAAI,SAAS,KAAK;AACnD,WAAO,KAAK,UAAU,KAAK,WAAW,QAAQ,MAAM;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,wBAAwB,WAAoB,UAAkC;AAC1F,UAAM,gBAA+B;AACrC,QAAI,UAAU;AACd,QAAI;AAEJ,QAAI,KAAK,YAAY,uBAAuB;AAC1C,UAAI;AACF,cAAM,SAAS,MAAM,KAAK,WAAW,sBAAsB,EAAE,eAAe,WAAW,SAAS,CAAC;AACjG,kBAAU,OAAO;AACjB,kBAAU,OAAO;AAAA,MACnB,QAAQ;AACN,kBAAU;AAAA,MACZ;AAAA,IACF;AAEA,QAAI,CAAC,SAAS;AACZ,UAAI;AACF,cAAM,KAAK,YAAY,qBAAqB,EAAE,eAAe,QAAQ,CAAC;AAAA,MACxE,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,eAAkB,KAA2B;AACnD,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,UAAM,OAAO,KAAK,eAAe,OAAO;AACxC,UAAM,WAAW,KAAK,mBAAmB,MAAM,OAAO;AACtD,WAAO,QAAQ,MAAM,QAAQ;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,eAAe,SAAoC;AAEzD,QAAI,QAAQ,SAAS,yBAAyB,KAAK,QAAQ,SAAS,gBAAgB,GAAG;AACrF,aAAO,kBAAkB;AAAA,IAC3B;AACA,QAAI,QAAQ,SAAS,oBAAoB,KAAK,QAAQ,SAAS,qBAAqB,GAAG;AACrF,aAAO,kBAAkB;AAAA,IAC3B;AACA,QAAI,QAAQ,SAAS,sBAAsB,GAAG;AAC5C,aAAO,kBAAkB;AAAA,IAC3B;AACA,QAAI,QAAQ,SAAS,4BAA4B,GAAG;AAClD,aAAO,kBAAkB;AAAA,IAC3B;AACA,QAAI,QAAQ,SAAS,sBAAsB,GAAG;AAC5C,aAAO,kBAAkB;AAAA,IAC3B;AACA,QAAI,QAAQ,SAAS,iBAAiB,GAAG;AACvC,aAAO,kBAAkB;AAAA,IAC3B;AACA,QAAI,QAAQ,SAAS,qBAAqB,GAAG;AAC3C,aAAO,kBAAkB;AAAA,IAC3B;AACA,QAAI,QAAQ,SAAS,mBAAmB,GAAG;AACzC,aAAO,kBAAkB;AAAA,IAC3B;AACA,QAAI,QAAQ,SAAS,8BAA8B,GAAG;AACpD,aAAO,kBAAkB;AAAA,IAC3B;AACA,QAAI,QAAQ,SAAS,uBAAuB,GAAG;AAC7C,aAAO,kBAAkB;AAAA,IAC3B;AACA,QAAI,QAAQ,SAAS,yBAAyB,KAAK,QAAQ,SAAS,sBAAsB,GAAG;AAC3F,aAAO,kBAAkB;AAAA,IAC3B;AACA,QAAI,QAAQ,SAAS,mBAAmB,GAAG;AACzC,aAAO,kBAAkB;AAAA,IAC3B;AACA,WAAO,kBAAkB;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAKQ,mBAAmB,MAAyB,iBAAiC;AACnF,YAAQ,MAAM;AAAA,MACZ,KAAK,kBAAkB;AACrB,eAAO,GAAG,eAAe;AAAA,MAC3B,KAAK,kBAAkB;AACrB,eAAO,GAAG,eAAe;AAAA,MAC3B,KAAK,kBAAkB;AACrB,eAAO,GAAG,eAAe;AAAA,MAC3B,KAAK,kBAAkB;AACrB,eAAO,GAAG,eAAe;AAAA,MAC3B,KAAK,kBAAkB;AACrB,eAAO,GAAG,eAAe;AAAA,MAC3B,KAAK,kBAAkB;AACrB,eAAO,GAAG,eAAe;AAAA,MAC3B,KAAK,kBAAkB;AACrB,eAAO,GAAG,eAAe;AAAA,MAC3B;AACE,eAAO;AAAA,IACX;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,UACZ,QACA,QACA,YAC8B;AAC9B,UAAM,UAAqB,CAAC;AAC5B,aAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,YAAM,SAAS,MAAM,OAAO,OAAO,CAAC,CAAC;AACrC,UAAI,CAAC,OAAO,SAAS;AACnB,eAAO;AAAA,MACT;AACA,cAAQ,KAAK,OAAO,OAAO;AAC3B,mBAAa,EAAE,OAAO,GAAG,OAAO,OAAO,OAAO,CAAC;AAAA,IACjD;AACA,WAAO,QAAQ,OAAO;AAAA,EACxB;AAAA;AAAA;AAAA,EAKQ,SAAS,KAAqB;AACpC,WAAO,IAAI,WAAW,IAAI,IAAI,MAAM,KAAK,GAAG;AAAA,EAC9C;AAAA;AAAA,EAGQ,SAAS,KAAqB;AACpC,UAAM,WAAW,IAAI,WAAW,IAAI,IAAI,IAAI,MAAM,CAAC,IAAI;AACvD,WAAO,KAAK,SAAS,SAAS,IAAI,GAAG,CAAC;AAAA,EACxC;AAAA,EA6BQ,yBAA+B;AACrC,SAAK,UAAU,GAAG,kBAAkB,KAAK,oBAAoB;AAC7D,SAAK,UAAU,GAAG,qBAAqB,KAAK,uBAAuB;AACnE,SAAK,UAAU,GAAG,cAAc,KAAK,gBAAgB;AACrD,SAAK,UAAU,GAAG,YAAY,KAAK,cAAc;AAAA,EACnD;AAAA,EAEQ,2BAAiC;AACvC,SAAK,UAAU,IAAI,kBAAkB,KAAK,oBAAoB;AAC9D,SAAK,UAAU,IAAI,qBAAqB,KAAK,uBAAuB;AACpE,SAAK,UAAU,IAAI,cAAc,KAAK,gBAAgB;AACtD,SAAK,UAAU,IAAI,YAAY,KAAK,cAAc;AAAA,EACpD;AAAA,EAEQ,cAAc,OAAkD;AACtE,QAAI,CAAC,MAAM,KAAM;AAEjB,UAAM,UAAU,MAAM;AACtB,UAAM,gBAAiB,UAAU,QAAQ,KAAiC;AAC1E,UAAM,aAAa,gBAAgB,KAAK,6BAA6B,aAAa,IAAI,KAAK,cAAc;AAEzG,YAAQ,MAAM,MAAM;AAAA,MAClB,KAAK;AACH,aAAK,QAAQ,KAAK,WAAW,aAAa;AAAA,UACxC,MAAM,WAAW;AAAA,UACjB,SAAS,EAAE,QAAQ,WAAW;AAAA,QAChC,CAAC;AACD,YAAI,KAAK,YAAY,cAAc;AACjC,eAAK,WAAW,aAAa,UAAU,EAAE,KAAK,CAAC,QAAQ;AACrD,iBAAK,UAAU,WAAW;AAAA,cACxB,MAAM;AAAA,cACN,SAAS;AAAA,YACX,CAAC;AAAA,UACH,CAAC,EAAE,MAAM,MAAM;AAAA,UAEf,CAAC;AAAA,QACH;AACA;AAAA,MACF,KAAK;AACH,aAAK,QAAQ,KAAK,WAAW,oBAAoB;AAAA,UAC/C,MAAM,WAAW;AAAA,UACjB,SAAS,EAAE,QAAQ,WAAW;AAAA,QAChC,CAAC;AACD,YAAI,KAAK,YAAY,qBAAqB;AACxC,eAAK,WAAW,oBAAoB,UAAU,EAAE,KAAK,CAAC,WAAW;AAC/D,kBAAM,WAAW,OAAO,WAAW,WAC/B,EAAE,YAAY,QAAQ,UAAU,MAAM,IACtC,UAAU,EAAE,YAAY,IAAI,UAAU,MAAM;AAChD,gBAAI,SAAS,UAAU;AACrB,mBAAK,UAAU,WAAW;AAAA,gBACxB,MAAM;AAAA,gBACN,SAAS;AAAA,kBACP,OAAO;AAAA,kBACP,oBAAoB;AAAA,kBACpB,MAAM;AAAA,gBACR;AAAA,cACF,CAAC;AAAA,YACH,OAAO;AACL,mBAAK,UAAU,WAAW;AAAA,gBACxB,MAAM;AAAA,gBACN,SAAS;AAAA,kBACP,OAAO,SAAS;AAAA,kBAChB,oBAAoB;AAAA,kBACpB,MAAM;AAAA,gBACR;AAAA,cACF,CAAC;AAAA,YACH;AAAA,UACF,CAAC,EAAE,MAAM,MAAM;AAAA,UAEf,CAAC;AAAA,QACH;AACA;AAAA,MACF,KAAK;AACH,aAAK,QAAQ,KAAK,WAAW,gBAAgB;AAAA,UAC3C,MAAM,WAAW;AAAA,UACjB,SAAS,EAAE,QAAQ,WAAW;AAAA,QAChC,CAAC;AACD;AAAA,IACJ;AAAA,EACF;AAAA,EAEQ,4BAA4B,QAAqC;AACvE,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,OAAO,OAAO,SAAS;AAAA,MACvB,iBAAiB;AAAA,MACjB,UAAU,OAAO;AAAA,MACjB,WAAW,OAAO;AAAA,MAClB,OAAO,OAAO;AAAA,MACd,gBAAgB;AAAA,IAClB;AAAA,EACF;AAAA,EAEQ,6BAA6B,SAA8C;AACjF,UAAM,WAAW,QAAQ,UAAU;AACnC,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,OAAQ,WAAW,OAAO,KAAiB,QAAQ,OAAO,KAAgB;AAAA,MAC1E,iBAAiB,WACb,GAAG,SAAS,eAAe,KAAK,CAAC,IAAI,SAAS,eAAe,KAAK,CAAC,IAAI,SAAS,eAAe,KAAK,CAAC,KACrG;AAAA,MACJ,UAAW,WAAW,WAAW,KAAiB,QAAQ,IAAI,KAAgB;AAAA,MAC9E,WAAY,QAAQ,MAAM,KAAgB;AAAA,MAC1C,OAAQ,WAAW,OAAO,KAAiB,QAAQ,OAAO;AAAA,MAC1D,gBAAgB;AAAA,IAClB;AAAA,EACF;AAAA,EAEQ,gBAA4B;AAClC,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,iBAAiB;AAAA,MACjB,UAAU;AAAA,MACV,WAAW;AAAA,MACX,gBAAgB;AAAA,IAClB;AAAA,EACF;AACF;;;ACz3BA,SAAS,2BAA2B;AAa7B,IAAe,oBAAf,cAAyC,oBAA8C;AAAA;AAAA,EAM5F,mBAAmB,QAAiE;AAClF,WAAO,KAAK,KAAK,sBAAsB,MAAM;AAAA,EAC/C;AAAA,EACA,qBAAqB,QAAiE;AACpF,WAAO,KAAK,KAAK,wBAAwB,MAAM;AAAA,EACjD;AAAA,EACA,wBAAwB,QAAiE;AACvF,WAAO,KAAK,KAAK,2BAA2B,MAAM;AAAA,EACpD;AAAA,EACA,oBAAoB,QAAiE;AACnF,WAAO,KAAK,KAAK,uBAAuB,MAAM;AAAA,EAChD;AAAA,EACA,sBAAsB,QAAiE;AACrF,WAAO,KAAK,KAAK,yBAAyB,MAAM;AAAA,EAClD;AAAA,EACA,WAAW,QAAiE;AAC1E,WAAO,KAAK,KAAK,cAAc,MAAM;AAAA,EACvC;AAAA,EACA,aAAa,QAAiE;AAC5E,WAAO,KAAK,KAAK,gBAAgB,MAAM;AAAA,EACzC;AAAA,EACA,gBAAgB,QAAiE;AAC/E,WAAO,KAAK,KAAK,mBAAmB,MAAM;AAAA,EAC5C;AAAA,EACA,YAAY,QAAiE;AAC3E,WAAO,KAAK,KAAK,eAAe,MAAM;AAAA,EACxC;AAAA,EACA,iBAAiB,QAAiE;AAChF,WAAO,KAAK,KAAK,oBAAoB,MAAM;AAAA,EAC7C;AAAA,EACA,sBAAsB,QAAiE;AACrF,WAAO,KAAK,KAAK,yBAAyB,MAAM;AAAA,EAClD;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/TrezorAdapter.ts","../src/TrezorProxyClient.ts"],"sourcesContent":["import {\n type IHardwareWallet,\n type IUiHandler,\n type IConnector,\n type ConnectorDevice,\n type ChainCapability,\n type DeviceEventListener,\n type ConnectionType,\n type DeviceInfo,\n type TransportType,\n type Response,\n type EvmGetAddressParams,\n type EvmAddress,\n type EvmGetPublicKeyParams,\n type EvmPublicKey,\n type EvmSignTxParams,\n type EvmSignedTx,\n type EvmSignMsgParams,\n type EvmSignTypedDataParams,\n type EvmSignature,\n type ProgressCallback,\n type BtcGetAddressParams,\n type BtcAddress,\n type BtcGetPublicKeyParams,\n type BtcPublicKey,\n type BtcSignTxParams,\n type BtcSignedTx,\n type BtcSignMsgParams,\n type BtcSignature,\n type SolGetAddressParams,\n type SolAddress,\n type SolGetPublicKeyParams,\n type SolPublicKey,\n type SolSignTxParams,\n type SolSignedTx,\n type SolSignMsgParams,\n type SolSignature,\n type HardwareEventMap,\n type ChainForFingerprint,\n HardwareErrorCode,\n success,\n failure,\n DEVICE,\n UI_REQUEST,\n TypedEventEmitter,\n} from '@bytezhang/hardware-wallet-core';\n\n/**\n * Trezor hardware wallet adapter that delegates to an IConnector.\n *\n * This is a thin translation layer that:\n * - Accepts a pre-configured IConnector (transport decisions are made at connector creation time)\n * - Translates IHardwareWallet method calls to connector.call() invocations\n * - Maps connector results/errors to our Response<T> format with enriched error messages\n * - Translates connector events to HardwareEventMap events\n * - Integrates with IUiHandler for interactive flows (PIN, passphrase)\n */\nexport class TrezorAdapter implements IHardwareWallet {\n readonly vendor = 'trezor' as const;\n\n private readonly connector: IConnector;\n private readonly emitter = new TypedEventEmitter<HardwareEventMap>();\n\n private _uiHandler: Partial<IUiHandler> | null = null;\n\n // Device cache: tracks discovered devices from connector events\n private _discoveredDevices = new Map<string, DeviceInfo>();\n\n // Session tracking: maps connectId -> sessionId\n private _sessions = new Map<string, string>();\n\n constructor(connector: IConnector) {\n this.connector = connector;\n this.registerEventListeners();\n }\n\n // ─── Transport ──────────────────────────────────────────\n // Transport is decided at connector creation time. These methods\n // satisfy the IHardwareWallet interface with sensible defaults.\n\n get activeTransport(): TransportType | null {\n return 'usb';\n }\n\n getAvailableTransports(): TransportType[] {\n return ['usb'];\n }\n\n async switchTransport(_type: TransportType): Promise<void> {\n // Transport is fixed at connector creation time.\n // To switch transport, create a new TrezorAdapter with a different connector.\n }\n\n // ─── UI handler ────────────────────────────────────────────\n\n setUiHandler(handler: Partial<IUiHandler>): void {\n this._uiHandler = handler;\n }\n\n // ─── Lifecycle ────────────────────────────────────────────\n\n async init(_config?: unknown): Promise<void> {\n // Connector is injected via constructor, already initialized.\n // Nothing to do here.\n }\n\n async dispose(): Promise<void> {\n this.unregisterEventListeners();\n this.connector.reset();\n this._uiHandler = null;\n this._discoveredDevices.clear();\n this._sessions.clear();\n this.emitter.removeAllListeners();\n }\n\n // ─── Device management ────────────────────────────────────\n\n async searchDevices(): Promise<DeviceInfo[]> {\n await this._ensureDevicePermission();\n\n const devices = await this.connector.searchDevices();\n\n for (const d of devices) {\n if (d.connectId && !this._discoveredDevices.has(d.connectId)) {\n this._discoveredDevices.set(d.connectId, this.connectorDeviceToDeviceInfo(d));\n }\n }\n\n // If no devices found, ensure permission (no connectId = search context)\n if (this._discoveredDevices.size === 0) {\n await this._ensureDevicePermission();\n }\n\n return Array.from(this._discoveredDevices.values());\n }\n\n async connectDevice(connectId: string): Promise<Response<string>> {\n try {\n const session = await this.connector.connect(connectId);\n this._sessions.set(connectId, session.sessionId);\n\n // Update device cache with richer info from session\n if (session.deviceInfo) {\n this._discoveredDevices.set(connectId, session.deviceInfo);\n }\n\n return success(connectId);\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async disconnectDevice(connectId: string): Promise<void> {\n const sessionId = this._sessions.get(connectId);\n if (sessionId) {\n await this.connector.disconnect(sessionId);\n this._sessions.delete(connectId);\n }\n }\n\n async getDeviceInfo(\n connectId: string,\n deviceId: string,\n ): Promise<Response<DeviceInfo>> {\n await this._ensureDevicePermission(connectId, deviceId);\n\n // Look up the device in the cache populated by event handlers / searchDevices.\n // Try connectId first (the USB path), then fall back to scanning by deviceId.\n const cached =\n this._discoveredDevices.get(connectId) ??\n Array.from(this._discoveredDevices.values()).find(\n (d) => d.deviceId === deviceId,\n );\n\n if (cached) {\n return success(cached);\n }\n\n return failure(\n HardwareErrorCode.DeviceNotFound,\n 'Device not found in cache. Call searchDevices() or wait for a device-connected event first.',\n );\n }\n\n getSupportedChains(): ChainCapability[] {\n return ['evm', 'btc', 'sol'];\n }\n\n // ─── Event handling ───────────────────────────────────────\n\n on<K extends keyof HardwareEventMap>(event: K, listener: (event: HardwareEventMap[K]) => void): void;\n on(event: string, listener: DeviceEventListener): void;\n on(event: string, listener: (event: any) => void): void {\n this.emitter.on(event, listener);\n }\n\n off<K extends keyof HardwareEventMap>(event: K, listener: (event: HardwareEventMap[K]) => void): void;\n off(event: string, listener: DeviceEventListener): void;\n off(event: string, listener: (event: any) => void): void {\n this.emitter.off(event, listener);\n }\n\n cancel(connectId: string): void {\n const sessionId = this._sessions.get(connectId) ?? connectId;\n void this.connector.cancel(sessionId);\n }\n\n // ─── Chain fingerprint ────────────────────────────────────\n\n /**\n * For Trezor, the chain fingerprint is the hardware device_id from firmware.\n * Trezor has a persistent device identity, so no address derivation is needed.\n */\n async getChainFingerprint(\n connectId: string,\n deviceId: string,\n _chain: ChainForFingerprint,\n ): Promise<Response<string>> {\n await this._ensureDevicePermission(connectId, deviceId);\n\n // Look up the device in cache to get the firmware device_id\n const cached =\n this._discoveredDevices.get(connectId) ??\n Array.from(this._discoveredDevices.values()).find(\n (d) => d.deviceId === deviceId,\n );\n\n if (cached?.deviceId) {\n return success(cached.deviceId);\n }\n\n // Fall back: try to get device info from the connector\n try {\n const result = await this.connectorCall(connectId, 'getFeatures', {}) as {\n device_id?: string;\n };\n if (result.device_id) {\n return success(result.device_id);\n }\n } catch {\n // Ignore — fall through to error\n }\n\n return failure(\n HardwareErrorCode.DeviceNotFound,\n 'Could not determine Trezor device identity. Ensure the device is connected.',\n );\n }\n\n // ─── EVM methods ──────────────────────────────────────────\n\n async evmGetAddress(\n connectId: string,\n _deviceId: string,\n params: EvmGetAddressParams,\n ): Promise<Response<EvmAddress>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const result = await this.connectorCall(connectId, 'evmGetAddress', {\n path: params.path,\n showOnDevice: params.showOnDevice,\n chainId: params.chainId,\n }) as { address: string; path: string };\n\n return success({\n address: result.address,\n path: params.path,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async evmGetAddresses(\n connectId: string,\n deviceId: string,\n params: EvmGetAddressParams[],\n onProgress?: ProgressCallback,\n ): Promise<Response<EvmAddress[]>> {\n return this.batchCall(\n params,\n (p) => this.evmGetAddress(connectId, deviceId, p),\n onProgress,\n );\n }\n\n async evmGetPublicKey(\n connectId: string,\n _deviceId: string,\n params: EvmGetPublicKeyParams,\n ): Promise<Response<EvmPublicKey>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const result = await this.connectorCall(connectId, 'evmGetPublicKey', {\n path: params.path,\n showOnDevice: params.showOnDevice,\n }) as { publicKey: string; path: string };\n\n return success({\n publicKey: result.publicKey,\n path: params.path,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async evmSignTransaction(\n connectId: string,\n _deviceId: string,\n params: EvmSignTxParams,\n ): Promise<Response<EvmSignedTx>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const result = await this.connectorCall(connectId, 'evmSignTransaction', {\n path: params.path,\n transaction: {\n to: params.to,\n value: params.value,\n chainId: params.chainId,\n nonce: params.nonce,\n gasLimit: params.gasLimit,\n gasPrice: params.gasPrice,\n maxFeePerGas: params.maxFeePerGas,\n maxPriorityFeePerGas: params.maxPriorityFeePerGas,\n accessList: params.accessList,\n data: params.data,\n },\n }) as { v: string; r: string; s: string; serializedTx?: string };\n\n return success({\n v: this.ensure0x(result.v),\n r: this.padHex64(result.r),\n s: this.padHex64(result.s),\n serializedTx: result.serializedTx,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async evmSignMessage(\n connectId: string,\n _deviceId: string,\n params: EvmSignMsgParams,\n ): Promise<Response<EvmSignature>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const result = await this.connectorCall(connectId, 'evmSignMessage', {\n path: params.path,\n message: params.message,\n hex: params.hex,\n }) as { signature: string; address?: string };\n\n return success({\n signature: this.ensure0x(result.signature),\n address: result.address,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async evmSignTypedData(\n connectId: string,\n _deviceId: string,\n params: EvmSignTypedDataParams,\n ): Promise<Response<EvmSignature>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const callParams: Record<string, unknown> = {\n path: params.path,\n };\n\n if (params.mode !== 'hash') {\n callParams['mode'] = params.mode ?? 'full';\n callParams['data'] = params.data;\n callParams['metamaskV4Compat'] = params.metamaskV4Compat ?? true;\n } else {\n callParams['mode'] = 'hash';\n callParams['domainSeparatorHash'] = params.domainSeparatorHash;\n callParams['messageHash'] = params.messageHash;\n }\n\n const result = await this.connectorCall(connectId, 'evmSignTypedData', callParams) as {\n signature: string;\n address?: string;\n };\n\n return success({\n signature: this.ensure0x(result.signature),\n address: result.address,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n // ─── BTC methods ──────────────────────────────────────────\n\n async btcGetAddress(\n connectId: string,\n _deviceId: string,\n params: BtcGetAddressParams,\n ): Promise<Response<BtcAddress>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const result = await this.connectorCall(connectId, 'btcGetAddress', {\n path: params.path,\n coin: params.coin,\n showOnDevice: params.showOnDevice,\n scriptType: params.scriptType,\n }) as { address: string; path: string };\n\n return success({\n address: result.address,\n path: params.path,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async btcGetAddresses(\n connectId: string,\n deviceId: string,\n params: BtcGetAddressParams[],\n onProgress?: ProgressCallback,\n ): Promise<Response<BtcAddress[]>> {\n return this.batchCall(\n params,\n (p) => this.btcGetAddress(connectId, deviceId, p),\n onProgress,\n );\n }\n\n async btcGetPublicKey(\n connectId: string,\n _deviceId: string,\n params: BtcGetPublicKeyParams,\n ): Promise<Response<BtcPublicKey>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const result = await this.connectorCall(connectId, 'btcGetPublicKey', {\n path: params.path,\n coin: params.coin,\n showOnDevice: params.showOnDevice,\n }) as {\n xpub: string;\n publicKey: string;\n fingerprint: number;\n chainCode: string;\n path: string;\n depth: number;\n };\n\n return success({\n xpub: result.xpub,\n publicKey: result.publicKey,\n fingerprint: result.fingerprint,\n chainCode: result.chainCode,\n path: params.path,\n depth: result.depth,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async btcSignTransaction(\n connectId: string,\n _deviceId: string,\n params: BtcSignTxParams,\n ): Promise<Response<BtcSignedTx>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const result = await this.connectorCall(connectId, 'btcSignTransaction', {\n inputs: params.inputs ?? [],\n outputs: params.outputs ?? [],\n refTxs: params.refTxs,\n coin: params.coin,\n locktime: params.locktime,\n version: params.version,\n }) as { signatures: string[]; serializedTx: string; txid?: string };\n\n return success({\n signatures: result.signatures,\n serializedTx: result.serializedTx,\n txid: result.txid,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async btcSignMessage(\n connectId: string,\n _deviceId: string,\n params: BtcSignMsgParams,\n ): Promise<Response<BtcSignature>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const result = await this.connectorCall(connectId, 'btcSignMessage', {\n path: params.path,\n message: params.message,\n coin: params.coin,\n }) as { signature: string; address: string };\n\n return success({\n signature: result.signature,\n address: result.address,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async btcGetMasterFingerprint(\n connectId: string,\n _deviceId: string,\n ): Promise<Response<{ masterFingerprint: string }>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n // The parent fingerprint of a child of \"m\" IS the master fingerprint.\n // Query \"m/0'\" and read its `fingerprint` field (parent key fingerprint).\n const result = await this.connectorCall(connectId, 'btcGetPublicKey', {\n path: \"m/0'\",\n }) as { fingerprint: number };\n\n const fp = (result.fingerprint) >>> 0;\n const hex = fp.toString(16).padStart(8, '0');\n return success({ masterFingerprint: hex });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n // ─── Solana methods ───────────────────────────────────────\n\n async solGetAddress(\n connectId: string,\n _deviceId: string,\n params: SolGetAddressParams,\n ): Promise<Response<SolAddress>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const result = await this.connectorCall(connectId, 'solGetAddress', {\n path: params.path,\n showOnDevice: params.showOnDevice,\n }) as { address: string; path: string };\n\n return success({\n address: result.address,\n path: params.path,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async solGetAddresses(\n connectId: string,\n deviceId: string,\n params: SolGetAddressParams[],\n onProgress?: ProgressCallback,\n ): Promise<Response<SolAddress[]>> {\n return this.batchCall(\n params,\n (p) => this.solGetAddress(connectId, deviceId, p),\n onProgress,\n );\n }\n\n async solGetPublicKey(\n connectId: string,\n _deviceId: string,\n params: SolGetPublicKeyParams,\n ): Promise<Response<SolPublicKey>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n // Solana address IS the public key\n const result = await this.connectorCall(connectId, 'solGetAddress', {\n path: params.path,\n showOnDevice: params.showOnDevice,\n }) as { address: string; path: string };\n\n return success({\n publicKey: result.address,\n path: params.path,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async solSignTransaction(\n connectId: string,\n _deviceId: string,\n params: SolSignTxParams,\n ): Promise<Response<SolSignedTx>> {\n await this._ensureDevicePermission(connectId, _deviceId);\n try {\n const result = await this.connectorCall(connectId, 'solSignTransaction', {\n path: params.path,\n serializedTx: params.serializedTx,\n additionalInfo: params.additionalInfo,\n }) as { signature: string };\n\n return success({\n signature: result.signature,\n });\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async solSignMessage(\n _connectId: string,\n _deviceId: string,\n _params: SolSignMsgParams,\n ): Promise<Response<SolSignature>> {\n return failure(\n HardwareErrorCode.MethodNotSupported,\n 'Solana signMessage is not supported by Trezor Connect',\n );\n }\n\n // ─── Private helpers ──────────────────────────────────────\n\n /**\n * Call the connector with session resolution.\n * Looks up sessionId from connectId, falls back to connectId itself.\n */\n private async connectorCall(\n connectId: string,\n method: string,\n params: unknown,\n ): Promise<unknown> {\n const sessionId = this._sessions.get(connectId) ?? connectId;\n return this.connector.call(sessionId, method, params);\n }\n\n /**\n * Ensure device permission before proceeding.\n * - No connectId (searchDevices): check environment-level permission\n * - With connectId (business methods): check device-level permission\n * If not granted, calls onDevicePermission so the consumer can request access.\n */\n private async _ensureDevicePermission(connectId?: string, deviceId?: string): Promise<void> {\n const transportType: TransportType = 'usb';\n let granted = false;\n let context: Record<string, unknown> | undefined;\n\n if (this._uiHandler?.checkDevicePermission) {\n try {\n const result = await this._uiHandler.checkDevicePermission({ transportType, connectId, deviceId });\n granted = result.granted;\n context = result.context;\n } catch {\n granted = false;\n }\n }\n\n if (!granted) {\n try {\n await this._uiHandler?.onDevicePermission?.({ transportType, context });\n } catch {\n // UI handler cancelled or failed\n }\n }\n }\n\n /**\n * Convert a thrown error to a Response failure.\n * Parses TrezorConnect error strings to map to HardwareErrorCode values.\n */\n private errorToFailure<T>(err: unknown): Response<T> {\n const message = err instanceof Error ? err.message : String(err);\n const code = this.parseErrorCode(message);\n const enriched = this.enrichErrorMessage(code, message);\n return failure(code, enriched);\n }\n\n /**\n * Parse TrezorConnect error codes from error message strings.\n * The connector throws errors with messages like \"Trezor ethereumGetAddress failed: <error>\".\n * We also check for embedded code patterns.\n */\n private parseErrorCode(message: string): HardwareErrorCode {\n // Check for known error patterns in the message\n if (message.includes('Failure_ActionCancelled') || message.includes('Failure_Cancel')) {\n return HardwareErrorCode.UserRejected;\n }\n if (message.includes('Failure_PinInvalid') || message.includes('Failure_PinMismatch')) {\n return HardwareErrorCode.PinInvalid;\n }\n if (message.includes('Failure_PinCancelled')) {\n return HardwareErrorCode.PinCancelled;\n }\n if (message.includes('Failure_PassphraseRejected')) {\n return HardwareErrorCode.PassphraseRejected;\n }\n if (message.includes('Device_UsedElsewhere')) {\n return HardwareErrorCode.DeviceBusy;\n }\n if (message.includes('Device_NotFound')) {\n return HardwareErrorCode.DeviceNotFound;\n }\n if (message.includes('Device_InvalidState')) {\n return HardwareErrorCode.DeviceNotInitialized;\n }\n if (message.includes('Transport_Missing')) {\n return HardwareErrorCode.TransportNotAvailable;\n }\n if (message.includes('Transport_DeviceDisconnected')) {\n return HardwareErrorCode.DeviceDisconnected;\n }\n if (message.includes('Failure_FirmwareError')) {\n return HardwareErrorCode.FirmwareTooOld;\n }\n if (message.includes('Method_InvalidParameter') || message.includes('Method_InvalidParams')) {\n return HardwareErrorCode.InvalidParams;\n }\n if (message.includes('Method_NotAllowed')) {\n return HardwareErrorCode.MethodNotSupported;\n }\n return HardwareErrorCode.UnknownError;\n }\n\n /**\n * Enrich error messages with actionable recovery info for the caller.\n */\n private enrichErrorMessage(code: HardwareErrorCode, originalMessage: string): string {\n switch (code) {\n case HardwareErrorCode.PinInvalid:\n return `${originalMessage}. Please re-enter your PIN.`;\n case HardwareErrorCode.PinCancelled:\n return `${originalMessage}. PIN entry was cancelled.`;\n case HardwareErrorCode.DeviceBusy:\n return `${originalMessage}. The device is in use by another application. Close other wallet apps and try again.`;\n case HardwareErrorCode.DeviceDisconnected:\n return `${originalMessage}. Please reconnect the device and try again.`;\n case HardwareErrorCode.TransportNotAvailable:\n return `${originalMessage}. Ensure Trezor Bridge is installed and running, or connect via USB.`;\n case HardwareErrorCode.FirmwareTooOld:\n return `${originalMessage}. Please update your Trezor firmware via Trezor Suite.`;\n case HardwareErrorCode.DeviceNotInitialized:\n return `${originalMessage}. The device may need to be set up first via Trezor Suite.`;\n default:\n return originalMessage;\n }\n }\n\n /**\n * Generic batch call with progress reporting.\n * If any single call fails, returns the failure immediately.\n */\n private async batchCall<TParam, TResult>(\n params: TParam[],\n callFn: (p: TParam) => Promise<Response<TResult>>,\n onProgress?: ProgressCallback,\n ): Promise<Response<TResult[]>> {\n const results: TResult[] = [];\n for (let i = 0; i < params.length; i++) {\n const result = await callFn(params[i]);\n if (!result.success) {\n return result;\n }\n results.push(result.payload);\n onProgress?.({ index: i, total: params.length });\n }\n return success(results);\n }\n\n // ─── Hex formatting ──────────────────────────────────────\n\n /** Ensure a hex string has the `0x` prefix. */\n private ensure0x(hex: string): string {\n return hex.startsWith('0x') ? hex : `0x${hex}`;\n }\n\n /** Ensure a hex string is `0x`-prefixed and zero-padded to 64 hex chars (32 bytes). */\n private padHex64(hex: string): string {\n const stripped = hex.startsWith('0x') ? hex.slice(2) : hex;\n return `0x${stripped.padStart(64, '0')}`;\n }\n\n // ─── Event translation ────────────────────────────────────\n\n private deviceConnectHandler = (data: { device: ConnectorDevice }): void => {\n const deviceInfo = this.connectorDeviceToDeviceInfo(data.device);\n this._discoveredDevices.set(deviceInfo.connectId, deviceInfo);\n this.emitter.emit(DEVICE.CONNECT, {\n type: DEVICE.CONNECT,\n payload: deviceInfo,\n });\n };\n\n private deviceDisconnectHandler = (data: { connectId: string }): void => {\n this._discoveredDevices.delete(data.connectId);\n this.emitter.emit(DEVICE.DISCONNECT, {\n type: DEVICE.DISCONNECT,\n payload: { connectId: data.connectId },\n });\n };\n\n private uiRequestHandler = (data: { type: string; payload?: unknown }): void => {\n this.handleUiEvent(data);\n };\n\n private uiEventHandler = (data: { type: string; payload?: unknown }): void => {\n this.handleUiEvent(data);\n };\n\n private registerEventListeners(): void {\n this.connector.on('device-connect', this.deviceConnectHandler);\n this.connector.on('device-disconnect', this.deviceDisconnectHandler);\n this.connector.on('ui-request', this.uiRequestHandler);\n this.connector.on('ui-event', this.uiEventHandler);\n }\n\n private unregisterEventListeners(): void {\n this.connector.off('device-connect', this.deviceConnectHandler);\n this.connector.off('device-disconnect', this.deviceDisconnectHandler);\n this.connector.off('ui-request', this.uiRequestHandler);\n this.connector.off('ui-event', this.uiEventHandler);\n }\n\n private handleUiEvent(event: { type: string; payload?: unknown }): void {\n if (!event.type) return;\n\n const payload = event.payload as Record<string, unknown> | undefined;\n const devicePayload = (payload?.['device'] as Record<string, unknown>) ?? payload;\n const deviceInfo = devicePayload ? this.extractDeviceInfoFromPayload(devicePayload) : this.unknownDevice();\n\n switch (event.type) {\n case 'ui-request_pin':\n this.emitter.emit(UI_REQUEST.REQUEST_PIN, {\n type: UI_REQUEST.REQUEST_PIN,\n payload: { device: deviceInfo },\n });\n if (this._uiHandler?.onPinRequest) {\n this._uiHandler.onPinRequest(deviceInfo).then((pin) => {\n this.connector.uiResponse({\n type: 'receive-pin',\n payload: pin,\n });\n }).catch(() => {\n // User cancelled -- no response sent\n });\n }\n break;\n case 'ui-request_passphrase':\n this.emitter.emit(UI_REQUEST.REQUEST_PASSPHRASE, {\n type: UI_REQUEST.REQUEST_PASSPHRASE,\n payload: { device: deviceInfo },\n });\n if (this._uiHandler?.onPassphraseRequest) {\n this._uiHandler.onPassphraseRequest(deviceInfo).then((result) => {\n const response = typeof result === 'string'\n ? { passphrase: result, onDevice: false }\n : result ?? { passphrase: '', onDevice: false };\n if (response.onDevice) {\n this.connector.uiResponse({\n type: 'receive-passphrase',\n payload: {\n value: '',\n passphraseOnDevice: true,\n save: false,\n },\n });\n } else {\n this.connector.uiResponse({\n type: 'receive-passphrase',\n payload: {\n value: response.passphrase,\n passphraseOnDevice: false,\n save: false,\n },\n });\n }\n }).catch(() => {\n // User cancelled -- no response sent\n });\n }\n break;\n case 'ui-request_confirmation':\n this.emitter.emit(UI_REQUEST.REQUEST_BUTTON, {\n type: UI_REQUEST.REQUEST_BUTTON,\n payload: { device: deviceInfo },\n });\n break;\n }\n }\n\n private connectorDeviceToDeviceInfo(device: ConnectorDevice): DeviceInfo {\n return {\n vendor: 'trezor',\n model: device.model ?? 'unknown',\n firmwareVersion: '',\n deviceId: device.deviceId,\n connectId: device.connectId,\n label: device.name,\n connectionType: 'usb' as ConnectionType,\n };\n }\n\n private extractDeviceInfoFromPayload(payload: Record<string, unknown>): DeviceInfo {\n const features = payload['features'] as Record<string, unknown> | undefined;\n return {\n vendor: 'trezor',\n model: (features?.['model'] as string) ?? (payload['model'] as string) ?? 'unknown',\n firmwareVersion: features\n ? `${features['major_version'] ?? 0}.${features['minor_version'] ?? 0}.${features['patch_version'] ?? 0}`\n : '',\n deviceId: (features?.['device_id'] as string) ?? (payload['id'] as string) ?? '',\n connectId: (payload['path'] as string) ?? '',\n label: (features?.['label'] as string) ?? (payload['label'] as string),\n connectionType: 'usb' as ConnectionType,\n };\n }\n\n private unknownDevice(): DeviceInfo {\n return {\n vendor: 'trezor',\n model: 'unknown',\n firmwareVersion: '',\n deviceId: '',\n connectId: '',\n connectionType: 'usb',\n };\n }\n}\n","import { AbstractProxyClient } from '@bytezhang/hardware-transport-core';\nimport type { ITrezorConnect, TrezorConnectResponse } from './types';\n\n/**\n * Trezor method stubs on top of AbstractProxyClient.\n *\n * All cross-process Trezor proxy clients (Electron IPC, Extension messaging)\n * extend this class. They only need to implement:\n * - `sendCall()` — the transport channel\n * - `dispose()` / `cancel()` / `uiResponse()` — lifecycle\n *\n * The 11 TrezorConnect method stubs are defined here once.\n */\nexport abstract class TrezorProxyClient extends AbstractProxyClient implements ITrezorConnect {\n abstract dispose(): void;\n abstract cancel(reason?: string): void;\n abstract uiResponse(response: { type: string; payload: unknown }): void;\n\n // ─── TrezorConnect method stubs — all delegate to call() ────\n ethereumGetAddress(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('ethereumGetAddress', params) as Promise<TrezorConnectResponse>;\n }\n ethereumGetPublicKey(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('ethereumGetPublicKey', params) as Promise<TrezorConnectResponse>;\n }\n ethereumSignTransaction(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('ethereumSignTransaction', params) as Promise<TrezorConnectResponse>;\n }\n ethereumSignMessage(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('ethereumSignMessage', params) as Promise<TrezorConnectResponse>;\n }\n ethereumSignTypedData(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('ethereumSignTypedData', params) as Promise<TrezorConnectResponse>;\n }\n getAddress(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('getAddress', params) as Promise<TrezorConnectResponse>;\n }\n getPublicKey(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('getPublicKey', params) as Promise<TrezorConnectResponse>;\n }\n signTransaction(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('signTransaction', params) as Promise<TrezorConnectResponse>;\n }\n signMessage(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('signMessage', params) as Promise<TrezorConnectResponse>;\n }\n solanaGetAddress(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('solanaGetAddress', params) as Promise<TrezorConnectResponse>;\n }\n solanaSignTransaction(params: Record<string, unknown>): Promise<TrezorConnectResponse> {\n return this.call('solanaSignTransaction', params) as Promise<TrezorConnectResponse>;\n }\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bytezhang/hardware-trezor-adapter",
3
- "version": "0.0.1",
3
+ "version": "0.0.8",
4
4
  "description": "Trezor hardware wallet adapter using IConnector abstraction",
5
5
  "author": "OneKey",
6
6
  "license": "MIT",
@@ -9,11 +9,19 @@
9
9
  "types": "dist/index.d.ts",
10
10
  "exports": {
11
11
  ".": {
12
- "import": { "types": "./dist/index.d.mts", "default": "./dist/index.mjs" },
13
- "require": { "types": "./dist/index.d.ts", "default": "./dist/index.js" }
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
+ }
14
20
  }
15
21
  },
16
- "files": ["dist"],
22
+ "files": [
23
+ "dist"
24
+ ],
17
25
  "scripts": {
18
26
  "build": "tsup",
19
27
  "dev": "tsup --watch",
package/dist/index.d.mts DELETED
@@ -1,193 +0,0 @@
1
- import { IHardwareWallet, IConnector, TransportType, IUiHandler, DeviceInfo, Response, ChainCapability, HardwareEventMap, DeviceEventListener, EvmGetAddressParams, EvmAddress, ProgressCallback, EvmGetPublicKeyParams, EvmPublicKey, EvmSignTxParams, EvmSignedTx, EvmSignMsgParams, EvmSignature, EvmSignTypedDataParams, BtcGetAddressParams, BtcAddress, BtcGetPublicKeyParams, BtcPublicKey, BtcSignTxParams, BtcSignedTx, BtcSignMsgParams, BtcSignature, SolGetAddressParams, SolAddress, SolGetPublicKeyParams, SolPublicKey, SolSignTxParams, SolSignedTx, SolSignMsgParams, SolSignature } from '@bytezhang/hardware-wallet-core';
2
- import { AbstractProxyClient } from '@bytezhang/hardware-transport-core';
3
-
4
- /**
5
- * Trezor hardware wallet adapter that delegates to an IConnector.
6
- *
7
- * This is a thin translation layer that:
8
- * - Accepts a pre-configured IConnector (transport decisions are made at connector creation time)
9
- * - Translates IHardwareWallet method calls to connector.call() invocations
10
- * - Maps connector results/errors to our Response<T> format with enriched error messages
11
- * - Translates connector events to HardwareEventMap events
12
- * - Integrates with IUiHandler for interactive flows (PIN, passphrase)
13
- */
14
- declare class TrezorAdapter implements IHardwareWallet {
15
- readonly vendor: "trezor";
16
- private readonly connector;
17
- private readonly emitter;
18
- private _uiHandler;
19
- private _discoveredDevices;
20
- private _sessions;
21
- constructor(connector: IConnector);
22
- get activeTransport(): TransportType | null;
23
- getAvailableTransports(): TransportType[];
24
- switchTransport(_type: TransportType): Promise<void>;
25
- setUiHandler(handler: Partial<IUiHandler>): void;
26
- init(_config?: unknown): Promise<void>;
27
- dispose(): Promise<void>;
28
- searchDevices(): Promise<DeviceInfo[]>;
29
- connectDevice(connectId: string): Promise<Response<string>>;
30
- disconnectDevice(connectId: string): Promise<void>;
31
- getDeviceInfo(connectId: string, deviceId: string): Promise<Response<DeviceInfo>>;
32
- getSupportedChains(): ChainCapability[];
33
- on<K extends keyof HardwareEventMap>(event: K, listener: (event: HardwareEventMap[K]) => void): void;
34
- on(event: string, listener: DeviceEventListener): void;
35
- off<K extends keyof HardwareEventMap>(event: K, listener: (event: HardwareEventMap[K]) => void): void;
36
- off(event: string, listener: DeviceEventListener): void;
37
- cancel(connectId: string): void;
38
- evmGetAddress(connectId: string, _deviceId: string, params: EvmGetAddressParams): Promise<Response<EvmAddress>>;
39
- evmGetAddresses(connectId: string, deviceId: string, params: EvmGetAddressParams[], onProgress?: ProgressCallback): Promise<Response<EvmAddress[]>>;
40
- evmGetPublicKey(connectId: string, _deviceId: string, params: EvmGetPublicKeyParams): Promise<Response<EvmPublicKey>>;
41
- evmSignTransaction(connectId: string, _deviceId: string, params: EvmSignTxParams): Promise<Response<EvmSignedTx>>;
42
- evmSignMessage(connectId: string, _deviceId: string, params: EvmSignMsgParams): Promise<Response<EvmSignature>>;
43
- evmSignTypedData(connectId: string, _deviceId: string, params: EvmSignTypedDataParams): Promise<Response<EvmSignature>>;
44
- btcGetAddress(connectId: string, _deviceId: string, params: BtcGetAddressParams): Promise<Response<BtcAddress>>;
45
- btcGetAddresses(connectId: string, deviceId: string, params: BtcGetAddressParams[], onProgress?: ProgressCallback): Promise<Response<BtcAddress[]>>;
46
- btcGetPublicKey(connectId: string, _deviceId: string, params: BtcGetPublicKeyParams): Promise<Response<BtcPublicKey>>;
47
- btcSignTransaction(connectId: string, _deviceId: string, params: BtcSignTxParams): Promise<Response<BtcSignedTx>>;
48
- btcSignMessage(connectId: string, _deviceId: string, params: BtcSignMsgParams): Promise<Response<BtcSignature>>;
49
- btcGetMasterFingerprint(connectId: string, _deviceId: string): Promise<Response<{
50
- masterFingerprint: string;
51
- }>>;
52
- solGetAddress(connectId: string, _deviceId: string, params: SolGetAddressParams): Promise<Response<SolAddress>>;
53
- solGetAddresses(connectId: string, deviceId: string, params: SolGetAddressParams[], onProgress?: ProgressCallback): Promise<Response<SolAddress[]>>;
54
- solGetPublicKey(connectId: string, _deviceId: string, params: SolGetPublicKeyParams): Promise<Response<SolPublicKey>>;
55
- solSignTransaction(connectId: string, _deviceId: string, params: SolSignTxParams): Promise<Response<SolSignedTx>>;
56
- solSignMessage(_connectId: string, _deviceId: string, _params: SolSignMsgParams): Promise<Response<SolSignature>>;
57
- /**
58
- * Call the connector with session resolution.
59
- * Looks up sessionId from connectId, falls back to connectId itself.
60
- */
61
- private connectorCall;
62
- /**
63
- * Ensure device permission before proceeding.
64
- * - No connectId (searchDevices): check environment-level permission
65
- * - With connectId (business methods): check device-level permission
66
- * If not granted, calls onDevicePermission so the consumer can request access.
67
- */
68
- private _ensureDevicePermission;
69
- /**
70
- * Convert a thrown error to a Response failure.
71
- * Parses TrezorConnect error strings to map to HardwareErrorCode values.
72
- */
73
- private errorToFailure;
74
- /**
75
- * Parse TrezorConnect error codes from error message strings.
76
- * The connector throws errors with messages like "Trezor ethereumGetAddress failed: <error>".
77
- * We also check for embedded code patterns.
78
- */
79
- private parseErrorCode;
80
- /**
81
- * Enrich error messages with actionable recovery info for the caller.
82
- */
83
- private enrichErrorMessage;
84
- /**
85
- * Generic batch call with progress reporting.
86
- * If any single call fails, returns the failure immediately.
87
- */
88
- private batchCall;
89
- /** Ensure a hex string has the `0x` prefix. */
90
- private ensure0x;
91
- /** Ensure a hex string is `0x`-prefixed and zero-padded to 64 hex chars (32 bytes). */
92
- private padHex64;
93
- private deviceConnectHandler;
94
- private deviceDisconnectHandler;
95
- private uiRequestHandler;
96
- private uiEventHandler;
97
- private registerEventListeners;
98
- private unregisterEventListeners;
99
- private handleUiEvent;
100
- private connectorDeviceToDeviceInfo;
101
- private extractDeviceInfoFromPayload;
102
- private unknownDevice;
103
- }
104
-
105
- /**
106
- * Response shape returned by connector.call() results that follow
107
- * the TrezorConnect success/failure pattern.
108
- *
109
- * The connector may either:
110
- * 1. Return the result directly (success case from TrezorDirectConnector)
111
- * 2. Throw an error (failure case from TrezorDirectConnector)
112
- *
113
- * These types are kept for error parsing when the connector propagates
114
- * TrezorConnect error strings.
115
- */
116
- interface ConnectorCallError {
117
- message: string;
118
- code?: string;
119
- }
120
- /**
121
- * Abstraction over @trezor/connect API surface.
122
- *
123
- * Does NOT include `init()` — the consumer calls init() inside createConnect().
124
- * Adapter calls dispose() when switching or tearing down.
125
- */
126
- interface ITrezorConnect {
127
- dispose(): void;
128
- cancel(reason?: string): void;
129
- on(event: string, handler: (...args: unknown[]) => void): void;
130
- off(event: string, handler: (...args: unknown[]) => void): void;
131
- removeAllListeners?(): void;
132
- uiResponse(response: {
133
- type: string;
134
- payload: unknown;
135
- }): void;
136
- enumerate?(): Promise<Array<Record<string, unknown>>>;
137
- ethereumGetAddress(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
138
- ethereumGetPublicKey(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
139
- ethereumSignTransaction(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
140
- ethereumSignMessage(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
141
- ethereumSignTypedData(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
142
- getAddress(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
143
- getPublicKey(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
144
- signTransaction(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
145
- signMessage(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
146
- solanaGetAddress(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
147
- solanaSignTransaction(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
148
- }
149
- /**
150
- * Response shape returned by all @trezor/connect methods.
151
- */
152
- type TrezorConnectResponse = {
153
- success: true;
154
- payload: Record<string, unknown>;
155
- } | {
156
- success: false;
157
- payload: {
158
- error: string;
159
- code?: string;
160
- };
161
- };
162
-
163
- /**
164
- * Trezor method stubs on top of AbstractProxyClient.
165
- *
166
- * All cross-process Trezor proxy clients (Electron IPC, Extension messaging)
167
- * extend this class. They only need to implement:
168
- * - `sendCall()` — the transport channel
169
- * - `dispose()` / `cancel()` / `uiResponse()` — lifecycle
170
- *
171
- * The 11 TrezorConnect method stubs are defined here once.
172
- */
173
- declare abstract class TrezorProxyClient extends AbstractProxyClient implements ITrezorConnect {
174
- abstract dispose(): void;
175
- abstract cancel(reason?: string): void;
176
- abstract uiResponse(response: {
177
- type: string;
178
- payload: unknown;
179
- }): void;
180
- ethereumGetAddress(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
181
- ethereumGetPublicKey(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
182
- ethereumSignTransaction(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
183
- ethereumSignMessage(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
184
- ethereumSignTypedData(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
185
- getAddress(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
186
- getPublicKey(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
187
- signTransaction(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
188
- signMessage(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
189
- solanaGetAddress(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
190
- solanaSignTransaction(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
191
- }
192
-
193
- export { type ConnectorCallError, type ITrezorConnect, TrezorAdapter, type TrezorConnectResponse, TrezorProxyClient };
package/dist/index.d.ts DELETED
@@ -1,193 +0,0 @@
1
- import { IHardwareWallet, IConnector, TransportType, IUiHandler, DeviceInfo, Response, ChainCapability, HardwareEventMap, DeviceEventListener, EvmGetAddressParams, EvmAddress, ProgressCallback, EvmGetPublicKeyParams, EvmPublicKey, EvmSignTxParams, EvmSignedTx, EvmSignMsgParams, EvmSignature, EvmSignTypedDataParams, BtcGetAddressParams, BtcAddress, BtcGetPublicKeyParams, BtcPublicKey, BtcSignTxParams, BtcSignedTx, BtcSignMsgParams, BtcSignature, SolGetAddressParams, SolAddress, SolGetPublicKeyParams, SolPublicKey, SolSignTxParams, SolSignedTx, SolSignMsgParams, SolSignature } from '@bytezhang/hardware-wallet-core';
2
- import { AbstractProxyClient } from '@bytezhang/hardware-transport-core';
3
-
4
- /**
5
- * Trezor hardware wallet adapter that delegates to an IConnector.
6
- *
7
- * This is a thin translation layer that:
8
- * - Accepts a pre-configured IConnector (transport decisions are made at connector creation time)
9
- * - Translates IHardwareWallet method calls to connector.call() invocations
10
- * - Maps connector results/errors to our Response<T> format with enriched error messages
11
- * - Translates connector events to HardwareEventMap events
12
- * - Integrates with IUiHandler for interactive flows (PIN, passphrase)
13
- */
14
- declare class TrezorAdapter implements IHardwareWallet {
15
- readonly vendor: "trezor";
16
- private readonly connector;
17
- private readonly emitter;
18
- private _uiHandler;
19
- private _discoveredDevices;
20
- private _sessions;
21
- constructor(connector: IConnector);
22
- get activeTransport(): TransportType | null;
23
- getAvailableTransports(): TransportType[];
24
- switchTransport(_type: TransportType): Promise<void>;
25
- setUiHandler(handler: Partial<IUiHandler>): void;
26
- init(_config?: unknown): Promise<void>;
27
- dispose(): Promise<void>;
28
- searchDevices(): Promise<DeviceInfo[]>;
29
- connectDevice(connectId: string): Promise<Response<string>>;
30
- disconnectDevice(connectId: string): Promise<void>;
31
- getDeviceInfo(connectId: string, deviceId: string): Promise<Response<DeviceInfo>>;
32
- getSupportedChains(): ChainCapability[];
33
- on<K extends keyof HardwareEventMap>(event: K, listener: (event: HardwareEventMap[K]) => void): void;
34
- on(event: string, listener: DeviceEventListener): void;
35
- off<K extends keyof HardwareEventMap>(event: K, listener: (event: HardwareEventMap[K]) => void): void;
36
- off(event: string, listener: DeviceEventListener): void;
37
- cancel(connectId: string): void;
38
- evmGetAddress(connectId: string, _deviceId: string, params: EvmGetAddressParams): Promise<Response<EvmAddress>>;
39
- evmGetAddresses(connectId: string, deviceId: string, params: EvmGetAddressParams[], onProgress?: ProgressCallback): Promise<Response<EvmAddress[]>>;
40
- evmGetPublicKey(connectId: string, _deviceId: string, params: EvmGetPublicKeyParams): Promise<Response<EvmPublicKey>>;
41
- evmSignTransaction(connectId: string, _deviceId: string, params: EvmSignTxParams): Promise<Response<EvmSignedTx>>;
42
- evmSignMessage(connectId: string, _deviceId: string, params: EvmSignMsgParams): Promise<Response<EvmSignature>>;
43
- evmSignTypedData(connectId: string, _deviceId: string, params: EvmSignTypedDataParams): Promise<Response<EvmSignature>>;
44
- btcGetAddress(connectId: string, _deviceId: string, params: BtcGetAddressParams): Promise<Response<BtcAddress>>;
45
- btcGetAddresses(connectId: string, deviceId: string, params: BtcGetAddressParams[], onProgress?: ProgressCallback): Promise<Response<BtcAddress[]>>;
46
- btcGetPublicKey(connectId: string, _deviceId: string, params: BtcGetPublicKeyParams): Promise<Response<BtcPublicKey>>;
47
- btcSignTransaction(connectId: string, _deviceId: string, params: BtcSignTxParams): Promise<Response<BtcSignedTx>>;
48
- btcSignMessage(connectId: string, _deviceId: string, params: BtcSignMsgParams): Promise<Response<BtcSignature>>;
49
- btcGetMasterFingerprint(connectId: string, _deviceId: string): Promise<Response<{
50
- masterFingerprint: string;
51
- }>>;
52
- solGetAddress(connectId: string, _deviceId: string, params: SolGetAddressParams): Promise<Response<SolAddress>>;
53
- solGetAddresses(connectId: string, deviceId: string, params: SolGetAddressParams[], onProgress?: ProgressCallback): Promise<Response<SolAddress[]>>;
54
- solGetPublicKey(connectId: string, _deviceId: string, params: SolGetPublicKeyParams): Promise<Response<SolPublicKey>>;
55
- solSignTransaction(connectId: string, _deviceId: string, params: SolSignTxParams): Promise<Response<SolSignedTx>>;
56
- solSignMessage(_connectId: string, _deviceId: string, _params: SolSignMsgParams): Promise<Response<SolSignature>>;
57
- /**
58
- * Call the connector with session resolution.
59
- * Looks up sessionId from connectId, falls back to connectId itself.
60
- */
61
- private connectorCall;
62
- /**
63
- * Ensure device permission before proceeding.
64
- * - No connectId (searchDevices): check environment-level permission
65
- * - With connectId (business methods): check device-level permission
66
- * If not granted, calls onDevicePermission so the consumer can request access.
67
- */
68
- private _ensureDevicePermission;
69
- /**
70
- * Convert a thrown error to a Response failure.
71
- * Parses TrezorConnect error strings to map to HardwareErrorCode values.
72
- */
73
- private errorToFailure;
74
- /**
75
- * Parse TrezorConnect error codes from error message strings.
76
- * The connector throws errors with messages like "Trezor ethereumGetAddress failed: <error>".
77
- * We also check for embedded code patterns.
78
- */
79
- private parseErrorCode;
80
- /**
81
- * Enrich error messages with actionable recovery info for the caller.
82
- */
83
- private enrichErrorMessage;
84
- /**
85
- * Generic batch call with progress reporting.
86
- * If any single call fails, returns the failure immediately.
87
- */
88
- private batchCall;
89
- /** Ensure a hex string has the `0x` prefix. */
90
- private ensure0x;
91
- /** Ensure a hex string is `0x`-prefixed and zero-padded to 64 hex chars (32 bytes). */
92
- private padHex64;
93
- private deviceConnectHandler;
94
- private deviceDisconnectHandler;
95
- private uiRequestHandler;
96
- private uiEventHandler;
97
- private registerEventListeners;
98
- private unregisterEventListeners;
99
- private handleUiEvent;
100
- private connectorDeviceToDeviceInfo;
101
- private extractDeviceInfoFromPayload;
102
- private unknownDevice;
103
- }
104
-
105
- /**
106
- * Response shape returned by connector.call() results that follow
107
- * the TrezorConnect success/failure pattern.
108
- *
109
- * The connector may either:
110
- * 1. Return the result directly (success case from TrezorDirectConnector)
111
- * 2. Throw an error (failure case from TrezorDirectConnector)
112
- *
113
- * These types are kept for error parsing when the connector propagates
114
- * TrezorConnect error strings.
115
- */
116
- interface ConnectorCallError {
117
- message: string;
118
- code?: string;
119
- }
120
- /**
121
- * Abstraction over @trezor/connect API surface.
122
- *
123
- * Does NOT include `init()` — the consumer calls init() inside createConnect().
124
- * Adapter calls dispose() when switching or tearing down.
125
- */
126
- interface ITrezorConnect {
127
- dispose(): void;
128
- cancel(reason?: string): void;
129
- on(event: string, handler: (...args: unknown[]) => void): void;
130
- off(event: string, handler: (...args: unknown[]) => void): void;
131
- removeAllListeners?(): void;
132
- uiResponse(response: {
133
- type: string;
134
- payload: unknown;
135
- }): void;
136
- enumerate?(): Promise<Array<Record<string, unknown>>>;
137
- ethereumGetAddress(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
138
- ethereumGetPublicKey(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
139
- ethereumSignTransaction(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
140
- ethereumSignMessage(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
141
- ethereumSignTypedData(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
142
- getAddress(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
143
- getPublicKey(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
144
- signTransaction(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
145
- signMessage(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
146
- solanaGetAddress(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
147
- solanaSignTransaction(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
148
- }
149
- /**
150
- * Response shape returned by all @trezor/connect methods.
151
- */
152
- type TrezorConnectResponse = {
153
- success: true;
154
- payload: Record<string, unknown>;
155
- } | {
156
- success: false;
157
- payload: {
158
- error: string;
159
- code?: string;
160
- };
161
- };
162
-
163
- /**
164
- * Trezor method stubs on top of AbstractProxyClient.
165
- *
166
- * All cross-process Trezor proxy clients (Electron IPC, Extension messaging)
167
- * extend this class. They only need to implement:
168
- * - `sendCall()` — the transport channel
169
- * - `dispose()` / `cancel()` / `uiResponse()` — lifecycle
170
- *
171
- * The 11 TrezorConnect method stubs are defined here once.
172
- */
173
- declare abstract class TrezorProxyClient extends AbstractProxyClient implements ITrezorConnect {
174
- abstract dispose(): void;
175
- abstract cancel(reason?: string): void;
176
- abstract uiResponse(response: {
177
- type: string;
178
- payload: unknown;
179
- }): void;
180
- ethereumGetAddress(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
181
- ethereumGetPublicKey(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
182
- ethereumSignTransaction(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
183
- ethereumSignMessage(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
184
- ethereumSignTypedData(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
185
- getAddress(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
186
- getPublicKey(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
187
- signTransaction(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
188
- signMessage(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
189
- solanaGetAddress(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
190
- solanaSignTransaction(params: Record<string, unknown>): Promise<TrezorConnectResponse>;
191
- }
192
-
193
- export { type ConnectorCallError, type ITrezorConnect, TrezorAdapter, type TrezorConnectResponse, TrezorProxyClient };