@onekeyfe/hwk-adapter-core 1.1.29-alpha.3 → 1.1.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,19 +1,68 @@
1
- import {
2
- HardwareErrorCode,
3
- ORPHAN_ELIGIBLE_ERROR_CODES,
4
- createHwkError,
5
- enrichErrorMessage
6
- } from "./chunk-D5OZT7RZ.mjs";
7
- import {
8
- UI_EVENT,
9
- UI_REQUEST,
10
- UI_REQUEST_CANCELLED_TAG,
11
- UI_REQUEST_DEFAULT_TIMEOUT_MS,
12
- UI_REQUEST_PREEMPTED_TAG,
13
- UI_REQUEST_TIMEOUT_TAG,
14
- UI_RESPONSE,
15
- UiRequestRegistry
16
- } from "./chunk-6JWUE3GT.mjs";
1
+ // src/types/errors.ts
2
+ var HardwareErrorCode = /* @__PURE__ */ ((HardwareErrorCode2) => {
3
+ HardwareErrorCode2[HardwareErrorCode2["UnknownError"] = 1e4] = "UnknownError";
4
+ HardwareErrorCode2[HardwareErrorCode2["UserRejected"] = 10001] = "UserRejected";
5
+ HardwareErrorCode2[HardwareErrorCode2["InvalidParams"] = 10002] = "InvalidParams";
6
+ HardwareErrorCode2[HardwareErrorCode2["OperationTimeout"] = 10003] = "OperationTimeout";
7
+ HardwareErrorCode2[HardwareErrorCode2["MethodNotSupported"] = 10004] = "MethodNotSupported";
8
+ HardwareErrorCode2[HardwareErrorCode2["UserAborted"] = 10005] = "UserAborted";
9
+ HardwareErrorCode2[HardwareErrorCode2["DeviceNotFound"] = 10100] = "DeviceNotFound";
10
+ HardwareErrorCode2[HardwareErrorCode2["DeviceDisconnected"] = 10101] = "DeviceDisconnected";
11
+ HardwareErrorCode2[HardwareErrorCode2["DeviceBusy"] = 10102] = "DeviceBusy";
12
+ HardwareErrorCode2[HardwareErrorCode2["DeviceLocked"] = 10103] = "DeviceLocked";
13
+ HardwareErrorCode2[HardwareErrorCode2["DeviceNotInitialized"] = 10104] = "DeviceNotInitialized";
14
+ HardwareErrorCode2[HardwareErrorCode2["DeviceInBootloader"] = 10105] = "DeviceInBootloader";
15
+ HardwareErrorCode2[HardwareErrorCode2["DeviceMismatch"] = 10106] = "DeviceMismatch";
16
+ HardwareErrorCode2[HardwareErrorCode2["DeviceAppStuck"] = 10107] = "DeviceAppStuck";
17
+ HardwareErrorCode2[HardwareErrorCode2["ChainNotSupported"] = 10108] = "ChainNotSupported";
18
+ HardwareErrorCode2[HardwareErrorCode2["DeviceOneDeviceOnly"] = 10109] = "DeviceOneDeviceOnly";
19
+ HardwareErrorCode2[HardwareErrorCode2["FirmwareTooOld"] = 10200] = "FirmwareTooOld";
20
+ HardwareErrorCode2[HardwareErrorCode2["FirmwareUpdateRequired"] = 10201] = "FirmwareUpdateRequired";
21
+ HardwareErrorCode2[HardwareErrorCode2["TransportError"] = 10300] = "TransportError";
22
+ HardwareErrorCode2[HardwareErrorCode2["BridgeNotFound"] = 10301] = "BridgeNotFound";
23
+ HardwareErrorCode2[HardwareErrorCode2["TransportNotAvailable"] = 10302] = "TransportNotAvailable";
24
+ HardwareErrorCode2[HardwareErrorCode2["DevicePermissionDenied"] = 10303] = "DevicePermissionDenied";
25
+ HardwareErrorCode2[HardwareErrorCode2["BlePairingTimeout"] = 10304] = "BlePairingTimeout";
26
+ HardwareErrorCode2[HardwareErrorCode2["NetworkError"] = 10305] = "NetworkError";
27
+ HardwareErrorCode2[HardwareErrorCode2["PinInvalid"] = 10400] = "PinInvalid";
28
+ HardwareErrorCode2[HardwareErrorCode2["PinCancelled"] = 10401] = "PinCancelled";
29
+ HardwareErrorCode2[HardwareErrorCode2["PassphraseRejected"] = 10402] = "PassphraseRejected";
30
+ HardwareErrorCode2[HardwareErrorCode2["AppNotInstalled"] = 10500] = "AppNotInstalled";
31
+ HardwareErrorCode2[HardwareErrorCode2["WrongApp"] = 10501] = "WrongApp";
32
+ HardwareErrorCode2[HardwareErrorCode2["AppTooOld"] = 10502] = "AppTooOld";
33
+ HardwareErrorCode2[HardwareErrorCode2["DeviceOutOfMemory"] = 10503] = "DeviceOutOfMemory";
34
+ HardwareErrorCode2[HardwareErrorCode2["EvmBlindSigningRequired"] = 11e3] = "EvmBlindSigningRequired";
35
+ HardwareErrorCode2[HardwareErrorCode2["EvmClearSignPluginMissing"] = 11001] = "EvmClearSignPluginMissing";
36
+ HardwareErrorCode2[HardwareErrorCode2["EvmDataTooLarge"] = 11002] = "EvmDataTooLarge";
37
+ HardwareErrorCode2[HardwareErrorCode2["EvmTxTypeNotSupported"] = 11003] = "EvmTxTypeNotSupported";
38
+ HardwareErrorCode2[HardwareErrorCode2["SolanaBlindSigningRequired"] = 11100] = "SolanaBlindSigningRequired";
39
+ HardwareErrorCode2[HardwareErrorCode2["TronCustomContractRequired"] = 11200] = "TronCustomContractRequired";
40
+ HardwareErrorCode2[HardwareErrorCode2["TronDataSigningRequired"] = 11201] = "TronDataSigningRequired";
41
+ HardwareErrorCode2[HardwareErrorCode2["TronSignByHashRequired"] = 11202] = "TronSignByHashRequired";
42
+ HardwareErrorCode2[HardwareErrorCode2["BtcWalletPolicyHmacMismatch"] = 11300] = "BtcWalletPolicyHmacMismatch";
43
+ HardwareErrorCode2[HardwareErrorCode2["BtcUnexpectedState"] = 11301] = "BtcUnexpectedState";
44
+ return HardwareErrorCode2;
45
+ })(HardwareErrorCode || {});
46
+ var ORPHAN_ELIGIBLE_ERROR_CODES = [
47
+ 10005 /* UserAborted */,
48
+ 10001 /* UserRejected */,
49
+ 10100 /* DeviceNotFound */,
50
+ 10101 /* DeviceDisconnected */,
51
+ 10106 /* DeviceMismatch */,
52
+ 10107 /* DeviceAppStuck */,
53
+ 10109 /* DeviceOneDeviceOnly */,
54
+ 10300 /* TransportError */,
55
+ 10303 /* DevicePermissionDenied */,
56
+ 10304 /* BlePairingTimeout */
57
+ ];
58
+ function createHwkError(payload) {
59
+ return Object.assign(new Error(payload.message), {
60
+ code: payload.code,
61
+ ...payload._tag !== void 0 && { _tag: payload._tag },
62
+ ...payload.appName !== void 0 && { appName: payload.appName },
63
+ ...payload.params !== void 0 && { params: payload.params }
64
+ });
65
+ }
17
66
 
18
67
  // src/types/response.ts
19
68
  function success(payload) {
@@ -46,19 +95,43 @@ var DEVICE_EVENT = "DEVICE_EVENT";
46
95
  var DEVICE = {
47
96
  CONNECT: "device-connect",
48
97
  DISCONNECT: "device-disconnect",
49
- CHANGED: "device-changed",
50
- FEATURES: "features",
51
- /**
52
- * Trezor-only. Emitted after a successful THP handshake that minted or
53
- * refreshed pairing credentials. The host should persist `credentials`
54
- * keyed by `deviceId` and feed them back into the connector on the next
55
- * connect to skip the CodeEntry/QrCode/NFC pairing UX.
56
- *
57
- * The `TREZOR_` prefix mirrors `UI_REQUEST.REQUEST_TREZOR_THP_PAIRING` —
58
- * vendor-specific events live in the shared event taxonomy but are named
59
- * so hosts can ignore them when they don't drive Trezor hardware.
60
- */
61
- TREZOR_THP_CREDENTIALS_CHANGED: "device-trezor-thp-credentials-changed"
98
+ CHANGED: "device-changed"
99
+ };
100
+
101
+ // src/events/ui-request.ts
102
+ var UI_EVENT = "UI_EVENT";
103
+ var UI_REQUEST = {
104
+ REQUEST_PIN: "ui-request-pin",
105
+ REQUEST_PASSPHRASE: "ui-request-passphrase",
106
+ REQUEST_PASSPHRASE_ON_DEVICE: "ui-request-passphrase-on-device",
107
+ REQUEST_BUTTON: "ui-request-button",
108
+ REQUEST_QR_DISPLAY: "ui-request-qr-display",
109
+ REQUEST_QR_SCAN: "ui-request-qr-scan",
110
+ REQUEST_DEVICE_PERMISSION: "ui-request-device-permission",
111
+ REQUEST_SELECT_DEVICE: "ui-request-select-device",
112
+ REQUEST_DEVICE_CONNECT: "ui-request-device-connect",
113
+ // Ledger BTC App: account index >= 100 requires display=true. Adapter asks
114
+ // the user once per session before promoting the call.
115
+ REQUEST_BTC_HIGH_INDEX_CONFIRM: "ui-request-btc-high-index-confirm",
116
+ // Required app is not installed; with autoInstallApp on, ask the user
117
+ // whether to install it before retrying the operation.
118
+ REQUEST_INSTALL_APP: "ui-request-install-app",
119
+ CLOSE_UI_WINDOW: "ui-close",
120
+ DEVICE_PROGRESS: "ui-device_progress",
121
+ FIRMWARE_PROGRESS: "ui-firmware-progress",
122
+ FIRMWARE_TIP: "ui-firmware-tip"
123
+ };
124
+ var UI_RESPONSE = {
125
+ RECEIVE_PIN: "receive-pin",
126
+ RECEIVE_PASSPHRASE: "receive-passphrase",
127
+ RECEIVE_PASSPHRASE_ON_DEVICE: "receive-passphrase-on-device",
128
+ RECEIVE_QR_RESPONSE: "receive-qr-response",
129
+ RECEIVE_SELECT_DEVICE: "receive-select-device",
130
+ RECEIVE_DEVICE_CONNECT: "receive-device-connect",
131
+ RECEIVE_DEVICE_PERMISSION: "receive-device-permission",
132
+ RECEIVE_BTC_HIGH_INDEX_CONFIRM: "receive-btc-high-index-confirm",
133
+ RECEIVE_INSTALL_APP: "receive-install-app",
134
+ CANCEL: "cancel"
62
135
  };
63
136
 
64
137
  // src/events/sdk.ts
@@ -189,7 +262,7 @@ function createBridgedConnector(vendor, connectionType, bridge) {
189
262
  const handlerMap = /* @__PURE__ */ new Map();
190
263
  return {
191
264
  connectionType,
192
- searchDevices: (options) => bridge.searchDevices({ vendor, options }),
265
+ searchDevices: () => bridge.searchDevices({ vendor }),
193
266
  connect: (deviceId) => bridge.connect({ vendor, deviceId }),
194
267
  disconnect: (sessionId) => bridge.disconnect({ vendor, sessionId }),
195
268
  call: (sessionId, method, callParams) => bridge.call({ vendor, sessionId, method, callParams }),
@@ -217,8 +290,7 @@ function createBridgedConnector(vendor, connectionType, bridge) {
217
290
  inner.delete(handler);
218
291
  if (inner.size === 0) handlerMap.delete(event);
219
292
  },
220
- reset: () => bridge.reset({ vendor }),
221
- setKnownCredentials: bridge.setKnownCredentials ? (credentials) => bridge.setKnownCredentials({ vendor, credentials }) : void 0
293
+ reset: () => bridge.reset({ vendor })
222
294
  };
223
295
  }
224
296
  var SERIALIZED_ERROR_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set([
@@ -278,222 +350,6 @@ function rehydrateConnectorError(error) {
278
350
  ...params ?? {}
279
351
  });
280
352
  }
281
- function isDeviceUnavailableError(error) {
282
- const typed = error;
283
- if (typed.code === 10100 /* DeviceNotFound */ || typed.code === 10101 /* DeviceDisconnected */) {
284
- return true;
285
- }
286
- return false;
287
- }
288
- function combinedDeviceNotFoundError(message) {
289
- return createHwkError({
290
- code: 10100 /* DeviceNotFound */,
291
- message
292
- });
293
- }
294
- function combinedSessionNotFoundError(message) {
295
- return createHwkError({
296
- code: 10101 /* DeviceDisconnected */,
297
- message
298
- });
299
- }
300
- function createCombinedConnector(connectors) {
301
- if (connectors.length === 0) {
302
- throw new Error("createCombinedConnector: at least one connector is required");
303
- }
304
- const SEARCH_SETTLE_AFTER_FIRST_DEVICE_MS = 250;
305
- const deviceOwner = /* @__PURE__ */ new Map();
306
- const sessionOwner = /* @__PURE__ */ new Map();
307
- const forwarders = /* @__PURE__ */ new Map();
308
- const rank = (device) => device.connectionType === "ble" ? 1 : 0;
309
- const sharedCredentials = [];
310
- const credentialKey = (c) => c.credential ?? JSON.stringify(c);
311
- const mergeShared = (incoming) => {
312
- let changed = false;
313
- for (const cred of incoming) {
314
- const key = credentialKey(cred);
315
- if (!sharedCredentials.some((e) => credentialKey(e) === key)) {
316
- sharedCredentials.push(cred);
317
- changed = true;
318
- }
319
- }
320
- return changed;
321
- };
322
- const broadcastCredentials = async () => {
323
- await Promise.all(
324
- connectors.map((child) => Promise.resolve(child.setKnownCredentials?.(sharedCredentials)))
325
- );
326
- };
327
- for (const child of connectors) {
328
- child.on("device-trezor-thp-credentials-changed", (data) => {
329
- if (mergeShared(data.credentials)) void broadcastCredentials();
330
- });
331
- }
332
- const searchDevices = async (options = {}) => {
333
- const perConnector = [];
334
- await new Promise((resolve) => {
335
- let finished = false;
336
- let remaining = connectors.length;
337
- let settleTimer;
338
- const finish = () => {
339
- if (finished) return;
340
- finished = true;
341
- if (settleTimer) clearTimeout(settleTimer);
342
- resolve();
343
- };
344
- connectors.forEach((child, index) => {
345
- void child.searchDevices().then(
346
- (devices) => devices.map((device) => ({
347
- ...device,
348
- connectionType: device.connectionType ?? child.connectionType
349
- }))
350
- ).catch(
351
- () => (
352
- // A transport that can't scan (powered off, unauthorized, absent)
353
- // must not fail the whole fused search.
354
- []
355
- )
356
- ).then((devices) => {
357
- remaining -= 1;
358
- if (!finished) {
359
- perConnector.push({ index, devices });
360
- }
361
- if (remaining === 0) {
362
- finish();
363
- return;
364
- }
365
- const hasUsbDevice = devices.some((device) => device.connectionType === "usb");
366
- if (hasUsbDevice && !settleTimer && !options.waitForAll) {
367
- settleTimer = setTimeout(finish, SEARCH_SETTLE_AFTER_FIRST_DEVICE_MS);
368
- }
369
- });
370
- });
371
- });
372
- perConnector.sort((a, b) => a.index - b.index);
373
- deviceOwner.clear();
374
- const merged = [];
375
- perConnector.forEach(({ index, devices }) => {
376
- for (const device of devices) {
377
- deviceOwner.set(device.connectId, connectors[index]);
378
- merged.push(device);
379
- }
380
- });
381
- return merged.sort((a, b) => rank(a) - rank(b));
382
- };
383
- const resolveOwner = async (deviceId) => {
384
- if (deviceId && deviceOwner.has(deviceId)) {
385
- return { owner: deviceOwner.get(deviceId), deviceId };
386
- }
387
- const devices = await searchDevices({ waitForAll: Boolean(deviceId) });
388
- if (deviceId) {
389
- const owner = deviceOwner.get(deviceId);
390
- if (!owner)
391
- throw combinedDeviceNotFoundError(`Combined connector: device not found: ${deviceId}`);
392
- return { owner, deviceId };
393
- }
394
- const first = devices[0];
395
- if (!first) throw combinedDeviceNotFoundError("Combined connector: no devices found");
396
- return { owner: deviceOwner.get(first.connectId), deviceId: first.connectId };
397
- };
398
- const connectByExplicitId = async (deviceId) => {
399
- const cachedOwner = deviceOwner.get(deviceId);
400
- if (cachedOwner) {
401
- return { session: await cachedOwner.connect(deviceId), owner: cachedOwner };
402
- }
403
- let lastError;
404
- for (const child of connectors) {
405
- try {
406
- const session = await child.connect(deviceId);
407
- deviceOwner.set(deviceId, child);
408
- return { session, owner: child };
409
- } catch (error) {
410
- if (!isDeviceUnavailableError(error)) {
411
- throw error;
412
- }
413
- lastError = error;
414
- }
415
- }
416
- const message = lastError instanceof Error ? lastError.message : `Combined connector: device not found: ${deviceId}`;
417
- throw createHwkError({
418
- code: 10100 /* DeviceNotFound */,
419
- message
420
- });
421
- };
422
- return {
423
- // Nominal value only — the per-device `connectionType` is authoritative
424
- // for a fused connector.
425
- connectionType: connectors[0].connectionType,
426
- searchDevices: (options) => searchDevices({ waitForAll: options?.waitForAll }),
427
- connect: async (deviceId) => {
428
- let owner;
429
- let session;
430
- if (deviceId) {
431
- ({ session, owner } = await connectByExplicitId(deviceId));
432
- } else {
433
- const resolved = await resolveOwner();
434
- owner = resolved.owner;
435
- session = await owner.connect(resolved.deviceId);
436
- }
437
- sessionOwner.set(session.sessionId, owner);
438
- return session;
439
- },
440
- disconnect: async (sessionId) => {
441
- const owner = sessionOwner.get(sessionId);
442
- if (!owner) return;
443
- await owner.disconnect(sessionId);
444
- sessionOwner.delete(sessionId);
445
- },
446
- call: async (sessionId, method, params) => {
447
- const owner = sessionOwner.get(sessionId);
448
- if (!owner) {
449
- throw combinedSessionNotFoundError(`Combined connector: session not found: ${sessionId}`);
450
- }
451
- return owner.call(sessionId, method, params);
452
- },
453
- cancel: async (sessionId) => {
454
- const owner = sessionOwner.get(sessionId);
455
- if (!owner) return;
456
- await owner.cancel(sessionId);
457
- },
458
- uiResponse: (response) => {
459
- for (const child of connectors) child.uiResponse(response);
460
- },
461
- on: (event, handler) => {
462
- const attached = connectors.map((child) => {
463
- const forward = (data) => handler(data);
464
- child.on(event, forward);
465
- return { child, handler: forward };
466
- });
467
- let inner = forwarders.get(event);
468
- if (!inner) {
469
- inner = /* @__PURE__ */ new Map();
470
- forwarders.set(event, inner);
471
- }
472
- inner.set(handler, attached);
473
- },
474
- off: (event, handler) => {
475
- const inner = forwarders.get(event);
476
- const attached = inner?.get(handler);
477
- if (!attached || !inner) return;
478
- for (const { child, handler: forward } of attached) {
479
- child.off(event, forward);
480
- }
481
- inner.delete(handler);
482
- if (inner.size === 0) forwarders.delete(event);
483
- },
484
- reset: () => {
485
- for (const child of connectors) child.reset();
486
- deviceOwner.clear();
487
- sessionOwner.clear();
488
- forwarders.clear();
489
- },
490
- setKnownCredentials: connectors.some((c) => c.setKnownCredentials) ? async (credentials) => {
491
- sharedCredentials.length = 0;
492
- mergeShared(credentials ?? []);
493
- await broadcastCredentials();
494
- } : void 0
495
- };
496
- }
497
353
 
498
354
  // src/utils/TypedEventEmitter.ts
499
355
  var TypedEventEmitter = class {
@@ -525,9 +381,103 @@ var TypedEventEmitter = class {
525
381
  removeAllListeners() {
526
382
  this._listeners.clear();
527
383
  }
528
- /** Number of listeners registered for `event`. 0 if none. */
529
- listenerCount(event) {
530
- return this._listeners.get(event)?.size ?? 0;
384
+ };
385
+
386
+ // src/utils/UiRequestRegistry.ts
387
+ var UI_REQUEST_DEFAULT_TIMEOUT_MS = 6e5;
388
+ var RESPONSE_TO_REQUEST = {
389
+ [UI_RESPONSE.RECEIVE_PIN]: UI_REQUEST.REQUEST_PIN,
390
+ [UI_RESPONSE.RECEIVE_PASSPHRASE]: UI_REQUEST.REQUEST_PASSPHRASE,
391
+ [UI_RESPONSE.RECEIVE_PASSPHRASE_ON_DEVICE]: UI_REQUEST.REQUEST_PASSPHRASE_ON_DEVICE,
392
+ [UI_RESPONSE.RECEIVE_SELECT_DEVICE]: UI_REQUEST.REQUEST_SELECT_DEVICE,
393
+ [UI_RESPONSE.RECEIVE_DEVICE_CONNECT]: UI_REQUEST.REQUEST_DEVICE_CONNECT,
394
+ [UI_RESPONSE.RECEIVE_DEVICE_PERMISSION]: UI_REQUEST.REQUEST_DEVICE_PERMISSION,
395
+ [UI_RESPONSE.RECEIVE_BTC_HIGH_INDEX_CONFIRM]: UI_REQUEST.REQUEST_BTC_HIGH_INDEX_CONFIRM,
396
+ [UI_RESPONSE.RECEIVE_INSTALL_APP]: UI_REQUEST.REQUEST_INSTALL_APP
397
+ // RECEIVE_QR_RESPONSE maps to QR_DISPLAY or QR_SCAN — resolved dynamically below.
398
+ };
399
+ var UI_REQUEST_PREEMPTED_TAG = "UiRequestPreempted";
400
+ var UI_REQUEST_CANCELLED_TAG = "UiRequestCancelled";
401
+ var UI_REQUEST_TIMEOUT_TAG = "UiRequestTimeout";
402
+ var UiRequestRegistry = class {
403
+ constructor() {
404
+ this.pending = /* @__PURE__ */ new Map();
405
+ }
406
+ wait(requestType, options) {
407
+ const existing = this.pending.get(requestType);
408
+ if (existing) {
409
+ clearTimeout(existing.timer);
410
+ this.pending.delete(requestType);
411
+ existing.reject(
412
+ Object.assign(new Error(`UI request '${requestType}' was superseded by a new request`), {
413
+ _tag: UI_REQUEST_PREEMPTED_TAG
414
+ })
415
+ );
416
+ }
417
+ const timeoutMs = options?.timeoutMs ?? UI_REQUEST_DEFAULT_TIMEOUT_MS;
418
+ return new Promise((resolve, reject) => {
419
+ const timer = setTimeout(() => {
420
+ if (this.pending.get(requestType)?.timer === timer) {
421
+ this.pending.delete(requestType);
422
+ reject(
423
+ Object.assign(new Error(`UI request '${requestType}' timed out after ${timeoutMs}ms`), {
424
+ _tag: UI_REQUEST_TIMEOUT_TAG
425
+ })
426
+ );
427
+ }
428
+ }, timeoutMs);
429
+ this.pending.set(requestType, {
430
+ resolve,
431
+ reject,
432
+ timer
433
+ });
434
+ });
435
+ }
436
+ resolve(responseType, payload) {
437
+ let requestType = RESPONSE_TO_REQUEST[responseType];
438
+ if (responseType === UI_RESPONSE.RECEIVE_QR_RESPONSE) {
439
+ if (this.pending.has(UI_REQUEST.REQUEST_QR_DISPLAY)) {
440
+ requestType = UI_REQUEST.REQUEST_QR_DISPLAY;
441
+ } else if (this.pending.has(UI_REQUEST.REQUEST_QR_SCAN)) {
442
+ requestType = UI_REQUEST.REQUEST_QR_SCAN;
443
+ }
444
+ }
445
+ if (!requestType) return;
446
+ const entry = this.pending.get(requestType);
447
+ if (!entry) return;
448
+ clearTimeout(entry.timer);
449
+ this.pending.delete(requestType);
450
+ entry.resolve(payload);
451
+ }
452
+ cancel(requestType) {
453
+ if (requestType) {
454
+ const entry = this.pending.get(requestType);
455
+ if (!entry) return;
456
+ clearTimeout(entry.timer);
457
+ this.pending.delete(requestType);
458
+ entry.reject(
459
+ Object.assign(new Error(`UI request '${requestType}' was cancelled`), {
460
+ _tag: UI_REQUEST_CANCELLED_TAG
461
+ })
462
+ );
463
+ return;
464
+ }
465
+ for (const [type, entry] of this.pending) {
466
+ clearTimeout(entry.timer);
467
+ entry.reject(
468
+ Object.assign(new Error(`UI request '${type}' was cancelled`), {
469
+ _tag: UI_REQUEST_CANCELLED_TAG
470
+ })
471
+ );
472
+ }
473
+ this.pending.clear();
474
+ }
475
+ reset() {
476
+ this.cancel();
477
+ }
478
+ hasPending(requestType) {
479
+ if (requestType) return this.pending.has(requestType);
480
+ return this.pending.size > 0;
531
481
  }
532
482
  };
533
483
 
@@ -562,37 +512,64 @@ function bytesToHex2(bytes) {
562
512
  return nobleBytesToHex(bytes);
563
513
  }
564
514
 
565
- // src/utils/deviceIdentity.ts
566
- var ONEKEY_BLE_SERVICE_UUID = "00000001-0000-1000-8000-00805f9b34fb";
567
- var TREZOR_BLE_SERVICE_UUID = "8c000001-a59b-4d58-a9ad-073df69fa1b1";
568
- var LEDGER_USB_VENDOR_ID = 11415;
569
- var lower = (value) => value?.trim().toLowerCase() ?? "";
570
- var hasServiceUuid = (input, uuid) => {
571
- const expected = uuid.toLowerCase();
572
- const values = [
573
- ...input.serviceUUIDs ?? [],
574
- ...input.advertisedServiceUuids ?? [],
575
- ...input.serviceUuids ?? []
576
- ];
577
- return values.some((value) => value.toLowerCase() === expected);
578
- };
579
- function detectHardwareVendorFromDescriptor(input) {
580
- const manufacturerName = lower(input.manufacturerName);
581
- const fwVendor = lower(input.fw_vendor);
582
- if (hasServiceUuid(input, ONEKEY_BLE_SERVICE_UUID) || manufacturerName.includes("onekey") || fwVendor === "onekey" || input.onekey_version || input.onekey_device_type || input.onekey_serial) {
583
- return "onekey";
584
- }
585
- if (hasServiceUuid(input, TREZOR_BLE_SERVICE_UUID) || manufacturerName.includes("trezor") || fwVendor === "trezor") {
586
- return "trezor";
587
- }
588
- if (typeof input.vendor === "number" && input.vendor === LEDGER_USB_VENDOR_ID || input.vendorId === LEDGER_USB_VENDOR_ID || manufacturerName.includes("ledger")) {
589
- return "ledger";
515
+ // src/utils/errorMessages.ts
516
+ function enrichErrorMessage(code, originalMessage) {
517
+ switch (code) {
518
+ case 10400 /* PinInvalid */:
519
+ return `${originalMessage}. Please re-enter your PIN.`;
520
+ case 10401 /* PinCancelled */:
521
+ return `${originalMessage}. PIN entry was cancelled.`;
522
+ case 10102 /* DeviceBusy */:
523
+ return `${originalMessage}. The device is in use by another application. Close other wallet apps and try again.`;
524
+ case 10101 /* DeviceDisconnected */:
525
+ return `${originalMessage}. Please reconnect the device and try again.`;
526
+ case 10103 /* DeviceLocked */:
527
+ return `${originalMessage}. Please unlock your device and try again.`;
528
+ case 10109 /* DeviceOneDeviceOnly */:
529
+ return `${originalMessage}. Disconnect the extra device and try again.`;
530
+ case 10001 /* UserRejected */:
531
+ return `${originalMessage}. The request was rejected on the device.`;
532
+ case 10501 /* WrongApp */:
533
+ return `${originalMessage}. Please open the correct app on your device.`;
534
+ case 10500 /* AppNotInstalled */:
535
+ return `${originalMessage}. The required app is not installed on the device.`;
536
+ case 10503 /* DeviceOutOfMemory */:
537
+ return `${originalMessage}. Not enough free space on the device. Please uninstall some apps and try again.`;
538
+ case 10302 /* TransportNotAvailable */:
539
+ return `${originalMessage}. Ensure the device bridge/transport is available and running.`;
540
+ case 10305 /* NetworkError */:
541
+ return `${originalMessage}. Network error \u2014 check your internet connection and try again.`;
542
+ case 10200 /* FirmwareTooOld */:
543
+ return `${originalMessage}. Please update your device firmware.`;
544
+ case 10104 /* DeviceNotInitialized */:
545
+ return `${originalMessage}. The device may need to be set up first.`;
546
+ case 10003 /* OperationTimeout */:
547
+ return `${originalMessage}. The operation timed out. Please try again.`;
548
+ case 11e3 /* EvmBlindSigningRequired */:
549
+ return "Ledger: Blind signing not enabled in Ethereum app.";
550
+ case 11001 /* EvmClearSignPluginMissing */:
551
+ return "Ledger: Required plugin not installed (install via Ledger Live).";
552
+ case 11002 /* EvmDataTooLarge */:
553
+ return "Ledger: Transaction data too large for device memory.";
554
+ case 11003 /* EvmTxTypeNotSupported */:
555
+ return "Ledger: Transaction type not supported by current Ethereum app.";
556
+ case 10502 /* AppTooOld */:
557
+ return "Ledger: App out of date (update via Ledger Live).";
558
+ case 11100 /* SolanaBlindSigningRequired */:
559
+ return "Blind signing disabled in the Solana app.";
560
+ case 11200 /* TronCustomContractRequired */:
561
+ return "Custom Contracts setting disabled in the Tron app.";
562
+ case 11201 /* TronDataSigningRequired */:
563
+ return "Transactions Data setting disabled in the Tron app.";
564
+ case 11202 /* TronSignByHashRequired */:
565
+ return "Sign by Hash setting disabled in the Tron app.";
566
+ case 11300 /* BtcWalletPolicyHmacMismatch */:
567
+ return "Wallet policy not registered or HMAC mismatch.";
568
+ case 11301 /* BtcUnexpectedState */:
569
+ return "Signing aborted due to unexpected device state.";
570
+ default:
571
+ return originalMessage;
590
572
  }
591
- return void 0;
592
- }
593
- function isKnownNonTargetHardwareVendor(input, targetVendor) {
594
- const detectedVendor = detectHardwareVendorFromDescriptor(input);
595
- return detectedVendor !== void 0 && detectedVendor !== targetVendor;
596
573
  }
597
574
 
598
575
  // src/utils/batchCall.ts
@@ -608,123 +585,12 @@ async function batchCall(params, callFn, onProgress) {
608
585
  }
609
586
  return { success: true, payload: results };
610
587
  }
611
-
612
- // src/utils/methodCatalog.ts
613
- var HARDWARE_METHOD_CATALOG = {
614
- evmGetAddress: { chain: "evm", allNetwork: true },
615
- evmSignTransaction: { chain: "evm", allNetwork: false },
616
- evmSignMessage: { chain: "evm", allNetwork: false },
617
- evmSignTypedData: { chain: "evm", allNetwork: false },
618
- btcGetAddress: { chain: "btc", allNetwork: true },
619
- btcGetPublicKey: { chain: "btc", allNetwork: true },
620
- btcSignTransaction: { chain: "btc", allNetwork: false },
621
- btcSignPsbt: { chain: "btc", allNetwork: false },
622
- btcSignMessage: { chain: "btc", allNetwork: false },
623
- btcGetMasterFingerprint: { chain: "btc", allNetwork: false },
624
- solGetAddress: { chain: "sol", allNetwork: true },
625
- solSignTransaction: { chain: "sol", allNetwork: false },
626
- solSignMessage: { chain: "sol", allNetwork: false },
627
- tronGetAddress: { chain: "tron", allNetwork: true },
628
- tronSignTransaction: { chain: "tron", allNetwork: false },
629
- tronSignMessage: { chain: "tron", allNetwork: false }
630
- };
631
- var ALL_NETWORK_METHOD_NAMES = Object.entries(HARDWARE_METHOD_CATALOG).filter(([, metadata]) => metadata.allNetwork).map(([method]) => method);
632
- var ALL_NETWORK_METHOD_SET = new Set(ALL_NETWORK_METHOD_NAMES);
633
- function getHardwareMethodMetadata(method) {
634
- return HARDWARE_METHOD_CATALOG[method];
635
- }
636
- function isAllNetworkMethodName(method) {
637
- return ALL_NETWORK_METHOD_SET.has(method);
638
- }
639
- function getAllNetworkMethodChain(method) {
640
- return HARDWARE_METHOD_CATALOG[method].chain;
641
- }
642
-
643
- // src/utils/allNetwork.ts
644
- async function runAllNetworkGetAddress({
645
- connectId,
646
- deviceId,
647
- params,
648
- getMethodChain = (method) => getAllNetworkMethodChain(method),
649
- normalizeItem = (_method, item) => item,
650
- buildUnsupportedNetworkResponse,
651
- callItem,
652
- attachIdentity,
653
- shouldAbortBundle = () => false,
654
- buildTopLevelFailure = defaultBuildTopLevelFailure
655
- }) {
656
- const responses = [];
657
- for (const [index, item] of params.bundle.entries()) {
658
- if (!isAllNetworkMethodName(String(item.methodName))) {
659
- responses.push(buildUnsupportedMethodResponse(item));
660
- continue;
661
- }
662
- const method = item.methodName;
663
- const unsupportedNetwork = buildUnsupportedNetworkResponse?.(item, method);
664
- if (unsupportedNetwork) {
665
- responses.push(unsupportedNetwork);
666
- continue;
667
- }
668
- const chain = getMethodChain(method, item);
669
- const normalizedItem = normalizeItem(method, item);
670
- const context = {
671
- connectId,
672
- deviceId,
673
- method,
674
- chain,
675
- item: normalizedItem,
676
- index
677
- };
678
- const response = await callItem(context);
679
- const itemResponse = response.success ? await attachIdentity({
680
- ...context,
681
- payload: response.payload
682
- }) : {
683
- ...normalizedItem,
684
- success: false,
685
- payload: response.payload
686
- };
687
- const responseContext = { ...context, response: itemResponse };
688
- if (!itemResponse.success && shouldAbortBundle(itemResponse, responseContext)) {
689
- return buildTopLevelFailure(itemResponse, responseContext);
690
- }
691
- responses.push(itemResponse);
692
- }
693
- return success(responses);
694
- }
695
- function buildUnsupportedMethodResponse(item) {
696
- return {
697
- ...item,
698
- success: false,
699
- payload: {
700
- code: 10002 /* InvalidParams */,
701
- error: `Unsupported allNetwork method: ${String(item.methodName)}`
702
- }
703
- };
704
- }
705
- function defaultBuildTopLevelFailure(response) {
706
- const payload = response.payload ?? {};
707
- return failure(
708
- payload.code ?? 10106 /* DeviceMismatch */,
709
- payload.error ?? "All-network get-address aborted",
710
- normalizeFailureParams(payload.params)
711
- );
712
- }
713
- function normalizeFailureParams(params) {
714
- return params && typeof params === "object" ? params : void 0;
715
- }
716
-
717
- // src/constants.ts
718
- var DEVICE_CONNECT_RETRY_DELAY_MS = 1e3;
719
588
  export {
720
- ALL_NETWORK_METHOD_NAMES,
721
589
  CHAIN_FINGERPRINT_PATHS,
722
590
  DEVICE,
723
- DEVICE_CONNECT_RETRY_DELAY_MS,
724
591
  DEVICE_EVENT,
725
592
  DeviceJobQueue,
726
593
  EConnectorInteraction,
727
- HARDWARE_METHOD_CATALOG,
728
594
  HardwareErrorCode,
729
595
  ORPHAN_ELIGIBLE_ERROR_CODES,
730
596
  SDK,
@@ -738,25 +604,17 @@ export {
738
604
  UI_RESPONSE,
739
605
  UiRequestRegistry,
740
606
  batchCall,
741
- buildUnsupportedMethodResponse,
742
607
  bytesToHex2 as bytesToHex,
743
608
  compareSemver,
744
609
  createBridgedConnector,
745
- createCombinedConnector,
746
610
  createHwkError,
747
611
  deriveDeviceFingerprint,
748
- detectHardwareVendorFromDescriptor,
749
612
  enrichErrorMessage,
750
613
  ensure0x,
751
614
  failure,
752
- getAllNetworkMethodChain,
753
- getHardwareMethodMetadata,
754
615
  hexToBytes,
755
- isAllNetworkMethodName,
756
- isKnownNonTargetHardwareVendor,
757
616
  padHex64,
758
617
  rehydrateConnectorError,
759
- runAllNetworkGetAddress,
760
618
  serializeConnectorError,
761
619
  stripHex,
762
620
  success