@onekeyfe/hwk-ledger-adapter 1.1.27-alpha.6 → 1.1.27-patch.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -53,7 +53,7 @@ __export(index_exports, {
53
53
  module.exports = __toCommonJS(index_exports);
54
54
 
55
55
  // src/adapter/LedgerAdapter.ts
56
- var import_hwk_adapter_core2 = require("@onekeyfe/hwk-adapter-core");
56
+ var import_hwk_adapter_core3 = require("@onekeyfe/hwk-adapter-core");
57
57
 
58
58
  // src/errors.ts
59
59
  var import_hwk_adapter_core = require("@onekeyfe/hwk-adapter-core");
@@ -75,30 +75,37 @@ var USER_REJECTED_CODES = /* @__PURE__ */ new Set(["6985", "27013"]);
75
75
  var WRONG_APP_CODES = /* @__PURE__ */ new Set(["6e00", "28160", "6d00", "27904", "6a83", "27267"]);
76
76
  var APP_NOT_INSTALLED_CODES = /* @__PURE__ */ new Set(["6807", "26631"]);
77
77
  var STEP_BLIND_SIGN_TRANSACTION_FALLBACK = "signer.eth.steps.blindSignTransactionFallback";
78
+ var STEP_DETECT_BLIND_SIGNING = "signer.eth.steps.detectBlindSigning";
79
+ var BLIND_SIGNING_STEPS = /* @__PURE__ */ new Set([
80
+ STEP_BLIND_SIGN_TRANSACTION_FALLBACK,
81
+ STEP_DETECT_BLIND_SIGNING
82
+ ]);
83
+ function normalizeApduHex(value) {
84
+ if (typeof value === "number" && Number.isInteger(value) && value >= 0 && value <= 65535) {
85
+ return value.toString(16).padStart(4, "0");
86
+ }
87
+ if (typeof value !== "string") return null;
88
+ const raw = value.toLowerCase().replace(/^0x/, "");
89
+ return /^[0-9a-f]{1,4}$/i.test(raw) ? raw.padStart(4, "0") : null;
90
+ }
78
91
  function getEthAppErrorCode(err) {
79
92
  if (!err || typeof err !== "object") return null;
80
93
  const e = err;
81
- if (e._tag === ERROR_TAG.EthAppCommand && typeof e.errorCode === "string") {
82
- return e.errorCode.toLowerCase();
94
+ if (e._tag === ERROR_TAG.EthAppCommand) {
95
+ const code = normalizeApduHex(e.errorCode) ?? normalizeApduHex(e.statusCode) ?? normalizeApduHex(e.code);
96
+ if (code) return code;
83
97
  }
84
98
  const orig = e.originalError;
85
- if (orig?._tag === ERROR_TAG.EthAppCommand && typeof orig.errorCode === "string") {
86
- return orig.errorCode.toLowerCase();
99
+ if (orig?._tag === ERROR_TAG.EthAppCommand) {
100
+ return normalizeApduHex(orig.errorCode) ?? normalizeApduHex(orig.statusCode) ?? normalizeApduHex(orig.code);
87
101
  }
88
102
  return null;
89
103
  }
90
104
  function extractApduHex(err) {
91
105
  if (!err || typeof err !== "object") return null;
92
106
  const e = err;
93
- if (typeof e.errorCode === "string" && /^[0-9a-f]+$/i.test(e.errorCode)) {
94
- return e.errorCode.toLowerCase();
95
- }
96
- if (typeof e.statusCode === "number" && Number.isFinite(e.statusCode)) {
97
- return e.statusCode.toString(16).padStart(4, "0");
98
- }
99
- if (typeof e.statusCode === "string" && /^[0-9a-f]+$/i.test(e.statusCode)) {
100
- return e.statusCode.toLowerCase();
101
- }
107
+ const direct = normalizeApduHex(e.errorCode) ?? normalizeApduHex(e.statusCode);
108
+ if (direct) return direct;
102
109
  if (e.originalError != null) {
103
110
  const nested = extractApduHex(e.originalError);
104
111
  if (nested) return nested;
@@ -157,10 +164,15 @@ function classifyEthAppError(err) {
157
164
  const ethCode = getEthAppErrorCode(err);
158
165
  if (!ethCode) return null;
159
166
  if (ethCode === "6a80") {
160
- return hasBlindSignFallbackStep(err) ? import_hwk_adapter_core.HardwareErrorCode.EvmBlindSigningRequired : null;
167
+ return hasBlindSigningStep(err) ? import_hwk_adapter_core.HardwareErrorCode.EvmBlindSigningRequired : null;
161
168
  }
162
169
  return mapEthAppErrorCode(ethCode);
163
170
  }
171
+ function classifyBlindSigningDetectionError(err) {
172
+ if (!hasBlindSigningStep(err)) return null;
173
+ if (hasInvalidArgumentCode(err)) return import_hwk_adapter_core.HardwareErrorCode.EvmBlindSigningRequired;
174
+ return null;
175
+ }
164
176
  var ERROR_TAG = {
165
177
  // SDK-mint
166
178
  DeviceNotAdvertising: "DeviceNotAdvertisingError",
@@ -176,6 +188,10 @@ var ERROR_TAG = {
176
188
  // chain app wedged (APDU 0x6901)
177
189
  DeviceTransportStuck: "DeviceTransportStuck",
178
190
  // DMK transport queue wedged
191
+ // installApp resolved success but the app is still missing on device —
192
+ // DMK quirk. Surfaced as a distinct tag so callers can tell it apart from
193
+ // the original DMK-thrown AppNotInstalled.
194
+ AppInstallVerifyFailed: "AppInstallVerifyFailedError",
179
195
  // DMK-reuse (DMK throws same string; we synthesize too)
180
196
  DeviceLocked: "DeviceLockedError",
181
197
  DeviceNotRecognized: "DeviceNotRecognizedError",
@@ -201,7 +217,11 @@ var ERROR_TAG = {
201
217
  // ble-plx surfaces this when GATT notification setup fails — typical
202
218
  // outcome when the user doesn't confirm pairing on the device, or the
203
219
  // existing bond is invalid. Observed in production after ~30s.
204
- PairingRefused: "PairingRefusedError"
220
+ PairingRefused: "PairingRefusedError",
221
+ // DMK remote-network failures (manager-api HTTP / secure-channel WS).
222
+ WebSocketConnection: "WebSocketConnectionError",
223
+ HttpFetch: "FetchError",
224
+ InvalidFirmwareMetadataResponse: "InvalidGetFirmwareMetadataResponseError"
205
225
  };
206
226
  function isDeviceLockedError(err) {
207
227
  if (!err || typeof err !== "object") return false;
@@ -289,15 +309,30 @@ function hasStatusCode(err, codeSet) {
289
309
  if (e.error != null && e._tag && hasStatusCode(e.error, codeSet)) return true;
290
310
  return false;
291
311
  }
292
- function hasBlindSignFallbackStep(err) {
312
+ function hasDeviceActionStep(err, step) {
293
313
  if (!err || typeof err !== "object") return false;
294
314
  const e = err;
295
- if (e._lastStep === STEP_BLIND_SIGN_TRANSACTION_FALLBACK) return true;
296
- if (Array.isArray(e._deviceActionSteps) && e._deviceActionSteps.includes(STEP_BLIND_SIGN_TRANSACTION_FALLBACK)) {
315
+ if (e._lastStep === step) return true;
316
+ if (Array.isArray(e._deviceActionSteps) && e._deviceActionSteps.includes(step)) {
297
317
  return true;
298
318
  }
299
- if (e.originalError != null && hasBlindSignFallbackStep(e.originalError)) return true;
300
- if (e.error != null && e._tag && hasBlindSignFallbackStep(e.error)) return true;
319
+ if (e.originalError != null && hasDeviceActionStep(e.originalError, step)) return true;
320
+ if (e.error != null && e._tag && hasDeviceActionStep(e.error, step)) return true;
321
+ return false;
322
+ }
323
+ function hasBlindSigningStep(err) {
324
+ for (const step of BLIND_SIGNING_STEPS) {
325
+ if (hasDeviceActionStep(err, step)) return true;
326
+ }
327
+ return false;
328
+ }
329
+ function hasInvalidArgumentCode(err) {
330
+ if (!err || typeof err !== "object") return false;
331
+ const e = err;
332
+ if (e.code === "INVALID_ARGUMENT") return true;
333
+ if (typeof e.message === "string" && e.message.includes("code=INVALID_ARGUMENT")) return true;
334
+ if (e.originalError != null && hasInvalidArgumentCode(e.originalError)) return true;
335
+ if (e.error != null && e._tag && hasInvalidArgumentCode(e.error)) return true;
301
336
  return false;
302
337
  }
303
338
  function isDeviceNotFoundError(err) {
@@ -326,6 +361,11 @@ function isUserRejectedError(err) {
326
361
  if (hasStatusCode(err, USER_REJECTED_CODES)) return true;
327
362
  return false;
328
363
  }
364
+ function isUserAbortedError(err) {
365
+ if (!err || typeof err !== "object") return false;
366
+ const e = err;
367
+ return e._tag === ERROR_TAG.UserAborted;
368
+ }
329
369
  function isWrongAppError(err) {
330
370
  if (!err || typeof err !== "object") return false;
331
371
  const e = err;
@@ -352,6 +392,20 @@ function isOutOfMemoryError(err) {
352
392
  const e = err;
353
393
  return e._tag === "OutOfMemoryDAError";
354
394
  }
395
+ var NETWORK_ERROR_TAGS = /* @__PURE__ */ new Set([
396
+ ERROR_TAG.WebSocketConnection,
397
+ ERROR_TAG.HttpFetch,
398
+ ERROR_TAG.InvalidFirmwareMetadataResponse
399
+ ]);
400
+ function isNetworkError(err) {
401
+ if (!err || typeof err !== "object") return false;
402
+ const e = err;
403
+ const tag = e._tag;
404
+ if (typeof tag === "string" && NETWORK_ERROR_TAGS.has(tag)) return true;
405
+ if (e.originalError != null && isNetworkError(e.originalError)) return true;
406
+ if (e.error != null && isNetworkError(e.error)) return true;
407
+ return false;
408
+ }
355
409
  function isDeviceDisconnectedError(err) {
356
410
  if (!err || typeof err !== "object") return false;
357
411
  const e = err;
@@ -408,6 +462,8 @@ function mapLedgerError(err, opts) {
408
462
  code = import_hwk_adapter_core.HardwareErrorCode.DeviceBusy;
409
463
  } else if (isBlePairingFailureError(err)) {
410
464
  code = import_hwk_adapter_core.HardwareErrorCode.BlePairingTimeout;
465
+ } else if (isUserAbortedError(err)) {
466
+ code = import_hwk_adapter_core.HardwareErrorCode.UserAborted;
411
467
  } else if (isUserRejectedError(err)) {
412
468
  code = import_hwk_adapter_core.HardwareErrorCode.UserRejected;
413
469
  } else if (isWrongAppError(err)) {
@@ -416,12 +472,14 @@ function mapLedgerError(err, opts) {
416
472
  code = import_hwk_adapter_core.HardwareErrorCode.AppNotInstalled;
417
473
  } else if (isOutOfMemoryError(err)) {
418
474
  code = import_hwk_adapter_core.HardwareErrorCode.DeviceOutOfMemory;
475
+ } else if (isNetworkError(err)) {
476
+ code = import_hwk_adapter_core.HardwareErrorCode.NetworkError;
419
477
  } else if (isDeviceDisconnectedError(err)) {
420
478
  code = import_hwk_adapter_core.HardwareErrorCode.DeviceDisconnected;
421
479
  } else if (isTimeoutError(err)) {
422
480
  code = import_hwk_adapter_core.HardwareErrorCode.OperationTimeout;
423
481
  } else {
424
- const ethMapped = classifyEthAppError(err);
482
+ const ethMapped = classifyEthAppError(err) ?? classifyBlindSigningDetectionError(err);
425
483
  const apduHex = ethMapped ? null : extractApduHex(err);
426
484
  const chainMapped = apduHex ? mapSolanaAppError(apduHex) ?? mapTronAppError(apduHex) ?? mapBtcAppError(apduHex) : null;
427
485
  code = ethMapped ?? chainMapped ?? import_hwk_adapter_core.HardwareErrorCode.UnknownError;
@@ -431,17 +489,8 @@ function mapLedgerError(err, opts) {
431
489
  return { code, message: (0, import_hwk_adapter_core.enrichErrorMessage)(code, originalMessage), appName };
432
490
  }
433
491
 
434
- // src/utils/ledgerDmkTransport.ts
435
- function isLedgerDmkBleTransport(transport) {
436
- const normalized = transport?.toUpperCase();
437
- return normalized === "BLE" || normalized?.endsWith("_BLE") === true;
438
- }
439
- function isLedgerBleConnectionType(connectionType) {
440
- return connectionType === "ble";
441
- }
442
- function isLedgerBleDescriptor(connectionType, descriptor) {
443
- return isLedgerBleConnectionType(connectionType) || isLedgerDmkBleTransport(descriptor.transport);
444
- }
492
+ // src/adapter/methods/allNetworkGetAddress.ts
493
+ var import_hwk_adapter_core2 = require("@onekeyfe/hwk-adapter-core");
445
494
 
446
495
  // src/utils/sdkEventBus.ts
447
496
  var listeners = /* @__PURE__ */ new Set();
@@ -488,6 +537,252 @@ function debugError(...args) {
488
537
  emitLog("error", ...args);
489
538
  }
490
539
 
540
+ // src/adapter/methods/allNetworkGetAddress.ts
541
+ var LEDGER_BTC_NETWORK_COIN_MAP = {
542
+ tbtc: "Testnet",
543
+ bch: "Bcash",
544
+ doge: "Dogecoin",
545
+ ltc: "Litecoin",
546
+ neurai: "Neurai"
547
+ };
548
+ function createAllNetworkGetAddress({
549
+ callChain,
550
+ getChainFingerprint
551
+ }) {
552
+ return async function allNetworkGetAddress(connectId, _deviceId, params) {
553
+ debugLog("[LedgerAdapter][REQ]", { method: "allNetworkGetAddress", connectId, params });
554
+ const installContext = {};
555
+ const commonParams = {
556
+ autoInstallApp: params.autoInstallApp
557
+ };
558
+ const responses = [];
559
+ const chainFingerprints = /* @__PURE__ */ new Map();
560
+ for (const item of params.bundle) {
561
+ const method = getAllNetworkMethod(item);
562
+ if (!method) {
563
+ responses.push(buildUnsupportedMethodResponse(item));
564
+ } else {
565
+ const chain = getFingerprintChain(method);
566
+ const itemDeviceId = getItemDeviceId(item) ?? chainFingerprints.get(chain) ?? "";
567
+ const normalizedItem = normalizeLedgerAllNetworkItem(method, item);
568
+ const response = await callAllNetworkItem(
569
+ callChain,
570
+ getChainFingerprint,
571
+ connectId,
572
+ itemDeviceId,
573
+ chain,
574
+ method,
575
+ normalizedItem,
576
+ commonParams,
577
+ installContext,
578
+ chainFingerprints
579
+ );
580
+ if (isTopLevelAllNetworkFailure(response)) {
581
+ const code = response.payload?.code ?? import_hwk_adapter_core2.HardwareErrorCode.DeviceMismatch;
582
+ const result2 = (0, import_hwk_adapter_core2.failure)(
583
+ code,
584
+ response.payload?.error ?? "All-network get-address aborted",
585
+ response.payload?.params
586
+ );
587
+ debugLog("[LedgerAdapter][RES]", {
588
+ method: "allNetworkGetAddress",
589
+ success: false,
590
+ payload: result2
591
+ });
592
+ return result2;
593
+ }
594
+ responses.push(response);
595
+ }
596
+ }
597
+ const result = (0, import_hwk_adapter_core2.success)(responses);
598
+ debugLog("[LedgerAdapter][RES]", {
599
+ method: "allNetworkGetAddress",
600
+ success: true,
601
+ payload: result
602
+ });
603
+ return result;
604
+ };
605
+ }
606
+ function isTopLevelAllNetworkFailure(response) {
607
+ if (response.success) {
608
+ return false;
609
+ }
610
+ const code = response.payload?.code;
611
+ return code === import_hwk_adapter_core2.HardwareErrorCode.DeviceMismatch || code === import_hwk_adapter_core2.HardwareErrorCode.UserAborted || code === import_hwk_adapter_core2.HardwareErrorCode.UserRejected;
612
+ }
613
+ function getItemDeviceId(item) {
614
+ const { deviceId } = item;
615
+ return typeof deviceId === "string" && deviceId.length > 0 ? deviceId : void 0;
616
+ }
617
+ function getAllNetworkMethod(item) {
618
+ switch (item.methodName) {
619
+ case "evmGetAddress":
620
+ case "btcGetAddress":
621
+ case "btcGetPublicKey":
622
+ case "solGetAddress":
623
+ case "tronGetAddress":
624
+ return item.methodName;
625
+ default:
626
+ return void 0;
627
+ }
628
+ }
629
+ function buildUnsupportedMethodResponse(item) {
630
+ return {
631
+ ...item,
632
+ success: false,
633
+ payload: {
634
+ code: import_hwk_adapter_core2.HardwareErrorCode.InvalidParams,
635
+ error: `Unsupported allNetwork method: ${String(item.methodName)}`
636
+ }
637
+ };
638
+ }
639
+ function normalizeLedgerAllNetworkItem(method, item) {
640
+ if (method !== "btcGetAddress" && method !== "btcGetPublicKey") {
641
+ return item;
642
+ }
643
+ const itemWithCoin = item;
644
+ if (itemWithCoin.coin) {
645
+ return item;
646
+ }
647
+ const coin = LEDGER_BTC_NETWORK_COIN_MAP[item.network];
648
+ return coin ? { ...item, coin } : item;
649
+ }
650
+ async function callAllNetworkItem(callChain, getChainFingerprint, connectId, deviceId, chain, method, item, commonParams, installContext, chainFingerprints) {
651
+ const response = await callAllNetworkMethod(
652
+ callChain,
653
+ connectId,
654
+ deviceId,
655
+ method,
656
+ item,
657
+ commonParams,
658
+ installContext
659
+ );
660
+ if (!response.success) {
661
+ return { ...item, success: false, payload: response.payload };
662
+ }
663
+ const payload = response.payload;
664
+ const fingerprint = deviceId || chainFingerprints.get(chain) || await bootstrapChainFingerprint(getChainFingerprint, connectId, chain);
665
+ if (!fingerprint) {
666
+ return buildFingerprintBootstrapFailure(item, chain);
667
+ }
668
+ chainFingerprints.set(chain, fingerprint);
669
+ return {
670
+ ...item,
671
+ success: true,
672
+ payload: {
673
+ ...payload,
674
+ chainFingerprint: fingerprint,
675
+ chainFingerprintChain: chain
676
+ }
677
+ };
678
+ }
679
+ async function bootstrapChainFingerprint(getChainFingerprint, connectId, chain) {
680
+ const response = await getChainFingerprint(connectId, chain);
681
+ return response.success ? response.payload : "";
682
+ }
683
+ function buildFingerprintBootstrapFailure(item, chain) {
684
+ return {
685
+ ...item,
686
+ success: false,
687
+ payload: {
688
+ code: import_hwk_adapter_core2.HardwareErrorCode.DeviceMismatch,
689
+ error: `Could not establish chain fingerprint for ${chain} after device call; refusing to return unverifiable result. Please retry.`
690
+ }
691
+ };
692
+ }
693
+ function getFingerprintChain(method) {
694
+ switch (method) {
695
+ case "evmGetAddress":
696
+ return "evm";
697
+ case "btcGetAddress":
698
+ case "btcGetPublicKey":
699
+ return "btc";
700
+ case "solGetAddress":
701
+ return "sol";
702
+ case "tronGetAddress":
703
+ return "tron";
704
+ default:
705
+ throw Object.assign(new Error(`Unsupported allNetwork method: ${method}`), {
706
+ code: import_hwk_adapter_core2.HardwareErrorCode.InvalidParams
707
+ });
708
+ }
709
+ }
710
+ async function callAllNetworkMethod(callChain, connectId, deviceId, method, item, commonParams, installContext) {
711
+ switch (method) {
712
+ case "evmGetAddress":
713
+ return callChain(
714
+ connectId,
715
+ deviceId,
716
+ "evm",
717
+ "evmGetAddress",
718
+ item,
719
+ commonParams,
720
+ false,
721
+ installContext
722
+ );
723
+ case "btcGetAddress":
724
+ return callChain(
725
+ connectId,
726
+ deviceId,
727
+ "btc",
728
+ "btcGetAddress",
729
+ item,
730
+ commonParams,
731
+ false,
732
+ installContext
733
+ );
734
+ case "btcGetPublicKey":
735
+ return callChain(
736
+ connectId,
737
+ deviceId,
738
+ "btc",
739
+ "btcGetPublicKey",
740
+ item,
741
+ commonParams,
742
+ false,
743
+ installContext
744
+ );
745
+ case "solGetAddress":
746
+ return callChain(
747
+ connectId,
748
+ deviceId,
749
+ "sol",
750
+ "solGetAddress",
751
+ item,
752
+ commonParams,
753
+ false,
754
+ installContext
755
+ );
756
+ case "tronGetAddress":
757
+ return callChain(
758
+ connectId,
759
+ deviceId,
760
+ "tron",
761
+ "tronGetAddress",
762
+ item,
763
+ commonParams,
764
+ false,
765
+ installContext
766
+ );
767
+ default:
768
+ throw Object.assign(new Error(`Unsupported allNetwork method: ${method}`), {
769
+ code: import_hwk_adapter_core2.HardwareErrorCode.InvalidParams
770
+ });
771
+ }
772
+ }
773
+
774
+ // src/utils/ledgerDmkTransport.ts
775
+ function isLedgerDmkBleTransport(transport) {
776
+ const normalized = transport?.toUpperCase();
777
+ return normalized === "BLE" || normalized?.endsWith("_BLE") === true;
778
+ }
779
+ function isLedgerBleConnectionType(connectionType) {
780
+ return connectionType === "ble";
781
+ }
782
+ function isLedgerBleDescriptor(connectionType, descriptor) {
783
+ return isLedgerBleConnectionType(connectionType) || isLedgerDmkBleTransport(descriptor.transport);
784
+ }
785
+
491
786
  // src/adapter/LedgerAdapter.ts
492
787
  function formatDeviceMismatchError(expected, actual) {
493
788
  return `Wrong device: expected ${expected}, got ${actual}`;
@@ -503,10 +798,10 @@ function btcAccountIndexFromPath(path) {
503
798
  var _LedgerAdapter = class _LedgerAdapter {
504
799
  constructor(connector, options) {
505
800
  this.vendor = "ledger";
506
- this.emitter = new import_hwk_adapter_core2.TypedEventEmitter();
801
+ this.emitter = new import_hwk_adapter_core3.TypedEventEmitter();
507
802
  this._discoveredDevices = /* @__PURE__ */ new Map();
508
803
  this._sessions = /* @__PURE__ */ new Map();
509
- this._uiRegistry = new import_hwk_adapter_core2.UiRequestRegistry();
804
+ this._uiRegistry = new import_hwk_adapter_core3.UiRequestRegistry();
510
805
  // BTC App rejects account index >= 100 unless display=true. Cached per
511
806
  // adapter instance: first 100+ path asks the user once via UI request,
512
807
  // subsequent 100+ paths in the same session auto-promote silently.
@@ -515,6 +810,11 @@ var _LedgerAdapter = class _LedgerAdapter {
515
810
  this._btcHighIndexConfirmedThisSession = false;
516
811
  // Shared across concurrent callers — only `cancel()` aborts.
517
812
  this._doConnectAbortController = null;
813
+ this._installProgressLastEmittedValue = -Infinity;
814
+ this.allNetworkGetAddress = createAllNetworkGetAddress({
815
+ callChain: this.callChain.bind(this),
816
+ getChainFingerprint: (connectId, chain) => this.getChainFingerprint(connectId, "", chain)
817
+ });
518
818
  // ---------------------------------------------------------------------------
519
819
  // Private helpers
520
820
  // ---------------------------------------------------------------------------
@@ -534,16 +834,16 @@ var _LedgerAdapter = class _LedgerAdapter {
534
834
  const deviceInfo = this.connectorDeviceToDeviceInfo(data.device);
535
835
  this._discoveredDevices.set(deviceInfo.connectId, deviceInfo);
536
836
  this._sessions.delete(deviceInfo.connectId);
537
- this.emitter.emit(import_hwk_adapter_core2.DEVICE.CONNECT, {
538
- type: import_hwk_adapter_core2.DEVICE.CONNECT,
837
+ this.emitter.emit(import_hwk_adapter_core3.DEVICE.CONNECT, {
838
+ type: import_hwk_adapter_core3.DEVICE.CONNECT,
539
839
  payload: deviceInfo
540
840
  });
541
841
  };
542
842
  this.deviceDisconnectHandler = (data) => {
543
843
  this._discoveredDevices.delete(data.connectId);
544
844
  this._sessions.delete(data.connectId);
545
- this.emitter.emit(import_hwk_adapter_core2.DEVICE.DISCONNECT, {
546
- type: import_hwk_adapter_core2.DEVICE.DISCONNECT,
845
+ this.emitter.emit(import_hwk_adapter_core3.DEVICE.DISCONNECT, {
846
+ type: import_hwk_adapter_core3.DEVICE.DISCONNECT,
547
847
  payload: { connectId: data.connectId }
548
848
  });
549
849
  };
@@ -553,7 +853,7 @@ var _LedgerAdapter = class _LedgerAdapter {
553
853
  // exists (race during teardown) we drop. All other variants pass through
554
854
  // unchanged.
555
855
  this.uiEventForwarder = (event) => {
556
- if (event.type === import_hwk_adapter_core2.EConnectorInteraction.AppInstallProgress) {
856
+ if (event.type === import_hwk_adapter_core3.EConnectorInteraction.AppInstallProgress) {
557
857
  let connectId;
558
858
  for (const [cid, sid] of this._sessions) {
559
859
  if (sid === event.payload.sessionId) {
@@ -568,12 +868,23 @@ var _LedgerAdapter = class _LedgerAdapter {
568
868
  );
569
869
  return;
570
870
  }
871
+ const { appName, progress } = event.payload;
872
+ const key = `${connectId}:${appName}`;
873
+ if (this._installProgressLastKey !== key || this._installProgressLastEmittedValue >= 1) {
874
+ this._installProgressLastEmittedValue = -Infinity;
875
+ this._installProgressLastKey = key;
876
+ }
877
+ const delta = progress - this._installProgressLastEmittedValue;
878
+ if (delta < _LedgerAdapter.APP_INSTALL_PROGRESS_MIN_DELTA && progress < 1) {
879
+ return;
880
+ }
881
+ this._installProgressLastEmittedValue = progress;
571
882
  this.emitter.emit("ui-event", {
572
- type: import_hwk_adapter_core2.EConnectorInteraction.AppInstallProgress,
883
+ type: import_hwk_adapter_core3.EConnectorInteraction.AppInstallProgress,
573
884
  payload: {
574
885
  connectId,
575
- appName: event.payload.appName,
576
- progress: event.payload.progress
886
+ appName,
887
+ progress
577
888
  }
578
889
  });
579
890
  return;
@@ -582,7 +893,7 @@ var _LedgerAdapter = class _LedgerAdapter {
582
893
  };
583
894
  this.connector = connector;
584
895
  this._defaultAutoInstallApp = options?.autoInstallApp ?? false;
585
- this._jobQueue = new import_hwk_adapter_core2.DeviceJobQueue();
896
+ this._jobQueue = new import_hwk_adapter_core3.DeviceJobQueue();
586
897
  this.registerEventListeners();
587
898
  }
588
899
  // Transport
@@ -630,30 +941,42 @@ var _LedgerAdapter = class _LedgerAdapter {
630
941
  // Device management
631
942
  // ---------------------------------------------------------------------------
632
943
  async searchDevices(options) {
633
- if (options?.resetSession) {
634
- this._doConnectAbortController?.abort();
635
- this._sessions.clear();
636
- this._connectingPromise = null;
637
- this._doConnectAbortController = null;
638
- this._btcHighIndexConfirmedThisSession = false;
639
- }
640
- await this._ensureDevicePermission();
641
- const devices = await this.connector.searchDevices();
642
- this._discoveredDevices.clear();
643
- for (const d of devices) {
644
- if (d.connectId) {
645
- this._discoveredDevices.set(d.connectId, this.connectorDeviceToDeviceInfo(d));
944
+ debugLog("[LedgerAdapter][REQ]", { method: "searchDevices", params: options });
945
+ try {
946
+ if (options?.resetSession) {
947
+ this._doConnectAbortController?.abort();
948
+ this._sessions.clear();
949
+ this._connectingPromise = null;
950
+ this._doConnectAbortController = null;
951
+ this._btcHighIndexConfirmedThisSession = false;
646
952
  }
647
- }
648
- if (this._discoveredDevices.size === 0) {
649
953
  await this._ensureDevicePermission();
954
+ const devices = await this.connector.searchDevices();
955
+ this._discoveredDevices.clear();
956
+ for (const d of devices) {
957
+ if (d.connectId) {
958
+ this._discoveredDevices.set(d.connectId, this.connectorDeviceToDeviceInfo(d));
959
+ }
960
+ }
961
+ if (this._discoveredDevices.size === 0) {
962
+ await this._ensureDevicePermission();
963
+ }
964
+ const result = Array.from(this._discoveredDevices.values());
965
+ debugLog("[LedgerAdapter][RES]", {
966
+ method: "searchDevices",
967
+ success: true,
968
+ payload: result
969
+ });
970
+ return result;
971
+ } catch (err) {
972
+ const e = err;
973
+ debugLog("[LedgerAdapter][RES]", {
974
+ method: "searchDevices",
975
+ success: false,
976
+ error: { message: e?.message, _tag: e?._tag, code: e?.code ?? e?.errorCode }
977
+ });
978
+ throw err;
650
979
  }
651
- debugLog(
652
- `[LedgerAdapter] searchDevices() return count=${this._discoveredDevices.size} ids=[${[
653
- ...this._discoveredDevices.keys()
654
- ].join(",")}]`
655
- );
656
- return Array.from(this._discoveredDevices.values());
657
980
  }
658
981
  // USB single-session invariant: evict all sessions, best-effort (see connectDevice).
659
982
  async _evictAllSessions() {
@@ -669,14 +992,15 @@ var _LedgerAdapter = class _LedgerAdapter {
669
992
  }
670
993
  static _createDeviceBusyError(method) {
671
994
  return Object.assign(new Error(`Ledger device is busy while calling ${method}`), {
672
- code: import_hwk_adapter_core2.HardwareErrorCode.DeviceBusy
995
+ code: import_hwk_adapter_core3.HardwareErrorCode.DeviceBusy
673
996
  });
674
997
  }
675
998
  async connectDevice(connectId) {
999
+ debugLog("[LedgerAdapter][REQ]", { method: "connectDevice", connectId, params: { connectId } });
676
1000
  try {
677
1001
  if (isLedgerBleConnectionType(this.connector.connectionType) && !connectId) {
678
1002
  throw Object.assign(new Error("Ledger BLE connectId is required."), {
679
- code: import_hwk_adapter_core2.HardwareErrorCode.DeviceNotFound
1003
+ code: import_hwk_adapter_core3.HardwareErrorCode.DeviceNotFound
680
1004
  });
681
1005
  }
682
1006
  if (!isLedgerBleConnectionType(this.connector.connectionType)) {
@@ -688,28 +1012,79 @@ var _LedgerAdapter = class _LedgerAdapter {
688
1012
  if (session.deviceInfo) {
689
1013
  this._discoveredDevices.set(connectId, session.deviceInfo);
690
1014
  }
691
- return (0, import_hwk_adapter_core2.success)(connectId);
1015
+ const result = (0, import_hwk_adapter_core3.success)(connectId);
1016
+ debugLog("[LedgerAdapter][RES]", { method: "connectDevice", success: true, payload: result });
1017
+ return result;
692
1018
  } catch (err) {
693
- return this.errorToFailure(err);
1019
+ const failureResult = this.errorToFailure(err);
1020
+ debugLog("[LedgerAdapter][RES]", {
1021
+ method: "connectDevice",
1022
+ success: false,
1023
+ payload: failureResult
1024
+ });
1025
+ return failureResult;
694
1026
  }
695
1027
  }
696
1028
  async disconnectDevice(connectId) {
697
- const sessionId = this._sessions.get(connectId);
698
- if (sessionId) {
699
- await this.connector.disconnect(sessionId);
700
- this._sessions.delete(connectId);
1029
+ debugLog("[LedgerAdapter][REQ]", {
1030
+ method: "disconnectDevice",
1031
+ connectId,
1032
+ params: { connectId }
1033
+ });
1034
+ try {
1035
+ const sessionId = this._sessions.get(connectId);
1036
+ if (sessionId) {
1037
+ await this.connector.disconnect(sessionId);
1038
+ this._sessions.delete(connectId);
1039
+ }
1040
+ debugLog("[LedgerAdapter][RES]", { method: "disconnectDevice", success: true });
1041
+ } catch (err) {
1042
+ const e = err;
1043
+ debugLog("[LedgerAdapter][RES]", {
1044
+ method: "disconnectDevice",
1045
+ success: false,
1046
+ error: { message: e?.message, _tag: e?._tag, code: e?.code ?? e?.errorCode }
1047
+ });
1048
+ throw err;
701
1049
  }
702
1050
  }
703
1051
  async getDeviceInfo(connectId, deviceId) {
704
- await this._ensureDevicePermission(connectId, deviceId);
705
- const cached = this._discoveredDevices.get(connectId) ?? Array.from(this._discoveredDevices.values()).find((d) => d.deviceId === deviceId);
706
- if (cached) {
707
- return (0, import_hwk_adapter_core2.success)(cached);
1052
+ debugLog("[LedgerAdapter][REQ]", {
1053
+ method: "getDeviceInfo",
1054
+ connectId,
1055
+ params: { connectId, deviceId }
1056
+ });
1057
+ try {
1058
+ await this._ensureDevicePermission(connectId, deviceId);
1059
+ const cached = this._discoveredDevices.get(connectId) ?? Array.from(this._discoveredDevices.values()).find((d) => d.deviceId === deviceId);
1060
+ if (cached) {
1061
+ const result = (0, import_hwk_adapter_core3.success)(cached);
1062
+ debugLog("[LedgerAdapter][RES]", {
1063
+ method: "getDeviceInfo",
1064
+ success: true,
1065
+ payload: result
1066
+ });
1067
+ return result;
1068
+ }
1069
+ const notFound = (0, import_hwk_adapter_core3.failure)(
1070
+ import_hwk_adapter_core3.HardwareErrorCode.DeviceNotFound,
1071
+ "Device not found in cache. Call searchDevices() or wait for a device-connected event first."
1072
+ );
1073
+ debugLog("[LedgerAdapter][RES]", {
1074
+ method: "getDeviceInfo",
1075
+ success: false,
1076
+ payload: notFound
1077
+ });
1078
+ return notFound;
1079
+ } catch (err) {
1080
+ const e = err;
1081
+ debugLog("[LedgerAdapter][RES]", {
1082
+ method: "getDeviceInfo",
1083
+ success: false,
1084
+ error: { message: e?.message, _tag: e?._tag, code: e?.code ?? e?.errorCode }
1085
+ });
1086
+ throw err;
708
1087
  }
709
- return (0, import_hwk_adapter_core2.failure)(
710
- import_hwk_adapter_core2.HardwareErrorCode.DeviceNotFound,
711
- "Device not found in cache. Call searchDevices() or wait for a device-connected event first."
712
- );
713
1088
  }
714
1089
  getSupportedChains() {
715
1090
  return ["evm", "btc", "sol", "tron"];
@@ -717,7 +1092,7 @@ var _LedgerAdapter = class _LedgerAdapter {
717
1092
  // ---------------------------------------------------------------------------
718
1093
  // Chain call helper
719
1094
  // ---------------------------------------------------------------------------
720
- async callChain(connectId, deviceId, chain, method, params, commonParams, skipFingerprint = false) {
1095
+ async callChain(connectId, deviceId, chain, method, params, commonParams, skipFingerprint = false, installContext) {
721
1096
  try {
722
1097
  const result = await this.connectorCall(
723
1098
  connectId,
@@ -729,9 +1104,10 @@ var _LedgerAdapter = class _LedgerAdapter {
729
1104
  skipFingerprint
730
1105
  },
731
1106
  void 0,
732
- commonParams
1107
+ commonParams,
1108
+ installContext
733
1109
  );
734
- return (0, import_hwk_adapter_core2.success)(result);
1110
+ return (0, import_hwk_adapter_core3.success)(result);
735
1111
  } catch (err) {
736
1112
  return this.errorToFailure(err);
737
1113
  }
@@ -916,7 +1292,7 @@ var _LedgerAdapter = class _LedgerAdapter {
916
1292
  async installApp(connectId, appName) {
917
1293
  try {
918
1294
  await this.connectorCall(connectId, "installApp", { appName });
919
- return (0, import_hwk_adapter_core2.success)(void 0);
1295
+ return (0, import_hwk_adapter_core3.success)(void 0);
920
1296
  } catch (err) {
921
1297
  return this.errorToFailure(err);
922
1298
  }
@@ -924,7 +1300,16 @@ var _LedgerAdapter = class _LedgerAdapter {
924
1300
  async listInstalledApps(connectId) {
925
1301
  try {
926
1302
  const result = await this.connectorCall(connectId, "listInstalledApps", {});
927
- return (0, import_hwk_adapter_core2.success)(result);
1303
+ return (0, import_hwk_adapter_core3.success)(result);
1304
+ } catch (err) {
1305
+ return this.errorToFailure(err);
1306
+ }
1307
+ }
1308
+ // Offline app-presence + unlock probe. No manager-api catalog (unlike listInstalledApps).
1309
+ async listInstalledNames(connectId) {
1310
+ try {
1311
+ const result = await this.connectorCall(connectId, "listInstalledNames", {});
1312
+ return (0, import_hwk_adapter_core3.success)(result);
928
1313
  } catch (err) {
929
1314
  return this.errorToFailure(err);
930
1315
  }
@@ -932,7 +1317,7 @@ var _LedgerAdapter = class _LedgerAdapter {
932
1317
  async listAvailableApps(connectId) {
933
1318
  try {
934
1319
  const result = await this.connectorCall(connectId, "listAvailableApps", {});
935
- return (0, import_hwk_adapter_core2.success)(result);
1320
+ return (0, import_hwk_adapter_core3.success)(result);
936
1321
  } catch (err) {
937
1322
  return this.errorToFailure(err);
938
1323
  }
@@ -940,7 +1325,7 @@ var _LedgerAdapter = class _LedgerAdapter {
940
1325
  async getLedgerFirmwareVersion(connectId) {
941
1326
  try {
942
1327
  const result = await this.connectorCall(connectId, "getFirmwareVersion", {});
943
- return (0, import_hwk_adapter_core2.success)(result);
1328
+ return (0, import_hwk_adapter_core3.success)(result);
944
1329
  } catch (err) {
945
1330
  return this.errorToFailure(err);
946
1331
  }
@@ -948,7 +1333,7 @@ var _LedgerAdapter = class _LedgerAdapter {
948
1333
  async getLedgerDeviceInfo(connectId) {
949
1334
  try {
950
1335
  const result = await this.connectorCall(connectId, "getDeviceInfo", {});
951
- return (0, import_hwk_adapter_core2.success)(result);
1336
+ return (0, import_hwk_adapter_core3.success)(result);
952
1337
  } catch (err) {
953
1338
  return this.errorToFailure(err);
954
1339
  }
@@ -961,7 +1346,7 @@ var _LedgerAdapter = class _LedgerAdapter {
961
1346
  }
962
1347
  cancel(connectId) {
963
1348
  const userAbortReason = Object.assign(new Error("User aborted operation"), {
964
- code: import_hwk_adapter_core2.HardwareErrorCode.UserAborted,
1349
+ code: import_hwk_adapter_core3.HardwareErrorCode.UserAborted,
965
1350
  _tag: ERROR_TAG.UserAborted
966
1351
  });
967
1352
  this._lastCancelReason = userAbortReason;
@@ -995,7 +1380,7 @@ var _LedgerAdapter = class _LedgerAdapter {
995
1380
  chain,
996
1381
  (method, params) => this.connectorCall(connectId, method, params, void 0, deviceId)
997
1382
  );
998
- return (0, import_hwk_adapter_core2.success)(fingerprint);
1383
+ return (0, import_hwk_adapter_core3.success)(fingerprint);
999
1384
  } catch (err) {
1000
1385
  debugError("[LedgerAdapter] getChainFingerprint error:", chain, err);
1001
1386
  return this.errorToFailure(err);
@@ -1018,7 +1403,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1018
1403
  return { success: false, expected: deviceId, actual: fingerprint };
1019
1404
  } catch (err) {
1020
1405
  const mapped = mapLedgerError(err);
1021
- if (mapped.code === import_hwk_adapter_core2.HardwareErrorCode.WrongApp || mapped.code === import_hwk_adapter_core2.HardwareErrorCode.DeviceLocked) {
1406
+ if (mapped.code === import_hwk_adapter_core3.HardwareErrorCode.WrongApp || mapped.code === import_hwk_adapter_core3.HardwareErrorCode.DeviceLocked) {
1022
1407
  return { success: true };
1023
1408
  }
1024
1409
  throw err;
@@ -1043,7 +1428,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1043
1428
  const result = await callMethod("btcGetMasterFingerprint", {});
1044
1429
  return result.masterFingerprint;
1045
1430
  }
1046
- const path = import_hwk_adapter_core2.CHAIN_FINGERPRINT_PATHS[chain];
1431
+ const path = import_hwk_adapter_core3.CHAIN_FINGERPRINT_PATHS[chain];
1047
1432
  let address;
1048
1433
  if (chain === "evm") {
1049
1434
  address = (await callMethod("evmGetAddress", { path, showOnDevice: false })).address.toLowerCase();
@@ -1054,7 +1439,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1054
1439
  } else {
1055
1440
  throw new Error(`Unsupported chain for fingerprint: ${chain}`);
1056
1441
  }
1057
- return (0, import_hwk_adapter_core2.deriveDeviceFingerprint)(address);
1442
+ return (0, import_hwk_adapter_core3.deriveDeviceFingerprint)(address);
1058
1443
  }
1059
1444
  // Ledger WebUSB won't expose a locked device, so we can't auto-detect unlock.
1060
1445
  // The user must press Confirm after unlocking, which triggers a search retry.
@@ -1066,10 +1451,10 @@ var _LedgerAdapter = class _LedgerAdapter {
1066
1451
  _LedgerAdapter._throwIfAborted(signal);
1067
1452
  }
1068
1453
  const waitPromise = this._uiRegistry.wait(
1069
- import_hwk_adapter_core2.UI_REQUEST.REQUEST_DEVICE_CONNECT
1454
+ import_hwk_adapter_core3.UI_REQUEST.REQUEST_DEVICE_CONNECT
1070
1455
  );
1071
- this.emitter.emit(import_hwk_adapter_core2.UI_REQUEST.REQUEST_DEVICE_CONNECT, {
1072
- type: import_hwk_adapter_core2.UI_REQUEST.REQUEST_DEVICE_CONNECT,
1456
+ this.emitter.emit(import_hwk_adapter_core3.UI_REQUEST.REQUEST_DEVICE_CONNECT, {
1457
+ type: import_hwk_adapter_core3.UI_REQUEST.REQUEST_DEVICE_CONNECT,
1073
1458
  payload: {
1074
1459
  vendor: "ledger",
1075
1460
  reason: "device-not-found",
@@ -1080,7 +1465,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1080
1465
  try {
1081
1466
  if (signal) {
1082
1467
  const onAbort = () => {
1083
- this._uiRegistry.cancel(import_hwk_adapter_core2.UI_REQUEST.REQUEST_DEVICE_CONNECT);
1468
+ this._uiRegistry.cancel(import_hwk_adapter_core3.UI_REQUEST.REQUEST_DEVICE_CONNECT);
1084
1469
  };
1085
1470
  signal.addEventListener("abort", onAbort, { once: true });
1086
1471
  try {
@@ -1092,20 +1477,20 @@ var _LedgerAdapter = class _LedgerAdapter {
1092
1477
  payload = await waitPromise;
1093
1478
  }
1094
1479
  } catch (err) {
1095
- this.emitter.emit(import_hwk_adapter_core2.UI_REQUEST.CLOSE_UI_WINDOW, {
1096
- type: import_hwk_adapter_core2.UI_REQUEST.CLOSE_UI_WINDOW,
1480
+ this.emitter.emit(import_hwk_adapter_core3.UI_REQUEST.CLOSE_UI_WINDOW, {
1481
+ type: import_hwk_adapter_core3.UI_REQUEST.CLOSE_UI_WINDOW,
1097
1482
  payload: {}
1098
1483
  });
1099
1484
  throw Object.assign(new Error("User cancelled Ledger connection"), {
1100
1485
  _tag: ERROR_TAG.UserAborted,
1101
- code: import_hwk_adapter_core2.HardwareErrorCode.UserAborted,
1486
+ code: import_hwk_adapter_core3.HardwareErrorCode.UserAborted,
1102
1487
  cause: err
1103
1488
  });
1104
1489
  }
1105
1490
  if (!payload?.confirmed) {
1106
1491
  throw Object.assign(new Error("User cancelled Ledger connection"), {
1107
1492
  _tag: ERROR_TAG.UserAborted,
1108
- code: import_hwk_adapter_core2.HardwareErrorCode.UserAborted
1493
+ code: import_hwk_adapter_core3.HardwareErrorCode.UserAborted
1109
1494
  });
1110
1495
  }
1111
1496
  await new Promise((resolve) => {
@@ -1135,10 +1520,10 @@ var _LedgerAdapter = class _LedgerAdapter {
1135
1520
  }
1136
1521
  async _waitForBtcHighIndexConfirm(path, accountIndex) {
1137
1522
  const waitPromise = this._uiRegistry.wait(
1138
- import_hwk_adapter_core2.UI_REQUEST.REQUEST_BTC_HIGH_INDEX_CONFIRM
1523
+ import_hwk_adapter_core3.UI_REQUEST.REQUEST_BTC_HIGH_INDEX_CONFIRM
1139
1524
  );
1140
- this.emitter.emit(import_hwk_adapter_core2.UI_REQUEST.REQUEST_BTC_HIGH_INDEX_CONFIRM, {
1141
- type: import_hwk_adapter_core2.UI_REQUEST.REQUEST_BTC_HIGH_INDEX_CONFIRM,
1525
+ this.emitter.emit(import_hwk_adapter_core3.UI_REQUEST.REQUEST_BTC_HIGH_INDEX_CONFIRM, {
1526
+ type: import_hwk_adapter_core3.UI_REQUEST.REQUEST_BTC_HIGH_INDEX_CONFIRM,
1142
1527
  payload: {
1143
1528
  vendor: "ledger",
1144
1529
  path,
@@ -1149,8 +1534,8 @@ var _LedgerAdapter = class _LedgerAdapter {
1149
1534
  const payload = await waitPromise;
1150
1535
  return !!payload?.confirmed;
1151
1536
  } catch (err) {
1152
- this.emitter.emit(import_hwk_adapter_core2.UI_REQUEST.CLOSE_UI_WINDOW, {
1153
- type: import_hwk_adapter_core2.UI_REQUEST.CLOSE_UI_WINDOW,
1537
+ this.emitter.emit(import_hwk_adapter_core3.UI_REQUEST.CLOSE_UI_WINDOW, {
1538
+ type: import_hwk_adapter_core3.UI_REQUEST.CLOSE_UI_WINDOW,
1154
1539
  payload: {}
1155
1540
  });
1156
1541
  return false;
@@ -1160,18 +1545,18 @@ var _LedgerAdapter = class _LedgerAdapter {
1160
1545
  // Same register-then-emit ordering as the BTC high-index gate.
1161
1546
  async _waitForInstallAppConfirm(appName) {
1162
1547
  const waitPromise = this._uiRegistry.wait(
1163
- import_hwk_adapter_core2.UI_REQUEST.REQUEST_INSTALL_APP
1548
+ import_hwk_adapter_core3.UI_REQUEST.REQUEST_INSTALL_APP
1164
1549
  );
1165
- this.emitter.emit(import_hwk_adapter_core2.UI_REQUEST.REQUEST_INSTALL_APP, {
1166
- type: import_hwk_adapter_core2.UI_REQUEST.REQUEST_INSTALL_APP,
1550
+ this.emitter.emit(import_hwk_adapter_core3.UI_REQUEST.REQUEST_INSTALL_APP, {
1551
+ type: import_hwk_adapter_core3.UI_REQUEST.REQUEST_INSTALL_APP,
1167
1552
  payload: { vendor: "ledger", appName }
1168
1553
  });
1169
1554
  try {
1170
1555
  const payload = await waitPromise;
1171
1556
  return !!payload?.confirmed;
1172
1557
  } catch (err) {
1173
- this.emitter.emit(import_hwk_adapter_core2.UI_REQUEST.CLOSE_UI_WINDOW, {
1174
- type: import_hwk_adapter_core2.UI_REQUEST.CLOSE_UI_WINDOW,
1558
+ this.emitter.emit(import_hwk_adapter_core3.UI_REQUEST.CLOSE_UI_WINDOW, {
1559
+ type: import_hwk_adapter_core3.UI_REQUEST.CLOSE_UI_WINDOW,
1175
1560
  payload: {}
1176
1561
  });
1177
1562
  return false;
@@ -1184,7 +1569,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1184
1569
  if (signal.aborted) _LedgerAdapter._throwIfAborted(signal);
1185
1570
  if (isLedgerBleConnectionType(this.connector.connectionType) && !connectId) {
1186
1571
  throw Object.assign(new Error("Ledger BLE connectId is required."), {
1187
- code: import_hwk_adapter_core2.HardwareErrorCode.DeviceNotFound
1572
+ code: import_hwk_adapter_core3.HardwareErrorCode.DeviceNotFound
1188
1573
  });
1189
1574
  }
1190
1575
  if (connectId && this._sessions.has(connectId)) return connectId;
@@ -1194,7 +1579,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1194
1579
  new Error(
1195
1580
  "Ledger USB session invariant violated: more than one session is active. Please reconnect the device."
1196
1581
  ),
1197
- { code: import_hwk_adapter_core2.HardwareErrorCode.DeviceOneDeviceOnly }
1582
+ { code: import_hwk_adapter_core3.HardwareErrorCode.DeviceOneDeviceOnly }
1198
1583
  );
1199
1584
  }
1200
1585
  return this._sessions.keys().next().value;
@@ -1236,7 +1621,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1236
1621
  let confirms = 0;
1237
1622
  while (!internalSignal.aborted) {
1238
1623
  this.emitter.emit("ui-event", {
1239
- type: import_hwk_adapter_core2.EConnectorInteraction.Searching,
1624
+ type: import_hwk_adapter_core3.EConnectorInteraction.Searching,
1240
1625
  payload: { sessionId: "" }
1241
1626
  });
1242
1627
  let devices = await this.searchDevices();
@@ -1274,7 +1659,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1274
1659
  new Error(
1275
1660
  "Device not connected after multiple attempts. Please ensure your Ledger is awake, unlocked, and in range, then try again."
1276
1661
  ),
1277
- { code: import_hwk_adapter_core2.HardwareErrorCode.DeviceNotFound }
1662
+ { code: import_hwk_adapter_core3.HardwareErrorCode.DeviceNotFound }
1278
1663
  );
1279
1664
  }
1280
1665
  await this._waitForDeviceConnect(internalSignal);
@@ -1298,7 +1683,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1298
1683
  return this._connectDeviceOrThrow(devices[0].connectId);
1299
1684
  }
1300
1685
  const err = Object.assign(new Error(`Target Ledger unavailable: ${targetConnectId}`), {
1301
- code: import_hwk_adapter_core2.HardwareErrorCode.DeviceNotFound
1686
+ code: import_hwk_adapter_core3.HardwareErrorCode.DeviceNotFound
1302
1687
  });
1303
1688
  if (isLedgerBleConnectionType(this.connector.connectionType)) {
1304
1689
  err._tag = ERROR_TAG.DeviceNotAdvertising;
@@ -1307,7 +1692,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1307
1692
  }
1308
1693
  if (isLedgerBleConnectionType(this.connector.connectionType)) {
1309
1694
  throw Object.assign(new Error("Ledger BLE connectId is required."), {
1310
- code: import_hwk_adapter_core2.HardwareErrorCode.DeviceNotFound
1695
+ code: import_hwk_adapter_core3.HardwareErrorCode.DeviceNotFound
1311
1696
  });
1312
1697
  }
1313
1698
  if (devices.length > 1) {
@@ -1315,7 +1700,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1315
1700
  }
1316
1701
  if (devices.length !== 1) {
1317
1702
  throw Object.assign(new Error("Ledger device not found."), {
1318
- code: import_hwk_adapter_core2.HardwareErrorCode.DeviceNotFound
1703
+ code: import_hwk_adapter_core3.HardwareErrorCode.DeviceNotFound
1319
1704
  });
1320
1705
  }
1321
1706
  return this._connectDeviceOrThrow(devices[0].connectId);
@@ -1353,7 +1738,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1353
1738
  */
1354
1739
  _unwrapConnectorResult(result) {
1355
1740
  if (result.success) return result.payload;
1356
- throw (0, import_hwk_adapter_core2.rehydrateConnectorError)(result.error);
1741
+ throw (0, import_hwk_adapter_core3.rehydrateConnectorError)(result.error);
1357
1742
  }
1358
1743
  /**
1359
1744
  * `connector.call` + result unwrap, optionally raced against an abort
@@ -1366,26 +1751,43 @@ var _LedgerAdapter = class _LedgerAdapter {
1366
1751
  const result = signal ? await this._abortable(signal, promise) : await promise;
1367
1752
  return this._unwrapConnectorResult(result);
1368
1753
  }
1369
- async connectorCall(connectId, method, params, fingerprint, permissionDeviceId, commonParams) {
1370
- debugLog("[LedgerAdapter] connectorCall:", method, "connectId:", connectId || "(empty)");
1754
+ async connectorCall(connectId, method, params, fingerprint, permissionDeviceId, commonParams, installContext) {
1755
+ debugLog("[LedgerAdapter][REQ]", { method, connectId: connectId || "(empty)", params });
1371
1756
  const queueKey = connectId || "__ledger_default__";
1372
- return this._jobQueue.enqueue(
1373
- queueKey,
1374
- async (signal) => this._runConnectorCall(
1375
- connectId,
1757
+ try {
1758
+ const result = await this._jobQueue.enqueue(
1759
+ queueKey,
1760
+ async (signal) => this._runConnectorCall(
1761
+ connectId,
1762
+ method,
1763
+ params,
1764
+ signal,
1765
+ fingerprint,
1766
+ permissionDeviceId,
1767
+ commonParams,
1768
+ installContext
1769
+ ),
1770
+ {
1771
+ label: method,
1772
+ rejectIfBusy: true,
1773
+ busyError: _LedgerAdapter._createDeviceBusyError(method)
1774
+ }
1775
+ );
1776
+ debugLog("[LedgerAdapter][RES]", { method, success: true, payload: result });
1777
+ return result;
1778
+ } catch (err) {
1779
+ const e = err;
1780
+ debugLog("[LedgerAdapter][RES]", {
1376
1781
  method,
1377
- params,
1378
- signal,
1379
- fingerprint,
1380
- permissionDeviceId,
1381
- commonParams
1382
- ),
1383
- {
1384
- label: method,
1385
- rejectIfBusy: true,
1386
- busyError: _LedgerAdapter._createDeviceBusyError(method)
1387
- }
1388
- );
1782
+ success: false,
1783
+ error: {
1784
+ message: e?.message,
1785
+ _tag: e?._tag,
1786
+ code: e?.code ?? e?.errorCode
1787
+ }
1788
+ });
1789
+ throw err;
1790
+ }
1389
1791
  }
1390
1792
  /**
1391
1793
  * Race a promise against an abort signal. On abort, rejects with
@@ -1420,7 +1822,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1420
1822
  }
1421
1823
  }
1422
1824
  /** Actual work done under the job queue — connection, fingerprint, call, and recovery. */
1423
- async _runConnectorCall(connectId, method, params, signal, fingerprint, permissionDeviceId, commonParams) {
1825
+ async _runConnectorCall(connectId, method, params, signal, fingerprint, permissionDeviceId, commonParams, installContext) {
1424
1826
  _LedgerAdapter._throwIfAborted(signal);
1425
1827
  await this._ensureDevicePermission(
1426
1828
  connectId,
@@ -1434,7 +1836,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1434
1836
  if (gatedParams === null) {
1435
1837
  throw Object.assign(new Error("User cancelled BTC high-index confirmation"), {
1436
1838
  _tag: ERROR_TAG.UserAborted,
1437
- code: import_hwk_adapter_core2.HardwareErrorCode.UserAborted
1839
+ code: import_hwk_adapter_core3.HardwareErrorCode.UserAborted
1438
1840
  });
1439
1841
  }
1440
1842
  effectiveParams = gatedParams;
@@ -1463,7 +1865,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1463
1865
  );
1464
1866
  if (!fp.success) {
1465
1867
  throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {
1466
- code: import_hwk_adapter_core2.HardwareErrorCode.DeviceMismatch
1868
+ code: import_hwk_adapter_core3.HardwareErrorCode.DeviceMismatch
1467
1869
  });
1468
1870
  }
1469
1871
  }
@@ -1482,22 +1884,62 @@ var _LedgerAdapter = class _LedgerAdapter {
1482
1884
  isStuckApp: isStuckAppStateError(err)
1483
1885
  });
1484
1886
  const autoInstallApp = commonParams?.autoInstallApp ?? this._defaultAutoInstallApp;
1485
- const isAppMissing = isAppNotInstalledError(err) || err?.code === import_hwk_adapter_core2.HardwareErrorCode.AppNotInstalled;
1887
+ const isAppMissing = isAppNotInstalledError(err) || err?.code === import_hwk_adapter_core3.HardwareErrorCode.AppNotInstalled;
1486
1888
  if (autoInstallApp && isAppMissing) {
1889
+ if (installContext?.deviceOutOfMemoryError) {
1890
+ throw installContext.deviceOutOfMemoryError;
1891
+ }
1487
1892
  const appName = err?.appName ?? mapLedgerError(err).appName;
1488
1893
  if (appName) {
1894
+ if (installContext?.installAttemptedAppNames?.has(appName)) {
1895
+ throw (0, import_hwk_adapter_core3.createHwkError)({
1896
+ code: import_hwk_adapter_core3.HardwareErrorCode.AppNotInstalled,
1897
+ message: `${appName} install reported success but the app is still missing on device`,
1898
+ _tag: ERROR_TAG.AppInstallVerifyFailed,
1899
+ appName
1900
+ });
1901
+ }
1489
1902
  const confirmed = await this._waitForInstallAppConfirm(appName);
1490
- if (!confirmed) throw err;
1903
+ if (!confirmed) {
1904
+ throw (0, import_hwk_adapter_core3.createHwkError)({
1905
+ code: import_hwk_adapter_core3.HardwareErrorCode.UserAborted,
1906
+ message: `User declined to install ${appName}`,
1907
+ _tag: ERROR_TAG.UserAborted,
1908
+ appName
1909
+ });
1910
+ }
1491
1911
  this.emitter.emit("ui-event", {
1492
- type: import_hwk_adapter_core2.EConnectorInteraction.AppInstallProgress,
1912
+ type: import_hwk_adapter_core3.EConnectorInteraction.AppInstallProgress,
1493
1913
  payload: { connectId: resolvedConnectId, appName, progress: 0 }
1494
1914
  });
1495
- await this._callConnector(sessionId, "installApp", { appName }, signal);
1496
- this.emitter.emit(import_hwk_adapter_core2.UI_REQUEST.CLOSE_UI_WINDOW, {
1497
- type: import_hwk_adapter_core2.UI_REQUEST.CLOSE_UI_WINDOW,
1915
+ try {
1916
+ await this._callConnector(sessionId, "installApp", { appName }, signal);
1917
+ } catch (installErr) {
1918
+ if (mapLedgerError(installErr).code === import_hwk_adapter_core3.HardwareErrorCode.DeviceOutOfMemory) {
1919
+ if (installContext) {
1920
+ installContext.deviceOutOfMemoryError = installErr;
1921
+ }
1922
+ }
1923
+ throw installErr;
1924
+ }
1925
+ if (installContext) {
1926
+ installContext.installAttemptedAppNames = installContext.installAttemptedAppNames ?? /* @__PURE__ */ new Set();
1927
+ installContext.installAttemptedAppNames.add(appName);
1928
+ }
1929
+ this.emitter.emit(import_hwk_adapter_core3.UI_REQUEST.CLOSE_UI_WINDOW, {
1930
+ type: import_hwk_adapter_core3.UI_REQUEST.CLOSE_UI_WINDOW,
1498
1931
  payload: {}
1499
1932
  });
1500
- return await this._callConnector(sessionId, method, effectiveParams, signal);
1933
+ return await this._runConnectorCall(
1934
+ resolvedConnectId,
1935
+ method,
1936
+ effectiveParams,
1937
+ signal,
1938
+ fingerprint,
1939
+ permissionDeviceId,
1940
+ commonParams,
1941
+ installContext
1942
+ );
1501
1943
  }
1502
1944
  }
1503
1945
  if (isStuckAppStateError(err)) {
@@ -1572,7 +2014,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1572
2014
  );
1573
2015
  if (!fp.success) {
1574
2016
  throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {
1575
- code: import_hwk_adapter_core2.HardwareErrorCode.DeviceMismatch
2017
+ code: import_hwk_adapter_core3.HardwareErrorCode.DeviceMismatch
1576
2018
  });
1577
2019
  }
1578
2020
  }
@@ -1607,7 +2049,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1607
2049
  this.connector.reset();
1608
2050
  const codeNum = err?.code;
1609
2051
  throw Object.assign(err, {
1610
- code: codeNum ?? import_hwk_adapter_core2.HardwareErrorCode.DeviceDisconnected
2052
+ code: codeNum ?? import_hwk_adapter_core3.HardwareErrorCode.DeviceDisconnected
1611
2053
  });
1612
2054
  }
1613
2055
  throw err;
@@ -1641,7 +2083,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1641
2083
  );
1642
2084
  if (!fp.success) {
1643
2085
  throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {
1644
- code: import_hwk_adapter_core2.HardwareErrorCode.DeviceMismatch
2086
+ code: import_hwk_adapter_core3.HardwareErrorCode.DeviceMismatch
1645
2087
  });
1646
2088
  }
1647
2089
  }
@@ -1698,7 +2140,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1698
2140
  );
1699
2141
  if (!fp.success) {
1700
2142
  throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {
1701
- code: import_hwk_adapter_core2.HardwareErrorCode.DeviceMismatch
2143
+ code: import_hwk_adapter_core3.HardwareErrorCode.DeviceMismatch
1702
2144
  });
1703
2145
  }
1704
2146
  }
@@ -1739,7 +2181,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1739
2181
  );
1740
2182
  if (!fp.success) {
1741
2183
  throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {
1742
- code: import_hwk_adapter_core2.HardwareErrorCode.DeviceMismatch
2184
+ code: import_hwk_adapter_core3.HardwareErrorCode.DeviceMismatch
1743
2185
  });
1744
2186
  }
1745
2187
  }
@@ -1764,16 +2206,16 @@ var _LedgerAdapter = class _LedgerAdapter {
1764
2206
  }
1765
2207
  const transportType = this.activeTransport ?? "hid";
1766
2208
  const waitPromise = this._uiRegistry.wait(
1767
- import_hwk_adapter_core2.UI_REQUEST.REQUEST_DEVICE_PERMISSION,
2209
+ import_hwk_adapter_core3.UI_REQUEST.REQUEST_DEVICE_PERMISSION,
1768
2210
  { timeoutMs: 6e4 }
1769
2211
  );
1770
- this.emitter.emit(import_hwk_adapter_core2.UI_REQUEST.REQUEST_DEVICE_PERMISSION, {
1771
- type: import_hwk_adapter_core2.UI_REQUEST.REQUEST_DEVICE_PERMISSION,
2212
+ this.emitter.emit(import_hwk_adapter_core3.UI_REQUEST.REQUEST_DEVICE_PERMISSION, {
2213
+ type: import_hwk_adapter_core3.UI_REQUEST.REQUEST_DEVICE_PERMISSION,
1772
2214
  payload: { transportType, connectId, deviceId }
1773
2215
  });
1774
2216
  let response;
1775
2217
  const onAbort = () => {
1776
- this._uiRegistry.cancel(import_hwk_adapter_core2.UI_REQUEST.REQUEST_DEVICE_PERMISSION);
2218
+ this._uiRegistry.cancel(import_hwk_adapter_core3.UI_REQUEST.REQUEST_DEVICE_PERMISSION);
1777
2219
  };
1778
2220
  try {
1779
2221
  signal?.addEventListener("abort", onAbort, { once: true });
@@ -1782,14 +2224,14 @@ var _LedgerAdapter = class _LedgerAdapter {
1782
2224
  if (signal?.aborted) {
1783
2225
  _LedgerAdapter._throwIfAborted(signal);
1784
2226
  }
1785
- if (err?._tag === import_hwk_adapter_core2.UI_REQUEST_PREEMPTED_TAG) {
1786
- this.emitter.emit(import_hwk_adapter_core2.UI_REQUEST.CLOSE_UI_WINDOW, {
1787
- type: import_hwk_adapter_core2.UI_REQUEST.CLOSE_UI_WINDOW,
2227
+ if (err?._tag === import_hwk_adapter_core3.UI_REQUEST_PREEMPTED_TAG) {
2228
+ this.emitter.emit(import_hwk_adapter_core3.UI_REQUEST.CLOSE_UI_WINDOW, {
2229
+ type: import_hwk_adapter_core3.UI_REQUEST.CLOSE_UI_WINDOW,
1788
2230
  payload: {}
1789
2231
  });
1790
2232
  throw Object.assign(new Error("Device permission request superseded"), {
1791
2233
  _tag: ERROR_TAG.UserAborted,
1792
- code: import_hwk_adapter_core2.HardwareErrorCode.UserAborted,
2234
+ code: import_hwk_adapter_core3.HardwareErrorCode.UserAborted,
1793
2235
  cause: err
1794
2236
  });
1795
2237
  }
@@ -1800,7 +2242,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1800
2242
  const { granted, reason, message } = response;
1801
2243
  if (!granted) {
1802
2244
  throw Object.assign(new Error(message ?? "Device permission denied"), {
1803
- code: import_hwk_adapter_core2.HardwareErrorCode.DevicePermissionDenied,
2245
+ code: import_hwk_adapter_core3.HardwareErrorCode.DevicePermissionDenied,
1804
2246
  reason
1805
2247
  });
1806
2248
  }
@@ -1814,7 +2256,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1814
2256
  const tag = err && typeof err === "object" ? err._tag : void 0;
1815
2257
  if (err && typeof err === "object" && "code" in err && typeof err.code === "number") {
1816
2258
  const e = err;
1817
- const params = e.code === import_hwk_adapter_core2.HardwareErrorCode.DevicePermissionDenied && e.reason ? { permissionDeniedReason: e.reason } : e.params;
2259
+ const params = e.code === import_hwk_adapter_core3.HardwareErrorCode.DevicePermissionDenied && e.reason ? { permissionDeniedReason: e.reason } : e.params;
1818
2260
  return ledgerFailure(e.code, e.message ?? "Unknown error", e.appName, tag, params);
1819
2261
  }
1820
2262
  const mapped = mapLedgerError(err);
@@ -1861,10 +2303,13 @@ _LedgerAdapter.STUCK_APP_RETRY_DELAY_MS = 500;
1861
2303
  // Confirm but device never shows up / never unlocks), throw DeviceNotFound
1862
2304
  // instead of looping forever.
1863
2305
  _LedgerAdapter.MAX_DOCONNECT_CONFIRMS = 3;
2306
+ // Throttle AppInstallProgress by progress delta — DMK streams much faster
2307
+ // than UIs need. Final frame (progress >= 1) always passes.
2308
+ _LedgerAdapter.APP_INSTALL_PROGRESS_MIN_DELTA = 0.05;
1864
2309
  var LedgerAdapter = _LedgerAdapter;
1865
2310
 
1866
2311
  // src/connector/LedgerConnectorBase.ts
1867
- var import_hwk_adapter_core12 = require("@onekeyfe/hwk-adapter-core");
2312
+ var import_hwk_adapter_core13 = require("@onekeyfe/hwk-adapter-core");
1868
2313
 
1869
2314
  // src/device/LedgerDeviceManager.ts
1870
2315
  var LedgerDeviceManager = class {
@@ -2137,7 +2582,7 @@ var import_device_signer_kit_ethereum = require("@ledgerhq/device-signer-kit-eth
2137
2582
  var import_context_module = require("@ledgerhq/context-module");
2138
2583
 
2139
2584
  // src/signer/SignerEth.ts
2140
- var import_hwk_adapter_core3 = require("@onekeyfe/hwk-adapter-core");
2585
+ var import_hwk_adapter_core4 = require("@onekeyfe/hwk-adapter-core");
2141
2586
 
2142
2587
  // src/signer/deviceActionToPromise.ts
2143
2588
  var import_device_management_kit = require("@ledgerhq/device-management-kit");
@@ -2350,7 +2795,7 @@ var SignerEth = class {
2350
2795
  );
2351
2796
  }
2352
2797
  async signTransaction(derivationPath, serializedTxHex) {
2353
- const action = this._sdk.signTransaction(derivationPath, (0, import_hwk_adapter_core3.hexToBytes)(serializedTxHex));
2798
+ const action = this._sdk.signTransaction(derivationPath, (0, import_hwk_adapter_core4.hexToBytes)(serializedTxHex));
2354
2799
  return deviceActionToPromise(
2355
2800
  action,
2356
2801
  this.onInteraction,
@@ -2359,7 +2804,7 @@ var SignerEth = class {
2359
2804
  );
2360
2805
  }
2361
2806
  async signMessage(derivationPath, message) {
2362
- const action = this._sdk.signMessage(derivationPath, (0, import_hwk_adapter_core3.hexToBytes)(message));
2807
+ const action = this._sdk.signMessage(derivationPath, (0, import_hwk_adapter_core4.hexToBytes)(message));
2363
2808
  return deviceActionToPromise(
2364
2809
  action,
2365
2810
  this.onInteraction,
@@ -2419,23 +2864,23 @@ var SignerManager = class _SignerManager {
2419
2864
  };
2420
2865
 
2421
2866
  // src/connector/chains/evm.ts
2422
- var import_hwk_adapter_core5 = require("@onekeyfe/hwk-adapter-core");
2867
+ var import_hwk_adapter_core6 = require("@onekeyfe/hwk-adapter-core");
2423
2868
 
2424
2869
  // src/connector/chains/utils.ts
2425
- var import_hwk_adapter_core4 = require("@onekeyfe/hwk-adapter-core");
2870
+ var import_hwk_adapter_core5 = require("@onekeyfe/hwk-adapter-core");
2426
2871
  function normalizePath(path) {
2427
2872
  return path.startsWith("m/") ? path.slice(2) : path;
2428
2873
  }
2429
2874
  function collapseSignerInteraction(interaction) {
2430
2875
  switch (interaction) {
2431
2876
  case "confirm-open-app":
2432
- return import_hwk_adapter_core4.EConnectorInteraction.ConfirmOpenApp;
2877
+ return import_hwk_adapter_core5.EConnectorInteraction.ConfirmOpenApp;
2433
2878
  case "unlock-device":
2434
- return import_hwk_adapter_core4.EConnectorInteraction.UnlockDevice;
2879
+ return import_hwk_adapter_core5.EConnectorInteraction.UnlockDevice;
2435
2880
  case "interaction-complete":
2436
- return import_hwk_adapter_core4.EConnectorInteraction.InteractionComplete;
2881
+ return import_hwk_adapter_core5.EConnectorInteraction.InteractionComplete;
2437
2882
  default:
2438
- return import_hwk_adapter_core4.EConnectorInteraction.ConfirmOnDevice;
2883
+ return import_hwk_adapter_core5.EConnectorInteraction.ConfirmOnDevice;
2439
2884
  }
2440
2885
  }
2441
2886
 
@@ -2461,7 +2906,7 @@ async function evmSignTransaction(ctx, sessionId, params) {
2461
2906
  new Error(
2462
2907
  "Ledger requires a pre-serialized transaction (serializedTx). Provide an RLP-encoded hex string."
2463
2908
  ),
2464
- { code: import_hwk_adapter_core5.HardwareErrorCode.InvalidParams }
2909
+ { code: import_hwk_adapter_core6.HardwareErrorCode.InvalidParams }
2465
2910
  );
2466
2911
  }
2467
2912
  const signer = await _getEthSigner(ctx, sessionId);
@@ -2470,8 +2915,8 @@ async function evmSignTransaction(ctx, sessionId, params) {
2470
2915
  const result = await signer.signTransaction(path, params.serializedTx);
2471
2916
  return {
2472
2917
  v: `0x${result.v.toString(16)}`,
2473
- r: (0, import_hwk_adapter_core5.padHex64)(result.r),
2474
- s: (0, import_hwk_adapter_core5.padHex64)(result.s)
2918
+ r: (0, import_hwk_adapter_core6.padHex64)(result.r),
2919
+ s: (0, import_hwk_adapter_core6.padHex64)(result.s)
2475
2920
  };
2476
2921
  } catch (err) {
2477
2922
  ctx.invalidateSession(sessionId);
@@ -2485,8 +2930,8 @@ async function evmSignMessage(ctx, sessionId, params) {
2485
2930
  const path = normalizePath(params.path);
2486
2931
  try {
2487
2932
  const result = await signer.signMessage(path, params.message);
2488
- const rHex = (0, import_hwk_adapter_core5.stripHex)(result.r).padStart(64, "0");
2489
- const sHex = (0, import_hwk_adapter_core5.stripHex)(result.s).padStart(64, "0");
2933
+ const rHex = (0, import_hwk_adapter_core6.stripHex)(result.r).padStart(64, "0");
2934
+ const sHex = (0, import_hwk_adapter_core6.stripHex)(result.s).padStart(64, "0");
2490
2935
  const vHex = result.v.toString(16).padStart(2, "0");
2491
2936
  return { signature: `0x${rHex}${sHex}${vHex}` };
2492
2937
  } catch (err) {
@@ -2502,15 +2947,15 @@ async function evmSignTypedData(ctx, sessionId, params) {
2502
2947
  new Error(
2503
2948
  'Ledger does not support hash-only EIP-712 signing. Use mode "full" with the complete typed data structure.'
2504
2949
  ),
2505
- { code: import_hwk_adapter_core5.HardwareErrorCode.MethodNotSupported }
2950
+ { code: import_hwk_adapter_core6.HardwareErrorCode.MethodNotSupported }
2506
2951
  );
2507
2952
  }
2508
2953
  const signer = await _getEthSigner(ctx, sessionId);
2509
2954
  const path = normalizePath(params.path);
2510
2955
  try {
2511
2956
  const result = await signer.signTypedData(path, params.data);
2512
- const rHex = (0, import_hwk_adapter_core5.stripHex)(result.r).padStart(64, "0");
2513
- const sHex = (0, import_hwk_adapter_core5.stripHex)(result.s).padStart(64, "0");
2957
+ const rHex = (0, import_hwk_adapter_core6.stripHex)(result.r).padStart(64, "0");
2958
+ const sHex = (0, import_hwk_adapter_core6.stripHex)(result.s).padStart(64, "0");
2514
2959
  const vHex = result.v.toString(16).padStart(2, "0");
2515
2960
  return { signature: `0x${rHex}${sHex}${vHex}` };
2516
2961
  } catch (err) {
@@ -2537,13 +2982,13 @@ async function _getEthSigner(ctx, sessionId) {
2537
2982
  }
2538
2983
 
2539
2984
  // src/connector/chains/btc.ts
2540
- var import_hwk_adapter_core7 = require("@onekeyfe/hwk-adapter-core");
2985
+ var import_hwk_adapter_core8 = require("@onekeyfe/hwk-adapter-core");
2541
2986
  var import_bitcoinjs_lib = require("bitcoinjs-lib");
2542
2987
 
2543
2988
  // src/signer/SignerBtc.ts
2544
- var import_hwk_adapter_core6 = require("@onekeyfe/hwk-adapter-core");
2989
+ var import_hwk_adapter_core7 = require("@onekeyfe/hwk-adapter-core");
2545
2990
  function hexToUtf8(hex) {
2546
- return new TextDecoder().decode((0, import_hwk_adapter_core6.hexToBytes)(hex));
2991
+ return new TextDecoder().decode((0, import_hwk_adapter_core7.hexToBytes)(hex));
2547
2992
  }
2548
2993
  var INTERACTIVE_TIMEOUT_MS2 = 5 * 6e4;
2549
2994
  var SignerBtc = class {
@@ -2658,7 +3103,7 @@ function _purposeToTemplate(purpose, DDT) {
2658
3103
  return DDT.TAPROOT;
2659
3104
  default:
2660
3105
  throw Object.assign(new Error(`Unsupported BTC purpose: m/${purpose ?? "<undefined>"}'`), {
2661
- code: import_hwk_adapter_core7.HardwareErrorCode.InvalidParams
3106
+ code: import_hwk_adapter_core8.HardwareErrorCode.InvalidParams
2662
3107
  });
2663
3108
  }
2664
3109
  }
@@ -2714,7 +3159,7 @@ async function btcSignTransaction(ctx, sessionId, params) {
2714
3159
  if (!params.psbt) {
2715
3160
  throw Object.assign(
2716
3161
  new Error("Ledger requires PSBT format for BTC transaction signing. Provide params.psbt."),
2717
- { code: import_hwk_adapter_core7.HardwareErrorCode.InvalidParams }
3162
+ { code: import_hwk_adapter_core8.HardwareErrorCode.InvalidParams }
2718
3163
  );
2719
3164
  }
2720
3165
  const btcSigner = await _createBtcSigner(ctx, sessionId);
@@ -2728,7 +3173,7 @@ async function btcSignTransaction(ctx, sessionId, params) {
2728
3173
  debugLog("[LedgerConnector] btcSignTransaction wallet:", { path, purpose, template });
2729
3174
  const wallet = new DefaultWallet(path, template);
2730
3175
  const signedTxHex = await btcSigner.signTransaction(wallet, params.psbt);
2731
- return { serializedTx: (0, import_hwk_adapter_core7.stripHex)(signedTxHex) };
3176
+ return { serializedTx: (0, import_hwk_adapter_core8.stripHex)(signedTxHex) };
2732
3177
  } catch (err) {
2733
3178
  ctx.invalidateSession(sessionId);
2734
3179
  throw ctx.wrapError(err);
@@ -2739,7 +3184,7 @@ async function btcSignTransaction(ctx, sessionId, params) {
2739
3184
  async function btcSignPsbt(ctx, sessionId, params) {
2740
3185
  if (!params.psbt) {
2741
3186
  throw Object.assign(new Error("btcSignPsbt requires params.psbt"), {
2742
- code: import_hwk_adapter_core7.HardwareErrorCode.InvalidParams
3187
+ code: import_hwk_adapter_core8.HardwareErrorCode.InvalidParams
2743
3188
  });
2744
3189
  }
2745
3190
  const btcSigner = await _createBtcSigner(ctx, sessionId);
@@ -2769,8 +3214,8 @@ async function btcSignMessage(ctx, sessionId, params) {
2769
3214
  try {
2770
3215
  const result = await btcSigner.signMessage(path, params.message);
2771
3216
  const vHex = result.v.toString(16).padStart(2, "0");
2772
- const rHex = (0, import_hwk_adapter_core7.stripHex)(result.r).padStart(64, "0");
2773
- const sHex = (0, import_hwk_adapter_core7.stripHex)(result.s).padStart(64, "0");
3217
+ const rHex = (0, import_hwk_adapter_core8.stripHex)(result.r).padStart(64, "0");
3218
+ const sHex = (0, import_hwk_adapter_core8.stripHex)(result.s).padStart(64, "0");
2774
3219
  return { signature: `${vHex}${rHex}${sHex}` };
2775
3220
  } catch (err) {
2776
3221
  ctx.invalidateSession(sessionId);
@@ -2870,7 +3315,7 @@ function _applySignaturesToPsbt(psbtHex, signatures) {
2870
3315
  }
2871
3316
 
2872
3317
  // src/connector/chains/sol.ts
2873
- var import_hwk_adapter_core8 = require("@onekeyfe/hwk-adapter-core");
3318
+ var import_hwk_adapter_core9 = require("@onekeyfe/hwk-adapter-core");
2874
3319
 
2875
3320
  // src/signer/SignerSol.ts
2876
3321
  var SignerSol = class {
@@ -2938,10 +3383,10 @@ async function solGetAddress(ctx, sessionId, params) {
2938
3383
  async function solSignTransaction(ctx, sessionId, params) {
2939
3384
  const solSigner = await _createSolSigner(ctx, sessionId);
2940
3385
  const path = normalizePath(params.path);
2941
- const txBytes = (0, import_hwk_adapter_core8.hexToBytes)(params.serializedTx);
3386
+ const txBytes = (0, import_hwk_adapter_core9.hexToBytes)(params.serializedTx);
2942
3387
  try {
2943
3388
  const result = await solSigner.signTransaction(path, txBytes);
2944
- return { signature: (0, import_hwk_adapter_core8.bytesToHex)(result) };
3389
+ return { signature: (0, import_hwk_adapter_core9.bytesToHex)(result) };
2945
3390
  } catch (err) {
2946
3391
  ctx.invalidateSession(sessionId);
2947
3392
  throw ctx.wrapError(err);
@@ -2952,7 +3397,7 @@ async function solSignTransaction(ctx, sessionId, params) {
2952
3397
  async function solSignMessage(ctx, sessionId, params) {
2953
3398
  const solSigner = await _createSolSigner(ctx, sessionId);
2954
3399
  const path = normalizePath(params.path);
2955
- const messageBytes = (0, import_hwk_adapter_core8.hexToBytes)(params.message);
3400
+ const messageBytes = (0, import_hwk_adapter_core9.hexToBytes)(params.message);
2956
3401
  try {
2957
3402
  const result = await solSigner.signMessage(path, messageBytes);
2958
3403
  return { signature: result.signature };
@@ -2984,15 +3429,15 @@ async function _createSolSigner(ctx, sessionId) {
2984
3429
  }
2985
3430
 
2986
3431
  // src/connector/chains/tron.ts
2987
- var import_hwk_adapter_core11 = require("@onekeyfe/hwk-adapter-core");
3432
+ var import_hwk_adapter_core12 = require("@onekeyfe/hwk-adapter-core");
2988
3433
  var import_hw_app_trx = __toESM(require("@ledgerhq/hw-app-trx"));
2989
3434
 
2990
3435
  // src/connector/chains/legacyChainCall.ts
2991
- var import_hwk_adapter_core10 = require("@onekeyfe/hwk-adapter-core");
3436
+ var import_hwk_adapter_core11 = require("@onekeyfe/hwk-adapter-core");
2992
3437
 
2993
3438
  // src/app/AppManager.ts
2994
3439
  var import_device_management_kit2 = require("@ledgerhq/device-management-kit");
2995
- var import_hwk_adapter_core9 = require("@onekeyfe/hwk-adapter-core");
3440
+ var import_hwk_adapter_core10 = require("@onekeyfe/hwk-adapter-core");
2996
3441
  var APP_NAME_MAP = {
2997
3442
  ETH: "Ethereum",
2998
3443
  BTC: "Bitcoin",
@@ -3096,15 +3541,30 @@ var AppManager = class {
3096
3541
  command: new import_device_management_kit2.OpenAppCommand({ appName })
3097
3542
  });
3098
3543
  if (!(0, import_device_management_kit2.isSuccessCommandResult)(result)) {
3099
- const { statusCode } = result;
3100
- const hasStatusCode2 = statusCode != null && statusCode !== "";
3101
- debugLog("[AppManager] openApp failed:", appName, "statusCode:", statusCode);
3544
+ const dmkErr = result.error;
3545
+ const errorCode = "errorCode" in dmkErr && dmkErr.errorCode != null ? String(dmkErr.errorCode) : "";
3546
+ const message = "message" in dmkErr && typeof dmkErr.message === "string" ? dmkErr.message : "";
3547
+ debugLog(
3548
+ "[AppManager] openApp failed:",
3549
+ appName,
3550
+ "errorCode:",
3551
+ errorCode,
3552
+ "tag:",
3553
+ dmkErr._tag
3554
+ );
3555
+ let code;
3556
+ if (errorCode === "6807" || /unknown application/i.test(message)) {
3557
+ code = import_hwk_adapter_core10.HardwareErrorCode.AppNotInstalled;
3558
+ } else if (errorCode === "5501" || dmkErr._tag === "ActionRefusedError") {
3559
+ code = import_hwk_adapter_core10.HardwareErrorCode.UserRejected;
3560
+ }
3102
3561
  throw Object.assign(new Error(`Failed to open "${appName}"`), {
3103
3562
  _tag: ERROR_TAG.OpenAppCommand,
3104
- code: hasStatusCode2 ? void 0 : import_hwk_adapter_core9.HardwareErrorCode.AppNotInstalled,
3105
- errorCode: String(statusCode ?? ""),
3106
- statusCode,
3107
- appName
3563
+ code,
3564
+ errorCode,
3565
+ statusCode: errorCode,
3566
+ appName,
3567
+ originalError: dmkErr
3108
3568
  });
3109
3569
  }
3110
3570
  }
@@ -3157,14 +3617,14 @@ async function withLegacyChainCall(ctx, sessionId, options, action) {
3157
3617
  const onAppOpenPrompt = () => {
3158
3618
  openAppPromptShown = true;
3159
3619
  ctx.emit("ui-event", {
3160
- type: import_hwk_adapter_core10.EConnectorInteraction.ConfirmOpenApp,
3620
+ type: import_hwk_adapter_core11.EConnectorInteraction.ConfirmOpenApp,
3161
3621
  payload: { sessionId }
3162
3622
  });
3163
3623
  };
3164
3624
  const closeOpenAppUiIfShown = () => {
3165
3625
  if (openAppPromptShown) {
3166
3626
  ctx.emit("ui-event", {
3167
- type: import_hwk_adapter_core10.EConnectorInteraction.InteractionComplete,
3627
+ type: import_hwk_adapter_core11.EConnectorInteraction.InteractionComplete,
3168
3628
  payload: { sessionId }
3169
3629
  });
3170
3630
  openAppPromptShown = false;
@@ -3185,7 +3645,7 @@ async function withLegacyChainCall(ctx, sessionId, options, action) {
3185
3645
  let confirmEmitted = false;
3186
3646
  if (needsConfirmation) {
3187
3647
  ctx.emit("ui-event", {
3188
- type: import_hwk_adapter_core10.EConnectorInteraction.ConfirmOnDevice,
3648
+ type: import_hwk_adapter_core11.EConnectorInteraction.ConfirmOnDevice,
3189
3649
  payload: { sessionId }
3190
3650
  });
3191
3651
  confirmEmitted = true;
@@ -3195,7 +3655,7 @@ async function withLegacyChainCall(ctx, sessionId, options, action) {
3195
3655
  } finally {
3196
3656
  if (confirmEmitted || openAppPromptShown) {
3197
3657
  ctx.emit("ui-event", {
3198
- type: import_hwk_adapter_core10.EConnectorInteraction.InteractionComplete,
3658
+ type: import_hwk_adapter_core11.EConnectorInteraction.InteractionComplete,
3199
3659
  payload: { sessionId }
3200
3660
  });
3201
3661
  openAppPromptShown = false;
@@ -3283,7 +3743,7 @@ async function tronSignTransaction(ctx, sessionId, params) {
3283
3743
  if (!params.rawTxHex) {
3284
3744
  throw Object.assign(
3285
3745
  new Error("TRON signing requires a protobuf-encoded raw transaction hex (rawTxHex)."),
3286
- { code: import_hwk_adapter_core11.HardwareErrorCode.InvalidParams }
3746
+ { code: import_hwk_adapter_core12.HardwareErrorCode.InvalidParams }
3287
3747
  );
3288
3748
  }
3289
3749
  const path = normalizePath(params.path);
@@ -3444,6 +3904,22 @@ var DeviceApps = class {
3444
3904
  );
3445
3905
  return result.filter((a) => a !== null).map(applicationToMetadata);
3446
3906
  }
3907
+ /** Installed app names via ListApps APDU. Offline (no manager-api), but still requires unlock + dashboard. */
3908
+ async listInstalledNames(options) {
3909
+ const action = this._dmk.executeDeviceAction({
3910
+ sessionId: this._sessionId,
3911
+ deviceAction: new this._ledgerKit.ListAppsDeviceAction({
3912
+ input: { unlockTimeout: options?.unlockTimeout }
3913
+ })
3914
+ });
3915
+ const result = await deviceActionToPromise(
3916
+ action,
3917
+ this.onInteraction,
3918
+ void 0,
3919
+ this.onRegisterCanceller
3920
+ );
3921
+ return result.map((entry) => entry?.appName).filter((name) => typeof name === "string" && name.length > 0);
3922
+ }
3447
3923
  // Catalog lookup via custom device action — DMK has no typed wrapper for this.
3448
3924
  async listAvailable() {
3449
3925
  const customAction = new ListAvailableAppsDeviceAction({
@@ -3507,6 +3983,22 @@ var DeviceApps = class {
3507
3983
  async install(appName, onProgress, options) {
3508
3984
  if (!appName) throw new Error("DeviceApps.install: appName is required");
3509
3985
  debugLog("[DeviceApps] install:", appName);
3986
+ const refreshAction = this._dmk.executeDeviceAction({
3987
+ sessionId: this._sessionId,
3988
+ deviceAction: new this._ledgerKit.GetDeviceMetadataDeviceAction({
3989
+ input: {
3990
+ useSecureChannel: true,
3991
+ forceUpdate: true,
3992
+ unlockTimeout: options?.unlockTimeout
3993
+ }
3994
+ })
3995
+ });
3996
+ await deviceActionToPromise(
3997
+ refreshAction,
3998
+ this.onInteraction,
3999
+ INSTALL_TIMEOUT_MS,
4000
+ this.onRegisterCanceller
4001
+ );
3510
4002
  const action = this._dmk.executeDeviceAction({
3511
4003
  sessionId: this._sessionId,
3512
4004
  deviceAction: new this._ledgerKit.InstallOrUpdateAppsDeviceAction({
@@ -3584,7 +4076,7 @@ var METHOD_PREFIX_TO_APP_NAME = {
3584
4076
  tron: "Tron"
3585
4077
  };
3586
4078
  var HARDWARE_ERROR_CODE_VALUES = new Set(
3587
- Object.values(import_hwk_adapter_core12.HardwareErrorCode).filter((value) => typeof value === "number")
4079
+ Object.values(import_hwk_adapter_core13.HardwareErrorCode).filter((value) => typeof value === "number")
3588
4080
  );
3589
4081
  var BLE_CONNECT_SCAN_TIMEOUT_MS = 1500;
3590
4082
  async function defaultLedgerKitImporter(pkg) {
@@ -3755,7 +4247,7 @@ var LedgerConnectorBase = class {
3755
4247
  `Ledger BLE connect did not return within ${HANG_CEILING_MS / 6e4}min \u2014 DMK hang fallback.`
3756
4248
  );
3757
4249
  err._tag = ERROR_TAG.BlePairingTimeout;
3758
- err.code = import_hwk_adapter_core12.HardwareErrorCode.BlePairingTimeout;
4250
+ err.code = import_hwk_adapter_core13.HardwareErrorCode.BlePairingTimeout;
3759
4251
  reject(err);
3760
4252
  }, HANG_CEILING_MS);
3761
4253
  });
@@ -3788,7 +4280,7 @@ var LedgerConnectorBase = class {
3788
4280
  "Ledger device is not currently advertising. Wake up and unlock the device, keep it nearby, then try again."
3789
4281
  );
3790
4282
  err._tag = ERROR_TAG.DeviceNotAdvertising;
3791
- err.code = import_hwk_adapter_core12.HardwareErrorCode.DeviceNotFound;
4283
+ err.code = import_hwk_adapter_core13.HardwareErrorCode.DeviceNotFound;
3792
4284
  throw err;
3793
4285
  };
3794
4286
  const doConnect = async (path) => {
@@ -3852,7 +4344,7 @@ var LedgerConnectorBase = class {
3852
4344
  "Ledger Bluetooth pairing failed. Make sure the device is unlocked and nearby, then try again."
3853
4345
  );
3854
4346
  wrapped._tag = ERROR_TAG.BleGattBondingFailed;
3855
- wrapped.code = import_hwk_adapter_core12.HardwareErrorCode.BlePairingTimeout;
4347
+ wrapped.code = import_hwk_adapter_core13.HardwareErrorCode.BlePairingTimeout;
3856
4348
  wrapped.originalError = err;
3857
4349
  throw wrapped;
3858
4350
  }
@@ -3930,7 +4422,7 @@ var LedgerConnectorBase = class {
3930
4422
  this._unwatchSessionState(sessionId);
3931
4423
  this._signerManager?.invalidate(sessionId);
3932
4424
  this._cancellers.get(sessionId)?.({
3933
- code: import_hwk_adapter_core12.HardwareErrorCode.DeviceDisconnected,
4425
+ code: import_hwk_adapter_core13.HardwareErrorCode.DeviceDisconnected,
3934
4426
  tag: "DeviceDisconnected",
3935
4427
  message: "Device disconnected"
3936
4428
  });
@@ -3954,9 +4446,9 @@ var LedgerConnectorBase = class {
3954
4446
  if (isAppStuckByApdu(err)) {
3955
4447
  return {
3956
4448
  success: false,
3957
- error: (0, import_hwk_adapter_core12.serializeConnectorError)(
4449
+ error: (0, import_hwk_adapter_core13.serializeConnectorError)(
3958
4450
  Object.assign(new Error("Ledger app is unresponsive"), {
3959
- code: import_hwk_adapter_core12.HardwareErrorCode.DeviceAppStuck,
4451
+ code: import_hwk_adapter_core13.HardwareErrorCode.DeviceAppStuck,
3960
4452
  _tag: ERROR_TAG.DeviceAppStuck,
3961
4453
  originalError: err
3962
4454
  })
@@ -3966,16 +4458,16 @@ var LedgerConnectorBase = class {
3966
4458
  if (isTransportStuck(err)) {
3967
4459
  return {
3968
4460
  success: false,
3969
- error: (0, import_hwk_adapter_core12.serializeConnectorError)(
4461
+ error: (0, import_hwk_adapter_core13.serializeConnectorError)(
3970
4462
  Object.assign(new Error("Device communication interrupted, please retry"), {
3971
- code: import_hwk_adapter_core12.HardwareErrorCode.TransportError,
4463
+ code: import_hwk_adapter_core13.HardwareErrorCode.TransportError,
3972
4464
  _tag: ERROR_TAG.DeviceTransportStuck,
3973
4465
  originalError: err
3974
4466
  })
3975
4467
  )
3976
4468
  };
3977
4469
  }
3978
- return { success: false, error: (0, import_hwk_adapter_core12.serializeConnectorError)(err) };
4470
+ return { success: false, error: (0, import_hwk_adapter_core13.serializeConnectorError)(err) };
3979
4471
  }
3980
4472
  }
3981
4473
  async _dispatch(sessionId, method, params) {
@@ -4038,7 +4530,7 @@ var LedgerConnectorBase = class {
4038
4530
  try {
4039
4531
  return await apps.install(p.appName, ({ progress }) => {
4040
4532
  ctx.emit("ui-event", {
4041
- type: import_hwk_adapter_core12.EConnectorInteraction.AppInstallProgress,
4533
+ type: import_hwk_adapter_core13.EConnectorInteraction.AppInstallProgress,
4042
4534
  payload: {
4043
4535
  sessionId,
4044
4536
  appName: p.appName,
@@ -4064,6 +4556,17 @@ var LedgerConnectorBase = class {
4064
4556
  ctx.clearCanceller(sessionId);
4065
4557
  }
4066
4558
  }
4559
+ case "listInstalledNames": {
4560
+ const apps = await _getDeviceApps(ctx, sessionId);
4561
+ try {
4562
+ return await apps.listInstalledNames(params);
4563
+ } catch (err) {
4564
+ ctx.invalidateSession(sessionId);
4565
+ throw ctx.wrapError(err);
4566
+ } finally {
4567
+ ctx.clearCanceller(sessionId);
4568
+ }
4569
+ }
4067
4570
  case "listAvailableApps": {
4068
4571
  const apps = await _getDeviceApps(ctx, sessionId);
4069
4572
  try {