@onekeyfe/hwk-keystone-connector-usb 1.2.8-alpha.13 → 1.2.8-alpha.52

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.
@@ -66,7 +66,7 @@ function mapKeystoneUsbError(err) {
66
66
  const fromDevice = isDeviceStatus(statusCode);
67
67
  let code = fromDevice ? DEVICE_STATUS_MAP[statusCode] ?? HardwareErrorCode.UnknownError : CLIENT_STATUS_MAP[statusCode] ?? HardwareErrorCode.TransportError;
68
68
  if (statusCode === Status.PRS_PARSING_DISALLOWED && !/\blocked\b/i.test(message)) {
69
- code = HardwareErrorCode.DeviceBusy;
69
+ code = HardwareErrorCode.DeviceBusyInternal;
70
70
  }
71
71
  let origin;
72
72
  if (fromDevice) {
@@ -93,7 +93,6 @@ function mapKeystoneUsbError(err) {
93
93
 
94
94
  // src/KeystoneUsbConnectorBase.ts
95
95
  import { UR, URDecoder, UREncoder } from "@ngraveio/bc-ur";
96
- import bytewords from "@ngraveio/bc-ur/dist/bytewords";
97
96
  import { Actions } from "@keystonehq/hw-transport-usb";
98
97
  import {
99
98
  EConnectorInteraction,
@@ -148,10 +147,7 @@ function readFountainPart(input) {
148
147
  function assertBoundedUrPart(part) {
149
148
  const match = /^ur:[a-z0-9-]+\/(?:(\d{1,9})-(\d{1,9})\/)?([a-z]+)$/i.exec(part);
150
149
  if (!match) throw new Error("Keystone USB reply part is not a UR");
151
- const payload = Buffer.from(
152
- bytewords.decode(match[3].toLowerCase(), bytewords.STYLES.MINIMAL),
153
- "hex"
154
- );
150
+ const payload = URDecoder.decode(`ur:bytes/${match[3].toLowerCase()}`).cbor;
155
151
  assertBoundedCbor(payload, MAX_UR_MESSAGE_BYTES);
156
152
  if (match[1] === void 0) return;
157
153
  const header = readFountainPart(payload);
@@ -170,7 +166,8 @@ function fromUrEncoded(encoded) {
170
166
  decoder.receivePart(part);
171
167
  if (decoder.isComplete()) break;
172
168
  }
173
- } catch {
169
+ } catch (error) {
170
+ if (error instanceof TypeError || error instanceof ReferenceError) throw error;
174
171
  }
175
172
  if (!parts.length || !decoder.isComplete() || !decoder.isSuccess()) {
176
173
  const shape = typeof encoded === "string" ? `string len=${text.length} parts=${parts.length}` : typeof encoded;
@@ -635,4 +632,4 @@ export {
635
632
  mapKeystoneUsbError,
636
633
  KeystoneUsbConnectorBase
637
634
  };
638
- //# sourceMappingURL=chunk-RZ6UI5PS.mjs.map
635
+ //# sourceMappingURL=chunk-I3VFU34J.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/errors.ts","../src/KeystoneUsbConnectorBase.ts"],"sourcesContent":["import { HardwareErrorCode, createHwkError } from '@onekeyfe/hwk-adapter-core';\nimport { Status } from '@keystonehq/hw-transport-error';\n\nimport type { HwkError, HwkErrorOrigin } from '@onekeyfe/hwk-adapter-core';\n\n/**\n * Firmware status words are the low end of `Status` (0..15); client codes start at\n * `ERR_DEVICE_NOT_OPENED` (0xA0000001), so anything below came from a device response frame.\n */\nfunction isDeviceStatus(statusCode: number): boolean {\n return statusCode >= 0 && statusCode < Status.ERR_DEVICE_NOT_OPENED;\n}\n\n/** Firmware status words from a device response (EAPDU_Readme.md in the Keystone USB SDK). */\nconst DEVICE_STATUS_MAP: Partial<Record<number, HardwareErrorCode>> = {\n [Status.RSP_FAILURE_CODE]: HardwareErrorCode.UnknownError,\n [Status.PRS_INVALID_TOTAL_PACKETS]: HardwareErrorCode.InvalidParams,\n [Status.PRS_INVALID_INDEX]: HardwareErrorCode.InvalidParams,\n [Status.PRS_PARSING_REJECTED]: HardwareErrorCode.UserRejected,\n [Status.PRS_PARSING_ERROR]: HardwareErrorCode.InvalidParams,\n [Status.PRS_PARSING_DISALLOWED]: HardwareErrorCode.DeviceLocked,\n [Status.PRS_PARSING_UNMATCHED]: HardwareErrorCode.InvalidParams,\n [Status.PRS_PARSING_MISMATCHED_WALLET]: HardwareErrorCode.DeviceMismatch,\n [Status.PRS_PARSING_VERIFY_PASSWORD_ERROR]: HardwareErrorCode.PinInvalid,\n [Status.PRS_EXPORT_ADDRESS_UNSUPPORTED_CHAIN]: HardwareErrorCode.ChainNotSupported,\n [Status.PRS_EXPORT_ADDRESS_INVALID_PARAMS]: HardwareErrorCode.InvalidParams,\n [Status.PRS_EXPORT_ADDRESS_ERROR]: HardwareErrorCode.UnknownError,\n [Status.PRS_EXPORT_ADDRESS_DISALLOWED]: HardwareErrorCode.DeviceLocked,\n [Status.PRS_EXPORT_ADDRESS_REJECTED]: HardwareErrorCode.UserRejected,\n [Status.PRS_EXPORT_ADDRESS_BUSY]: HardwareErrorCode.DeviceBusyInternal,\n};\n\n/** Used when the transport forwarded only its 'unknown error' placeholder for a firmware status. */\nconst DEVICE_STATUS_MESSAGE: Partial<Record<number, string>> = {\n [Status.RSP_FAILURE_CODE]: 'Keystone reported a failure',\n [Status.PRS_INVALID_TOTAL_PACKETS]: 'Keystone rejected the request framing (total packets)',\n [Status.PRS_INVALID_INDEX]: 'Keystone rejected the request framing (packet index)',\n [Status.PRS_PARSING_REJECTED]: 'Rejected on the Keystone screen',\n [Status.PRS_PARSING_ERROR]: 'Keystone could not parse the request',\n [Status.PRS_PARSING_DISALLOWED]: 'Keystone declined the request in its current state',\n [Status.PRS_PARSING_UNMATCHED]: 'Keystone found no handler for the request',\n [Status.PRS_PARSING_MISMATCHED_WALLET]: 'The request belongs to a different Keystone wallet',\n [Status.PRS_PARSING_VERIFY_PASSWORD_ERROR]: 'Keystone password verification failed',\n [Status.PRS_EXPORT_ADDRESS_UNSUPPORTED_CHAIN]: 'Keystone does not support this chain',\n [Status.PRS_EXPORT_ADDRESS_INVALID_PARAMS]: 'Keystone rejected the address export parameters',\n [Status.PRS_EXPORT_ADDRESS_ERROR]: 'Keystone failed to export the address',\n [Status.PRS_EXPORT_ADDRESS_DISALLOWED]: 'Keystone declined to export the address',\n [Status.PRS_EXPORT_ADDRESS_REJECTED]: 'Address export rejected on the Keystone screen',\n [Status.PRS_EXPORT_ADDRESS_BUSY]: 'Keystone is busy with another request',\n};\n\n/** The placeholder both Keystone transports use when they have nothing better. */\nconst PLACEHOLDER_MESSAGE = /^unknown error\\b/i;\n\n/** Client-side (transport/framing) failures, never reached the device. */\nconst CLIENT_STATUS_MAP: Partial<Record<number, HardwareErrorCode>> = {\n [Status.ERR_DEVICE_NOT_OPENED]: HardwareErrorCode.DeviceNotFound,\n [Status.ERR_DEVICE_NOT_FOUND]: HardwareErrorCode.DeviceNotFound,\n [Status.ERR_TIMEOUT]: HardwareErrorCode.OperationTimeout,\n [Status.ERR_DATA_TOO_LARGE]: HardwareErrorCode.PayloadTooLarge,\n [Status.ERR_NOT_SUPPORTED]: HardwareErrorCode.TransportNotAvailable,\n};\n\n/** WebUSB DOMExceptions; an unplug or bus reset mid-call is the common case. */\nconst DOM_EXCEPTION_MAP = new Map<string, { code: HardwareErrorCode; origin: HwkErrorOrigin }>([\n ['NotFoundError', { code: HardwareErrorCode.DeviceNotFound, origin: 'transport' }],\n ['NetworkError', { code: HardwareErrorCode.DeviceNotFound, origin: 'transport' }],\n ['SecurityError', { code: HardwareErrorCode.DevicePermissionDenied, origin: 'host' }],\n ['NotAllowedError', { code: HardwareErrorCode.DevicePermissionDenied, origin: 'host' }],\n ['InvalidStateError', { code: HardwareErrorCode.DeviceBusy, origin: 'transport' }],\n ['AbortError', { code: HardwareErrorCode.DeviceBusy, origin: 'transport' }],\n]);\n\n/**\n * Maps a Keystone USB SDK failure to `HardwareErrorCode`. Fields are read duck-typed because\n * duplicate `@keystonehq/*` module instances break `instanceof`.\n */\nexport function mapKeystoneUsbError(err: unknown): HwkError {\n const fields: { name?: unknown; code?: unknown; transportErrorCode?: unknown } =\n err && typeof err === 'object' ? err : {};\n const domName = typeof fields.name === 'string' ? fields.name : undefined;\n\n // Only five-digit codes are HWK codes; legacy DOMException codes (NotFoundError\n // is 8) must not pass through as hardware errors.\n if (typeof fields.code === 'number' && fields.code >= 10000 && fields.code <= 99999) {\n return err as HwkError;\n }\n\n const statusCode =\n typeof fields.transportErrorCode === 'number' ? fields.transportErrorCode : undefined;\n\n const message = err instanceof Error ? err.message : String(err);\n\n if (statusCode !== undefined) {\n const fromDevice = isDeviceStatus(statusCode);\n // An unlisted firmware status keeps origin 'device'; 'transport' would make the\n // adapter tear down a live session over an on-device decline.\n let code = fromDevice\n ? DEVICE_STATUS_MAP[statusCode] ?? HardwareErrorCode.UnknownError\n : CLIENT_STATUS_MAP[statusCode] ?? HardwareErrorCode.TransportError;\n // Firmware also returns PRS_PARSING_DISALLOWED for an unfinished request, a pending approval\n // and a screen that takes no requests; only its \"Device is locked\" text means locked.\n if (statusCode === Status.PRS_PARSING_DISALLOWED && !/\\blocked\\b/i.test(message)) {\n code = HardwareErrorCode.DeviceBusyInternal;\n }\n let origin: HwkErrorOrigin | undefined;\n if (fromDevice) {\n origin = 'device';\n } else if (code !== HardwareErrorCode.OperationTimeout) {\n origin = 'transport';\n }\n const description = DEVICE_STATUS_MESSAGE[statusCode];\n return createHwkError({\n code,\n // The device's own payload text wins over the table.\n message:\n description && PLACEHOLDER_MESSAGE.test(message)\n ? `${description} (error_code: ${statusCode})`\n : message,\n // A timeout may be either side, so it stays unlabeled.\n origin,\n params: { statusCode, details: (err as { details?: string }).details },\n });\n }\n\n const domMapping = domName ? DOM_EXCEPTION_MAP.get(domName) : undefined;\n if (domMapping) {\n return createHwkError({ ...domMapping, message, params: { domExceptionName: domName } });\n }\n\n // This mapper only wraps transport calls, so 'transport' names the throw site.\n return createHwkError({ code: HardwareErrorCode.TransportError, message, origin: 'transport' });\n}\n","import { UR, URDecoder, UREncoder } from '@ngraveio/bc-ur';\nimport { Actions } from '@keystonehq/hw-transport-usb';\nimport {\n EConnectorInteraction,\n HardwareErrorCode,\n MISSING_BIP32_MASTER_FINGERPRINT,\n TypedEventEmitter,\n assertBoundedCbor,\n createHardwareLinkId,\n createHardwareSearchTargetId,\n createHwkError,\n hasHardwareRuntimeIdPrefix,\n parseBip32MasterFingerprint,\n parseHardwareRuntimeId,\n serializeConnectorError,\n success,\n} from '@onekeyfe/hwk-adapter-core';\n\nimport { mapKeystoneUsbError } from './errors';\n\nimport type {\n ConnectorCallResult,\n ConnectorConnectTarget,\n ConnectorDevice,\n ConnectorEventMap,\n ConnectorEventType,\n ConnectorSearchDevicesOptions,\n ConnectorSession,\n IConnector,\n UiResponseEvent,\n} from '@onekeyfe/hwk-adapter-core';\nimport type { TransportConfig, TransportHID } from '@keystonehq/hw-transport-usb';\n\n/** Descriptor fields readable before opening; any may be absent if not published. */\nexport interface KeystoneUsbDeviceDescriptor {\n serialNumber?: string;\n productName?: string;\n manufacturerName?: string;\n vendorId?: number;\n productId?: number;\n /** Device release number (bcdDevice), split into its three nibble groups. */\n deviceVersionMajor?: number;\n deviceVersionMinor?: number;\n deviceVersionSubminor?: number;\n usbVersionMajor?: number;\n usbVersionMinor?: number;\n usbVersionSubminor?: number;\n deviceClass?: number;\n deviceSubclass?: number;\n deviceProtocol?: number;\n}\n\n/** The serial is not shown on the unit, so it would not help tell two devices apart. */\nfunction usbDisplayName(device: KeystoneUsbDeviceDescriptor): string {\n return device.productName?.trim() || 'Keystone';\n}\n\n/** Static surface of `TransportWebUSB`, injected by `_subpath/webusb`. */\nexport interface KeystoneUsbTransportStatic {\n connect(config?: TransportConfig): Promise<TransportHID>;\n connectDevice?(\n device: KeystoneUsbDeviceDescriptor,\n config?: TransportConfig\n ): Promise<TransportHID>;\n getKeystoneDevices(): Promise<ReadonlyArray<KeystoneUsbDeviceDescriptor>>;\n requestPermission?(): Promise<void>;\n isSupported(): Promise<boolean>;\n /** Release transport-lifetime resources owned by the platform wrapper. */\n disposeTransport?(transport: TransportHID): void;\n}\n\ninterface KeystoneUr {\n urType: string;\n urData: string;\n}\n\ninterface UsbSession {\n transport: TransportHID;\n mfp?: string;\n dispose(): void;\n}\n\ninterface AppConfig {\n version?: string;\n mfp?: string;\n}\n\ninterface OpenedUsbTransport {\n transport: TransportHID;\n bindSessionId(sessionId: string): void;\n dispose(): void;\n}\n\ntype KeystoneUsbConnectInput =\n | { searchTargetId: string; expectedMasterFingerprint?: never }\n | { searchTargetId?: never; expectedMasterFingerprint: string }\n | { searchTargetId?: never; expectedMasterFingerprint?: never };\n\n// The SDK default of 15s is too short for on-device confirmation.\nconst DEFAULT_TIMEOUT_MS = 100_000;\n\nconst KEYSTONE_PUBLIC_DATA_UR_TYPE = 'qr-hardware-call';\n\nfunction toUrEncoded(ur: KeystoneUr): string {\n return new UREncoder(new UR(Buffer.from(ur.urData, 'hex'), ur.urType), Infinity)\n .nextPart()\n .toUpperCase();\n}\n\n/** The most data one reply may carry, whatever its fragment size. */\nconst MAX_UR_MESSAGE_BYTES = 1024 * 1024;\n/**\n * The fountain decoder's work per mixed part grows with the square of the part count, so a reply\n * cut into tiny fragments can stall it even within the byte limit.\n */\nconst MAX_UR_SEQ_LENGTH = 32_768;\n/** Argument bytes for CBOR additional info 24, 25, 26 and 27. */\nconst CBOR_ARGUMENT_BYTES = [1, 2, 4, 8];\n\n/** Reads `[seqNum, seqLen, messageLen, checksum, fragment]` from CBOR that passed the bounds. */\nfunction readFountainPart(input: Uint8Array) {\n let offset = 0;\n const readHead = (expectedMajor: number): number => {\n const initial = input[offset];\n offset += 1;\n if (Math.floor(initial / 32) !== expectedMajor) {\n throw new Error('Keystone USB reply part is not a fountain part');\n }\n const info = initial % 32;\n if (info < 24) return info;\n const size = CBOR_ARGUMENT_BYTES[info - 24];\n let value = 0;\n for (let i = 0; i < size; i += 1) value = value * 256 + input[offset + i];\n offset += size;\n return value;\n };\n if (readHead(4) !== 5) throw new Error('Keystone USB reply part is not a fountain part');\n const seqNum = readHead(0);\n const seqLength = readHead(0);\n const messageLength = readHead(0);\n readHead(0); // checksum\n const fragmentLength = readHead(2);\n return { seqNum, seqLength, messageLength, fragmentLength };\n}\n\n/** Checks one UR part from the device before the vendor decoder parses its CBOR. */\nfunction assertBoundedUrPart(part: string): void {\n const match = /^ur:[a-z0-9-]+\\/(?:(\\d{1,9})-(\\d{1,9})\\/)?([a-z]+)$/i.exec(part);\n if (!match) throw new Error('Keystone USB reply part is not a UR');\n // Decodes the minimal bytewords body (CRC32-checked, throws on a mismatch) through the package\n // root: a deep `dist/` import breaks strict ESM consumers of this package's `.mjs` build.\n const payload = URDecoder.decode(`ur:bytes/${match[3].toLowerCase()}`).cbor;\n assertBoundedCbor(payload, MAX_UR_MESSAGE_BYTES);\n if (match[1] === undefined) return;\n const header = readFountainPart(payload);\n // The text header, the CBOR header and the real sizes must agree, so the declared part count\n // is tied to the data the reply actually carries. USB is lossless and Keystone answers with a\n // single-part UR, so a mixed fountain part (seqNum past seqLen) is refused: decoding each one\n // costs time quadratic in the part count.\n if (\n header.seqNum < 1 ||\n header.seqNum > header.seqLength ||\n header.seqNum !== Number(match[1]) ||\n header.seqLength !== Number(match[2]) ||\n header.fragmentLength < 1 ||\n header.messageLength < 1 ||\n header.messageLength > MAX_UR_MESSAGE_BYTES ||\n header.seqLength > MAX_UR_SEQ_LENGTH ||\n header.seqLength !== Math.ceil(header.messageLength / header.fragmentLength)\n ) {\n throw new Error('Keystone USB reply part has inconsistent or oversized headers');\n }\n}\n\nfunction fromUrEncoded(encoded: unknown): KeystoneUr {\n // One complete UR or whitespace-separated parts; EAPDU framing is the transport's job.\n const text = typeof encoded === 'string' ? encoded.trim() : '';\n const parts = text.split(/\\s+/).filter(Boolean);\n const decoder = new URDecoder();\n try {\n if (parts.length > MAX_UR_SEQ_LENGTH) throw new Error('Keystone USB reply has too many parts');\n for (const part of parts) {\n assertBoundedUrPart(part);\n decoder.receivePart(part);\n if (decoder.isComplete()) break;\n }\n } catch (error) {\n // A part that does not decode is the device's reply, not a broken link: report it below as\n // an unreadable answer so the session is kept rather than re-claimed. A TypeError or\n // ReferenceError is a bug or a broken install, not device data, so it surfaces as is.\n if (error instanceof TypeError || error instanceof ReferenceError) throw error;\n }\n if (!parts.length || !decoder.isComplete() || !decoder.isSuccess()) {\n const shape =\n typeof encoded === 'string'\n ? `string len=${text.length} parts=${parts.length}`\n : typeof encoded;\n throw createHwkError({\n code: HardwareErrorCode.PayloadTooLarge,\n message: `Keystone USB returned an incomplete BC-UR response (${shape})`,\n origin: 'device',\n // The device processed the request; only its reply is unusable.\n params: { replyUnreadable: true },\n });\n }\n const ur = decoder.resultUR();\n return { urType: ur.type, urData: ur.cbor.toString('hex') };\n}\n\n/**\n * Keystone USB `IConnector`. Each transport call is its own open/claim/transfer/close cycle, so\n * `connect()` only caches the transport object.\n */\nexport class KeystoneUsbConnectorBase implements IConnector {\n readonly connectionType = 'usb' as const;\n\n private readonly transportClass: KeystoneUsbTransportStatic;\n\n private readonly timeoutMs: number;\n\n private readonly emitter = new TypedEventEmitter<ConnectorEventMap>();\n\n private readonly sessions = new Map<string, UsbSession>();\n\n private readonly discoveredDevices = new Map<string, KeystoneUsbDeviceDescriptor>();\n\n private readonly availabilityDevices = new Map<string, KeystoneUsbDeviceDescriptor>();\n\n private activeDiscoveryGeneration: symbol | undefined;\n\n private activeAvailabilityGeneration: symbol | undefined;\n\n /**\n * Wallets (by mfp) that approved a public-data export. Connector-scoped because the device can\n * re-enumerate between exports, and that must not re-prompt.\n */\n private readonly publicDataConfirmedWallets = new Set<string>();\n\n constructor(transportClass: KeystoneUsbTransportStatic, options?: { timeoutMs?: number }) {\n this.transportClass = transportClass;\n this.timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n }\n\n private _invalidateDiscoverySnapshot(): void {\n this.activeDiscoveryGeneration = undefined;\n this.discoveredDevices.clear();\n }\n\n private _invalidateAvailabilitySnapshot(): void {\n this.activeAvailabilityGeneration = undefined;\n this.availabilityDevices.clear();\n }\n\n async searchDevices(options?: ConnectorSearchDevicesOptions): Promise<ConnectorDevice[]> {\n const isAvailabilitySearch = options?.purpose === 'availability';\n const discoveryGeneration = Symbol(\n isAvailabilitySearch ? 'keystone-usb-availability' : 'keystone-usb-discovery'\n );\n if (isAvailabilitySearch) {\n this._invalidateAvailabilitySnapshot();\n this.activeAvailabilityGeneration = discoveryGeneration;\n } else {\n this._invalidateDiscoverySnapshot();\n this.activeDiscoveryGeneration = discoveryGeneration;\n }\n // Enumeration DOMException codes collide with the HWK range, so map them too.\n let devices: ReadonlyArray<KeystoneUsbDeviceDescriptor>;\n try {\n devices = await this.transportClass.getKeystoneDevices();\n } catch (err) {\n throw mapKeystoneUsbError(err);\n }\n // Without an mfp before opening, the target id names only this snapshot; platforms that\n // cannot reopen a cached descriptor fail closed on multi-device selection.\n if (\n (isAvailabilitySearch\n ? this.activeAvailabilityGeneration\n : this.activeDiscoveryGeneration) !== discoveryGeneration\n ) {\n return [];\n }\n return devices.map(device => {\n const connectId = createHardwareSearchTargetId('keystone');\n (isAvailabilitySearch ? this.availabilityDevices : this.discoveredDevices).set(\n connectId,\n device\n );\n return {\n connectId,\n deviceId: '',\n name: usbDisplayName(device),\n connectionType: 'usb',\n serialNumber: device.serialNumber,\n capabilities: { persistentDeviceIdentity: false },\n // Verbatim descriptor fields; a missing key means the device did not publish it.\n raw: {\n serialNumber: device.serialNumber,\n productName: device.productName,\n manufacturerName: device.manufacturerName,\n vendorId: device.vendorId,\n productId: device.productId,\n deviceVersionMajor: device.deviceVersionMajor,\n deviceVersionMinor: device.deviceVersionMinor,\n deviceVersionSubminor: device.deviceVersionSubminor,\n usbVersionMajor: device.usbVersionMajor,\n usbVersionMinor: device.usbVersionMinor,\n usbVersionSubminor: device.usbVersionSubminor,\n deviceClass: device.deviceClass,\n deviceSubclass: device.deviceSubclass,\n deviceProtocol: device.deviceProtocol,\n },\n };\n });\n }\n\n async connect(searchTargetIdOrExpectedMasterFingerprint?: string): Promise<ConnectorSession> {\n return this._connectResolved(\n this._resolveConnectInput(searchTargetIdOrExpectedMasterFingerprint)\n );\n }\n\n async connectTarget(target: ConnectorConnectTarget): Promise<ConnectorSession> {\n switch (target.type) {\n case 'default':\n return this._connectResolved({});\n case 'search-target':\n return this._connectResolved({ searchTargetId: target.searchTargetId });\n case 'expected-device-identity': {\n const expectedMasterFingerprint = parseBip32MasterFingerprint(target.deviceIdentity);\n if (!expectedMasterFingerprint) {\n throw createHwkError({\n code: HardwareErrorCode.InvalidParams,\n message: 'Keystone USB connector requires a valid master fingerprint identity',\n });\n }\n return this._connectResolved({ expectedMasterFingerprint });\n }\n default:\n throw createHwkError({\n code: HardwareErrorCode.InvalidParams,\n message: 'Unsupported Keystone USB connection target',\n });\n }\n }\n\n private async _connectResolved({\n searchTargetId,\n expectedMasterFingerprint,\n }: KeystoneUsbConnectInput): Promise<ConnectorSession> {\n this.emitter.emit('ui-event', {\n type: EConnectorInteraction.Searching,\n payload: { sessionId: '' },\n });\n let selectedDevice = searchTargetId\n ? this.discoveredDevices.get(searchTargetId) ?? this.availabilityDevices.get(searchTargetId)\n : undefined;\n if (searchTargetId && !selectedDevice) {\n throw createHwkError({\n code: HardwareErrorCode.DeviceNotFound,\n message: `Keystone USB search target is not in the current scan: ${searchTargetId}`,\n recovery: { scope: 'search-target' },\n });\n }\n let openedTransport: OpenedUsbTransport | undefined;\n try {\n let config: AppConfig;\n\n if (expectedMasterFingerprint && !searchTargetId) {\n const availableDevices = await this.transportClass.getKeystoneDevices();\n if (!this.transportClass.connectDevice && availableDevices.length > 1) {\n throw createHwkError({\n code: HardwareErrorCode.DeviceOneDeviceOnly,\n message: 'This platform cannot identify one of multiple connected Keystone devices',\n });\n }\n\n if (this.transportClass.connectDevice) {\n if (availableDevices.length === 0) {\n throw createHwkError({\n code: HardwareErrorCode.DeviceNotFound,\n message: 'No Keystone USB device is available',\n });\n }\n let readableDeviceFound = false;\n let ambiguous = false;\n let lastError: unknown;\n let matched:\n | {\n device: KeystoneUsbDeviceDescriptor;\n opened: OpenedUsbTransport;\n config: AppConfig;\n }\n | undefined;\n for (const device of availableDevices) {\n let candidate: OpenedUsbTransport | undefined;\n try {\n // eslint-disable-next-line no-await-in-loop\n candidate = await this._openTransport(device);\n // eslint-disable-next-line no-await-in-loop\n const candidateConfig = await this._readAppConfig(candidate.transport);\n readableDeviceFound = true;\n if (candidateConfig.mfp?.toLowerCase() === expectedMasterFingerprint.toLowerCase()) {\n if (matched) {\n candidate.dispose();\n ambiguous = true;\n break;\n }\n matched = { device, opened: candidate, config: candidateConfig };\n // eslint-disable-next-line no-continue\n continue;\n }\n candidate.dispose();\n } catch (error) {\n candidate?.dispose();\n lastError = error;\n }\n }\n // The fingerprint is self-reported, so two claimants are refused, not ranked.\n if (ambiguous) {\n matched?.opened.dispose();\n throw createHwkError({\n code: HardwareErrorCode.DeviceOneDeviceOnly,\n message: 'More than one connected Keystone reports this wallet; keep one connected',\n });\n }\n if (!matched) {\n if (!readableDeviceFound && lastError) throw mapKeystoneUsbError(lastError);\n throw createHwkError({\n code: HardwareErrorCode.DeviceMismatch,\n message: 'No connected Keystone matches the requested wallet',\n });\n }\n selectedDevice = matched.device;\n openedTransport = matched.opened;\n config = matched.config;\n } else {\n openedTransport = await this._openTransport();\n config = await this._readAppConfig(openedTransport.transport);\n }\n } else {\n if (!selectedDevice && this.transportClass.connectDevice) {\n const availableDevices = await this.transportClass.getKeystoneDevices();\n if (availableDevices.length === 0) {\n throw createHwkError({\n code: HardwareErrorCode.DeviceNotFound,\n message: 'No Keystone USB device is available',\n });\n }\n if (availableDevices.length > 1) {\n throw createHwkError({\n code: HardwareErrorCode.DeviceOneDeviceOnly,\n message: 'Select a Keystone USB device before connecting',\n });\n }\n [selectedDevice] = availableDevices;\n }\n if (selectedDevice && !this.transportClass.connectDevice) {\n const availableDevices = await this.transportClass.getKeystoneDevices();\n if (availableDevices.length > 1) {\n throw createHwkError({\n code: HardwareErrorCode.DeviceOneDeviceOnly,\n message: 'This platform cannot target one of multiple connected Keystone devices',\n });\n }\n }\n openedTransport = await this._openTransport(selectedDevice);\n config = await this._readAppConfig(openedTransport.transport);\n }\n\n const activeOpenedTransport = openedTransport;\n const { transport } = activeOpenedTransport;\n if (\n expectedMasterFingerprint &&\n config.mfp &&\n config.mfp.toLowerCase() !== expectedMasterFingerprint.toLowerCase()\n ) {\n throw createHwkError({\n code: HardwareErrorCode.DeviceMismatch,\n // The master fingerprint identifies the wallet; keep it out of messages that reach logs.\n message: 'Connected Keystone wallet does not match the requested wallet',\n });\n }\n const sessionId = createHardwareLinkId('keystone');\n activeOpenedTransport.bindSessionId(sessionId);\n this.sessions.set(sessionId, {\n transport,\n mfp: config.mfp,\n dispose: () => activeOpenedTransport.dispose(),\n });\n openedTransport = undefined;\n const device: ConnectorDevice = {\n connectId: sessionId,\n deviceId: '',\n name: selectedDevice ? usbDisplayName(selectedDevice) : 'Keystone',\n model: selectedDevice?.productName,\n connectionType: 'usb',\n serialNumber: selectedDevice?.serialNumber,\n capabilities: { persistentDeviceIdentity: false },\n raw: { masterFingerprint: config.mfp },\n };\n this.emitter.emit('device-connect', { device });\n return {\n sessionId,\n deviceInfo: this._toDeviceInfo(device, config.version, config.mfp),\n };\n } catch (err) {\n openedTransport?.dispose();\n throw mapKeystoneUsbError(err);\n }\n }\n\n private async _openTransport(device?: KeystoneUsbDeviceDescriptor): Promise<OpenedUsbTransport> {\n // A rejected candidate may keep its disconnect listener; a per-descriptor\n // holder stops it from retiring a later matched session.\n let connectedSessionId: string | undefined;\n const transportConfig: TransportConfig = {\n timeout: this.timeoutMs,\n disconnectListener: () =>\n connectedSessionId ? this.disconnect(connectedSessionId) : undefined,\n };\n const transport = await (device && this.transportClass.connectDevice\n ? this.transportClass.connectDevice(device, transportConfig)\n : this.transportClass.connect(transportConfig));\n let disposed = false;\n return {\n transport,\n bindSessionId(sessionId: string) {\n connectedSessionId = sessionId;\n },\n dispose: () => {\n if (disposed) return;\n disposed = true;\n this.transportClass.disposeTransport?.(transport);\n },\n };\n }\n\n private _resolveConnectInput(value?: string): KeystoneUsbConnectInput {\n if (!value) return {};\n\n const runtimeId = parseHardwareRuntimeId(value);\n if (runtimeId) {\n // Ownership is settled by the snapshot lookup in `_connectResolved`.\n if (runtimeId.kind === 'search-target' && runtimeId.vendor === 'keystone') {\n return { searchTargetId: value };\n }\n throw createHwkError({\n code: HardwareErrorCode.InvalidParams,\n message: 'Keystone USB connector received an incompatible hardware runtime id',\n params: { kind: runtimeId.kind, vendor: runtimeId.vendor },\n });\n }\n\n if (hasHardwareRuntimeIdPrefix(value)) {\n throw createHwkError({\n code: HardwareErrorCode.InvalidParams,\n message: 'Keystone USB connector received a malformed hardware runtime id',\n });\n }\n\n const expectedMasterFingerprint = parseBip32MasterFingerprint(value);\n if (!expectedMasterFingerprint) {\n throw createHwkError({\n code: HardwareErrorCode.InvalidParams,\n message: 'Keystone USB connector requires a search target or master fingerprint',\n });\n }\n return { expectedMasterFingerprint };\n }\n\n disconnect(sessionId: string): Promise<void> {\n const session = this.sessions.get(sessionId);\n this.sessions.delete(sessionId);\n if (session) {\n session.dispose();\n // No persistent claim to release; each send() already closed the device.\n this.emitter.emit('device-disconnect', { connectId: sessionId });\n }\n return Promise.resolve();\n }\n\n /** Keep the vendor transport as the EAPDU framing authority. */\n private async _sendResolveUr(transport: TransportHID, encodedUr: string): Promise<KeystoneUr> {\n const response = await transport.send<{ payload: string }>(Actions.CMD_RESOLVE_UR, encodedUr);\n return fromUrEncoded(response.payload);\n }\n\n async call(sessionId: string, method: string, params: unknown): Promise<ConnectorCallResult> {\n const session = this.sessions.get(sessionId);\n if (!session) {\n return {\n success: false,\n error: serializeConnectorError(\n createHwkError({\n code: HardwareErrorCode.DeviceNotFound,\n message: `Unknown Keystone USB session: ${sessionId}`,\n })\n ),\n };\n }\n\n try {\n switch (method) {\n case 'resolveUr': {\n const { urType, urData } = params as KeystoneUr;\n const encoded = toUrEncoded({ urType, urData });\n const isPublicDataRequest = urType === KEYSTONE_PUBLIC_DATA_UR_TYPE;\n // Public-data export prompts once per wallet; signing always prompts. A signing request\n // leaves the device's export screen, so the next export may ask again and prompts again.\n const publicDataKey = session.mfp?.toLowerCase() ?? sessionId;\n if (!isPublicDataRequest) this.publicDataConfirmedWallets.delete(publicDataKey);\n const shouldShowConfirmation =\n !isPublicDataRequest || !this.publicDataConfirmedWallets.has(publicDataKey);\n if (shouldShowConfirmation) {\n this.emitter.emit('ui-event', {\n type: EConnectorInteraction.ConfirmOnDevice,\n payload: { sessionId },\n });\n }\n try {\n const response = await this._sendResolveUr(session.transport, encoded);\n if (isPublicDataRequest) {\n this.publicDataConfirmedWallets.add(publicDataKey);\n }\n return success(response);\n } finally {\n if (shouldShowConfirmation) {\n this.emitter.emit('ui-event', {\n type: EConnectorInteraction.InteractionComplete,\n payload: { sessionId },\n });\n }\n }\n }\n case 'checkLockStatus': {\n const response = await session.transport.send<{ payload: boolean }>(\n Actions.CMD_CHECK_LOCK_STATUS,\n ''\n );\n // `true` = locked is inferred from the SDK method name only; unverified on hardware.\n // Only a real boolean true counts, so a malformed reply never reads as a lock state.\n return success({ locked: response.payload === true });\n }\n case 'getAppConfig':\n return success(await this._readAppConfig(session.transport));\n default:\n return {\n success: false,\n error: serializeConnectorError(\n createHwkError({\n code: HardwareErrorCode.MethodNotSupported,\n message: `Unknown Keystone USB connector method: ${method}`,\n })\n ),\n };\n }\n } catch (err) {\n return { success: false, error: serializeConnectorError(mapKeystoneUsbError(err)) };\n }\n }\n\n // The SDK cannot interrupt an in-flight transfer; the pending send() settles or\n // times out on its own.\n cancel(_sessionId: string): Promise<void> {\n return Promise.resolve();\n }\n\n // PIN/passphrase entry happens on the device touchscreen, never via the host.\n uiResponse(_response: UiResponseEvent): void {}\n\n on<K extends ConnectorEventType>(event: K, handler: (data: ConnectorEventMap[K]) => void): void {\n this.emitter.on(event, handler);\n }\n\n off<K extends ConnectorEventType>(event: K, handler: (data: ConnectorEventMap[K]) => void): void {\n this.emitter.off(event, handler);\n }\n\n reset(): void {\n for (const session of this.sessions.values()) {\n session.dispose();\n }\n this.sessions.clear();\n this._invalidateDiscoverySnapshot();\n this._invalidateAvailabilitySnapshot();\n this.publicDataConfirmedWallets.clear();\n }\n\n private async _readAppConfig(transport: TransportHID): Promise<AppConfig> {\n const response = await transport.send<Record<string, unknown>>(\n Actions.CMD_GET_DEVICE_VERSION,\n ''\n );\n const rawMasterFingerprint = response.walletMFP;\n const masterFingerprint = parseBip32MasterFingerprint(rawMasterFingerprint);\n if (masterFingerprint === MISSING_BIP32_MASTER_FINGERPRINT) {\n throw createHwkError({\n code: HardwareErrorCode.DeviceNotInitialized,\n message: 'Keystone has no wallet yet; it reported an empty master fingerprint',\n });\n }\n if (rawMasterFingerprint !== undefined && !masterFingerprint) {\n throw createHwkError({\n code: HardwareErrorCode.DeviceMismatch,\n message:\n 'Keystone returned an invalid master fingerprint; expected exactly 4 bytes (8 hex characters)',\n });\n }\n return {\n // Device-supplied text reaches the host UI and version gates; accept only a version number.\n version:\n typeof response.firmwareVersion === 'string' &&\n /^\\d{1,4}(\\.\\d{1,4}){1,3}(-[0-9A-Za-z.]{1,20})?$/.test(response.firmwareVersion)\n ? response.firmwareVersion\n : undefined,\n mfp: masterFingerprint,\n };\n }\n\n private _toDeviceInfo(\n device: ConnectorDevice,\n firmwareVersion?: string,\n masterFingerprint?: string\n ) {\n return {\n vendor: 'keystone' as const,\n // Model is the USB `productName`; empty, not 'unknown', so the host's\n // default-name fallback wins.\n model: device.model ?? '',\n modelName: device.modelName,\n firmwareVersion: firmwareVersion ?? '0.0.0',\n deviceId: device.deviceId,\n connectId: device.connectId,\n connectionType: 'usb' as const,\n serialNumber: device.serialNumber,\n capabilities: { persistentDeviceIdentity: false },\n raw: { masterFingerprint },\n };\n }\n}\n"],"mappings":";AAAA,SAAS,mBAAmB,sBAAsB;AAClD,SAAS,cAAc;AAQvB,SAAS,eAAe,YAA6B;AACnD,SAAO,cAAc,KAAK,aAAa,OAAO;AAChD;AAGA,IAAM,oBAAgE;AAAA,EACpE,CAAC,OAAO,gBAAgB,GAAG,kBAAkB;AAAA,EAC7C,CAAC,OAAO,yBAAyB,GAAG,kBAAkB;AAAA,EACtD,CAAC,OAAO,iBAAiB,GAAG,kBAAkB;AAAA,EAC9C,CAAC,OAAO,oBAAoB,GAAG,kBAAkB;AAAA,EACjD,CAAC,OAAO,iBAAiB,GAAG,kBAAkB;AAAA,EAC9C,CAAC,OAAO,sBAAsB,GAAG,kBAAkB;AAAA,EACnD,CAAC,OAAO,qBAAqB,GAAG,kBAAkB;AAAA,EAClD,CAAC,OAAO,6BAA6B,GAAG,kBAAkB;AAAA,EAC1D,CAAC,OAAO,iCAAiC,GAAG,kBAAkB;AAAA,EAC9D,CAAC,OAAO,oCAAoC,GAAG,kBAAkB;AAAA,EACjE,CAAC,OAAO,iCAAiC,GAAG,kBAAkB;AAAA,EAC9D,CAAC,OAAO,wBAAwB,GAAG,kBAAkB;AAAA,EACrD,CAAC,OAAO,6BAA6B,GAAG,kBAAkB;AAAA,EAC1D,CAAC,OAAO,2BAA2B,GAAG,kBAAkB;AAAA,EACxD,CAAC,OAAO,uBAAuB,GAAG,kBAAkB;AACtD;AAGA,IAAM,wBAAyD;AAAA,EAC7D,CAAC,OAAO,gBAAgB,GAAG;AAAA,EAC3B,CAAC,OAAO,yBAAyB,GAAG;AAAA,EACpC,CAAC,OAAO,iBAAiB,GAAG;AAAA,EAC5B,CAAC,OAAO,oBAAoB,GAAG;AAAA,EAC/B,CAAC,OAAO,iBAAiB,GAAG;AAAA,EAC5B,CAAC,OAAO,sBAAsB,GAAG;AAAA,EACjC,CAAC,OAAO,qBAAqB,GAAG;AAAA,EAChC,CAAC,OAAO,6BAA6B,GAAG;AAAA,EACxC,CAAC,OAAO,iCAAiC,GAAG;AAAA,EAC5C,CAAC,OAAO,oCAAoC,GAAG;AAAA,EAC/C,CAAC,OAAO,iCAAiC,GAAG;AAAA,EAC5C,CAAC,OAAO,wBAAwB,GAAG;AAAA,EACnC,CAAC,OAAO,6BAA6B,GAAG;AAAA,EACxC,CAAC,OAAO,2BAA2B,GAAG;AAAA,EACtC,CAAC,OAAO,uBAAuB,GAAG;AACpC;AAGA,IAAM,sBAAsB;AAG5B,IAAM,oBAAgE;AAAA,EACpE,CAAC,OAAO,qBAAqB,GAAG,kBAAkB;AAAA,EAClD,CAAC,OAAO,oBAAoB,GAAG,kBAAkB;AAAA,EACjD,CAAC,OAAO,WAAW,GAAG,kBAAkB;AAAA,EACxC,CAAC,OAAO,kBAAkB,GAAG,kBAAkB;AAAA,EAC/C,CAAC,OAAO,iBAAiB,GAAG,kBAAkB;AAChD;AAGA,IAAM,oBAAoB,oBAAI,IAAiE;AAAA,EAC7F,CAAC,iBAAiB,EAAE,MAAM,kBAAkB,gBAAgB,QAAQ,YAAY,CAAC;AAAA,EACjF,CAAC,gBAAgB,EAAE,MAAM,kBAAkB,gBAAgB,QAAQ,YAAY,CAAC;AAAA,EAChF,CAAC,iBAAiB,EAAE,MAAM,kBAAkB,wBAAwB,QAAQ,OAAO,CAAC;AAAA,EACpF,CAAC,mBAAmB,EAAE,MAAM,kBAAkB,wBAAwB,QAAQ,OAAO,CAAC;AAAA,EACtF,CAAC,qBAAqB,EAAE,MAAM,kBAAkB,YAAY,QAAQ,YAAY,CAAC;AAAA,EACjF,CAAC,cAAc,EAAE,MAAM,kBAAkB,YAAY,QAAQ,YAAY,CAAC;AAC5E,CAAC;AAMM,SAAS,oBAAoB,KAAwB;AAC1D,QAAM,SACJ,OAAO,OAAO,QAAQ,WAAW,MAAM,CAAC;AAC1C,QAAM,UAAU,OAAO,OAAO,SAAS,WAAW,OAAO,OAAO;AAIhE,MAAI,OAAO,OAAO,SAAS,YAAY,OAAO,QAAQ,OAAS,OAAO,QAAQ,OAAO;AACnF,WAAO;AAAA,EACT;AAEA,QAAM,aACJ,OAAO,OAAO,uBAAuB,WAAW,OAAO,qBAAqB;AAE9E,QAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAE/D,MAAI,eAAe,QAAW;AAC5B,UAAM,aAAa,eAAe,UAAU;AAG5C,QAAI,OAAO,aACP,kBAAkB,UAAU,KAAK,kBAAkB,eACnD,kBAAkB,UAAU,KAAK,kBAAkB;AAGvD,QAAI,eAAe,OAAO,0BAA0B,CAAC,cAAc,KAAK,OAAO,GAAG;AAChF,aAAO,kBAAkB;AAAA,IAC3B;AACA,QAAI;AACJ,QAAI,YAAY;AACd,eAAS;AAAA,IACX,WAAW,SAAS,kBAAkB,kBAAkB;AACtD,eAAS;AAAA,IACX;AACA,UAAM,cAAc,sBAAsB,UAAU;AACpD,WAAO,eAAe;AAAA,MACpB;AAAA;AAAA,MAEA,SACE,eAAe,oBAAoB,KAAK,OAAO,IAC3C,GAAG,WAAW,iBAAiB,UAAU,MACzC;AAAA;AAAA,MAEN;AAAA,MACA,QAAQ,EAAE,YAAY,SAAU,IAA6B,QAAQ;AAAA,IACvE,CAAC;AAAA,EACH;AAEA,QAAM,aAAa,UAAU,kBAAkB,IAAI,OAAO,IAAI;AAC9D,MAAI,YAAY;AACd,WAAO,eAAe,EAAE,GAAG,YAAY,SAAS,QAAQ,EAAE,kBAAkB,QAAQ,EAAE,CAAC;AAAA,EACzF;AAGA,SAAO,eAAe,EAAE,MAAM,kBAAkB,gBAAgB,SAAS,QAAQ,YAAY,CAAC;AAChG;;;ACpIA,SAAS,IAAI,WAAW,iBAAiB;AACzC,SAAS,eAAe;AACxB;AAAA,EACE;AAAA,EACA,qBAAAA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,kBAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAqCP,SAAS,eAAe,QAA6C;AACnE,SAAO,OAAO,aAAa,KAAK,KAAK;AACvC;AA4CA,IAAM,qBAAqB;AAE3B,IAAM,+BAA+B;AAErC,SAAS,YAAY,IAAwB;AAC3C,SAAO,IAAI,UAAU,IAAI,GAAG,OAAO,KAAK,GAAG,QAAQ,KAAK,GAAG,GAAG,MAAM,GAAG,QAAQ,EAC5E,SAAS,EACT,YAAY;AACjB;AAGA,IAAM,uBAAuB,OAAO;AAKpC,IAAM,oBAAoB;AAE1B,IAAM,sBAAsB,CAAC,GAAG,GAAG,GAAG,CAAC;AAGvC,SAAS,iBAAiB,OAAmB;AAC3C,MAAI,SAAS;AACb,QAAM,WAAW,CAAC,kBAAkC;AAClD,UAAM,UAAU,MAAM,MAAM;AAC5B,cAAU;AACV,QAAI,KAAK,MAAM,UAAU,EAAE,MAAM,eAAe;AAC9C,YAAM,IAAI,MAAM,gDAAgD;AAAA,IAClE;AACA,UAAM,OAAO,UAAU;AACvB,QAAI,OAAO,GAAI,QAAO;AACtB,UAAM,OAAO,oBAAoB,OAAO,EAAE;AAC1C,QAAI,QAAQ;AACZ,aAAS,IAAI,GAAG,IAAI,MAAM,KAAK,EAAG,SAAQ,QAAQ,MAAM,MAAM,SAAS,CAAC;AACxE,cAAU;AACV,WAAO;AAAA,EACT;AACA,MAAI,SAAS,CAAC,MAAM,EAAG,OAAM,IAAI,MAAM,gDAAgD;AACvF,QAAM,SAAS,SAAS,CAAC;AACzB,QAAM,YAAY,SAAS,CAAC;AAC5B,QAAM,gBAAgB,SAAS,CAAC;AAChC,WAAS,CAAC;AACV,QAAM,iBAAiB,SAAS,CAAC;AACjC,SAAO,EAAE,QAAQ,WAAW,eAAe,eAAe;AAC5D;AAGA,SAAS,oBAAoB,MAAoB;AAC/C,QAAM,QAAQ,uDAAuD,KAAK,IAAI;AAC9E,MAAI,CAAC,MAAO,OAAM,IAAI,MAAM,qCAAqC;AAGjE,QAAM,UAAU,UAAU,OAAO,YAAY,MAAM,CAAC,EAAE,YAAY,CAAC,EAAE,EAAE;AACvE,oBAAkB,SAAS,oBAAoB;AAC/C,MAAI,MAAM,CAAC,MAAM,OAAW;AAC5B,QAAM,SAAS,iBAAiB,OAAO;AAKvC,MACE,OAAO,SAAS,KAChB,OAAO,SAAS,OAAO,aACvB,OAAO,WAAW,OAAO,MAAM,CAAC,CAAC,KACjC,OAAO,cAAc,OAAO,MAAM,CAAC,CAAC,KACpC,OAAO,iBAAiB,KACxB,OAAO,gBAAgB,KACvB,OAAO,gBAAgB,wBACvB,OAAO,YAAY,qBACnB,OAAO,cAAc,KAAK,KAAK,OAAO,gBAAgB,OAAO,cAAc,GAC3E;AACA,UAAM,IAAI,MAAM,+DAA+D;AAAA,EACjF;AACF;AAEA,SAAS,cAAc,SAA8B;AAEnD,QAAM,OAAO,OAAO,YAAY,WAAW,QAAQ,KAAK,IAAI;AAC5D,QAAM,QAAQ,KAAK,MAAM,KAAK,EAAE,OAAO,OAAO;AAC9C,QAAM,UAAU,IAAI,UAAU;AAC9B,MAAI;AACF,QAAI,MAAM,SAAS,kBAAmB,OAAM,IAAI,MAAM,uCAAuC;AAC7F,eAAW,QAAQ,OAAO;AACxB,0BAAoB,IAAI;AACxB,cAAQ,YAAY,IAAI;AACxB,UAAI,QAAQ,WAAW,EAAG;AAAA,IAC5B;AAAA,EACF,SAAS,OAAO;AAId,QAAI,iBAAiB,aAAa,iBAAiB,eAAgB,OAAM;AAAA,EAC3E;AACA,MAAI,CAAC,MAAM,UAAU,CAAC,QAAQ,WAAW,KAAK,CAAC,QAAQ,UAAU,GAAG;AAClE,UAAM,QACJ,OAAO,YAAY,WACf,cAAc,KAAK,MAAM,UAAU,MAAM,MAAM,KAC/C,OAAO;AACb,UAAMC,gBAAe;AAAA,MACnB,MAAMC,mBAAkB;AAAA,MACxB,SAAS,uDAAuD,KAAK;AAAA,MACrE,QAAQ;AAAA;AAAA,MAER,QAAQ,EAAE,iBAAiB,KAAK;AAAA,IAClC,CAAC;AAAA,EACH;AACA,QAAM,KAAK,QAAQ,SAAS;AAC5B,SAAO,EAAE,QAAQ,GAAG,MAAM,QAAQ,GAAG,KAAK,SAAS,KAAK,EAAE;AAC5D;AAMO,IAAM,2BAAN,MAAqD;AAAA,EAyB1D,YAAY,gBAA4C,SAAkC;AAxB1F,SAAS,iBAAiB;AAM1B,SAAiB,UAAU,IAAI,kBAAqC;AAEpE,SAAiB,WAAW,oBAAI,IAAwB;AAExD,SAAiB,oBAAoB,oBAAI,IAAyC;AAElF,SAAiB,sBAAsB,oBAAI,IAAyC;AAUpF;AAAA;AAAA;AAAA;AAAA,SAAiB,6BAA6B,oBAAI,IAAY;AAG5D,SAAK,iBAAiB;AACtB,SAAK,YAAY,SAAS,aAAa;AAAA,EACzC;AAAA,EAEQ,+BAAqC;AAC3C,SAAK,4BAA4B;AACjC,SAAK,kBAAkB,MAAM;AAAA,EAC/B;AAAA,EAEQ,kCAAwC;AAC9C,SAAK,+BAA+B;AACpC,SAAK,oBAAoB,MAAM;AAAA,EACjC;AAAA,EAEA,MAAM,cAAc,SAAqE;AACvF,UAAM,uBAAuB,SAAS,YAAY;AAClD,UAAM,sBAAsB;AAAA,MAC1B,uBAAuB,8BAA8B;AAAA,IACvD;AACA,QAAI,sBAAsB;AACxB,WAAK,gCAAgC;AACrC,WAAK,+BAA+B;AAAA,IACtC,OAAO;AACL,WAAK,6BAA6B;AAClC,WAAK,4BAA4B;AAAA,IACnC;AAEA,QAAI;AACJ,QAAI;AACF,gBAAU,MAAM,KAAK,eAAe,mBAAmB;AAAA,IACzD,SAAS,KAAK;AACZ,YAAM,oBAAoB,GAAG;AAAA,IAC/B;AAGA,SACG,uBACG,KAAK,+BACL,KAAK,+BAA+B,qBACxC;AACA,aAAO,CAAC;AAAA,IACV;AACA,WAAO,QAAQ,IAAI,YAAU;AAC3B,YAAM,YAAY,6BAA6B,UAAU;AACzD,OAAC,uBAAuB,KAAK,sBAAsB,KAAK,mBAAmB;AAAA,QACzE;AAAA,QACA;AAAA,MACF;AACA,aAAO;AAAA,QACL;AAAA,QACA,UAAU;AAAA,QACV,MAAM,eAAe,MAAM;AAAA,QAC3B,gBAAgB;AAAA,QAChB,cAAc,OAAO;AAAA,QACrB,cAAc,EAAE,0BAA0B,MAAM;AAAA;AAAA,QAEhD,KAAK;AAAA,UACH,cAAc,OAAO;AAAA,UACrB,aAAa,OAAO;AAAA,UACpB,kBAAkB,OAAO;AAAA,UACzB,UAAU,OAAO;AAAA,UACjB,WAAW,OAAO;AAAA,UAClB,oBAAoB,OAAO;AAAA,UAC3B,oBAAoB,OAAO;AAAA,UAC3B,uBAAuB,OAAO;AAAA,UAC9B,iBAAiB,OAAO;AAAA,UACxB,iBAAiB,OAAO;AAAA,UACxB,oBAAoB,OAAO;AAAA,UAC3B,aAAa,OAAO;AAAA,UACpB,gBAAgB,OAAO;AAAA,UACvB,gBAAgB,OAAO;AAAA,QACzB;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,QAAQ,2CAA+E;AAC3F,WAAO,KAAK;AAAA,MACV,KAAK,qBAAqB,yCAAyC;AAAA,IACrE;AAAA,EACF;AAAA,EAEA,MAAM,cAAc,QAA2D;AAC7E,YAAQ,OAAO,MAAM;AAAA,MACnB,KAAK;AACH,eAAO,KAAK,iBAAiB,CAAC,CAAC;AAAA,MACjC,KAAK;AACH,eAAO,KAAK,iBAAiB,EAAE,gBAAgB,OAAO,eAAe,CAAC;AAAA,MACxE,KAAK,4BAA4B;AAC/B,cAAM,4BAA4B,4BAA4B,OAAO,cAAc;AACnF,YAAI,CAAC,2BAA2B;AAC9B,gBAAMD,gBAAe;AAAA,YACnB,MAAMC,mBAAkB;AAAA,YACxB,SAAS;AAAA,UACX,CAAC;AAAA,QACH;AACA,eAAO,KAAK,iBAAiB,EAAE,0BAA0B,CAAC;AAAA,MAC5D;AAAA,MACA;AACE,cAAMD,gBAAe;AAAA,UACnB,MAAMC,mBAAkB;AAAA,UACxB,SAAS;AAAA,QACX,CAAC;AAAA,IACL;AAAA,EACF;AAAA,EAEA,MAAc,iBAAiB;AAAA,IAC7B;AAAA,IACA;AAAA,EACF,GAAuD;AACrD,SAAK,QAAQ,KAAK,YAAY;AAAA,MAC5B,MAAM,sBAAsB;AAAA,MAC5B,SAAS,EAAE,WAAW,GAAG;AAAA,IAC3B,CAAC;AACD,QAAI,iBAAiB,iBACjB,KAAK,kBAAkB,IAAI,cAAc,KAAK,KAAK,oBAAoB,IAAI,cAAc,IACzF;AACJ,QAAI,kBAAkB,CAAC,gBAAgB;AACrC,YAAMD,gBAAe;AAAA,QACnB,MAAMC,mBAAkB;AAAA,QACxB,SAAS,0DAA0D,cAAc;AAAA,QACjF,UAAU,EAAE,OAAO,gBAAgB;AAAA,MACrC,CAAC;AAAA,IACH;AACA,QAAI;AACJ,QAAI;AACF,UAAI;AAEJ,UAAI,6BAA6B,CAAC,gBAAgB;AAChD,cAAM,mBAAmB,MAAM,KAAK,eAAe,mBAAmB;AACtE,YAAI,CAAC,KAAK,eAAe,iBAAiB,iBAAiB,SAAS,GAAG;AACrE,gBAAMD,gBAAe;AAAA,YACnB,MAAMC,mBAAkB;AAAA,YACxB,SAAS;AAAA,UACX,CAAC;AAAA,QACH;AAEA,YAAI,KAAK,eAAe,eAAe;AACrC,cAAI,iBAAiB,WAAW,GAAG;AACjC,kBAAMD,gBAAe;AAAA,cACnB,MAAMC,mBAAkB;AAAA,cACxB,SAAS;AAAA,YACX,CAAC;AAAA,UACH;AACA,cAAI,sBAAsB;AAC1B,cAAI,YAAY;AAChB,cAAI;AACJ,cAAI;AAOJ,qBAAWC,WAAU,kBAAkB;AACrC,gBAAI;AACJ,gBAAI;AAEF,0BAAY,MAAM,KAAK,eAAeA,OAAM;AAE5C,oBAAM,kBAAkB,MAAM,KAAK,eAAe,UAAU,SAAS;AACrE,oCAAsB;AACtB,kBAAI,gBAAgB,KAAK,YAAY,MAAM,0BAA0B,YAAY,GAAG;AAClF,oBAAI,SAAS;AACX,4BAAU,QAAQ;AAClB,8BAAY;AACZ;AAAA,gBACF;AACA,0BAAU,EAAE,QAAAA,SAAQ,QAAQ,WAAW,QAAQ,gBAAgB;AAE/D;AAAA,cACF;AACA,wBAAU,QAAQ;AAAA,YACpB,SAAS,OAAO;AACd,yBAAW,QAAQ;AACnB,0BAAY;AAAA,YACd;AAAA,UACF;AAEA,cAAI,WAAW;AACb,qBAAS,OAAO,QAAQ;AACxB,kBAAMF,gBAAe;AAAA,cACnB,MAAMC,mBAAkB;AAAA,cACxB,SAAS;AAAA,YACX,CAAC;AAAA,UACH;AACA,cAAI,CAAC,SAAS;AACZ,gBAAI,CAAC,uBAAuB,UAAW,OAAM,oBAAoB,SAAS;AAC1E,kBAAMD,gBAAe;AAAA,cACnB,MAAMC,mBAAkB;AAAA,cACxB,SAAS;AAAA,YACX,CAAC;AAAA,UACH;AACA,2BAAiB,QAAQ;AACzB,4BAAkB,QAAQ;AAC1B,mBAAS,QAAQ;AAAA,QACnB,OAAO;AACL,4BAAkB,MAAM,KAAK,eAAe;AAC5C,mBAAS,MAAM,KAAK,eAAe,gBAAgB,SAAS;AAAA,QAC9D;AAAA,MACF,OAAO;AACL,YAAI,CAAC,kBAAkB,KAAK,eAAe,eAAe;AACxD,gBAAM,mBAAmB,MAAM,KAAK,eAAe,mBAAmB;AACtE,cAAI,iBAAiB,WAAW,GAAG;AACjC,kBAAMD,gBAAe;AAAA,cACnB,MAAMC,mBAAkB;AAAA,cACxB,SAAS;AAAA,YACX,CAAC;AAAA,UACH;AACA,cAAI,iBAAiB,SAAS,GAAG;AAC/B,kBAAMD,gBAAe;AAAA,cACnB,MAAMC,mBAAkB;AAAA,cACxB,SAAS;AAAA,YACX,CAAC;AAAA,UACH;AACA,WAAC,cAAc,IAAI;AAAA,QACrB;AACA,YAAI,kBAAkB,CAAC,KAAK,eAAe,eAAe;AACxD,gBAAM,mBAAmB,MAAM,KAAK,eAAe,mBAAmB;AACtE,cAAI,iBAAiB,SAAS,GAAG;AAC/B,kBAAMD,gBAAe;AAAA,cACnB,MAAMC,mBAAkB;AAAA,cACxB,SAAS;AAAA,YACX,CAAC;AAAA,UACH;AAAA,QACF;AACA,0BAAkB,MAAM,KAAK,eAAe,cAAc;AAC1D,iBAAS,MAAM,KAAK,eAAe,gBAAgB,SAAS;AAAA,MAC9D;AAEA,YAAM,wBAAwB;AAC9B,YAAM,EAAE,UAAU,IAAI;AACtB,UACE,6BACA,OAAO,OACP,OAAO,IAAI,YAAY,MAAM,0BAA0B,YAAY,GACnE;AACA,cAAMD,gBAAe;AAAA,UACnB,MAAMC,mBAAkB;AAAA;AAAA,UAExB,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AACA,YAAM,YAAY,qBAAqB,UAAU;AACjD,4BAAsB,cAAc,SAAS;AAC7C,WAAK,SAAS,IAAI,WAAW;AAAA,QAC3B;AAAA,QACA,KAAK,OAAO;AAAA,QACZ,SAAS,MAAM,sBAAsB,QAAQ;AAAA,MAC/C,CAAC;AACD,wBAAkB;AAClB,YAAM,SAA0B;AAAA,QAC9B,WAAW;AAAA,QACX,UAAU;AAAA,QACV,MAAM,iBAAiB,eAAe,cAAc,IAAI;AAAA,QACxD,OAAO,gBAAgB;AAAA,QACvB,gBAAgB;AAAA,QAChB,cAAc,gBAAgB;AAAA,QAC9B,cAAc,EAAE,0BAA0B,MAAM;AAAA,QAChD,KAAK,EAAE,mBAAmB,OAAO,IAAI;AAAA,MACvC;AACA,WAAK,QAAQ,KAAK,kBAAkB,EAAE,OAAO,CAAC;AAC9C,aAAO;AAAA,QACL;AAAA,QACA,YAAY,KAAK,cAAc,QAAQ,OAAO,SAAS,OAAO,GAAG;AAAA,MACnE;AAAA,IACF,SAAS,KAAK;AACZ,uBAAiB,QAAQ;AACzB,YAAM,oBAAoB,GAAG;AAAA,IAC/B;AAAA,EACF;AAAA,EAEA,MAAc,eAAe,QAAmE;AAG9F,QAAI;AACJ,UAAM,kBAAmC;AAAA,MACvC,SAAS,KAAK;AAAA,MACd,oBAAoB,MAClB,qBAAqB,KAAK,WAAW,kBAAkB,IAAI;AAAA,IAC/D;AACA,UAAM,YAAY,OAAO,UAAU,KAAK,eAAe,gBACnD,KAAK,eAAe,cAAc,QAAQ,eAAe,IACzD,KAAK,eAAe,QAAQ,eAAe;AAC/C,QAAI,WAAW;AACf,WAAO;AAAA,MACL;AAAA,MACA,cAAc,WAAmB;AAC/B,6BAAqB;AAAA,MACvB;AAAA,MACA,SAAS,MAAM;AACb,YAAI,SAAU;AACd,mBAAW;AACX,aAAK,eAAe,mBAAmB,SAAS;AAAA,MAClD;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,qBAAqB,OAAyC;AACpE,QAAI,CAAC,MAAO,QAAO,CAAC;AAEpB,UAAM,YAAY,uBAAuB,KAAK;AAC9C,QAAI,WAAW;AAEb,UAAI,UAAU,SAAS,mBAAmB,UAAU,WAAW,YAAY;AACzE,eAAO,EAAE,gBAAgB,MAAM;AAAA,MACjC;AACA,YAAMD,gBAAe;AAAA,QACnB,MAAMC,mBAAkB;AAAA,QACxB,SAAS;AAAA,QACT,QAAQ,EAAE,MAAM,UAAU,MAAM,QAAQ,UAAU,OAAO;AAAA,MAC3D,CAAC;AAAA,IACH;AAEA,QAAI,2BAA2B,KAAK,GAAG;AACrC,YAAMD,gBAAe;AAAA,QACnB,MAAMC,mBAAkB;AAAA,QACxB,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAEA,UAAM,4BAA4B,4BAA4B,KAAK;AACnE,QAAI,CAAC,2BAA2B;AAC9B,YAAMD,gBAAe;AAAA,QACnB,MAAMC,mBAAkB;AAAA,QACxB,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AACA,WAAO,EAAE,0BAA0B;AAAA,EACrC;AAAA,EAEA,WAAW,WAAkC;AAC3C,UAAM,UAAU,KAAK,SAAS,IAAI,SAAS;AAC3C,SAAK,SAAS,OAAO,SAAS;AAC9B,QAAI,SAAS;AACX,cAAQ,QAAQ;AAEhB,WAAK,QAAQ,KAAK,qBAAqB,EAAE,WAAW,UAAU,CAAC;AAAA,IACjE;AACA,WAAO,QAAQ,QAAQ;AAAA,EACzB;AAAA;AAAA,EAGA,MAAc,eAAe,WAAyB,WAAwC;AAC5F,UAAM,WAAW,MAAM,UAAU,KAA0B,QAAQ,gBAAgB,SAAS;AAC5F,WAAO,cAAc,SAAS,OAAO;AAAA,EACvC;AAAA,EAEA,MAAM,KAAK,WAAmB,QAAgB,QAA+C;AAC3F,UAAM,UAAU,KAAK,SAAS,IAAI,SAAS;AAC3C,QAAI,CAAC,SAAS;AACZ,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO;AAAA,UACLD,gBAAe;AAAA,YACb,MAAMC,mBAAkB;AAAA,YACxB,SAAS,iCAAiC,SAAS;AAAA,UACrD,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAEA,QAAI;AACF,cAAQ,QAAQ;AAAA,QACd,KAAK,aAAa;AAChB,gBAAM,EAAE,QAAQ,OAAO,IAAI;AAC3B,gBAAM,UAAU,YAAY,EAAE,QAAQ,OAAO,CAAC;AAC9C,gBAAM,sBAAsB,WAAW;AAGvC,gBAAM,gBAAgB,QAAQ,KAAK,YAAY,KAAK;AACpD,cAAI,CAAC,oBAAqB,MAAK,2BAA2B,OAAO,aAAa;AAC9E,gBAAM,yBACJ,CAAC,uBAAuB,CAAC,KAAK,2BAA2B,IAAI,aAAa;AAC5E,cAAI,wBAAwB;AAC1B,iBAAK,QAAQ,KAAK,YAAY;AAAA,cAC5B,MAAM,sBAAsB;AAAA,cAC5B,SAAS,EAAE,UAAU;AAAA,YACvB,CAAC;AAAA,UACH;AACA,cAAI;AACF,kBAAM,WAAW,MAAM,KAAK,eAAe,QAAQ,WAAW,OAAO;AACrE,gBAAI,qBAAqB;AACvB,mBAAK,2BAA2B,IAAI,aAAa;AAAA,YACnD;AACA,mBAAO,QAAQ,QAAQ;AAAA,UACzB,UAAE;AACA,gBAAI,wBAAwB;AAC1B,mBAAK,QAAQ,KAAK,YAAY;AAAA,gBAC5B,MAAM,sBAAsB;AAAA,gBAC5B,SAAS,EAAE,UAAU;AAAA,cACvB,CAAC;AAAA,YACH;AAAA,UACF;AAAA,QACF;AAAA,QACA,KAAK,mBAAmB;AACtB,gBAAM,WAAW,MAAM,QAAQ,UAAU;AAAA,YACvC,QAAQ;AAAA,YACR;AAAA,UACF;AAGA,iBAAO,QAAQ,EAAE,QAAQ,SAAS,YAAY,KAAK,CAAC;AAAA,QACtD;AAAA,QACA,KAAK;AACH,iBAAO,QAAQ,MAAM,KAAK,eAAe,QAAQ,SAAS,CAAC;AAAA,QAC7D;AACE,iBAAO;AAAA,YACL,SAAS;AAAA,YACT,OAAO;AAAA,cACLD,gBAAe;AAAA,gBACb,MAAMC,mBAAkB;AAAA,gBACxB,SAAS,0CAA0C,MAAM;AAAA,cAC3D,CAAC;AAAA,YACH;AAAA,UACF;AAAA,MACJ;AAAA,IACF,SAAS,KAAK;AACZ,aAAO,EAAE,SAAS,OAAO,OAAO,wBAAwB,oBAAoB,GAAG,CAAC,EAAE;AAAA,IACpF;AAAA,EACF;AAAA;AAAA;AAAA,EAIA,OAAO,YAAmC;AACxC,WAAO,QAAQ,QAAQ;AAAA,EACzB;AAAA;AAAA,EAGA,WAAW,WAAkC;AAAA,EAAC;AAAA,EAE9C,GAAiC,OAAU,SAAqD;AAC9F,SAAK,QAAQ,GAAG,OAAO,OAAO;AAAA,EAChC;AAAA,EAEA,IAAkC,OAAU,SAAqD;AAC/F,SAAK,QAAQ,IAAI,OAAO,OAAO;AAAA,EACjC;AAAA,EAEA,QAAc;AACZ,eAAW,WAAW,KAAK,SAAS,OAAO,GAAG;AAC5C,cAAQ,QAAQ;AAAA,IAClB;AACA,SAAK,SAAS,MAAM;AACpB,SAAK,6BAA6B;AAClC,SAAK,gCAAgC;AACrC,SAAK,2BAA2B,MAAM;AAAA,EACxC;AAAA,EAEA,MAAc,eAAe,WAA6C;AACxE,UAAM,WAAW,MAAM,UAAU;AAAA,MAC/B,QAAQ;AAAA,MACR;AAAA,IACF;AACA,UAAM,uBAAuB,SAAS;AACtC,UAAM,oBAAoB,4BAA4B,oBAAoB;AAC1E,QAAI,sBAAsB,kCAAkC;AAC1D,YAAMD,gBAAe;AAAA,QACnB,MAAMC,mBAAkB;AAAA,QACxB,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AACA,QAAI,yBAAyB,UAAa,CAAC,mBAAmB;AAC5D,YAAMD,gBAAe;AAAA,QACnB,MAAMC,mBAAkB;AAAA,QACxB,SACE;AAAA,MACJ,CAAC;AAAA,IACH;AACA,WAAO;AAAA;AAAA,MAEL,SACE,OAAO,SAAS,oBAAoB,YACpC,kDAAkD,KAAK,SAAS,eAAe,IAC3E,SAAS,kBACT;AAAA,MACN,KAAK;AAAA,IACP;AAAA,EACF;AAAA,EAEQ,cACN,QACA,iBACA,mBACA;AACA,WAAO;AAAA,MACL,QAAQ;AAAA;AAAA;AAAA,MAGR,OAAO,OAAO,SAAS;AAAA,MACvB,WAAW,OAAO;AAAA,MAClB,iBAAiB,mBAAmB;AAAA,MACpC,UAAU,OAAO;AAAA,MACjB,WAAW,OAAO;AAAA,MAClB,gBAAgB;AAAA,MAChB,cAAc,OAAO;AAAA,MACrB,cAAc,EAAE,0BAA0B,MAAM;AAAA,MAChD,KAAK,EAAE,kBAAkB;AAAA,IAC3B;AAAA,EACF;AACF;","names":["HardwareErrorCode","createHwkError","createHwkError","HardwareErrorCode","device"]}
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/errors.ts
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/errors.ts
2
2
  var _hwkadaptercore = require('@onekeyfe/hwk-adapter-core');
3
3
  var _hwtransporterror = require('@keystonehq/hw-transport-error');
4
4
  function isDeviceStatus(statusCode) {
@@ -66,7 +66,7 @@ function mapKeystoneUsbError(err) {
66
66
  const fromDevice = isDeviceStatus(statusCode);
67
67
  let code = fromDevice ? _nullishCoalesce(DEVICE_STATUS_MAP[statusCode], () => ( _hwkadaptercore.HardwareErrorCode.UnknownError)) : _nullishCoalesce(CLIENT_STATUS_MAP[statusCode], () => ( _hwkadaptercore.HardwareErrorCode.TransportError));
68
68
  if (statusCode === _hwtransporterror.Status.PRS_PARSING_DISALLOWED && !/\blocked\b/i.test(message)) {
69
- code = _hwkadaptercore.HardwareErrorCode.DeviceBusy;
69
+ code = _hwkadaptercore.HardwareErrorCode.DeviceBusyInternal;
70
70
  }
71
71
  let origin;
72
72
  if (fromDevice) {
@@ -93,7 +93,6 @@ function mapKeystoneUsbError(err) {
93
93
 
94
94
  // src/KeystoneUsbConnectorBase.ts
95
95
  var _bcur = require('@ngraveio/bc-ur');
96
- var _bytewords = require('@ngraveio/bc-ur/dist/bytewords'); var _bytewords2 = _interopRequireDefault(_bytewords);
97
96
  var _hwtransportusb = require('@keystonehq/hw-transport-usb');
98
97
 
99
98
 
@@ -148,10 +147,7 @@ function readFountainPart(input) {
148
147
  function assertBoundedUrPart(part) {
149
148
  const match = /^ur:[a-z0-9-]+\/(?:(\d{1,9})-(\d{1,9})\/)?([a-z]+)$/i.exec(part);
150
149
  if (!match) throw new Error("Keystone USB reply part is not a UR");
151
- const payload = Buffer.from(
152
- _bytewords2.default.decode(match[3].toLowerCase(), _bytewords2.default.STYLES.MINIMAL),
153
- "hex"
154
- );
150
+ const payload = _bcur.URDecoder.decode(`ur:bytes/${match[3].toLowerCase()}`).cbor;
155
151
  _hwkadaptercore.assertBoundedCbor.call(void 0, payload, MAX_UR_MESSAGE_BYTES);
156
152
  if (match[1] === void 0) return;
157
153
  const header = readFountainPart(payload);
@@ -170,7 +166,8 @@ function fromUrEncoded(encoded) {
170
166
  decoder.receivePart(part);
171
167
  if (decoder.isComplete()) break;
172
168
  }
173
- } catch (e) {
169
+ } catch (error) {
170
+ if (error instanceof TypeError || error instanceof ReferenceError) throw error;
174
171
  }
175
172
  if (!parts.length || !decoder.isComplete() || !decoder.isSuccess()) {
176
173
  const shape = typeof encoded === "string" ? `string len=${text.length} parts=${parts.length}` : typeof encoded;
@@ -635,4 +632,4 @@ var KeystoneUsbConnectorBase = class {
635
632
 
636
633
 
637
634
  exports.mapKeystoneUsbError = mapKeystoneUsbError; exports.KeystoneUsbConnectorBase = KeystoneUsbConnectorBase;
638
- //# sourceMappingURL=chunk-U76BQU3H.js.map
635
+ //# sourceMappingURL=chunk-SSX2PJQZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/home/runner/work/hardware-js-sdk/hardware-js-sdk/packages/hwk-keystone-connector-usb/dist/chunk-SSX2PJQZ.js","../src/errors.ts","../src/KeystoneUsbConnectorBase.ts"],"names":["HardwareErrorCode","createHwkError"],"mappings":"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","file":"/home/runner/work/hardware-js-sdk/hardware-js-sdk/packages/hwk-keystone-connector-usb/dist/chunk-SSX2PJQZ.js","sourcesContent":[null,"import { HardwareErrorCode, createHwkError } from '@onekeyfe/hwk-adapter-core';\nimport { Status } from '@keystonehq/hw-transport-error';\n\nimport type { HwkError, HwkErrorOrigin } from '@onekeyfe/hwk-adapter-core';\n\n/**\n * Firmware status words are the low end of `Status` (0..15); client codes start at\n * `ERR_DEVICE_NOT_OPENED` (0xA0000001), so anything below came from a device response frame.\n */\nfunction isDeviceStatus(statusCode: number): boolean {\n return statusCode >= 0 && statusCode < Status.ERR_DEVICE_NOT_OPENED;\n}\n\n/** Firmware status words from a device response (EAPDU_Readme.md in the Keystone USB SDK). */\nconst DEVICE_STATUS_MAP: Partial<Record<number, HardwareErrorCode>> = {\n [Status.RSP_FAILURE_CODE]: HardwareErrorCode.UnknownError,\n [Status.PRS_INVALID_TOTAL_PACKETS]: HardwareErrorCode.InvalidParams,\n [Status.PRS_INVALID_INDEX]: HardwareErrorCode.InvalidParams,\n [Status.PRS_PARSING_REJECTED]: HardwareErrorCode.UserRejected,\n [Status.PRS_PARSING_ERROR]: HardwareErrorCode.InvalidParams,\n [Status.PRS_PARSING_DISALLOWED]: HardwareErrorCode.DeviceLocked,\n [Status.PRS_PARSING_UNMATCHED]: HardwareErrorCode.InvalidParams,\n [Status.PRS_PARSING_MISMATCHED_WALLET]: HardwareErrorCode.DeviceMismatch,\n [Status.PRS_PARSING_VERIFY_PASSWORD_ERROR]: HardwareErrorCode.PinInvalid,\n [Status.PRS_EXPORT_ADDRESS_UNSUPPORTED_CHAIN]: HardwareErrorCode.ChainNotSupported,\n [Status.PRS_EXPORT_ADDRESS_INVALID_PARAMS]: HardwareErrorCode.InvalidParams,\n [Status.PRS_EXPORT_ADDRESS_ERROR]: HardwareErrorCode.UnknownError,\n [Status.PRS_EXPORT_ADDRESS_DISALLOWED]: HardwareErrorCode.DeviceLocked,\n [Status.PRS_EXPORT_ADDRESS_REJECTED]: HardwareErrorCode.UserRejected,\n [Status.PRS_EXPORT_ADDRESS_BUSY]: HardwareErrorCode.DeviceBusyInternal,\n};\n\n/** Used when the transport forwarded only its 'unknown error' placeholder for a firmware status. */\nconst DEVICE_STATUS_MESSAGE: Partial<Record<number, string>> = {\n [Status.RSP_FAILURE_CODE]: 'Keystone reported a failure',\n [Status.PRS_INVALID_TOTAL_PACKETS]: 'Keystone rejected the request framing (total packets)',\n [Status.PRS_INVALID_INDEX]: 'Keystone rejected the request framing (packet index)',\n [Status.PRS_PARSING_REJECTED]: 'Rejected on the Keystone screen',\n [Status.PRS_PARSING_ERROR]: 'Keystone could not parse the request',\n [Status.PRS_PARSING_DISALLOWED]: 'Keystone declined the request in its current state',\n [Status.PRS_PARSING_UNMATCHED]: 'Keystone found no handler for the request',\n [Status.PRS_PARSING_MISMATCHED_WALLET]: 'The request belongs to a different Keystone wallet',\n [Status.PRS_PARSING_VERIFY_PASSWORD_ERROR]: 'Keystone password verification failed',\n [Status.PRS_EXPORT_ADDRESS_UNSUPPORTED_CHAIN]: 'Keystone does not support this chain',\n [Status.PRS_EXPORT_ADDRESS_INVALID_PARAMS]: 'Keystone rejected the address export parameters',\n [Status.PRS_EXPORT_ADDRESS_ERROR]: 'Keystone failed to export the address',\n [Status.PRS_EXPORT_ADDRESS_DISALLOWED]: 'Keystone declined to export the address',\n [Status.PRS_EXPORT_ADDRESS_REJECTED]: 'Address export rejected on the Keystone screen',\n [Status.PRS_EXPORT_ADDRESS_BUSY]: 'Keystone is busy with another request',\n};\n\n/** The placeholder both Keystone transports use when they have nothing better. */\nconst PLACEHOLDER_MESSAGE = /^unknown error\\b/i;\n\n/** Client-side (transport/framing) failures, never reached the device. */\nconst CLIENT_STATUS_MAP: Partial<Record<number, HardwareErrorCode>> = {\n [Status.ERR_DEVICE_NOT_OPENED]: HardwareErrorCode.DeviceNotFound,\n [Status.ERR_DEVICE_NOT_FOUND]: HardwareErrorCode.DeviceNotFound,\n [Status.ERR_TIMEOUT]: HardwareErrorCode.OperationTimeout,\n [Status.ERR_DATA_TOO_LARGE]: HardwareErrorCode.PayloadTooLarge,\n [Status.ERR_NOT_SUPPORTED]: HardwareErrorCode.TransportNotAvailable,\n};\n\n/** WebUSB DOMExceptions; an unplug or bus reset mid-call is the common case. */\nconst DOM_EXCEPTION_MAP = new Map<string, { code: HardwareErrorCode; origin: HwkErrorOrigin }>([\n ['NotFoundError', { code: HardwareErrorCode.DeviceNotFound, origin: 'transport' }],\n ['NetworkError', { code: HardwareErrorCode.DeviceNotFound, origin: 'transport' }],\n ['SecurityError', { code: HardwareErrorCode.DevicePermissionDenied, origin: 'host' }],\n ['NotAllowedError', { code: HardwareErrorCode.DevicePermissionDenied, origin: 'host' }],\n ['InvalidStateError', { code: HardwareErrorCode.DeviceBusy, origin: 'transport' }],\n ['AbortError', { code: HardwareErrorCode.DeviceBusy, origin: 'transport' }],\n]);\n\n/**\n * Maps a Keystone USB SDK failure to `HardwareErrorCode`. Fields are read duck-typed because\n * duplicate `@keystonehq/*` module instances break `instanceof`.\n */\nexport function mapKeystoneUsbError(err: unknown): HwkError {\n const fields: { name?: unknown; code?: unknown; transportErrorCode?: unknown } =\n err && typeof err === 'object' ? err : {};\n const domName = typeof fields.name === 'string' ? fields.name : undefined;\n\n // Only five-digit codes are HWK codes; legacy DOMException codes (NotFoundError\n // is 8) must not pass through as hardware errors.\n if (typeof fields.code === 'number' && fields.code >= 10000 && fields.code <= 99999) {\n return err as HwkError;\n }\n\n const statusCode =\n typeof fields.transportErrorCode === 'number' ? fields.transportErrorCode : undefined;\n\n const message = err instanceof Error ? err.message : String(err);\n\n if (statusCode !== undefined) {\n const fromDevice = isDeviceStatus(statusCode);\n // An unlisted firmware status keeps origin 'device'; 'transport' would make the\n // adapter tear down a live session over an on-device decline.\n let code = fromDevice\n ? DEVICE_STATUS_MAP[statusCode] ?? HardwareErrorCode.UnknownError\n : CLIENT_STATUS_MAP[statusCode] ?? HardwareErrorCode.TransportError;\n // Firmware also returns PRS_PARSING_DISALLOWED for an unfinished request, a pending approval\n // and a screen that takes no requests; only its \"Device is locked\" text means locked.\n if (statusCode === Status.PRS_PARSING_DISALLOWED && !/\\blocked\\b/i.test(message)) {\n code = HardwareErrorCode.DeviceBusyInternal;\n }\n let origin: HwkErrorOrigin | undefined;\n if (fromDevice) {\n origin = 'device';\n } else if (code !== HardwareErrorCode.OperationTimeout) {\n origin = 'transport';\n }\n const description = DEVICE_STATUS_MESSAGE[statusCode];\n return createHwkError({\n code,\n // The device's own payload text wins over the table.\n message:\n description && PLACEHOLDER_MESSAGE.test(message)\n ? `${description} (error_code: ${statusCode})`\n : message,\n // A timeout may be either side, so it stays unlabeled.\n origin,\n params: { statusCode, details: (err as { details?: string }).details },\n });\n }\n\n const domMapping = domName ? DOM_EXCEPTION_MAP.get(domName) : undefined;\n if (domMapping) {\n return createHwkError({ ...domMapping, message, params: { domExceptionName: domName } });\n }\n\n // This mapper only wraps transport calls, so 'transport' names the throw site.\n return createHwkError({ code: HardwareErrorCode.TransportError, message, origin: 'transport' });\n}\n","import { UR, URDecoder, UREncoder } from '@ngraveio/bc-ur';\nimport { Actions } from '@keystonehq/hw-transport-usb';\nimport {\n EConnectorInteraction,\n HardwareErrorCode,\n MISSING_BIP32_MASTER_FINGERPRINT,\n TypedEventEmitter,\n assertBoundedCbor,\n createHardwareLinkId,\n createHardwareSearchTargetId,\n createHwkError,\n hasHardwareRuntimeIdPrefix,\n parseBip32MasterFingerprint,\n parseHardwareRuntimeId,\n serializeConnectorError,\n success,\n} from '@onekeyfe/hwk-adapter-core';\n\nimport { mapKeystoneUsbError } from './errors';\n\nimport type {\n ConnectorCallResult,\n ConnectorConnectTarget,\n ConnectorDevice,\n ConnectorEventMap,\n ConnectorEventType,\n ConnectorSearchDevicesOptions,\n ConnectorSession,\n IConnector,\n UiResponseEvent,\n} from '@onekeyfe/hwk-adapter-core';\nimport type { TransportConfig, TransportHID } from '@keystonehq/hw-transport-usb';\n\n/** Descriptor fields readable before opening; any may be absent if not published. */\nexport interface KeystoneUsbDeviceDescriptor {\n serialNumber?: string;\n productName?: string;\n manufacturerName?: string;\n vendorId?: number;\n productId?: number;\n /** Device release number (bcdDevice), split into its three nibble groups. */\n deviceVersionMajor?: number;\n deviceVersionMinor?: number;\n deviceVersionSubminor?: number;\n usbVersionMajor?: number;\n usbVersionMinor?: number;\n usbVersionSubminor?: number;\n deviceClass?: number;\n deviceSubclass?: number;\n deviceProtocol?: number;\n}\n\n/** The serial is not shown on the unit, so it would not help tell two devices apart. */\nfunction usbDisplayName(device: KeystoneUsbDeviceDescriptor): string {\n return device.productName?.trim() || 'Keystone';\n}\n\n/** Static surface of `TransportWebUSB`, injected by `_subpath/webusb`. */\nexport interface KeystoneUsbTransportStatic {\n connect(config?: TransportConfig): Promise<TransportHID>;\n connectDevice?(\n device: KeystoneUsbDeviceDescriptor,\n config?: TransportConfig\n ): Promise<TransportHID>;\n getKeystoneDevices(): Promise<ReadonlyArray<KeystoneUsbDeviceDescriptor>>;\n requestPermission?(): Promise<void>;\n isSupported(): Promise<boolean>;\n /** Release transport-lifetime resources owned by the platform wrapper. */\n disposeTransport?(transport: TransportHID): void;\n}\n\ninterface KeystoneUr {\n urType: string;\n urData: string;\n}\n\ninterface UsbSession {\n transport: TransportHID;\n mfp?: string;\n dispose(): void;\n}\n\ninterface AppConfig {\n version?: string;\n mfp?: string;\n}\n\ninterface OpenedUsbTransport {\n transport: TransportHID;\n bindSessionId(sessionId: string): void;\n dispose(): void;\n}\n\ntype KeystoneUsbConnectInput =\n | { searchTargetId: string; expectedMasterFingerprint?: never }\n | { searchTargetId?: never; expectedMasterFingerprint: string }\n | { searchTargetId?: never; expectedMasterFingerprint?: never };\n\n// The SDK default of 15s is too short for on-device confirmation.\nconst DEFAULT_TIMEOUT_MS = 100_000;\n\nconst KEYSTONE_PUBLIC_DATA_UR_TYPE = 'qr-hardware-call';\n\nfunction toUrEncoded(ur: KeystoneUr): string {\n return new UREncoder(new UR(Buffer.from(ur.urData, 'hex'), ur.urType), Infinity)\n .nextPart()\n .toUpperCase();\n}\n\n/** The most data one reply may carry, whatever its fragment size. */\nconst MAX_UR_MESSAGE_BYTES = 1024 * 1024;\n/**\n * The fountain decoder's work per mixed part grows with the square of the part count, so a reply\n * cut into tiny fragments can stall it even within the byte limit.\n */\nconst MAX_UR_SEQ_LENGTH = 32_768;\n/** Argument bytes for CBOR additional info 24, 25, 26 and 27. */\nconst CBOR_ARGUMENT_BYTES = [1, 2, 4, 8];\n\n/** Reads `[seqNum, seqLen, messageLen, checksum, fragment]` from CBOR that passed the bounds. */\nfunction readFountainPart(input: Uint8Array) {\n let offset = 0;\n const readHead = (expectedMajor: number): number => {\n const initial = input[offset];\n offset += 1;\n if (Math.floor(initial / 32) !== expectedMajor) {\n throw new Error('Keystone USB reply part is not a fountain part');\n }\n const info = initial % 32;\n if (info < 24) return info;\n const size = CBOR_ARGUMENT_BYTES[info - 24];\n let value = 0;\n for (let i = 0; i < size; i += 1) value = value * 256 + input[offset + i];\n offset += size;\n return value;\n };\n if (readHead(4) !== 5) throw new Error('Keystone USB reply part is not a fountain part');\n const seqNum = readHead(0);\n const seqLength = readHead(0);\n const messageLength = readHead(0);\n readHead(0); // checksum\n const fragmentLength = readHead(2);\n return { seqNum, seqLength, messageLength, fragmentLength };\n}\n\n/** Checks one UR part from the device before the vendor decoder parses its CBOR. */\nfunction assertBoundedUrPart(part: string): void {\n const match = /^ur:[a-z0-9-]+\\/(?:(\\d{1,9})-(\\d{1,9})\\/)?([a-z]+)$/i.exec(part);\n if (!match) throw new Error('Keystone USB reply part is not a UR');\n // Decodes the minimal bytewords body (CRC32-checked, throws on a mismatch) through the package\n // root: a deep `dist/` import breaks strict ESM consumers of this package's `.mjs` build.\n const payload = URDecoder.decode(`ur:bytes/${match[3].toLowerCase()}`).cbor;\n assertBoundedCbor(payload, MAX_UR_MESSAGE_BYTES);\n if (match[1] === undefined) return;\n const header = readFountainPart(payload);\n // The text header, the CBOR header and the real sizes must agree, so the declared part count\n // is tied to the data the reply actually carries. USB is lossless and Keystone answers with a\n // single-part UR, so a mixed fountain part (seqNum past seqLen) is refused: decoding each one\n // costs time quadratic in the part count.\n if (\n header.seqNum < 1 ||\n header.seqNum > header.seqLength ||\n header.seqNum !== Number(match[1]) ||\n header.seqLength !== Number(match[2]) ||\n header.fragmentLength < 1 ||\n header.messageLength < 1 ||\n header.messageLength > MAX_UR_MESSAGE_BYTES ||\n header.seqLength > MAX_UR_SEQ_LENGTH ||\n header.seqLength !== Math.ceil(header.messageLength / header.fragmentLength)\n ) {\n throw new Error('Keystone USB reply part has inconsistent or oversized headers');\n }\n}\n\nfunction fromUrEncoded(encoded: unknown): KeystoneUr {\n // One complete UR or whitespace-separated parts; EAPDU framing is the transport's job.\n const text = typeof encoded === 'string' ? encoded.trim() : '';\n const parts = text.split(/\\s+/).filter(Boolean);\n const decoder = new URDecoder();\n try {\n if (parts.length > MAX_UR_SEQ_LENGTH) throw new Error('Keystone USB reply has too many parts');\n for (const part of parts) {\n assertBoundedUrPart(part);\n decoder.receivePart(part);\n if (decoder.isComplete()) break;\n }\n } catch (error) {\n // A part that does not decode is the device's reply, not a broken link: report it below as\n // an unreadable answer so the session is kept rather than re-claimed. A TypeError or\n // ReferenceError is a bug or a broken install, not device data, so it surfaces as is.\n if (error instanceof TypeError || error instanceof ReferenceError) throw error;\n }\n if (!parts.length || !decoder.isComplete() || !decoder.isSuccess()) {\n const shape =\n typeof encoded === 'string'\n ? `string len=${text.length} parts=${parts.length}`\n : typeof encoded;\n throw createHwkError({\n code: HardwareErrorCode.PayloadTooLarge,\n message: `Keystone USB returned an incomplete BC-UR response (${shape})`,\n origin: 'device',\n // The device processed the request; only its reply is unusable.\n params: { replyUnreadable: true },\n });\n }\n const ur = decoder.resultUR();\n return { urType: ur.type, urData: ur.cbor.toString('hex') };\n}\n\n/**\n * Keystone USB `IConnector`. Each transport call is its own open/claim/transfer/close cycle, so\n * `connect()` only caches the transport object.\n */\nexport class KeystoneUsbConnectorBase implements IConnector {\n readonly connectionType = 'usb' as const;\n\n private readonly transportClass: KeystoneUsbTransportStatic;\n\n private readonly timeoutMs: number;\n\n private readonly emitter = new TypedEventEmitter<ConnectorEventMap>();\n\n private readonly sessions = new Map<string, UsbSession>();\n\n private readonly discoveredDevices = new Map<string, KeystoneUsbDeviceDescriptor>();\n\n private readonly availabilityDevices = new Map<string, KeystoneUsbDeviceDescriptor>();\n\n private activeDiscoveryGeneration: symbol | undefined;\n\n private activeAvailabilityGeneration: symbol | undefined;\n\n /**\n * Wallets (by mfp) that approved a public-data export. Connector-scoped because the device can\n * re-enumerate between exports, and that must not re-prompt.\n */\n private readonly publicDataConfirmedWallets = new Set<string>();\n\n constructor(transportClass: KeystoneUsbTransportStatic, options?: { timeoutMs?: number }) {\n this.transportClass = transportClass;\n this.timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n }\n\n private _invalidateDiscoverySnapshot(): void {\n this.activeDiscoveryGeneration = undefined;\n this.discoveredDevices.clear();\n }\n\n private _invalidateAvailabilitySnapshot(): void {\n this.activeAvailabilityGeneration = undefined;\n this.availabilityDevices.clear();\n }\n\n async searchDevices(options?: ConnectorSearchDevicesOptions): Promise<ConnectorDevice[]> {\n const isAvailabilitySearch = options?.purpose === 'availability';\n const discoveryGeneration = Symbol(\n isAvailabilitySearch ? 'keystone-usb-availability' : 'keystone-usb-discovery'\n );\n if (isAvailabilitySearch) {\n this._invalidateAvailabilitySnapshot();\n this.activeAvailabilityGeneration = discoveryGeneration;\n } else {\n this._invalidateDiscoverySnapshot();\n this.activeDiscoveryGeneration = discoveryGeneration;\n }\n // Enumeration DOMException codes collide with the HWK range, so map them too.\n let devices: ReadonlyArray<KeystoneUsbDeviceDescriptor>;\n try {\n devices = await this.transportClass.getKeystoneDevices();\n } catch (err) {\n throw mapKeystoneUsbError(err);\n }\n // Without an mfp before opening, the target id names only this snapshot; platforms that\n // cannot reopen a cached descriptor fail closed on multi-device selection.\n if (\n (isAvailabilitySearch\n ? this.activeAvailabilityGeneration\n : this.activeDiscoveryGeneration) !== discoveryGeneration\n ) {\n return [];\n }\n return devices.map(device => {\n const connectId = createHardwareSearchTargetId('keystone');\n (isAvailabilitySearch ? this.availabilityDevices : this.discoveredDevices).set(\n connectId,\n device\n );\n return {\n connectId,\n deviceId: '',\n name: usbDisplayName(device),\n connectionType: 'usb',\n serialNumber: device.serialNumber,\n capabilities: { persistentDeviceIdentity: false },\n // Verbatim descriptor fields; a missing key means the device did not publish it.\n raw: {\n serialNumber: device.serialNumber,\n productName: device.productName,\n manufacturerName: device.manufacturerName,\n vendorId: device.vendorId,\n productId: device.productId,\n deviceVersionMajor: device.deviceVersionMajor,\n deviceVersionMinor: device.deviceVersionMinor,\n deviceVersionSubminor: device.deviceVersionSubminor,\n usbVersionMajor: device.usbVersionMajor,\n usbVersionMinor: device.usbVersionMinor,\n usbVersionSubminor: device.usbVersionSubminor,\n deviceClass: device.deviceClass,\n deviceSubclass: device.deviceSubclass,\n deviceProtocol: device.deviceProtocol,\n },\n };\n });\n }\n\n async connect(searchTargetIdOrExpectedMasterFingerprint?: string): Promise<ConnectorSession> {\n return this._connectResolved(\n this._resolveConnectInput(searchTargetIdOrExpectedMasterFingerprint)\n );\n }\n\n async connectTarget(target: ConnectorConnectTarget): Promise<ConnectorSession> {\n switch (target.type) {\n case 'default':\n return this._connectResolved({});\n case 'search-target':\n return this._connectResolved({ searchTargetId: target.searchTargetId });\n case 'expected-device-identity': {\n const expectedMasterFingerprint = parseBip32MasterFingerprint(target.deviceIdentity);\n if (!expectedMasterFingerprint) {\n throw createHwkError({\n code: HardwareErrorCode.InvalidParams,\n message: 'Keystone USB connector requires a valid master fingerprint identity',\n });\n }\n return this._connectResolved({ expectedMasterFingerprint });\n }\n default:\n throw createHwkError({\n code: HardwareErrorCode.InvalidParams,\n message: 'Unsupported Keystone USB connection target',\n });\n }\n }\n\n private async _connectResolved({\n searchTargetId,\n expectedMasterFingerprint,\n }: KeystoneUsbConnectInput): Promise<ConnectorSession> {\n this.emitter.emit('ui-event', {\n type: EConnectorInteraction.Searching,\n payload: { sessionId: '' },\n });\n let selectedDevice = searchTargetId\n ? this.discoveredDevices.get(searchTargetId) ?? this.availabilityDevices.get(searchTargetId)\n : undefined;\n if (searchTargetId && !selectedDevice) {\n throw createHwkError({\n code: HardwareErrorCode.DeviceNotFound,\n message: `Keystone USB search target is not in the current scan: ${searchTargetId}`,\n recovery: { scope: 'search-target' },\n });\n }\n let openedTransport: OpenedUsbTransport | undefined;\n try {\n let config: AppConfig;\n\n if (expectedMasterFingerprint && !searchTargetId) {\n const availableDevices = await this.transportClass.getKeystoneDevices();\n if (!this.transportClass.connectDevice && availableDevices.length > 1) {\n throw createHwkError({\n code: HardwareErrorCode.DeviceOneDeviceOnly,\n message: 'This platform cannot identify one of multiple connected Keystone devices',\n });\n }\n\n if (this.transportClass.connectDevice) {\n if (availableDevices.length === 0) {\n throw createHwkError({\n code: HardwareErrorCode.DeviceNotFound,\n message: 'No Keystone USB device is available',\n });\n }\n let readableDeviceFound = false;\n let ambiguous = false;\n let lastError: unknown;\n let matched:\n | {\n device: KeystoneUsbDeviceDescriptor;\n opened: OpenedUsbTransport;\n config: AppConfig;\n }\n | undefined;\n for (const device of availableDevices) {\n let candidate: OpenedUsbTransport | undefined;\n try {\n // eslint-disable-next-line no-await-in-loop\n candidate = await this._openTransport(device);\n // eslint-disable-next-line no-await-in-loop\n const candidateConfig = await this._readAppConfig(candidate.transport);\n readableDeviceFound = true;\n if (candidateConfig.mfp?.toLowerCase() === expectedMasterFingerprint.toLowerCase()) {\n if (matched) {\n candidate.dispose();\n ambiguous = true;\n break;\n }\n matched = { device, opened: candidate, config: candidateConfig };\n // eslint-disable-next-line no-continue\n continue;\n }\n candidate.dispose();\n } catch (error) {\n candidate?.dispose();\n lastError = error;\n }\n }\n // The fingerprint is self-reported, so two claimants are refused, not ranked.\n if (ambiguous) {\n matched?.opened.dispose();\n throw createHwkError({\n code: HardwareErrorCode.DeviceOneDeviceOnly,\n message: 'More than one connected Keystone reports this wallet; keep one connected',\n });\n }\n if (!matched) {\n if (!readableDeviceFound && lastError) throw mapKeystoneUsbError(lastError);\n throw createHwkError({\n code: HardwareErrorCode.DeviceMismatch,\n message: 'No connected Keystone matches the requested wallet',\n });\n }\n selectedDevice = matched.device;\n openedTransport = matched.opened;\n config = matched.config;\n } else {\n openedTransport = await this._openTransport();\n config = await this._readAppConfig(openedTransport.transport);\n }\n } else {\n if (!selectedDevice && this.transportClass.connectDevice) {\n const availableDevices = await this.transportClass.getKeystoneDevices();\n if (availableDevices.length === 0) {\n throw createHwkError({\n code: HardwareErrorCode.DeviceNotFound,\n message: 'No Keystone USB device is available',\n });\n }\n if (availableDevices.length > 1) {\n throw createHwkError({\n code: HardwareErrorCode.DeviceOneDeviceOnly,\n message: 'Select a Keystone USB device before connecting',\n });\n }\n [selectedDevice] = availableDevices;\n }\n if (selectedDevice && !this.transportClass.connectDevice) {\n const availableDevices = await this.transportClass.getKeystoneDevices();\n if (availableDevices.length > 1) {\n throw createHwkError({\n code: HardwareErrorCode.DeviceOneDeviceOnly,\n message: 'This platform cannot target one of multiple connected Keystone devices',\n });\n }\n }\n openedTransport = await this._openTransport(selectedDevice);\n config = await this._readAppConfig(openedTransport.transport);\n }\n\n const activeOpenedTransport = openedTransport;\n const { transport } = activeOpenedTransport;\n if (\n expectedMasterFingerprint &&\n config.mfp &&\n config.mfp.toLowerCase() !== expectedMasterFingerprint.toLowerCase()\n ) {\n throw createHwkError({\n code: HardwareErrorCode.DeviceMismatch,\n // The master fingerprint identifies the wallet; keep it out of messages that reach logs.\n message: 'Connected Keystone wallet does not match the requested wallet',\n });\n }\n const sessionId = createHardwareLinkId('keystone');\n activeOpenedTransport.bindSessionId(sessionId);\n this.sessions.set(sessionId, {\n transport,\n mfp: config.mfp,\n dispose: () => activeOpenedTransport.dispose(),\n });\n openedTransport = undefined;\n const device: ConnectorDevice = {\n connectId: sessionId,\n deviceId: '',\n name: selectedDevice ? usbDisplayName(selectedDevice) : 'Keystone',\n model: selectedDevice?.productName,\n connectionType: 'usb',\n serialNumber: selectedDevice?.serialNumber,\n capabilities: { persistentDeviceIdentity: false },\n raw: { masterFingerprint: config.mfp },\n };\n this.emitter.emit('device-connect', { device });\n return {\n sessionId,\n deviceInfo: this._toDeviceInfo(device, config.version, config.mfp),\n };\n } catch (err) {\n openedTransport?.dispose();\n throw mapKeystoneUsbError(err);\n }\n }\n\n private async _openTransport(device?: KeystoneUsbDeviceDescriptor): Promise<OpenedUsbTransport> {\n // A rejected candidate may keep its disconnect listener; a per-descriptor\n // holder stops it from retiring a later matched session.\n let connectedSessionId: string | undefined;\n const transportConfig: TransportConfig = {\n timeout: this.timeoutMs,\n disconnectListener: () =>\n connectedSessionId ? this.disconnect(connectedSessionId) : undefined,\n };\n const transport = await (device && this.transportClass.connectDevice\n ? this.transportClass.connectDevice(device, transportConfig)\n : this.transportClass.connect(transportConfig));\n let disposed = false;\n return {\n transport,\n bindSessionId(sessionId: string) {\n connectedSessionId = sessionId;\n },\n dispose: () => {\n if (disposed) return;\n disposed = true;\n this.transportClass.disposeTransport?.(transport);\n },\n };\n }\n\n private _resolveConnectInput(value?: string): KeystoneUsbConnectInput {\n if (!value) return {};\n\n const runtimeId = parseHardwareRuntimeId(value);\n if (runtimeId) {\n // Ownership is settled by the snapshot lookup in `_connectResolved`.\n if (runtimeId.kind === 'search-target' && runtimeId.vendor === 'keystone') {\n return { searchTargetId: value };\n }\n throw createHwkError({\n code: HardwareErrorCode.InvalidParams,\n message: 'Keystone USB connector received an incompatible hardware runtime id',\n params: { kind: runtimeId.kind, vendor: runtimeId.vendor },\n });\n }\n\n if (hasHardwareRuntimeIdPrefix(value)) {\n throw createHwkError({\n code: HardwareErrorCode.InvalidParams,\n message: 'Keystone USB connector received a malformed hardware runtime id',\n });\n }\n\n const expectedMasterFingerprint = parseBip32MasterFingerprint(value);\n if (!expectedMasterFingerprint) {\n throw createHwkError({\n code: HardwareErrorCode.InvalidParams,\n message: 'Keystone USB connector requires a search target or master fingerprint',\n });\n }\n return { expectedMasterFingerprint };\n }\n\n disconnect(sessionId: string): Promise<void> {\n const session = this.sessions.get(sessionId);\n this.sessions.delete(sessionId);\n if (session) {\n session.dispose();\n // No persistent claim to release; each send() already closed the device.\n this.emitter.emit('device-disconnect', { connectId: sessionId });\n }\n return Promise.resolve();\n }\n\n /** Keep the vendor transport as the EAPDU framing authority. */\n private async _sendResolveUr(transport: TransportHID, encodedUr: string): Promise<KeystoneUr> {\n const response = await transport.send<{ payload: string }>(Actions.CMD_RESOLVE_UR, encodedUr);\n return fromUrEncoded(response.payload);\n }\n\n async call(sessionId: string, method: string, params: unknown): Promise<ConnectorCallResult> {\n const session = this.sessions.get(sessionId);\n if (!session) {\n return {\n success: false,\n error: serializeConnectorError(\n createHwkError({\n code: HardwareErrorCode.DeviceNotFound,\n message: `Unknown Keystone USB session: ${sessionId}`,\n })\n ),\n };\n }\n\n try {\n switch (method) {\n case 'resolveUr': {\n const { urType, urData } = params as KeystoneUr;\n const encoded = toUrEncoded({ urType, urData });\n const isPublicDataRequest = urType === KEYSTONE_PUBLIC_DATA_UR_TYPE;\n // Public-data export prompts once per wallet; signing always prompts. A signing request\n // leaves the device's export screen, so the next export may ask again and prompts again.\n const publicDataKey = session.mfp?.toLowerCase() ?? sessionId;\n if (!isPublicDataRequest) this.publicDataConfirmedWallets.delete(publicDataKey);\n const shouldShowConfirmation =\n !isPublicDataRequest || !this.publicDataConfirmedWallets.has(publicDataKey);\n if (shouldShowConfirmation) {\n this.emitter.emit('ui-event', {\n type: EConnectorInteraction.ConfirmOnDevice,\n payload: { sessionId },\n });\n }\n try {\n const response = await this._sendResolveUr(session.transport, encoded);\n if (isPublicDataRequest) {\n this.publicDataConfirmedWallets.add(publicDataKey);\n }\n return success(response);\n } finally {\n if (shouldShowConfirmation) {\n this.emitter.emit('ui-event', {\n type: EConnectorInteraction.InteractionComplete,\n payload: { sessionId },\n });\n }\n }\n }\n case 'checkLockStatus': {\n const response = await session.transport.send<{ payload: boolean }>(\n Actions.CMD_CHECK_LOCK_STATUS,\n ''\n );\n // `true` = locked is inferred from the SDK method name only; unverified on hardware.\n // Only a real boolean true counts, so a malformed reply never reads as a lock state.\n return success({ locked: response.payload === true });\n }\n case 'getAppConfig':\n return success(await this._readAppConfig(session.transport));\n default:\n return {\n success: false,\n error: serializeConnectorError(\n createHwkError({\n code: HardwareErrorCode.MethodNotSupported,\n message: `Unknown Keystone USB connector method: ${method}`,\n })\n ),\n };\n }\n } catch (err) {\n return { success: false, error: serializeConnectorError(mapKeystoneUsbError(err)) };\n }\n }\n\n // The SDK cannot interrupt an in-flight transfer; the pending send() settles or\n // times out on its own.\n cancel(_sessionId: string): Promise<void> {\n return Promise.resolve();\n }\n\n // PIN/passphrase entry happens on the device touchscreen, never via the host.\n uiResponse(_response: UiResponseEvent): void {}\n\n on<K extends ConnectorEventType>(event: K, handler: (data: ConnectorEventMap[K]) => void): void {\n this.emitter.on(event, handler);\n }\n\n off<K extends ConnectorEventType>(event: K, handler: (data: ConnectorEventMap[K]) => void): void {\n this.emitter.off(event, handler);\n }\n\n reset(): void {\n for (const session of this.sessions.values()) {\n session.dispose();\n }\n this.sessions.clear();\n this._invalidateDiscoverySnapshot();\n this._invalidateAvailabilitySnapshot();\n this.publicDataConfirmedWallets.clear();\n }\n\n private async _readAppConfig(transport: TransportHID): Promise<AppConfig> {\n const response = await transport.send<Record<string, unknown>>(\n Actions.CMD_GET_DEVICE_VERSION,\n ''\n );\n const rawMasterFingerprint = response.walletMFP;\n const masterFingerprint = parseBip32MasterFingerprint(rawMasterFingerprint);\n if (masterFingerprint === MISSING_BIP32_MASTER_FINGERPRINT) {\n throw createHwkError({\n code: HardwareErrorCode.DeviceNotInitialized,\n message: 'Keystone has no wallet yet; it reported an empty master fingerprint',\n });\n }\n if (rawMasterFingerprint !== undefined && !masterFingerprint) {\n throw createHwkError({\n code: HardwareErrorCode.DeviceMismatch,\n message:\n 'Keystone returned an invalid master fingerprint; expected exactly 4 bytes (8 hex characters)',\n });\n }\n return {\n // Device-supplied text reaches the host UI and version gates; accept only a version number.\n version:\n typeof response.firmwareVersion === 'string' &&\n /^\\d{1,4}(\\.\\d{1,4}){1,3}(-[0-9A-Za-z.]{1,20})?$/.test(response.firmwareVersion)\n ? response.firmwareVersion\n : undefined,\n mfp: masterFingerprint,\n };\n }\n\n private _toDeviceInfo(\n device: ConnectorDevice,\n firmwareVersion?: string,\n masterFingerprint?: string\n ) {\n return {\n vendor: 'keystone' as const,\n // Model is the USB `productName`; empty, not 'unknown', so the host's\n // default-name fallback wins.\n model: device.model ?? '',\n modelName: device.modelName,\n firmwareVersion: firmwareVersion ?? '0.0.0',\n deviceId: device.deviceId,\n connectId: device.connectId,\n connectionType: 'usb' as const,\n serialNumber: device.serialNumber,\n capabilities: { persistentDeviceIdentity: false },\n raw: { masterFingerprint },\n };\n }\n}\n"]}
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
2
 
3
3
 
4
- var _chunkU76BQU3Hjs = require('./chunk-U76BQU3H.js');
4
+ var _chunkSSX2PJQZjs = require('./chunk-SSX2PJQZ.js');
5
5
 
6
6
 
7
7
 
8
- exports.KeystoneUsbConnectorBase = _chunkU76BQU3Hjs.KeystoneUsbConnectorBase; exports.mapKeystoneUsbError = _chunkU76BQU3Hjs.mapKeystoneUsbError;
8
+ exports.KeystoneUsbConnectorBase = _chunkSSX2PJQZjs.KeystoneUsbConnectorBase; exports.mapKeystoneUsbError = _chunkSSX2PJQZjs.mapKeystoneUsbError;
9
9
  //# sourceMappingURL=index.js.map
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  KeystoneUsbConnectorBase,
3
3
  mapKeystoneUsbError
4
- } from "./chunk-RZ6UI5PS.mjs";
4
+ } from "./chunk-I3VFU34J.mjs";
5
5
  export {
6
6
  KeystoneUsbConnectorBase,
7
7
  mapKeystoneUsbError
package/dist/webusb.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
2
 
3
- var _chunkU76BQU3Hjs = require('./chunk-U76BQU3H.js');
3
+ var _chunkSSX2PJQZjs = require('./chunk-SSX2PJQZ.js');
4
4
 
5
5
  // src/_subpath/webusb.ts
6
6
  var _hwtransportwebusb = require('@keystonehq/hw-transport-webusb');
@@ -25,7 +25,7 @@ function createKeystoneWebUsbConnector(options) {
25
25
  disconnectListenerCleanupByTransport.set(transport, cleanup);
26
26
  return transport;
27
27
  };
28
- return new (0, _chunkU76BQU3Hjs.KeystoneUsbConnectorBase)(
28
+ return new (0, _chunkSSX2PJQZjs.KeystoneUsbConnectorBase)(
29
29
  {
30
30
  connect: async (config) => {
31
31
  await _hwtransportwebusb.TransportWebUSB.isSupported();
package/dist/webusb.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  KeystoneUsbConnectorBase
3
- } from "./chunk-RZ6UI5PS.mjs";
3
+ } from "./chunk-I3VFU34J.mjs";
4
4
 
5
5
  // src/_subpath/webusb.ts
6
6
  import { TransportWebUSB } from "@keystonehq/hw-transport-webusb";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/hwk-keystone-connector-usb",
3
- "version": "1.2.8-alpha.13",
3
+ "version": "1.2.8-alpha.52",
4
4
  "description": "IConnector implementation for Keystone hardware wallets via WebUSB",
5
5
  "author": "OneKey",
6
6
  "license": "MIT",
@@ -33,7 +33,7 @@
33
33
  "dist"
34
34
  ],
35
35
  "scripts": {
36
- "build": "tsup",
36
+ "build": "tsup && node scripts/verify-esm.mjs",
37
37
  "dev": "tsup --watch",
38
38
  "clean": "rimraf dist",
39
39
  "test": "jest"
@@ -59,7 +59,7 @@
59
59
  "@keystonehq/hw-transport-usb": "0.2.0",
60
60
  "@keystonehq/hw-transport-webusb": "0.5.3",
61
61
  "@ngraveio/bc-ur": "1.1.13",
62
- "@onekeyfe/hwk-adapter-core": "1.2.8-alpha.13"
62
+ "@onekeyfe/hwk-adapter-core": "1.2.8-alpha.52"
63
63
  },
64
64
  "devDependencies": {
65
65
  "@keystonehq/bc-ur-registry-eth": "0.22.1",
@@ -67,5 +67,5 @@
67
67
  "tsup": "^8.0.0",
68
68
  "typescript": "^5.4.0"
69
69
  },
70
- "gitHead": "ed22eddce37ce0562b329c42a6985b50949ca412"
70
+ "gitHead": "389c588beb19de26451c729bb09bc8e7ce6b0717"
71
71
  }
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/KeystoneUsbConnectorBase.ts"],"sourcesContent":["import { HardwareErrorCode, createHwkError } from '@onekeyfe/hwk-adapter-core';\nimport { Status } from '@keystonehq/hw-transport-error';\n\nimport type { HwkError, HwkErrorOrigin } from '@onekeyfe/hwk-adapter-core';\n\n/**\n * Firmware status words are the low end of `Status` (0..15); client codes start at\n * `ERR_DEVICE_NOT_OPENED` (0xA0000001), so anything below came from a device response frame.\n */\nfunction isDeviceStatus(statusCode: number): boolean {\n return statusCode >= 0 && statusCode < Status.ERR_DEVICE_NOT_OPENED;\n}\n\n/** Firmware status words from a device response (EAPDU_Readme.md in the Keystone USB SDK). */\nconst DEVICE_STATUS_MAP: Partial<Record<number, HardwareErrorCode>> = {\n [Status.RSP_FAILURE_CODE]: HardwareErrorCode.UnknownError,\n [Status.PRS_INVALID_TOTAL_PACKETS]: HardwareErrorCode.InvalidParams,\n [Status.PRS_INVALID_INDEX]: HardwareErrorCode.InvalidParams,\n [Status.PRS_PARSING_REJECTED]: HardwareErrorCode.UserRejected,\n [Status.PRS_PARSING_ERROR]: HardwareErrorCode.InvalidParams,\n [Status.PRS_PARSING_DISALLOWED]: HardwareErrorCode.DeviceLocked,\n [Status.PRS_PARSING_UNMATCHED]: HardwareErrorCode.InvalidParams,\n [Status.PRS_PARSING_MISMATCHED_WALLET]: HardwareErrorCode.DeviceMismatch,\n [Status.PRS_PARSING_VERIFY_PASSWORD_ERROR]: HardwareErrorCode.PinInvalid,\n [Status.PRS_EXPORT_ADDRESS_UNSUPPORTED_CHAIN]: HardwareErrorCode.ChainNotSupported,\n [Status.PRS_EXPORT_ADDRESS_INVALID_PARAMS]: HardwareErrorCode.InvalidParams,\n [Status.PRS_EXPORT_ADDRESS_ERROR]: HardwareErrorCode.UnknownError,\n [Status.PRS_EXPORT_ADDRESS_DISALLOWED]: HardwareErrorCode.DeviceLocked,\n [Status.PRS_EXPORT_ADDRESS_REJECTED]: HardwareErrorCode.UserRejected,\n [Status.PRS_EXPORT_ADDRESS_BUSY]: HardwareErrorCode.DeviceBusyInternal,\n};\n\n/** Used when the transport forwarded only its 'unknown error' placeholder for a firmware status. */\nconst DEVICE_STATUS_MESSAGE: Partial<Record<number, string>> = {\n [Status.RSP_FAILURE_CODE]: 'Keystone reported a failure',\n [Status.PRS_INVALID_TOTAL_PACKETS]: 'Keystone rejected the request framing (total packets)',\n [Status.PRS_INVALID_INDEX]: 'Keystone rejected the request framing (packet index)',\n [Status.PRS_PARSING_REJECTED]: 'Rejected on the Keystone screen',\n [Status.PRS_PARSING_ERROR]: 'Keystone could not parse the request',\n [Status.PRS_PARSING_DISALLOWED]: 'Keystone declined the request in its current state',\n [Status.PRS_PARSING_UNMATCHED]: 'Keystone found no handler for the request',\n [Status.PRS_PARSING_MISMATCHED_WALLET]: 'The request belongs to a different Keystone wallet',\n [Status.PRS_PARSING_VERIFY_PASSWORD_ERROR]: 'Keystone password verification failed',\n [Status.PRS_EXPORT_ADDRESS_UNSUPPORTED_CHAIN]: 'Keystone does not support this chain',\n [Status.PRS_EXPORT_ADDRESS_INVALID_PARAMS]: 'Keystone rejected the address export parameters',\n [Status.PRS_EXPORT_ADDRESS_ERROR]: 'Keystone failed to export the address',\n [Status.PRS_EXPORT_ADDRESS_DISALLOWED]: 'Keystone declined to export the address',\n [Status.PRS_EXPORT_ADDRESS_REJECTED]: 'Address export rejected on the Keystone screen',\n [Status.PRS_EXPORT_ADDRESS_BUSY]: 'Keystone is busy with another request',\n};\n\n/** The placeholder both Keystone transports use when they have nothing better. */\nconst PLACEHOLDER_MESSAGE = /^unknown error\\b/i;\n\n/** Client-side (transport/framing) failures, never reached the device. */\nconst CLIENT_STATUS_MAP: Partial<Record<number, HardwareErrorCode>> = {\n [Status.ERR_DEVICE_NOT_OPENED]: HardwareErrorCode.DeviceNotFound,\n [Status.ERR_DEVICE_NOT_FOUND]: HardwareErrorCode.DeviceNotFound,\n [Status.ERR_TIMEOUT]: HardwareErrorCode.OperationTimeout,\n [Status.ERR_DATA_TOO_LARGE]: HardwareErrorCode.PayloadTooLarge,\n [Status.ERR_NOT_SUPPORTED]: HardwareErrorCode.TransportNotAvailable,\n};\n\n/** WebUSB DOMExceptions; an unplug or bus reset mid-call is the common case. */\nconst DOM_EXCEPTION_MAP = new Map<string, { code: HardwareErrorCode; origin: HwkErrorOrigin }>([\n ['NotFoundError', { code: HardwareErrorCode.DeviceNotFound, origin: 'transport' }],\n ['NetworkError', { code: HardwareErrorCode.DeviceNotFound, origin: 'transport' }],\n ['SecurityError', { code: HardwareErrorCode.DevicePermissionDenied, origin: 'host' }],\n ['NotAllowedError', { code: HardwareErrorCode.DevicePermissionDenied, origin: 'host' }],\n ['InvalidStateError', { code: HardwareErrorCode.DeviceBusy, origin: 'transport' }],\n ['AbortError', { code: HardwareErrorCode.DeviceBusy, origin: 'transport' }],\n]);\n\n/**\n * Maps a Keystone USB SDK failure to `HardwareErrorCode`. Fields are read duck-typed because\n * duplicate `@keystonehq/*` module instances break `instanceof`.\n */\nexport function mapKeystoneUsbError(err: unknown): HwkError {\n const fields: { name?: unknown; code?: unknown; transportErrorCode?: unknown } =\n err && typeof err === 'object' ? err : {};\n const domName = typeof fields.name === 'string' ? fields.name : undefined;\n\n // Only five-digit codes are HWK codes; legacy DOMException codes (NotFoundError\n // is 8) must not pass through as hardware errors.\n if (typeof fields.code === 'number' && fields.code >= 10000 && fields.code <= 99999) {\n return err as HwkError;\n }\n\n const statusCode =\n typeof fields.transportErrorCode === 'number' ? fields.transportErrorCode : undefined;\n\n const message = err instanceof Error ? err.message : String(err);\n\n if (statusCode !== undefined) {\n const fromDevice = isDeviceStatus(statusCode);\n // An unlisted firmware status keeps origin 'device'; 'transport' would make the\n // adapter tear down a live session over an on-device decline.\n let code = fromDevice\n ? DEVICE_STATUS_MAP[statusCode] ?? HardwareErrorCode.UnknownError\n : CLIENT_STATUS_MAP[statusCode] ?? HardwareErrorCode.TransportError;\n // Firmware also returns PRS_PARSING_DISALLOWED for an unfinished request, a pending approval\n // and a screen that takes no requests; only its \"Device is locked\" text means locked.\n if (statusCode === Status.PRS_PARSING_DISALLOWED && !/\\blocked\\b/i.test(message)) {\n code = HardwareErrorCode.DeviceBusy;\n }\n let origin: HwkErrorOrigin | undefined;\n if (fromDevice) {\n origin = 'device';\n } else if (code !== HardwareErrorCode.OperationTimeout) {\n origin = 'transport';\n }\n const description = DEVICE_STATUS_MESSAGE[statusCode];\n return createHwkError({\n code,\n // The device's own payload text wins over the table.\n message:\n description && PLACEHOLDER_MESSAGE.test(message)\n ? `${description} (error_code: ${statusCode})`\n : message,\n // A timeout may be either side, so it stays unlabeled.\n origin,\n params: { statusCode, details: (err as { details?: string }).details },\n });\n }\n\n const domMapping = domName ? DOM_EXCEPTION_MAP.get(domName) : undefined;\n if (domMapping) {\n return createHwkError({ ...domMapping, message, params: { domExceptionName: domName } });\n }\n\n // This mapper only wraps transport calls, so 'transport' names the throw site.\n return createHwkError({ code: HardwareErrorCode.TransportError, message, origin: 'transport' });\n}\n","import { UR, URDecoder, UREncoder } from '@ngraveio/bc-ur';\n// Not re-exported by the package root; pinned with the package version.\nimport bytewords from '@ngraveio/bc-ur/dist/bytewords';\nimport { Actions } from '@keystonehq/hw-transport-usb';\nimport {\n EConnectorInteraction,\n HardwareErrorCode,\n MISSING_BIP32_MASTER_FINGERPRINT,\n TypedEventEmitter,\n assertBoundedCbor,\n createHardwareLinkId,\n createHardwareSearchTargetId,\n createHwkError,\n hasHardwareRuntimeIdPrefix,\n parseBip32MasterFingerprint,\n parseHardwareRuntimeId,\n serializeConnectorError,\n success,\n} from '@onekeyfe/hwk-adapter-core';\n\nimport { mapKeystoneUsbError } from './errors';\n\nimport type {\n ConnectorCallResult,\n ConnectorConnectTarget,\n ConnectorDevice,\n ConnectorEventMap,\n ConnectorEventType,\n ConnectorSearchDevicesOptions,\n ConnectorSession,\n IConnector,\n UiResponseEvent,\n} from '@onekeyfe/hwk-adapter-core';\nimport type { TransportConfig, TransportHID } from '@keystonehq/hw-transport-usb';\n\n/** Descriptor fields readable before opening; any may be absent if not published. */\nexport interface KeystoneUsbDeviceDescriptor {\n serialNumber?: string;\n productName?: string;\n manufacturerName?: string;\n vendorId?: number;\n productId?: number;\n /** Device release number (bcdDevice), split into its three nibble groups. */\n deviceVersionMajor?: number;\n deviceVersionMinor?: number;\n deviceVersionSubminor?: number;\n usbVersionMajor?: number;\n usbVersionMinor?: number;\n usbVersionSubminor?: number;\n deviceClass?: number;\n deviceSubclass?: number;\n deviceProtocol?: number;\n}\n\n/** The serial is not shown on the unit, so it would not help tell two devices apart. */\nfunction usbDisplayName(device: KeystoneUsbDeviceDescriptor): string {\n return device.productName?.trim() || 'Keystone';\n}\n\n/** Static surface of `TransportWebUSB`, injected by `_subpath/webusb`. */\nexport interface KeystoneUsbTransportStatic {\n connect(config?: TransportConfig): Promise<TransportHID>;\n connectDevice?(\n device: KeystoneUsbDeviceDescriptor,\n config?: TransportConfig\n ): Promise<TransportHID>;\n getKeystoneDevices(): Promise<ReadonlyArray<KeystoneUsbDeviceDescriptor>>;\n requestPermission?(): Promise<void>;\n isSupported(): Promise<boolean>;\n /** Release transport-lifetime resources owned by the platform wrapper. */\n disposeTransport?(transport: TransportHID): void;\n}\n\ninterface KeystoneUr {\n urType: string;\n urData: string;\n}\n\ninterface UsbSession {\n transport: TransportHID;\n mfp?: string;\n dispose(): void;\n}\n\ninterface AppConfig {\n version?: string;\n mfp?: string;\n}\n\ninterface OpenedUsbTransport {\n transport: TransportHID;\n bindSessionId(sessionId: string): void;\n dispose(): void;\n}\n\ntype KeystoneUsbConnectInput =\n | { searchTargetId: string; expectedMasterFingerprint?: never }\n | { searchTargetId?: never; expectedMasterFingerprint: string }\n | { searchTargetId?: never; expectedMasterFingerprint?: never };\n\n// The SDK default of 15s is too short for on-device confirmation.\nconst DEFAULT_TIMEOUT_MS = 100_000;\n\nconst KEYSTONE_PUBLIC_DATA_UR_TYPE = 'qr-hardware-call';\n\nfunction toUrEncoded(ur: KeystoneUr): string {\n return new UREncoder(new UR(Buffer.from(ur.urData, 'hex'), ur.urType), Infinity)\n .nextPart()\n .toUpperCase();\n}\n\n/** The most data one reply may carry, whatever its fragment size. */\nconst MAX_UR_MESSAGE_BYTES = 1024 * 1024;\n/**\n * The fountain decoder's work per mixed part grows with the square of the part count, so a reply\n * cut into tiny fragments can stall it even within the byte limit.\n */\nconst MAX_UR_SEQ_LENGTH = 32_768;\n/** Argument bytes for CBOR additional info 24, 25, 26 and 27. */\nconst CBOR_ARGUMENT_BYTES = [1, 2, 4, 8];\n\n/** Reads `[seqNum, seqLen, messageLen, checksum, fragment]` from CBOR that passed the bounds. */\nfunction readFountainPart(input: Uint8Array) {\n let offset = 0;\n const readHead = (expectedMajor: number): number => {\n const initial = input[offset];\n offset += 1;\n if (Math.floor(initial / 32) !== expectedMajor) {\n throw new Error('Keystone USB reply part is not a fountain part');\n }\n const info = initial % 32;\n if (info < 24) return info;\n const size = CBOR_ARGUMENT_BYTES[info - 24];\n let value = 0;\n for (let i = 0; i < size; i += 1) value = value * 256 + input[offset + i];\n offset += size;\n return value;\n };\n if (readHead(4) !== 5) throw new Error('Keystone USB reply part is not a fountain part');\n const seqNum = readHead(0);\n const seqLength = readHead(0);\n const messageLength = readHead(0);\n readHead(0); // checksum\n const fragmentLength = readHead(2);\n return { seqNum, seqLength, messageLength, fragmentLength };\n}\n\n/** Checks one UR part from the device before the vendor decoder parses its CBOR. */\nfunction assertBoundedUrPart(part: string): void {\n const match = /^ur:[a-z0-9-]+\\/(?:(\\d{1,9})-(\\d{1,9})\\/)?([a-z]+)$/i.exec(part);\n if (!match) throw new Error('Keystone USB reply part is not a UR');\n // Minimal bytewords carry their own CRC32; decode throws on a mismatch.\n const payload = Buffer.from(\n bytewords.decode(match[3].toLowerCase(), bytewords.STYLES.MINIMAL),\n 'hex'\n );\n assertBoundedCbor(payload, MAX_UR_MESSAGE_BYTES);\n if (match[1] === undefined) return;\n const header = readFountainPart(payload);\n // The text header, the CBOR header and the real sizes must agree, so the declared part count\n // is tied to the data the reply actually carries. USB is lossless and Keystone answers with a\n // single-part UR, so a mixed fountain part (seqNum past seqLen) is refused: decoding each one\n // costs time quadratic in the part count.\n if (\n header.seqNum < 1 ||\n header.seqNum > header.seqLength ||\n header.seqNum !== Number(match[1]) ||\n header.seqLength !== Number(match[2]) ||\n header.fragmentLength < 1 ||\n header.messageLength < 1 ||\n header.messageLength > MAX_UR_MESSAGE_BYTES ||\n header.seqLength > MAX_UR_SEQ_LENGTH ||\n header.seqLength !== Math.ceil(header.messageLength / header.fragmentLength)\n ) {\n throw new Error('Keystone USB reply part has inconsistent or oversized headers');\n }\n}\n\nfunction fromUrEncoded(encoded: unknown): KeystoneUr {\n // One complete UR or whitespace-separated parts; EAPDU framing is the transport's job.\n const text = typeof encoded === 'string' ? encoded.trim() : '';\n const parts = text.split(/\\s+/).filter(Boolean);\n const decoder = new URDecoder();\n try {\n if (parts.length > MAX_UR_SEQ_LENGTH) throw new Error('Keystone USB reply has too many parts');\n for (const part of parts) {\n assertBoundedUrPart(part);\n decoder.receivePart(part);\n if (decoder.isComplete()) break;\n }\n } catch {\n // A part that does not decode is the device's reply, not a broken link: report it below as\n // an unreadable answer so the session is kept rather than re-claimed.\n }\n if (!parts.length || !decoder.isComplete() || !decoder.isSuccess()) {\n const shape =\n typeof encoded === 'string'\n ? `string len=${text.length} parts=${parts.length}`\n : typeof encoded;\n throw createHwkError({\n code: HardwareErrorCode.PayloadTooLarge,\n message: `Keystone USB returned an incomplete BC-UR response (${shape})`,\n origin: 'device',\n // The device processed the request; only its reply is unusable.\n params: { replyUnreadable: true },\n });\n }\n const ur = decoder.resultUR();\n return { urType: ur.type, urData: ur.cbor.toString('hex') };\n}\n\n/**\n * Keystone USB `IConnector`. Each transport call is its own open/claim/transfer/close cycle, so\n * `connect()` only caches the transport object.\n */\nexport class KeystoneUsbConnectorBase implements IConnector {\n readonly connectionType = 'usb' as const;\n\n private readonly transportClass: KeystoneUsbTransportStatic;\n\n private readonly timeoutMs: number;\n\n private readonly emitter = new TypedEventEmitter<ConnectorEventMap>();\n\n private readonly sessions = new Map<string, UsbSession>();\n\n private readonly discoveredDevices = new Map<string, KeystoneUsbDeviceDescriptor>();\n\n private readonly availabilityDevices = new Map<string, KeystoneUsbDeviceDescriptor>();\n\n private activeDiscoveryGeneration: symbol | undefined;\n\n private activeAvailabilityGeneration: symbol | undefined;\n\n /**\n * Wallets (by mfp) that approved a public-data export. Connector-scoped because the device can\n * re-enumerate between exports, and that must not re-prompt.\n */\n private readonly publicDataConfirmedWallets = new Set<string>();\n\n constructor(transportClass: KeystoneUsbTransportStatic, options?: { timeoutMs?: number }) {\n this.transportClass = transportClass;\n this.timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n }\n\n private _invalidateDiscoverySnapshot(): void {\n this.activeDiscoveryGeneration = undefined;\n this.discoveredDevices.clear();\n }\n\n private _invalidateAvailabilitySnapshot(): void {\n this.activeAvailabilityGeneration = undefined;\n this.availabilityDevices.clear();\n }\n\n async searchDevices(options?: ConnectorSearchDevicesOptions): Promise<ConnectorDevice[]> {\n const isAvailabilitySearch = options?.purpose === 'availability';\n const discoveryGeneration = Symbol(\n isAvailabilitySearch ? 'keystone-usb-availability' : 'keystone-usb-discovery'\n );\n if (isAvailabilitySearch) {\n this._invalidateAvailabilitySnapshot();\n this.activeAvailabilityGeneration = discoveryGeneration;\n } else {\n this._invalidateDiscoverySnapshot();\n this.activeDiscoveryGeneration = discoveryGeneration;\n }\n // Enumeration DOMException codes collide with the HWK range, so map them too.\n let devices: ReadonlyArray<KeystoneUsbDeviceDescriptor>;\n try {\n devices = await this.transportClass.getKeystoneDevices();\n } catch (err) {\n throw mapKeystoneUsbError(err);\n }\n // Without an mfp before opening, the target id names only this snapshot; platforms that\n // cannot reopen a cached descriptor fail closed on multi-device selection.\n if (\n (isAvailabilitySearch\n ? this.activeAvailabilityGeneration\n : this.activeDiscoveryGeneration) !== discoveryGeneration\n ) {\n return [];\n }\n return devices.map(device => {\n const connectId = createHardwareSearchTargetId('keystone');\n (isAvailabilitySearch ? this.availabilityDevices : this.discoveredDevices).set(\n connectId,\n device\n );\n return {\n connectId,\n deviceId: '',\n name: usbDisplayName(device),\n connectionType: 'usb',\n serialNumber: device.serialNumber,\n capabilities: { persistentDeviceIdentity: false },\n // Verbatim descriptor fields; a missing key means the device did not publish it.\n raw: {\n serialNumber: device.serialNumber,\n productName: device.productName,\n manufacturerName: device.manufacturerName,\n vendorId: device.vendorId,\n productId: device.productId,\n deviceVersionMajor: device.deviceVersionMajor,\n deviceVersionMinor: device.deviceVersionMinor,\n deviceVersionSubminor: device.deviceVersionSubminor,\n usbVersionMajor: device.usbVersionMajor,\n usbVersionMinor: device.usbVersionMinor,\n usbVersionSubminor: device.usbVersionSubminor,\n deviceClass: device.deviceClass,\n deviceSubclass: device.deviceSubclass,\n deviceProtocol: device.deviceProtocol,\n },\n };\n });\n }\n\n async connect(searchTargetIdOrExpectedMasterFingerprint?: string): Promise<ConnectorSession> {\n return this._connectResolved(\n this._resolveConnectInput(searchTargetIdOrExpectedMasterFingerprint)\n );\n }\n\n async connectTarget(target: ConnectorConnectTarget): Promise<ConnectorSession> {\n switch (target.type) {\n case 'default':\n return this._connectResolved({});\n case 'search-target':\n return this._connectResolved({ searchTargetId: target.searchTargetId });\n case 'expected-device-identity': {\n const expectedMasterFingerprint = parseBip32MasterFingerprint(target.deviceIdentity);\n if (!expectedMasterFingerprint) {\n throw createHwkError({\n code: HardwareErrorCode.InvalidParams,\n message: 'Keystone USB connector requires a valid master fingerprint identity',\n });\n }\n return this._connectResolved({ expectedMasterFingerprint });\n }\n default:\n throw createHwkError({\n code: HardwareErrorCode.InvalidParams,\n message: 'Unsupported Keystone USB connection target',\n });\n }\n }\n\n private async _connectResolved({\n searchTargetId,\n expectedMasterFingerprint,\n }: KeystoneUsbConnectInput): Promise<ConnectorSession> {\n this.emitter.emit('ui-event', {\n type: EConnectorInteraction.Searching,\n payload: { sessionId: '' },\n });\n let selectedDevice = searchTargetId\n ? this.discoveredDevices.get(searchTargetId) ?? this.availabilityDevices.get(searchTargetId)\n : undefined;\n if (searchTargetId && !selectedDevice) {\n throw createHwkError({\n code: HardwareErrorCode.DeviceNotFound,\n message: `Keystone USB search target is not in the current scan: ${searchTargetId}`,\n recovery: { scope: 'search-target' },\n });\n }\n let openedTransport: OpenedUsbTransport | undefined;\n try {\n let config: AppConfig;\n\n if (expectedMasterFingerprint && !searchTargetId) {\n const availableDevices = await this.transportClass.getKeystoneDevices();\n if (!this.transportClass.connectDevice && availableDevices.length > 1) {\n throw createHwkError({\n code: HardwareErrorCode.DeviceOneDeviceOnly,\n message: 'This platform cannot identify one of multiple connected Keystone devices',\n });\n }\n\n if (this.transportClass.connectDevice) {\n if (availableDevices.length === 0) {\n throw createHwkError({\n code: HardwareErrorCode.DeviceNotFound,\n message: 'No Keystone USB device is available',\n });\n }\n let readableDeviceFound = false;\n let ambiguous = false;\n let lastError: unknown;\n let matched:\n | {\n device: KeystoneUsbDeviceDescriptor;\n opened: OpenedUsbTransport;\n config: AppConfig;\n }\n | undefined;\n for (const device of availableDevices) {\n let candidate: OpenedUsbTransport | undefined;\n try {\n // eslint-disable-next-line no-await-in-loop\n candidate = await this._openTransport(device);\n // eslint-disable-next-line no-await-in-loop\n const candidateConfig = await this._readAppConfig(candidate.transport);\n readableDeviceFound = true;\n if (candidateConfig.mfp?.toLowerCase() === expectedMasterFingerprint.toLowerCase()) {\n if (matched) {\n candidate.dispose();\n ambiguous = true;\n break;\n }\n matched = { device, opened: candidate, config: candidateConfig };\n // eslint-disable-next-line no-continue\n continue;\n }\n candidate.dispose();\n } catch (error) {\n candidate?.dispose();\n lastError = error;\n }\n }\n // The fingerprint is self-reported, so two claimants are refused, not ranked.\n if (ambiguous) {\n matched?.opened.dispose();\n throw createHwkError({\n code: HardwareErrorCode.DeviceOneDeviceOnly,\n message: 'More than one connected Keystone reports this wallet; keep one connected',\n });\n }\n if (!matched) {\n if (!readableDeviceFound && lastError) throw mapKeystoneUsbError(lastError);\n throw createHwkError({\n code: HardwareErrorCode.DeviceMismatch,\n message: 'No connected Keystone matches the requested wallet',\n });\n }\n selectedDevice = matched.device;\n openedTransport = matched.opened;\n config = matched.config;\n } else {\n openedTransport = await this._openTransport();\n config = await this._readAppConfig(openedTransport.transport);\n }\n } else {\n if (!selectedDevice && this.transportClass.connectDevice) {\n const availableDevices = await this.transportClass.getKeystoneDevices();\n if (availableDevices.length === 0) {\n throw createHwkError({\n code: HardwareErrorCode.DeviceNotFound,\n message: 'No Keystone USB device is available',\n });\n }\n if (availableDevices.length > 1) {\n throw createHwkError({\n code: HardwareErrorCode.DeviceOneDeviceOnly,\n message: 'Select a Keystone USB device before connecting',\n });\n }\n [selectedDevice] = availableDevices;\n }\n if (selectedDevice && !this.transportClass.connectDevice) {\n const availableDevices = await this.transportClass.getKeystoneDevices();\n if (availableDevices.length > 1) {\n throw createHwkError({\n code: HardwareErrorCode.DeviceOneDeviceOnly,\n message: 'This platform cannot target one of multiple connected Keystone devices',\n });\n }\n }\n openedTransport = await this._openTransport(selectedDevice);\n config = await this._readAppConfig(openedTransport.transport);\n }\n\n const activeOpenedTransport = openedTransport;\n const { transport } = activeOpenedTransport;\n if (\n expectedMasterFingerprint &&\n config.mfp &&\n config.mfp.toLowerCase() !== expectedMasterFingerprint.toLowerCase()\n ) {\n throw createHwkError({\n code: HardwareErrorCode.DeviceMismatch,\n // The master fingerprint identifies the wallet; keep it out of messages that reach logs.\n message: 'Connected Keystone wallet does not match the requested wallet',\n });\n }\n const sessionId = createHardwareLinkId('keystone');\n activeOpenedTransport.bindSessionId(sessionId);\n this.sessions.set(sessionId, {\n transport,\n mfp: config.mfp,\n dispose: () => activeOpenedTransport.dispose(),\n });\n openedTransport = undefined;\n const device: ConnectorDevice = {\n connectId: sessionId,\n deviceId: '',\n name: selectedDevice ? usbDisplayName(selectedDevice) : 'Keystone',\n model: selectedDevice?.productName,\n connectionType: 'usb',\n serialNumber: selectedDevice?.serialNumber,\n capabilities: { persistentDeviceIdentity: false },\n raw: { masterFingerprint: config.mfp },\n };\n this.emitter.emit('device-connect', { device });\n return {\n sessionId,\n deviceInfo: this._toDeviceInfo(device, config.version, config.mfp),\n };\n } catch (err) {\n openedTransport?.dispose();\n throw mapKeystoneUsbError(err);\n }\n }\n\n private async _openTransport(device?: KeystoneUsbDeviceDescriptor): Promise<OpenedUsbTransport> {\n // A rejected candidate may keep its disconnect listener; a per-descriptor\n // holder stops it from retiring a later matched session.\n let connectedSessionId: string | undefined;\n const transportConfig: TransportConfig = {\n timeout: this.timeoutMs,\n disconnectListener: () =>\n connectedSessionId ? this.disconnect(connectedSessionId) : undefined,\n };\n const transport = await (device && this.transportClass.connectDevice\n ? this.transportClass.connectDevice(device, transportConfig)\n : this.transportClass.connect(transportConfig));\n let disposed = false;\n return {\n transport,\n bindSessionId(sessionId: string) {\n connectedSessionId = sessionId;\n },\n dispose: () => {\n if (disposed) return;\n disposed = true;\n this.transportClass.disposeTransport?.(transport);\n },\n };\n }\n\n private _resolveConnectInput(value?: string): KeystoneUsbConnectInput {\n if (!value) return {};\n\n const runtimeId = parseHardwareRuntimeId(value);\n if (runtimeId) {\n // Ownership is settled by the snapshot lookup in `_connectResolved`.\n if (runtimeId.kind === 'search-target' && runtimeId.vendor === 'keystone') {\n return { searchTargetId: value };\n }\n throw createHwkError({\n code: HardwareErrorCode.InvalidParams,\n message: 'Keystone USB connector received an incompatible hardware runtime id',\n params: { kind: runtimeId.kind, vendor: runtimeId.vendor },\n });\n }\n\n if (hasHardwareRuntimeIdPrefix(value)) {\n throw createHwkError({\n code: HardwareErrorCode.InvalidParams,\n message: 'Keystone USB connector received a malformed hardware runtime id',\n });\n }\n\n const expectedMasterFingerprint = parseBip32MasterFingerprint(value);\n if (!expectedMasterFingerprint) {\n throw createHwkError({\n code: HardwareErrorCode.InvalidParams,\n message: 'Keystone USB connector requires a search target or master fingerprint',\n });\n }\n return { expectedMasterFingerprint };\n }\n\n disconnect(sessionId: string): Promise<void> {\n const session = this.sessions.get(sessionId);\n this.sessions.delete(sessionId);\n if (session) {\n session.dispose();\n // No persistent claim to release; each send() already closed the device.\n this.emitter.emit('device-disconnect', { connectId: sessionId });\n }\n return Promise.resolve();\n }\n\n /** Keep the vendor transport as the EAPDU framing authority. */\n private async _sendResolveUr(transport: TransportHID, encodedUr: string): Promise<KeystoneUr> {\n const response = await transport.send<{ payload: string }>(Actions.CMD_RESOLVE_UR, encodedUr);\n return fromUrEncoded(response.payload);\n }\n\n async call(sessionId: string, method: string, params: unknown): Promise<ConnectorCallResult> {\n const session = this.sessions.get(sessionId);\n if (!session) {\n return {\n success: false,\n error: serializeConnectorError(\n createHwkError({\n code: HardwareErrorCode.DeviceNotFound,\n message: `Unknown Keystone USB session: ${sessionId}`,\n })\n ),\n };\n }\n\n try {\n switch (method) {\n case 'resolveUr': {\n const { urType, urData } = params as KeystoneUr;\n const encoded = toUrEncoded({ urType, urData });\n const isPublicDataRequest = urType === KEYSTONE_PUBLIC_DATA_UR_TYPE;\n // Public-data export prompts once per wallet; signing always prompts. A signing request\n // leaves the device's export screen, so the next export may ask again and prompts again.\n const publicDataKey = session.mfp?.toLowerCase() ?? sessionId;\n if (!isPublicDataRequest) this.publicDataConfirmedWallets.delete(publicDataKey);\n const shouldShowConfirmation =\n !isPublicDataRequest || !this.publicDataConfirmedWallets.has(publicDataKey);\n if (shouldShowConfirmation) {\n this.emitter.emit('ui-event', {\n type: EConnectorInteraction.ConfirmOnDevice,\n payload: { sessionId },\n });\n }\n try {\n const response = await this._sendResolveUr(session.transport, encoded);\n if (isPublicDataRequest) {\n this.publicDataConfirmedWallets.add(publicDataKey);\n }\n return success(response);\n } finally {\n if (shouldShowConfirmation) {\n this.emitter.emit('ui-event', {\n type: EConnectorInteraction.InteractionComplete,\n payload: { sessionId },\n });\n }\n }\n }\n case 'checkLockStatus': {\n const response = await session.transport.send<{ payload: boolean }>(\n Actions.CMD_CHECK_LOCK_STATUS,\n ''\n );\n // `true` = locked is inferred from the SDK method name only; unverified on hardware.\n // Only a real boolean true counts, so a malformed reply never reads as a lock state.\n return success({ locked: response.payload === true });\n }\n case 'getAppConfig':\n return success(await this._readAppConfig(session.transport));\n default:\n return {\n success: false,\n error: serializeConnectorError(\n createHwkError({\n code: HardwareErrorCode.MethodNotSupported,\n message: `Unknown Keystone USB connector method: ${method}`,\n })\n ),\n };\n }\n } catch (err) {\n return { success: false, error: serializeConnectorError(mapKeystoneUsbError(err)) };\n }\n }\n\n // The SDK cannot interrupt an in-flight transfer; the pending send() settles or\n // times out on its own.\n cancel(_sessionId: string): Promise<void> {\n return Promise.resolve();\n }\n\n // PIN/passphrase entry happens on the device touchscreen, never via the host.\n uiResponse(_response: UiResponseEvent): void {}\n\n on<K extends ConnectorEventType>(event: K, handler: (data: ConnectorEventMap[K]) => void): void {\n this.emitter.on(event, handler);\n }\n\n off<K extends ConnectorEventType>(event: K, handler: (data: ConnectorEventMap[K]) => void): void {\n this.emitter.off(event, handler);\n }\n\n reset(): void {\n for (const session of this.sessions.values()) {\n session.dispose();\n }\n this.sessions.clear();\n this._invalidateDiscoverySnapshot();\n this._invalidateAvailabilitySnapshot();\n this.publicDataConfirmedWallets.clear();\n }\n\n private async _readAppConfig(transport: TransportHID): Promise<AppConfig> {\n const response = await transport.send<Record<string, unknown>>(\n Actions.CMD_GET_DEVICE_VERSION,\n ''\n );\n const rawMasterFingerprint = response.walletMFP;\n const masterFingerprint = parseBip32MasterFingerprint(rawMasterFingerprint);\n if (masterFingerprint === MISSING_BIP32_MASTER_FINGERPRINT) {\n throw createHwkError({\n code: HardwareErrorCode.DeviceNotInitialized,\n message: 'Keystone has no wallet yet; it reported an empty master fingerprint',\n });\n }\n if (rawMasterFingerprint !== undefined && !masterFingerprint) {\n throw createHwkError({\n code: HardwareErrorCode.DeviceMismatch,\n message:\n 'Keystone returned an invalid master fingerprint; expected exactly 4 bytes (8 hex characters)',\n });\n }\n return {\n // Device-supplied text reaches the host UI and version gates; accept only a version number.\n version:\n typeof response.firmwareVersion === 'string' &&\n /^\\d{1,4}(\\.\\d{1,4}){1,3}(-[0-9A-Za-z.]{1,20})?$/.test(response.firmwareVersion)\n ? response.firmwareVersion\n : undefined,\n mfp: masterFingerprint,\n };\n }\n\n private _toDeviceInfo(\n device: ConnectorDevice,\n firmwareVersion?: string,\n masterFingerprint?: string\n ) {\n return {\n vendor: 'keystone' as const,\n // Model is the USB `productName`; empty, not 'unknown', so the host's\n // default-name fallback wins.\n model: device.model ?? '',\n modelName: device.modelName,\n firmwareVersion: firmwareVersion ?? '0.0.0',\n deviceId: device.deviceId,\n connectId: device.connectId,\n connectionType: 'usb' as const,\n serialNumber: device.serialNumber,\n capabilities: { persistentDeviceIdentity: false },\n raw: { masterFingerprint },\n };\n }\n}\n"],"mappings":"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","names":["HardwareErrorCode","createHwkError","createHwkError","HardwareErrorCode","device"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["/home/runner/work/hardware-js-sdk/hardware-js-sdk/packages/hwk-keystone-connector-usb/dist/chunk-U76BQU3H.js","../src/errors.ts","../src/KeystoneUsbConnectorBase.ts"],"names":["HardwareErrorCode","createHwkError"],"mappings":"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","file":"/home/runner/work/hardware-js-sdk/hardware-js-sdk/packages/hwk-keystone-connector-usb/dist/chunk-U76BQU3H.js","sourcesContent":[null,"import { HardwareErrorCode, createHwkError } from '@onekeyfe/hwk-adapter-core';\nimport { Status } from '@keystonehq/hw-transport-error';\n\nimport type { HwkError, HwkErrorOrigin } from '@onekeyfe/hwk-adapter-core';\n\n/**\n * Firmware status words are the low end of `Status` (0..15); client codes start at\n * `ERR_DEVICE_NOT_OPENED` (0xA0000001), so anything below came from a device response frame.\n */\nfunction isDeviceStatus(statusCode: number): boolean {\n return statusCode >= 0 && statusCode < Status.ERR_DEVICE_NOT_OPENED;\n}\n\n/** Firmware status words from a device response (EAPDU_Readme.md in the Keystone USB SDK). */\nconst DEVICE_STATUS_MAP: Partial<Record<number, HardwareErrorCode>> = {\n [Status.RSP_FAILURE_CODE]: HardwareErrorCode.UnknownError,\n [Status.PRS_INVALID_TOTAL_PACKETS]: HardwareErrorCode.InvalidParams,\n [Status.PRS_INVALID_INDEX]: HardwareErrorCode.InvalidParams,\n [Status.PRS_PARSING_REJECTED]: HardwareErrorCode.UserRejected,\n [Status.PRS_PARSING_ERROR]: HardwareErrorCode.InvalidParams,\n [Status.PRS_PARSING_DISALLOWED]: HardwareErrorCode.DeviceLocked,\n [Status.PRS_PARSING_UNMATCHED]: HardwareErrorCode.InvalidParams,\n [Status.PRS_PARSING_MISMATCHED_WALLET]: HardwareErrorCode.DeviceMismatch,\n [Status.PRS_PARSING_VERIFY_PASSWORD_ERROR]: HardwareErrorCode.PinInvalid,\n [Status.PRS_EXPORT_ADDRESS_UNSUPPORTED_CHAIN]: HardwareErrorCode.ChainNotSupported,\n [Status.PRS_EXPORT_ADDRESS_INVALID_PARAMS]: HardwareErrorCode.InvalidParams,\n [Status.PRS_EXPORT_ADDRESS_ERROR]: HardwareErrorCode.UnknownError,\n [Status.PRS_EXPORT_ADDRESS_DISALLOWED]: HardwareErrorCode.DeviceLocked,\n [Status.PRS_EXPORT_ADDRESS_REJECTED]: HardwareErrorCode.UserRejected,\n [Status.PRS_EXPORT_ADDRESS_BUSY]: HardwareErrorCode.DeviceBusyInternal,\n};\n\n/** Used when the transport forwarded only its 'unknown error' placeholder for a firmware status. */\nconst DEVICE_STATUS_MESSAGE: Partial<Record<number, string>> = {\n [Status.RSP_FAILURE_CODE]: 'Keystone reported a failure',\n [Status.PRS_INVALID_TOTAL_PACKETS]: 'Keystone rejected the request framing (total packets)',\n [Status.PRS_INVALID_INDEX]: 'Keystone rejected the request framing (packet index)',\n [Status.PRS_PARSING_REJECTED]: 'Rejected on the Keystone screen',\n [Status.PRS_PARSING_ERROR]: 'Keystone could not parse the request',\n [Status.PRS_PARSING_DISALLOWED]: 'Keystone declined the request in its current state',\n [Status.PRS_PARSING_UNMATCHED]: 'Keystone found no handler for the request',\n [Status.PRS_PARSING_MISMATCHED_WALLET]: 'The request belongs to a different Keystone wallet',\n [Status.PRS_PARSING_VERIFY_PASSWORD_ERROR]: 'Keystone password verification failed',\n [Status.PRS_EXPORT_ADDRESS_UNSUPPORTED_CHAIN]: 'Keystone does not support this chain',\n [Status.PRS_EXPORT_ADDRESS_INVALID_PARAMS]: 'Keystone rejected the address export parameters',\n [Status.PRS_EXPORT_ADDRESS_ERROR]: 'Keystone failed to export the address',\n [Status.PRS_EXPORT_ADDRESS_DISALLOWED]: 'Keystone declined to export the address',\n [Status.PRS_EXPORT_ADDRESS_REJECTED]: 'Address export rejected on the Keystone screen',\n [Status.PRS_EXPORT_ADDRESS_BUSY]: 'Keystone is busy with another request',\n};\n\n/** The placeholder both Keystone transports use when they have nothing better. */\nconst PLACEHOLDER_MESSAGE = /^unknown error\\b/i;\n\n/** Client-side (transport/framing) failures, never reached the device. */\nconst CLIENT_STATUS_MAP: Partial<Record<number, HardwareErrorCode>> = {\n [Status.ERR_DEVICE_NOT_OPENED]: HardwareErrorCode.DeviceNotFound,\n [Status.ERR_DEVICE_NOT_FOUND]: HardwareErrorCode.DeviceNotFound,\n [Status.ERR_TIMEOUT]: HardwareErrorCode.OperationTimeout,\n [Status.ERR_DATA_TOO_LARGE]: HardwareErrorCode.PayloadTooLarge,\n [Status.ERR_NOT_SUPPORTED]: HardwareErrorCode.TransportNotAvailable,\n};\n\n/** WebUSB DOMExceptions; an unplug or bus reset mid-call is the common case. */\nconst DOM_EXCEPTION_MAP = new Map<string, { code: HardwareErrorCode; origin: HwkErrorOrigin }>([\n ['NotFoundError', { code: HardwareErrorCode.DeviceNotFound, origin: 'transport' }],\n ['NetworkError', { code: HardwareErrorCode.DeviceNotFound, origin: 'transport' }],\n ['SecurityError', { code: HardwareErrorCode.DevicePermissionDenied, origin: 'host' }],\n ['NotAllowedError', { code: HardwareErrorCode.DevicePermissionDenied, origin: 'host' }],\n ['InvalidStateError', { code: HardwareErrorCode.DeviceBusy, origin: 'transport' }],\n ['AbortError', { code: HardwareErrorCode.DeviceBusy, origin: 'transport' }],\n]);\n\n/**\n * Maps a Keystone USB SDK failure to `HardwareErrorCode`. Fields are read duck-typed because\n * duplicate `@keystonehq/*` module instances break `instanceof`.\n */\nexport function mapKeystoneUsbError(err: unknown): HwkError {\n const fields: { name?: unknown; code?: unknown; transportErrorCode?: unknown } =\n err && typeof err === 'object' ? err : {};\n const domName = typeof fields.name === 'string' ? fields.name : undefined;\n\n // Only five-digit codes are HWK codes; legacy DOMException codes (NotFoundError\n // is 8) must not pass through as hardware errors.\n if (typeof fields.code === 'number' && fields.code >= 10000 && fields.code <= 99999) {\n return err as HwkError;\n }\n\n const statusCode =\n typeof fields.transportErrorCode === 'number' ? fields.transportErrorCode : undefined;\n\n const message = err instanceof Error ? err.message : String(err);\n\n if (statusCode !== undefined) {\n const fromDevice = isDeviceStatus(statusCode);\n // An unlisted firmware status keeps origin 'device'; 'transport' would make the\n // adapter tear down a live session over an on-device decline.\n let code = fromDevice\n ? DEVICE_STATUS_MAP[statusCode] ?? HardwareErrorCode.UnknownError\n : CLIENT_STATUS_MAP[statusCode] ?? HardwareErrorCode.TransportError;\n // Firmware also returns PRS_PARSING_DISALLOWED for an unfinished request, a pending approval\n // and a screen that takes no requests; only its \"Device is locked\" text means locked.\n if (statusCode === Status.PRS_PARSING_DISALLOWED && !/\\blocked\\b/i.test(message)) {\n code = HardwareErrorCode.DeviceBusy;\n }\n let origin: HwkErrorOrigin | undefined;\n if (fromDevice) {\n origin = 'device';\n } else if (code !== HardwareErrorCode.OperationTimeout) {\n origin = 'transport';\n }\n const description = DEVICE_STATUS_MESSAGE[statusCode];\n return createHwkError({\n code,\n // The device's own payload text wins over the table.\n message:\n description && PLACEHOLDER_MESSAGE.test(message)\n ? `${description} (error_code: ${statusCode})`\n : message,\n // A timeout may be either side, so it stays unlabeled.\n origin,\n params: { statusCode, details: (err as { details?: string }).details },\n });\n }\n\n const domMapping = domName ? DOM_EXCEPTION_MAP.get(domName) : undefined;\n if (domMapping) {\n return createHwkError({ ...domMapping, message, params: { domExceptionName: domName } });\n }\n\n // This mapper only wraps transport calls, so 'transport' names the throw site.\n return createHwkError({ code: HardwareErrorCode.TransportError, message, origin: 'transport' });\n}\n","import { UR, URDecoder, UREncoder } from '@ngraveio/bc-ur';\n// Not re-exported by the package root; pinned with the package version.\nimport bytewords from '@ngraveio/bc-ur/dist/bytewords';\nimport { Actions } from '@keystonehq/hw-transport-usb';\nimport {\n EConnectorInteraction,\n HardwareErrorCode,\n MISSING_BIP32_MASTER_FINGERPRINT,\n TypedEventEmitter,\n assertBoundedCbor,\n createHardwareLinkId,\n createHardwareSearchTargetId,\n createHwkError,\n hasHardwareRuntimeIdPrefix,\n parseBip32MasterFingerprint,\n parseHardwareRuntimeId,\n serializeConnectorError,\n success,\n} from '@onekeyfe/hwk-adapter-core';\n\nimport { mapKeystoneUsbError } from './errors';\n\nimport type {\n ConnectorCallResult,\n ConnectorConnectTarget,\n ConnectorDevice,\n ConnectorEventMap,\n ConnectorEventType,\n ConnectorSearchDevicesOptions,\n ConnectorSession,\n IConnector,\n UiResponseEvent,\n} from '@onekeyfe/hwk-adapter-core';\nimport type { TransportConfig, TransportHID } from '@keystonehq/hw-transport-usb';\n\n/** Descriptor fields readable before opening; any may be absent if not published. */\nexport interface KeystoneUsbDeviceDescriptor {\n serialNumber?: string;\n productName?: string;\n manufacturerName?: string;\n vendorId?: number;\n productId?: number;\n /** Device release number (bcdDevice), split into its three nibble groups. */\n deviceVersionMajor?: number;\n deviceVersionMinor?: number;\n deviceVersionSubminor?: number;\n usbVersionMajor?: number;\n usbVersionMinor?: number;\n usbVersionSubminor?: number;\n deviceClass?: number;\n deviceSubclass?: number;\n deviceProtocol?: number;\n}\n\n/** The serial is not shown on the unit, so it would not help tell two devices apart. */\nfunction usbDisplayName(device: KeystoneUsbDeviceDescriptor): string {\n return device.productName?.trim() || 'Keystone';\n}\n\n/** Static surface of `TransportWebUSB`, injected by `_subpath/webusb`. */\nexport interface KeystoneUsbTransportStatic {\n connect(config?: TransportConfig): Promise<TransportHID>;\n connectDevice?(\n device: KeystoneUsbDeviceDescriptor,\n config?: TransportConfig\n ): Promise<TransportHID>;\n getKeystoneDevices(): Promise<ReadonlyArray<KeystoneUsbDeviceDescriptor>>;\n requestPermission?(): Promise<void>;\n isSupported(): Promise<boolean>;\n /** Release transport-lifetime resources owned by the platform wrapper. */\n disposeTransport?(transport: TransportHID): void;\n}\n\ninterface KeystoneUr {\n urType: string;\n urData: string;\n}\n\ninterface UsbSession {\n transport: TransportHID;\n mfp?: string;\n dispose(): void;\n}\n\ninterface AppConfig {\n version?: string;\n mfp?: string;\n}\n\ninterface OpenedUsbTransport {\n transport: TransportHID;\n bindSessionId(sessionId: string): void;\n dispose(): void;\n}\n\ntype KeystoneUsbConnectInput =\n | { searchTargetId: string; expectedMasterFingerprint?: never }\n | { searchTargetId?: never; expectedMasterFingerprint: string }\n | { searchTargetId?: never; expectedMasterFingerprint?: never };\n\n// The SDK default of 15s is too short for on-device confirmation.\nconst DEFAULT_TIMEOUT_MS = 100_000;\n\nconst KEYSTONE_PUBLIC_DATA_UR_TYPE = 'qr-hardware-call';\n\nfunction toUrEncoded(ur: KeystoneUr): string {\n return new UREncoder(new UR(Buffer.from(ur.urData, 'hex'), ur.urType), Infinity)\n .nextPart()\n .toUpperCase();\n}\n\n/** The most data one reply may carry, whatever its fragment size. */\nconst MAX_UR_MESSAGE_BYTES = 1024 * 1024;\n/**\n * The fountain decoder's work per mixed part grows with the square of the part count, so a reply\n * cut into tiny fragments can stall it even within the byte limit.\n */\nconst MAX_UR_SEQ_LENGTH = 32_768;\n/** Argument bytes for CBOR additional info 24, 25, 26 and 27. */\nconst CBOR_ARGUMENT_BYTES = [1, 2, 4, 8];\n\n/** Reads `[seqNum, seqLen, messageLen, checksum, fragment]` from CBOR that passed the bounds. */\nfunction readFountainPart(input: Uint8Array) {\n let offset = 0;\n const readHead = (expectedMajor: number): number => {\n const initial = input[offset];\n offset += 1;\n if (Math.floor(initial / 32) !== expectedMajor) {\n throw new Error('Keystone USB reply part is not a fountain part');\n }\n const info = initial % 32;\n if (info < 24) return info;\n const size = CBOR_ARGUMENT_BYTES[info - 24];\n let value = 0;\n for (let i = 0; i < size; i += 1) value = value * 256 + input[offset + i];\n offset += size;\n return value;\n };\n if (readHead(4) !== 5) throw new Error('Keystone USB reply part is not a fountain part');\n const seqNum = readHead(0);\n const seqLength = readHead(0);\n const messageLength = readHead(0);\n readHead(0); // checksum\n const fragmentLength = readHead(2);\n return { seqNum, seqLength, messageLength, fragmentLength };\n}\n\n/** Checks one UR part from the device before the vendor decoder parses its CBOR. */\nfunction assertBoundedUrPart(part: string): void {\n const match = /^ur:[a-z0-9-]+\\/(?:(\\d{1,9})-(\\d{1,9})\\/)?([a-z]+)$/i.exec(part);\n if (!match) throw new Error('Keystone USB reply part is not a UR');\n // Minimal bytewords carry their own CRC32; decode throws on a mismatch.\n const payload = Buffer.from(\n bytewords.decode(match[3].toLowerCase(), bytewords.STYLES.MINIMAL),\n 'hex'\n );\n assertBoundedCbor(payload, MAX_UR_MESSAGE_BYTES);\n if (match[1] === undefined) return;\n const header = readFountainPart(payload);\n // The text header, the CBOR header and the real sizes must agree, so the declared part count\n // is tied to the data the reply actually carries. USB is lossless and Keystone answers with a\n // single-part UR, so a mixed fountain part (seqNum past seqLen) is refused: decoding each one\n // costs time quadratic in the part count.\n if (\n header.seqNum < 1 ||\n header.seqNum > header.seqLength ||\n header.seqNum !== Number(match[1]) ||\n header.seqLength !== Number(match[2]) ||\n header.fragmentLength < 1 ||\n header.messageLength < 1 ||\n header.messageLength > MAX_UR_MESSAGE_BYTES ||\n header.seqLength > MAX_UR_SEQ_LENGTH ||\n header.seqLength !== Math.ceil(header.messageLength / header.fragmentLength)\n ) {\n throw new Error('Keystone USB reply part has inconsistent or oversized headers');\n }\n}\n\nfunction fromUrEncoded(encoded: unknown): KeystoneUr {\n // One complete UR or whitespace-separated parts; EAPDU framing is the transport's job.\n const text = typeof encoded === 'string' ? encoded.trim() : '';\n const parts = text.split(/\\s+/).filter(Boolean);\n const decoder = new URDecoder();\n try {\n if (parts.length > MAX_UR_SEQ_LENGTH) throw new Error('Keystone USB reply has too many parts');\n for (const part of parts) {\n assertBoundedUrPart(part);\n decoder.receivePart(part);\n if (decoder.isComplete()) break;\n }\n } catch {\n // A part that does not decode is the device's reply, not a broken link: report it below as\n // an unreadable answer so the session is kept rather than re-claimed.\n }\n if (!parts.length || !decoder.isComplete() || !decoder.isSuccess()) {\n const shape =\n typeof encoded === 'string'\n ? `string len=${text.length} parts=${parts.length}`\n : typeof encoded;\n throw createHwkError({\n code: HardwareErrorCode.PayloadTooLarge,\n message: `Keystone USB returned an incomplete BC-UR response (${shape})`,\n origin: 'device',\n // The device processed the request; only its reply is unusable.\n params: { replyUnreadable: true },\n });\n }\n const ur = decoder.resultUR();\n return { urType: ur.type, urData: ur.cbor.toString('hex') };\n}\n\n/**\n * Keystone USB `IConnector`. Each transport call is its own open/claim/transfer/close cycle, so\n * `connect()` only caches the transport object.\n */\nexport class KeystoneUsbConnectorBase implements IConnector {\n readonly connectionType = 'usb' as const;\n\n private readonly transportClass: KeystoneUsbTransportStatic;\n\n private readonly timeoutMs: number;\n\n private readonly emitter = new TypedEventEmitter<ConnectorEventMap>();\n\n private readonly sessions = new Map<string, UsbSession>();\n\n private readonly discoveredDevices = new Map<string, KeystoneUsbDeviceDescriptor>();\n\n private readonly availabilityDevices = new Map<string, KeystoneUsbDeviceDescriptor>();\n\n private activeDiscoveryGeneration: symbol | undefined;\n\n private activeAvailabilityGeneration: symbol | undefined;\n\n /**\n * Wallets (by mfp) that approved a public-data export. Connector-scoped because the device can\n * re-enumerate between exports, and that must not re-prompt.\n */\n private readonly publicDataConfirmedWallets = new Set<string>();\n\n constructor(transportClass: KeystoneUsbTransportStatic, options?: { timeoutMs?: number }) {\n this.transportClass = transportClass;\n this.timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n }\n\n private _invalidateDiscoverySnapshot(): void {\n this.activeDiscoveryGeneration = undefined;\n this.discoveredDevices.clear();\n }\n\n private _invalidateAvailabilitySnapshot(): void {\n this.activeAvailabilityGeneration = undefined;\n this.availabilityDevices.clear();\n }\n\n async searchDevices(options?: ConnectorSearchDevicesOptions): Promise<ConnectorDevice[]> {\n const isAvailabilitySearch = options?.purpose === 'availability';\n const discoveryGeneration = Symbol(\n isAvailabilitySearch ? 'keystone-usb-availability' : 'keystone-usb-discovery'\n );\n if (isAvailabilitySearch) {\n this._invalidateAvailabilitySnapshot();\n this.activeAvailabilityGeneration = discoveryGeneration;\n } else {\n this._invalidateDiscoverySnapshot();\n this.activeDiscoveryGeneration = discoveryGeneration;\n }\n // Enumeration DOMException codes collide with the HWK range, so map them too.\n let devices: ReadonlyArray<KeystoneUsbDeviceDescriptor>;\n try {\n devices = await this.transportClass.getKeystoneDevices();\n } catch (err) {\n throw mapKeystoneUsbError(err);\n }\n // Without an mfp before opening, the target id names only this snapshot; platforms that\n // cannot reopen a cached descriptor fail closed on multi-device selection.\n if (\n (isAvailabilitySearch\n ? this.activeAvailabilityGeneration\n : this.activeDiscoveryGeneration) !== discoveryGeneration\n ) {\n return [];\n }\n return devices.map(device => {\n const connectId = createHardwareSearchTargetId('keystone');\n (isAvailabilitySearch ? this.availabilityDevices : this.discoveredDevices).set(\n connectId,\n device\n );\n return {\n connectId,\n deviceId: '',\n name: usbDisplayName(device),\n connectionType: 'usb',\n serialNumber: device.serialNumber,\n capabilities: { persistentDeviceIdentity: false },\n // Verbatim descriptor fields; a missing key means the device did not publish it.\n raw: {\n serialNumber: device.serialNumber,\n productName: device.productName,\n manufacturerName: device.manufacturerName,\n vendorId: device.vendorId,\n productId: device.productId,\n deviceVersionMajor: device.deviceVersionMajor,\n deviceVersionMinor: device.deviceVersionMinor,\n deviceVersionSubminor: device.deviceVersionSubminor,\n usbVersionMajor: device.usbVersionMajor,\n usbVersionMinor: device.usbVersionMinor,\n usbVersionSubminor: device.usbVersionSubminor,\n deviceClass: device.deviceClass,\n deviceSubclass: device.deviceSubclass,\n deviceProtocol: device.deviceProtocol,\n },\n };\n });\n }\n\n async connect(searchTargetIdOrExpectedMasterFingerprint?: string): Promise<ConnectorSession> {\n return this._connectResolved(\n this._resolveConnectInput(searchTargetIdOrExpectedMasterFingerprint)\n );\n }\n\n async connectTarget(target: ConnectorConnectTarget): Promise<ConnectorSession> {\n switch (target.type) {\n case 'default':\n return this._connectResolved({});\n case 'search-target':\n return this._connectResolved({ searchTargetId: target.searchTargetId });\n case 'expected-device-identity': {\n const expectedMasterFingerprint = parseBip32MasterFingerprint(target.deviceIdentity);\n if (!expectedMasterFingerprint) {\n throw createHwkError({\n code: HardwareErrorCode.InvalidParams,\n message: 'Keystone USB connector requires a valid master fingerprint identity',\n });\n }\n return this._connectResolved({ expectedMasterFingerprint });\n }\n default:\n throw createHwkError({\n code: HardwareErrorCode.InvalidParams,\n message: 'Unsupported Keystone USB connection target',\n });\n }\n }\n\n private async _connectResolved({\n searchTargetId,\n expectedMasterFingerprint,\n }: KeystoneUsbConnectInput): Promise<ConnectorSession> {\n this.emitter.emit('ui-event', {\n type: EConnectorInteraction.Searching,\n payload: { sessionId: '' },\n });\n let selectedDevice = searchTargetId\n ? this.discoveredDevices.get(searchTargetId) ?? this.availabilityDevices.get(searchTargetId)\n : undefined;\n if (searchTargetId && !selectedDevice) {\n throw createHwkError({\n code: HardwareErrorCode.DeviceNotFound,\n message: `Keystone USB search target is not in the current scan: ${searchTargetId}`,\n recovery: { scope: 'search-target' },\n });\n }\n let openedTransport: OpenedUsbTransport | undefined;\n try {\n let config: AppConfig;\n\n if (expectedMasterFingerprint && !searchTargetId) {\n const availableDevices = await this.transportClass.getKeystoneDevices();\n if (!this.transportClass.connectDevice && availableDevices.length > 1) {\n throw createHwkError({\n code: HardwareErrorCode.DeviceOneDeviceOnly,\n message: 'This platform cannot identify one of multiple connected Keystone devices',\n });\n }\n\n if (this.transportClass.connectDevice) {\n if (availableDevices.length === 0) {\n throw createHwkError({\n code: HardwareErrorCode.DeviceNotFound,\n message: 'No Keystone USB device is available',\n });\n }\n let readableDeviceFound = false;\n let ambiguous = false;\n let lastError: unknown;\n let matched:\n | {\n device: KeystoneUsbDeviceDescriptor;\n opened: OpenedUsbTransport;\n config: AppConfig;\n }\n | undefined;\n for (const device of availableDevices) {\n let candidate: OpenedUsbTransport | undefined;\n try {\n // eslint-disable-next-line no-await-in-loop\n candidate = await this._openTransport(device);\n // eslint-disable-next-line no-await-in-loop\n const candidateConfig = await this._readAppConfig(candidate.transport);\n readableDeviceFound = true;\n if (candidateConfig.mfp?.toLowerCase() === expectedMasterFingerprint.toLowerCase()) {\n if (matched) {\n candidate.dispose();\n ambiguous = true;\n break;\n }\n matched = { device, opened: candidate, config: candidateConfig };\n // eslint-disable-next-line no-continue\n continue;\n }\n candidate.dispose();\n } catch (error) {\n candidate?.dispose();\n lastError = error;\n }\n }\n // The fingerprint is self-reported, so two claimants are refused, not ranked.\n if (ambiguous) {\n matched?.opened.dispose();\n throw createHwkError({\n code: HardwareErrorCode.DeviceOneDeviceOnly,\n message: 'More than one connected Keystone reports this wallet; keep one connected',\n });\n }\n if (!matched) {\n if (!readableDeviceFound && lastError) throw mapKeystoneUsbError(lastError);\n throw createHwkError({\n code: HardwareErrorCode.DeviceMismatch,\n message: 'No connected Keystone matches the requested wallet',\n });\n }\n selectedDevice = matched.device;\n openedTransport = matched.opened;\n config = matched.config;\n } else {\n openedTransport = await this._openTransport();\n config = await this._readAppConfig(openedTransport.transport);\n }\n } else {\n if (!selectedDevice && this.transportClass.connectDevice) {\n const availableDevices = await this.transportClass.getKeystoneDevices();\n if (availableDevices.length === 0) {\n throw createHwkError({\n code: HardwareErrorCode.DeviceNotFound,\n message: 'No Keystone USB device is available',\n });\n }\n if (availableDevices.length > 1) {\n throw createHwkError({\n code: HardwareErrorCode.DeviceOneDeviceOnly,\n message: 'Select a Keystone USB device before connecting',\n });\n }\n [selectedDevice] = availableDevices;\n }\n if (selectedDevice && !this.transportClass.connectDevice) {\n const availableDevices = await this.transportClass.getKeystoneDevices();\n if (availableDevices.length > 1) {\n throw createHwkError({\n code: HardwareErrorCode.DeviceOneDeviceOnly,\n message: 'This platform cannot target one of multiple connected Keystone devices',\n });\n }\n }\n openedTransport = await this._openTransport(selectedDevice);\n config = await this._readAppConfig(openedTransport.transport);\n }\n\n const activeOpenedTransport = openedTransport;\n const { transport } = activeOpenedTransport;\n if (\n expectedMasterFingerprint &&\n config.mfp &&\n config.mfp.toLowerCase() !== expectedMasterFingerprint.toLowerCase()\n ) {\n throw createHwkError({\n code: HardwareErrorCode.DeviceMismatch,\n // The master fingerprint identifies the wallet; keep it out of messages that reach logs.\n message: 'Connected Keystone wallet does not match the requested wallet',\n });\n }\n const sessionId = createHardwareLinkId('keystone');\n activeOpenedTransport.bindSessionId(sessionId);\n this.sessions.set(sessionId, {\n transport,\n mfp: config.mfp,\n dispose: () => activeOpenedTransport.dispose(),\n });\n openedTransport = undefined;\n const device: ConnectorDevice = {\n connectId: sessionId,\n deviceId: '',\n name: selectedDevice ? usbDisplayName(selectedDevice) : 'Keystone',\n model: selectedDevice?.productName,\n connectionType: 'usb',\n serialNumber: selectedDevice?.serialNumber,\n capabilities: { persistentDeviceIdentity: false },\n raw: { masterFingerprint: config.mfp },\n };\n this.emitter.emit('device-connect', { device });\n return {\n sessionId,\n deviceInfo: this._toDeviceInfo(device, config.version, config.mfp),\n };\n } catch (err) {\n openedTransport?.dispose();\n throw mapKeystoneUsbError(err);\n }\n }\n\n private async _openTransport(device?: KeystoneUsbDeviceDescriptor): Promise<OpenedUsbTransport> {\n // A rejected candidate may keep its disconnect listener; a per-descriptor\n // holder stops it from retiring a later matched session.\n let connectedSessionId: string | undefined;\n const transportConfig: TransportConfig = {\n timeout: this.timeoutMs,\n disconnectListener: () =>\n connectedSessionId ? this.disconnect(connectedSessionId) : undefined,\n };\n const transport = await (device && this.transportClass.connectDevice\n ? this.transportClass.connectDevice(device, transportConfig)\n : this.transportClass.connect(transportConfig));\n let disposed = false;\n return {\n transport,\n bindSessionId(sessionId: string) {\n connectedSessionId = sessionId;\n },\n dispose: () => {\n if (disposed) return;\n disposed = true;\n this.transportClass.disposeTransport?.(transport);\n },\n };\n }\n\n private _resolveConnectInput(value?: string): KeystoneUsbConnectInput {\n if (!value) return {};\n\n const runtimeId = parseHardwareRuntimeId(value);\n if (runtimeId) {\n // Ownership is settled by the snapshot lookup in `_connectResolved`.\n if (runtimeId.kind === 'search-target' && runtimeId.vendor === 'keystone') {\n return { searchTargetId: value };\n }\n throw createHwkError({\n code: HardwareErrorCode.InvalidParams,\n message: 'Keystone USB connector received an incompatible hardware runtime id',\n params: { kind: runtimeId.kind, vendor: runtimeId.vendor },\n });\n }\n\n if (hasHardwareRuntimeIdPrefix(value)) {\n throw createHwkError({\n code: HardwareErrorCode.InvalidParams,\n message: 'Keystone USB connector received a malformed hardware runtime id',\n });\n }\n\n const expectedMasterFingerprint = parseBip32MasterFingerprint(value);\n if (!expectedMasterFingerprint) {\n throw createHwkError({\n code: HardwareErrorCode.InvalidParams,\n message: 'Keystone USB connector requires a search target or master fingerprint',\n });\n }\n return { expectedMasterFingerprint };\n }\n\n disconnect(sessionId: string): Promise<void> {\n const session = this.sessions.get(sessionId);\n this.sessions.delete(sessionId);\n if (session) {\n session.dispose();\n // No persistent claim to release; each send() already closed the device.\n this.emitter.emit('device-disconnect', { connectId: sessionId });\n }\n return Promise.resolve();\n }\n\n /** Keep the vendor transport as the EAPDU framing authority. */\n private async _sendResolveUr(transport: TransportHID, encodedUr: string): Promise<KeystoneUr> {\n const response = await transport.send<{ payload: string }>(Actions.CMD_RESOLVE_UR, encodedUr);\n return fromUrEncoded(response.payload);\n }\n\n async call(sessionId: string, method: string, params: unknown): Promise<ConnectorCallResult> {\n const session = this.sessions.get(sessionId);\n if (!session) {\n return {\n success: false,\n error: serializeConnectorError(\n createHwkError({\n code: HardwareErrorCode.DeviceNotFound,\n message: `Unknown Keystone USB session: ${sessionId}`,\n })\n ),\n };\n }\n\n try {\n switch (method) {\n case 'resolveUr': {\n const { urType, urData } = params as KeystoneUr;\n const encoded = toUrEncoded({ urType, urData });\n const isPublicDataRequest = urType === KEYSTONE_PUBLIC_DATA_UR_TYPE;\n // Public-data export prompts once per wallet; signing always prompts. A signing request\n // leaves the device's export screen, so the next export may ask again and prompts again.\n const publicDataKey = session.mfp?.toLowerCase() ?? sessionId;\n if (!isPublicDataRequest) this.publicDataConfirmedWallets.delete(publicDataKey);\n const shouldShowConfirmation =\n !isPublicDataRequest || !this.publicDataConfirmedWallets.has(publicDataKey);\n if (shouldShowConfirmation) {\n this.emitter.emit('ui-event', {\n type: EConnectorInteraction.ConfirmOnDevice,\n payload: { sessionId },\n });\n }\n try {\n const response = await this._sendResolveUr(session.transport, encoded);\n if (isPublicDataRequest) {\n this.publicDataConfirmedWallets.add(publicDataKey);\n }\n return success(response);\n } finally {\n if (shouldShowConfirmation) {\n this.emitter.emit('ui-event', {\n type: EConnectorInteraction.InteractionComplete,\n payload: { sessionId },\n });\n }\n }\n }\n case 'checkLockStatus': {\n const response = await session.transport.send<{ payload: boolean }>(\n Actions.CMD_CHECK_LOCK_STATUS,\n ''\n );\n // `true` = locked is inferred from the SDK method name only; unverified on hardware.\n // Only a real boolean true counts, so a malformed reply never reads as a lock state.\n return success({ locked: response.payload === true });\n }\n case 'getAppConfig':\n return success(await this._readAppConfig(session.transport));\n default:\n return {\n success: false,\n error: serializeConnectorError(\n createHwkError({\n code: HardwareErrorCode.MethodNotSupported,\n message: `Unknown Keystone USB connector method: ${method}`,\n })\n ),\n };\n }\n } catch (err) {\n return { success: false, error: serializeConnectorError(mapKeystoneUsbError(err)) };\n }\n }\n\n // The SDK cannot interrupt an in-flight transfer; the pending send() settles or\n // times out on its own.\n cancel(_sessionId: string): Promise<void> {\n return Promise.resolve();\n }\n\n // PIN/passphrase entry happens on the device touchscreen, never via the host.\n uiResponse(_response: UiResponseEvent): void {}\n\n on<K extends ConnectorEventType>(event: K, handler: (data: ConnectorEventMap[K]) => void): void {\n this.emitter.on(event, handler);\n }\n\n off<K extends ConnectorEventType>(event: K, handler: (data: ConnectorEventMap[K]) => void): void {\n this.emitter.off(event, handler);\n }\n\n reset(): void {\n for (const session of this.sessions.values()) {\n session.dispose();\n }\n this.sessions.clear();\n this._invalidateDiscoverySnapshot();\n this._invalidateAvailabilitySnapshot();\n this.publicDataConfirmedWallets.clear();\n }\n\n private async _readAppConfig(transport: TransportHID): Promise<AppConfig> {\n const response = await transport.send<Record<string, unknown>>(\n Actions.CMD_GET_DEVICE_VERSION,\n ''\n );\n const rawMasterFingerprint = response.walletMFP;\n const masterFingerprint = parseBip32MasterFingerprint(rawMasterFingerprint);\n if (masterFingerprint === MISSING_BIP32_MASTER_FINGERPRINT) {\n throw createHwkError({\n code: HardwareErrorCode.DeviceNotInitialized,\n message: 'Keystone has no wallet yet; it reported an empty master fingerprint',\n });\n }\n if (rawMasterFingerprint !== undefined && !masterFingerprint) {\n throw createHwkError({\n code: HardwareErrorCode.DeviceMismatch,\n message:\n 'Keystone returned an invalid master fingerprint; expected exactly 4 bytes (8 hex characters)',\n });\n }\n return {\n // Device-supplied text reaches the host UI and version gates; accept only a version number.\n version:\n typeof response.firmwareVersion === 'string' &&\n /^\\d{1,4}(\\.\\d{1,4}){1,3}(-[0-9A-Za-z.]{1,20})?$/.test(response.firmwareVersion)\n ? response.firmwareVersion\n : undefined,\n mfp: masterFingerprint,\n };\n }\n\n private _toDeviceInfo(\n device: ConnectorDevice,\n firmwareVersion?: string,\n masterFingerprint?: string\n ) {\n return {\n vendor: 'keystone' as const,\n // Model is the USB `productName`; empty, not 'unknown', so the host's\n // default-name fallback wins.\n model: device.model ?? '',\n modelName: device.modelName,\n firmwareVersion: firmwareVersion ?? '0.0.0',\n deviceId: device.deviceId,\n connectId: device.connectId,\n connectionType: 'usb' as const,\n serialNumber: device.serialNumber,\n capabilities: { persistentDeviceIdentity: false },\n raw: { masterFingerprint },\n };\n }\n}\n"]}