@bytezhang/hardware-ledger-connector-webhid 0.0.1 → 0.0.4

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
@@ -70,12 +70,21 @@ var LedgerWebHidConnector = class {
70
70
  }
71
71
  descriptors = await dm.enumerate();
72
72
  }
73
- return descriptors.map((d) => ({
73
+ console.log("[LedgerWebHidConnector] descriptors:", JSON.stringify(descriptors));
74
+ const result = descriptors.map((d) => ({
75
+ // d.path is a temporary DMK UUID (regenerated on each discovery).
76
+ // Used internally for routing. NOT a persistent device ID.
74
77
  connectId: d.path,
75
78
  deviceId: d.path,
76
- name: d.type ?? "Ledger",
77
- model: d.type
79
+ name: d.type || "Ledger",
80
+ model: d.type,
81
+ capabilities: {
82
+ // WebHID: DMK generates ephemeral UUIDs each session
83
+ persistentDeviceIdentity: false
84
+ }
78
85
  }));
86
+ console.log("[LedgerWebHidConnector] searchDevices result:", JSON.stringify(result));
87
+ return result;
79
88
  }
80
89
  // ---------------------------------------------------------------------------
81
90
  // IConnector — Connection
@@ -103,7 +112,10 @@ var LedgerWebHidConnector = class {
103
112
  firmwareVersion: "unknown",
104
113
  deviceId: resolvedDeviceId,
105
114
  connectId: resolvedDeviceId,
106
- connectionType: "usb"
115
+ connectionType: "usb",
116
+ capabilities: {
117
+ persistentDeviceIdentity: false
118
+ }
107
119
  }
108
120
  };
109
121
  this._emit("device-connect", {
@@ -340,7 +352,14 @@ var LedgerWebHidConnector = class {
340
352
  const dmk = await this._getOrCreateDmk();
341
353
  this._initManagers(dmk);
342
354
  }
343
- return this._signerManager.getOrCreate(sessionId);
355
+ const signer = await this._signerManager.getOrCreate(sessionId);
356
+ signer.onInteraction = (interaction) => {
357
+ this._emit("ui-event", {
358
+ type: interaction,
359
+ payload: { sessionId }
360
+ });
361
+ };
362
+ return signer;
344
363
  }
345
364
  async _createBtcSigner(sessionId) {
346
365
  const dmk = await this._getOrCreateDmk();
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/LedgerWebHidConnector.ts"],"sourcesContent":["import type { IConnector } from '@bytezhang/hardware-wallet-core';\nimport type { IDmk } from '@bytezhang/ledger-adapter';\n\nimport {\n LedgerWebHidConnector,\n} from './LedgerWebHidConnector';\nimport type { LedgerWebHidConnectorOptions } from './LedgerWebHidConnector';\n\nexport { LedgerWebHidConnector };\nexport type { LedgerWebHidConnectorOptions };\n\n/**\n * Create a LedgerWebHidConnector.\n *\n * @param dmk - Optional pre-built DMK instance. If omitted, the connector\n * will lazily create one using `@ledgerhq/device-management-kit`\n * and `@ledgerhq/device-transport-kit-web-hid`.\n */\nexport function createLedgerWebHidConnector(dmk?: IDmk): IConnector {\n return new LedgerWebHidConnector({ dmk });\n}\n","import type {\n IConnector,\n ConnectorDevice,\n ConnectorSession,\n ConnectorEventType,\n ConnectorEventMap,\n} from '@bytezhang/hardware-wallet-core';\nimport type { IDmk, SignerEvmSignature } from '@bytezhang/ledger-adapter';\nimport {\n LedgerDeviceManager,\n SignerManager,\n SignerBtc,\n mapLedgerError,\n} from '@bytezhang/ledger-adapter';\n\n// ---------------------------------------------------------------------------\n// Internal types\n// ---------------------------------------------------------------------------\n\ntype EventHandler<K extends ConnectorEventType> = (\n data: ConnectorEventMap[K],\n) => void;\n\n/** Parameters for evmGetAddress */\ninterface EvmGetAddressCallParams {\n path: string;\n showOnDevice?: boolean;\n}\n\n/** Parameters for evmSignTransaction */\ninterface EvmSignTransactionCallParams {\n path: string;\n /** RLP-serialized transaction hex (0x-prefixed or plain) */\n serializedTx: string;\n}\n\n/** Parameters for evmSignMessage */\ninterface EvmSignMessageCallParams {\n path: string;\n message: string;\n}\n\n/** Parameters for evmSignTypedData */\ninterface EvmSignTypedDataCallParams {\n path: string;\n data: unknown;\n}\n\n/** Parameters for btcGetAddress */\ninterface BtcGetAddressCallParams {\n path: string;\n showOnDevice?: boolean;\n}\n\n/** Parameters for btcGetPublicKey */\ninterface BtcGetPublicKeyCallParams {\n path: string;\n showOnDevice?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Strip the \"m/\" prefix from BIP-44 derivation paths. */\nfunction normalizePath(path: string): string {\n return path.startsWith('m/') ? path.slice(2) : path;\n}\n\n/** Remove `0x` prefix from a hex string if present. */\nfunction stripHex(hex: string): string {\n return hex.startsWith('0x') ? hex.slice(2) : hex;\n}\n\n/** Ensure a hex string is `0x`-prefixed and zero-padded to 64 hex chars (32 bytes). */\nfunction padHex64(hex: string): string {\n return `0x${stripHex(hex).padStart(64, '0')}`;\n}\n\n// ---------------------------------------------------------------------------\n// LedgerWebHidConnector\n// ---------------------------------------------------------------------------\n\nexport interface LedgerWebHidConnectorOptions {\n /**\n * Pre-built DMK instance. If not provided, a DMK will be created\n * lazily on first use via `@ledgerhq/device-management-kit` and\n * `@ledgerhq/device-transport-kit-web-hid`.\n */\n dmk?: IDmk;\n}\n\n/**\n * IConnector implementation for Ledger hardware wallets via WebHID.\n *\n * Wraps the Ledger DMK (Device Management Kit) and signer kits into\n * the unified IConnector interface used by the adapter layer.\n *\n * Design:\n * - Constructor accepts an optional pre-built DMK instance (or creates one lazily).\n * - searchDevices() uses DMK's listenToAvailableDevices() observable.\n * - connect() calls dmk.connect({ device }), returns a ConnectorSession.\n * - call() dispatches to chain-specific signer methods (EVM, BTC).\n * - Internally uses LedgerDeviceManager for session tracking and\n * SignerManager for per-session signer caching.\n */\nexport class LedgerWebHidConnector implements IConnector {\n private _deviceManager: LedgerDeviceManager | null = null;\n private _signerManager: SignerManager | null = null;\n private _dmk: IDmk | null = null;\n\n private readonly _eventHandlers = new Map<\n ConnectorEventType,\n Set<EventHandler<ConnectorEventType>>\n >();\n\n private readonly _providedDmk: IDmk | undefined;\n\n constructor(options?: LedgerWebHidConnectorOptions) {\n this._providedDmk = options?.dmk;\n if (this._providedDmk) {\n this._initManagers(this._providedDmk);\n }\n }\n\n // ---------------------------------------------------------------------------\n // IConnector — Device discovery\n // ---------------------------------------------------------------------------\n\n async searchDevices(): Promise<ConnectorDevice[]> {\n const dm = await this._getDeviceManager();\n\n let descriptors = await dm.enumerate();\n\n // If no devices found, trigger browser permission dialog via startDiscovering\n if (descriptors.length === 0) {\n try {\n await dm.requestDevice();\n } catch {\n // User may cancel the permission dialog — that's OK\n }\n descriptors = await dm.enumerate();\n }\n\n return descriptors.map((d) => ({\n connectId: d.path,\n deviceId: d.path,\n name: d.type ?? 'Ledger',\n model: d.type,\n }));\n }\n\n // ---------------------------------------------------------------------------\n // IConnector — Connection\n // ---------------------------------------------------------------------------\n\n async connect(deviceId?: string): Promise<ConnectorSession> {\n const dm = await this._getDeviceManager();\n\n // Ensure we have fresh device list\n await this.searchDevices();\n\n let resolvedDeviceId = deviceId;\n\n if (!resolvedDeviceId) {\n // Use the first available device\n const descriptors = await dm.enumerate();\n if (descriptors.length === 0) {\n throw new Error(\n 'No Ledger device found. Make sure the device is connected via USB and unlocked.',\n );\n }\n resolvedDeviceId = descriptors[0].path;\n }\n\n try {\n const sessionId = await dm.connect(resolvedDeviceId);\n\n const session: ConnectorSession = {\n sessionId,\n deviceInfo: {\n vendor: 'ledger',\n model: 'unknown',\n firmwareVersion: 'unknown',\n deviceId: resolvedDeviceId,\n connectId: resolvedDeviceId,\n connectionType: 'usb',\n },\n };\n\n this._emit('device-connect', {\n device: {\n connectId: resolvedDeviceId,\n deviceId: resolvedDeviceId,\n name: 'Ledger',\n },\n });\n\n return session;\n } catch (err) {\n // Retry once: reset and re-discover\n this._resetManagers();\n const dm2 = await this._getDeviceManager();\n await this.searchDevices();\n\n const descriptors = await dm2.enumerate();\n const retryId = deviceId\n ? descriptors.find((d) => d.path === deviceId)?.path\n : descriptors[0]?.path;\n\n if (!retryId) {\n throw new Error(\n 'No Ledger device found after retry. Make sure the device is connected via USB and unlocked.',\n );\n }\n\n const sessionId = await dm2.connect(retryId);\n\n const session: ConnectorSession = {\n sessionId,\n deviceInfo: {\n vendor: 'ledger',\n model: 'unknown',\n firmwareVersion: 'unknown',\n deviceId: retryId,\n connectId: retryId,\n connectionType: 'usb',\n },\n };\n\n this._emit('device-connect', {\n device: {\n connectId: retryId,\n deviceId: retryId,\n name: 'Ledger',\n },\n });\n\n return session;\n }\n }\n\n async disconnect(sessionId: string): Promise<void> {\n if (!this._deviceManager) return;\n\n const deviceId = this._deviceManager.getDeviceId(sessionId);\n this._signerManager?.invalidate(sessionId);\n await this._deviceManager.disconnect(sessionId);\n\n if (deviceId) {\n this._emit('device-disconnect', { connectId: deviceId });\n }\n }\n\n // ---------------------------------------------------------------------------\n // IConnector — Method dispatch\n // ---------------------------------------------------------------------------\n\n async call(\n sessionId: string,\n method: string,\n params: unknown,\n ): Promise<unknown> {\n switch (method) {\n case 'evmGetAddress':\n return this._evmGetAddress(sessionId, params as EvmGetAddressCallParams);\n case 'evmSignTransaction':\n return this._evmSignTransaction(sessionId, params as EvmSignTransactionCallParams);\n case 'evmSignMessage':\n return this._evmSignMessage(sessionId, params as EvmSignMessageCallParams);\n case 'evmSignTypedData':\n return this._evmSignTypedData(sessionId, params as EvmSignTypedDataCallParams);\n case 'btcGetAddress':\n return this._btcGetAddress(sessionId, params as BtcGetAddressCallParams);\n case 'btcGetPublicKey':\n return this._btcGetPublicKey(sessionId, params as BtcGetPublicKeyCallParams);\n default:\n throw new Error(`LedgerWebHidConnector: unknown method \"${method}\"`);\n }\n }\n\n async cancel(_sessionId: string): Promise<void> {\n // Ledger DMK doesn't expose a generic cancel mechanism\n }\n\n uiResponse(_response: { type: string; payload: unknown }): void {\n // Ledger does not use interactive UI responses (PIN/passphrase)\n }\n\n // ---------------------------------------------------------------------------\n // IConnector — Events\n // ---------------------------------------------------------------------------\n\n on<K extends ConnectorEventType>(\n event: K,\n handler: (data: ConnectorEventMap[K]) => void,\n ): void {\n if (!this._eventHandlers.has(event)) {\n this._eventHandlers.set(event, new Set());\n }\n this._eventHandlers\n .get(event)!\n .add(handler as EventHandler<ConnectorEventType>);\n }\n\n off<K extends ConnectorEventType>(\n event: K,\n handler: (data: ConnectorEventMap[K]) => void,\n ): void {\n this._eventHandlers\n .get(event)\n ?.delete(handler as EventHandler<ConnectorEventType>);\n }\n\n // ---------------------------------------------------------------------------\n // IConnector — Reset\n // ---------------------------------------------------------------------------\n\n reset(): void {\n this._resetManagers();\n }\n\n // ---------------------------------------------------------------------------\n // Private — EVM methods\n // ---------------------------------------------------------------------------\n\n private async _evmGetAddress(\n sessionId: string,\n params: EvmGetAddressCallParams,\n ): Promise<{ address: string; publicKey?: string }> {\n const signer = await this._getEthSigner(sessionId);\n const path = normalizePath(params.path);\n\n try {\n const result = await signer.getAddress(path, {\n checkOnDevice: params.showOnDevice ?? false,\n });\n return { address: result.address, publicKey: result.publicKey };\n } catch (err) {\n this._invalidateSession(sessionId);\n throw this._wrapError(err);\n }\n }\n\n private async _evmSignTransaction(\n sessionId: string,\n params: EvmSignTransactionCallParams,\n ): Promise<{ v: string; r: string; s: string }> {\n const signer = await this._getEthSigner(sessionId);\n const path = normalizePath(params.path);\n\n try {\n const result: SignerEvmSignature = await signer.signTransaction(\n path,\n params.serializedTx,\n );\n return {\n v: `0x${result.v.toString(16)}`,\n r: padHex64(result.r),\n s: padHex64(result.s),\n };\n } catch (err) {\n this._invalidateSession(sessionId);\n throw this._wrapError(err);\n }\n }\n\n private async _evmSignMessage(\n sessionId: string,\n params: EvmSignMessageCallParams,\n ): Promise<{ signature: string }> {\n const signer = await this._getEthSigner(sessionId);\n const path = normalizePath(params.path);\n\n try {\n const result: SignerEvmSignature = await signer.signMessage(\n path,\n params.message,\n );\n const rHex = stripHex(result.r).padStart(64, '0');\n const sHex = stripHex(result.s).padStart(64, '0');\n const vHex = result.v.toString(16).padStart(2, '0');\n return { signature: `0x${rHex}${sHex}${vHex}` };\n } catch (err) {\n this._invalidateSession(sessionId);\n throw this._wrapError(err);\n }\n }\n\n private async _evmSignTypedData(\n sessionId: string,\n params: EvmSignTypedDataCallParams,\n ): Promise<{ signature: string }> {\n const signer = await this._getEthSigner(sessionId);\n const path = normalizePath(params.path);\n\n try {\n const result: SignerEvmSignature = await signer.signTypedData(\n path,\n params.data,\n );\n const rHex = stripHex(result.r).padStart(64, '0');\n const sHex = stripHex(result.s).padStart(64, '0');\n const vHex = result.v.toString(16).padStart(2, '0');\n return { signature: `0x${rHex}${sHex}${vHex}` };\n } catch (err) {\n this._invalidateSession(sessionId);\n throw this._wrapError(err);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Private — BTC methods\n // ---------------------------------------------------------------------------\n\n private async _btcGetAddress(\n sessionId: string,\n params: BtcGetAddressCallParams,\n ): Promise<{ address: string; path: string }> {\n const btcSigner = await this._createBtcSigner(sessionId);\n const path = normalizePath(params.path);\n\n try {\n const { DefaultWallet, DefaultDescriptorTemplate } = await import(\n '@ledgerhq/device-signer-kit-bitcoin'\n );\n const purpose = path.split('/')[0]?.replace(\"'\", '');\n let template = DefaultDescriptorTemplate.NATIVE_SEGWIT;\n if (purpose === '44') template = DefaultDescriptorTemplate.LEGACY;\n else if (purpose === '49')\n template = DefaultDescriptorTemplate.NESTED_SEGWIT;\n else if (purpose === '86') template = DefaultDescriptorTemplate.TAPROOT;\n const wallet = new DefaultWallet(path, template);\n\n const result = await btcSigner.getWalletAddress(wallet, 0, {\n checkOnDevice: params.showOnDevice ?? false,\n change: false,\n });\n return { address: result.address, path: params.path };\n } catch (err) {\n this._invalidateSession(sessionId);\n throw this._wrapError(err);\n }\n }\n\n private async _btcGetPublicKey(\n sessionId: string,\n params: BtcGetPublicKeyCallParams,\n ): Promise<{ xpub: string; path: string }> {\n const btcSigner = await this._createBtcSigner(sessionId);\n const path = normalizePath(params.path);\n\n try {\n const xpub = await btcSigner.getExtendedPublicKey(path, {\n checkOnDevice: params.showOnDevice ?? false,\n });\n return { xpub, path: params.path };\n } catch (err) {\n this._invalidateSession(sessionId);\n throw this._wrapError(err);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Private — DMK / Manager lifecycle\n // ---------------------------------------------------------------------------\n\n /**\n * Lazily create or return the DMK instance.\n * If a DMK was provided via constructor, it is used directly.\n * Otherwise, one is created via dynamic import of the Ledger SDK.\n */\n private async _getOrCreateDmk(): Promise<IDmk> {\n if (this._dmk) return this._dmk;\n\n if (this._providedDmk) {\n this._dmk = this._providedDmk;\n return this._dmk;\n }\n\n const { DeviceManagementKitBuilder } = await import(\n '@ledgerhq/device-management-kit'\n );\n const { webHidTransportFactory } = await import(\n '@ledgerhq/device-transport-kit-web-hid'\n );\n\n this._dmk = new DeviceManagementKitBuilder()\n .addTransport(webHidTransportFactory)\n .build() as unknown as IDmk;\n\n return this._dmk;\n }\n\n private _initManagers(dmk: IDmk): void {\n this._dmk = dmk;\n this._deviceManager = new LedgerDeviceManager(dmk);\n this._signerManager = new SignerManager(dmk);\n }\n\n private async _getDeviceManager(): Promise<LedgerDeviceManager> {\n if (this._deviceManager) return this._deviceManager;\n\n const dmk = await this._getOrCreateDmk();\n this._initManagers(dmk);\n return this._deviceManager!;\n }\n\n private async _getEthSigner(sessionId: string) {\n if (!this._signerManager) {\n const dmk = await this._getOrCreateDmk();\n this._initManagers(dmk);\n }\n return this._signerManager!.getOrCreate(sessionId);\n }\n\n private async _createBtcSigner(sessionId: string): Promise<SignerBtc> {\n const dmk = await this._getOrCreateDmk();\n const { SignerBtcBuilder } = await import(\n '@ledgerhq/device-signer-kit-bitcoin'\n );\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const sdkSigner = new SignerBtcBuilder({\n dmk: dmk as any,\n sessionId,\n }).build();\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new SignerBtc(sdkSigner as any);\n }\n\n private _invalidateSession(sessionId: string): void {\n this._signerManager?.invalidate(sessionId);\n }\n\n private _resetManagers(): void {\n this._signerManager?.clearAll();\n this._deviceManager?.dispose();\n this._deviceManager = null;\n this._signerManager = null;\n this._dmk = null;\n }\n\n // ---------------------------------------------------------------------------\n // Private — Events\n // ---------------------------------------------------------------------------\n\n private _emit<K extends ConnectorEventType>(\n event: K,\n data: ConnectorEventMap[K],\n ): void {\n const handlers = this._eventHandlers.get(event);\n if (handlers) {\n for (const handler of handlers) {\n try {\n handler(data);\n } catch {\n // Don't let listener errors break the connector\n }\n }\n }\n }\n\n // ---------------------------------------------------------------------------\n // Private — Error handling\n // ---------------------------------------------------------------------------\n\n private _wrapError(err: unknown): Error {\n const mapped = mapLedgerError(err);\n const error = new Error(mapped.message);\n (error as any).code = mapped.code;\n return error;\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/LedgerWebHidConnector.ts"],"sourcesContent":["import type { IConnector } from '@bytezhang/hardware-wallet-core';\nimport type { IDmk } from '@bytezhang/ledger-adapter';\n\nimport {\n LedgerWebHidConnector,\n} from './LedgerWebHidConnector';\nimport type { LedgerWebHidConnectorOptions } from './LedgerWebHidConnector';\n\nexport { LedgerWebHidConnector };\nexport type { LedgerWebHidConnectorOptions };\n\n/**\n * Create a LedgerWebHidConnector.\n *\n * @param dmk - Optional pre-built DMK instance. If omitted, the connector\n * will lazily create one using `@ledgerhq/device-management-kit`\n * and `@ledgerhq/device-transport-kit-web-hid`.\n */\nexport function createLedgerWebHidConnector(dmk?: IDmk): IConnector {\n return new LedgerWebHidConnector({ dmk });\n}\n","import type {\n IConnector,\n ConnectorDevice,\n ConnectorSession,\n ConnectorEventType,\n ConnectorEventMap,\n} from '@bytezhang/hardware-wallet-core';\nimport type { IDmk, SignerEvmSignature } from '@bytezhang/ledger-adapter';\nimport {\n LedgerDeviceManager,\n SignerManager,\n SignerBtc,\n mapLedgerError,\n} from '@bytezhang/ledger-adapter';\n\n// ---------------------------------------------------------------------------\n// Internal types\n// ---------------------------------------------------------------------------\n\ntype EventHandler<K extends ConnectorEventType> = (\n data: ConnectorEventMap[K],\n) => void;\n\n/** Parameters for evmGetAddress */\ninterface EvmGetAddressCallParams {\n path: string;\n showOnDevice?: boolean;\n}\n\n/** Parameters for evmSignTransaction */\ninterface EvmSignTransactionCallParams {\n path: string;\n /** RLP-serialized transaction hex (0x-prefixed or plain) */\n serializedTx: string;\n}\n\n/** Parameters for evmSignMessage */\ninterface EvmSignMessageCallParams {\n path: string;\n message: string;\n}\n\n/** Parameters for evmSignTypedData */\ninterface EvmSignTypedDataCallParams {\n path: string;\n data: unknown;\n}\n\n/** Parameters for btcGetAddress */\ninterface BtcGetAddressCallParams {\n path: string;\n showOnDevice?: boolean;\n}\n\n/** Parameters for btcGetPublicKey */\ninterface BtcGetPublicKeyCallParams {\n path: string;\n showOnDevice?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Strip the \"m/\" prefix from BIP-44 derivation paths. */\nfunction normalizePath(path: string): string {\n return path.startsWith('m/') ? path.slice(2) : path;\n}\n\n/** Remove `0x` prefix from a hex string if present. */\nfunction stripHex(hex: string): string {\n return hex.startsWith('0x') ? hex.slice(2) : hex;\n}\n\n/** Ensure a hex string is `0x`-prefixed and zero-padded to 64 hex chars (32 bytes). */\nfunction padHex64(hex: string): string {\n return `0x${stripHex(hex).padStart(64, '0')}`;\n}\n\n// ---------------------------------------------------------------------------\n// LedgerWebHidConnector\n// ---------------------------------------------------------------------------\n\nexport interface LedgerWebHidConnectorOptions {\n /**\n * Pre-built DMK instance. If not provided, a DMK will be created\n * lazily on first use via `@ledgerhq/device-management-kit` and\n * `@ledgerhq/device-transport-kit-web-hid`.\n */\n dmk?: IDmk;\n}\n\n/**\n * IConnector implementation for Ledger hardware wallets via WebHID.\n *\n * Wraps the Ledger DMK (Device Management Kit) and signer kits into\n * the unified IConnector interface used by the adapter layer.\n *\n * Design:\n * - Constructor accepts an optional pre-built DMK instance (or creates one lazily).\n * - searchDevices() uses DMK's listenToAvailableDevices() observable.\n * - connect() calls dmk.connect({ device }), returns a ConnectorSession.\n * - call() dispatches to chain-specific signer methods (EVM, BTC).\n * - Internally uses LedgerDeviceManager for session tracking and\n * SignerManager for per-session signer caching.\n */\nexport class LedgerWebHidConnector implements IConnector {\n private _deviceManager: LedgerDeviceManager | null = null;\n private _signerManager: SignerManager | null = null;\n private _dmk: IDmk | null = null;\n\n private readonly _eventHandlers = new Map<\n ConnectorEventType,\n Set<EventHandler<ConnectorEventType>>\n >();\n\n private readonly _providedDmk: IDmk | undefined;\n\n constructor(options?: LedgerWebHidConnectorOptions) {\n this._providedDmk = options?.dmk;\n if (this._providedDmk) {\n this._initManagers(this._providedDmk);\n }\n }\n\n // ---------------------------------------------------------------------------\n // IConnector — Device discovery\n // ---------------------------------------------------------------------------\n\n async searchDevices(): Promise<ConnectorDevice[]> {\n const dm = await this._getDeviceManager();\n\n let descriptors = await dm.enumerate();\n\n // If no devices found, trigger browser permission dialog via startDiscovering\n if (descriptors.length === 0) {\n try {\n await dm.requestDevice();\n } catch {\n // User may cancel the permission dialog — that's OK\n }\n descriptors = await dm.enumerate();\n }\n\n console.log('[LedgerWebHidConnector] descriptors:', JSON.stringify(descriptors));\n const result: ConnectorDevice[] = descriptors.map((d) => ({\n // d.path is a temporary DMK UUID (regenerated on each discovery).\n // Used internally for routing. NOT a persistent device ID.\n connectId: d.path,\n deviceId: d.path,\n name: d.type || 'Ledger',\n model: d.type,\n capabilities: {\n // WebHID: DMK generates ephemeral UUIDs each session\n persistentDeviceIdentity: false,\n },\n }));\n console.log('[LedgerWebHidConnector] searchDevices result:', JSON.stringify(result));\n return result;\n }\n\n // ---------------------------------------------------------------------------\n // IConnector — Connection\n // ---------------------------------------------------------------------------\n\n async connect(deviceId?: string): Promise<ConnectorSession> {\n const dm = await this._getDeviceManager();\n\n // Ensure we have fresh device list\n await this.searchDevices();\n\n let resolvedDeviceId = deviceId;\n\n // Empty or missing deviceId — use first available device's DMK path\n if (!resolvedDeviceId) {\n // Use the first available device\n const descriptors = await dm.enumerate();\n if (descriptors.length === 0) {\n throw new Error(\n 'No Ledger device found. Make sure the device is connected via USB and unlocked.',\n );\n }\n resolvedDeviceId = descriptors[0].path;\n }\n\n try {\n const sessionId = await dm.connect(resolvedDeviceId);\n\n const session: ConnectorSession = {\n sessionId,\n deviceInfo: {\n vendor: 'ledger',\n model: 'unknown',\n firmwareVersion: 'unknown',\n deviceId: resolvedDeviceId,\n connectId: resolvedDeviceId,\n connectionType: 'usb',\n capabilities: {\n persistentDeviceIdentity: false,\n },\n },\n };\n\n this._emit('device-connect', {\n device: {\n connectId: resolvedDeviceId,\n deviceId: resolvedDeviceId,\n name: 'Ledger',\n },\n });\n\n return session;\n } catch (err) {\n // Retry once: reset and re-discover\n this._resetManagers();\n const dm2 = await this._getDeviceManager();\n await this.searchDevices();\n\n const descriptors = await dm2.enumerate();\n const retryId = deviceId\n ? descriptors.find((d) => d.path === deviceId)?.path\n : descriptors[0]?.path;\n\n if (!retryId) {\n throw new Error(\n 'No Ledger device found after retry. Make sure the device is connected via USB and unlocked.',\n );\n }\n\n const sessionId = await dm2.connect(retryId);\n\n const session: ConnectorSession = {\n sessionId,\n deviceInfo: {\n vendor: 'ledger',\n model: 'unknown',\n firmwareVersion: 'unknown',\n deviceId: retryId,\n connectId: retryId,\n connectionType: 'usb',\n },\n };\n\n this._emit('device-connect', {\n device: {\n connectId: retryId,\n deviceId: retryId,\n name: 'Ledger',\n },\n });\n\n return session;\n }\n }\n\n async disconnect(sessionId: string): Promise<void> {\n if (!this._deviceManager) return;\n\n const deviceId = this._deviceManager.getDeviceId(sessionId);\n this._signerManager?.invalidate(sessionId);\n await this._deviceManager.disconnect(sessionId);\n\n if (deviceId) {\n this._emit('device-disconnect', { connectId: deviceId });\n }\n }\n\n // ---------------------------------------------------------------------------\n // IConnector — Method dispatch\n // ---------------------------------------------------------------------------\n\n async call(\n sessionId: string,\n method: string,\n params: unknown,\n ): Promise<unknown> {\n switch (method) {\n case 'evmGetAddress':\n return this._evmGetAddress(sessionId, params as EvmGetAddressCallParams);\n case 'evmSignTransaction':\n return this._evmSignTransaction(sessionId, params as EvmSignTransactionCallParams);\n case 'evmSignMessage':\n return this._evmSignMessage(sessionId, params as EvmSignMessageCallParams);\n case 'evmSignTypedData':\n return this._evmSignTypedData(sessionId, params as EvmSignTypedDataCallParams);\n case 'btcGetAddress':\n return this._btcGetAddress(sessionId, params as BtcGetAddressCallParams);\n case 'btcGetPublicKey':\n return this._btcGetPublicKey(sessionId, params as BtcGetPublicKeyCallParams);\n default:\n throw new Error(`LedgerWebHidConnector: unknown method \"${method}\"`);\n }\n }\n\n async cancel(_sessionId: string): Promise<void> {\n // Ledger DMK doesn't expose a generic cancel mechanism\n }\n\n uiResponse(_response: { type: string; payload: unknown }): void {\n // Ledger does not use interactive UI responses (PIN/passphrase)\n }\n\n // ---------------------------------------------------------------------------\n // IConnector — Events\n // ---------------------------------------------------------------------------\n\n on<K extends ConnectorEventType>(\n event: K,\n handler: (data: ConnectorEventMap[K]) => void,\n ): void {\n if (!this._eventHandlers.has(event)) {\n this._eventHandlers.set(event, new Set());\n }\n this._eventHandlers\n .get(event)!\n .add(handler as EventHandler<ConnectorEventType>);\n }\n\n off<K extends ConnectorEventType>(\n event: K,\n handler: (data: ConnectorEventMap[K]) => void,\n ): void {\n this._eventHandlers\n .get(event)\n ?.delete(handler as EventHandler<ConnectorEventType>);\n }\n\n // ---------------------------------------------------------------------------\n // IConnector — Reset\n // ---------------------------------------------------------------------------\n\n reset(): void {\n this._resetManagers();\n }\n\n // ---------------------------------------------------------------------------\n // Private — EVM methods\n // ---------------------------------------------------------------------------\n\n private async _evmGetAddress(\n sessionId: string,\n params: EvmGetAddressCallParams,\n ): Promise<{ address: string; publicKey?: string }> {\n const signer = await this._getEthSigner(sessionId);\n const path = normalizePath(params.path);\n\n try {\n const result = await signer.getAddress(path, {\n checkOnDevice: params.showOnDevice ?? false,\n });\n return { address: result.address, publicKey: result.publicKey };\n } catch (err) {\n this._invalidateSession(sessionId);\n throw this._wrapError(err);\n }\n }\n\n private async _evmSignTransaction(\n sessionId: string,\n params: EvmSignTransactionCallParams,\n ): Promise<{ v: string; r: string; s: string }> {\n const signer = await this._getEthSigner(sessionId);\n const path = normalizePath(params.path);\n\n try {\n const result: SignerEvmSignature = await signer.signTransaction(\n path,\n params.serializedTx,\n );\n return {\n v: `0x${result.v.toString(16)}`,\n r: padHex64(result.r),\n s: padHex64(result.s),\n };\n } catch (err) {\n this._invalidateSession(sessionId);\n throw this._wrapError(err);\n }\n }\n\n private async _evmSignMessage(\n sessionId: string,\n params: EvmSignMessageCallParams,\n ): Promise<{ signature: string }> {\n const signer = await this._getEthSigner(sessionId);\n const path = normalizePath(params.path);\n\n try {\n const result: SignerEvmSignature = await signer.signMessage(\n path,\n params.message,\n );\n const rHex = stripHex(result.r).padStart(64, '0');\n const sHex = stripHex(result.s).padStart(64, '0');\n const vHex = result.v.toString(16).padStart(2, '0');\n return { signature: `0x${rHex}${sHex}${vHex}` };\n } catch (err) {\n this._invalidateSession(sessionId);\n throw this._wrapError(err);\n }\n }\n\n private async _evmSignTypedData(\n sessionId: string,\n params: EvmSignTypedDataCallParams,\n ): Promise<{ signature: string }> {\n const signer = await this._getEthSigner(sessionId);\n const path = normalizePath(params.path);\n\n try {\n const result: SignerEvmSignature = await signer.signTypedData(\n path,\n params.data,\n );\n const rHex = stripHex(result.r).padStart(64, '0');\n const sHex = stripHex(result.s).padStart(64, '0');\n const vHex = result.v.toString(16).padStart(2, '0');\n return { signature: `0x${rHex}${sHex}${vHex}` };\n } catch (err) {\n this._invalidateSession(sessionId);\n throw this._wrapError(err);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Private — BTC methods\n // ---------------------------------------------------------------------------\n\n private async _btcGetAddress(\n sessionId: string,\n params: BtcGetAddressCallParams,\n ): Promise<{ address: string; path: string }> {\n const btcSigner = await this._createBtcSigner(sessionId);\n const path = normalizePath(params.path);\n\n try {\n const { DefaultWallet, DefaultDescriptorTemplate } = await import(\n '@ledgerhq/device-signer-kit-bitcoin'\n );\n const purpose = path.split('/')[0]?.replace(\"'\", '');\n let template = DefaultDescriptorTemplate.NATIVE_SEGWIT;\n if (purpose === '44') template = DefaultDescriptorTemplate.LEGACY;\n else if (purpose === '49')\n template = DefaultDescriptorTemplate.NESTED_SEGWIT;\n else if (purpose === '86') template = DefaultDescriptorTemplate.TAPROOT;\n const wallet = new DefaultWallet(path, template);\n\n const result = await btcSigner.getWalletAddress(wallet, 0, {\n checkOnDevice: params.showOnDevice ?? false,\n change: false,\n });\n return { address: result.address, path: params.path };\n } catch (err) {\n this._invalidateSession(sessionId);\n throw this._wrapError(err);\n }\n }\n\n private async _btcGetPublicKey(\n sessionId: string,\n params: BtcGetPublicKeyCallParams,\n ): Promise<{ xpub: string; path: string }> {\n const btcSigner = await this._createBtcSigner(sessionId);\n const path = normalizePath(params.path);\n\n try {\n const xpub = await btcSigner.getExtendedPublicKey(path, {\n checkOnDevice: params.showOnDevice ?? false,\n });\n return { xpub, path: params.path };\n } catch (err) {\n this._invalidateSession(sessionId);\n throw this._wrapError(err);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Private — DMK / Manager lifecycle\n // ---------------------------------------------------------------------------\n\n /**\n * Lazily create or return the DMK instance.\n * If a DMK was provided via constructor, it is used directly.\n * Otherwise, one is created via dynamic import of the Ledger SDK.\n */\n private async _getOrCreateDmk(): Promise<IDmk> {\n if (this._dmk) return this._dmk;\n\n if (this._providedDmk) {\n this._dmk = this._providedDmk;\n return this._dmk;\n }\n\n const { DeviceManagementKitBuilder } = await import(\n '@ledgerhq/device-management-kit'\n );\n const { webHidTransportFactory } = await import(\n '@ledgerhq/device-transport-kit-web-hid'\n );\n\n this._dmk = new DeviceManagementKitBuilder()\n .addTransport(webHidTransportFactory)\n .build() as unknown as IDmk;\n\n return this._dmk;\n }\n\n private _initManagers(dmk: IDmk): void {\n this._dmk = dmk;\n this._deviceManager = new LedgerDeviceManager(dmk);\n this._signerManager = new SignerManager(dmk);\n }\n\n private async _getDeviceManager(): Promise<LedgerDeviceManager> {\n if (this._deviceManager) return this._deviceManager;\n\n const dmk = await this._getOrCreateDmk();\n this._initManagers(dmk);\n return this._deviceManager!;\n }\n\n private async _getEthSigner(sessionId: string) {\n if (!this._signerManager) {\n const dmk = await this._getOrCreateDmk();\n this._initManagers(dmk);\n }\n const signer = await this._signerManager!.getOrCreate(sessionId);\n\n // Wire up interaction events (open-app, unlock, verify-address, sign, etc.)\n signer.onInteraction = (interaction: string) => {\n this._emit('ui-event', {\n type: interaction,\n payload: { sessionId },\n });\n };\n\n return signer;\n }\n\n private async _createBtcSigner(sessionId: string): Promise<SignerBtc> {\n const dmk = await this._getOrCreateDmk();\n const { SignerBtcBuilder } = await import(\n '@ledgerhq/device-signer-kit-bitcoin'\n );\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const sdkSigner = new SignerBtcBuilder({\n dmk: dmk as any,\n sessionId,\n }).build();\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new SignerBtc(sdkSigner as any);\n }\n\n private _invalidateSession(sessionId: string): void {\n this._signerManager?.invalidate(sessionId);\n }\n\n private _resetManagers(): void {\n this._signerManager?.clearAll();\n this._deviceManager?.dispose();\n this._deviceManager = null;\n this._signerManager = null;\n this._dmk = null;\n }\n\n // ---------------------------------------------------------------------------\n // Private — Events\n // ---------------------------------------------------------------------------\n\n private _emit<K extends ConnectorEventType>(\n event: K,\n data: ConnectorEventMap[K],\n ): void {\n const handlers = this._eventHandlers.get(event);\n if (handlers) {\n for (const handler of handlers) {\n try {\n handler(data);\n } catch {\n // Don't let listener errors break the connector\n }\n }\n }\n }\n\n // ---------------------------------------------------------------------------\n // Private — Error handling\n // ---------------------------------------------------------------------------\n\n private _wrapError(err: unknown): Error {\n const mapped = mapLedgerError(err);\n const error = new Error(mapped.message);\n (error as any).code = mapped.code;\n return error;\n }\n}\n"],"mappings":"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","names":[]}
package/dist/index.mjs CHANGED
@@ -38,12 +38,21 @@ var LedgerWebHidConnector = class {
38
38
  }
39
39
  descriptors = await dm.enumerate();
40
40
  }
41
- return descriptors.map((d) => ({
41
+ console.log("[LedgerWebHidConnector] descriptors:", JSON.stringify(descriptors));
42
+ const result = descriptors.map((d) => ({
43
+ // d.path is a temporary DMK UUID (regenerated on each discovery).
44
+ // Used internally for routing. NOT a persistent device ID.
42
45
  connectId: d.path,
43
46
  deviceId: d.path,
44
- name: d.type ?? "Ledger",
45
- model: d.type
47
+ name: d.type || "Ledger",
48
+ model: d.type,
49
+ capabilities: {
50
+ // WebHID: DMK generates ephemeral UUIDs each session
51
+ persistentDeviceIdentity: false
52
+ }
46
53
  }));
54
+ console.log("[LedgerWebHidConnector] searchDevices result:", JSON.stringify(result));
55
+ return result;
47
56
  }
48
57
  // ---------------------------------------------------------------------------
49
58
  // IConnector — Connection
@@ -71,7 +80,10 @@ var LedgerWebHidConnector = class {
71
80
  firmwareVersion: "unknown",
72
81
  deviceId: resolvedDeviceId,
73
82
  connectId: resolvedDeviceId,
74
- connectionType: "usb"
83
+ connectionType: "usb",
84
+ capabilities: {
85
+ persistentDeviceIdentity: false
86
+ }
75
87
  }
76
88
  };
77
89
  this._emit("device-connect", {
@@ -308,7 +320,14 @@ var LedgerWebHidConnector = class {
308
320
  const dmk = await this._getOrCreateDmk();
309
321
  this._initManagers(dmk);
310
322
  }
311
- return this._signerManager.getOrCreate(sessionId);
323
+ const signer = await this._signerManager.getOrCreate(sessionId);
324
+ signer.onInteraction = (interaction) => {
325
+ this._emit("ui-event", {
326
+ type: interaction,
327
+ payload: { sessionId }
328
+ });
329
+ };
330
+ return signer;
312
331
  }
313
332
  async _createBtcSigner(sessionId) {
314
333
  const dmk = await this._getOrCreateDmk();
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/LedgerWebHidConnector.ts","../src/index.ts"],"sourcesContent":["import type {\n IConnector,\n ConnectorDevice,\n ConnectorSession,\n ConnectorEventType,\n ConnectorEventMap,\n} from '@bytezhang/hardware-wallet-core';\nimport type { IDmk, SignerEvmSignature } from '@bytezhang/ledger-adapter';\nimport {\n LedgerDeviceManager,\n SignerManager,\n SignerBtc,\n mapLedgerError,\n} from '@bytezhang/ledger-adapter';\n\n// ---------------------------------------------------------------------------\n// Internal types\n// ---------------------------------------------------------------------------\n\ntype EventHandler<K extends ConnectorEventType> = (\n data: ConnectorEventMap[K],\n) => void;\n\n/** Parameters for evmGetAddress */\ninterface EvmGetAddressCallParams {\n path: string;\n showOnDevice?: boolean;\n}\n\n/** Parameters for evmSignTransaction */\ninterface EvmSignTransactionCallParams {\n path: string;\n /** RLP-serialized transaction hex (0x-prefixed or plain) */\n serializedTx: string;\n}\n\n/** Parameters for evmSignMessage */\ninterface EvmSignMessageCallParams {\n path: string;\n message: string;\n}\n\n/** Parameters for evmSignTypedData */\ninterface EvmSignTypedDataCallParams {\n path: string;\n data: unknown;\n}\n\n/** Parameters for btcGetAddress */\ninterface BtcGetAddressCallParams {\n path: string;\n showOnDevice?: boolean;\n}\n\n/** Parameters for btcGetPublicKey */\ninterface BtcGetPublicKeyCallParams {\n path: string;\n showOnDevice?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Strip the \"m/\" prefix from BIP-44 derivation paths. */\nfunction normalizePath(path: string): string {\n return path.startsWith('m/') ? path.slice(2) : path;\n}\n\n/** Remove `0x` prefix from a hex string if present. */\nfunction stripHex(hex: string): string {\n return hex.startsWith('0x') ? hex.slice(2) : hex;\n}\n\n/** Ensure a hex string is `0x`-prefixed and zero-padded to 64 hex chars (32 bytes). */\nfunction padHex64(hex: string): string {\n return `0x${stripHex(hex).padStart(64, '0')}`;\n}\n\n// ---------------------------------------------------------------------------\n// LedgerWebHidConnector\n// ---------------------------------------------------------------------------\n\nexport interface LedgerWebHidConnectorOptions {\n /**\n * Pre-built DMK instance. If not provided, a DMK will be created\n * lazily on first use via `@ledgerhq/device-management-kit` and\n * `@ledgerhq/device-transport-kit-web-hid`.\n */\n dmk?: IDmk;\n}\n\n/**\n * IConnector implementation for Ledger hardware wallets via WebHID.\n *\n * Wraps the Ledger DMK (Device Management Kit) and signer kits into\n * the unified IConnector interface used by the adapter layer.\n *\n * Design:\n * - Constructor accepts an optional pre-built DMK instance (or creates one lazily).\n * - searchDevices() uses DMK's listenToAvailableDevices() observable.\n * - connect() calls dmk.connect({ device }), returns a ConnectorSession.\n * - call() dispatches to chain-specific signer methods (EVM, BTC).\n * - Internally uses LedgerDeviceManager for session tracking and\n * SignerManager for per-session signer caching.\n */\nexport class LedgerWebHidConnector implements IConnector {\n private _deviceManager: LedgerDeviceManager | null = null;\n private _signerManager: SignerManager | null = null;\n private _dmk: IDmk | null = null;\n\n private readonly _eventHandlers = new Map<\n ConnectorEventType,\n Set<EventHandler<ConnectorEventType>>\n >();\n\n private readonly _providedDmk: IDmk | undefined;\n\n constructor(options?: LedgerWebHidConnectorOptions) {\n this._providedDmk = options?.dmk;\n if (this._providedDmk) {\n this._initManagers(this._providedDmk);\n }\n }\n\n // ---------------------------------------------------------------------------\n // IConnector — Device discovery\n // ---------------------------------------------------------------------------\n\n async searchDevices(): Promise<ConnectorDevice[]> {\n const dm = await this._getDeviceManager();\n\n let descriptors = await dm.enumerate();\n\n // If no devices found, trigger browser permission dialog via startDiscovering\n if (descriptors.length === 0) {\n try {\n await dm.requestDevice();\n } catch {\n // User may cancel the permission dialog — that's OK\n }\n descriptors = await dm.enumerate();\n }\n\n return descriptors.map((d) => ({\n connectId: d.path,\n deviceId: d.path,\n name: d.type ?? 'Ledger',\n model: d.type,\n }));\n }\n\n // ---------------------------------------------------------------------------\n // IConnector — Connection\n // ---------------------------------------------------------------------------\n\n async connect(deviceId?: string): Promise<ConnectorSession> {\n const dm = await this._getDeviceManager();\n\n // Ensure we have fresh device list\n await this.searchDevices();\n\n let resolvedDeviceId = deviceId;\n\n if (!resolvedDeviceId) {\n // Use the first available device\n const descriptors = await dm.enumerate();\n if (descriptors.length === 0) {\n throw new Error(\n 'No Ledger device found. Make sure the device is connected via USB and unlocked.',\n );\n }\n resolvedDeviceId = descriptors[0].path;\n }\n\n try {\n const sessionId = await dm.connect(resolvedDeviceId);\n\n const session: ConnectorSession = {\n sessionId,\n deviceInfo: {\n vendor: 'ledger',\n model: 'unknown',\n firmwareVersion: 'unknown',\n deviceId: resolvedDeviceId,\n connectId: resolvedDeviceId,\n connectionType: 'usb',\n },\n };\n\n this._emit('device-connect', {\n device: {\n connectId: resolvedDeviceId,\n deviceId: resolvedDeviceId,\n name: 'Ledger',\n },\n });\n\n return session;\n } catch (err) {\n // Retry once: reset and re-discover\n this._resetManagers();\n const dm2 = await this._getDeviceManager();\n await this.searchDevices();\n\n const descriptors = await dm2.enumerate();\n const retryId = deviceId\n ? descriptors.find((d) => d.path === deviceId)?.path\n : descriptors[0]?.path;\n\n if (!retryId) {\n throw new Error(\n 'No Ledger device found after retry. Make sure the device is connected via USB and unlocked.',\n );\n }\n\n const sessionId = await dm2.connect(retryId);\n\n const session: ConnectorSession = {\n sessionId,\n deviceInfo: {\n vendor: 'ledger',\n model: 'unknown',\n firmwareVersion: 'unknown',\n deviceId: retryId,\n connectId: retryId,\n connectionType: 'usb',\n },\n };\n\n this._emit('device-connect', {\n device: {\n connectId: retryId,\n deviceId: retryId,\n name: 'Ledger',\n },\n });\n\n return session;\n }\n }\n\n async disconnect(sessionId: string): Promise<void> {\n if (!this._deviceManager) return;\n\n const deviceId = this._deviceManager.getDeviceId(sessionId);\n this._signerManager?.invalidate(sessionId);\n await this._deviceManager.disconnect(sessionId);\n\n if (deviceId) {\n this._emit('device-disconnect', { connectId: deviceId });\n }\n }\n\n // ---------------------------------------------------------------------------\n // IConnector — Method dispatch\n // ---------------------------------------------------------------------------\n\n async call(\n sessionId: string,\n method: string,\n params: unknown,\n ): Promise<unknown> {\n switch (method) {\n case 'evmGetAddress':\n return this._evmGetAddress(sessionId, params as EvmGetAddressCallParams);\n case 'evmSignTransaction':\n return this._evmSignTransaction(sessionId, params as EvmSignTransactionCallParams);\n case 'evmSignMessage':\n return this._evmSignMessage(sessionId, params as EvmSignMessageCallParams);\n case 'evmSignTypedData':\n return this._evmSignTypedData(sessionId, params as EvmSignTypedDataCallParams);\n case 'btcGetAddress':\n return this._btcGetAddress(sessionId, params as BtcGetAddressCallParams);\n case 'btcGetPublicKey':\n return this._btcGetPublicKey(sessionId, params as BtcGetPublicKeyCallParams);\n default:\n throw new Error(`LedgerWebHidConnector: unknown method \"${method}\"`);\n }\n }\n\n async cancel(_sessionId: string): Promise<void> {\n // Ledger DMK doesn't expose a generic cancel mechanism\n }\n\n uiResponse(_response: { type: string; payload: unknown }): void {\n // Ledger does not use interactive UI responses (PIN/passphrase)\n }\n\n // ---------------------------------------------------------------------------\n // IConnector — Events\n // ---------------------------------------------------------------------------\n\n on<K extends ConnectorEventType>(\n event: K,\n handler: (data: ConnectorEventMap[K]) => void,\n ): void {\n if (!this._eventHandlers.has(event)) {\n this._eventHandlers.set(event, new Set());\n }\n this._eventHandlers\n .get(event)!\n .add(handler as EventHandler<ConnectorEventType>);\n }\n\n off<K extends ConnectorEventType>(\n event: K,\n handler: (data: ConnectorEventMap[K]) => void,\n ): void {\n this._eventHandlers\n .get(event)\n ?.delete(handler as EventHandler<ConnectorEventType>);\n }\n\n // ---------------------------------------------------------------------------\n // IConnector — Reset\n // ---------------------------------------------------------------------------\n\n reset(): void {\n this._resetManagers();\n }\n\n // ---------------------------------------------------------------------------\n // Private — EVM methods\n // ---------------------------------------------------------------------------\n\n private async _evmGetAddress(\n sessionId: string,\n params: EvmGetAddressCallParams,\n ): Promise<{ address: string; publicKey?: string }> {\n const signer = await this._getEthSigner(sessionId);\n const path = normalizePath(params.path);\n\n try {\n const result = await signer.getAddress(path, {\n checkOnDevice: params.showOnDevice ?? false,\n });\n return { address: result.address, publicKey: result.publicKey };\n } catch (err) {\n this._invalidateSession(sessionId);\n throw this._wrapError(err);\n }\n }\n\n private async _evmSignTransaction(\n sessionId: string,\n params: EvmSignTransactionCallParams,\n ): Promise<{ v: string; r: string; s: string }> {\n const signer = await this._getEthSigner(sessionId);\n const path = normalizePath(params.path);\n\n try {\n const result: SignerEvmSignature = await signer.signTransaction(\n path,\n params.serializedTx,\n );\n return {\n v: `0x${result.v.toString(16)}`,\n r: padHex64(result.r),\n s: padHex64(result.s),\n };\n } catch (err) {\n this._invalidateSession(sessionId);\n throw this._wrapError(err);\n }\n }\n\n private async _evmSignMessage(\n sessionId: string,\n params: EvmSignMessageCallParams,\n ): Promise<{ signature: string }> {\n const signer = await this._getEthSigner(sessionId);\n const path = normalizePath(params.path);\n\n try {\n const result: SignerEvmSignature = await signer.signMessage(\n path,\n params.message,\n );\n const rHex = stripHex(result.r).padStart(64, '0');\n const sHex = stripHex(result.s).padStart(64, '0');\n const vHex = result.v.toString(16).padStart(2, '0');\n return { signature: `0x${rHex}${sHex}${vHex}` };\n } catch (err) {\n this._invalidateSession(sessionId);\n throw this._wrapError(err);\n }\n }\n\n private async _evmSignTypedData(\n sessionId: string,\n params: EvmSignTypedDataCallParams,\n ): Promise<{ signature: string }> {\n const signer = await this._getEthSigner(sessionId);\n const path = normalizePath(params.path);\n\n try {\n const result: SignerEvmSignature = await signer.signTypedData(\n path,\n params.data,\n );\n const rHex = stripHex(result.r).padStart(64, '0');\n const sHex = stripHex(result.s).padStart(64, '0');\n const vHex = result.v.toString(16).padStart(2, '0');\n return { signature: `0x${rHex}${sHex}${vHex}` };\n } catch (err) {\n this._invalidateSession(sessionId);\n throw this._wrapError(err);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Private — BTC methods\n // ---------------------------------------------------------------------------\n\n private async _btcGetAddress(\n sessionId: string,\n params: BtcGetAddressCallParams,\n ): Promise<{ address: string; path: string }> {\n const btcSigner = await this._createBtcSigner(sessionId);\n const path = normalizePath(params.path);\n\n try {\n const { DefaultWallet, DefaultDescriptorTemplate } = await import(\n '@ledgerhq/device-signer-kit-bitcoin'\n );\n const purpose = path.split('/')[0]?.replace(\"'\", '');\n let template = DefaultDescriptorTemplate.NATIVE_SEGWIT;\n if (purpose === '44') template = DefaultDescriptorTemplate.LEGACY;\n else if (purpose === '49')\n template = DefaultDescriptorTemplate.NESTED_SEGWIT;\n else if (purpose === '86') template = DefaultDescriptorTemplate.TAPROOT;\n const wallet = new DefaultWallet(path, template);\n\n const result = await btcSigner.getWalletAddress(wallet, 0, {\n checkOnDevice: params.showOnDevice ?? false,\n change: false,\n });\n return { address: result.address, path: params.path };\n } catch (err) {\n this._invalidateSession(sessionId);\n throw this._wrapError(err);\n }\n }\n\n private async _btcGetPublicKey(\n sessionId: string,\n params: BtcGetPublicKeyCallParams,\n ): Promise<{ xpub: string; path: string }> {\n const btcSigner = await this._createBtcSigner(sessionId);\n const path = normalizePath(params.path);\n\n try {\n const xpub = await btcSigner.getExtendedPublicKey(path, {\n checkOnDevice: params.showOnDevice ?? false,\n });\n return { xpub, path: params.path };\n } catch (err) {\n this._invalidateSession(sessionId);\n throw this._wrapError(err);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Private — DMK / Manager lifecycle\n // ---------------------------------------------------------------------------\n\n /**\n * Lazily create or return the DMK instance.\n * If a DMK was provided via constructor, it is used directly.\n * Otherwise, one is created via dynamic import of the Ledger SDK.\n */\n private async _getOrCreateDmk(): Promise<IDmk> {\n if (this._dmk) return this._dmk;\n\n if (this._providedDmk) {\n this._dmk = this._providedDmk;\n return this._dmk;\n }\n\n const { DeviceManagementKitBuilder } = await import(\n '@ledgerhq/device-management-kit'\n );\n const { webHidTransportFactory } = await import(\n '@ledgerhq/device-transport-kit-web-hid'\n );\n\n this._dmk = new DeviceManagementKitBuilder()\n .addTransport(webHidTransportFactory)\n .build() as unknown as IDmk;\n\n return this._dmk;\n }\n\n private _initManagers(dmk: IDmk): void {\n this._dmk = dmk;\n this._deviceManager = new LedgerDeviceManager(dmk);\n this._signerManager = new SignerManager(dmk);\n }\n\n private async _getDeviceManager(): Promise<LedgerDeviceManager> {\n if (this._deviceManager) return this._deviceManager;\n\n const dmk = await this._getOrCreateDmk();\n this._initManagers(dmk);\n return this._deviceManager!;\n }\n\n private async _getEthSigner(sessionId: string) {\n if (!this._signerManager) {\n const dmk = await this._getOrCreateDmk();\n this._initManagers(dmk);\n }\n return this._signerManager!.getOrCreate(sessionId);\n }\n\n private async _createBtcSigner(sessionId: string): Promise<SignerBtc> {\n const dmk = await this._getOrCreateDmk();\n const { SignerBtcBuilder } = await import(\n '@ledgerhq/device-signer-kit-bitcoin'\n );\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const sdkSigner = new SignerBtcBuilder({\n dmk: dmk as any,\n sessionId,\n }).build();\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new SignerBtc(sdkSigner as any);\n }\n\n private _invalidateSession(sessionId: string): void {\n this._signerManager?.invalidate(sessionId);\n }\n\n private _resetManagers(): void {\n this._signerManager?.clearAll();\n this._deviceManager?.dispose();\n this._deviceManager = null;\n this._signerManager = null;\n this._dmk = null;\n }\n\n // ---------------------------------------------------------------------------\n // Private — Events\n // ---------------------------------------------------------------------------\n\n private _emit<K extends ConnectorEventType>(\n event: K,\n data: ConnectorEventMap[K],\n ): void {\n const handlers = this._eventHandlers.get(event);\n if (handlers) {\n for (const handler of handlers) {\n try {\n handler(data);\n } catch {\n // Don't let listener errors break the connector\n }\n }\n }\n }\n\n // ---------------------------------------------------------------------------\n // Private — Error handling\n // ---------------------------------------------------------------------------\n\n private _wrapError(err: unknown): Error {\n const mapped = mapLedgerError(err);\n const error = new Error(mapped.message);\n (error as any).code = mapped.code;\n return error;\n }\n}\n","import type { IConnector } from '@bytezhang/hardware-wallet-core';\nimport type { IDmk } from '@bytezhang/ledger-adapter';\n\nimport {\n LedgerWebHidConnector,\n} from './LedgerWebHidConnector';\nimport type { LedgerWebHidConnectorOptions } from './LedgerWebHidConnector';\n\nexport { LedgerWebHidConnector };\nexport type { LedgerWebHidConnectorOptions };\n\n/**\n * Create a LedgerWebHidConnector.\n *\n * @param dmk - Optional pre-built DMK instance. If omitted, the connector\n * will lazily create one using `@ledgerhq/device-management-kit`\n * and `@ledgerhq/device-transport-kit-web-hid`.\n */\nexport function createLedgerWebHidConnector(dmk?: IDmk): IConnector {\n return new LedgerWebHidConnector({ dmk });\n}\n"],"mappings":";AAQA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAoDP,SAAS,cAAc,MAAsB;AAC3C,SAAO,KAAK,WAAW,IAAI,IAAI,KAAK,MAAM,CAAC,IAAI;AACjD;AAGA,SAAS,SAAS,KAAqB;AACrC,SAAO,IAAI,WAAW,IAAI,IAAI,IAAI,MAAM,CAAC,IAAI;AAC/C;AAGA,SAAS,SAAS,KAAqB;AACrC,SAAO,KAAK,SAAS,GAAG,EAAE,SAAS,IAAI,GAAG,CAAC;AAC7C;AA6BO,IAAM,wBAAN,MAAkD;AAAA,EAYvD,YAAY,SAAwC;AAXpD,SAAQ,iBAA6C;AACrD,SAAQ,iBAAuC;AAC/C,SAAQ,OAAoB;AAE5B,SAAiB,iBAAiB,oBAAI,IAGpC;AAKA,SAAK,eAAe,SAAS;AAC7B,QAAI,KAAK,cAAc;AACrB,WAAK,cAAc,KAAK,YAAY;AAAA,IACtC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,gBAA4C;AAChD,UAAM,KAAK,MAAM,KAAK,kBAAkB;AAExC,QAAI,cAAc,MAAM,GAAG,UAAU;AAGrC,QAAI,YAAY,WAAW,GAAG;AAC5B,UAAI;AACF,cAAM,GAAG,cAAc;AAAA,MACzB,QAAQ;AAAA,MAER;AACA,oBAAc,MAAM,GAAG,UAAU;AAAA,IACnC;AAEA,WAAO,YAAY,IAAI,CAAC,OAAO;AAAA,MAC7B,WAAW,EAAE;AAAA,MACb,UAAU,EAAE;AAAA,MACZ,MAAM,EAAE,QAAQ;AAAA,MAChB,OAAO,EAAE;AAAA,IACX,EAAE;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,QAAQ,UAA8C;AAC1D,UAAM,KAAK,MAAM,KAAK,kBAAkB;AAGxC,UAAM,KAAK,cAAc;AAEzB,QAAI,mBAAmB;AAEvB,QAAI,CAAC,kBAAkB;AAErB,YAAM,cAAc,MAAM,GAAG,UAAU;AACvC,UAAI,YAAY,WAAW,GAAG;AAC5B,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAAA,MACF;AACA,yBAAmB,YAAY,CAAC,EAAE;AAAA,IACpC;AAEA,QAAI;AACF,YAAM,YAAY,MAAM,GAAG,QAAQ,gBAAgB;AAEnD,YAAM,UAA4B;AAAA,QAChC;AAAA,QACA,YAAY;AAAA,UACV,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,iBAAiB;AAAA,UACjB,UAAU;AAAA,UACV,WAAW;AAAA,UACX,gBAAgB;AAAA,QAClB;AAAA,MACF;AAEA,WAAK,MAAM,kBAAkB;AAAA,QAC3B,QAAQ;AAAA,UACN,WAAW;AAAA,UACX,UAAU;AAAA,UACV,MAAM;AAAA,QACR;AAAA,MACF,CAAC;AAED,aAAO;AAAA,IACT,SAAS,KAAK;AAEZ,WAAK,eAAe;AACpB,YAAM,MAAM,MAAM,KAAK,kBAAkB;AACzC,YAAM,KAAK,cAAc;AAEzB,YAAM,cAAc,MAAM,IAAI,UAAU;AACxC,YAAM,UAAU,WACZ,YAAY,KAAK,CAAC,MAAM,EAAE,SAAS,QAAQ,GAAG,OAC9C,YAAY,CAAC,GAAG;AAEpB,UAAI,CAAC,SAAS;AACZ,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAEA,YAAM,YAAY,MAAM,IAAI,QAAQ,OAAO;AAE3C,YAAM,UAA4B;AAAA,QAChC;AAAA,QACA,YAAY;AAAA,UACV,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,iBAAiB;AAAA,UACjB,UAAU;AAAA,UACV,WAAW;AAAA,UACX,gBAAgB;AAAA,QAClB;AAAA,MACF;AAEA,WAAK,MAAM,kBAAkB;AAAA,QAC3B,QAAQ;AAAA,UACN,WAAW;AAAA,UACX,UAAU;AAAA,UACV,MAAM;AAAA,QACR;AAAA,MACF,CAAC;AAED,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAM,WAAW,WAAkC;AACjD,QAAI,CAAC,KAAK,eAAgB;AAE1B,UAAM,WAAW,KAAK,eAAe,YAAY,SAAS;AAC1D,SAAK,gBAAgB,WAAW,SAAS;AACzC,UAAM,KAAK,eAAe,WAAW,SAAS;AAE9C,QAAI,UAAU;AACZ,WAAK,MAAM,qBAAqB,EAAE,WAAW,SAAS,CAAC;AAAA,IACzD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,KACJ,WACA,QACA,QACkB;AAClB,YAAQ,QAAQ;AAAA,MACd,KAAK;AACH,eAAO,KAAK,eAAe,WAAW,MAAiC;AAAA,MACzE,KAAK;AACH,eAAO,KAAK,oBAAoB,WAAW,MAAsC;AAAA,MACnF,KAAK;AACH,eAAO,KAAK,gBAAgB,WAAW,MAAkC;AAAA,MAC3E,KAAK;AACH,eAAO,KAAK,kBAAkB,WAAW,MAAoC;AAAA,MAC/E,KAAK;AACH,eAAO,KAAK,eAAe,WAAW,MAAiC;AAAA,MACzE,KAAK;AACH,eAAO,KAAK,iBAAiB,WAAW,MAAmC;AAAA,MAC7E;AACE,cAAM,IAAI,MAAM,0CAA0C,MAAM,GAAG;AAAA,IACvE;AAAA,EACF;AAAA,EAEA,MAAM,OAAO,YAAmC;AAAA,EAEhD;AAAA,EAEA,WAAW,WAAqD;AAAA,EAEhE;AAAA;AAAA;AAAA;AAAA,EAMA,GACE,OACA,SACM;AACN,QAAI,CAAC,KAAK,eAAe,IAAI,KAAK,GAAG;AACnC,WAAK,eAAe,IAAI,OAAO,oBAAI,IAAI,CAAC;AAAA,IAC1C;AACA,SAAK,eACF,IAAI,KAAK,EACT,IAAI,OAA2C;AAAA,EACpD;AAAA,EAEA,IACE,OACA,SACM;AACN,SAAK,eACF,IAAI,KAAK,GACR,OAAO,OAA2C;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA,EAMA,QAAc;AACZ,SAAK,eAAe;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,eACZ,WACA,QACkD;AAClD,UAAM,SAAS,MAAM,KAAK,cAAc,SAAS;AACjD,UAAM,OAAO,cAAc,OAAO,IAAI;AAEtC,QAAI;AACF,YAAM,SAAS,MAAM,OAAO,WAAW,MAAM;AAAA,QAC3C,eAAe,OAAO,gBAAgB;AAAA,MACxC,CAAC;AACD,aAAO,EAAE,SAAS,OAAO,SAAS,WAAW,OAAO,UAAU;AAAA,IAChE,SAAS,KAAK;AACZ,WAAK,mBAAmB,SAAS;AACjC,YAAM,KAAK,WAAW,GAAG;AAAA,IAC3B;AAAA,EACF;AAAA,EAEA,MAAc,oBACZ,WACA,QAC8C;AAC9C,UAAM,SAAS,MAAM,KAAK,cAAc,SAAS;AACjD,UAAM,OAAO,cAAc,OAAO,IAAI;AAEtC,QAAI;AACF,YAAM,SAA6B,MAAM,OAAO;AAAA,QAC9C;AAAA,QACA,OAAO;AAAA,MACT;AACA,aAAO;AAAA,QACL,GAAG,KAAK,OAAO,EAAE,SAAS,EAAE,CAAC;AAAA,QAC7B,GAAG,SAAS,OAAO,CAAC;AAAA,QACpB,GAAG,SAAS,OAAO,CAAC;AAAA,MACtB;AAAA,IACF,SAAS,KAAK;AACZ,WAAK,mBAAmB,SAAS;AACjC,YAAM,KAAK,WAAW,GAAG;AAAA,IAC3B;AAAA,EACF;AAAA,EAEA,MAAc,gBACZ,WACA,QACgC;AAChC,UAAM,SAAS,MAAM,KAAK,cAAc,SAAS;AACjD,UAAM,OAAO,cAAc,OAAO,IAAI;AAEtC,QAAI;AACF,YAAM,SAA6B,MAAM,OAAO;AAAA,QAC9C;AAAA,QACA,OAAO;AAAA,MACT;AACA,YAAM,OAAO,SAAS,OAAO,CAAC,EAAE,SAAS,IAAI,GAAG;AAChD,YAAM,OAAO,SAAS,OAAO,CAAC,EAAE,SAAS,IAAI,GAAG;AAChD,YAAM,OAAO,OAAO,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG;AAClD,aAAO,EAAE,WAAW,KAAK,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG;AAAA,IAChD,SAAS,KAAK;AACZ,WAAK,mBAAmB,SAAS;AACjC,YAAM,KAAK,WAAW,GAAG;AAAA,IAC3B;AAAA,EACF;AAAA,EAEA,MAAc,kBACZ,WACA,QACgC;AAChC,UAAM,SAAS,MAAM,KAAK,cAAc,SAAS;AACjD,UAAM,OAAO,cAAc,OAAO,IAAI;AAEtC,QAAI;AACF,YAAM,SAA6B,MAAM,OAAO;AAAA,QAC9C;AAAA,QACA,OAAO;AAAA,MACT;AACA,YAAM,OAAO,SAAS,OAAO,CAAC,EAAE,SAAS,IAAI,GAAG;AAChD,YAAM,OAAO,SAAS,OAAO,CAAC,EAAE,SAAS,IAAI,GAAG;AAChD,YAAM,OAAO,OAAO,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG;AAClD,aAAO,EAAE,WAAW,KAAK,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG;AAAA,IAChD,SAAS,KAAK;AACZ,WAAK,mBAAmB,SAAS;AACjC,YAAM,KAAK,WAAW,GAAG;AAAA,IAC3B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,eACZ,WACA,QAC4C;AAC5C,UAAM,YAAY,MAAM,KAAK,iBAAiB,SAAS;AACvD,UAAM,OAAO,cAAc,OAAO,IAAI;AAEtC,QAAI;AACF,YAAM,EAAE,eAAe,0BAA0B,IAAI,MAAM,OACzD,qCACF;AACA,YAAM,UAAU,KAAK,MAAM,GAAG,EAAE,CAAC,GAAG,QAAQ,KAAK,EAAE;AACnD,UAAI,WAAW,0BAA0B;AACzC,UAAI,YAAY,KAAM,YAAW,0BAA0B;AAAA,eAClD,YAAY;AACnB,mBAAW,0BAA0B;AAAA,eAC9B,YAAY,KAAM,YAAW,0BAA0B;AAChE,YAAM,SAAS,IAAI,cAAc,MAAM,QAAQ;AAE/C,YAAM,SAAS,MAAM,UAAU,iBAAiB,QAAQ,GAAG;AAAA,QACzD,eAAe,OAAO,gBAAgB;AAAA,QACtC,QAAQ;AAAA,MACV,CAAC;AACD,aAAO,EAAE,SAAS,OAAO,SAAS,MAAM,OAAO,KAAK;AAAA,IACtD,SAAS,KAAK;AACZ,WAAK,mBAAmB,SAAS;AACjC,YAAM,KAAK,WAAW,GAAG;AAAA,IAC3B;AAAA,EACF;AAAA,EAEA,MAAc,iBACZ,WACA,QACyC;AACzC,UAAM,YAAY,MAAM,KAAK,iBAAiB,SAAS;AACvD,UAAM,OAAO,cAAc,OAAO,IAAI;AAEtC,QAAI;AACF,YAAM,OAAO,MAAM,UAAU,qBAAqB,MAAM;AAAA,QACtD,eAAe,OAAO,gBAAgB;AAAA,MACxC,CAAC;AACD,aAAO,EAAE,MAAM,MAAM,OAAO,KAAK;AAAA,IACnC,SAAS,KAAK;AACZ,WAAK,mBAAmB,SAAS;AACjC,YAAM,KAAK,WAAW,GAAG;AAAA,IAC3B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAc,kBAAiC;AAC7C,QAAI,KAAK,KAAM,QAAO,KAAK;AAE3B,QAAI,KAAK,cAAc;AACrB,WAAK,OAAO,KAAK;AACjB,aAAO,KAAK;AAAA,IACd;AAEA,UAAM,EAAE,2BAA2B,IAAI,MAAM,OAC3C,iCACF;AACA,UAAM,EAAE,uBAAuB,IAAI,MAAM,OACvC,wCACF;AAEA,SAAK,OAAO,IAAI,2BAA2B,EACxC,aAAa,sBAAsB,EACnC,MAAM;AAET,WAAO,KAAK;AAAA,EACd;AAAA,EAEQ,cAAc,KAAiB;AACrC,SAAK,OAAO;AACZ,SAAK,iBAAiB,IAAI,oBAAoB,GAAG;AACjD,SAAK,iBAAiB,IAAI,cAAc,GAAG;AAAA,EAC7C;AAAA,EAEA,MAAc,oBAAkD;AAC9D,QAAI,KAAK,eAAgB,QAAO,KAAK;AAErC,UAAM,MAAM,MAAM,KAAK,gBAAgB;AACvC,SAAK,cAAc,GAAG;AACtB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAc,cAAc,WAAmB;AAC7C,QAAI,CAAC,KAAK,gBAAgB;AACxB,YAAM,MAAM,MAAM,KAAK,gBAAgB;AACvC,WAAK,cAAc,GAAG;AAAA,IACxB;AACA,WAAO,KAAK,eAAgB,YAAY,SAAS;AAAA,EACnD;AAAA,EAEA,MAAc,iBAAiB,WAAuC;AACpE,UAAM,MAAM,MAAM,KAAK,gBAAgB;AACvC,UAAM,EAAE,iBAAiB,IAAI,MAAM,OACjC,qCACF;AAEA,UAAM,YAAY,IAAI,iBAAiB;AAAA,MACrC;AAAA,MACA;AAAA,IACF,CAAC,EAAE,MAAM;AAET,WAAO,IAAI,UAAU,SAAgB;AAAA,EACvC;AAAA,EAEQ,mBAAmB,WAAyB;AAClD,SAAK,gBAAgB,WAAW,SAAS;AAAA,EAC3C;AAAA,EAEQ,iBAAuB;AAC7B,SAAK,gBAAgB,SAAS;AAC9B,SAAK,gBAAgB,QAAQ;AAC7B,SAAK,iBAAiB;AACtB,SAAK,iBAAiB;AACtB,SAAK,OAAO;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAMQ,MACN,OACA,MACM;AACN,UAAM,WAAW,KAAK,eAAe,IAAI,KAAK;AAC9C,QAAI,UAAU;AACZ,iBAAW,WAAW,UAAU;AAC9B,YAAI;AACF,kBAAQ,IAAI;AAAA,QACd,QAAQ;AAAA,QAER;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMQ,WAAW,KAAqB;AACtC,UAAM,SAAS,eAAe,GAAG;AACjC,UAAM,QAAQ,IAAI,MAAM,OAAO,OAAO;AACtC,IAAC,MAAc,OAAO,OAAO;AAC7B,WAAO;AAAA,EACT;AACF;;;AC1iBO,SAAS,4BAA4B,KAAwB;AAClE,SAAO,IAAI,sBAAsB,EAAE,IAAI,CAAC;AAC1C;","names":[]}
1
+ {"version":3,"sources":["../src/LedgerWebHidConnector.ts","../src/index.ts"],"sourcesContent":["import type {\n IConnector,\n ConnectorDevice,\n ConnectorSession,\n ConnectorEventType,\n ConnectorEventMap,\n} from '@bytezhang/hardware-wallet-core';\nimport type { IDmk, SignerEvmSignature } from '@bytezhang/ledger-adapter';\nimport {\n LedgerDeviceManager,\n SignerManager,\n SignerBtc,\n mapLedgerError,\n} from '@bytezhang/ledger-adapter';\n\n// ---------------------------------------------------------------------------\n// Internal types\n// ---------------------------------------------------------------------------\n\ntype EventHandler<K extends ConnectorEventType> = (\n data: ConnectorEventMap[K],\n) => void;\n\n/** Parameters for evmGetAddress */\ninterface EvmGetAddressCallParams {\n path: string;\n showOnDevice?: boolean;\n}\n\n/** Parameters for evmSignTransaction */\ninterface EvmSignTransactionCallParams {\n path: string;\n /** RLP-serialized transaction hex (0x-prefixed or plain) */\n serializedTx: string;\n}\n\n/** Parameters for evmSignMessage */\ninterface EvmSignMessageCallParams {\n path: string;\n message: string;\n}\n\n/** Parameters for evmSignTypedData */\ninterface EvmSignTypedDataCallParams {\n path: string;\n data: unknown;\n}\n\n/** Parameters for btcGetAddress */\ninterface BtcGetAddressCallParams {\n path: string;\n showOnDevice?: boolean;\n}\n\n/** Parameters for btcGetPublicKey */\ninterface BtcGetPublicKeyCallParams {\n path: string;\n showOnDevice?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Strip the \"m/\" prefix from BIP-44 derivation paths. */\nfunction normalizePath(path: string): string {\n return path.startsWith('m/') ? path.slice(2) : path;\n}\n\n/** Remove `0x` prefix from a hex string if present. */\nfunction stripHex(hex: string): string {\n return hex.startsWith('0x') ? hex.slice(2) : hex;\n}\n\n/** Ensure a hex string is `0x`-prefixed and zero-padded to 64 hex chars (32 bytes). */\nfunction padHex64(hex: string): string {\n return `0x${stripHex(hex).padStart(64, '0')}`;\n}\n\n// ---------------------------------------------------------------------------\n// LedgerWebHidConnector\n// ---------------------------------------------------------------------------\n\nexport interface LedgerWebHidConnectorOptions {\n /**\n * Pre-built DMK instance. If not provided, a DMK will be created\n * lazily on first use via `@ledgerhq/device-management-kit` and\n * `@ledgerhq/device-transport-kit-web-hid`.\n */\n dmk?: IDmk;\n}\n\n/**\n * IConnector implementation for Ledger hardware wallets via WebHID.\n *\n * Wraps the Ledger DMK (Device Management Kit) and signer kits into\n * the unified IConnector interface used by the adapter layer.\n *\n * Design:\n * - Constructor accepts an optional pre-built DMK instance (or creates one lazily).\n * - searchDevices() uses DMK's listenToAvailableDevices() observable.\n * - connect() calls dmk.connect({ device }), returns a ConnectorSession.\n * - call() dispatches to chain-specific signer methods (EVM, BTC).\n * - Internally uses LedgerDeviceManager for session tracking and\n * SignerManager for per-session signer caching.\n */\nexport class LedgerWebHidConnector implements IConnector {\n private _deviceManager: LedgerDeviceManager | null = null;\n private _signerManager: SignerManager | null = null;\n private _dmk: IDmk | null = null;\n\n private readonly _eventHandlers = new Map<\n ConnectorEventType,\n Set<EventHandler<ConnectorEventType>>\n >();\n\n private readonly _providedDmk: IDmk | undefined;\n\n constructor(options?: LedgerWebHidConnectorOptions) {\n this._providedDmk = options?.dmk;\n if (this._providedDmk) {\n this._initManagers(this._providedDmk);\n }\n }\n\n // ---------------------------------------------------------------------------\n // IConnector — Device discovery\n // ---------------------------------------------------------------------------\n\n async searchDevices(): Promise<ConnectorDevice[]> {\n const dm = await this._getDeviceManager();\n\n let descriptors = await dm.enumerate();\n\n // If no devices found, trigger browser permission dialog via startDiscovering\n if (descriptors.length === 0) {\n try {\n await dm.requestDevice();\n } catch {\n // User may cancel the permission dialog — that's OK\n }\n descriptors = await dm.enumerate();\n }\n\n console.log('[LedgerWebHidConnector] descriptors:', JSON.stringify(descriptors));\n const result: ConnectorDevice[] = descriptors.map((d) => ({\n // d.path is a temporary DMK UUID (regenerated on each discovery).\n // Used internally for routing. NOT a persistent device ID.\n connectId: d.path,\n deviceId: d.path,\n name: d.type || 'Ledger',\n model: d.type,\n capabilities: {\n // WebHID: DMK generates ephemeral UUIDs each session\n persistentDeviceIdentity: false,\n },\n }));\n console.log('[LedgerWebHidConnector] searchDevices result:', JSON.stringify(result));\n return result;\n }\n\n // ---------------------------------------------------------------------------\n // IConnector — Connection\n // ---------------------------------------------------------------------------\n\n async connect(deviceId?: string): Promise<ConnectorSession> {\n const dm = await this._getDeviceManager();\n\n // Ensure we have fresh device list\n await this.searchDevices();\n\n let resolvedDeviceId = deviceId;\n\n // Empty or missing deviceId — use first available device's DMK path\n if (!resolvedDeviceId) {\n // Use the first available device\n const descriptors = await dm.enumerate();\n if (descriptors.length === 0) {\n throw new Error(\n 'No Ledger device found. Make sure the device is connected via USB and unlocked.',\n );\n }\n resolvedDeviceId = descriptors[0].path;\n }\n\n try {\n const sessionId = await dm.connect(resolvedDeviceId);\n\n const session: ConnectorSession = {\n sessionId,\n deviceInfo: {\n vendor: 'ledger',\n model: 'unknown',\n firmwareVersion: 'unknown',\n deviceId: resolvedDeviceId,\n connectId: resolvedDeviceId,\n connectionType: 'usb',\n capabilities: {\n persistentDeviceIdentity: false,\n },\n },\n };\n\n this._emit('device-connect', {\n device: {\n connectId: resolvedDeviceId,\n deviceId: resolvedDeviceId,\n name: 'Ledger',\n },\n });\n\n return session;\n } catch (err) {\n // Retry once: reset and re-discover\n this._resetManagers();\n const dm2 = await this._getDeviceManager();\n await this.searchDevices();\n\n const descriptors = await dm2.enumerate();\n const retryId = deviceId\n ? descriptors.find((d) => d.path === deviceId)?.path\n : descriptors[0]?.path;\n\n if (!retryId) {\n throw new Error(\n 'No Ledger device found after retry. Make sure the device is connected via USB and unlocked.',\n );\n }\n\n const sessionId = await dm2.connect(retryId);\n\n const session: ConnectorSession = {\n sessionId,\n deviceInfo: {\n vendor: 'ledger',\n model: 'unknown',\n firmwareVersion: 'unknown',\n deviceId: retryId,\n connectId: retryId,\n connectionType: 'usb',\n },\n };\n\n this._emit('device-connect', {\n device: {\n connectId: retryId,\n deviceId: retryId,\n name: 'Ledger',\n },\n });\n\n return session;\n }\n }\n\n async disconnect(sessionId: string): Promise<void> {\n if (!this._deviceManager) return;\n\n const deviceId = this._deviceManager.getDeviceId(sessionId);\n this._signerManager?.invalidate(sessionId);\n await this._deviceManager.disconnect(sessionId);\n\n if (deviceId) {\n this._emit('device-disconnect', { connectId: deviceId });\n }\n }\n\n // ---------------------------------------------------------------------------\n // IConnector — Method dispatch\n // ---------------------------------------------------------------------------\n\n async call(\n sessionId: string,\n method: string,\n params: unknown,\n ): Promise<unknown> {\n switch (method) {\n case 'evmGetAddress':\n return this._evmGetAddress(sessionId, params as EvmGetAddressCallParams);\n case 'evmSignTransaction':\n return this._evmSignTransaction(sessionId, params as EvmSignTransactionCallParams);\n case 'evmSignMessage':\n return this._evmSignMessage(sessionId, params as EvmSignMessageCallParams);\n case 'evmSignTypedData':\n return this._evmSignTypedData(sessionId, params as EvmSignTypedDataCallParams);\n case 'btcGetAddress':\n return this._btcGetAddress(sessionId, params as BtcGetAddressCallParams);\n case 'btcGetPublicKey':\n return this._btcGetPublicKey(sessionId, params as BtcGetPublicKeyCallParams);\n default:\n throw new Error(`LedgerWebHidConnector: unknown method \"${method}\"`);\n }\n }\n\n async cancel(_sessionId: string): Promise<void> {\n // Ledger DMK doesn't expose a generic cancel mechanism\n }\n\n uiResponse(_response: { type: string; payload: unknown }): void {\n // Ledger does not use interactive UI responses (PIN/passphrase)\n }\n\n // ---------------------------------------------------------------------------\n // IConnector — Events\n // ---------------------------------------------------------------------------\n\n on<K extends ConnectorEventType>(\n event: K,\n handler: (data: ConnectorEventMap[K]) => void,\n ): void {\n if (!this._eventHandlers.has(event)) {\n this._eventHandlers.set(event, new Set());\n }\n this._eventHandlers\n .get(event)!\n .add(handler as EventHandler<ConnectorEventType>);\n }\n\n off<K extends ConnectorEventType>(\n event: K,\n handler: (data: ConnectorEventMap[K]) => void,\n ): void {\n this._eventHandlers\n .get(event)\n ?.delete(handler as EventHandler<ConnectorEventType>);\n }\n\n // ---------------------------------------------------------------------------\n // IConnector — Reset\n // ---------------------------------------------------------------------------\n\n reset(): void {\n this._resetManagers();\n }\n\n // ---------------------------------------------------------------------------\n // Private — EVM methods\n // ---------------------------------------------------------------------------\n\n private async _evmGetAddress(\n sessionId: string,\n params: EvmGetAddressCallParams,\n ): Promise<{ address: string; publicKey?: string }> {\n const signer = await this._getEthSigner(sessionId);\n const path = normalizePath(params.path);\n\n try {\n const result = await signer.getAddress(path, {\n checkOnDevice: params.showOnDevice ?? false,\n });\n return { address: result.address, publicKey: result.publicKey };\n } catch (err) {\n this._invalidateSession(sessionId);\n throw this._wrapError(err);\n }\n }\n\n private async _evmSignTransaction(\n sessionId: string,\n params: EvmSignTransactionCallParams,\n ): Promise<{ v: string; r: string; s: string }> {\n const signer = await this._getEthSigner(sessionId);\n const path = normalizePath(params.path);\n\n try {\n const result: SignerEvmSignature = await signer.signTransaction(\n path,\n params.serializedTx,\n );\n return {\n v: `0x${result.v.toString(16)}`,\n r: padHex64(result.r),\n s: padHex64(result.s),\n };\n } catch (err) {\n this._invalidateSession(sessionId);\n throw this._wrapError(err);\n }\n }\n\n private async _evmSignMessage(\n sessionId: string,\n params: EvmSignMessageCallParams,\n ): Promise<{ signature: string }> {\n const signer = await this._getEthSigner(sessionId);\n const path = normalizePath(params.path);\n\n try {\n const result: SignerEvmSignature = await signer.signMessage(\n path,\n params.message,\n );\n const rHex = stripHex(result.r).padStart(64, '0');\n const sHex = stripHex(result.s).padStart(64, '0');\n const vHex = result.v.toString(16).padStart(2, '0');\n return { signature: `0x${rHex}${sHex}${vHex}` };\n } catch (err) {\n this._invalidateSession(sessionId);\n throw this._wrapError(err);\n }\n }\n\n private async _evmSignTypedData(\n sessionId: string,\n params: EvmSignTypedDataCallParams,\n ): Promise<{ signature: string }> {\n const signer = await this._getEthSigner(sessionId);\n const path = normalizePath(params.path);\n\n try {\n const result: SignerEvmSignature = await signer.signTypedData(\n path,\n params.data,\n );\n const rHex = stripHex(result.r).padStart(64, '0');\n const sHex = stripHex(result.s).padStart(64, '0');\n const vHex = result.v.toString(16).padStart(2, '0');\n return { signature: `0x${rHex}${sHex}${vHex}` };\n } catch (err) {\n this._invalidateSession(sessionId);\n throw this._wrapError(err);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Private — BTC methods\n // ---------------------------------------------------------------------------\n\n private async _btcGetAddress(\n sessionId: string,\n params: BtcGetAddressCallParams,\n ): Promise<{ address: string; path: string }> {\n const btcSigner = await this._createBtcSigner(sessionId);\n const path = normalizePath(params.path);\n\n try {\n const { DefaultWallet, DefaultDescriptorTemplate } = await import(\n '@ledgerhq/device-signer-kit-bitcoin'\n );\n const purpose = path.split('/')[0]?.replace(\"'\", '');\n let template = DefaultDescriptorTemplate.NATIVE_SEGWIT;\n if (purpose === '44') template = DefaultDescriptorTemplate.LEGACY;\n else if (purpose === '49')\n template = DefaultDescriptorTemplate.NESTED_SEGWIT;\n else if (purpose === '86') template = DefaultDescriptorTemplate.TAPROOT;\n const wallet = new DefaultWallet(path, template);\n\n const result = await btcSigner.getWalletAddress(wallet, 0, {\n checkOnDevice: params.showOnDevice ?? false,\n change: false,\n });\n return { address: result.address, path: params.path };\n } catch (err) {\n this._invalidateSession(sessionId);\n throw this._wrapError(err);\n }\n }\n\n private async _btcGetPublicKey(\n sessionId: string,\n params: BtcGetPublicKeyCallParams,\n ): Promise<{ xpub: string; path: string }> {\n const btcSigner = await this._createBtcSigner(sessionId);\n const path = normalizePath(params.path);\n\n try {\n const xpub = await btcSigner.getExtendedPublicKey(path, {\n checkOnDevice: params.showOnDevice ?? false,\n });\n return { xpub, path: params.path };\n } catch (err) {\n this._invalidateSession(sessionId);\n throw this._wrapError(err);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Private — DMK / Manager lifecycle\n // ---------------------------------------------------------------------------\n\n /**\n * Lazily create or return the DMK instance.\n * If a DMK was provided via constructor, it is used directly.\n * Otherwise, one is created via dynamic import of the Ledger SDK.\n */\n private async _getOrCreateDmk(): Promise<IDmk> {\n if (this._dmk) return this._dmk;\n\n if (this._providedDmk) {\n this._dmk = this._providedDmk;\n return this._dmk;\n }\n\n const { DeviceManagementKitBuilder } = await import(\n '@ledgerhq/device-management-kit'\n );\n const { webHidTransportFactory } = await import(\n '@ledgerhq/device-transport-kit-web-hid'\n );\n\n this._dmk = new DeviceManagementKitBuilder()\n .addTransport(webHidTransportFactory)\n .build() as unknown as IDmk;\n\n return this._dmk;\n }\n\n private _initManagers(dmk: IDmk): void {\n this._dmk = dmk;\n this._deviceManager = new LedgerDeviceManager(dmk);\n this._signerManager = new SignerManager(dmk);\n }\n\n private async _getDeviceManager(): Promise<LedgerDeviceManager> {\n if (this._deviceManager) return this._deviceManager;\n\n const dmk = await this._getOrCreateDmk();\n this._initManagers(dmk);\n return this._deviceManager!;\n }\n\n private async _getEthSigner(sessionId: string) {\n if (!this._signerManager) {\n const dmk = await this._getOrCreateDmk();\n this._initManagers(dmk);\n }\n const signer = await this._signerManager!.getOrCreate(sessionId);\n\n // Wire up interaction events (open-app, unlock, verify-address, sign, etc.)\n signer.onInteraction = (interaction: string) => {\n this._emit('ui-event', {\n type: interaction,\n payload: { sessionId },\n });\n };\n\n return signer;\n }\n\n private async _createBtcSigner(sessionId: string): Promise<SignerBtc> {\n const dmk = await this._getOrCreateDmk();\n const { SignerBtcBuilder } = await import(\n '@ledgerhq/device-signer-kit-bitcoin'\n );\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const sdkSigner = new SignerBtcBuilder({\n dmk: dmk as any,\n sessionId,\n }).build();\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new SignerBtc(sdkSigner as any);\n }\n\n private _invalidateSession(sessionId: string): void {\n this._signerManager?.invalidate(sessionId);\n }\n\n private _resetManagers(): void {\n this._signerManager?.clearAll();\n this._deviceManager?.dispose();\n this._deviceManager = null;\n this._signerManager = null;\n this._dmk = null;\n }\n\n // ---------------------------------------------------------------------------\n // Private — Events\n // ---------------------------------------------------------------------------\n\n private _emit<K extends ConnectorEventType>(\n event: K,\n data: ConnectorEventMap[K],\n ): void {\n const handlers = this._eventHandlers.get(event);\n if (handlers) {\n for (const handler of handlers) {\n try {\n handler(data);\n } catch {\n // Don't let listener errors break the connector\n }\n }\n }\n }\n\n // ---------------------------------------------------------------------------\n // Private — Error handling\n // ---------------------------------------------------------------------------\n\n private _wrapError(err: unknown): Error {\n const mapped = mapLedgerError(err);\n const error = new Error(mapped.message);\n (error as any).code = mapped.code;\n return error;\n }\n}\n","import type { IConnector } from '@bytezhang/hardware-wallet-core';\nimport type { IDmk } from '@bytezhang/ledger-adapter';\n\nimport {\n LedgerWebHidConnector,\n} from './LedgerWebHidConnector';\nimport type { LedgerWebHidConnectorOptions } from './LedgerWebHidConnector';\n\nexport { LedgerWebHidConnector };\nexport type { LedgerWebHidConnectorOptions };\n\n/**\n * Create a LedgerWebHidConnector.\n *\n * @param dmk - Optional pre-built DMK instance. If omitted, the connector\n * will lazily create one using `@ledgerhq/device-management-kit`\n * and `@ledgerhq/device-transport-kit-web-hid`.\n */\nexport function createLedgerWebHidConnector(dmk?: IDmk): IConnector {\n return new LedgerWebHidConnector({ dmk });\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bytezhang/hardware-ledger-connector-webhid",
3
- "version": "0.0.1",
3
+ "version": "0.0.4",
4
4
  "description": "IConnector implementation for Ledger hardware wallets via WebHID (DMK)",
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",
@@ -46,7 +54,9 @@
46
54
  "@ledgerhq/device-transport-kit-web-hid": "^1.0.0"
47
55
  },
48
56
  "peerDependenciesMeta": {
49
- "@ledgerhq/device-signer-kit-bitcoin": { "optional": true }
57
+ "@ledgerhq/device-signer-kit-bitcoin": {
58
+ "optional": true
59
+ }
50
60
  },
51
61
  "devDependencies": {
52
62
  "@ledgerhq/device-management-kit": "^1.1.0",