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

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.
@@ -64,7 +64,10 @@ function mapKeystoneUsbError(err) {
64
64
  const message = err instanceof Error ? err.message : String(err);
65
65
  if (statusCode !== void 0) {
66
66
  const fromDevice = isDeviceStatus(statusCode);
67
- const code = fromDevice ? DEVICE_STATUS_MAP[statusCode] ?? HardwareErrorCode.UnknownError : CLIENT_STATUS_MAP[statusCode] ?? HardwareErrorCode.TransportError;
67
+ let code = fromDevice ? DEVICE_STATUS_MAP[statusCode] ?? HardwareErrorCode.UnknownError : CLIENT_STATUS_MAP[statusCode] ?? HardwareErrorCode.TransportError;
68
+ if (statusCode === Status.PRS_PARSING_DISALLOWED && !/\blocked\b/i.test(message)) {
69
+ code = HardwareErrorCode.DeviceBusy;
70
+ }
68
71
  let origin;
69
72
  if (fromDevice) {
70
73
  origin = "device";
@@ -90,12 +93,14 @@ function mapKeystoneUsbError(err) {
90
93
 
91
94
  // src/KeystoneUsbConnectorBase.ts
92
95
  import { UR, URDecoder, UREncoder } from "@ngraveio/bc-ur";
96
+ import bytewords from "@ngraveio/bc-ur/dist/bytewords";
93
97
  import { Actions } from "@keystonehq/hw-transport-usb";
94
98
  import {
95
99
  EConnectorInteraction,
96
100
  HardwareErrorCode as HardwareErrorCode2,
97
101
  MISSING_BIP32_MASTER_FINGERPRINT,
98
102
  TypedEventEmitter,
103
+ assertBoundedCbor,
99
104
  createHardwareLinkId,
100
105
  createHardwareSearchTargetId,
101
106
  createHwkError as createHwkError2,
@@ -113,20 +118,68 @@ var KEYSTONE_PUBLIC_DATA_UR_TYPE = "qr-hardware-call";
113
118
  function toUrEncoded(ur) {
114
119
  return new UREncoder(new UR(Buffer.from(ur.urData, "hex"), ur.urType), Infinity).nextPart().toUpperCase();
115
120
  }
121
+ var MAX_UR_MESSAGE_BYTES = 1024 * 1024;
122
+ var MAX_UR_SEQ_LENGTH = 32768;
123
+ var CBOR_ARGUMENT_BYTES = [1, 2, 4, 8];
124
+ function readFountainPart(input) {
125
+ let offset = 0;
126
+ const readHead = (expectedMajor) => {
127
+ const initial = input[offset];
128
+ offset += 1;
129
+ if (Math.floor(initial / 32) !== expectedMajor) {
130
+ throw new Error("Keystone USB reply part is not a fountain part");
131
+ }
132
+ const info = initial % 32;
133
+ if (info < 24) return info;
134
+ const size = CBOR_ARGUMENT_BYTES[info - 24];
135
+ let value = 0;
136
+ for (let i = 0; i < size; i += 1) value = value * 256 + input[offset + i];
137
+ offset += size;
138
+ return value;
139
+ };
140
+ if (readHead(4) !== 5) throw new Error("Keystone USB reply part is not a fountain part");
141
+ const seqNum = readHead(0);
142
+ const seqLength = readHead(0);
143
+ const messageLength = readHead(0);
144
+ readHead(0);
145
+ const fragmentLength = readHead(2);
146
+ return { seqNum, seqLength, messageLength, fragmentLength };
147
+ }
148
+ function assertBoundedUrPart(part) {
149
+ const match = /^ur:[a-z0-9-]+\/(?:(\d{1,9})-(\d{1,9})\/)?([a-z]+)$/i.exec(part);
150
+ 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
+ );
155
+ assertBoundedCbor(payload, MAX_UR_MESSAGE_BYTES);
156
+ if (match[1] === void 0) return;
157
+ const header = readFountainPart(payload);
158
+ if (header.seqNum < 1 || header.seqNum > header.seqLength || header.seqNum !== Number(match[1]) || header.seqLength !== Number(match[2]) || header.fragmentLength < 1 || header.messageLength < 1 || header.messageLength > MAX_UR_MESSAGE_BYTES || header.seqLength > MAX_UR_SEQ_LENGTH || header.seqLength !== Math.ceil(header.messageLength / header.fragmentLength)) {
159
+ throw new Error("Keystone USB reply part has inconsistent or oversized headers");
160
+ }
161
+ }
116
162
  function fromUrEncoded(encoded) {
117
163
  const text = typeof encoded === "string" ? encoded.trim() : "";
118
164
  const parts = text.split(/\s+/).filter(Boolean);
119
165
  const decoder = new URDecoder();
120
- for (const part of parts) {
121
- decoder.receivePart(part);
122
- if (decoder.isComplete()) break;
166
+ try {
167
+ if (parts.length > MAX_UR_SEQ_LENGTH) throw new Error("Keystone USB reply has too many parts");
168
+ for (const part of parts) {
169
+ assertBoundedUrPart(part);
170
+ decoder.receivePart(part);
171
+ if (decoder.isComplete()) break;
172
+ }
173
+ } catch {
123
174
  }
124
175
  if (!parts.length || !decoder.isComplete() || !decoder.isSuccess()) {
125
176
  const shape = typeof encoded === "string" ? `string len=${text.length} parts=${parts.length}` : typeof encoded;
126
177
  throw createHwkError2({
127
178
  code: HardwareErrorCode2.PayloadTooLarge,
128
179
  message: `Keystone USB returned an incomplete BC-UR response (${shape})`,
129
- origin: "device"
180
+ origin: "device",
181
+ // The device processed the request; only its reply is unusable.
182
+ params: { replyUnreadable: true }
130
183
  });
131
184
  }
132
185
  const ur = decoder.resultUR();
@@ -265,7 +318,14 @@ var KeystoneUsbConnectorBase = class {
265
318
  });
266
319
  }
267
320
  if (this.transportClass.connectDevice) {
321
+ if (availableDevices.length === 0) {
322
+ throw createHwkError2({
323
+ code: HardwareErrorCode2.DeviceNotFound,
324
+ message: "No Keystone USB device is available"
325
+ });
326
+ }
268
327
  let readableDeviceFound = false;
328
+ let ambiguous = false;
269
329
  let lastError;
270
330
  let matched;
271
331
  for (const device2 of availableDevices) {
@@ -275,8 +335,13 @@ var KeystoneUsbConnectorBase = class {
275
335
  const candidateConfig = await this._readAppConfig(candidate.transport);
276
336
  readableDeviceFound = true;
277
337
  if (candidateConfig.mfp?.toLowerCase() === expectedMasterFingerprint.toLowerCase()) {
338
+ if (matched) {
339
+ candidate.dispose();
340
+ ambiguous = true;
341
+ break;
342
+ }
278
343
  matched = { device: device2, opened: candidate, config: candidateConfig };
279
- break;
344
+ continue;
280
345
  }
281
346
  candidate.dispose();
282
347
  } catch (error) {
@@ -284,11 +349,18 @@ var KeystoneUsbConnectorBase = class {
284
349
  lastError = error;
285
350
  }
286
351
  }
352
+ if (ambiguous) {
353
+ matched?.opened.dispose();
354
+ throw createHwkError2({
355
+ code: HardwareErrorCode2.DeviceOneDeviceOnly,
356
+ message: "More than one connected Keystone reports this wallet; keep one connected"
357
+ });
358
+ }
287
359
  if (!matched) {
288
360
  if (!readableDeviceFound && lastError) throw mapKeystoneUsbError(lastError);
289
361
  throw createHwkError2({
290
362
  code: HardwareErrorCode2.DeviceMismatch,
291
- message: `No connected Keystone wallet matches fingerprint ${expectedMasterFingerprint}`
363
+ message: "No connected Keystone matches the requested wallet"
292
364
  });
293
365
  }
294
366
  selectedDevice = matched.device;
@@ -332,7 +404,8 @@ var KeystoneUsbConnectorBase = class {
332
404
  if (expectedMasterFingerprint && config.mfp && config.mfp.toLowerCase() !== expectedMasterFingerprint.toLowerCase()) {
333
405
  throw createHwkError2({
334
406
  code: HardwareErrorCode2.DeviceMismatch,
335
- message: `Connected Keystone wallet (mfp ${config.mfp}) does not match the requested wallet fingerprint (${expectedMasterFingerprint})`
407
+ // The master fingerprint identifies the wallet; keep it out of messages that reach logs.
408
+ message: "Connected Keystone wallet does not match the requested wallet"
336
409
  });
337
410
  }
338
411
  const sessionId = createHardwareLinkId("keystone");
@@ -445,6 +518,7 @@ var KeystoneUsbConnectorBase = class {
445
518
  const encoded = toUrEncoded({ urType, urData });
446
519
  const isPublicDataRequest = urType === KEYSTONE_PUBLIC_DATA_UR_TYPE;
447
520
  const publicDataKey = session.mfp?.toLowerCase() ?? sessionId;
521
+ if (!isPublicDataRequest) this.publicDataConfirmedWallets.delete(publicDataKey);
448
522
  const shouldShowConfirmation = !isPublicDataRequest || !this.publicDataConfirmedWallets.has(publicDataKey);
449
523
  if (shouldShowConfirmation) {
450
524
  this.emitter.emit("ui-event", {
@@ -472,7 +546,7 @@ var KeystoneUsbConnectorBase = class {
472
546
  Actions.CMD_CHECK_LOCK_STATUS,
473
547
  ""
474
548
  );
475
- return success({ locked: response.payload });
549
+ return success({ locked: response.payload === true });
476
550
  }
477
551
  case "getAppConfig":
478
552
  return success(await this._readAppConfig(session.transport));
@@ -534,7 +608,8 @@ var KeystoneUsbConnectorBase = class {
534
608
  });
535
609
  }
536
610
  return {
537
- version: typeof response.firmwareVersion === "string" ? response.firmwareVersion : void 0,
611
+ // Device-supplied text reaches the host UI and version gates; accept only a version number.
612
+ version: typeof response.firmwareVersion === "string" && /^\d{1,4}(\.\d{1,4}){1,3}(-[0-9A-Za-z.]{1,20})?$/.test(response.firmwareVersion) ? response.firmwareVersion : void 0,
538
613
  mfp: masterFingerprint
539
614
  };
540
615
  }
@@ -560,4 +635,4 @@ export {
560
635
  mapKeystoneUsbError,
561
636
  KeystoneUsbConnectorBase
562
637
  };
563
- //# sourceMappingURL=chunk-VMQB3BQI.mjs.map
638
+ //# sourceMappingURL=chunk-RZ6UI5PS.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.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,4 +1,4 @@
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
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
2
2
  var _hwkadaptercore = require('@onekeyfe/hwk-adapter-core');
3
3
  var _hwtransporterror = require('@keystonehq/hw-transport-error');
4
4
  function isDeviceStatus(statusCode) {
@@ -64,7 +64,10 @@ function mapKeystoneUsbError(err) {
64
64
  const message = err instanceof Error ? err.message : String(err);
65
65
  if (statusCode !== void 0) {
66
66
  const fromDevice = isDeviceStatus(statusCode);
67
- const code = fromDevice ? _nullishCoalesce(DEVICE_STATUS_MAP[statusCode], () => ( _hwkadaptercore.HardwareErrorCode.UnknownError)) : _nullishCoalesce(CLIENT_STATUS_MAP[statusCode], () => ( _hwkadaptercore.HardwareErrorCode.TransportError));
67
+ let code = fromDevice ? _nullishCoalesce(DEVICE_STATUS_MAP[statusCode], () => ( _hwkadaptercore.HardwareErrorCode.UnknownError)) : _nullishCoalesce(CLIENT_STATUS_MAP[statusCode], () => ( _hwkadaptercore.HardwareErrorCode.TransportError));
68
+ if (statusCode === _hwtransporterror.Status.PRS_PARSING_DISALLOWED && !/\blocked\b/i.test(message)) {
69
+ code = _hwkadaptercore.HardwareErrorCode.DeviceBusy;
70
+ }
68
71
  let origin;
69
72
  if (fromDevice) {
70
73
  origin = "device";
@@ -90,6 +93,7 @@ function mapKeystoneUsbError(err) {
90
93
 
91
94
  // src/KeystoneUsbConnectorBase.ts
92
95
  var _bcur = require('@ngraveio/bc-ur');
96
+ var _bytewords = require('@ngraveio/bc-ur/dist/bytewords'); var _bytewords2 = _interopRequireDefault(_bytewords);
93
97
  var _hwtransportusb = require('@keystonehq/hw-transport-usb');
94
98
 
95
99
 
@@ -105,6 +109,7 @@ var _hwtransportusb = require('@keystonehq/hw-transport-usb');
105
109
 
106
110
 
107
111
 
112
+
108
113
  function usbDisplayName(device) {
109
114
  return _optionalChain([device, 'access', _ => _.productName, 'optionalAccess', _2 => _2.trim, 'call', _3 => _3()]) || "Keystone";
110
115
  }
@@ -113,20 +118,68 @@ var KEYSTONE_PUBLIC_DATA_UR_TYPE = "qr-hardware-call";
113
118
  function toUrEncoded(ur) {
114
119
  return new (0, _bcur.UREncoder)(new (0, _bcur.UR)(Buffer.from(ur.urData, "hex"), ur.urType), Infinity).nextPart().toUpperCase();
115
120
  }
121
+ var MAX_UR_MESSAGE_BYTES = 1024 * 1024;
122
+ var MAX_UR_SEQ_LENGTH = 32768;
123
+ var CBOR_ARGUMENT_BYTES = [1, 2, 4, 8];
124
+ function readFountainPart(input) {
125
+ let offset = 0;
126
+ const readHead = (expectedMajor) => {
127
+ const initial = input[offset];
128
+ offset += 1;
129
+ if (Math.floor(initial / 32) !== expectedMajor) {
130
+ throw new Error("Keystone USB reply part is not a fountain part");
131
+ }
132
+ const info = initial % 32;
133
+ if (info < 24) return info;
134
+ const size = CBOR_ARGUMENT_BYTES[info - 24];
135
+ let value = 0;
136
+ for (let i = 0; i < size; i += 1) value = value * 256 + input[offset + i];
137
+ offset += size;
138
+ return value;
139
+ };
140
+ if (readHead(4) !== 5) throw new Error("Keystone USB reply part is not a fountain part");
141
+ const seqNum = readHead(0);
142
+ const seqLength = readHead(0);
143
+ const messageLength = readHead(0);
144
+ readHead(0);
145
+ const fragmentLength = readHead(2);
146
+ return { seqNum, seqLength, messageLength, fragmentLength };
147
+ }
148
+ function assertBoundedUrPart(part) {
149
+ const match = /^ur:[a-z0-9-]+\/(?:(\d{1,9})-(\d{1,9})\/)?([a-z]+)$/i.exec(part);
150
+ 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
+ );
155
+ _hwkadaptercore.assertBoundedCbor.call(void 0, payload, MAX_UR_MESSAGE_BYTES);
156
+ if (match[1] === void 0) return;
157
+ const header = readFountainPart(payload);
158
+ if (header.seqNum < 1 || header.seqNum > header.seqLength || header.seqNum !== Number(match[1]) || header.seqLength !== Number(match[2]) || header.fragmentLength < 1 || header.messageLength < 1 || header.messageLength > MAX_UR_MESSAGE_BYTES || header.seqLength > MAX_UR_SEQ_LENGTH || header.seqLength !== Math.ceil(header.messageLength / header.fragmentLength)) {
159
+ throw new Error("Keystone USB reply part has inconsistent or oversized headers");
160
+ }
161
+ }
116
162
  function fromUrEncoded(encoded) {
117
163
  const text = typeof encoded === "string" ? encoded.trim() : "";
118
164
  const parts = text.split(/\s+/).filter(Boolean);
119
165
  const decoder = new (0, _bcur.URDecoder)();
120
- for (const part of parts) {
121
- decoder.receivePart(part);
122
- if (decoder.isComplete()) break;
166
+ try {
167
+ if (parts.length > MAX_UR_SEQ_LENGTH) throw new Error("Keystone USB reply has too many parts");
168
+ for (const part of parts) {
169
+ assertBoundedUrPart(part);
170
+ decoder.receivePart(part);
171
+ if (decoder.isComplete()) break;
172
+ }
173
+ } catch (e) {
123
174
  }
124
175
  if (!parts.length || !decoder.isComplete() || !decoder.isSuccess()) {
125
176
  const shape = typeof encoded === "string" ? `string len=${text.length} parts=${parts.length}` : typeof encoded;
126
177
  throw _hwkadaptercore.createHwkError.call(void 0, {
127
178
  code: _hwkadaptercore.HardwareErrorCode.PayloadTooLarge,
128
179
  message: `Keystone USB returned an incomplete BC-UR response (${shape})`,
129
- origin: "device"
180
+ origin: "device",
181
+ // The device processed the request; only its reply is unusable.
182
+ params: { replyUnreadable: true }
130
183
  });
131
184
  }
132
185
  const ur = decoder.resultUR();
@@ -265,7 +318,14 @@ var KeystoneUsbConnectorBase = class {
265
318
  });
266
319
  }
267
320
  if (this.transportClass.connectDevice) {
321
+ if (availableDevices.length === 0) {
322
+ throw _hwkadaptercore.createHwkError.call(void 0, {
323
+ code: _hwkadaptercore.HardwareErrorCode.DeviceNotFound,
324
+ message: "No Keystone USB device is available"
325
+ });
326
+ }
268
327
  let readableDeviceFound = false;
328
+ let ambiguous = false;
269
329
  let lastError;
270
330
  let matched;
271
331
  for (const device2 of availableDevices) {
@@ -275,8 +335,13 @@ var KeystoneUsbConnectorBase = class {
275
335
  const candidateConfig = await this._readAppConfig(candidate.transport);
276
336
  readableDeviceFound = true;
277
337
  if (_optionalChain([candidateConfig, 'access', _6 => _6.mfp, 'optionalAccess', _7 => _7.toLowerCase, 'call', _8 => _8()]) === expectedMasterFingerprint.toLowerCase()) {
338
+ if (matched) {
339
+ candidate.dispose();
340
+ ambiguous = true;
341
+ break;
342
+ }
278
343
  matched = { device: device2, opened: candidate, config: candidateConfig };
279
- break;
344
+ continue;
280
345
  }
281
346
  candidate.dispose();
282
347
  } catch (error) {
@@ -284,11 +349,18 @@ var KeystoneUsbConnectorBase = class {
284
349
  lastError = error;
285
350
  }
286
351
  }
352
+ if (ambiguous) {
353
+ _optionalChain([matched, 'optionalAccess', _11 => _11.opened, 'access', _12 => _12.dispose, 'call', _13 => _13()]);
354
+ throw _hwkadaptercore.createHwkError.call(void 0, {
355
+ code: _hwkadaptercore.HardwareErrorCode.DeviceOneDeviceOnly,
356
+ message: "More than one connected Keystone reports this wallet; keep one connected"
357
+ });
358
+ }
287
359
  if (!matched) {
288
360
  if (!readableDeviceFound && lastError) throw mapKeystoneUsbError(lastError);
289
361
  throw _hwkadaptercore.createHwkError.call(void 0, {
290
362
  code: _hwkadaptercore.HardwareErrorCode.DeviceMismatch,
291
- message: `No connected Keystone wallet matches fingerprint ${expectedMasterFingerprint}`
363
+ message: "No connected Keystone matches the requested wallet"
292
364
  });
293
365
  }
294
366
  selectedDevice = matched.device;
@@ -332,7 +404,8 @@ var KeystoneUsbConnectorBase = class {
332
404
  if (expectedMasterFingerprint && config.mfp && config.mfp.toLowerCase() !== expectedMasterFingerprint.toLowerCase()) {
333
405
  throw _hwkadaptercore.createHwkError.call(void 0, {
334
406
  code: _hwkadaptercore.HardwareErrorCode.DeviceMismatch,
335
- message: `Connected Keystone wallet (mfp ${config.mfp}) does not match the requested wallet fingerprint (${expectedMasterFingerprint})`
407
+ // The master fingerprint identifies the wallet; keep it out of messages that reach logs.
408
+ message: "Connected Keystone wallet does not match the requested wallet"
336
409
  });
337
410
  }
338
411
  const sessionId = _hwkadaptercore.createHardwareLinkId.call(void 0, "keystone");
@@ -347,9 +420,9 @@ var KeystoneUsbConnectorBase = class {
347
420
  connectId: sessionId,
348
421
  deviceId: "",
349
422
  name: selectedDevice ? usbDisplayName(selectedDevice) : "Keystone",
350
- model: _optionalChain([selectedDevice, 'optionalAccess', _11 => _11.productName]),
423
+ model: _optionalChain([selectedDevice, 'optionalAccess', _14 => _14.productName]),
351
424
  connectionType: "usb",
352
- serialNumber: _optionalChain([selectedDevice, 'optionalAccess', _12 => _12.serialNumber]),
425
+ serialNumber: _optionalChain([selectedDevice, 'optionalAccess', _15 => _15.serialNumber]),
353
426
  capabilities: { persistentDeviceIdentity: false },
354
427
  raw: { masterFingerprint: config.mfp }
355
428
  };
@@ -359,7 +432,7 @@ var KeystoneUsbConnectorBase = class {
359
432
  deviceInfo: this._toDeviceInfo(device, config.version, config.mfp)
360
433
  };
361
434
  } catch (err) {
362
- _optionalChain([openedTransport, 'optionalAccess', _13 => _13.dispose, 'call', _14 => _14()]);
435
+ _optionalChain([openedTransport, 'optionalAccess', _16 => _16.dispose, 'call', _17 => _17()]);
363
436
  throw mapKeystoneUsbError(err);
364
437
  }
365
438
  }
@@ -379,7 +452,7 @@ var KeystoneUsbConnectorBase = class {
379
452
  dispose: () => {
380
453
  if (disposed) return;
381
454
  disposed = true;
382
- _optionalChain([this, 'access', _15 => _15.transportClass, 'access', _16 => _16.disposeTransport, 'optionalCall', _17 => _17(transport)]);
455
+ _optionalChain([this, 'access', _18 => _18.transportClass, 'access', _19 => _19.disposeTransport, 'optionalCall', _20 => _20(transport)]);
383
456
  }
384
457
  };
385
458
  }
@@ -444,7 +517,8 @@ var KeystoneUsbConnectorBase = class {
444
517
  const { urType, urData } = params;
445
518
  const encoded = toUrEncoded({ urType, urData });
446
519
  const isPublicDataRequest = urType === KEYSTONE_PUBLIC_DATA_UR_TYPE;
447
- const publicDataKey = _nullishCoalesce(_optionalChain([session, 'access', _18 => _18.mfp, 'optionalAccess', _19 => _19.toLowerCase, 'call', _20 => _20()]), () => ( sessionId));
520
+ const publicDataKey = _nullishCoalesce(_optionalChain([session, 'access', _21 => _21.mfp, 'optionalAccess', _22 => _22.toLowerCase, 'call', _23 => _23()]), () => ( sessionId));
521
+ if (!isPublicDataRequest) this.publicDataConfirmedWallets.delete(publicDataKey);
448
522
  const shouldShowConfirmation = !isPublicDataRequest || !this.publicDataConfirmedWallets.has(publicDataKey);
449
523
  if (shouldShowConfirmation) {
450
524
  this.emitter.emit("ui-event", {
@@ -472,7 +546,7 @@ var KeystoneUsbConnectorBase = class {
472
546
  _hwtransportusb.Actions.CMD_CHECK_LOCK_STATUS,
473
547
  ""
474
548
  );
475
- return _hwkadaptercore.success.call(void 0, { locked: response.payload });
549
+ return _hwkadaptercore.success.call(void 0, { locked: response.payload === true });
476
550
  }
477
551
  case "getAppConfig":
478
552
  return _hwkadaptercore.success.call(void 0, await this._readAppConfig(session.transport));
@@ -534,7 +608,8 @@ var KeystoneUsbConnectorBase = class {
534
608
  });
535
609
  }
536
610
  return {
537
- version: typeof response.firmwareVersion === "string" ? response.firmwareVersion : void 0,
611
+ // Device-supplied text reaches the host UI and version gates; accept only a version number.
612
+ version: typeof response.firmwareVersion === "string" && /^\d{1,4}(\.\d{1,4}){1,3}(-[0-9A-Za-z.]{1,20})?$/.test(response.firmwareVersion) ? response.firmwareVersion : void 0,
538
613
  mfp: masterFingerprint
539
614
  };
540
615
  }
@@ -560,4 +635,4 @@ var KeystoneUsbConnectorBase = class {
560
635
 
561
636
 
562
637
  exports.mapKeystoneUsbError = mapKeystoneUsbError; exports.KeystoneUsbConnectorBase = KeystoneUsbConnectorBase;
563
- //# sourceMappingURL=chunk-BYR5HEA3.js.map
638
+ //# sourceMappingURL=chunk-U76BQU3H.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-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"]}
package/dist/index.d.mts CHANGED
@@ -19,7 +19,7 @@ interface KeystoneUsbDeviceDescriptor {
19
19
  deviceSubclass?: number;
20
20
  deviceProtocol?: number;
21
21
  }
22
- /** Static surface of `TransportWebUSB`/`TransportNodeUSB`, injected by `_subpath/*`. */
22
+ /** Static surface of `TransportWebUSB`, injected by `_subpath/webusb`. */
23
23
  interface KeystoneUsbTransportStatic {
24
24
  connect(config?: TransportConfig): Promise<TransportHID>;
25
25
  connectDevice?(device: KeystoneUsbDeviceDescriptor, config?: TransportConfig): Promise<TransportHID>;
package/dist/index.d.ts CHANGED
@@ -19,7 +19,7 @@ interface KeystoneUsbDeviceDescriptor {
19
19
  deviceSubclass?: number;
20
20
  deviceProtocol?: number;
21
21
  }
22
- /** Static surface of `TransportWebUSB`/`TransportNodeUSB`, injected by `_subpath/*`. */
22
+ /** Static surface of `TransportWebUSB`, injected by `_subpath/webusb`. */
23
23
  interface KeystoneUsbTransportStatic {
24
24
  connect(config?: TransportConfig): Promise<TransportHID>;
25
25
  connectDevice?(device: KeystoneUsbDeviceDescriptor, config?: TransportConfig): Promise<TransportHID>;
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 _chunkBYR5HEA3js = require('./chunk-BYR5HEA3.js');
4
+ var _chunkU76BQU3Hjs = require('./chunk-U76BQU3H.js');
5
5
 
6
6
 
7
7
 
8
- exports.KeystoneUsbConnectorBase = _chunkBYR5HEA3js.KeystoneUsbConnectorBase; exports.mapKeystoneUsbError = _chunkBYR5HEA3js.mapKeystoneUsbError;
8
+ exports.KeystoneUsbConnectorBase = _chunkU76BQU3Hjs.KeystoneUsbConnectorBase; exports.mapKeystoneUsbError = _chunkU76BQU3Hjs.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-VMQB3BQI.mjs";
4
+ } from "./chunk-RZ6UI5PS.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 _chunkBYR5HEA3js = require('./chunk-BYR5HEA3.js');
3
+ var _chunkU76BQU3Hjs = require('./chunk-U76BQU3H.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, _chunkBYR5HEA3js.KeystoneUsbConnectorBase)(
28
+ return new (0, _chunkU76BQU3Hjs.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-VMQB3BQI.mjs";
3
+ } from "./chunk-RZ6UI5PS.mjs";
4
4
 
5
5
  // src/_subpath/webusb.ts
6
6
  import { TransportWebUSB } from "@keystonehq/hw-transport-webusb";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@onekeyfe/hwk-keystone-connector-usb",
3
- "version": "1.2.6-alpha.0",
4
- "description": "IConnector implementation for Keystone hardware wallets via USB (WebUSB + Node USB)",
3
+ "version": "1.2.8-alpha.13",
4
+ "description": "IConnector implementation for Keystone hardware wallets via WebUSB",
5
5
  "author": "OneKey",
6
6
  "license": "MIT",
7
7
  "main": "dist/index.js",
@@ -27,16 +27,6 @@
27
27
  "types": "./dist/webusb.d.ts",
28
28
  "default": "./dist/webusb.js"
29
29
  }
30
- },
31
- "./nodeusb": {
32
- "import": {
33
- "types": "./dist/nodeusb.d.mts",
34
- "default": "./dist/nodeusb.mjs"
35
- },
36
- "require": {
37
- "types": "./dist/nodeusb.d.ts",
38
- "default": "./dist/nodeusb.js"
39
- }
40
30
  }
41
31
  },
42
32
  "files": [
@@ -69,22 +59,13 @@
69
59
  "@keystonehq/hw-transport-usb": "0.2.0",
70
60
  "@keystonehq/hw-transport-webusb": "0.5.3",
71
61
  "@ngraveio/bc-ur": "1.1.13",
72
- "@onekeyfe/hwk-adapter-core": "1.2.6-alpha.0"
62
+ "@onekeyfe/hwk-adapter-core": "1.2.8-alpha.13"
73
63
  },
74
64
  "devDependencies": {
75
65
  "@keystonehq/bc-ur-registry-eth": "0.22.1",
76
- "@keystonehq/hw-transport-nodeusb": "0.2.0",
77
66
  "rimraf": "^5.0.0",
78
67
  "tsup": "^8.0.0",
79
68
  "typescript": "^5.4.0"
80
69
  },
81
- "peerDependencies": {
82
- "@keystonehq/hw-transport-nodeusb": "0.2.0"
83
- },
84
- "peerDependenciesMeta": {
85
- "@keystonehq/hw-transport-nodeusb": {
86
- "optional": true
87
- }
88
- },
89
- "gitHead": "9aa91a0780c3169164da575deadf5d256013d416"
70
+ "gitHead": "ed22eddce37ce0562b329c42a6985b50949ca412"
90
71
  }
@@ -1 +0,0 @@
1
- {"version":3,"sources":["/home/runner/work/hardware-js-sdk/hardware-js-sdk/packages/hwk-keystone-connector-usb/dist/chunk-BYR5HEA3.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-BYR5HEA3.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 const code = fromDevice\n ? DEVICE_STATUS_MAP[statusCode] ?? HardwareErrorCode.UnknownError\n : CLIENT_STATUS_MAP[statusCode] ?? HardwareErrorCode.TransportError;\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 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`/`TransportNodeUSB`, injected by `_subpath/*`. */\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\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 for (const part of parts) {\n decoder.receivePart(part);\n if (decoder.isComplete()) break;\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 });\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 let readableDeviceFound = 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 matched = { device, opened: candidate, config: candidateConfig };\n break;\n }\n candidate.dispose();\n } catch (error) {\n candidate?.dispose();\n lastError = error;\n }\n }\n if (!matched) {\n if (!readableDeviceFound && lastError) throw mapKeystoneUsbError(lastError);\n throw createHwkError({\n code: HardwareErrorCode.DeviceMismatch,\n message: `No connected Keystone wallet matches fingerprint ${expectedMasterFingerprint}`,\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 message: `Connected Keystone wallet (mfp ${config.mfp}) does not match the requested wallet fingerprint (${expectedMasterFingerprint})`,\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.\n const publicDataKey = session.mfp?.toLowerCase() ?? sessionId;\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 return success({ locked: response.payload });\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 version: typeof response.firmwareVersion === 'string' ? response.firmwareVersion : 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"]}
@@ -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 const code = fromDevice\n ? DEVICE_STATUS_MAP[statusCode] ?? HardwareErrorCode.UnknownError\n : CLIENT_STATUS_MAP[statusCode] ?? HardwareErrorCode.TransportError;\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 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`/`TransportNodeUSB`, injected by `_subpath/*`. */\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\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 for (const part of parts) {\n decoder.receivePart(part);\n if (decoder.isComplete()) break;\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 });\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 let readableDeviceFound = 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 matched = { device, opened: candidate, config: candidateConfig };\n break;\n }\n candidate.dispose();\n } catch (error) {\n candidate?.dispose();\n lastError = error;\n }\n }\n if (!matched) {\n if (!readableDeviceFound && lastError) throw mapKeystoneUsbError(lastError);\n throw createHwkError({\n code: HardwareErrorCode.DeviceMismatch,\n message: `No connected Keystone wallet matches fingerprint ${expectedMasterFingerprint}`,\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 message: `Connected Keystone wallet (mfp ${config.mfp}) does not match the requested wallet fingerprint (${expectedMasterFingerprint})`,\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.\n const publicDataKey = session.mfp?.toLowerCase() ?? sessionId;\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 return success({ locked: response.payload });\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 version: typeof response.firmwareVersion === 'string' ? response.firmwareVersion : 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,UAAM,OAAO,aACT,kBAAkB,UAAU,KAAK,kBAAkB,eACnD,kBAAkB,UAAU,KAAK,kBAAkB;AACvD,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;;;AC/HA,SAAS,IAAI,WAAW,iBAAiB;AACzC,SAAS,eAAe;AACxB;AAAA,EACE;AAAA,EACA,qBAAAA;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;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,aAAW,QAAQ,OAAO;AACxB,YAAQ,YAAY,IAAI;AACxB,QAAI,QAAQ,WAAW,EAAG;AAAA,EAC5B;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,IACV,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,sBAAsB;AAC1B,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,0BAAU,EAAE,QAAAA,SAAQ,QAAQ,WAAW,QAAQ,gBAAgB;AAC/D;AAAA,cACF;AACA,wBAAU,QAAQ;AAAA,YACpB,SAAS,OAAO;AACd,yBAAW,QAAQ;AACnB,0BAAY;AAAA,YACd;AAAA,UACF;AACA,cAAI,CAAC,SAAS;AACZ,gBAAI,CAAC,uBAAuB,UAAW,OAAM,oBAAoB,SAAS;AAC1E,kBAAMF,gBAAe;AAAA,cACnB,MAAMC,mBAAkB;AAAA,cACxB,SAAS,oDAAoD,yBAAyB;AAAA,YACxF,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,UACxB,SAAS,kCAAkC,OAAO,GAAG,sDAAsD,yBAAyB;AAAA,QACtI,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;AAEvC,gBAAM,gBAAgB,QAAQ,KAAK,YAAY,KAAK;AACpD,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;AAEA,iBAAO,QAAQ,EAAE,QAAQ,SAAS,QAAQ,CAAC;AAAA,QAC7C;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,MACL,SAAS,OAAO,SAAS,oBAAoB,WAAW,SAAS,kBAAkB;AAAA,MACnF,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,7 +0,0 @@
1
- import { IConnector } from '@onekeyfe/hwk-adapter-core';
2
-
3
- declare function createKeystoneNodeUsbConnector(options?: {
4
- timeoutMs?: number;
5
- }): IConnector;
6
-
7
- export { createKeystoneNodeUsbConnector };
package/dist/nodeusb.d.ts DELETED
@@ -1,7 +0,0 @@
1
- import { IConnector } from '@onekeyfe/hwk-adapter-core';
2
-
3
- declare function createKeystoneNodeUsbConnector(options?: {
4
- timeoutMs?: number;
5
- }): IConnector;
6
-
7
- export { createKeystoneNodeUsbConnector };
package/dist/nodeusb.js DELETED
@@ -1,13 +0,0 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
-
3
- var _chunkBYR5HEA3js = require('./chunk-BYR5HEA3.js');
4
-
5
- // src/_subpath/nodeusb.ts
6
- var _hwtransportnodeusb = require('@keystonehq/hw-transport-nodeusb');
7
- function createKeystoneNodeUsbConnector(options) {
8
- return new (0, _chunkBYR5HEA3js.KeystoneUsbConnectorBase)(_hwtransportnodeusb.TransportNodeUSB, options);
9
- }
10
-
11
-
12
- exports.createKeystoneNodeUsbConnector = createKeystoneNodeUsbConnector;
13
- //# sourceMappingURL=nodeusb.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["/home/runner/work/hardware-js-sdk/hardware-js-sdk/packages/hwk-keystone-connector-usb/dist/nodeusb.js","../src/_subpath/nodeusb.ts"],"names":[],"mappings":"AAAA;AACE;AACF,sDAA4B;AAC5B;AACA;ACJA,sEAAiC;AAM1B,SAAS,8BAAA,CAA+B,OAAA,EAA8C;AAC3F,EAAA,OAAO,IAAI,8CAAA,CAAyB,oCAAA,EAAkB,OAAO,CAAA;AAC/D;ADCA;AACE;AACF,wEAAC","file":"/home/runner/work/hardware-js-sdk/hardware-js-sdk/packages/hwk-keystone-connector-usb/dist/nodeusb.js","sourcesContent":[null,"import { TransportNodeUSB } from '@keystonehq/hw-transport-nodeusb';\n\nimport { KeystoneUsbConnectorBase } from '../KeystoneUsbConnectorBase';\n\nimport type { IConnector } from '@onekeyfe/hwk-adapter-core';\n\nexport function createKeystoneNodeUsbConnector(options?: { timeoutMs?: number }): IConnector {\n return new KeystoneUsbConnectorBase(TransportNodeUSB, options);\n}\n"]}
package/dist/nodeusb.mjs DELETED
@@ -1,13 +0,0 @@
1
- import {
2
- KeystoneUsbConnectorBase
3
- } from "./chunk-VMQB3BQI.mjs";
4
-
5
- // src/_subpath/nodeusb.ts
6
- import { TransportNodeUSB } from "@keystonehq/hw-transport-nodeusb";
7
- function createKeystoneNodeUsbConnector(options) {
8
- return new KeystoneUsbConnectorBase(TransportNodeUSB, options);
9
- }
10
- export {
11
- createKeystoneNodeUsbConnector
12
- };
13
- //# sourceMappingURL=nodeusb.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/_subpath/nodeusb.ts"],"sourcesContent":["import { TransportNodeUSB } from '@keystonehq/hw-transport-nodeusb';\n\nimport { KeystoneUsbConnectorBase } from '../KeystoneUsbConnectorBase';\n\nimport type { IConnector } from '@onekeyfe/hwk-adapter-core';\n\nexport function createKeystoneNodeUsbConnector(options?: { timeoutMs?: number }): IConnector {\n return new KeystoneUsbConnectorBase(TransportNodeUSB, options);\n}\n"],"mappings":";;;;;AAAA,SAAS,wBAAwB;AAM1B,SAAS,+BAA+B,SAA8C;AAC3F,SAAO,IAAI,yBAAyB,kBAAkB,OAAO;AAC/D;","names":[]}