@onekeyfe/hwk-ledger-adapter 1.2.0-alpha.12 → 1.2.0-alpha.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,216 @@ 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
+ ltc: "Litecoin",
545
+ neurai: "Neurai"
546
+ };
547
+ var LEDGER_UNSUPPORTED_ALLNETWORK_NETWORKS = /* @__PURE__ */ new Set(["doge", "dogecoin"]);
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 chainFingerprints = /* @__PURE__ */ new Map();
559
+ const result = await (0, import_hwk_adapter_core2.runAllNetworkGetAddress)({
560
+ connectId,
561
+ deviceId: _deviceId,
562
+ params,
563
+ normalizeItem: normalizeLedgerAllNetworkItem,
564
+ buildUnsupportedNetworkResponse: (item) => isUnsupportedLedgerAllNetworkNetwork(item) ? buildUnsupportedNetworkResponse(item) : void 0,
565
+ callItem: async ({ method, chain, item }) => {
566
+ const itemDeviceId = getItemDeviceId(item) ?? chainFingerprints.get(chain) ?? "";
567
+ return callAllNetworkMethod(
568
+ callChain,
569
+ connectId,
570
+ itemDeviceId,
571
+ method,
572
+ item,
573
+ commonParams,
574
+ installContext
575
+ );
576
+ },
577
+ attachIdentity: async ({ item, chain, payload }) => attachLedgerIdentity(
578
+ getChainFingerprint,
579
+ connectId,
580
+ item,
581
+ chain,
582
+ payload,
583
+ chainFingerprints
584
+ ),
585
+ shouldAbortBundle: isTopLevelAllNetworkFailure,
586
+ buildTopLevelFailure: (response) => {
587
+ const code = response.payload?.code ?? import_hwk_adapter_core2.HardwareErrorCode.DeviceMismatch;
588
+ return (0, import_hwk_adapter_core2.failure)(
589
+ code,
590
+ response.payload?.error ?? "All-network get-address aborted",
591
+ response.payload?.params
592
+ );
593
+ }
594
+ });
595
+ debugLog("[LedgerAdapter][RES]", {
596
+ method: "allNetworkGetAddress",
597
+ success: result.success,
598
+ payload: result
599
+ });
600
+ return result;
601
+ };
602
+ }
603
+ function isTopLevelAllNetworkFailure(response) {
604
+ if (response.success) {
605
+ return false;
606
+ }
607
+ const code = response.payload?.code;
608
+ return code === import_hwk_adapter_core2.HardwareErrorCode.DeviceMismatch || code === import_hwk_adapter_core2.HardwareErrorCode.UserAborted || code === import_hwk_adapter_core2.HardwareErrorCode.UserRejected;
609
+ }
610
+ function getItemDeviceId(item) {
611
+ const { deviceId } = item;
612
+ return typeof deviceId === "string" && deviceId.length > 0 ? deviceId : void 0;
613
+ }
614
+ function isUnsupportedLedgerAllNetworkNetwork(item) {
615
+ return LEDGER_UNSUPPORTED_ALLNETWORK_NETWORKS.has(item.network.toLowerCase());
616
+ }
617
+ function buildUnsupportedNetworkResponse(item) {
618
+ return {
619
+ ...item,
620
+ success: false,
621
+ payload: {
622
+ code: import_hwk_adapter_core2.HardwareErrorCode.ChainNotSupported,
623
+ error: `Ledger allNetwork does not support ${item.network.toLowerCase() === "doge" ? "Dogecoin" : item.network}`
624
+ }
625
+ };
626
+ }
627
+ function normalizeLedgerAllNetworkItem(method, item) {
628
+ if (method !== "btcGetAddress" && method !== "btcGetPublicKey") {
629
+ return item;
630
+ }
631
+ const itemWithCoin = item;
632
+ if (itemWithCoin.coin) {
633
+ return item;
634
+ }
635
+ const coin = LEDGER_BTC_NETWORK_COIN_MAP[item.network];
636
+ return coin ? { ...item, coin } : item;
637
+ }
638
+ async function attachLedgerIdentity(getChainFingerprint, connectId, item, chain, payload, chainFingerprints) {
639
+ const fingerprint = getItemDeviceId(item) || chainFingerprints.get(chain) || await bootstrapChainFingerprint(getChainFingerprint, connectId, chain);
640
+ if (!fingerprint) {
641
+ return buildFingerprintBootstrapFailure(item, chain);
642
+ }
643
+ chainFingerprints.set(chain, fingerprint);
644
+ return {
645
+ ...item,
646
+ success: true,
647
+ payload: {
648
+ ...payload,
649
+ deviceIdentity: {
650
+ vendor: "ledger",
651
+ type: "chainFingerprint",
652
+ chain,
653
+ value: fingerprint
654
+ },
655
+ chainFingerprint: fingerprint,
656
+ chainFingerprintChain: chain
657
+ }
658
+ };
659
+ }
660
+ async function bootstrapChainFingerprint(getChainFingerprint, connectId, chain) {
661
+ const response = await getChainFingerprint(connectId, chain);
662
+ return response.success ? response.payload : "";
663
+ }
664
+ function buildFingerprintBootstrapFailure(item, chain) {
665
+ return {
666
+ ...item,
667
+ success: false,
668
+ payload: {
669
+ code: import_hwk_adapter_core2.HardwareErrorCode.DeviceMismatch,
670
+ error: `Could not establish chain fingerprint for ${chain} after device call; refusing to return unverifiable result. Please retry.`
671
+ }
672
+ };
673
+ }
674
+ async function callAllNetworkMethod(callChain, connectId, deviceId, method, item, commonParams, installContext) {
675
+ switch (method) {
676
+ case "evmGetAddress":
677
+ return callChain(
678
+ connectId,
679
+ deviceId,
680
+ "evm",
681
+ "evmGetAddress",
682
+ item,
683
+ commonParams,
684
+ false,
685
+ installContext
686
+ );
687
+ case "btcGetAddress":
688
+ return callChain(
689
+ connectId,
690
+ deviceId,
691
+ "btc",
692
+ "btcGetAddress",
693
+ item,
694
+ commonParams,
695
+ false,
696
+ installContext
697
+ );
698
+ case "btcGetPublicKey":
699
+ return callChain(
700
+ connectId,
701
+ deviceId,
702
+ "btc",
703
+ "btcGetPublicKey",
704
+ item,
705
+ commonParams,
706
+ false,
707
+ installContext
708
+ );
709
+ case "solGetAddress":
710
+ return callChain(
711
+ connectId,
712
+ deviceId,
713
+ "sol",
714
+ "solGetAddress",
715
+ item,
716
+ commonParams,
717
+ false,
718
+ installContext
719
+ );
720
+ case "tronGetAddress":
721
+ return callChain(
722
+ connectId,
723
+ deviceId,
724
+ "tron",
725
+ "tronGetAddress",
726
+ item,
727
+ commonParams,
728
+ false,
729
+ installContext
730
+ );
731
+ default:
732
+ throw Object.assign(new Error(`Unsupported allNetwork method: ${method}`), {
733
+ code: import_hwk_adapter_core2.HardwareErrorCode.InvalidParams
734
+ });
735
+ }
736
+ }
737
+
738
+ // src/utils/ledgerDmkTransport.ts
739
+ function isLedgerDmkBleTransport(transport) {
740
+ const normalized = transport?.toUpperCase();
741
+ return normalized === "BLE" || normalized?.endsWith("_BLE") === true;
742
+ }
743
+ function isLedgerBleConnectionType(connectionType) {
744
+ return connectionType === "ble";
745
+ }
746
+ function isLedgerBleDescriptor(connectionType, descriptor) {
747
+ return isLedgerBleConnectionType(connectionType) || isLedgerDmkBleTransport(descriptor.transport);
748
+ }
749
+
491
750
  // src/adapter/LedgerAdapter.ts
492
751
  function formatDeviceMismatchError(expected, actual) {
493
752
  return `Wrong device: expected ${expected}, got ${actual}`;
@@ -503,10 +762,10 @@ function btcAccountIndexFromPath(path) {
503
762
  var _LedgerAdapter = class _LedgerAdapter {
504
763
  constructor(connector, options) {
505
764
  this.vendor = "ledger";
506
- this.emitter = new import_hwk_adapter_core2.TypedEventEmitter();
765
+ this.emitter = new import_hwk_adapter_core3.TypedEventEmitter();
507
766
  this._discoveredDevices = /* @__PURE__ */ new Map();
508
767
  this._sessions = /* @__PURE__ */ new Map();
509
- this._uiRegistry = new import_hwk_adapter_core2.UiRequestRegistry();
768
+ this._uiRegistry = new import_hwk_adapter_core3.UiRequestRegistry();
510
769
  // BTC App rejects account index >= 100 unless display=true. Cached per
511
770
  // adapter instance: first 100+ path asks the user once via UI request,
512
771
  // subsequent 100+ paths in the same session auto-promote silently.
@@ -515,6 +774,11 @@ var _LedgerAdapter = class _LedgerAdapter {
515
774
  this._btcHighIndexConfirmedThisSession = false;
516
775
  // Shared across concurrent callers — only `cancel()` aborts.
517
776
  this._doConnectAbortController = null;
777
+ this._installProgressLastEmittedValue = -Infinity;
778
+ this.allNetworkGetAddress = createAllNetworkGetAddress({
779
+ callChain: this.callChain.bind(this),
780
+ getChainFingerprint: (connectId, chain) => this.getChainFingerprint(connectId, "", chain)
781
+ });
518
782
  // ---------------------------------------------------------------------------
519
783
  // Private helpers
520
784
  // ---------------------------------------------------------------------------
@@ -534,16 +798,16 @@ var _LedgerAdapter = class _LedgerAdapter {
534
798
  const deviceInfo = this.connectorDeviceToDeviceInfo(data.device);
535
799
  this._discoveredDevices.set(deviceInfo.connectId, deviceInfo);
536
800
  this._sessions.delete(deviceInfo.connectId);
537
- this.emitter.emit(import_hwk_adapter_core2.DEVICE.CONNECT, {
538
- type: import_hwk_adapter_core2.DEVICE.CONNECT,
801
+ this.emitter.emit(import_hwk_adapter_core3.DEVICE.CONNECT, {
802
+ type: import_hwk_adapter_core3.DEVICE.CONNECT,
539
803
  payload: deviceInfo
540
804
  });
541
805
  };
542
806
  this.deviceDisconnectHandler = (data) => {
543
807
  this._discoveredDevices.delete(data.connectId);
544
808
  this._sessions.delete(data.connectId);
545
- this.emitter.emit(import_hwk_adapter_core2.DEVICE.DISCONNECT, {
546
- type: import_hwk_adapter_core2.DEVICE.DISCONNECT,
809
+ this.emitter.emit(import_hwk_adapter_core3.DEVICE.DISCONNECT, {
810
+ type: import_hwk_adapter_core3.DEVICE.DISCONNECT,
547
811
  payload: { connectId: data.connectId }
548
812
  });
549
813
  };
@@ -553,7 +817,7 @@ var _LedgerAdapter = class _LedgerAdapter {
553
817
  // exists (race during teardown) we drop. All other variants pass through
554
818
  // unchanged.
555
819
  this.uiEventForwarder = (event) => {
556
- if (event.type === import_hwk_adapter_core2.EConnectorInteraction.AppInstallProgress) {
820
+ if (event.type === import_hwk_adapter_core3.EConnectorInteraction.AppInstallProgress) {
557
821
  let connectId;
558
822
  for (const [cid, sid] of this._sessions) {
559
823
  if (sid === event.payload.sessionId) {
@@ -568,12 +832,23 @@ var _LedgerAdapter = class _LedgerAdapter {
568
832
  );
569
833
  return;
570
834
  }
835
+ const { appName, progress } = event.payload;
836
+ const key = `${connectId}:${appName}`;
837
+ if (this._installProgressLastKey !== key || this._installProgressLastEmittedValue >= 1) {
838
+ this._installProgressLastEmittedValue = -Infinity;
839
+ this._installProgressLastKey = key;
840
+ }
841
+ const delta = progress - this._installProgressLastEmittedValue;
842
+ if (delta < _LedgerAdapter.APP_INSTALL_PROGRESS_MIN_DELTA && progress < 1) {
843
+ return;
844
+ }
845
+ this._installProgressLastEmittedValue = progress;
571
846
  this.emitter.emit("ui-event", {
572
- type: import_hwk_adapter_core2.EConnectorInteraction.AppInstallProgress,
847
+ type: import_hwk_adapter_core3.EConnectorInteraction.AppInstallProgress,
573
848
  payload: {
574
849
  connectId,
575
- appName: event.payload.appName,
576
- progress: event.payload.progress
850
+ appName,
851
+ progress
577
852
  }
578
853
  });
579
854
  return;
@@ -582,7 +857,7 @@ var _LedgerAdapter = class _LedgerAdapter {
582
857
  };
583
858
  this.connector = connector;
584
859
  this._defaultAutoInstallApp = options?.autoInstallApp ?? false;
585
- this._jobQueue = new import_hwk_adapter_core2.DeviceJobQueue();
860
+ this._jobQueue = new import_hwk_adapter_core3.DeviceJobQueue();
586
861
  this.registerEventListeners();
587
862
  }
588
863
  // Transport
@@ -630,30 +905,42 @@ var _LedgerAdapter = class _LedgerAdapter {
630
905
  // Device management
631
906
  // ---------------------------------------------------------------------------
632
907
  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));
908
+ debugLog("[LedgerAdapter][REQ]", { method: "searchDevices", params: options });
909
+ try {
910
+ if (options?.resetSession) {
911
+ this._doConnectAbortController?.abort();
912
+ this._sessions.clear();
913
+ this._connectingPromise = null;
914
+ this._doConnectAbortController = null;
915
+ this._btcHighIndexConfirmedThisSession = false;
646
916
  }
647
- }
648
- if (this._discoveredDevices.size === 0) {
649
917
  await this._ensureDevicePermission();
918
+ const devices = await this.connector.searchDevices();
919
+ this._discoveredDevices.clear();
920
+ for (const d of devices) {
921
+ if (d.connectId) {
922
+ this._discoveredDevices.set(d.connectId, this.connectorDeviceToDeviceInfo(d));
923
+ }
924
+ }
925
+ if (this._discoveredDevices.size === 0) {
926
+ await this._ensureDevicePermission();
927
+ }
928
+ const result = Array.from(this._discoveredDevices.values());
929
+ debugLog("[LedgerAdapter][RES]", {
930
+ method: "searchDevices",
931
+ success: true,
932
+ payload: result
933
+ });
934
+ return result;
935
+ } catch (err) {
936
+ const e = err;
937
+ debugLog("[LedgerAdapter][RES]", {
938
+ method: "searchDevices",
939
+ success: false,
940
+ error: { message: e?.message, _tag: e?._tag, code: e?.code ?? e?.errorCode }
941
+ });
942
+ throw err;
650
943
  }
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
944
  }
658
945
  // USB single-session invariant: evict all sessions, best-effort (see connectDevice).
659
946
  async _evictAllSessions() {
@@ -669,14 +956,15 @@ var _LedgerAdapter = class _LedgerAdapter {
669
956
  }
670
957
  static _createDeviceBusyError(method) {
671
958
  return Object.assign(new Error(`Ledger device is busy while calling ${method}`), {
672
- code: import_hwk_adapter_core2.HardwareErrorCode.DeviceBusy
959
+ code: import_hwk_adapter_core3.HardwareErrorCode.DeviceBusy
673
960
  });
674
961
  }
675
962
  async connectDevice(connectId) {
963
+ debugLog("[LedgerAdapter][REQ]", { method: "connectDevice", connectId, params: { connectId } });
676
964
  try {
677
965
  if (isLedgerBleConnectionType(this.connector.connectionType) && !connectId) {
678
966
  throw Object.assign(new Error("Ledger BLE connectId is required."), {
679
- code: import_hwk_adapter_core2.HardwareErrorCode.DeviceNotFound
967
+ code: import_hwk_adapter_core3.HardwareErrorCode.DeviceNotFound
680
968
  });
681
969
  }
682
970
  if (!isLedgerBleConnectionType(this.connector.connectionType)) {
@@ -688,28 +976,79 @@ var _LedgerAdapter = class _LedgerAdapter {
688
976
  if (session.deviceInfo) {
689
977
  this._discoveredDevices.set(connectId, session.deviceInfo);
690
978
  }
691
- return (0, import_hwk_adapter_core2.success)(connectId);
979
+ const result = (0, import_hwk_adapter_core3.success)(connectId);
980
+ debugLog("[LedgerAdapter][RES]", { method: "connectDevice", success: true, payload: result });
981
+ return result;
692
982
  } catch (err) {
693
- return this.errorToFailure(err);
983
+ const failureResult = this.errorToFailure(err);
984
+ debugLog("[LedgerAdapter][RES]", {
985
+ method: "connectDevice",
986
+ success: false,
987
+ payload: failureResult
988
+ });
989
+ return failureResult;
694
990
  }
695
991
  }
696
992
  async disconnectDevice(connectId) {
697
- const sessionId = this._sessions.get(connectId);
698
- if (sessionId) {
699
- await this.connector.disconnect(sessionId);
700
- this._sessions.delete(connectId);
993
+ debugLog("[LedgerAdapter][REQ]", {
994
+ method: "disconnectDevice",
995
+ connectId,
996
+ params: { connectId }
997
+ });
998
+ try {
999
+ const sessionId = this._sessions.get(connectId);
1000
+ if (sessionId) {
1001
+ await this.connector.disconnect(sessionId);
1002
+ this._sessions.delete(connectId);
1003
+ }
1004
+ debugLog("[LedgerAdapter][RES]", { method: "disconnectDevice", success: true });
1005
+ } catch (err) {
1006
+ const e = err;
1007
+ debugLog("[LedgerAdapter][RES]", {
1008
+ method: "disconnectDevice",
1009
+ success: false,
1010
+ error: { message: e?.message, _tag: e?._tag, code: e?.code ?? e?.errorCode }
1011
+ });
1012
+ throw err;
701
1013
  }
702
1014
  }
703
1015
  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);
1016
+ debugLog("[LedgerAdapter][REQ]", {
1017
+ method: "getDeviceInfo",
1018
+ connectId,
1019
+ params: { connectId, deviceId }
1020
+ });
1021
+ try {
1022
+ await this._ensureDevicePermission(connectId, deviceId);
1023
+ const cached = this._discoveredDevices.get(connectId) ?? Array.from(this._discoveredDevices.values()).find((d) => d.deviceId === deviceId);
1024
+ if (cached) {
1025
+ const result = (0, import_hwk_adapter_core3.success)(cached);
1026
+ debugLog("[LedgerAdapter][RES]", {
1027
+ method: "getDeviceInfo",
1028
+ success: true,
1029
+ payload: result
1030
+ });
1031
+ return result;
1032
+ }
1033
+ const notFound = (0, import_hwk_adapter_core3.failure)(
1034
+ import_hwk_adapter_core3.HardwareErrorCode.DeviceNotFound,
1035
+ "Device not found in cache. Call searchDevices() or wait for a device-connected event first."
1036
+ );
1037
+ debugLog("[LedgerAdapter][RES]", {
1038
+ method: "getDeviceInfo",
1039
+ success: false,
1040
+ payload: notFound
1041
+ });
1042
+ return notFound;
1043
+ } catch (err) {
1044
+ const e = err;
1045
+ debugLog("[LedgerAdapter][RES]", {
1046
+ method: "getDeviceInfo",
1047
+ success: false,
1048
+ error: { message: e?.message, _tag: e?._tag, code: e?.code ?? e?.errorCode }
1049
+ });
1050
+ throw err;
708
1051
  }
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
1052
  }
714
1053
  getSupportedChains() {
715
1054
  return ["evm", "btc", "sol", "tron"];
@@ -717,7 +1056,7 @@ var _LedgerAdapter = class _LedgerAdapter {
717
1056
  // ---------------------------------------------------------------------------
718
1057
  // Chain call helper
719
1058
  // ---------------------------------------------------------------------------
720
- async callChain(connectId, deviceId, chain, method, params, commonParams, skipFingerprint = false) {
1059
+ async callChain(connectId, deviceId, chain, method, params, commonParams, skipFingerprint = false, installContext) {
721
1060
  try {
722
1061
  const result = await this.connectorCall(
723
1062
  connectId,
@@ -729,183 +1068,204 @@ var _LedgerAdapter = class _LedgerAdapter {
729
1068
  skipFingerprint
730
1069
  },
731
1070
  void 0,
732
- commonParams
1071
+ commonParams,
1072
+ installContext
733
1073
  );
734
- return (0, import_hwk_adapter_core2.success)(result);
1074
+ return (0, import_hwk_adapter_core3.success)(result);
735
1075
  } catch (err) {
736
1076
  return this.errorToFailure(err);
737
1077
  }
738
1078
  }
1079
+ static normalizeCallArgs(connectId, deviceId, params) {
1080
+ return {
1081
+ connectId: connectId ?? "",
1082
+ deviceId: deviceId ?? "",
1083
+ params: params ?? {}
1084
+ };
1085
+ }
1086
+ static splitCommonParams(params) {
1087
+ if (params && typeof params === "object") {
1088
+ const {
1089
+ autoInstallApp,
1090
+ passphraseState: _passphraseState,
1091
+ useEmptyPassphrase: _useEmptyPassphrase,
1092
+ ...rest
1093
+ } = params;
1094
+ return {
1095
+ commonParams: {
1096
+ autoInstallApp: typeof autoInstallApp === "boolean" ? autoInstallApp : void 0
1097
+ },
1098
+ rest
1099
+ };
1100
+ }
1101
+ return { commonParams: {}, rest: params ?? {} };
1102
+ }
1103
+ callChainWithMergedParams(connectId, deviceId, chain, method, params) {
1104
+ const normalized = _LedgerAdapter.normalizeCallArgs(connectId, deviceId, params);
1105
+ const { commonParams, rest } = _LedgerAdapter.splitCommonParams(normalized.params);
1106
+ return this.callChain(
1107
+ normalized.connectId,
1108
+ normalized.deviceId,
1109
+ chain,
1110
+ method,
1111
+ rest,
1112
+ commonParams
1113
+ );
1114
+ }
739
1115
  // ---------------------------------------------------------------------------
740
1116
  // EVM chain methods
741
1117
  // ---------------------------------------------------------------------------
742
- evmGetAddress(connectId, deviceId, params, commonParams) {
743
- return this.callChain(
1118
+ evmGetAddress(connectId, deviceId, params) {
1119
+ return this.callChainWithMergedParams(
744
1120
  connectId,
745
1121
  deviceId,
746
1122
  "evm",
747
1123
  "evmGetAddress",
748
- params,
749
- commonParams
1124
+ params
750
1125
  );
751
1126
  }
752
- evmSignTransaction(connectId, deviceId, params, commonParams) {
753
- return this.callChain(
1127
+ evmSignTransaction(connectId, deviceId, params) {
1128
+ return this.callChainWithMergedParams(
754
1129
  connectId,
755
1130
  deviceId,
756
1131
  "evm",
757
1132
  "evmSignTransaction",
758
- params,
759
- commonParams
1133
+ params
760
1134
  );
761
1135
  }
762
- evmSignMessage(connectId, deviceId, params, commonParams) {
763
- return this.callChain(
1136
+ evmSignMessage(connectId, deviceId, params) {
1137
+ return this.callChainWithMergedParams(
764
1138
  connectId,
765
1139
  deviceId,
766
1140
  "evm",
767
1141
  "evmSignMessage",
768
- params,
769
- commonParams
1142
+ params
770
1143
  );
771
1144
  }
772
- evmSignTypedData(connectId, deviceId, params, commonParams) {
773
- return this.callChain(
1145
+ evmSignTypedData(connectId, deviceId, params) {
1146
+ return this.callChainWithMergedParams(
774
1147
  connectId,
775
1148
  deviceId,
776
1149
  "evm",
777
1150
  "evmSignTypedData",
778
- params,
779
- commonParams
1151
+ params
780
1152
  );
781
1153
  }
782
1154
  // ---------------------------------------------------------------------------
783
1155
  // BTC chain methods
784
1156
  // ---------------------------------------------------------------------------
785
- btcGetAddress(connectId, deviceId, params, commonParams) {
786
- return this.callChain(
1157
+ btcGetAddress(connectId, deviceId, params) {
1158
+ return this.callChainWithMergedParams(
787
1159
  connectId,
788
1160
  deviceId,
789
1161
  "btc",
790
1162
  "btcGetAddress",
791
- params,
792
- commonParams
1163
+ params
793
1164
  );
794
1165
  }
795
- btcGetPublicKey(connectId, deviceId, params, commonParams) {
796
- return this.callChain(
1166
+ btcGetPublicKey(connectId, deviceId, params) {
1167
+ return this.callChainWithMergedParams(
797
1168
  connectId,
798
1169
  deviceId,
799
1170
  "btc",
800
1171
  "btcGetPublicKey",
801
- params,
802
- commonParams
1172
+ params
803
1173
  );
804
1174
  }
805
- btcSignTransaction(connectId, deviceId, params, commonParams) {
806
- return this.callChain(
1175
+ btcSignTransaction(connectId, deviceId, params) {
1176
+ return this.callChainWithMergedParams(
807
1177
  connectId,
808
1178
  deviceId,
809
1179
  "btc",
810
1180
  "btcSignTransaction",
811
- params,
812
- commonParams
1181
+ params
813
1182
  );
814
1183
  }
815
- btcSignPsbt(connectId, deviceId, params, commonParams) {
816
- return this.callChain(
1184
+ btcSignPsbt(connectId, deviceId, params) {
1185
+ return this.callChainWithMergedParams(
817
1186
  connectId,
818
1187
  deviceId,
819
1188
  "btc",
820
1189
  "btcSignPsbt",
821
- params,
822
- commonParams
1190
+ params
823
1191
  );
824
1192
  }
825
- btcSignMessage(connectId, deviceId, params, commonParams) {
826
- return this.callChain(
1193
+ btcSignMessage(connectId, deviceId, params) {
1194
+ return this.callChainWithMergedParams(
827
1195
  connectId,
828
1196
  deviceId,
829
1197
  "btc",
830
1198
  "btcSignMessage",
831
- params,
832
- commonParams
1199
+ params
833
1200
  );
834
1201
  }
835
- btcGetMasterFingerprint(connectId, deviceId, commonParams) {
836
- return this.callChain(
1202
+ btcGetMasterFingerprint(connectId, deviceId, params) {
1203
+ return this.callChainWithMergedParams(
837
1204
  connectId,
838
1205
  deviceId,
839
1206
  "btc",
840
1207
  "btcGetMasterFingerprint",
841
- {},
842
- commonParams
1208
+ params
843
1209
  );
844
1210
  }
845
1211
  // ---------------------------------------------------------------------------
846
1212
  // SOL chain methods
847
1213
  // ---------------------------------------------------------------------------
848
- solGetAddress(connectId, deviceId, params, commonParams) {
849
- return this.callChain(
1214
+ solGetAddress(connectId, deviceId, params) {
1215
+ return this.callChainWithMergedParams(
850
1216
  connectId,
851
1217
  deviceId,
852
1218
  "sol",
853
1219
  "solGetAddress",
854
- params,
855
- commonParams
1220
+ params
856
1221
  );
857
1222
  }
858
- solSignTransaction(connectId, deviceId, params, commonParams) {
859
- return this.callChain(
1223
+ solSignTransaction(connectId, deviceId, params) {
1224
+ return this.callChainWithMergedParams(
860
1225
  connectId,
861
1226
  deviceId,
862
1227
  "sol",
863
1228
  "solSignTransaction",
864
- params,
865
- commonParams
1229
+ params
866
1230
  );
867
1231
  }
868
- solSignMessage(connectId, deviceId, params, commonParams) {
869
- return this.callChain(
1232
+ solSignMessage(connectId, deviceId, params) {
1233
+ return this.callChainWithMergedParams(
870
1234
  connectId,
871
1235
  deviceId,
872
1236
  "sol",
873
1237
  "solSignMessage",
874
- params,
875
- commonParams
1238
+ params
876
1239
  );
877
1240
  }
878
1241
  // ---------------------------------------------------------------------------
879
1242
  // TRON chain methods
880
1243
  // ---------------------------------------------------------------------------
881
- tronGetAddress(connectId, deviceId, params, commonParams) {
882
- return this.callChain(
1244
+ tronGetAddress(connectId, deviceId, params) {
1245
+ return this.callChainWithMergedParams(
883
1246
  connectId,
884
1247
  deviceId,
885
1248
  "tron",
886
1249
  "tronGetAddress",
887
- params,
888
- commonParams
1250
+ params
889
1251
  );
890
1252
  }
891
- tronSignTransaction(connectId, deviceId, params, commonParams) {
892
- return this.callChain(
1253
+ tronSignTransaction(connectId, deviceId, params) {
1254
+ return this.callChainWithMergedParams(
893
1255
  connectId,
894
1256
  deviceId,
895
1257
  "tron",
896
1258
  "tronSignTransaction",
897
- params,
898
- commonParams
1259
+ params
899
1260
  );
900
1261
  }
901
- tronSignMessage(connectId, deviceId, params, commonParams) {
902
- return this.callChain(
1262
+ tronSignMessage(connectId, deviceId, params) {
1263
+ return this.callChainWithMergedParams(
903
1264
  connectId,
904
1265
  deviceId,
905
1266
  "tron",
906
1267
  "tronSignMessage",
907
- params,
908
- commonParams
1268
+ params
909
1269
  );
910
1270
  }
911
1271
  // ---------------------------------------------------------------------------
@@ -916,7 +1276,7 @@ var _LedgerAdapter = class _LedgerAdapter {
916
1276
  async installApp(connectId, appName) {
917
1277
  try {
918
1278
  await this.connectorCall(connectId, "installApp", { appName });
919
- return (0, import_hwk_adapter_core2.success)(void 0);
1279
+ return (0, import_hwk_adapter_core3.success)(void 0);
920
1280
  } catch (err) {
921
1281
  return this.errorToFailure(err);
922
1282
  }
@@ -924,7 +1284,16 @@ var _LedgerAdapter = class _LedgerAdapter {
924
1284
  async listInstalledApps(connectId) {
925
1285
  try {
926
1286
  const result = await this.connectorCall(connectId, "listInstalledApps", {});
927
- return (0, import_hwk_adapter_core2.success)(result);
1287
+ return (0, import_hwk_adapter_core3.success)(result);
1288
+ } catch (err) {
1289
+ return this.errorToFailure(err);
1290
+ }
1291
+ }
1292
+ // Offline app-presence + unlock probe. No manager-api catalog (unlike listInstalledApps).
1293
+ async listInstalledNames(connectId) {
1294
+ try {
1295
+ const result = await this.connectorCall(connectId, "listInstalledNames", {});
1296
+ return (0, import_hwk_adapter_core3.success)(result);
928
1297
  } catch (err) {
929
1298
  return this.errorToFailure(err);
930
1299
  }
@@ -932,7 +1301,7 @@ var _LedgerAdapter = class _LedgerAdapter {
932
1301
  async listAvailableApps(connectId) {
933
1302
  try {
934
1303
  const result = await this.connectorCall(connectId, "listAvailableApps", {});
935
- return (0, import_hwk_adapter_core2.success)(result);
1304
+ return (0, import_hwk_adapter_core3.success)(result);
936
1305
  } catch (err) {
937
1306
  return this.errorToFailure(err);
938
1307
  }
@@ -940,7 +1309,7 @@ var _LedgerAdapter = class _LedgerAdapter {
940
1309
  async getLedgerFirmwareVersion(connectId) {
941
1310
  try {
942
1311
  const result = await this.connectorCall(connectId, "getFirmwareVersion", {});
943
- return (0, import_hwk_adapter_core2.success)(result);
1312
+ return (0, import_hwk_adapter_core3.success)(result);
944
1313
  } catch (err) {
945
1314
  return this.errorToFailure(err);
946
1315
  }
@@ -948,7 +1317,7 @@ var _LedgerAdapter = class _LedgerAdapter {
948
1317
  async getLedgerDeviceInfo(connectId) {
949
1318
  try {
950
1319
  const result = await this.connectorCall(connectId, "getDeviceInfo", {});
951
- return (0, import_hwk_adapter_core2.success)(result);
1320
+ return (0, import_hwk_adapter_core3.success)(result);
952
1321
  } catch (err) {
953
1322
  return this.errorToFailure(err);
954
1323
  }
@@ -961,7 +1330,7 @@ var _LedgerAdapter = class _LedgerAdapter {
961
1330
  }
962
1331
  cancel(connectId) {
963
1332
  const userAbortReason = Object.assign(new Error("User aborted operation"), {
964
- code: import_hwk_adapter_core2.HardwareErrorCode.UserAborted,
1333
+ code: import_hwk_adapter_core3.HardwareErrorCode.UserAborted,
965
1334
  _tag: ERROR_TAG.UserAborted
966
1335
  });
967
1336
  this._lastCancelReason = userAbortReason;
@@ -995,7 +1364,7 @@ var _LedgerAdapter = class _LedgerAdapter {
995
1364
  chain,
996
1365
  (method, params) => this.connectorCall(connectId, method, params, void 0, deviceId)
997
1366
  );
998
- return (0, import_hwk_adapter_core2.success)(fingerprint);
1367
+ return (0, import_hwk_adapter_core3.success)(fingerprint);
999
1368
  } catch (err) {
1000
1369
  debugError("[LedgerAdapter] getChainFingerprint error:", chain, err);
1001
1370
  return this.errorToFailure(err);
@@ -1018,7 +1387,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1018
1387
  return { success: false, expected: deviceId, actual: fingerprint };
1019
1388
  } catch (err) {
1020
1389
  const mapped = mapLedgerError(err);
1021
- if (mapped.code === import_hwk_adapter_core2.HardwareErrorCode.WrongApp || mapped.code === import_hwk_adapter_core2.HardwareErrorCode.DeviceLocked) {
1390
+ if (mapped.code === import_hwk_adapter_core3.HardwareErrorCode.WrongApp || mapped.code === import_hwk_adapter_core3.HardwareErrorCode.DeviceLocked) {
1022
1391
  return { success: true };
1023
1392
  }
1024
1393
  throw err;
@@ -1043,7 +1412,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1043
1412
  const result = await callMethod("btcGetMasterFingerprint", {});
1044
1413
  return result.masterFingerprint;
1045
1414
  }
1046
- const path = import_hwk_adapter_core2.CHAIN_FINGERPRINT_PATHS[chain];
1415
+ const path = import_hwk_adapter_core3.CHAIN_FINGERPRINT_PATHS[chain];
1047
1416
  let address;
1048
1417
  if (chain === "evm") {
1049
1418
  address = (await callMethod("evmGetAddress", { path, showOnDevice: false })).address.toLowerCase();
@@ -1054,7 +1423,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1054
1423
  } else {
1055
1424
  throw new Error(`Unsupported chain for fingerprint: ${chain}`);
1056
1425
  }
1057
- return (0, import_hwk_adapter_core2.deriveDeviceFingerprint)(address);
1426
+ return (0, import_hwk_adapter_core3.deriveDeviceFingerprint)(address);
1058
1427
  }
1059
1428
  // Ledger WebUSB won't expose a locked device, so we can't auto-detect unlock.
1060
1429
  // The user must press Confirm after unlocking, which triggers a search retry.
@@ -1066,10 +1435,10 @@ var _LedgerAdapter = class _LedgerAdapter {
1066
1435
  _LedgerAdapter._throwIfAborted(signal);
1067
1436
  }
1068
1437
  const waitPromise = this._uiRegistry.wait(
1069
- import_hwk_adapter_core2.UI_REQUEST.REQUEST_DEVICE_CONNECT
1438
+ import_hwk_adapter_core3.UI_REQUEST.REQUEST_DEVICE_CONNECT
1070
1439
  );
1071
- this.emitter.emit(import_hwk_adapter_core2.UI_REQUEST.REQUEST_DEVICE_CONNECT, {
1072
- type: import_hwk_adapter_core2.UI_REQUEST.REQUEST_DEVICE_CONNECT,
1440
+ this.emitter.emit(import_hwk_adapter_core3.UI_REQUEST.REQUEST_DEVICE_CONNECT, {
1441
+ type: import_hwk_adapter_core3.UI_REQUEST.REQUEST_DEVICE_CONNECT,
1073
1442
  payload: {
1074
1443
  vendor: "ledger",
1075
1444
  reason: "device-not-found",
@@ -1080,7 +1449,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1080
1449
  try {
1081
1450
  if (signal) {
1082
1451
  const onAbort = () => {
1083
- this._uiRegistry.cancel(import_hwk_adapter_core2.UI_REQUEST.REQUEST_DEVICE_CONNECT);
1452
+ this._uiRegistry.cancel(import_hwk_adapter_core3.UI_REQUEST.REQUEST_DEVICE_CONNECT);
1084
1453
  };
1085
1454
  signal.addEventListener("abort", onAbort, { once: true });
1086
1455
  try {
@@ -1092,20 +1461,20 @@ var _LedgerAdapter = class _LedgerAdapter {
1092
1461
  payload = await waitPromise;
1093
1462
  }
1094
1463
  } 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,
1464
+ this.emitter.emit(import_hwk_adapter_core3.UI_REQUEST.CLOSE_UI_WINDOW, {
1465
+ type: import_hwk_adapter_core3.UI_REQUEST.CLOSE_UI_WINDOW,
1097
1466
  payload: {}
1098
1467
  });
1099
1468
  throw Object.assign(new Error("User cancelled Ledger connection"), {
1100
1469
  _tag: ERROR_TAG.UserAborted,
1101
- code: import_hwk_adapter_core2.HardwareErrorCode.UserAborted,
1470
+ code: import_hwk_adapter_core3.HardwareErrorCode.UserAborted,
1102
1471
  cause: err
1103
1472
  });
1104
1473
  }
1105
1474
  if (!payload?.confirmed) {
1106
1475
  throw Object.assign(new Error("User cancelled Ledger connection"), {
1107
1476
  _tag: ERROR_TAG.UserAborted,
1108
- code: import_hwk_adapter_core2.HardwareErrorCode.UserAborted
1477
+ code: import_hwk_adapter_core3.HardwareErrorCode.UserAborted
1109
1478
  });
1110
1479
  }
1111
1480
  await new Promise((resolve) => {
@@ -1135,10 +1504,10 @@ var _LedgerAdapter = class _LedgerAdapter {
1135
1504
  }
1136
1505
  async _waitForBtcHighIndexConfirm(path, accountIndex) {
1137
1506
  const waitPromise = this._uiRegistry.wait(
1138
- import_hwk_adapter_core2.UI_REQUEST.REQUEST_BTC_HIGH_INDEX_CONFIRM
1507
+ import_hwk_adapter_core3.UI_REQUEST.REQUEST_BTC_HIGH_INDEX_CONFIRM
1139
1508
  );
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,
1509
+ this.emitter.emit(import_hwk_adapter_core3.UI_REQUEST.REQUEST_BTC_HIGH_INDEX_CONFIRM, {
1510
+ type: import_hwk_adapter_core3.UI_REQUEST.REQUEST_BTC_HIGH_INDEX_CONFIRM,
1142
1511
  payload: {
1143
1512
  vendor: "ledger",
1144
1513
  path,
@@ -1149,8 +1518,8 @@ var _LedgerAdapter = class _LedgerAdapter {
1149
1518
  const payload = await waitPromise;
1150
1519
  return !!payload?.confirmed;
1151
1520
  } 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,
1521
+ this.emitter.emit(import_hwk_adapter_core3.UI_REQUEST.CLOSE_UI_WINDOW, {
1522
+ type: import_hwk_adapter_core3.UI_REQUEST.CLOSE_UI_WINDOW,
1154
1523
  payload: {}
1155
1524
  });
1156
1525
  return false;
@@ -1160,18 +1529,18 @@ var _LedgerAdapter = class _LedgerAdapter {
1160
1529
  // Same register-then-emit ordering as the BTC high-index gate.
1161
1530
  async _waitForInstallAppConfirm(appName) {
1162
1531
  const waitPromise = this._uiRegistry.wait(
1163
- import_hwk_adapter_core2.UI_REQUEST.REQUEST_INSTALL_APP
1532
+ import_hwk_adapter_core3.UI_REQUEST.REQUEST_INSTALL_APP
1164
1533
  );
1165
- this.emitter.emit(import_hwk_adapter_core2.UI_REQUEST.REQUEST_INSTALL_APP, {
1166
- type: import_hwk_adapter_core2.UI_REQUEST.REQUEST_INSTALL_APP,
1534
+ this.emitter.emit(import_hwk_adapter_core3.UI_REQUEST.REQUEST_INSTALL_APP, {
1535
+ type: import_hwk_adapter_core3.UI_REQUEST.REQUEST_INSTALL_APP,
1167
1536
  payload: { vendor: "ledger", appName }
1168
1537
  });
1169
1538
  try {
1170
1539
  const payload = await waitPromise;
1171
1540
  return !!payload?.confirmed;
1172
1541
  } 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,
1542
+ this.emitter.emit(import_hwk_adapter_core3.UI_REQUEST.CLOSE_UI_WINDOW, {
1543
+ type: import_hwk_adapter_core3.UI_REQUEST.CLOSE_UI_WINDOW,
1175
1544
  payload: {}
1176
1545
  });
1177
1546
  return false;
@@ -1184,7 +1553,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1184
1553
  if (signal.aborted) _LedgerAdapter._throwIfAborted(signal);
1185
1554
  if (isLedgerBleConnectionType(this.connector.connectionType) && !connectId) {
1186
1555
  throw Object.assign(new Error("Ledger BLE connectId is required."), {
1187
- code: import_hwk_adapter_core2.HardwareErrorCode.DeviceNotFound
1556
+ code: import_hwk_adapter_core3.HardwareErrorCode.DeviceNotFound
1188
1557
  });
1189
1558
  }
1190
1559
  if (connectId && this._sessions.has(connectId)) return connectId;
@@ -1194,7 +1563,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1194
1563
  new Error(
1195
1564
  "Ledger USB session invariant violated: more than one session is active. Please reconnect the device."
1196
1565
  ),
1197
- { code: import_hwk_adapter_core2.HardwareErrorCode.DeviceOneDeviceOnly }
1566
+ { code: import_hwk_adapter_core3.HardwareErrorCode.DeviceOneDeviceOnly }
1198
1567
  );
1199
1568
  }
1200
1569
  return this._sessions.keys().next().value;
@@ -1236,14 +1605,14 @@ var _LedgerAdapter = class _LedgerAdapter {
1236
1605
  let confirms = 0;
1237
1606
  while (!internalSignal.aborted) {
1238
1607
  this.emitter.emit("ui-event", {
1239
- type: import_hwk_adapter_core2.EConnectorInteraction.Searching,
1608
+ type: import_hwk_adapter_core3.EConnectorInteraction.Searching,
1240
1609
  payload: { sessionId: "" }
1241
1610
  });
1242
1611
  let devices = await this.searchDevices();
1243
1612
  if (devices.length === 0) {
1244
1613
  for (let i = 0; i < 3 && !internalSignal.aborted; i += 1) {
1245
1614
  await new Promise((resolve) => {
1246
- setTimeout(resolve, 1e3);
1615
+ setTimeout(resolve, import_hwk_adapter_core3.DEVICE_CONNECT_RETRY_DELAY_MS);
1247
1616
  });
1248
1617
  devices = await this.searchDevices();
1249
1618
  if (devices.length > 0) break;
@@ -1274,7 +1643,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1274
1643
  new Error(
1275
1644
  "Device not connected after multiple attempts. Please ensure your Ledger is awake, unlocked, and in range, then try again."
1276
1645
  ),
1277
- { code: import_hwk_adapter_core2.HardwareErrorCode.DeviceNotFound }
1646
+ { code: import_hwk_adapter_core3.HardwareErrorCode.DeviceNotFound }
1278
1647
  );
1279
1648
  }
1280
1649
  await this._waitForDeviceConnect(internalSignal);
@@ -1298,7 +1667,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1298
1667
  return this._connectDeviceOrThrow(devices[0].connectId);
1299
1668
  }
1300
1669
  const err = Object.assign(new Error(`Target Ledger unavailable: ${targetConnectId}`), {
1301
- code: import_hwk_adapter_core2.HardwareErrorCode.DeviceNotFound
1670
+ code: import_hwk_adapter_core3.HardwareErrorCode.DeviceNotFound
1302
1671
  });
1303
1672
  if (isLedgerBleConnectionType(this.connector.connectionType)) {
1304
1673
  err._tag = ERROR_TAG.DeviceNotAdvertising;
@@ -1307,7 +1676,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1307
1676
  }
1308
1677
  if (isLedgerBleConnectionType(this.connector.connectionType)) {
1309
1678
  throw Object.assign(new Error("Ledger BLE connectId is required."), {
1310
- code: import_hwk_adapter_core2.HardwareErrorCode.DeviceNotFound
1679
+ code: import_hwk_adapter_core3.HardwareErrorCode.DeviceNotFound
1311
1680
  });
1312
1681
  }
1313
1682
  if (devices.length > 1) {
@@ -1315,7 +1684,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1315
1684
  }
1316
1685
  if (devices.length !== 1) {
1317
1686
  throw Object.assign(new Error("Ledger device not found."), {
1318
- code: import_hwk_adapter_core2.HardwareErrorCode.DeviceNotFound
1687
+ code: import_hwk_adapter_core3.HardwareErrorCode.DeviceNotFound
1319
1688
  });
1320
1689
  }
1321
1690
  return this._connectDeviceOrThrow(devices[0].connectId);
@@ -1353,7 +1722,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1353
1722
  */
1354
1723
  _unwrapConnectorResult(result) {
1355
1724
  if (result.success) return result.payload;
1356
- throw (0, import_hwk_adapter_core2.rehydrateConnectorError)(result.error);
1725
+ throw (0, import_hwk_adapter_core3.rehydrateConnectorError)(result.error);
1357
1726
  }
1358
1727
  /**
1359
1728
  * `connector.call` + result unwrap, optionally raced against an abort
@@ -1366,26 +1735,43 @@ var _LedgerAdapter = class _LedgerAdapter {
1366
1735
  const result = signal ? await this._abortable(signal, promise) : await promise;
1367
1736
  return this._unwrapConnectorResult(result);
1368
1737
  }
1369
- async connectorCall(connectId, method, params, fingerprint, permissionDeviceId, commonParams) {
1370
- debugLog("[LedgerAdapter] connectorCall:", method, "connectId:", connectId || "(empty)");
1738
+ async connectorCall(connectId, method, params, fingerprint, permissionDeviceId, commonParams, installContext) {
1739
+ debugLog("[LedgerAdapter][REQ]", { method, connectId: connectId || "(empty)", params });
1371
1740
  const queueKey = connectId || "__ledger_default__";
1372
- return this._jobQueue.enqueue(
1373
- queueKey,
1374
- async (signal) => this._runConnectorCall(
1375
- connectId,
1741
+ try {
1742
+ const result = await this._jobQueue.enqueue(
1743
+ queueKey,
1744
+ async (signal) => this._runConnectorCall(
1745
+ connectId,
1746
+ method,
1747
+ params,
1748
+ signal,
1749
+ fingerprint,
1750
+ permissionDeviceId,
1751
+ commonParams,
1752
+ installContext
1753
+ ),
1754
+ {
1755
+ label: method,
1756
+ rejectIfBusy: true,
1757
+ busyError: _LedgerAdapter._createDeviceBusyError(method)
1758
+ }
1759
+ );
1760
+ debugLog("[LedgerAdapter][RES]", { method, success: true, payload: result });
1761
+ return result;
1762
+ } catch (err) {
1763
+ const e = err;
1764
+ debugLog("[LedgerAdapter][RES]", {
1376
1765
  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
- );
1766
+ success: false,
1767
+ error: {
1768
+ message: e?.message,
1769
+ _tag: e?._tag,
1770
+ code: e?.code ?? e?.errorCode
1771
+ }
1772
+ });
1773
+ throw err;
1774
+ }
1389
1775
  }
1390
1776
  /**
1391
1777
  * Race a promise against an abort signal. On abort, rejects with
@@ -1420,7 +1806,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1420
1806
  }
1421
1807
  }
1422
1808
  /** Actual work done under the job queue — connection, fingerprint, call, and recovery. */
1423
- async _runConnectorCall(connectId, method, params, signal, fingerprint, permissionDeviceId, commonParams) {
1809
+ async _runConnectorCall(connectId, method, params, signal, fingerprint, permissionDeviceId, commonParams, installContext) {
1424
1810
  _LedgerAdapter._throwIfAborted(signal);
1425
1811
  await this._ensureDevicePermission(
1426
1812
  connectId,
@@ -1434,7 +1820,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1434
1820
  if (gatedParams === null) {
1435
1821
  throw Object.assign(new Error("User cancelled BTC high-index confirmation"), {
1436
1822
  _tag: ERROR_TAG.UserAborted,
1437
- code: import_hwk_adapter_core2.HardwareErrorCode.UserAborted
1823
+ code: import_hwk_adapter_core3.HardwareErrorCode.UserAborted
1438
1824
  });
1439
1825
  }
1440
1826
  effectiveParams = gatedParams;
@@ -1463,7 +1849,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1463
1849
  );
1464
1850
  if (!fp.success) {
1465
1851
  throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {
1466
- code: import_hwk_adapter_core2.HardwareErrorCode.DeviceMismatch
1852
+ code: import_hwk_adapter_core3.HardwareErrorCode.DeviceMismatch
1467
1853
  });
1468
1854
  }
1469
1855
  }
@@ -1482,22 +1868,62 @@ var _LedgerAdapter = class _LedgerAdapter {
1482
1868
  isStuckApp: isStuckAppStateError(err)
1483
1869
  });
1484
1870
  const autoInstallApp = commonParams?.autoInstallApp ?? this._defaultAutoInstallApp;
1485
- const isAppMissing = isAppNotInstalledError(err) || err?.code === import_hwk_adapter_core2.HardwareErrorCode.AppNotInstalled;
1871
+ const isAppMissing = isAppNotInstalledError(err) || err?.code === import_hwk_adapter_core3.HardwareErrorCode.AppNotInstalled;
1486
1872
  if (autoInstallApp && isAppMissing) {
1873
+ if (installContext?.deviceOutOfMemoryError) {
1874
+ throw installContext.deviceOutOfMemoryError;
1875
+ }
1487
1876
  const appName = err?.appName ?? mapLedgerError(err).appName;
1488
1877
  if (appName) {
1878
+ if (installContext?.installAttemptedAppNames?.has(appName)) {
1879
+ throw (0, import_hwk_adapter_core3.createHwkError)({
1880
+ code: import_hwk_adapter_core3.HardwareErrorCode.AppNotInstalled,
1881
+ message: `${appName} install reported success but the app is still missing on device`,
1882
+ _tag: ERROR_TAG.AppInstallVerifyFailed,
1883
+ appName
1884
+ });
1885
+ }
1489
1886
  const confirmed = await this._waitForInstallAppConfirm(appName);
1490
- if (!confirmed) throw err;
1887
+ if (!confirmed) {
1888
+ throw (0, import_hwk_adapter_core3.createHwkError)({
1889
+ code: import_hwk_adapter_core3.HardwareErrorCode.UserAborted,
1890
+ message: `User declined to install ${appName}`,
1891
+ _tag: ERROR_TAG.UserAborted,
1892
+ appName
1893
+ });
1894
+ }
1491
1895
  this.emitter.emit("ui-event", {
1492
- type: import_hwk_adapter_core2.EConnectorInteraction.AppInstallProgress,
1896
+ type: import_hwk_adapter_core3.EConnectorInteraction.AppInstallProgress,
1493
1897
  payload: { connectId: resolvedConnectId, appName, progress: 0 }
1494
1898
  });
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,
1899
+ try {
1900
+ await this._callConnector(sessionId, "installApp", { appName }, signal);
1901
+ } catch (installErr) {
1902
+ if (mapLedgerError(installErr).code === import_hwk_adapter_core3.HardwareErrorCode.DeviceOutOfMemory) {
1903
+ if (installContext) {
1904
+ installContext.deviceOutOfMemoryError = installErr;
1905
+ }
1906
+ }
1907
+ throw installErr;
1908
+ }
1909
+ if (installContext) {
1910
+ installContext.installAttemptedAppNames = installContext.installAttemptedAppNames ?? /* @__PURE__ */ new Set();
1911
+ installContext.installAttemptedAppNames.add(appName);
1912
+ }
1913
+ this.emitter.emit(import_hwk_adapter_core3.UI_REQUEST.CLOSE_UI_WINDOW, {
1914
+ type: import_hwk_adapter_core3.UI_REQUEST.CLOSE_UI_WINDOW,
1498
1915
  payload: {}
1499
1916
  });
1500
- return await this._callConnector(sessionId, method, effectiveParams, signal);
1917
+ return await this._runConnectorCall(
1918
+ resolvedConnectId,
1919
+ method,
1920
+ effectiveParams,
1921
+ signal,
1922
+ fingerprint,
1923
+ permissionDeviceId,
1924
+ commonParams,
1925
+ installContext
1926
+ );
1501
1927
  }
1502
1928
  }
1503
1929
  if (isStuckAppStateError(err)) {
@@ -1572,7 +1998,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1572
1998
  );
1573
1999
  if (!fp.success) {
1574
2000
  throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {
1575
- code: import_hwk_adapter_core2.HardwareErrorCode.DeviceMismatch
2001
+ code: import_hwk_adapter_core3.HardwareErrorCode.DeviceMismatch
1576
2002
  });
1577
2003
  }
1578
2004
  }
@@ -1607,7 +2033,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1607
2033
  this.connector.reset();
1608
2034
  const codeNum = err?.code;
1609
2035
  throw Object.assign(err, {
1610
- code: codeNum ?? import_hwk_adapter_core2.HardwareErrorCode.DeviceDisconnected
2036
+ code: codeNum ?? import_hwk_adapter_core3.HardwareErrorCode.DeviceDisconnected
1611
2037
  });
1612
2038
  }
1613
2039
  throw err;
@@ -1641,7 +2067,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1641
2067
  );
1642
2068
  if (!fp.success) {
1643
2069
  throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {
1644
- code: import_hwk_adapter_core2.HardwareErrorCode.DeviceMismatch
2070
+ code: import_hwk_adapter_core3.HardwareErrorCode.DeviceMismatch
1645
2071
  });
1646
2072
  }
1647
2073
  }
@@ -1698,7 +2124,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1698
2124
  );
1699
2125
  if (!fp.success) {
1700
2126
  throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {
1701
- code: import_hwk_adapter_core2.HardwareErrorCode.DeviceMismatch
2127
+ code: import_hwk_adapter_core3.HardwareErrorCode.DeviceMismatch
1702
2128
  });
1703
2129
  }
1704
2130
  }
@@ -1739,7 +2165,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1739
2165
  );
1740
2166
  if (!fp.success) {
1741
2167
  throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {
1742
- code: import_hwk_adapter_core2.HardwareErrorCode.DeviceMismatch
2168
+ code: import_hwk_adapter_core3.HardwareErrorCode.DeviceMismatch
1743
2169
  });
1744
2170
  }
1745
2171
  }
@@ -1764,16 +2190,16 @@ var _LedgerAdapter = class _LedgerAdapter {
1764
2190
  }
1765
2191
  const transportType = this.activeTransport ?? "hid";
1766
2192
  const waitPromise = this._uiRegistry.wait(
1767
- import_hwk_adapter_core2.UI_REQUEST.REQUEST_DEVICE_PERMISSION,
2193
+ import_hwk_adapter_core3.UI_REQUEST.REQUEST_DEVICE_PERMISSION,
1768
2194
  { timeoutMs: 6e4 }
1769
2195
  );
1770
- this.emitter.emit(import_hwk_adapter_core2.UI_REQUEST.REQUEST_DEVICE_PERMISSION, {
1771
- type: import_hwk_adapter_core2.UI_REQUEST.REQUEST_DEVICE_PERMISSION,
2196
+ this.emitter.emit(import_hwk_adapter_core3.UI_REQUEST.REQUEST_DEVICE_PERMISSION, {
2197
+ type: import_hwk_adapter_core3.UI_REQUEST.REQUEST_DEVICE_PERMISSION,
1772
2198
  payload: { transportType, connectId, deviceId }
1773
2199
  });
1774
2200
  let response;
1775
2201
  const onAbort = () => {
1776
- this._uiRegistry.cancel(import_hwk_adapter_core2.UI_REQUEST.REQUEST_DEVICE_PERMISSION);
2202
+ this._uiRegistry.cancel(import_hwk_adapter_core3.UI_REQUEST.REQUEST_DEVICE_PERMISSION);
1777
2203
  };
1778
2204
  try {
1779
2205
  signal?.addEventListener("abort", onAbort, { once: true });
@@ -1782,14 +2208,14 @@ var _LedgerAdapter = class _LedgerAdapter {
1782
2208
  if (signal?.aborted) {
1783
2209
  _LedgerAdapter._throwIfAborted(signal);
1784
2210
  }
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,
2211
+ if (err?._tag === import_hwk_adapter_core3.UI_REQUEST_PREEMPTED_TAG) {
2212
+ this.emitter.emit(import_hwk_adapter_core3.UI_REQUEST.CLOSE_UI_WINDOW, {
2213
+ type: import_hwk_adapter_core3.UI_REQUEST.CLOSE_UI_WINDOW,
1788
2214
  payload: {}
1789
2215
  });
1790
2216
  throw Object.assign(new Error("Device permission request superseded"), {
1791
2217
  _tag: ERROR_TAG.UserAborted,
1792
- code: import_hwk_adapter_core2.HardwareErrorCode.UserAborted,
2218
+ code: import_hwk_adapter_core3.HardwareErrorCode.UserAborted,
1793
2219
  cause: err
1794
2220
  });
1795
2221
  }
@@ -1800,7 +2226,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1800
2226
  const { granted, reason, message } = response;
1801
2227
  if (!granted) {
1802
2228
  throw Object.assign(new Error(message ?? "Device permission denied"), {
1803
- code: import_hwk_adapter_core2.HardwareErrorCode.DevicePermissionDenied,
2229
+ code: import_hwk_adapter_core3.HardwareErrorCode.DevicePermissionDenied,
1804
2230
  reason
1805
2231
  });
1806
2232
  }
@@ -1814,7 +2240,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1814
2240
  const tag = err && typeof err === "object" ? err._tag : void 0;
1815
2241
  if (err && typeof err === "object" && "code" in err && typeof err.code === "number") {
1816
2242
  const e = err;
1817
- const params = e.code === import_hwk_adapter_core2.HardwareErrorCode.DevicePermissionDenied && e.reason ? { permissionDeniedReason: e.reason } : e.params;
2243
+ const params = e.code === import_hwk_adapter_core3.HardwareErrorCode.DevicePermissionDenied && e.reason ? { permissionDeniedReason: e.reason } : e.params;
1818
2244
  return ledgerFailure(e.code, e.message ?? "Unknown error", e.appName, tag, params);
1819
2245
  }
1820
2246
  const mapped = mapLedgerError(err);
@@ -1861,10 +2287,13 @@ _LedgerAdapter.STUCK_APP_RETRY_DELAY_MS = 500;
1861
2287
  // Confirm but device never shows up / never unlocks), throw DeviceNotFound
1862
2288
  // instead of looping forever.
1863
2289
  _LedgerAdapter.MAX_DOCONNECT_CONFIRMS = 3;
2290
+ // Throttle AppInstallProgress by progress delta — DMK streams much faster
2291
+ // than UIs need. Final frame (progress >= 1) always passes.
2292
+ _LedgerAdapter.APP_INSTALL_PROGRESS_MIN_DELTA = 0.05;
1864
2293
  var LedgerAdapter = _LedgerAdapter;
1865
2294
 
1866
2295
  // src/connector/LedgerConnectorBase.ts
1867
- var import_hwk_adapter_core12 = require("@onekeyfe/hwk-adapter-core");
2296
+ var import_hwk_adapter_core13 = require("@onekeyfe/hwk-adapter-core");
1868
2297
 
1869
2298
  // src/device/LedgerDeviceManager.ts
1870
2299
  var LedgerDeviceManager = class {
@@ -2137,7 +2566,7 @@ var import_device_signer_kit_ethereum = require("@ledgerhq/device-signer-kit-eth
2137
2566
  var import_context_module = require("@ledgerhq/context-module");
2138
2567
 
2139
2568
  // src/signer/SignerEth.ts
2140
- var import_hwk_adapter_core3 = require("@onekeyfe/hwk-adapter-core");
2569
+ var import_hwk_adapter_core4 = require("@onekeyfe/hwk-adapter-core");
2141
2570
 
2142
2571
  // src/signer/deviceActionToPromise.ts
2143
2572
  var import_device_management_kit = require("@ledgerhq/device-management-kit");
@@ -2350,7 +2779,7 @@ var SignerEth = class {
2350
2779
  );
2351
2780
  }
2352
2781
  async signTransaction(derivationPath, serializedTxHex) {
2353
- const action = this._sdk.signTransaction(derivationPath, (0, import_hwk_adapter_core3.hexToBytes)(serializedTxHex));
2782
+ const action = this._sdk.signTransaction(derivationPath, (0, import_hwk_adapter_core4.hexToBytes)(serializedTxHex));
2354
2783
  return deviceActionToPromise(
2355
2784
  action,
2356
2785
  this.onInteraction,
@@ -2359,7 +2788,7 @@ var SignerEth = class {
2359
2788
  );
2360
2789
  }
2361
2790
  async signMessage(derivationPath, message) {
2362
- const action = this._sdk.signMessage(derivationPath, (0, import_hwk_adapter_core3.hexToBytes)(message));
2791
+ const action = this._sdk.signMessage(derivationPath, (0, import_hwk_adapter_core4.hexToBytes)(message));
2363
2792
  return deviceActionToPromise(
2364
2793
  action,
2365
2794
  this.onInteraction,
@@ -2419,23 +2848,23 @@ var SignerManager = class _SignerManager {
2419
2848
  };
2420
2849
 
2421
2850
  // src/connector/chains/evm.ts
2422
- var import_hwk_adapter_core5 = require("@onekeyfe/hwk-adapter-core");
2851
+ var import_hwk_adapter_core6 = require("@onekeyfe/hwk-adapter-core");
2423
2852
 
2424
2853
  // src/connector/chains/utils.ts
2425
- var import_hwk_adapter_core4 = require("@onekeyfe/hwk-adapter-core");
2854
+ var import_hwk_adapter_core5 = require("@onekeyfe/hwk-adapter-core");
2426
2855
  function normalizePath(path) {
2427
2856
  return path.startsWith("m/") ? path.slice(2) : path;
2428
2857
  }
2429
2858
  function collapseSignerInteraction(interaction) {
2430
2859
  switch (interaction) {
2431
2860
  case "confirm-open-app":
2432
- return import_hwk_adapter_core4.EConnectorInteraction.ConfirmOpenApp;
2861
+ return import_hwk_adapter_core5.EConnectorInteraction.ConfirmOpenApp;
2433
2862
  case "unlock-device":
2434
- return import_hwk_adapter_core4.EConnectorInteraction.UnlockDevice;
2863
+ return import_hwk_adapter_core5.EConnectorInteraction.UnlockDevice;
2435
2864
  case "interaction-complete":
2436
- return import_hwk_adapter_core4.EConnectorInteraction.InteractionComplete;
2865
+ return import_hwk_adapter_core5.EConnectorInteraction.InteractionComplete;
2437
2866
  default:
2438
- return import_hwk_adapter_core4.EConnectorInteraction.ConfirmOnDevice;
2867
+ return import_hwk_adapter_core5.EConnectorInteraction.ConfirmOnDevice;
2439
2868
  }
2440
2869
  }
2441
2870
 
@@ -2461,7 +2890,7 @@ async function evmSignTransaction(ctx, sessionId, params) {
2461
2890
  new Error(
2462
2891
  "Ledger requires a pre-serialized transaction (serializedTx). Provide an RLP-encoded hex string."
2463
2892
  ),
2464
- { code: import_hwk_adapter_core5.HardwareErrorCode.InvalidParams }
2893
+ { code: import_hwk_adapter_core6.HardwareErrorCode.InvalidParams }
2465
2894
  );
2466
2895
  }
2467
2896
  const signer = await _getEthSigner(ctx, sessionId);
@@ -2470,8 +2899,8 @@ async function evmSignTransaction(ctx, sessionId, params) {
2470
2899
  const result = await signer.signTransaction(path, params.serializedTx);
2471
2900
  return {
2472
2901
  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)
2902
+ r: (0, import_hwk_adapter_core6.padHex64)(result.r),
2903
+ s: (0, import_hwk_adapter_core6.padHex64)(result.s)
2475
2904
  };
2476
2905
  } catch (err) {
2477
2906
  ctx.invalidateSession(sessionId);
@@ -2485,8 +2914,8 @@ async function evmSignMessage(ctx, sessionId, params) {
2485
2914
  const path = normalizePath(params.path);
2486
2915
  try {
2487
2916
  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");
2917
+ const rHex = (0, import_hwk_adapter_core6.stripHex)(result.r).padStart(64, "0");
2918
+ const sHex = (0, import_hwk_adapter_core6.stripHex)(result.s).padStart(64, "0");
2490
2919
  const vHex = result.v.toString(16).padStart(2, "0");
2491
2920
  return { signature: `0x${rHex}${sHex}${vHex}` };
2492
2921
  } catch (err) {
@@ -2502,15 +2931,15 @@ async function evmSignTypedData(ctx, sessionId, params) {
2502
2931
  new Error(
2503
2932
  'Ledger does not support hash-only EIP-712 signing. Use mode "full" with the complete typed data structure.'
2504
2933
  ),
2505
- { code: import_hwk_adapter_core5.HardwareErrorCode.MethodNotSupported }
2934
+ { code: import_hwk_adapter_core6.HardwareErrorCode.MethodNotSupported }
2506
2935
  );
2507
2936
  }
2508
2937
  const signer = await _getEthSigner(ctx, sessionId);
2509
2938
  const path = normalizePath(params.path);
2510
2939
  try {
2511
2940
  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");
2941
+ const rHex = (0, import_hwk_adapter_core6.stripHex)(result.r).padStart(64, "0");
2942
+ const sHex = (0, import_hwk_adapter_core6.stripHex)(result.s).padStart(64, "0");
2514
2943
  const vHex = result.v.toString(16).padStart(2, "0");
2515
2944
  return { signature: `0x${rHex}${sHex}${vHex}` };
2516
2945
  } catch (err) {
@@ -2537,13 +2966,13 @@ async function _getEthSigner(ctx, sessionId) {
2537
2966
  }
2538
2967
 
2539
2968
  // src/connector/chains/btc.ts
2540
- var import_hwk_adapter_core7 = require("@onekeyfe/hwk-adapter-core");
2969
+ var import_hwk_adapter_core8 = require("@onekeyfe/hwk-adapter-core");
2541
2970
  var import_bitcoinjs_lib = require("bitcoinjs-lib");
2542
2971
 
2543
2972
  // src/signer/SignerBtc.ts
2544
- var import_hwk_adapter_core6 = require("@onekeyfe/hwk-adapter-core");
2973
+ var import_hwk_adapter_core7 = require("@onekeyfe/hwk-adapter-core");
2545
2974
  function hexToUtf8(hex) {
2546
- return new TextDecoder().decode((0, import_hwk_adapter_core6.hexToBytes)(hex));
2975
+ return new TextDecoder().decode((0, import_hwk_adapter_core7.hexToBytes)(hex));
2547
2976
  }
2548
2977
  var INTERACTIVE_TIMEOUT_MS2 = 5 * 6e4;
2549
2978
  var SignerBtc = class {
@@ -2658,7 +3087,7 @@ function _purposeToTemplate(purpose, DDT) {
2658
3087
  return DDT.TAPROOT;
2659
3088
  default:
2660
3089
  throw Object.assign(new Error(`Unsupported BTC purpose: m/${purpose ?? "<undefined>"}'`), {
2661
- code: import_hwk_adapter_core7.HardwareErrorCode.InvalidParams
3090
+ code: import_hwk_adapter_core8.HardwareErrorCode.InvalidParams
2662
3091
  });
2663
3092
  }
2664
3093
  }
@@ -2714,7 +3143,7 @@ async function btcSignTransaction(ctx, sessionId, params) {
2714
3143
  if (!params.psbt) {
2715
3144
  throw Object.assign(
2716
3145
  new Error("Ledger requires PSBT format for BTC transaction signing. Provide params.psbt."),
2717
- { code: import_hwk_adapter_core7.HardwareErrorCode.InvalidParams }
3146
+ { code: import_hwk_adapter_core8.HardwareErrorCode.InvalidParams }
2718
3147
  );
2719
3148
  }
2720
3149
  const btcSigner = await _createBtcSigner(ctx, sessionId);
@@ -2728,7 +3157,7 @@ async function btcSignTransaction(ctx, sessionId, params) {
2728
3157
  debugLog("[LedgerConnector] btcSignTransaction wallet:", { path, purpose, template });
2729
3158
  const wallet = new DefaultWallet(path, template);
2730
3159
  const signedTxHex = await btcSigner.signTransaction(wallet, params.psbt);
2731
- return { serializedTx: (0, import_hwk_adapter_core7.stripHex)(signedTxHex) };
3160
+ return { serializedTx: (0, import_hwk_adapter_core8.stripHex)(signedTxHex) };
2732
3161
  } catch (err) {
2733
3162
  ctx.invalidateSession(sessionId);
2734
3163
  throw ctx.wrapError(err);
@@ -2739,7 +3168,7 @@ async function btcSignTransaction(ctx, sessionId, params) {
2739
3168
  async function btcSignPsbt(ctx, sessionId, params) {
2740
3169
  if (!params.psbt) {
2741
3170
  throw Object.assign(new Error("btcSignPsbt requires params.psbt"), {
2742
- code: import_hwk_adapter_core7.HardwareErrorCode.InvalidParams
3171
+ code: import_hwk_adapter_core8.HardwareErrorCode.InvalidParams
2743
3172
  });
2744
3173
  }
2745
3174
  const btcSigner = await _createBtcSigner(ctx, sessionId);
@@ -2769,8 +3198,8 @@ async function btcSignMessage(ctx, sessionId, params) {
2769
3198
  try {
2770
3199
  const result = await btcSigner.signMessage(path, params.message);
2771
3200
  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");
3201
+ const rHex = (0, import_hwk_adapter_core8.stripHex)(result.r).padStart(64, "0");
3202
+ const sHex = (0, import_hwk_adapter_core8.stripHex)(result.s).padStart(64, "0");
2774
3203
  return { signature: `${vHex}${rHex}${sHex}` };
2775
3204
  } catch (err) {
2776
3205
  ctx.invalidateSession(sessionId);
@@ -2870,7 +3299,7 @@ function _applySignaturesToPsbt(psbtHex, signatures) {
2870
3299
  }
2871
3300
 
2872
3301
  // src/connector/chains/sol.ts
2873
- var import_hwk_adapter_core8 = require("@onekeyfe/hwk-adapter-core");
3302
+ var import_hwk_adapter_core9 = require("@onekeyfe/hwk-adapter-core");
2874
3303
 
2875
3304
  // src/signer/SignerSol.ts
2876
3305
  var SignerSol = class {
@@ -2938,10 +3367,10 @@ async function solGetAddress(ctx, sessionId, params) {
2938
3367
  async function solSignTransaction(ctx, sessionId, params) {
2939
3368
  const solSigner = await _createSolSigner(ctx, sessionId);
2940
3369
  const path = normalizePath(params.path);
2941
- const txBytes = (0, import_hwk_adapter_core8.hexToBytes)(params.serializedTx);
3370
+ const txBytes = (0, import_hwk_adapter_core9.hexToBytes)(params.serializedTx);
2942
3371
  try {
2943
3372
  const result = await solSigner.signTransaction(path, txBytes);
2944
- return { signature: (0, import_hwk_adapter_core8.bytesToHex)(result) };
3373
+ return { signature: (0, import_hwk_adapter_core9.bytesToHex)(result) };
2945
3374
  } catch (err) {
2946
3375
  ctx.invalidateSession(sessionId);
2947
3376
  throw ctx.wrapError(err);
@@ -2952,7 +3381,7 @@ async function solSignTransaction(ctx, sessionId, params) {
2952
3381
  async function solSignMessage(ctx, sessionId, params) {
2953
3382
  const solSigner = await _createSolSigner(ctx, sessionId);
2954
3383
  const path = normalizePath(params.path);
2955
- const messageBytes = (0, import_hwk_adapter_core8.hexToBytes)(params.message);
3384
+ const messageBytes = (0, import_hwk_adapter_core9.hexToBytes)(params.message);
2956
3385
  try {
2957
3386
  const result = await solSigner.signMessage(path, messageBytes);
2958
3387
  return { signature: result.signature };
@@ -2984,15 +3413,15 @@ async function _createSolSigner(ctx, sessionId) {
2984
3413
  }
2985
3414
 
2986
3415
  // src/connector/chains/tron.ts
2987
- var import_hwk_adapter_core11 = require("@onekeyfe/hwk-adapter-core");
3416
+ var import_hwk_adapter_core12 = require("@onekeyfe/hwk-adapter-core");
2988
3417
  var import_hw_app_trx = __toESM(require("@ledgerhq/hw-app-trx"));
2989
3418
 
2990
3419
  // src/connector/chains/legacyChainCall.ts
2991
- var import_hwk_adapter_core10 = require("@onekeyfe/hwk-adapter-core");
3420
+ var import_hwk_adapter_core11 = require("@onekeyfe/hwk-adapter-core");
2992
3421
 
2993
3422
  // src/app/AppManager.ts
2994
3423
  var import_device_management_kit2 = require("@ledgerhq/device-management-kit");
2995
- var import_hwk_adapter_core9 = require("@onekeyfe/hwk-adapter-core");
3424
+ var import_hwk_adapter_core10 = require("@onekeyfe/hwk-adapter-core");
2996
3425
  var APP_NAME_MAP = {
2997
3426
  ETH: "Ethereum",
2998
3427
  BTC: "Bitcoin",
@@ -3096,15 +3525,30 @@ var AppManager = class {
3096
3525
  command: new import_device_management_kit2.OpenAppCommand({ appName })
3097
3526
  });
3098
3527
  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);
3528
+ const dmkErr = result.error;
3529
+ const errorCode = "errorCode" in dmkErr && dmkErr.errorCode != null ? String(dmkErr.errorCode) : "";
3530
+ const message = "message" in dmkErr && typeof dmkErr.message === "string" ? dmkErr.message : "";
3531
+ debugLog(
3532
+ "[AppManager] openApp failed:",
3533
+ appName,
3534
+ "errorCode:",
3535
+ errorCode,
3536
+ "tag:",
3537
+ dmkErr._tag
3538
+ );
3539
+ let code;
3540
+ if (errorCode === "6807" || /unknown application/i.test(message)) {
3541
+ code = import_hwk_adapter_core10.HardwareErrorCode.AppNotInstalled;
3542
+ } else if (errorCode === "5501" || dmkErr._tag === "ActionRefusedError") {
3543
+ code = import_hwk_adapter_core10.HardwareErrorCode.UserRejected;
3544
+ }
3102
3545
  throw Object.assign(new Error(`Failed to open "${appName}"`), {
3103
3546
  _tag: ERROR_TAG.OpenAppCommand,
3104
- code: hasStatusCode2 ? void 0 : import_hwk_adapter_core9.HardwareErrorCode.AppNotInstalled,
3105
- errorCode: String(statusCode ?? ""),
3106
- statusCode,
3107
- appName
3547
+ code,
3548
+ errorCode,
3549
+ statusCode: errorCode,
3550
+ appName,
3551
+ originalError: dmkErr
3108
3552
  });
3109
3553
  }
3110
3554
  }
@@ -3157,14 +3601,14 @@ async function withLegacyChainCall(ctx, sessionId, options, action) {
3157
3601
  const onAppOpenPrompt = () => {
3158
3602
  openAppPromptShown = true;
3159
3603
  ctx.emit("ui-event", {
3160
- type: import_hwk_adapter_core10.EConnectorInteraction.ConfirmOpenApp,
3604
+ type: import_hwk_adapter_core11.EConnectorInteraction.ConfirmOpenApp,
3161
3605
  payload: { sessionId }
3162
3606
  });
3163
3607
  };
3164
3608
  const closeOpenAppUiIfShown = () => {
3165
3609
  if (openAppPromptShown) {
3166
3610
  ctx.emit("ui-event", {
3167
- type: import_hwk_adapter_core10.EConnectorInteraction.InteractionComplete,
3611
+ type: import_hwk_adapter_core11.EConnectorInteraction.InteractionComplete,
3168
3612
  payload: { sessionId }
3169
3613
  });
3170
3614
  openAppPromptShown = false;
@@ -3185,7 +3629,7 @@ async function withLegacyChainCall(ctx, sessionId, options, action) {
3185
3629
  let confirmEmitted = false;
3186
3630
  if (needsConfirmation) {
3187
3631
  ctx.emit("ui-event", {
3188
- type: import_hwk_adapter_core10.EConnectorInteraction.ConfirmOnDevice,
3632
+ type: import_hwk_adapter_core11.EConnectorInteraction.ConfirmOnDevice,
3189
3633
  payload: { sessionId }
3190
3634
  });
3191
3635
  confirmEmitted = true;
@@ -3195,7 +3639,7 @@ async function withLegacyChainCall(ctx, sessionId, options, action) {
3195
3639
  } finally {
3196
3640
  if (confirmEmitted || openAppPromptShown) {
3197
3641
  ctx.emit("ui-event", {
3198
- type: import_hwk_adapter_core10.EConnectorInteraction.InteractionComplete,
3642
+ type: import_hwk_adapter_core11.EConnectorInteraction.InteractionComplete,
3199
3643
  payload: { sessionId }
3200
3644
  });
3201
3645
  openAppPromptShown = false;
@@ -3283,7 +3727,7 @@ async function tronSignTransaction(ctx, sessionId, params) {
3283
3727
  if (!params.rawTxHex) {
3284
3728
  throw Object.assign(
3285
3729
  new Error("TRON signing requires a protobuf-encoded raw transaction hex (rawTxHex)."),
3286
- { code: import_hwk_adapter_core11.HardwareErrorCode.InvalidParams }
3730
+ { code: import_hwk_adapter_core12.HardwareErrorCode.InvalidParams }
3287
3731
  );
3288
3732
  }
3289
3733
  const path = normalizePath(params.path);
@@ -3444,6 +3888,22 @@ var DeviceApps = class {
3444
3888
  );
3445
3889
  return result.filter((a) => a !== null).map(applicationToMetadata);
3446
3890
  }
3891
+ /** Installed app names via ListApps APDU. Offline (no manager-api), but still requires unlock + dashboard. */
3892
+ async listInstalledNames(options) {
3893
+ const action = this._dmk.executeDeviceAction({
3894
+ sessionId: this._sessionId,
3895
+ deviceAction: new this._ledgerKit.ListAppsDeviceAction({
3896
+ input: { unlockTimeout: options?.unlockTimeout }
3897
+ })
3898
+ });
3899
+ const result = await deviceActionToPromise(
3900
+ action,
3901
+ this.onInteraction,
3902
+ void 0,
3903
+ this.onRegisterCanceller
3904
+ );
3905
+ return result.map((entry) => entry?.appName).filter((name) => typeof name === "string" && name.length > 0);
3906
+ }
3447
3907
  // Catalog lookup via custom device action — DMK has no typed wrapper for this.
3448
3908
  async listAvailable() {
3449
3909
  const customAction = new ListAvailableAppsDeviceAction({
@@ -3507,6 +3967,22 @@ var DeviceApps = class {
3507
3967
  async install(appName, onProgress, options) {
3508
3968
  if (!appName) throw new Error("DeviceApps.install: appName is required");
3509
3969
  debugLog("[DeviceApps] install:", appName);
3970
+ const refreshAction = this._dmk.executeDeviceAction({
3971
+ sessionId: this._sessionId,
3972
+ deviceAction: new this._ledgerKit.GetDeviceMetadataDeviceAction({
3973
+ input: {
3974
+ useSecureChannel: true,
3975
+ forceUpdate: true,
3976
+ unlockTimeout: options?.unlockTimeout
3977
+ }
3978
+ })
3979
+ });
3980
+ await deviceActionToPromise(
3981
+ refreshAction,
3982
+ this.onInteraction,
3983
+ INSTALL_TIMEOUT_MS,
3984
+ this.onRegisterCanceller
3985
+ );
3510
3986
  const action = this._dmk.executeDeviceAction({
3511
3987
  sessionId: this._sessionId,
3512
3988
  deviceAction: new this._ledgerKit.InstallOrUpdateAppsDeviceAction({
@@ -3584,7 +4060,7 @@ var METHOD_PREFIX_TO_APP_NAME = {
3584
4060
  tron: "Tron"
3585
4061
  };
3586
4062
  var HARDWARE_ERROR_CODE_VALUES = new Set(
3587
- Object.values(import_hwk_adapter_core12.HardwareErrorCode).filter((value) => typeof value === "number")
4063
+ Object.values(import_hwk_adapter_core13.HardwareErrorCode).filter((value) => typeof value === "number")
3588
4064
  );
3589
4065
  var BLE_CONNECT_SCAN_TIMEOUT_MS = 1500;
3590
4066
  async function defaultLedgerKitImporter(pkg) {
@@ -3707,7 +4183,7 @@ var LedgerConnectorBase = class {
3707
4183
  async searchDevices() {
3708
4184
  const dm = await this._getDeviceManager();
3709
4185
  const descriptors = await this._discoverDescriptors(dm);
3710
- const resolvedDescriptors = descriptors.map((d) => ({
4186
+ const resolvedDescriptors = descriptors.filter((d) => !(0, import_hwk_adapter_core13.isKnownNonTargetHardwareVendor)(d, "ledger")).map((d) => ({
3711
4187
  descriptor: d,
3712
4188
  connectId: this._resolveConnectId(d)
3713
4189
  }));
@@ -3755,7 +4231,7 @@ var LedgerConnectorBase = class {
3755
4231
  `Ledger BLE connect did not return within ${HANG_CEILING_MS / 6e4}min \u2014 DMK hang fallback.`
3756
4232
  );
3757
4233
  err._tag = ERROR_TAG.BlePairingTimeout;
3758
- err.code = import_hwk_adapter_core12.HardwareErrorCode.BlePairingTimeout;
4234
+ err.code = import_hwk_adapter_core13.HardwareErrorCode.BlePairingTimeout;
3759
4235
  reject(err);
3760
4236
  }, HANG_CEILING_MS);
3761
4237
  });
@@ -3788,7 +4264,7 @@ var LedgerConnectorBase = class {
3788
4264
  "Ledger device is not currently advertising. Wake up and unlock the device, keep it nearby, then try again."
3789
4265
  );
3790
4266
  err._tag = ERROR_TAG.DeviceNotAdvertising;
3791
- err.code = import_hwk_adapter_core12.HardwareErrorCode.DeviceNotFound;
4267
+ err.code = import_hwk_adapter_core13.HardwareErrorCode.DeviceNotFound;
3792
4268
  throw err;
3793
4269
  };
3794
4270
  const doConnect = async (path) => {
@@ -3852,7 +4328,7 @@ var LedgerConnectorBase = class {
3852
4328
  "Ledger Bluetooth pairing failed. Make sure the device is unlocked and nearby, then try again."
3853
4329
  );
3854
4330
  wrapped._tag = ERROR_TAG.BleGattBondingFailed;
3855
- wrapped.code = import_hwk_adapter_core12.HardwareErrorCode.BlePairingTimeout;
4331
+ wrapped.code = import_hwk_adapter_core13.HardwareErrorCode.BlePairingTimeout;
3856
4332
  wrapped.originalError = err;
3857
4333
  throw wrapped;
3858
4334
  }
@@ -3930,7 +4406,7 @@ var LedgerConnectorBase = class {
3930
4406
  this._unwatchSessionState(sessionId);
3931
4407
  this._signerManager?.invalidate(sessionId);
3932
4408
  this._cancellers.get(sessionId)?.({
3933
- code: import_hwk_adapter_core12.HardwareErrorCode.DeviceDisconnected,
4409
+ code: import_hwk_adapter_core13.HardwareErrorCode.DeviceDisconnected,
3934
4410
  tag: "DeviceDisconnected",
3935
4411
  message: "Device disconnected"
3936
4412
  });
@@ -3954,9 +4430,9 @@ var LedgerConnectorBase = class {
3954
4430
  if (isAppStuckByApdu(err)) {
3955
4431
  return {
3956
4432
  success: false,
3957
- error: (0, import_hwk_adapter_core12.serializeConnectorError)(
4433
+ error: (0, import_hwk_adapter_core13.serializeConnectorError)(
3958
4434
  Object.assign(new Error("Ledger app is unresponsive"), {
3959
- code: import_hwk_adapter_core12.HardwareErrorCode.DeviceAppStuck,
4435
+ code: import_hwk_adapter_core13.HardwareErrorCode.DeviceAppStuck,
3960
4436
  _tag: ERROR_TAG.DeviceAppStuck,
3961
4437
  originalError: err
3962
4438
  })
@@ -3966,16 +4442,16 @@ var LedgerConnectorBase = class {
3966
4442
  if (isTransportStuck(err)) {
3967
4443
  return {
3968
4444
  success: false,
3969
- error: (0, import_hwk_adapter_core12.serializeConnectorError)(
4445
+ error: (0, import_hwk_adapter_core13.serializeConnectorError)(
3970
4446
  Object.assign(new Error("Device communication interrupted, please retry"), {
3971
- code: import_hwk_adapter_core12.HardwareErrorCode.TransportError,
4447
+ code: import_hwk_adapter_core13.HardwareErrorCode.TransportError,
3972
4448
  _tag: ERROR_TAG.DeviceTransportStuck,
3973
4449
  originalError: err
3974
4450
  })
3975
4451
  )
3976
4452
  };
3977
4453
  }
3978
- return { success: false, error: (0, import_hwk_adapter_core12.serializeConnectorError)(err) };
4454
+ return { success: false, error: (0, import_hwk_adapter_core13.serializeConnectorError)(err) };
3979
4455
  }
3980
4456
  }
3981
4457
  async _dispatch(sessionId, method, params) {
@@ -4038,7 +4514,7 @@ var LedgerConnectorBase = class {
4038
4514
  try {
4039
4515
  return await apps.install(p.appName, ({ progress }) => {
4040
4516
  ctx.emit("ui-event", {
4041
- type: import_hwk_adapter_core12.EConnectorInteraction.AppInstallProgress,
4517
+ type: import_hwk_adapter_core13.EConnectorInteraction.AppInstallProgress,
4042
4518
  payload: {
4043
4519
  sessionId,
4044
4520
  appName: p.appName,
@@ -4064,6 +4540,17 @@ var LedgerConnectorBase = class {
4064
4540
  ctx.clearCanceller(sessionId);
4065
4541
  }
4066
4542
  }
4543
+ case "listInstalledNames": {
4544
+ const apps = await _getDeviceApps(ctx, sessionId);
4545
+ try {
4546
+ return await apps.listInstalledNames(params);
4547
+ } catch (err) {
4548
+ ctx.invalidateSession(sessionId);
4549
+ throw ctx.wrapError(err);
4550
+ } finally {
4551
+ ctx.clearCanceller(sessionId);
4552
+ }
4553
+ }
4067
4554
  case "listAvailableApps": {
4068
4555
  const apps = await _getDeviceApps(ctx, sessionId);
4069
4556
  try {