@onekeyfe/hwk-ledger-adapter 1.2.3-alpha.3 → 1.2.3-alpha.5

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
@@ -39,7 +39,6 @@ __export(index_exports, {
39
39
  SignerEth: () => SignerEth,
40
40
  SignerManager: () => SignerManager,
41
41
  SignerSol: () => SignerSol,
42
- SignerZcash: () => SignerZcash,
43
42
  debugLog: () => debugLog,
44
43
  deviceActionToPromise: () => deviceActionToPromise,
45
44
  isDeviceLockedError: () => isDeviceLockedError,
@@ -58,14 +57,17 @@ var import_hwk_adapter_core3 = require("@onekeyfe/hwk-adapter-core");
58
57
 
59
58
  // src/errors.ts
60
59
  var import_hwk_adapter_core = require("@onekeyfe/hwk-adapter-core");
61
- function ledgerFailure(code, error, appName, tag, params, origin, recovery) {
60
+ var MULTIPLE_USB_LEDGER_DEVICES_ERROR_MESSAGE = "Multiple Ledger USB devices are connected. Please connect only one Ledger device and try again.";
61
+ function createMultipleUsbLedgerDevicesError() {
62
+ return Object.assign(new Error(MULTIPLE_USB_LEDGER_DEVICES_ERROR_MESSAGE), {
63
+ code: import_hwk_adapter_core.HardwareErrorCode.DeviceOneDeviceOnly
64
+ });
65
+ }
66
+ function ledgerFailure(code, error, appName, tag, params) {
62
67
  const payload = { error, code };
63
68
  if (appName !== void 0) payload.appName = appName;
64
69
  if (tag !== void 0) payload._tag = tag;
65
70
  if (params !== void 0) payload.params = params;
66
- const resolvedOrigin = origin ?? (0, import_hwk_adapter_core.defaultOriginForCode)(code);
67
- if (resolvedOrigin !== void 0) payload.origin = resolvedOrigin;
68
- payload.recovery = recovery ?? (0, import_hwk_adapter_core.defaultRecoveryForCode)(code);
69
71
  return { success: false, payload };
70
72
  }
71
73
  var LOCKED_ERROR_CODES = /* @__PURE__ */ new Set(["5515", "21781", "6982", "27010", "5303", "21251"]);
@@ -249,6 +251,7 @@ function isBlePairingFailureError(err) {
249
251
  return false;
250
252
  }
251
253
  var CONNECTION_LEVEL_TAGS = /* @__PURE__ */ new Set([
254
+ ERROR_TAG.DeviceLocked,
252
255
  ERROR_TAG.DeviceNotAdvertising,
253
256
  ERROR_TAG.BlePairingTimeout,
254
257
  ERROR_TAG.BleGattBondingFailed,
@@ -483,12 +486,7 @@ function mapLedgerError(err, opts) {
483
486
  }
484
487
  const errAppName = err && typeof err === "object" ? err.appName : void 0;
485
488
  const appName = errAppName ?? opts?.defaultAppName;
486
- return {
487
- code,
488
- message: (0, import_hwk_adapter_core.enrichErrorMessage)(code, originalMessage),
489
- origin: (0, import_hwk_adapter_core.defaultOriginForCode)(code),
490
- appName
491
- };
489
+ return { code, message: (0, import_hwk_adapter_core.enrichErrorMessage)(code, originalMessage), appName };
492
490
  }
493
491
 
494
492
  // src/adapter/methods/allNetworkGetAddress.ts
@@ -549,81 +547,57 @@ var LEDGER_BTC_NETWORK_COIN_MAP = {
549
547
  var LEDGER_UNSUPPORTED_ALLNETWORK_NETWORKS = /* @__PURE__ */ new Set(["doge", "dogecoin"]);
550
548
  function createAllNetworkGetAddress({
551
549
  callChain,
552
- getChainFingerprint,
553
- retainOperation,
554
- errorToFailure
550
+ getChainFingerprint
555
551
  }) {
556
552
  return async function allNetworkGetAddress(connectId, _deviceId, params) {
557
- debugLog("[LedgerAdapter][REQ]", {
558
- method: "allNetworkGetAddress",
559
- connectId,
560
- itemCount: params.bundle.length
561
- });
562
- const target = (0, import_hwk_adapter_core2.resolveHardwareOperationTarget)(connectId, params.operationId, "ledger");
563
- if (!target.success) return target;
564
- const effectiveTargetId = target.payload.targetId ?? "";
565
- let releaseOperationRetention;
566
- try {
567
- releaseOperationRetention = target.payload.operationId ? retainOperation(target.payload.operationId) : void 0;
568
- } catch (error) {
569
- return errorToFailure(error);
570
- }
553
+ debugLog("[LedgerAdapter][REQ]", { method: "allNetworkGetAddress", connectId, params });
571
554
  const installContext = {};
572
555
  const commonParams = {
573
- autoInstallApp: params.autoInstallApp,
574
- operationId: target.payload.operationId,
575
- knownConnections: params.knownConnections,
576
- extra: params.extra,
577
- allowDeviceSelection: params.allowDeviceSelection
556
+ autoInstallApp: params.autoInstallApp
578
557
  };
579
558
  const chainFingerprints = /* @__PURE__ */ new Map();
580
- try {
581
- const result = await (0, import_hwk_adapter_core2.runAllNetworkGetAddress)({
582
- connectId: effectiveTargetId,
583
- deviceId: _deviceId,
584
- params,
585
- normalizeItem: normalizeLedgerAllNetworkItem,
586
- buildUnsupportedNetworkResponse: (item) => isUnsupportedLedgerAllNetworkNetwork(item) ? buildUnsupportedNetworkResponse(item) : void 0,
587
- callItem: async ({ method, chain, item }) => {
588
- const itemDeviceId = getItemDeviceId(item) ?? chainFingerprints.get(chain) ?? "";
589
- return callAllNetworkMethod(
590
- callChain,
591
- effectiveTargetId,
592
- itemDeviceId,
593
- method,
594
- item,
595
- commonParams,
596
- installContext
597
- );
598
- },
599
- attachIdentity: async ({ item, chain, payload }) => attachLedgerIdentity(
600
- getChainFingerprint,
601
- effectiveTargetId,
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,
602
572
  item,
603
- chain,
604
- payload,
605
- chainFingerprints,
573
+ commonParams,
606
574
  installContext
607
- ),
608
- shouldAbortBundle: isTopLevelAllNetworkFailure,
609
- buildTopLevelFailure: (response) => {
610
- const code = response.payload?.code ?? import_hwk_adapter_core2.HardwareErrorCode.DeviceMismatch;
611
- return (0, import_hwk_adapter_core2.failure)(
612
- code,
613
- response.payload?.error ?? "All-network get-address aborted",
614
- response.payload?.params
615
- );
616
- }
617
- });
618
- debugLog("[LedgerAdapter][RES]", {
619
- method: "allNetworkGetAddress",
620
- success: result.success,
621
- payload: result
622
- });
623
- return result;
624
- } finally {
625
- releaseOperationRetention?.();
626
- }
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;
627
601
  };
628
602
  }
629
603
  function isTopLevelAllNetworkFailure(response) {
@@ -631,7 +605,7 @@ function isTopLevelAllNetworkFailure(response) {
631
605
  return false;
632
606
  }
633
607
  const code = response.payload?.code;
634
- return code === import_hwk_adapter_core2.HardwareErrorCode.DeviceMismatch || code === import_hwk_adapter_core2.HardwareErrorCode.DeviceDisconnected || code === import_hwk_adapter_core2.HardwareErrorCode.OperationTimeout || code === import_hwk_adapter_core2.HardwareErrorCode.TransportError || code === import_hwk_adapter_core2.HardwareErrorCode.OperationEnded || code === import_hwk_adapter_core2.HardwareErrorCode.OperationNotFound || code === import_hwk_adapter_core2.HardwareErrorCode.UserAborted || code === import_hwk_adapter_core2.HardwareErrorCode.UserRejected;
608
+ return code === import_hwk_adapter_core2.HardwareErrorCode.DeviceMismatch || code === import_hwk_adapter_core2.HardwareErrorCode.UserAborted || code === import_hwk_adapter_core2.HardwareErrorCode.UserRejected;
635
609
  }
636
610
  function getItemDeviceId(item) {
637
611
  const { deviceId } = item;
@@ -661,13 +635,8 @@ function normalizeLedgerAllNetworkItem(method, item) {
661
635
  const coin = LEDGER_BTC_NETWORK_COIN_MAP[item.network];
662
636
  return coin ? { ...item, coin } : item;
663
637
  }
664
- async function attachLedgerIdentity(getChainFingerprint, connectId, item, chain, payload, chainFingerprints, context) {
665
- const fingerprint = getItemDeviceId(item) || chainFingerprints.get(chain) || await bootstrapChainFingerprint(
666
- getChainFingerprint,
667
- context.connection?.connectId ?? connectId,
668
- chain,
669
- context
670
- );
638
+ async function attachLedgerIdentity(getChainFingerprint, connectId, item, chain, payload, chainFingerprints) {
639
+ const fingerprint = getItemDeviceId(item) || chainFingerprints.get(chain) || await bootstrapChainFingerprint(getChainFingerprint, connectId, chain);
671
640
  if (!fingerprint) {
672
641
  return buildFingerprintBootstrapFailure(item, chain);
673
642
  }
@@ -688,8 +657,8 @@ async function attachLedgerIdentity(getChainFingerprint, connectId, item, chain,
688
657
  }
689
658
  };
690
659
  }
691
- async function bootstrapChainFingerprint(getChainFingerprint, connectId, chain, context) {
692
- const response = await getChainFingerprint(connectId, chain, context);
660
+ async function bootstrapChainFingerprint(getChainFingerprint, connectId, chain) {
661
+ const response = await getChainFingerprint(connectId, chain);
693
662
  return response.success ? response.payload : "";
694
663
  }
695
664
  function buildFingerprintBootstrapFailure(item, chain) {
@@ -794,27 +763,8 @@ var _LedgerAdapter = class _LedgerAdapter {
794
763
  constructor(connector, options) {
795
764
  this.vendor = "ledger";
796
765
  this.emitter = new import_hwk_adapter_core3.TypedEventEmitter();
797
- this._operations = new import_hwk_adapter_core3.OperationRegistry({
798
- vendor: "ledger",
799
- onEnded: (operation, reason) => {
800
- const binding = this._pendingOperationBindings.get(operation.operationId);
801
- if (binding?.selectedConnection?.requestId === this._bindingSelectionRequestId) {
802
- this._finishBleBinding("cancelled");
803
- }
804
- this._pendingOperationBindings.delete(operation.operationId);
805
- this.emitter.emit(import_hwk_adapter_core3.SDK.OPERATION_ENDED, {
806
- type: import_hwk_adapter_core3.SDK.OPERATION_ENDED,
807
- payload: { operationId: operation.operationId, reason }
808
- });
809
- if (reason === "timeout") {
810
- void this._releaseOperationConnection(operation);
811
- }
812
- }
813
- });
814
766
  this._discoveredDevices = /* @__PURE__ */ new Map();
815
767
  this._sessions = /* @__PURE__ */ new Map();
816
- this._pendingOperationBindings = /* @__PURE__ */ new Map();
817
- this._verifiedBleReconnectTargets = /* @__PURE__ */ new Map();
818
768
  this._uiRegistry = new import_hwk_adapter_core3.UiRequestRegistry();
819
769
  // BTC App rejects account index >= 100 unless display=true. Cached per
820
770
  // adapter instance: first 100+ path asks the user once via UI request,
@@ -828,30 +778,10 @@ var _LedgerAdapter = class _LedgerAdapter {
828
778
  this._deviceAuthenticityQueueTail = Promise.resolve();
829
779
  // Shared across concurrent callers — only `cancel()` aborts.
830
780
  this._doConnectAbortController = null;
831
- this._unsettledConnectorOperations = /* @__PURE__ */ new Map();
832
- this._connectorIdleWaiters = /* @__PURE__ */ new Set();
833
- this._resetPromise = null;
834
- this._stateGeneration = 0;
835
- this._connectorTeardownTail = Promise.resolve();
836
- this._pendingConnectorTeardowns = 0;
837
- this._activeOperationJobs = /* @__PURE__ */ new Set();
838
- this._pendingOperationDisconnects = /* @__PURE__ */ new Set();
839
781
  this._installProgressLastEmittedValue = -Infinity;
840
782
  this.allNetworkGetAddress = createAllNetworkGetAddress({
841
783
  callChain: this.callChain.bind(this),
842
- getChainFingerprint: async (connectId, chain, context) => {
843
- try {
844
- const fingerprint = await this._computeChainFingerprint(
845
- chain,
846
- (method, params) => this.connectorCall(connectId, method, params, void 0, void 0, void 0, context)
847
- );
848
- return (0, import_hwk_adapter_core3.success)(fingerprint);
849
- } catch (error) {
850
- return this.errorToFailure(error);
851
- }
852
- },
853
- retainOperation: (operationId) => this._operations.retain(operationId),
854
- errorToFailure: (error) => this.errorToFailure(error)
784
+ getChainFingerprint: (connectId, chain) => this.getChainFingerprint(connectId, "", chain)
855
785
  });
856
786
  // ---------------------------------------------------------------------------
857
787
  // Private helpers
@@ -861,7 +791,7 @@ var _LedgerAdapter = class _LedgerAdapter {
861
791
  *
862
792
  * - If a session already exists for the given connectId, reuse it.
863
793
  * - If ANY session exists (Ledger IDs are ephemeral), reuse it.
864
- * - Otherwise: search → one USB device auto-connects; multiple asks the host to choose.
794
+ * - Otherwise: search → exactly 1 USB device auto-connects; multiple or none throws.
865
795
  */
866
796
  // Mutex for ensureConnected — prevents concurrent calls from establishing duplicate connections
867
797
  this._connectingPromise = null;
@@ -878,12 +808,6 @@ var _LedgerAdapter = class _LedgerAdapter {
878
808
  });
879
809
  };
880
810
  this.deviceDisconnectHandler = (data) => {
881
- const activeOperation = this._operations.findActiveByConnectionKey(data.connectId);
882
- if (activeOperation && this._activeOperationJobs.has(activeOperation.operationId)) {
883
- this._pendingOperationDisconnects.add(activeOperation.operationId);
884
- } else {
885
- this._operations.endByConnectionKey(data.connectId, "disconnect");
886
- }
887
811
  this._discoveredDevices.delete(data.connectId);
888
812
  this._sessions.delete(data.connectId);
889
813
  this.emitter.emit(import_hwk_adapter_core3.DEVICE.DISCONNECT, {
@@ -940,28 +864,11 @@ var _LedgerAdapter = class _LedgerAdapter {
940
864
  this._jobQueue = new import_hwk_adapter_core3.DeviceJobQueue();
941
865
  this.registerEventListeners();
942
866
  }
943
- _finishBleBinding(status) {
944
- const selectionRequestId = this._bindingSelectionRequestId;
945
- this._bindingSelectionRequestId = void 0;
946
- if (selectionRequestId)
947
- this.emitter.emit(import_hwk_adapter_core3.UI_REQUEST.DEVICE_BINDING_STATUS, {
948
- type: import_hwk_adapter_core3.UI_REQUEST.DEVICE_BINDING_STATUS,
949
- payload: { selectionRequestId, status }
950
- });
951
- }
952
- _isBleConnection() {
953
- return isLedgerBleConnectionType(this._activeConnectionType ?? this.connector.connectionType);
954
- }
955
867
  // Transport
956
868
  get activeTransport() {
957
- return this._isBleConnection() ? "ble" : "hid";
869
+ return isLedgerBleConnectionType(this.connector.connectionType) ? "ble" : "hid";
958
870
  }
959
871
  getAvailableTransports() {
960
- if (this.connector.availableTransports) {
961
- return this.connector.availableTransports.map(
962
- (transport) => transport === "ble" ? "ble" : "hid"
963
- );
964
- }
965
872
  return this.activeTransport ? [this.activeTransport] : [];
966
873
  }
967
874
  // Connector is bound at construction; switching requires a new adapter.
@@ -978,39 +885,21 @@ var _LedgerAdapter = class _LedgerAdapter {
978
885
  * The next operation will re-discover and re-connect automatically.
979
886
  */
980
887
  resetState() {
981
- void this._resetStateAndDisconnectSessions();
982
- }
983
- _resetStateAndDisconnectSessions() {
984
- if (this._resetPromise) return this._resetPromise;
985
- const sessionIds = new Set(this._sessions.values());
986
- this._stateGeneration += 1;
987
- this._finishBleBinding("cancelled");
988
- this._operations.endAll("runtime-reset");
989
- this._doConnectAbortController?.abort();
990
888
  this._discoveredDevices.clear();
991
889
  this._sessions.clear();
992
- this._verifiedBleReconnectTargets.clear();
993
890
  this._connectingPromise = null;
994
- this._doConnectAbortController = null;
995
891
  this._uiRegistry.reset();
996
892
  this._jobQueue.clear();
997
893
  this._btcHighIndexConfirmedThisSession = false;
998
- const resetPromise = this._runConnectorTeardown(async () => {
999
- for (const sessionId of sessionIds) {
1000
- await this.connector.disconnect(sessionId).catch(() => void 0);
1001
- }
1002
- });
1003
- this._resetPromise = resetPromise;
1004
- return resetPromise.finally(() => {
1005
- if (this._resetPromise === resetPromise) {
1006
- this._resetPromise = null;
1007
- }
1008
- });
1009
894
  }
1010
895
  async dispose() {
1011
- await this._resetStateAndDisconnectSessions();
896
+ this._uiRegistry.reset();
897
+ this._jobQueue.clear();
1012
898
  this.unregisterEventListeners();
1013
899
  this.connector.reset();
900
+ this._discoveredDevices.clear();
901
+ this._sessions.clear();
902
+ this._btcHighIndexConfirmedThisSession = false;
1014
903
  this.emitter.removeAllListeners();
1015
904
  }
1016
905
  uiResponse(response) {
@@ -1020,32 +909,17 @@ var _LedgerAdapter = class _LedgerAdapter {
1020
909
  // Device management
1021
910
  // ---------------------------------------------------------------------------
1022
911
  async searchDevices(options) {
1023
- return this._searchDevices(options);
1024
- }
1025
- async _searchDevices(options, signal) {
1026
912
  debugLog("[LedgerAdapter][REQ]", { method: "searchDevices", params: options });
1027
913
  try {
1028
914
  if (options?.resetSession) {
1029
- await this._resetStateAndDisconnectSessions();
1030
- } else {
1031
- await this._connectorTeardownTail;
1032
- }
1033
- await this._ensureDevicePermission(void 0, void 0, signal);
1034
- if (signal) _LedgerAdapter._throwIfAborted(signal);
1035
- const stateGeneration = this._stateGeneration;
1036
- const devices = await this.connector.searchDevices(
1037
- options?.transportType ? {
1038
- transportType: options.transportType,
1039
- waitForAll: options.waitForAllTransports
1040
- } : void 0
1041
- );
1042
- if (signal) _LedgerAdapter._throwIfAborted(signal);
1043
- if (stateGeneration !== this._stateGeneration) {
1044
- throw (0, import_hwk_adapter_core3.createHwkError)({
1045
- code: import_hwk_adapter_core3.HardwareErrorCode.UserAborted,
1046
- message: "Ledger discovery was reset"
1047
- });
915
+ this._doConnectAbortController?.abort();
916
+ this._sessions.clear();
917
+ this._connectingPromise = null;
918
+ this._doConnectAbortController = null;
919
+ this._btcHighIndexConfirmedThisSession = false;
1048
920
  }
921
+ await this._ensureDevicePermission();
922
+ const devices = await this.connector.searchDevices();
1049
923
  this._discoveredDevices.clear();
1050
924
  for (const d of devices) {
1051
925
  if (d.connectId) {
@@ -1053,7 +927,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1053
927
  }
1054
928
  }
1055
929
  if (this._discoveredDevices.size === 0) {
1056
- await this._ensureDevicePermission(void 0, void 0, signal);
930
+ await this._ensureDevicePermission();
1057
931
  }
1058
932
  const result = Array.from(this._discoveredDevices.values());
1059
933
  debugLog("[LedgerAdapter][RES]", {
@@ -1072,285 +946,41 @@ var _LedgerAdapter = class _LedgerAdapter {
1072
946
  throw err;
1073
947
  }
1074
948
  }
1075
- async searchDeviceTargets(options) {
1076
- const devices = await this.searchDevices(options);
1077
- return devices.map((device) => ({
1078
- searchTargetId: device.connectId,
1079
- searchTargetReusePolicy: (0, import_hwk_adapter_core3.resolveSearchTargetReusePolicy)(device),
1080
- vendor: "ledger",
1081
- connectionType: device.connectionType,
1082
- kind: "physical",
1083
- label: device.label,
1084
- model: device.model,
1085
- modelName: device.modelName,
1086
- serialNumber: device.serialNumber
1087
- }));
1088
- }
1089
- async listConnectionTargets(options) {
1090
- const targets = await this.searchDeviceTargets(options);
1091
- return targets.map(({ searchTargetId, ...target }) => ({
1092
- ...target,
1093
- targetId: searchTargetId
1094
- }));
1095
- }
1096
949
  // USB single-session invariant: evict all sessions, best-effort (see connectDevice).
1097
- async _evictAllSessions(preserveOperationId) {
1098
- this._operations.endAll("explicit", preserveOperationId);
950
+ async _evictAllSessions() {
1099
951
  if (this._sessions.size === 0) return;
1100
952
  const stale = [...this._sessions.values()];
1101
953
  this._sessions.clear();
1102
- await this._runConnectorTeardown(async () => {
1103
- for (const sid of stale) {
1104
- try {
1105
- await this.connector.disconnect(sid);
1106
- } catch {
1107
- }
954
+ for (const sid of stale) {
955
+ try {
956
+ await this.connector.disconnect(sid);
957
+ } catch {
1108
958
  }
1109
- });
959
+ }
1110
960
  }
1111
961
  static _createDeviceBusyError(method) {
1112
962
  return Object.assign(new Error(`Ledger device is busy while calling ${method}`), {
1113
963
  code: import_hwk_adapter_core3.HardwareErrorCode.DeviceBusy
1114
964
  });
1115
965
  }
1116
- async connectDevice(searchTargetId) {
1117
- try {
1118
- return await this._jobQueue.enqueue(
1119
- searchTargetId || "__ledger_connect__",
1120
- async () => {
1121
- const connected = await this._connectTarget(searchTargetId);
1122
- if (!connected.success) return connected;
1123
- return this._createOperation(searchTargetId, connected.payload);
1124
- },
1125
- {
1126
- label: "connectDevice",
1127
- rejectIfBusy: true,
1128
- busyError: _LedgerAdapter._createDeviceBusyError("connectDevice")
1129
- }
1130
- );
1131
- } catch (error) {
1132
- return this.errorToFailure(error);
1133
- }
1134
- }
1135
- async bindBleDevice(params) {
1136
- if (params.identity.vendor !== "ledger" || !params.identity.value) {
1137
- return (0, import_hwk_adapter_core3.failure)(import_hwk_adapter_core3.HardwareErrorCode.InvalidParams, "Ledger wallet identity is required");
1138
- }
1139
- const { chain, value: expectedFingerprint } = params.identity;
1140
- try {
1141
- return await this._jobQueue.enqueue(
1142
- expectedFingerprint,
1143
- async (signal) => {
1144
- if (!this.getAvailableTransports().includes("ble")) {
1145
- throw (0, import_hwk_adapter_core3.createHwkError)({
1146
- code: import_hwk_adapter_core3.HardwareErrorCode.TransportNotAvailable,
1147
- message: "Ledger Bluetooth transport is not available"
1148
- });
1149
- }
1150
- this._activeConnectionType = "ble";
1151
- await this._ensureDevicePermission(void 0, void 0, signal);
1152
- const attempt = {
1153
- extra: params.extra,
1154
- bindingReason: "manual-rebind"
1155
- };
1156
- try {
1157
- for (; ; ) {
1158
- const connectId = await this._connectFirstOrSelect(
1159
- [],
1160
- void 0,
1161
- true,
1162
- void 0,
1163
- attempt,
1164
- signal
1165
- );
1166
- const sessionId = this._sessions.get(connectId);
1167
- if (!sessionId) {
1168
- throw (0, import_hwk_adapter_core3.createHwkError)({
1169
- code: import_hwk_adapter_core3.HardwareErrorCode.DeviceDisconnected,
1170
- message: "Selected Ledger connection ended"
1171
- });
1172
- }
1173
- let saved = false;
1174
- try {
1175
- const installContext = {
1176
- connection: { connectId, sessionId }
1177
- };
1178
- const fingerprint = await this._computeChainFingerprint(
1179
- chain,
1180
- (method, callParams) => this._runConnectorCall(
1181
- connectId,
1182
- method,
1183
- callParams,
1184
- signal,
1185
- void 0,
1186
- void 0,
1187
- { autoInstallApp: true },
1188
- installContext
1189
- )
1190
- );
1191
- if (fingerprint !== expectedFingerprint) {
1192
- attempt.rejectedConnectIds ?? (attempt.rejectedConnectIds = /* @__PURE__ */ new Set());
1193
- attempt.rejectedConnectIds.add(connectId);
1194
- attempt.rejectedConnectId = connectId;
1195
- } else {
1196
- const persisted = await this._publishVerifiedBleBinding(
1197
- connectId,
1198
- chain,
1199
- fingerprint,
1200
- attempt,
1201
- void 0,
1202
- signal
1203
- );
1204
- if (!persisted) {
1205
- throw (0, import_hwk_adapter_core3.createHwkError)({
1206
- code: import_hwk_adapter_core3.HardwareErrorCode.UnknownError,
1207
- message: "Bluetooth binding could not be saved",
1208
- origin: "host"
1209
- });
1210
- }
1211
- saved = true;
1212
- return (0, import_hwk_adapter_core3.success)(connectId);
1213
- }
1214
- } finally {
1215
- if (!saved && this._sessions.get(connectId) === sessionId) {
1216
- this._sessions.delete(connectId);
1217
- const teardown = this._runConnectorTeardown(
1218
- () => this.connector.disconnect(sessionId)
1219
- ).catch(() => void 0);
1220
- if (!signal.aborted) await teardown;
1221
- }
1222
- }
1223
- }
1224
- } catch (error) {
1225
- this._finishBleBinding(signal.aborted ? "cancelled" : "failed");
1226
- throw error;
1227
- }
1228
- },
1229
- {
1230
- label: "bindBleDevice",
1231
- rejectIfBusy: true,
1232
- busyError: _LedgerAdapter._createDeviceBusyError("bindBleDevice")
1233
- }
1234
- );
1235
- } catch (error) {
1236
- return this.errorToFailure(error);
1237
- }
1238
- }
1239
- async acquireOperation(connectId, context) {
1240
- try {
1241
- return await this._jobQueue.enqueue(
1242
- connectId || "__ledger_acquire__",
1243
- async (signal) => {
1244
- const transport = this._isBleConnection() ? "ble" : "usb";
1245
- const hint = context.knownConnections?.find(
1246
- (connection) => connection.transport === transport
1247
- );
1248
- const target = hint && hint.transport !== "qr" ? hint.connectId : connectId;
1249
- await this._ensureDevicePermission(target, void 0, signal);
1250
- const attempt = {
1251
- ...context,
1252
- extra: context.extra ? { ...context.extra } : void 0
1253
- };
1254
- try {
1255
- const resolvedConnectId = await this.ensureConnected(
1256
- target,
1257
- signal,
1258
- true,
1259
- void 0,
1260
- attempt
1261
- );
1262
- _LedgerAdapter._throwIfAborted(signal);
1263
- const result = this._createOperation(connectId, resolvedConnectId);
1264
- if (result.success && attempt.selectedConnection) {
1265
- this._pendingOperationBindings.set(result.payload, attempt);
1266
- }
1267
- return result;
1268
- } catch (error) {
1269
- this._finishBleBinding(signal.aborted ? "cancelled" : "failed");
1270
- throw error;
1271
- }
1272
- },
1273
- {
1274
- label: "acquireOperation",
1275
- rejectIfBusy: true,
1276
- busyError: _LedgerAdapter._createDeviceBusyError("acquireOperation")
1277
- }
1278
- );
1279
- } catch (error) {
1280
- return this.errorToFailure(error);
1281
- }
1282
- }
1283
- _createOperation(searchTargetId, resolvedConnectId) {
1284
- this._operations.endByConnectionKey(resolvedConnectId, "explicit");
1285
- const sessionId = this._sessions.get(resolvedConnectId);
1286
- if (sessionId) this._operations.endByConnectionKey(sessionId, "explicit");
1287
- const device = this._discoveredDevices.get(resolvedConnectId) ?? {
1288
- vendor: "ledger",
1289
- model: "unknown",
1290
- firmwareVersion: "",
1291
- deviceId: "",
1292
- connectId: resolvedConnectId,
1293
- connectionType: this.connector.connectionType
1294
- };
1295
- const operation = this._operations.create({
1296
- searchTargetId,
1297
- connectId: resolvedConnectId,
1298
- device,
1299
- connectionKeys: [this._sessions.get(resolvedConnectId) ?? ""]
1300
- });
1301
- return (0, import_hwk_adapter_core3.success)(operation.operationId);
1302
- }
1303
- async _connectTarget(connectId, preserveOperationId, signal) {
966
+ async connectDevice(connectId) {
1304
967
  debugLog("[LedgerAdapter][REQ]", { method: "connectDevice", connectId, params: { connectId } });
1305
968
  try {
1306
- this._assertConnectorReady("connectDevice");
1307
- const discoveredType = this._discoveredDevices.get(connectId)?.connectionType;
1308
- if (discoveredType === "usb" || discoveredType === "ble") {
1309
- this._activeConnectionType = discoveredType;
1310
- }
1311
- if (this._isBleConnection() && !connectId) {
969
+ if (isLedgerBleConnectionType(this.connector.connectionType) && !connectId) {
1312
970
  throw Object.assign(new Error("Ledger BLE connectId is required."), {
1313
971
  code: import_hwk_adapter_core3.HardwareErrorCode.DeviceNotFound
1314
972
  });
1315
973
  }
1316
- await this._ensureDevicePermission(connectId, void 0, signal);
1317
- if (signal) _LedgerAdapter._throwIfAborted(signal);
1318
- if (this.connector.availableTransports && this.connector.availableTransports.length > 1) {
1319
- await this._evictAllSessions(preserveOperationId);
1320
- } else if (this._isBleConnection()) {
1321
- const previousSessionId = this._sessions.get(connectId);
1322
- this._operations.endByConnectionKey(connectId, "explicit", preserveOperationId);
1323
- if (previousSessionId) {
1324
- this._operations.endByConnectionKey(previousSessionId, "explicit", preserveOperationId);
1325
- this._sessions.delete(connectId);
1326
- await this.connector.disconnect(previousSessionId).catch(() => void 0);
1327
- }
1328
- } else {
1329
- await this._evictAllSessions(preserveOperationId);
1330
- }
1331
- if (signal) _LedgerAdapter._throwIfAborted(signal);
1332
- const stateGeneration = this._stateGeneration;
1333
- const releaseOperation = this._retainConnectorOperation(`connect:${connectId}`);
1334
- let session;
1335
- try {
1336
- session = this.connector.availableTransports?.length ? await this.connector.connect(connectId, {
1337
- transportType: this._activeConnectionType ?? "usb"
1338
- }) : await this.connector.connect(connectId);
1339
- if (signal?.aborted || stateGeneration !== this._stateGeneration) {
1340
- await this.connector.disconnect(session.sessionId).catch(() => void 0);
1341
- throw Object.assign(new Error("Ledger connection aborted"), {
1342
- code: import_hwk_adapter_core3.HardwareErrorCode.UserAborted
1343
- });
1344
- }
1345
- } finally {
1346
- releaseOperation();
974
+ if (!isLedgerBleConnectionType(this.connector.connectionType)) {
975
+ await this._evictAllSessions();
1347
976
  }
1348
- const resolvedConnectId = session.deviceInfo?.connectId || connectId;
1349
- this._sessions.set(resolvedConnectId, session.sessionId);
977
+ await this._ensureDevicePermission(connectId);
978
+ const session = await this.connector.connect(connectId);
979
+ this._sessions.set(connectId, session.sessionId);
1350
980
  if (session.deviceInfo) {
1351
- this._discoveredDevices.set(resolvedConnectId, session.deviceInfo);
981
+ this._discoveredDevices.set(connectId, session.deviceInfo);
1352
982
  }
1353
- const result = (0, import_hwk_adapter_core3.success)(resolvedConnectId);
983
+ const result = (0, import_hwk_adapter_core3.success)(connectId);
1354
984
  debugLog("[LedgerAdapter][RES]", { method: "connectDevice", success: true, payload: result });
1355
985
  return result;
1356
986
  } catch (err) {
@@ -1363,60 +993,30 @@ var _LedgerAdapter = class _LedgerAdapter {
1363
993
  return failureResult;
1364
994
  }
1365
995
  }
1366
- async releaseOperation(operationId) {
1367
- const operation = this._operations.find(operationId);
1368
- if (!operation) {
1369
- this._operations.resolve(operationId);
1370
- return;
1371
- }
1372
- const endedOperation = this._operations.end(operationId, "explicit");
1373
- if (!endedOperation) return;
1374
- const { connectId } = operation;
996
+ async disconnectDevice(connectId) {
1375
997
  debugLog("[LedgerAdapter][REQ]", {
1376
- method: "releaseOperation",
998
+ method: "disconnectDevice",
1377
999
  connectId,
1378
1000
  params: { connectId }
1379
1001
  });
1380
1002
  try {
1381
- await this._releaseOperationConnection(endedOperation);
1382
- debugLog("[LedgerAdapter][RES]", { method: "releaseOperation", success: true });
1003
+ const sessionId = this._sessions.get(connectId);
1004
+ if (sessionId) {
1005
+ await this.connector.disconnect(sessionId);
1006
+ this._sessions.delete(connectId);
1007
+ }
1008
+ debugLog("[LedgerAdapter][RES]", { method: "disconnectDevice", success: true });
1383
1009
  } catch (err) {
1384
1010
  const e = err;
1385
1011
  debugLog("[LedgerAdapter][RES]", {
1386
- method: "releaseOperation",
1012
+ method: "disconnectDevice",
1387
1013
  success: false,
1388
1014
  error: { message: e?.message, _tag: e?._tag, code: e?.code ?? e?.errorCode }
1389
1015
  });
1390
1016
  throw err;
1391
1017
  }
1392
1018
  }
1393
- async _releaseOperationConnection(operation) {
1394
- const sessionIds = /* @__PURE__ */ new Set();
1395
- for (const [connectId, sessionId] of this._sessions) {
1396
- if (connectId === operation.connectId || operation.connectionKeys.includes(connectId) || operation.connectionKeys.includes(sessionId)) {
1397
- this._sessions.delete(connectId);
1398
- sessionIds.add(sessionId);
1399
- }
1400
- }
1401
- for (const sessionId of sessionIds) {
1402
- await this._runConnectorTeardown(
1403
- () => this.connector.disconnect(sessionId).catch(() => void 0)
1404
- );
1405
- }
1406
- }
1407
- async _releaseLostOperationConnection(operationId) {
1408
- const endedOperation = this._operations.end(operationId, "disconnect");
1409
- if (!endedOperation) return;
1410
- this._discoveredDevices.delete(endedOperation.connectId);
1411
- await this._releaseOperationConnection(endedOperation);
1412
- }
1413
- async getDeviceInfo(connectIdOrOperationId, deviceId) {
1414
- let connectId;
1415
- try {
1416
- connectId = (0, import_hwk_adapter_core3.isHardwareOperationId)(connectIdOrOperationId) ? this._operations.resolve(connectIdOrOperationId).connectId : connectIdOrOperationId;
1417
- } catch (error) {
1418
- return this.errorToFailure(error);
1419
- }
1019
+ async getDeviceInfo(connectId, deviceId) {
1420
1020
  debugLog("[LedgerAdapter][REQ]", {
1421
1021
  method: "getDeviceInfo",
1422
1022
  connectId,
@@ -1454,6 +1054,9 @@ var _LedgerAdapter = class _LedgerAdapter {
1454
1054
  throw err;
1455
1055
  }
1456
1056
  }
1057
+ getSupportedChains() {
1058
+ return ["evm", "btc", "sol", "tron"];
1059
+ }
1457
1060
  // ---------------------------------------------------------------------------
1458
1061
  // Chain call helper
1459
1062
  // ---------------------------------------------------------------------------
@@ -1488,21 +1091,13 @@ var _LedgerAdapter = class _LedgerAdapter {
1488
1091
  if (params && typeof params === "object") {
1489
1092
  const {
1490
1093
  autoInstallApp,
1491
- operationId,
1492
1094
  passphraseState: _passphraseState,
1493
1095
  useEmptyPassphrase: _useEmptyPassphrase,
1494
- knownConnections,
1495
- extra,
1496
- allowDeviceSelection,
1497
1096
  ...rest
1498
1097
  } = params;
1499
1098
  return {
1500
1099
  commonParams: {
1501
- autoInstallApp: typeof autoInstallApp === "boolean" ? autoInstallApp : void 0,
1502
- operationId: typeof operationId === "string" ? operationId : void 0,
1503
- knownConnections,
1504
- extra,
1505
- allowDeviceSelection: typeof allowDeviceSelection === "boolean" ? allowDeviceSelection : void 0
1100
+ autoInstallApp: typeof autoInstallApp === "boolean" ? autoInstallApp : void 0
1506
1101
  },
1507
1102
  rest
1508
1103
  };
@@ -1678,27 +1273,6 @@ var _LedgerAdapter = class _LedgerAdapter {
1678
1273
  );
1679
1274
  }
1680
1275
  // ---------------------------------------------------------------------------
1681
- // Zcash chain methods (viewing key + shielded address reads; Zcash app >= 3.8.0)
1682
- // ---------------------------------------------------------------------------
1683
- zcashGetFullViewingKey(connectId, deviceId, params) {
1684
- return this.callChainWithMergedParams(
1685
- connectId,
1686
- deviceId,
1687
- "zcash",
1688
- "zcashGetFullViewingKey",
1689
- params
1690
- );
1691
- }
1692
- zcashGetShieldedAddress(connectId, deviceId, params) {
1693
- return this.callChainWithMergedParams(
1694
- connectId,
1695
- deviceId,
1696
- "zcash",
1697
- "zcashGetShieldedAddress",
1698
- params
1699
- );
1700
- }
1701
- // ---------------------------------------------------------------------------
1702
1276
  // App management — OS-level Ledger app install / list. Bypasses fingerprint
1703
1277
  // and chain-handler dispatch; installApp progress is forwarded to the adapter
1704
1278
  // emitter via 'ui-event' AppInstallProgress events.
@@ -1787,7 +1361,7 @@ var _LedgerAdapter = class _LedgerAdapter {
1787
1361
  );
1788
1362
  }
1789
1363
  await this.connector.configure({ ledgerGenuineCheckWebSocketUrl: relayUrl });
1790
- await this._resetStateAndDisconnectSessions();
1364
+ this.resetState();
1791
1365
  }
1792
1366
  const result = await this.connectorCall(connectId, "getDeviceGenuineCheck", {});
1793
1367
  if (!result.isGenuine) {
@@ -1813,10 +1387,10 @@ var _LedgerAdapter = class _LedgerAdapter {
1813
1387
  if (relayUrl) {
1814
1388
  try {
1815
1389
  await this.connector.configure?.({ ledgerGenuineCheckWebSocketUrl: void 0 });
1816
- await this._resetStateAndDisconnectSessions();
1390
+ this.resetState();
1817
1391
  } catch {
1818
1392
  this.connector.reset();
1819
- await this._resetStateAndDisconnectSessions();
1393
+ this.resetState();
1820
1394
  }
1821
1395
  }
1822
1396
  }
@@ -1828,20 +1402,6 @@ var _LedgerAdapter = class _LedgerAdapter {
1828
1402
  this.emitter.off(event, listener);
1829
1403
  }
1830
1404
  cancel(connectId) {
1831
- const namedOperationIsLive = (id) => {
1832
- try {
1833
- this._operations.resolve(id);
1834
- return true;
1835
- } catch {
1836
- return false;
1837
- }
1838
- };
1839
- if ((0, import_hwk_adapter_core3.isHardwareOperationId)(connectId) && !namedOperationIsLive(connectId)) {
1840
- debugLog("[LedgerAdapter] cancel target already ended; nothing to cancel", {
1841
- connectId
1842
- });
1843
- return;
1844
- }
1845
1405
  const userAbortReason = Object.assign(new Error("User aborted operation"), {
1846
1406
  code: import_hwk_adapter_core3.HardwareErrorCode.UserAborted,
1847
1407
  _tag: ERROR_TAG.UserAborted
@@ -1852,37 +1412,14 @@ var _LedgerAdapter = class _LedgerAdapter {
1852
1412
  this._lastCancelReason = void 0;
1853
1413
  }
1854
1414
  }, 2e3);
1855
- const activeJobId = this._jobQueue.getActiveJob()?.deviceId;
1856
- let operationId;
1857
- if ((0, import_hwk_adapter_core3.isHardwareOperationId)(connectId)) {
1858
- operationId = connectId;
1859
- } else if (!connectId && (0, import_hwk_adapter_core3.isHardwareOperationId)(activeJobId)) {
1860
- operationId = activeJobId;
1861
- }
1862
- let resolvedConnectId = connectId;
1863
- if (operationId) {
1864
- try {
1865
- resolvedConnectId = this._operations.resolve(operationId).connectId;
1866
- } catch {
1867
- resolvedConnectId = void 0;
1868
- }
1869
- }
1870
1415
  this._uiRegistry.cancel();
1871
- this._finishBleBinding("cancelled");
1872
- const interactionForPhysicalId = !operationId && connectId ? this._operations.findActiveByConnectionKey(connectId) : void 0;
1873
- const queueKey = operationId ?? (activeJobId === connectId ? connectId : interactionForPhysicalId?.operationId) ?? connectId;
1874
- const pendingOperationId = operationId ?? interactionForPhysicalId?.operationId;
1875
- if (!connectId) this._pendingOperationBindings.clear();
1876
- else if (pendingOperationId) {
1877
- this._pendingOperationBindings.delete(pendingOperationId);
1878
- }
1879
- if (queueKey) {
1880
- this._jobQueue.cancelActiveAndPending(queueKey, userAbortReason);
1416
+ if (connectId) {
1417
+ this._jobQueue.cancelActiveAndPending(connectId, userAbortReason);
1881
1418
  } else {
1882
1419
  this._jobQueue.cancelActiveAndPending(void 0, userAbortReason);
1883
1420
  }
1884
- if (resolvedConnectId) {
1885
- const sessionId = this._sessions.get(resolvedConnectId) ?? resolvedConnectId;
1421
+ if (connectId) {
1422
+ const sessionId = this._sessions.get(connectId) ?? connectId;
1886
1423
  void this.connector.cancel(sessionId);
1887
1424
  } else {
1888
1425
  for (const sid of this._sessions.values()) void this.connector.cancel(sid);
@@ -1894,98 +1431,41 @@ var _LedgerAdapter = class _LedgerAdapter {
1894
1431
  // ---------------------------------------------------------------------------
1895
1432
  // Chain fingerprint
1896
1433
  // ---------------------------------------------------------------------------
1897
- /** A non-empty deviceId is an expected chain fingerprint, not a transport identifier. */
1898
1434
  async getChainFingerprint(connectId, deviceId, chain) {
1899
1435
  try {
1900
1436
  const fingerprint = await this._computeChainFingerprint(
1901
1437
  chain,
1902
1438
  (method, params) => this.connectorCall(connectId, method, params, void 0, deviceId)
1903
1439
  );
1904
- if (deviceId) {
1905
- if (fingerprint !== deviceId) {
1906
- return (0, import_hwk_adapter_core3.failure)(
1907
- import_hwk_adapter_core3.HardwareErrorCode.DeviceMismatch,
1908
- formatDeviceMismatchError(deviceId, fingerprint)
1909
- );
1910
- }
1911
- if ((0, import_hwk_adapter_core3.isHardwareOperationId)(connectId)) {
1912
- const operation = this._operations.resolve(connectId);
1913
- await this._publishVerifiedBleBinding(
1914
- operation.connectId,
1915
- chain,
1916
- fingerprint,
1917
- void 0,
1918
- connectId
1919
- );
1920
- }
1921
- }
1922
1440
  return (0, import_hwk_adapter_core3.success)(fingerprint);
1923
1441
  } catch (err) {
1924
1442
  debugError("[LedgerAdapter] getChainFingerprint error:", chain, err);
1925
1443
  return this.errorToFailure(err);
1926
1444
  }
1927
1445
  }
1928
- /** Discovery may select a BLE target before a later call verifies its wallet. */
1929
- async _publishVerifiedBleBinding(connectId, chain, fingerprint, attempt, operationId, signal) {
1930
- const binding = operationId ? this._pendingOperationBindings.get(operationId) : attempt;
1931
- if (!this._isBleConnection() || binding?.selectedConnection?.connectId !== connectId) {
1932
- return false;
1933
- }
1446
+ /**
1447
+ * Verify fingerprint using an existing sessionId directly.
1448
+ * Safe to call inside connectorCall without causing queue deadlock.
1449
+ */
1450
+ async _verifyDeviceFingerprintWithSession(sessionId, deviceId, chain) {
1451
+ if (!deviceId) return { success: true };
1934
1452
  try {
1935
- const outcome = await (0, import_hwk_adapter_core3.requestSaveDeviceBinding)(
1936
- this.emitter,
1937
- this._uiRegistry,
1938
- {
1939
- selectionRequestId: binding.selectedConnection.requestId,
1940
- connection: { transport: "ble", connectId },
1941
- identity: { vendor: "ledger", type: "chainFingerprint", chain, value: fingerprint },
1942
- extra: binding.extra
1943
- },
1944
- signal
1453
+ const fingerprint = await this._computeChainFingerprint(
1454
+ chain,
1455
+ (method, params) => this._callConnector(sessionId, method, params)
1945
1456
  );
1946
- if (operationId) this._operations.resolve(operationId);
1947
- if (!outcome.saved) {
1948
- debugLog("[LedgerAdapter] BLE binding not persisted by host", {
1949
- connectId,
1950
- reason: outcome.reason
1951
- });
1952
- }
1953
- return outcome.saved;
1954
- } catch (error) {
1955
- if (operationId) {
1956
- this._pendingOperationBindings.delete(operationId);
1957
- this._operations.end(operationId, "explicit");
1958
- }
1959
- const sessionId = this._sessions.get(connectId);
1960
- this._sessions.delete(connectId);
1961
- if (sessionId) {
1962
- const teardown = this._runConnectorTeardown(
1963
- () => this.connector.disconnect(sessionId)
1964
- ).catch(() => void 0);
1965
- if (!signal?.aborted) await teardown;
1457
+ if (fingerprint === deviceId) {
1458
+ return { success: true };
1966
1459
  }
1967
- throw error;
1968
- } finally {
1969
- if (this._bindingSelectionRequestId === binding.selectedConnection.requestId) {
1970
- this._bindingSelectionRequestId = void 0;
1971
- }
1972
- if (operationId) {
1973
- this._pendingOperationBindings.delete(operationId);
1460
+ return { success: false, expected: deviceId, actual: fingerprint };
1461
+ } catch (err) {
1462
+ const mapped = mapLedgerError(err);
1463
+ if (mapped.code === import_hwk_adapter_core3.HardwareErrorCode.WrongApp || mapped.code === import_hwk_adapter_core3.HardwareErrorCode.DeviceLocked) {
1464
+ return { success: true };
1974
1465
  }
1466
+ throw err;
1975
1467
  }
1976
1468
  }
1977
- /** Verify on the acquired session without re-entering the job queue. */
1978
- async _verifyDeviceFingerprintWithSession(sessionId, deviceId, chain) {
1979
- if (!deviceId) return { success: true };
1980
- const fingerprint = await this._computeChainFingerprint(
1981
- chain,
1982
- (method, params) => this._callConnector(sessionId, method, params)
1983
- );
1984
- if (fingerprint === deviceId) {
1985
- return { success: true };
1986
- }
1987
- return { success: false, expected: deviceId, actual: fingerprint };
1988
- }
1989
1469
  /**
1990
1470
  * Compute the chain fingerprint via a caller-supplied call strategy.
1991
1471
  *
@@ -2013,8 +1493,6 @@ var _LedgerAdapter = class _LedgerAdapter {
2013
1493
  address = (await callMethod("solGetAddress", { path, showOnDevice: false })).address;
2014
1494
  } else if (chain === "tron") {
2015
1495
  address = (await callMethod("tronGetAddress", { path, showOnDevice: false })).address;
2016
- } else if (chain === "zcash") {
2017
- address = (await callMethod("zcashGetShieldedAddress", { path, showOnDevice: false })).address;
2018
1496
  } else {
2019
1497
  throw new Error(`Unsupported chain for fingerprint: ${chain}`);
2020
1498
  }
@@ -2144,17 +1622,16 @@ var _LedgerAdapter = class _LedgerAdapter {
2144
1622
  // Layer 1 entry. Caller signal only races the outer awaiter; the shared
2145
1623
  // `_doConnect` runs under its own internal controller so caller A's cancel
2146
1624
  // doesn't kill caller B's await.
2147
- async ensureConnected(connectId, signal, allowUsbEphemeralFallback = false, preserveOperationId, context) {
1625
+ async ensureConnected(connectId, signal, allowUsbEphemeralFallback = false) {
2148
1626
  if (signal.aborted) _LedgerAdapter._throwIfAborted(signal);
2149
- this._assertConnectorReady("connectDevice");
2150
- if (this._isBleConnection() && !connectId && !allowUsbEphemeralFallback) {
1627
+ if (isLedgerBleConnectionType(this.connector.connectionType) && !connectId) {
2151
1628
  throw Object.assign(new Error("Ledger BLE connectId is required."), {
2152
1629
  code: import_hwk_adapter_core3.HardwareErrorCode.DeviceNotFound
2153
1630
  });
2154
1631
  }
2155
1632
  if (connectId && this._sessions.has(connectId)) return connectId;
2156
1633
  if (!connectId && this._sessions.size > 0) {
2157
- if (!this._isBleConnection() && this._sessions.size > 1) {
1634
+ if (!isLedgerBleConnectionType(this.connector.connectionType) && this._sessions.size > 1) {
2158
1635
  throw Object.assign(
2159
1636
  new Error(
2160
1637
  "Ledger USB session invariant violated: more than one session is active. Please reconnect the device."
@@ -2164,24 +1641,15 @@ var _LedgerAdapter = class _LedgerAdapter {
2164
1641
  }
2165
1642
  return this._sessions.keys().next().value;
2166
1643
  }
2167
- if (!this._connectingPromise || this._doConnectAbortController?.signal.aborted) {
2168
- const controller = new AbortController();
2169
- this._doConnectAbortController = controller;
2170
- const innerSignal = controller.signal;
1644
+ if (!this._connectingPromise) {
1645
+ this._doConnectAbortController = new AbortController();
1646
+ const innerSignal = this._doConnectAbortController.signal;
2171
1647
  this._connectingPromise = (async () => {
2172
1648
  try {
2173
- return await this._doConnect(
2174
- innerSignal,
2175
- connectId,
2176
- allowUsbEphemeralFallback,
2177
- preserveOperationId,
2178
- context
2179
- );
1649
+ return await this._doConnect(innerSignal, connectId, allowUsbEphemeralFallback);
2180
1650
  } finally {
2181
- if (this._doConnectAbortController === controller) {
2182
- this._connectingPromise = null;
2183
- this._doConnectAbortController = null;
2184
- }
1651
+ this._connectingPromise = null;
1652
+ this._doConnectAbortController = null;
2185
1653
  }
2186
1654
  })();
2187
1655
  }
@@ -2190,51 +1658,22 @@ var _LedgerAdapter = class _LedgerAdapter {
2190
1658
  // Layer 1 main loop — the ONLY place in SDK that emits unlock dialog.
2191
1659
  // Bounded by MAX_DOCONNECT_CONFIRMS — after N Confirms with no progress,
2192
1660
  // throw DeviceNotFound so the user is kicked out of the loop.
2193
- async _doConnect(internalSignal, targetConnectId, allowUsbEphemeralFallback = false, preserveOperationId, context) {
2194
- _LedgerAdapter._throwIfAborted(internalSignal);
2195
- if (this.connector.availableTransports?.includes("usb") && this.connector.availableTransports.includes("ble")) {
2196
- this._activeConnectionType = "usb";
2197
- const usbDevices = await this._searchDevices({ transportType: "usb" }, internalSignal);
2198
- _LedgerAdapter._throwIfAborted(internalSignal);
2199
- if (usbDevices.length > 0) {
2200
- const knownUsb = context?.knownConnections?.find(
2201
- (connection) => connection.transport === "usb"
2202
- );
2203
- const usbTarget = knownUsb?.transport === "usb" ? knownUsb.connectId : usbDevices.find((device) => device.connectId === targetConnectId)?.connectId;
2204
- return this._connectFirstOrSelect(
2205
- usbDevices,
2206
- usbTarget,
2207
- allowUsbEphemeralFallback,
2208
- preserveOperationId,
2209
- context,
2210
- internalSignal
2211
- );
2212
- }
2213
- this._activeConnectionType = "ble";
2214
- const knownBle = context?.knownConnections?.find(
2215
- (connection) => connection.transport === "ble"
2216
- );
2217
- if (knownBle?.transport === "ble") {
2218
- return this._connectDeviceOrThrow(knownBle.connectId, preserveOperationId, internalSignal);
2219
- }
2220
- if (targetConnectId && context?.knownConnections === void 0) {
2221
- throw (0, import_hwk_adapter_core3.createHwkError)({
2222
- code: import_hwk_adapter_core3.HardwareErrorCode.DeviceNotFound,
2223
- message: "Ledger connection metadata is required before starting Bluetooth binding"
2224
- });
1661
+ async _doConnect(internalSignal, targetConnectId, allowUsbEphemeralFallback = false) {
1662
+ if (isLedgerBleConnectionType(this.connector.connectionType) && targetConnectId) {
1663
+ try {
1664
+ return await this._connectDeviceOrThrow(targetConnectId);
1665
+ } catch (err) {
1666
+ if (!isDeviceLockedError(err) && !isDeviceNotAdvertisingError(err) && !isDeviceDisconnectedError(err)) {
1667
+ throw err;
1668
+ }
1669
+ this._discoveredDevices.delete(targetConnectId);
1670
+ if (isDeviceDisconnectedError(err)) {
1671
+ try {
1672
+ this.connector.reset?.();
1673
+ } catch {
1674
+ }
1675
+ }
2225
1676
  }
2226
- const bleDevices = await this._searchDevices({ transportType: "ble" }, internalSignal);
2227
- return this._connectFirstOrSelect(
2228
- bleDevices,
2229
- void 0,
2230
- allowUsbEphemeralFallback,
2231
- preserveOperationId,
2232
- context,
2233
- internalSignal
2234
- );
2235
- }
2236
- if (this._isBleConnection() && targetConnectId) {
2237
- return this._connectDeviceOrThrow(targetConnectId, preserveOperationId, internalSignal);
2238
1677
  }
2239
1678
  let confirms = 0;
2240
1679
  while (!internalSignal.aborted) {
@@ -2242,28 +1681,22 @@ var _LedgerAdapter = class _LedgerAdapter {
2242
1681
  type: import_hwk_adapter_core3.EConnectorInteraction.Searching,
2243
1682
  payload: { sessionId: "" }
2244
1683
  });
2245
- let devices = await this._searchDevices(void 0, internalSignal);
2246
- _LedgerAdapter._throwIfAborted(internalSignal);
1684
+ let devices = await this.searchDevices();
2247
1685
  if (devices.length === 0) {
2248
1686
  for (let i = 0; i < 3 && !internalSignal.aborted; i += 1) {
2249
1687
  await new Promise((resolve) => {
2250
1688
  setTimeout(resolve, import_hwk_adapter_core3.DEVICE_CONNECT_RETRY_DELAY_MS);
2251
1689
  });
2252
- _LedgerAdapter._throwIfAborted(internalSignal);
2253
- devices = await this._searchDevices(void 0, internalSignal);
2254
- _LedgerAdapter._throwIfAborted(internalSignal);
1690
+ devices = await this.searchDevices();
2255
1691
  if (devices.length > 0) break;
2256
1692
  }
2257
1693
  }
2258
- if (devices.length > 0 || this._isBleConnection() && allowUsbEphemeralFallback) {
1694
+ if (devices.length > 0) {
2259
1695
  try {
2260
1696
  return await this._connectFirstOrSelect(
2261
1697
  devices,
2262
1698
  targetConnectId,
2263
- allowUsbEphemeralFallback,
2264
- preserveOperationId,
2265
- context,
2266
- internalSignal
1699
+ allowUsbEphemeralFallback
2267
1700
  );
2268
1701
  } catch (err) {
2269
1702
  if (!isDeviceLockedError(err) && !isDeviceNotAdvertisingError(err) && !isDeviceDisconnectedError(err)) {
@@ -2292,133 +1725,45 @@ var _LedgerAdapter = class _LedgerAdapter {
2292
1725
  _LedgerAdapter._throwIfAborted(internalSignal);
2293
1726
  throw new Error("_doConnect aborted");
2294
1727
  }
2295
- async _connectFirstOrSelect(devices, targetConnectId, allowUsbEphemeralFallback, preserveOperationId, context, signal) {
2296
- _LedgerAdapter._throwIfAborted(signal);
1728
+ async _connectFirstOrSelect(devices, targetConnectId, allowUsbEphemeralFallback = false) {
2297
1729
  if (targetConnectId) {
2298
1730
  const target = devices.find(
2299
1731
  (d) => d.connectId === targetConnectId || d.deviceId === targetConnectId
2300
1732
  );
2301
1733
  if (target) {
2302
- return this._connectDeviceOrThrow(target.connectId, preserveOperationId, signal);
1734
+ return this._connectDeviceOrThrow(target.connectId);
2303
1735
  }
2304
- if (!this._isBleConnection() && devices.length === 1 && allowUsbEphemeralFallback) {
1736
+ if (!isLedgerBleConnectionType(this.connector.connectionType) && devices.length === 1 && allowUsbEphemeralFallback) {
2305
1737
  debugLog(
2306
1738
  `[LedgerAdapter] target ${targetConnectId} not in fresh enumeration; accepting sole USB device ${devices[0].connectId} for fingerprint-verified recovery`
2307
1739
  );
2308
- return this._connectDeviceOrThrow(devices[0].connectId, preserveOperationId, signal);
1740
+ return this._connectDeviceOrThrow(devices[0].connectId);
2309
1741
  }
2310
- if (!this._isBleConnection() || !allowUsbEphemeralFallback) {
2311
- const err = Object.assign(new Error(`Target Ledger unavailable: ${targetConnectId}`), {
2312
- code: import_hwk_adapter_core3.HardwareErrorCode.DeviceNotFound
2313
- });
2314
- if (this._isBleConnection()) {
2315
- err._tag = ERROR_TAG.DeviceNotAdvertising;
2316
- }
2317
- throw err;
1742
+ const err = Object.assign(new Error(`Target Ledger unavailable: ${targetConnectId}`), {
1743
+ code: import_hwk_adapter_core3.HardwareErrorCode.DeviceNotFound
1744
+ });
1745
+ if (isLedgerBleConnectionType(this.connector.connectionType)) {
1746
+ err._tag = ERROR_TAG.DeviceNotAdvertising;
2318
1747
  }
1748
+ throw err;
2319
1749
  }
2320
- const requiresBleSelection = this._isBleConnection();
2321
- if (requiresBleSelection && !allowUsbEphemeralFallback) {
1750
+ if (isLedgerBleConnectionType(this.connector.connectionType)) {
2322
1751
  throw Object.assign(new Error("Ledger BLE connectId is required."), {
2323
1752
  code: import_hwk_adapter_core3.HardwareErrorCode.DeviceNotFound
2324
1753
  });
2325
1754
  }
2326
- if (requiresBleSelection && context?.allowDeviceSelection !== false) {
2327
- const bindingSessionId = context?.bindingSessionId ?? this._uiRegistry.createRequestId();
2328
- if (context) context.bindingSessionId = bindingSessionId;
2329
- const allowUsbFallback = context?.bindingReason !== "manual-rebind" && Boolean(this.connector.availableTransports?.includes("usb"));
2330
- const knownUsb = context?.knownConnections?.find(
2331
- (connection) => connection.transport === "usb"
2332
- );
2333
- const usbConnectId = knownUsb?.transport === "usb" ? knownUsb.connectId : targetConnectId;
2334
- const { device, requestId } = await (0, import_hwk_adapter_core3.requestBleDeviceSelection)({
2335
- emitter: this.emitter,
2336
- registry: this._uiRegistry,
2337
- signal,
2338
- allowUsbFallback,
2339
- scan: async () => {
2340
- if (allowUsbFallback) {
2341
- const usbDevices = await this._searchDevices({ transportType: "usb" }, signal);
2342
- const candidate = usbDevices.find(
2343
- (device2) => device2.connectionType === "usb" && device2.connectId === usbConnectId
2344
- ) ?? (usbDevices.length === 1 && usbDevices[0].connectionType === "usb" ? usbDevices[0] : void 0);
2345
- if (candidate) return [candidate];
2346
- }
2347
- return (await this._searchDevices({ transportType: "ble", waitForAllTransports: true }, signal)).filter((device2) => !context?.rejectedConnectIds?.has(device2.connectId));
2348
- },
2349
- request: {
2350
- devices: devices.filter((device2) => !context?.rejectedConnectIds?.has(device2.connectId)),
2351
- bindingSessionId,
2352
- rejectedConnectId: context?.rejectedConnectId,
2353
- context: {
2354
- kind: "bind-connection",
2355
- transport: "ble",
2356
- reason: context?.bindingReason ?? (targetConnectId ? "known-connection-unavailable" : "missing-binding")
2357
- },
2358
- extra: context?.extra
2359
- }
2360
- });
2361
- if (device.connectionType === "usb") {
2362
- this._activeConnectionType = "usb";
2363
- if (context) context.selectedConnection = void 0;
2364
- if (preserveOperationId) this._pendingOperationBindings.delete(preserveOperationId);
2365
- this._bindingSelectionRequestId = void 0;
2366
- this.emitter.emit(import_hwk_adapter_core3.UI_REQUEST.DEVICE_BINDING_STATUS, {
2367
- type: import_hwk_adapter_core3.UI_REQUEST.DEVICE_BINDING_STATUS,
2368
- payload: { selectionRequestId: requestId, status: "cancelled" }
2369
- });
2370
- return this._connectDeviceOrThrow(device.connectId, preserveOperationId, signal);
2371
- }
2372
- if (context) context.selectedConnection = { connectId: device.connectId, requestId };
2373
- this._bindingSelectionRequestId = requestId;
2374
- return this._connectDeviceOrThrow(device.connectId, preserveOperationId, signal);
2375
- }
2376
- if (devices.length > 0 && (devices.length > 1 || requiresBleSelection)) {
2377
- if (context?.allowDeviceSelection === false || !this.emitter.listenerCount(import_hwk_adapter_core3.UI_REQUEST.REQUEST_SELECT_DEVICE)) {
2378
- throw (0, import_hwk_adapter_core3.createHwkError)({
2379
- code: import_hwk_adapter_core3.HardwareErrorCode.DeviceNotFound,
2380
- message: "Select a Ledger device before continuing"
2381
- });
2382
- }
2383
- const requestId = this._uiRegistry.createRequestId();
2384
- const waitPromise = this._uiRegistry.wait(
2385
- import_hwk_adapter_core3.UI_REQUEST.REQUEST_SELECT_DEVICE,
2386
- { requestId }
2387
- );
2388
- this.emitter.emit(import_hwk_adapter_core3.UI_REQUEST.REQUEST_SELECT_DEVICE, {
2389
- type: import_hwk_adapter_core3.UI_REQUEST.REQUEST_SELECT_DEVICE,
2390
- payload: {
2391
- devices,
2392
- requestId,
2393
- context: requiresBleSelection ? {
2394
- kind: "bind-connection",
2395
- transport: "ble",
2396
- reason: targetConnectId ? "known-connection-unavailable" : "missing-binding"
2397
- } : { kind: "select-device", transport: "usb", reason: "multiple-candidates" },
2398
- extra: context?.extra
2399
- }
2400
- });
2401
- const { sdkConnectId } = await (signal ? this._abortable(signal, waitPromise) : waitPromise);
2402
- if (signal) _LedgerAdapter._throwIfAborted(signal);
2403
- const selected = devices.find((device) => device.connectId === sdkConnectId);
2404
- if (!selected) {
2405
- throw Object.assign(new Error("Selected Ledger is no longer available"), {
2406
- code: import_hwk_adapter_core3.HardwareErrorCode.DeviceNotFound
2407
- });
2408
- }
2409
- if (context && requiresBleSelection)
2410
- context.selectedConnection = { connectId: selected.connectId, requestId };
2411
- return this._connectDeviceOrThrow(selected.connectId, preserveOperationId, signal);
1755
+ if (devices.length > 1) {
1756
+ throw createMultipleUsbLedgerDevicesError();
2412
1757
  }
2413
1758
  if (devices.length !== 1) {
2414
1759
  throw Object.assign(new Error("Ledger device not found."), {
2415
1760
  code: import_hwk_adapter_core3.HardwareErrorCode.DeviceNotFound
2416
1761
  });
2417
1762
  }
2418
- return this._connectDeviceOrThrow(devices[0].connectId, preserveOperationId, signal);
1763
+ return this._connectDeviceOrThrow(devices[0].connectId);
2419
1764
  }
2420
- async _connectDeviceOrThrow(chosenConnectId, preserveOperationId, signal) {
2421
- const result = await this._connectTarget(chosenConnectId, preserveOperationId, signal);
1765
+ async _connectDeviceOrThrow(chosenConnectId) {
1766
+ const result = await this.connectDevice(chosenConnectId);
2422
1767
  if (!result.success) {
2423
1768
  const payload = result.payload;
2424
1769
  const rethrow = Object.assign(new Error(payload.error), {
@@ -2429,7 +1774,7 @@ var _LedgerAdapter = class _LedgerAdapter {
2429
1774
  }
2430
1775
  throw rethrow;
2431
1776
  }
2432
- return result.payload;
1777
+ return chosenConnectId;
2433
1778
  }
2434
1779
  /**
2435
1780
  * Call the connector with automatic session resolution and disconnect retry.
@@ -2459,122 +1804,26 @@ var _LedgerAdapter = class _LedgerAdapter {
2459
1804
  * lives in one place.
2460
1805
  */
2461
1806
  async _callConnector(sessionId, method, params, signal) {
2462
- this._assertConnectorReady(method);
2463
- if (signal?.aborted) throw this._abortReason(signal);
2464
- const releaseOperation = this._retainConnectorOperation(`call:${sessionId}`);
2465
- let promise;
2466
- try {
2467
- promise = this.connector.call(sessionId, method, params).finally(releaseOperation);
2468
- } catch (error) {
2469
- releaseOperation();
2470
- throw error;
2471
- }
1807
+ const promise = this.connector.call(sessionId, method, params);
2472
1808
  const result = signal ? await this._abortable(signal, promise) : await promise;
2473
1809
  return this._unwrapConnectorResult(result);
2474
1810
  }
2475
- _assertConnectorReady(method) {
2476
- if (this._resetPromise || this._pendingConnectorTeardowns > 0 || this._unsettledConnectorOperations.size > 0) {
2477
- throw _LedgerAdapter._createDeviceBusyError(method);
2478
- }
2479
- }
2480
- _runConnectorTeardown(task) {
2481
- const previous = this._connectorTeardownTail;
2482
- let releaseTail = () => void 0;
2483
- this._connectorTeardownTail = new Promise((resolve) => {
2484
- releaseTail = resolve;
2485
- });
2486
- this._pendingConnectorTeardowns += 1;
2487
- return (async () => {
2488
- try {
2489
- await previous;
2490
- await this._waitForConnectorOperationsToDrain();
2491
- await task();
2492
- } finally {
2493
- this._pendingConnectorTeardowns -= 1;
2494
- releaseTail();
2495
- }
2496
- })();
2497
- }
2498
- _waitForConnectorOperationsToDrain() {
2499
- if (this._unsettledConnectorOperations.size === 0) {
2500
- return Promise.resolve();
2501
- }
2502
- return new Promise((resolve) => {
2503
- this._connectorIdleWaiters.add(resolve);
2504
- });
2505
- }
2506
- _retainConnectorOperation(key) {
2507
- this._unsettledConnectorOperations.set(
2508
- key,
2509
- (this._unsettledConnectorOperations.get(key) ?? 0) + 1
2510
- );
2511
- let released = false;
2512
- return () => {
2513
- if (released) return;
2514
- released = true;
2515
- const remaining = (this._unsettledConnectorOperations.get(key) ?? 1) - 1;
2516
- if (remaining > 0) {
2517
- this._unsettledConnectorOperations.set(key, remaining);
2518
- } else {
2519
- this._unsettledConnectorOperations.delete(key);
2520
- }
2521
- if (this._unsettledConnectorOperations.size === 0) {
2522
- for (const resolve of this._connectorIdleWaiters) resolve();
2523
- this._connectorIdleWaiters.clear();
2524
- }
2525
- };
2526
- }
2527
1811
  async connectorCall(connectId, method, params, fingerprint, permissionDeviceId, commonParams, installContext) {
2528
- const positionalOperationId = (0, import_hwk_adapter_core3.isHardwareOperationId)(connectId) ? connectId : void 0;
2529
- if (positionalOperationId && commonParams?.operationId && positionalOperationId !== commonParams.operationId) {
2530
- throw (0, import_hwk_adapter_core3.createHwkError)({
2531
- code: import_hwk_adapter_core3.HardwareErrorCode.InvalidParams,
2532
- message: "Conflicting Ledger operation ids",
2533
- params: {
2534
- positionalOperationId,
2535
- commonOperationId: commonParams.operationId
2536
- }
2537
- });
2538
- }
2539
- const operationId = commonParams?.operationId ?? positionalOperationId;
2540
- const operation = operationId ? this._operations.resolve(operationId) : void 0;
2541
- const releaseOperationRetention = operationId ? this._operations.retain(operationId) : void 0;
2542
- const effectiveConnectId = operation?.connectId ?? connectId;
2543
- debugLog("[LedgerAdapter][REQ]", {
2544
- method,
2545
- connectId: effectiveConnectId || "(empty)",
2546
- params
2547
- });
2548
- const queueKey = (operationId ?? effectiveConnectId) || "__ledger_default__";
1812
+ debugLog("[LedgerAdapter][REQ]", { method, connectId: connectId || "(empty)", params });
1813
+ const queueKey = connectId || "__ledger_default__";
2549
1814
  try {
2550
1815
  const result = await this._jobQueue.enqueue(
2551
1816
  queueKey,
2552
- async (signal) => {
2553
- if (operationId) this._activeOperationJobs.add(operationId);
2554
- try {
2555
- return await this._runConnectorCall(
2556
- effectiveConnectId,
2557
- method,
2558
- params,
2559
- signal,
2560
- fingerprint,
2561
- permissionDeviceId,
2562
- commonParams,
2563
- installContext ?? {},
2564
- operationId
2565
- );
2566
- } catch (error) {
2567
- this._finishBleBinding(signal.aborted ? "cancelled" : "failed");
2568
- throw error;
2569
- } finally {
2570
- if (operationId) {
2571
- this._activeOperationJobs.delete(operationId);
2572
- if (this._pendingOperationDisconnects.delete(operationId)) {
2573
- await this._releaseLostOperationConnection(operationId);
2574
- }
2575
- }
2576
- }
2577
- },
1817
+ async (signal) => this._runConnectorCall(
1818
+ connectId,
1819
+ method,
1820
+ params,
1821
+ signal,
1822
+ fingerprint,
1823
+ permissionDeviceId,
1824
+ commonParams,
1825
+ installContext
1826
+ ),
2578
1827
  {
2579
1828
  label: method,
2580
1829
  rejectIfBusy: true,
@@ -2595,22 +1844,15 @@ var _LedgerAdapter = class _LedgerAdapter {
2595
1844
  }
2596
1845
  });
2597
1846
  throw err;
2598
- } finally {
2599
- releaseOperationRetention?.();
2600
1847
  }
2601
1848
  }
2602
1849
  /**
2603
1850
  * Race a promise against an abort signal. On abort, rejects with
2604
1851
  * signal.reason → instance _lastCancelReason → generic Error('Aborted').
2605
1852
  */
2606
- /** Hermes/RN polyfills don't always populate signal.reason; fall back. */
2607
- _abortReason(signal) {
2608
- return signal.reason ?? this._lastCancelReason ?? new Error("Aborted");
2609
- }
2610
1853
  _abortable(signal, promise) {
2611
- const getAbortReason = () => this._abortReason(signal);
1854
+ const getAbortReason = () => signal.reason ?? this._lastCancelReason ?? new Error("Aborted");
2612
1855
  if (signal.aborted) {
2613
- void promise.catch(() => void 0);
2614
1856
  return Promise.reject(getAbortReason());
2615
1857
  }
2616
1858
  return new Promise((resolve, reject) => {
@@ -2637,15 +1879,13 @@ var _LedgerAdapter = class _LedgerAdapter {
2637
1879
  }
2638
1880
  }
2639
1881
  /** Actual work done under the job queue — connection, fingerprint, call, and recovery. */
2640
- async _runConnectorCall(connectId, method, params, signal, fingerprint, permissionDeviceId, commonParams, installContext, operationId, lockedRetryBudget = _LedgerAdapter.MAX_BUSINESS_RETRY_BUDGET) {
1882
+ async _runConnectorCall(connectId, method, params, signal, fingerprint, permissionDeviceId, commonParams, installContext) {
2641
1883
  _LedgerAdapter._throwIfAborted(signal);
2642
- if (!operationId) {
2643
- await this._ensureDevicePermission(
2644
- connectId,
2645
- permissionDeviceId ?? fingerprint?.deviceId,
2646
- signal
2647
- );
2648
- }
1884
+ await this._ensureDevicePermission(
1885
+ connectId,
1886
+ permissionDeviceId ?? fingerprint?.deviceId,
1887
+ signal
1888
+ );
2649
1889
  _LedgerAdapter._throwIfAborted(signal);
2650
1890
  let effectiveParams = params;
2651
1891
  if (method === "btcGetPublicKey") {
@@ -2659,132 +1899,36 @@ var _LedgerAdapter = class _LedgerAdapter {
2659
1899
  effectiveParams = gatedParams;
2660
1900
  }
2661
1901
  const allowUsbEphemeralFallback = !!fingerprint?.deviceId && !fingerprint.skipFingerprint;
2662
- let businessCallStarted = false;
2663
- const verifiedBleTarget = connectId ? this._verifiedBleReconnectTargets.get(connectId) : void 0;
2664
- const knownTransport = this._isBleConnection() ? "ble" : "usb";
2665
- const hintedConnectId = commonParams?.knownConnections?.find(
2666
- (connection) => connection.transport === knownTransport
2667
- );
2668
- const inputConnectId = hintedConnectId && hintedConnectId.transport !== "qr" ? hintedConnectId.connectId : connectId;
2669
- const preferredConnectId = fingerprint && !fingerprint.skipFingerprint && verifiedBleTarget?.chain === fingerprint.chain && verifiedBleTarget.fingerprint === fingerprint.deviceId ? verifiedBleTarget.connectId : inputConnectId;
2670
- const connectionAttempt = { ...commonParams };
2671
- const bundleConnection = installContext?.connection;
2672
- if (bundleConnection && this._sessions.get(bundleConnection.connectId) !== bundleConnection.sessionId) {
2673
- throw (0, import_hwk_adapter_core3.createHwkError)({
2674
- code: import_hwk_adapter_core3.HardwareErrorCode.DeviceDisconnected,
2675
- message: "Ledger all-network connection ended"
2676
- });
2677
- }
2678
- let resolvedConnectId = operationId ? this._operations.resolve(operationId).connectId : bundleConnection?.connectId ?? await this.ensureConnected(
2679
- preferredConnectId,
1902
+ const resolvedConnectId = await this.ensureConnected(
1903
+ connectId,
2680
1904
  signal,
2681
- allowUsbEphemeralFallback,
2682
- void 0,
2683
- connectionAttempt
1905
+ allowUsbEphemeralFallback
2684
1906
  );
2685
- let sessionId = this._sessions.get(resolvedConnectId);
2686
- if (sessionId && installContext && !installContext.connection) {
2687
- installContext.connection = { connectId: resolvedConnectId, sessionId };
2688
- }
1907
+ const sessionId = this._sessions.get(resolvedConnectId);
2689
1908
  if (!sessionId) {
2690
- if (operationId) {
2691
- this._operations.end(operationId, "disconnect");
2692
- throw (0, import_hwk_adapter_core3.createHwkError)({
2693
- code: import_hwk_adapter_core3.HardwareErrorCode.OperationEnded,
2694
- message: "Ledger operation connection is no longer active",
2695
- params: { operationId, reason: "disconnect" }
2696
- });
2697
- }
2698
1909
  throw Object.assign(new Error("Auto-connect succeeded but no session found"), {
2699
1910
  _tag: ERROR_TAG.DeviceSessionNotFound
2700
1911
  });
2701
1912
  }
2702
1913
  try {
2703
1914
  if (fingerprint && !fingerprint.skipFingerprint && fingerprint.deviceId) {
2704
- for (; ; ) {
2705
- const fp = await this._abortable(
2706
- signal,
2707
- this._verifyDeviceFingerprintWithSession(
2708
- sessionId,
2709
- fingerprint.deviceId,
2710
- fingerprint.chain
2711
- )
2712
- );
2713
- if (fp.success) break;
2714
- const binding = operationId ? this._pendingOperationBindings.get(operationId) : connectionAttempt;
2715
- if (!this._isBleConnection() || binding?.selectedConnection?.connectId !== resolvedConnectId) {
2716
- throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {
2717
- code: import_hwk_adapter_core3.HardwareErrorCode.DeviceMismatch
2718
- });
2719
- }
2720
- binding.rejectedConnectIds ?? (binding.rejectedConnectIds = /* @__PURE__ */ new Set());
2721
- binding.rejectedConnectIds.add(resolvedConnectId);
2722
- binding.rejectedConnectId = resolvedConnectId;
2723
- this._sessions.delete(resolvedConnectId);
2724
- await this.connector.disconnect(sessionId);
2725
- if (operationId) this._pendingOperationDisconnects.delete(operationId);
2726
- _LedgerAdapter._throwIfAborted(signal);
2727
- resolvedConnectId = await this._connectFirstOrSelect(
2728
- [],
2729
- void 0,
2730
- true,
2731
- operationId,
2732
- binding,
2733
- signal
2734
- );
2735
- const selectedSession = this._sessions.get(resolvedConnectId);
2736
- const selectedDevice = this._discoveredDevices.get(resolvedConnectId);
2737
- if (!selectedSession || !selectedDevice)
2738
- throw (0, import_hwk_adapter_core3.createHwkError)({
2739
- code: import_hwk_adapter_core3.HardwareErrorCode.DeviceDisconnected,
2740
- message: "Selected Ledger connection ended"
2741
- });
2742
- sessionId = selectedSession;
2743
- if (operationId)
2744
- this._operations.rebind(operationId, {
2745
- connectId: resolvedConnectId,
2746
- device: selectedDevice,
2747
- connectionKeys: [sessionId]
2748
- });
2749
- if (installContext)
2750
- installContext.connection = { connectId: resolvedConnectId, sessionId };
2751
- }
2752
- await this._publishVerifiedBleBinding(
2753
- resolvedConnectId,
2754
- fingerprint.chain,
2755
- fingerprint.deviceId,
2756
- connectionAttempt,
2757
- operationId,
2758
- signal
1915
+ const fp = await this._abortable(
1916
+ signal,
1917
+ this._verifyDeviceFingerprintWithSession(
1918
+ sessionId,
1919
+ fingerprint.deviceId,
1920
+ fingerprint.chain
1921
+ )
2759
1922
  );
2760
- if (!operationId && connectionAttempt.selectedConnection?.connectId === resolvedConnectId && this._isBleConnection()) {
2761
- this._verifiedBleReconnectTargets.set(connectId, {
2762
- connectId: resolvedConnectId,
2763
- chain: fingerprint.chain,
2764
- fingerprint: fingerprint.deviceId
1923
+ if (!fp.success) {
1924
+ throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {
1925
+ code: import_hwk_adapter_core3.HardwareErrorCode.DeviceMismatch
2765
1926
  });
2766
1927
  }
2767
1928
  }
2768
- businessCallStarted = true;
2769
1929
  return await this._callConnector(sessionId, method, effectiveParams, signal);
2770
1930
  } catch (err) {
2771
1931
  if (signal.aborted) throw err;
2772
- if (isDeviceDisconnectedError(err) || isDeviceNotAdvertisingError(err) || isTimeoutError(err) || isConnectionLevelError(err)) {
2773
- this._discoveredDevices.delete(resolvedConnectId);
2774
- if (operationId) await this._releaseLostOperationConnection(operationId);
2775
- else {
2776
- this._sessions.delete(resolvedConnectId);
2777
- await this.connector.disconnect(sessionId).catch(() => void 0);
2778
- }
2779
- const ambiguous = businessCallStarted && !(0, import_hwk_adapter_core3.canReplayHardwareMethodAfterTransportFailure)(method);
2780
- const interactionParams = operationId ? { operationId, reason: "disconnect" } : void 0;
2781
- throw (0, import_hwk_adapter_core3.createHwkError)({
2782
- code: operationId ? import_hwk_adapter_core3.HardwareErrorCode.OperationEnded : mapLedgerError(err).code,
2783
- message: "Ledger operation connection was lost; start a new operation",
2784
- params: ambiguous ? (0, import_hwk_adapter_core3.operationMayHaveCompletedParams)(method, { operationId }) : interactionParams,
2785
- recovery: ambiguous ? { scope: "unknown" } : void 0
2786
- });
2787
- }
2788
1932
  const errObj = err;
2789
1933
  debugLog("[LedgerAdapter] connectorCall error:", method, {
2790
1934
  message: errObj?.message,
@@ -2796,65 +1940,6 @@ var _LedgerAdapter = class _LedgerAdapter {
2796
1940
  isNotAdvertising: isDeviceNotAdvertisingError(err),
2797
1941
  isStuckApp: isStuckAppStateError(err)
2798
1942
  });
2799
- if ((isDeviceLockedError(err) || errObj?.code === import_hwk_adapter_core3.HardwareErrorCode.DeviceLocked) && lockedRetryBudget > 0) {
2800
- await this._waitForDeviceConnect(signal);
2801
- if (this._sessions.get(resolvedConnectId) !== sessionId) {
2802
- throw (0, import_hwk_adapter_core3.createHwkError)({
2803
- code: operationId ? import_hwk_adapter_core3.HardwareErrorCode.OperationEnded : import_hwk_adapter_core3.HardwareErrorCode.DeviceDisconnected,
2804
- message: "Ledger connection ended while waiting for unlock"
2805
- });
2806
- }
2807
- return this._runConnectorCall(
2808
- resolvedConnectId,
2809
- method,
2810
- effectiveParams,
2811
- signal,
2812
- fingerprint,
2813
- permissionDeviceId,
2814
- commonParams,
2815
- installContext,
2816
- operationId,
2817
- lockedRetryBudget - 1
2818
- );
2819
- }
2820
- if (businessCallStarted && isStuckAppStateError(err)) {
2821
- await this._sleepAbortable(_LedgerAdapter.STUCK_APP_RETRY_DELAY_MS, signal);
2822
- if (this._sessions.get(resolvedConnectId) !== sessionId) {
2823
- throw (0, import_hwk_adapter_core3.createHwkError)({
2824
- code: operationId ? import_hwk_adapter_core3.HardwareErrorCode.OperationEnded : import_hwk_adapter_core3.HardwareErrorCode.DeviceDisconnected,
2825
- message: "Ledger connection ended during the app transition"
2826
- });
2827
- }
2828
- try {
2829
- return await this._callConnector(sessionId, method, effectiveParams, signal);
2830
- } catch (retryErr) {
2831
- if (isStuckAppStateError(retryErr)) throw err;
2832
- if (isDeviceDisconnectedError(retryErr) || isDeviceNotAdvertisingError(retryErr) || isTimeoutError(retryErr) || isConnectionLevelError(retryErr)) {
2833
- if (operationId) await this._releaseLostOperationConnection(operationId);
2834
- else {
2835
- this._sessions.delete(resolvedConnectId);
2836
- this._discoveredDevices.delete(resolvedConnectId);
2837
- await this.connector.disconnect(sessionId).catch(() => void 0);
2838
- }
2839
- throw (0, import_hwk_adapter_core3.createHwkError)({
2840
- code: operationId ? import_hwk_adapter_core3.HardwareErrorCode.OperationEnded : mapLedgerError(retryErr).code,
2841
- message: `Ledger ${method} may have completed before the connection was lost`,
2842
- params: !(0, import_hwk_adapter_core3.canReplayHardwareMethodAfterTransportFailure)(method) ? (0, import_hwk_adapter_core3.operationMayHaveCompletedParams)(method, {
2843
- operationId,
2844
- reason: "disconnect"
2845
- }) : { operationId, reason: "disconnect" },
2846
- recovery: !(0, import_hwk_adapter_core3.canReplayHardwareMethodAfterTransportFailure)(method) ? { scope: "unknown" } : void 0
2847
- });
2848
- }
2849
- throw retryErr;
2850
- }
2851
- }
2852
- if (!operationId && err?.code === import_hwk_adapter_core3.HardwareErrorCode.DeviceMismatch) {
2853
- this._sessions.delete(resolvedConnectId);
2854
- this._discoveredDevices.delete(resolvedConnectId);
2855
- await this.connector.disconnect(sessionId).catch(() => void 0);
2856
- throw err;
2857
- }
2858
1943
  const autoInstallApp = commonParams?.autoInstallApp ?? this._defaultAutoInstallApp;
2859
1944
  const isAppMissing = isAppNotInstalledError(err) || err?.code === import_hwk_adapter_core3.HardwareErrorCode.AppNotInstalled;
2860
1945
  if (autoInstallApp && isAppMissing) {
@@ -2910,14 +1995,157 @@ var _LedgerAdapter = class _LedgerAdapter {
2910
1995
  fingerprint,
2911
1996
  permissionDeviceId,
2912
1997
  commonParams,
2913
- installContext,
2914
- operationId
1998
+ installContext
1999
+ );
2000
+ }
2001
+ }
2002
+ if (isStuckAppStateError(err)) {
2003
+ try {
2004
+ this._sessions.delete(resolvedConnectId);
2005
+ this._discoveredDevices.delete(resolvedConnectId);
2006
+ this.connector.reset?.();
2007
+ } catch {
2008
+ }
2009
+ debugLog(
2010
+ "[LedgerAdapter] stuck-app retry: method=",
2011
+ method,
2012
+ "delayMs=",
2013
+ _LedgerAdapter.STUCK_APP_RETRY_DELAY_MS,
2014
+ "_tag=",
2015
+ err?._tag
2016
+ );
2017
+ try {
2018
+ const retryResult = await this._retryAfterStuckApp(
2019
+ resolvedConnectId,
2020
+ method,
2021
+ effectiveParams,
2022
+ signal,
2023
+ err,
2024
+ fingerprint
2915
2025
  );
2026
+ debugLog("[LedgerAdapter] stuck-app retry succeeded: method=", method);
2027
+ return retryResult;
2028
+ } catch (retryErr) {
2029
+ if (signal.aborted) throw retryErr;
2030
+ if (isStuckAppStateError(retryErr)) {
2031
+ debugLog("[LedgerAdapter] stuck-app retry exhausted (2nd 6901): method=", method);
2032
+ throw err;
2033
+ }
2034
+ debugLog(
2035
+ "[LedgerAdapter] stuck-app retry threw non-stuck error: method=",
2036
+ method,
2037
+ "retryErrTag=",
2038
+ retryErr?._tag
2039
+ );
2040
+ throw retryErr;
2041
+ }
2042
+ }
2043
+ if (isDeviceLockedError(err) || isDeviceNotAdvertisingError(err) || isDeviceDisconnectedError(err)) {
2044
+ let lastErr = err;
2045
+ for (let attempt = 0; attempt < _LedgerAdapter.MAX_BUSINESS_RETRY_BUDGET; attempt += 1) {
2046
+ if (signal.aborted) throw lastErr;
2047
+ try {
2048
+ this._sessions.delete(resolvedConnectId);
2049
+ this._discoveredDevices.delete(resolvedConnectId);
2050
+ if (isDeviceDisconnectedError(lastErr)) {
2051
+ try {
2052
+ this.connector.reset?.();
2053
+ } catch {
2054
+ }
2055
+ }
2056
+ const reConnectId = await this.ensureConnected(
2057
+ resolvedConnectId,
2058
+ signal,
2059
+ allowUsbEphemeralFallback
2060
+ );
2061
+ const reSessionId = this._sessions.get(reConnectId);
2062
+ if (!reSessionId) throw lastErr;
2063
+ if (fingerprint && !fingerprint.skipFingerprint && fingerprint.deviceId) {
2064
+ const fp = await this._abortable(
2065
+ signal,
2066
+ this._verifyDeviceFingerprintWithSession(
2067
+ reSessionId,
2068
+ fingerprint.deviceId,
2069
+ fingerprint.chain
2070
+ )
2071
+ );
2072
+ if (!fp.success) {
2073
+ throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {
2074
+ code: import_hwk_adapter_core3.HardwareErrorCode.DeviceMismatch
2075
+ });
2076
+ }
2077
+ }
2078
+ return await this._callConnector(reSessionId, method, effectiveParams, signal);
2079
+ } catch (retryErr) {
2080
+ if (signal.aborted) throw retryErr;
2081
+ lastErr = retryErr;
2082
+ const canRetry = attempt < _LedgerAdapter.MAX_BUSINESS_RETRY_BUDGET - 1 && (isDeviceLockedError(retryErr) || isDeviceNotAdvertisingError(retryErr) || isDeviceDisconnectedError(retryErr));
2083
+ if (!canRetry) {
2084
+ throw retryErr;
2085
+ }
2086
+ }
2916
2087
  }
2088
+ throw lastErr;
2089
+ }
2090
+ if (isTimeoutError(err)) {
2091
+ debugLog("[LedgerAdapter] timeout, retrying with fresh connection...");
2092
+ this._discoveredDevices.delete(resolvedConnectId);
2093
+ return this._retryWithFreshConnection(
2094
+ resolvedConnectId,
2095
+ method,
2096
+ effectiveParams,
2097
+ signal,
2098
+ err,
2099
+ fingerprint
2100
+ );
2101
+ }
2102
+ if (isConnectionLevelError(err)) {
2103
+ debugLog("[LedgerAdapter] connection-level fail-closed reset");
2104
+ this._sessions.delete(resolvedConnectId);
2105
+ this._discoveredDevices.delete(resolvedConnectId);
2106
+ this.connector.reset();
2107
+ const codeNum = err?.code;
2108
+ throw Object.assign(err, {
2109
+ code: codeNum ?? import_hwk_adapter_core3.HardwareErrorCode.DeviceDisconnected
2110
+ });
2917
2111
  }
2918
2112
  throw err;
2919
2113
  }
2920
2114
  }
2115
+ /**
2116
+ * Stuck-app recovery: pause for the device's UI transition, then retry once.
2117
+ *
2118
+ * Caller has already cleared the session + reset connector. We wait so Stax
2119
+ * finishes its post-CloseApp animation, then go through ensureConnected +
2120
+ * fingerprint check + call exactly once. Caller decides what to do on a
2121
+ * second stuck-app hit.
2122
+ */
2123
+ async _retryAfterStuckApp(resolvedConnectId, method, params, signal, originalErr, fingerprint) {
2124
+ await this._sleepAbortable(_LedgerAdapter.STUCK_APP_RETRY_DELAY_MS, signal);
2125
+ const retryConnectId = await this.ensureConnected(
2126
+ resolvedConnectId,
2127
+ signal,
2128
+ !!fingerprint?.deviceId && !fingerprint.skipFingerprint
2129
+ );
2130
+ const retrySessionId = this._sessions.get(retryConnectId);
2131
+ if (!retrySessionId) throw originalErr;
2132
+ if (fingerprint && !fingerprint.skipFingerprint && fingerprint.deviceId) {
2133
+ const fp = await this._abortable(
2134
+ signal,
2135
+ this._verifyDeviceFingerprintWithSession(
2136
+ retrySessionId,
2137
+ fingerprint.deviceId,
2138
+ fingerprint.chain
2139
+ )
2140
+ );
2141
+ if (!fp.success) {
2142
+ throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {
2143
+ code: import_hwk_adapter_core3.HardwareErrorCode.DeviceMismatch
2144
+ });
2145
+ }
2146
+ }
2147
+ return this._callConnector(retrySessionId, method, params, signal);
2148
+ }
2921
2149
  _sleepAbortable(ms, signal) {
2922
2150
  return new Promise((resolve, reject) => {
2923
2151
  if (signal.aborted) {
@@ -2935,6 +2163,88 @@ var _LedgerAdapter = class _LedgerAdapter {
2935
2163
  signal.addEventListener("abort", onAbort, { once: true });
2936
2164
  });
2937
2165
  }
2166
+ /**
2167
+ * Clear stale session, reconnect, and retry the call.
2168
+ *
2169
+ * Timeout recovery starts with a full connector reset. After an APDU
2170
+ * timeout, DMK/transport state may still emit malformed responses; retrying
2171
+ * on the same DMK can poison the next chain switch.
2172
+ */
2173
+ async _retryWithFreshConnection(targetConnectId, method, params, signal, originalErr, fingerprint) {
2174
+ this.connector.reset();
2175
+ this._sessions.clear();
2176
+ this._discoveredDevices.clear();
2177
+ this._connectingPromise = null;
2178
+ const allowUsbEphemeralFallback = !!fingerprint?.deviceId && !fingerprint.skipFingerprint;
2179
+ const retryConnectId = await this.ensureConnected(
2180
+ targetConnectId,
2181
+ signal,
2182
+ allowUsbEphemeralFallback
2183
+ );
2184
+ const retrySessionId = this._sessions.get(retryConnectId);
2185
+ if (!retrySessionId) {
2186
+ throw originalErr;
2187
+ }
2188
+ try {
2189
+ if (fingerprint && !fingerprint.skipFingerprint && fingerprint.deviceId) {
2190
+ const fp = await this._abortable(
2191
+ signal,
2192
+ this._verifyDeviceFingerprintWithSession(
2193
+ retrySessionId,
2194
+ fingerprint.deviceId,
2195
+ fingerprint.chain
2196
+ )
2197
+ );
2198
+ if (!fp.success) {
2199
+ throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {
2200
+ code: import_hwk_adapter_core3.HardwareErrorCode.DeviceMismatch
2201
+ });
2202
+ }
2203
+ }
2204
+ return await this._callConnector(retrySessionId, method, params, signal);
2205
+ } catch (retryErr) {
2206
+ if (signal.aborted) throw retryErr;
2207
+ this.connector.reset();
2208
+ this._sessions.clear();
2209
+ this._discoveredDevices.clear();
2210
+ this._connectingPromise = null;
2211
+ if (!isDeviceDisconnectedError(retryErr) && !isTimeoutError(retryErr)) {
2212
+ throw retryErr;
2213
+ }
2214
+ debugLog(
2215
+ "[LedgerAdapter] fresh-session retry still failed; resetting connector and rebuilding DMK"
2216
+ );
2217
+ this.connector.reset();
2218
+ this._sessions.clear();
2219
+ this._discoveredDevices.clear();
2220
+ this._connectingPromise = null;
2221
+ const finalConnectId = await this.ensureConnected(
2222
+ targetConnectId,
2223
+ signal,
2224
+ allowUsbEphemeralFallback
2225
+ );
2226
+ const finalSessionId = this._sessions.get(finalConnectId);
2227
+ if (!finalSessionId) {
2228
+ throw originalErr;
2229
+ }
2230
+ if (fingerprint && !fingerprint.skipFingerprint && fingerprint.deviceId) {
2231
+ const fp = await this._abortable(
2232
+ signal,
2233
+ this._verifyDeviceFingerprintWithSession(
2234
+ finalSessionId,
2235
+ fingerprint.deviceId,
2236
+ fingerprint.chain
2237
+ )
2238
+ );
2239
+ if (!fp.success) {
2240
+ throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {
2241
+ code: import_hwk_adapter_core3.HardwareErrorCode.DeviceMismatch
2242
+ });
2243
+ }
2244
+ }
2245
+ return this._callConnector(finalSessionId, method, params, signal);
2246
+ }
2247
+ }
2938
2248
  /**
2939
2249
  * Ensure OS-level device permission (Bluetooth / USB) before proceeding.
2940
2250
  *
@@ -3004,15 +2314,7 @@ var _LedgerAdapter = class _LedgerAdapter {
3004
2314
  if (err && typeof err === "object" && "code" in err && typeof err.code === "number") {
3005
2315
  const e = err;
3006
2316
  const params = e.code === import_hwk_adapter_core3.HardwareErrorCode.DevicePermissionDenied && e.reason ? { permissionDeniedReason: e.reason } : e.params;
3007
- return ledgerFailure(
3008
- e.code,
3009
- e.message ?? "Unknown error",
3010
- e.appName,
3011
- tag,
3012
- params,
3013
- void 0,
3014
- (0, import_hwk_adapter_core3.isHwkRecoveryHint)(e.recovery) ? e.recovery : void 0
3015
- );
2317
+ return ledgerFailure(e.code, e.message ?? "Unknown error", e.appName, tag, params);
3016
2318
  }
3017
2319
  const mapped = mapLedgerError(err);
3018
2320
  return ledgerFailure(mapped.code, mapped.message, mapped.appName, tag);
@@ -3039,7 +2341,7 @@ var _LedgerAdapter = class _LedgerAdapter {
3039
2341
  deviceId: device.deviceId,
3040
2342
  connectId: device.connectId,
3041
2343
  label: device.name,
3042
- connectionType: device.connectionType ?? this.connector.connectionType,
2344
+ connectionType: this.connector.connectionType,
3043
2345
  rssi: device.rssi,
3044
2346
  isConnectable: device.isConnectable,
3045
2347
  serialNumber: device.serialNumber,
@@ -3064,7 +2366,7 @@ _LedgerAdapter.APP_INSTALL_PROGRESS_MIN_DELTA = 0.05;
3064
2366
  var LedgerAdapter = _LedgerAdapter;
3065
2367
 
3066
2368
  // src/connector/LedgerConnectorBase.ts
3067
- var import_hwk_adapter_core12 = require("@onekeyfe/hwk-adapter-core");
2369
+ var import_hwk_adapter_core13 = require("@onekeyfe/hwk-adapter-core");
3068
2370
 
3069
2371
  // src/device/LedgerDeviceManager.ts
3070
2372
  var LedgerDeviceManager = class {
@@ -3600,7 +2902,7 @@ var SignerManager = class _SignerManager {
3600
2902
  return (args) => new import_device_signer_kit_ethereum.SignerEthBuilder(args);
3601
2903
  }
3602
2904
  static _createContextModule() {
3603
- const contextModule = new import_context_module.ContextModuleBuilder({}).setChain(import_context_module.ContextModuleChainID.Ethereum).removeDefaultLoaders().build();
2905
+ const contextModule = new import_context_module.ContextModuleBuilder({}).removeDefaultLoaders().build();
3604
2906
  return _SignerManager.wrapBlindSigningReportNonBlocking(contextModule);
3605
2907
  }
3606
2908
  static wrapBlindSigningReportNonBlocking(contextModule) {
@@ -4071,7 +3373,6 @@ function _applySignaturesToPsbt(psbtHex, signatures) {
4071
3373
 
4072
3374
  // src/connector/chains/sol.ts
4073
3375
  var import_hwk_adapter_core9 = require("@onekeyfe/hwk-adapter-core");
4074
- var import_bs58 = __toESM(require("bs58"));
4075
3376
 
4076
3377
  // src/signer/SignerSol.ts
4077
3378
  var SignerSol = class {
@@ -4155,21 +3456,8 @@ async function solSignMessage(ctx, sessionId, params) {
4155
3456
  const path = normalizePath(params.path);
4156
3457
  const messageBytes = (0, import_hwk_adapter_core9.hexToBytes)(params.message);
4157
3458
  try {
4158
- if (params.messageVersion === 1) {
4159
- const preparedMessage = (0, import_hwk_adapter_core9.prepareSolanaOffchainMessageV1)({
4160
- message: messageBytes,
4161
- requiredSigners: params.requiredSigners
4162
- });
4163
- const { SignMessageVersion } = await ctx.importLedgerKit(
4164
- "@ledgerhq/device-signer-kit-solana"
4165
- );
4166
- const result2 = await solSigner.signMessage(path, preparedMessage.serializedMessage, {
4167
- version: SignMessageVersion.Raw
4168
- });
4169
- return { signature: decodeBase58Signature(result2.signature) };
4170
- }
4171
3459
  const result = await solSigner.signMessage(path, messageBytes);
4172
- return { signature: decodeBase58EnvelopeSignature(result.signature) };
3460
+ return { signature: result.signature };
4173
3461
  } catch (err) {
4174
3462
  ctx.invalidateSession(sessionId);
4175
3463
  throw ctx.wrapError(err);
@@ -4177,27 +3465,11 @@ async function solSignMessage(ctx, sessionId, params) {
4177
3465
  ctx.clearCanceller(sessionId);
4178
3466
  }
4179
3467
  }
4180
- function decodeBase58Signature(signature) {
4181
- const bytes = import_bs58.default.decode(signature);
4182
- if (bytes.length !== 64) {
4183
- throw new Error(`Ledger Solana signature must be 64 bytes, received ${bytes.length}`);
4184
- }
4185
- return (0, import_hwk_adapter_core9.bytesToHex)(bytes);
4186
- }
4187
- function decodeBase58EnvelopeSignature(envelope) {
4188
- const bytes = import_bs58.default.decode(envelope);
4189
- if (bytes.length < 65 || bytes[0] !== 1) {
4190
- throw new Error("Ledger Solana signature envelope is invalid");
4191
- }
4192
- return (0, import_hwk_adapter_core9.bytesToHex)(bytes.subarray(1, 65));
4193
- }
4194
3468
  async function _createSolSigner(ctx, sessionId) {
4195
3469
  const dmk = await ctx.getOrCreateDmk();
4196
- const { ContextModuleBuilder: ContextModuleBuilder2, ContextModuleChainID: ContextModuleChainID2 } = await ctx.importLedgerKit(
4197
- "@ledgerhq/context-module"
4198
- );
3470
+ const { ContextModuleBuilder: ContextModuleBuilder2 } = await ctx.importLedgerKit("@ledgerhq/context-module");
4199
3471
  const { SignerSolanaBuilder } = await ctx.importLedgerKit("@ledgerhq/device-signer-kit-solana");
4200
- const contextModule = new ContextModuleBuilder2({}).setChain(ContextModuleChainID2.Solana).removeDefaultLoaders().build();
3472
+ const contextModule = new ContextModuleBuilder2({}).removeDefaultLoaders().build();
4201
3473
  const sdkSigner = new SignerSolanaBuilder({ dmk, sessionId }).withContextModule(contextModule).build();
4202
3474
  const signer = new SignerSol(sdkSigner);
4203
3475
  signer.onInteraction = (interaction) => {
@@ -4213,196 +3485,360 @@ async function _createSolSigner(ctx, sessionId) {
4213
3485
  return signer;
4214
3486
  }
4215
3487
 
4216
- // src/connector/chains/zcash.ts
4217
- var import_hwk_adapter_core10 = require("@onekeyfe/hwk-adapter-core");
3488
+ // src/connector/chains/tron.ts
3489
+ var import_hwk_adapter_core12 = require("@onekeyfe/hwk-adapter-core");
3490
+ var import_hw_app_trx = __toESM(require("@ledgerhq/hw-app-trx"));
4218
3491
 
4219
- // src/signer/SignerZcash.ts
4220
- var SignerZcash = class {
4221
- // eslint-disable-next-line no-useless-constructor, no-empty-function
4222
- constructor(_sdk) {
4223
- this._sdk = _sdk;
4224
- }
4225
- /** GET_VK: UFVK string (default) or raw 96-byte Orchard FVK. */
4226
- async getFullViewingKey(derivationPath, options) {
4227
- const action = this._sdk.getFullViewingKey(derivationPath, options);
4228
- return deviceActionToPromise(
4229
- action,
4230
- this.onInteraction,
4231
- void 0,
4232
- this.onRegisterCanceller
4233
- );
4234
- }
4235
- /** GET_SHIELDED_ADDRESS: single-Orchard-receiver UA for a 5-level transparent path. */
4236
- async getShieldedAddress(derivationPath, options) {
4237
- const action = this._sdk.getShieldedAddress(derivationPath, options);
4238
- return deviceActionToPromise(
4239
- action,
4240
- this.onInteraction,
4241
- void 0,
4242
- this.onRegisterCanceller
4243
- );
4244
- }
4245
- };
3492
+ // src/connector/chains/legacyChainCall.ts
3493
+ var import_hwk_adapter_core11 = require("@onekeyfe/hwk-adapter-core");
4246
3494
 
4247
- // src/connector/chains/zcash.ts
4248
- async function zcashGetFullViewingKey(ctx, sessionId, params) {
4249
- const signer = await _createZcashSigner(ctx, sessionId);
4250
- const path = normalizePath(params.path);
4251
- const mode = params.mode ?? "ufvk";
4252
- try {
4253
- const result = await signer.getFullViewingKey(path, { mode });
4254
- if (result.mode === "ufvk") {
4255
- return { path: params.path, mode, ufvk: result.fullViewingKey };
4256
- }
4257
- return { path: params.path, mode, orchardFvk: (0, import_hwk_adapter_core10.bytesToHex)(result.fullViewingKey) };
4258
- } catch (err) {
4259
- ctx.invalidateSession(sessionId);
4260
- throw ctx.wrapError(err);
4261
- } finally {
4262
- ctx.clearCanceller(sessionId);
3495
+ // src/app/AppManager.ts
3496
+ var import_device_management_kit2 = require("@ledgerhq/device-management-kit");
3497
+ var import_hwk_adapter_core10 = require("@onekeyfe/hwk-adapter-core");
3498
+ var APP_NAME_MAP = {
3499
+ ETH: "Ethereum",
3500
+ BTC: "Bitcoin",
3501
+ SOL: "Solana",
3502
+ TRX: "Tron",
3503
+ XRP: "XRP",
3504
+ ADA: "Cardano",
3505
+ DOT: "Polkadot",
3506
+ ATOM: "Cosmos"
3507
+ };
3508
+ var DASHBOARD_APP_NAME = "BOLOS";
3509
+ var AppManager = class {
3510
+ constructor(dmk, options) {
3511
+ this._dmk = dmk;
3512
+ this._waitMs = options?.waitMs ?? 1e3;
3513
+ this._maxRetries = options?.maxRetries ?? 10;
4263
3514
  }
4264
- }
4265
- async function zcashGetShieldedAddress(ctx, sessionId, params) {
4266
- const signer = await _createZcashSigner(ctx, sessionId);
4267
- const path = normalizePath(params.path);
4268
- try {
4269
- const result = await signer.getShieldedAddress(path, {
4270
- checkOnDevice: params.showOnDevice ?? false
3515
+ /**
3516
+ * Return the Ledger app name for a given chain ticker,
3517
+ * or undefined if the chain is not supported.
3518
+ */
3519
+ static getAppName(chain) {
3520
+ return APP_NAME_MAP[chain];
3521
+ }
3522
+ /**
3523
+ * Ensure the target app is open on the device identified by `sessionId`.
3524
+ *
3525
+ * Flow:
3526
+ * 1. Check the currently running app.
3527
+ * 2. If it is already the target, return immediately.
3528
+ * 3. If a different app is running (not dashboard), close it first.
3529
+ * 4. Open the target app.
3530
+ * 5. Poll until the device confirms the target app is running.
3531
+ */
3532
+ /**
3533
+ * @param onConfirmOnDevice Called BEFORE OpenAppCommand is issued — the
3534
+ * device is about to display "Open <app>" on screen and wait for the
3535
+ * user's button press. UI consumers should show their "open app" prompt
3536
+ * in response. NOT called when the target app is already open (no user
3537
+ * interaction needed in that case).
3538
+ *
3539
+ * Important: OpenAppCommand is blocking. It does not resolve until the user
3540
+ * has physically confirmed on the device, so anything that runs AFTER
3541
+ * `await this._openApp(...)` lands AFTER the prompt is already gone.
3542
+ * Hence the callback must fire BEFORE that await.
3543
+ */
3544
+ async ensureAppOpen(sessionId, targetAppName, onConfirmOnDevice) {
3545
+ const currentApp = await this._getCurrentApp(sessionId);
3546
+ if (currentApp === targetAppName) {
3547
+ return;
3548
+ }
3549
+ if (!this._isDashboard(currentApp)) {
3550
+ await this._closeCurrentApp(sessionId);
3551
+ await this._waitForApp(sessionId, DASHBOARD_APP_NAME);
3552
+ }
3553
+ onConfirmOnDevice?.();
3554
+ await this._openApp(sessionId, targetAppName);
3555
+ await this._waitForApp(sessionId, targetAppName);
3556
+ }
3557
+ // ---------------------------------------------------------------------------
3558
+ // Private helpers
3559
+ // ---------------------------------------------------------------------------
3560
+ async _getCurrentApp(sessionId) {
3561
+ const result = await this._dmk.sendCommand({
3562
+ sessionId,
3563
+ command: new import_device_management_kit2.GetAppAndVersionCommand()
4271
3564
  });
4272
- return { address: result.address, path: params.path };
4273
- } catch (err) {
4274
- ctx.invalidateSession(sessionId);
4275
- throw ctx.wrapError(err);
4276
- } finally {
4277
- ctx.clearCanceller(sessionId);
3565
+ if ((0, import_device_management_kit2.isSuccessCommandResult)(result)) {
3566
+ debugLog("[AppManager] currentApp:", result.data.name);
3567
+ return result.data.name;
3568
+ }
3569
+ const errResult = result;
3570
+ const dmkErr = errResult.error ?? {};
3571
+ const original = dmkErr.originalError;
3572
+ debugLog(
3573
+ "[AppManager] _getCurrentApp failed sessionId=",
3574
+ sessionId,
3575
+ "tag=",
3576
+ dmkErr._tag,
3577
+ "errorCode=",
3578
+ dmkErr.errorCode,
3579
+ "message=",
3580
+ dmkErr.message,
3581
+ "originalErrorMessage=",
3582
+ original?.message ?? String(original ?? "")
3583
+ );
3584
+ throw Object.assign(
3585
+ new Error(
3586
+ dmkErr.message ?? "Failed to get current app from device"
3587
+ ),
3588
+ {
3589
+ _tag: dmkErr._tag,
3590
+ errorCode: dmkErr.errorCode,
3591
+ originalError: original
3592
+ }
3593
+ );
4278
3594
  }
3595
+ async _openApp(sessionId, appName) {
3596
+ const result = await this._dmk.sendCommand({
3597
+ sessionId,
3598
+ command: new import_device_management_kit2.OpenAppCommand({ appName })
3599
+ });
3600
+ if (!(0, import_device_management_kit2.isSuccessCommandResult)(result)) {
3601
+ const dmkErr = result.error;
3602
+ const errorCode = "errorCode" in dmkErr && dmkErr.errorCode != null ? String(dmkErr.errorCode) : "";
3603
+ const message = "message" in dmkErr && typeof dmkErr.message === "string" ? dmkErr.message : "";
3604
+ debugLog(
3605
+ "[AppManager] openApp failed:",
3606
+ appName,
3607
+ "errorCode:",
3608
+ errorCode,
3609
+ "tag:",
3610
+ dmkErr._tag
3611
+ );
3612
+ let code;
3613
+ if (errorCode === "6807" || /unknown application/i.test(message)) {
3614
+ code = import_hwk_adapter_core10.HardwareErrorCode.AppNotInstalled;
3615
+ } else if (errorCode === "5501" || dmkErr._tag === "ActionRefusedError") {
3616
+ code = import_hwk_adapter_core10.HardwareErrorCode.UserRejected;
3617
+ }
3618
+ throw Object.assign(new Error(`Failed to open "${appName}"`), {
3619
+ _tag: ERROR_TAG.OpenAppCommand,
3620
+ code,
3621
+ errorCode,
3622
+ statusCode: errorCode,
3623
+ appName,
3624
+ originalError: dmkErr
3625
+ });
3626
+ }
3627
+ }
3628
+ async _closeCurrentApp(sessionId) {
3629
+ debugLog("[AppManager] closeCurrentApp");
3630
+ await this._dmk.sendCommand({
3631
+ sessionId,
3632
+ command: new import_device_management_kit2.CloseAppCommand()
3633
+ });
3634
+ }
3635
+ /**
3636
+ * Poll the device until the expected app is reported as running,
3637
+ * or throw after `_maxRetries` attempts.
3638
+ */
3639
+ async _waitForApp(sessionId, expectedAppName) {
3640
+ let lastSeen = "";
3641
+ for (let i = 0; i < this._maxRetries; i++) {
3642
+ await this._wait();
3643
+ const current = await this._getCurrentApp(sessionId);
3644
+ lastSeen = current;
3645
+ if (current === expectedAppName) {
3646
+ return;
3647
+ }
3648
+ }
3649
+ debugLog(
3650
+ "[AppManager] waitForApp exhausted: expected=",
3651
+ expectedAppName,
3652
+ "lastSeen=",
3653
+ lastSeen
3654
+ );
3655
+ throw new Error(
3656
+ `Ledger: failed to open "${expectedAppName}" after ${this._maxRetries} retries (last seen: ${lastSeen})`
3657
+ );
3658
+ }
3659
+ _isDashboard(appName) {
3660
+ return appName === DASHBOARD_APP_NAME;
3661
+ }
3662
+ _wait() {
3663
+ return new Promise((resolve) => setTimeout(resolve, this._waitMs));
3664
+ }
3665
+ };
3666
+
3667
+ // src/connector/chains/legacyChainCall.ts
3668
+ function isLegacyWrongAppError(err, _appName) {
3669
+ return isWrongAppError(err);
4279
3670
  }
4280
- async function _createZcashSigner(ctx, sessionId) {
4281
- const dmk = await ctx.getOrCreateDmk();
4282
- const { SignerZcashBuilder } = await ctx.importLedgerKit("@ledgerhq/device-signer-kit-zcash");
4283
- const sdkSigner = new SignerZcashBuilder({ dmk, sessionId }).build();
4284
- const signer = new SignerZcash(sdkSigner);
4285
- signer.onInteraction = (interaction) => {
4286
- debugLog("[LedgerConnector] zcash.onInteraction:", interaction);
3671
+ async function withLegacyChainCall(ctx, sessionId, options, action) {
3672
+ const { appName, needsConfirmation } = options;
3673
+ let openAppPromptShown = false;
3674
+ const onAppOpenPrompt = () => {
3675
+ openAppPromptShown = true;
4287
3676
  ctx.emit("ui-event", {
4288
- type: collapseSignerInteraction(interaction),
3677
+ type: import_hwk_adapter_core11.EConnectorInteraction.ConfirmOpenApp,
4289
3678
  payload: { sessionId }
4290
3679
  });
4291
3680
  };
4292
- signer.onRegisterCanceller = (cancel) => ctx.registerCanceller(sessionId, cancel);
4293
- return signer;
3681
+ const closeOpenAppUiIfShown = () => {
3682
+ if (openAppPromptShown) {
3683
+ ctx.emit("ui-event", {
3684
+ type: import_hwk_adapter_core11.EConnectorInteraction.InteractionComplete,
3685
+ payload: { sessionId }
3686
+ });
3687
+ openAppPromptShown = false;
3688
+ }
3689
+ };
3690
+ try {
3691
+ await _ensureAppOpen(ctx, sessionId, appName, onAppOpenPrompt);
3692
+ } catch (err) {
3693
+ debugLog(
3694
+ "[LegacyChainCall] pre-flight ensureAppOpen failed:",
3695
+ appName,
3696
+ err?.message
3697
+ );
3698
+ closeOpenAppUiIfShown();
3699
+ throw ctx.wrapError(err, { defaultAppName: appName });
3700
+ }
3701
+ const runOnce = async () => {
3702
+ let confirmEmitted = false;
3703
+ if (needsConfirmation) {
3704
+ ctx.emit("ui-event", {
3705
+ type: import_hwk_adapter_core11.EConnectorInteraction.ConfirmOnDevice,
3706
+ payload: { sessionId }
3707
+ });
3708
+ confirmEmitted = true;
3709
+ }
3710
+ try {
3711
+ return await action(sessionId);
3712
+ } finally {
3713
+ if (confirmEmitted || openAppPromptShown) {
3714
+ ctx.emit("ui-event", {
3715
+ type: import_hwk_adapter_core11.EConnectorInteraction.InteractionComplete,
3716
+ payload: { sessionId }
3717
+ });
3718
+ openAppPromptShown = false;
3719
+ }
3720
+ }
3721
+ };
3722
+ try {
3723
+ return await runOnce();
3724
+ } catch (err) {
3725
+ if (!isLegacyWrongAppError(err, appName)) {
3726
+ debugLog("[LegacyChainCall] non-wrong-app failure:", appName, err?.message);
3727
+ ctx.invalidateSession(sessionId);
3728
+ throw ctx.wrapError(err, { defaultAppName: appName });
3729
+ }
3730
+ debugLog("[LegacyChainCall] wrong-app detected, retrying:", appName);
3731
+ try {
3732
+ await _ensureAppOpen(ctx, sessionId, appName, onAppOpenPrompt);
3733
+ } catch (switchErr) {
3734
+ debugLog(
3735
+ "[LegacyChainCall] retry ensureAppOpen failed:",
3736
+ appName,
3737
+ switchErr?.message
3738
+ );
3739
+ closeOpenAppUiIfShown();
3740
+ throw ctx.wrapError(switchErr, { defaultAppName: appName });
3741
+ }
3742
+ ctx.clearAllSigners();
3743
+ const result = await runOnce();
3744
+ debugLog("[LegacyChainCall] retry succeeded:", appName);
3745
+ return result;
3746
+ }
3747
+ }
3748
+ async function _ensureAppOpen(ctx, sessionId, appName, onPrompt) {
3749
+ const dmk = await ctx.getOrCreateDmk();
3750
+ const appManager = new AppManager(dmk);
3751
+ await appManager.ensureAppOpen(sessionId, appName, onPrompt);
4294
3752
  }
4295
3753
 
4296
- // src/connector/chains/tron.ts
4297
- var import_hwk_adapter_core11 = require("@onekeyfe/hwk-adapter-core");
4298
-
4299
- // src/signer/SignerTron.ts
4300
- var SignerTron = class {
4301
- // eslint-disable-next-line no-useless-constructor, no-empty-function
4302
- constructor(_sdk) {
4303
- this._sdk = _sdk;
4304
- }
4305
- /** Base58 Tron address plus the uncompressed public key at `derivationPath`. */
4306
- async getAddress(derivationPath, options) {
4307
- const action = this._sdk.getAddress(derivationPath, options);
4308
- const result = await deviceActionToPromise(
4309
- action,
4310
- this.onInteraction,
4311
- void 0,
4312
- this.onRegisterCanceller
4313
- );
4314
- return { address: result.address, publicKey: result.publicKey };
3754
+ // src/transport/DmkTransport.ts
3755
+ var import_hw_transport = __toESM(require("@ledgerhq/hw-transport"));
3756
+ var DmkTransport = class extends import_hw_transport.default {
3757
+ constructor(dmk, sessionId) {
3758
+ super();
3759
+ this._dmk = dmk;
3760
+ this._sessionId = sessionId;
4315
3761
  }
4316
- /** Sign a protobuf-encoded raw transaction. */
4317
- async signTransaction(derivationPath, transaction, options) {
4318
- const action = this._sdk.signTransaction(derivationPath, transaction, options);
4319
- return deviceActionToPromise(
4320
- action,
4321
- this.onInteraction,
4322
- void 0,
4323
- this.onRegisterCanceller
4324
- );
3762
+ async exchange(apdu) {
3763
+ const response = await this._dmk.sendApdu({
3764
+ sessionId: this._sessionId,
3765
+ apdu: new Uint8Array(apdu)
3766
+ });
3767
+ const { data, statusCode } = response;
3768
+ const result = Buffer.alloc(data.length + 2);
3769
+ if (data.length > 0) {
3770
+ result.set(data, 0);
3771
+ }
3772
+ result.set(statusCode, data.length);
3773
+ return result;
4325
3774
  }
4326
- /** Sign a personal message (TIP-191). */
4327
- async signPersonalMessage(derivationPath, message, options) {
4328
- const action = this._sdk.signPersonalMessage(derivationPath, message, options);
4329
- return deviceActionToPromise(
4330
- action,
4331
- this.onInteraction,
4332
- void 0,
4333
- this.onRegisterCanceller
4334
- );
3775
+ async close() {
4335
3776
  }
4336
3777
  };
4337
3778
 
4338
3779
  // src/connector/chains/tron.ts
4339
3780
  async function tronGetAddress(ctx, sessionId, params) {
4340
- const tronSigner = await _createTronSigner(ctx, sessionId);
4341
3781
  const path = normalizePath(params.path);
4342
- try {
4343
- const result = await tronSigner.getAddress(path, {
4344
- checkOnDevice: params.showOnDevice ?? false
4345
- });
4346
- return { address: result.address, publicKey: result.publicKey, path: params.path };
4347
- } catch (err) {
4348
- ctx.invalidateSession(sessionId);
4349
- throw ctx.wrapError(err);
4350
- } finally {
4351
- ctx.clearCanceller(sessionId);
4352
- }
3782
+ const showOnDevice = params.showOnDevice ?? false;
3783
+ return withLegacyChainCall(
3784
+ ctx,
3785
+ sessionId,
3786
+ {
3787
+ appName: "Tron",
3788
+ // Only show "confirm on device" UI when the device is actually going
3789
+ // to display the address for the user to verify.
3790
+ needsConfirmation: showOnDevice
3791
+ },
3792
+ async (sid) => {
3793
+ const trx = await _createTrx(ctx, sid);
3794
+ const result = await trx.getAddress(path, showOnDevice);
3795
+ return { address: result.address, publicKey: result.publicKey, path: params.path };
3796
+ }
3797
+ );
4353
3798
  }
4354
3799
  async function tronSignTransaction(ctx, sessionId, params) {
4355
3800
  if (!params.rawTxHex) {
4356
3801
  throw Object.assign(
4357
3802
  new Error("TRON signing requires a protobuf-encoded raw transaction hex (rawTxHex)."),
4358
- { code: import_hwk_adapter_core11.HardwareErrorCode.InvalidParams }
3803
+ { code: import_hwk_adapter_core12.HardwareErrorCode.InvalidParams }
4359
3804
  );
4360
3805
  }
4361
- const tronSigner = await _createTronSigner(ctx, sessionId);
4362
3806
  const path = normalizePath(params.path);
4363
- try {
4364
- const signature = await tronSigner.signTransaction(path, (0, import_hwk_adapter_core11.hexToBytes)(params.rawTxHex));
4365
- return { signature: (0, import_hwk_adapter_core11.bytesToHex)(signature) };
4366
- } catch (err) {
4367
- ctx.invalidateSession(sessionId);
4368
- throw ctx.wrapError(err);
4369
- } finally {
4370
- ctx.clearCanceller(sessionId);
4371
- }
3807
+ return withLegacyChainCall(
3808
+ ctx,
3809
+ sessionId,
3810
+ { appName: "Tron", needsConfirmation: true },
3811
+ async (sid) => {
3812
+ const trx = await _createTrx(ctx, sid);
3813
+ const signature = await trx.signTransaction(
3814
+ path,
3815
+ params.rawTxHex,
3816
+ params.tokenSignatures ?? []
3817
+ );
3818
+ return { signature };
3819
+ }
3820
+ );
4372
3821
  }
4373
3822
  async function tronSignMessage(ctx, sessionId, params) {
4374
- const tronSigner = await _createTronSigner(ctx, sessionId);
4375
3823
  const path = normalizePath(params.path);
4376
- try {
4377
- const signature = await tronSigner.signPersonalMessage(path, (0, import_hwk_adapter_core11.hexToBytes)(params.messageHex));
4378
- return { signature: (0, import_hwk_adapter_core11.bytesToHex)(signature) };
4379
- } catch (err) {
4380
- ctx.invalidateSession(sessionId);
4381
- throw ctx.wrapError(err);
4382
- } finally {
4383
- ctx.clearCanceller(sessionId);
4384
- }
3824
+ return withLegacyChainCall(
3825
+ ctx,
3826
+ sessionId,
3827
+ { appName: "Tron", needsConfirmation: true },
3828
+ async (sid) => {
3829
+ const trx = await _createTrx(ctx, sid);
3830
+ const signature = await trx.signPersonalMessage(path, params.messageHex);
3831
+ return { signature };
3832
+ }
3833
+ );
4385
3834
  }
4386
- async function _createTronSigner(ctx, sessionId) {
3835
+ async function _createTrx(ctx, sessionId) {
4387
3836
  const dmk = await ctx.getOrCreateDmk();
4388
- const { SignerTrxBuilder } = await ctx.importLedgerKit("@ledgerhq/device-signer-kit-tron");
4389
- const sdkSigner = new SignerTrxBuilder({ dmk, sessionId }).build();
4390
- const signer = new SignerTron(sdkSigner);
4391
- signer.onInteraction = (interaction) => {
4392
- debugLog("[LedgerConnector] tron.onInteraction:", interaction);
4393
- ctx.emit("ui-event", {
4394
- type: collapseSignerInteraction(interaction),
4395
- payload: { sessionId }
4396
- });
4397
- };
4398
- signer.onRegisterCanceller = (cancel) => {
4399
- ctx.registerCanceller(sessionId, cancel);
4400
- };
4401
- return signer;
3837
+ return new import_hw_app_trx.default(new DmkTransport(dmk, sessionId));
4402
3838
  }
4403
3839
 
4404
3840
  // src/device-apps/customActions.ts
4405
- var import_device_management_kit2 = require("@ledgerhq/device-management-kit");
3841
+ var import_device_management_kit3 = require("@ledgerhq/device-management-kit");
4406
3842
  var import_rxjs = require("rxjs");
4407
3843
  var GetOsVersionDeviceAction = class {
4408
3844
  // eslint-disable-next-line no-useless-constructor, no-empty-function
@@ -4416,7 +3852,7 @@ var GetOsVersionDeviceAction = class {
4416
3852
  (async () => {
4417
3853
  try {
4418
3854
  subject.next({
4419
- status: import_device_management_kit2.DeviceActionStatus.Pending,
3855
+ status: import_device_management_kit3.DeviceActionStatus.Pending,
4420
3856
  intermediateValue: { requiredUserInteraction: "none" }
4421
3857
  });
4422
3858
  const result = await internalApi.sendCommand(new this._deps.GetOsVersionCommand());
@@ -4425,11 +3861,11 @@ var GetOsVersionDeviceAction = class {
4425
3861
  const errObj = result?.error;
4426
3862
  throw new Error(errObj?.message ?? "GetOsVersionCommand failed");
4427
3863
  }
4428
- subject.next({ status: import_device_management_kit2.DeviceActionStatus.Completed, output: result.data });
3864
+ subject.next({ status: import_device_management_kit3.DeviceActionStatus.Completed, output: result.data });
4429
3865
  subject.complete();
4430
3866
  } catch (err) {
4431
3867
  if (cancelled) return;
4432
- subject.next({ status: import_device_management_kit2.DeviceActionStatus.Error, error: err });
3868
+ subject.next({ status: import_device_management_kit3.DeviceActionStatus.Error, error: err });
4433
3869
  subject.complete();
4434
3870
  }
4435
3871
  })();
@@ -4437,7 +3873,7 @@ var GetOsVersionDeviceAction = class {
4437
3873
  observable: subject.asObservable(),
4438
3874
  cancel: () => {
4439
3875
  cancelled = true;
4440
- subject.next({ status: import_device_management_kit2.DeviceActionStatus.Stopped });
3876
+ subject.next({ status: import_device_management_kit3.DeviceActionStatus.Stopped });
4441
3877
  subject.complete();
4442
3878
  }
4443
3879
  };
@@ -4455,7 +3891,7 @@ var ListAvailableAppsDeviceAction = class {
4455
3891
  (async () => {
4456
3892
  try {
4457
3893
  subject.next({
4458
- status: import_device_management_kit2.DeviceActionStatus.Pending,
3894
+ status: import_device_management_kit3.DeviceActionStatus.Pending,
4459
3895
  intermediateValue: { requiredUserInteraction: "none" }
4460
3896
  });
4461
3897
  const osVersionResult = await internalApi.sendCommand(new this._GetOsVersionCommand());
@@ -4472,11 +3908,11 @@ var ListAvailableAppsDeviceAction = class {
4472
3908
  throw new Error(httpErr?.message ?? "Manager API getAppList failed");
4473
3909
  }
4474
3910
  const apps = either.extract();
4475
- subject.next({ status: import_device_management_kit2.DeviceActionStatus.Completed, output: apps });
3911
+ subject.next({ status: import_device_management_kit3.DeviceActionStatus.Completed, output: apps });
4476
3912
  subject.complete();
4477
3913
  } catch (err) {
4478
3914
  if (cancelled) return;
4479
- subject.next({ status: import_device_management_kit2.DeviceActionStatus.Error, error: err });
3915
+ subject.next({ status: import_device_management_kit3.DeviceActionStatus.Error, error: err });
4480
3916
  subject.complete();
4481
3917
  }
4482
3918
  })();
@@ -4484,7 +3920,7 @@ var ListAvailableAppsDeviceAction = class {
4484
3920
  observable: subject.asObservable(),
4485
3921
  cancel: () => {
4486
3922
  cancelled = true;
4487
- subject.next({ status: import_device_management_kit2.DeviceActionStatus.Stopped });
3923
+ subject.next({ status: import_device_management_kit3.DeviceActionStatus.Stopped });
4488
3924
  subject.complete();
4489
3925
  }
4490
3926
  };
@@ -4577,7 +4013,7 @@ var DeviceApps = class {
4577
4013
  seTargetId: v.seTargetId,
4578
4014
  mcuTargetId: v.mcuTargetId,
4579
4015
  seVersion: v.seVersion,
4580
- seFlagsHex: bytesToHex4(v.seFlags),
4016
+ seFlagsHex: bytesToHex2(v.seFlags),
4581
4017
  mcuSephVersion: v.mcuSephVersion,
4582
4018
  mcuBootloaderVersion: v.mcuBootloaderVersion,
4583
4019
  hwVersion: v.hwVersion
@@ -4651,7 +4087,7 @@ var DeviceApps = class {
4651
4087
  }
4652
4088
  }
4653
4089
  };
4654
- function bytesToHex4(bytes) {
4090
+ function bytesToHex2(bytes) {
4655
4091
  if (!bytes) return "";
4656
4092
  return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
4657
4093
  }
@@ -4694,11 +4130,10 @@ var METHOD_PREFIX_TO_APP_NAME = {
4694
4130
  evm: "Ethereum",
4695
4131
  btc: "Bitcoin",
4696
4132
  sol: "Solana",
4697
- tron: "Tron",
4698
- zcash: "Zcash"
4133
+ tron: "Tron"
4699
4134
  };
4700
4135
  var HARDWARE_ERROR_CODE_VALUES = new Set(
4701
- Object.values(import_hwk_adapter_core12.HardwareErrorCode).filter((value) => typeof value === "number")
4136
+ Object.values(import_hwk_adapter_core13.HardwareErrorCode).filter((value) => typeof value === "number")
4702
4137
  );
4703
4138
  var BLE_CONNECT_SCAN_TIMEOUT_MS = 1500;
4704
4139
  var LEDGER_RELAY_ALLOWED_ROOT_DOMAINS = ["onekeytest.com", "onekey.com"];
@@ -4735,10 +4170,6 @@ async function defaultLedgerKitImporter(pkg) {
4735
4170
  return import("@ledgerhq/device-signer-kit-bitcoin");
4736
4171
  case "@ledgerhq/device-signer-kit-solana":
4737
4172
  return import("@ledgerhq/device-signer-kit-solana");
4738
- case "@ledgerhq/device-signer-kit-tron":
4739
- return import("@ledgerhq/device-signer-kit-tron");
4740
- case "@ledgerhq/device-signer-kit-zcash":
4741
- return import("@ledgerhq/device-signer-kit-zcash");
4742
4173
  case "@ledgerhq/context-module":
4743
4174
  return import("@ledgerhq/context-module");
4744
4175
  default:
@@ -4849,7 +4280,7 @@ var LedgerConnectorBase = class {
4849
4280
  async searchDevices() {
4850
4281
  const dm = await this._getDeviceManager();
4851
4282
  const descriptors = await this._discoverDescriptors(dm);
4852
- const resolvedDescriptors = descriptors.filter((d) => !(0, import_hwk_adapter_core12.isKnownNonTargetHardwareVendor)(d, "ledger")).map((d) => ({
4283
+ const resolvedDescriptors = descriptors.filter((d) => !(0, import_hwk_adapter_core13.isKnownNonTargetHardwareVendor)(d, "ledger")).map((d) => ({
4853
4284
  descriptor: d,
4854
4285
  connectId: this._resolveConnectId(d)
4855
4286
  }));
@@ -4897,7 +4328,7 @@ var LedgerConnectorBase = class {
4897
4328
  `Ledger BLE connect did not return within ${HANG_CEILING_MS / 6e4}min \u2014 DMK hang fallback.`
4898
4329
  );
4899
4330
  err._tag = ERROR_TAG.BlePairingTimeout;
4900
- err.code = import_hwk_adapter_core12.HardwareErrorCode.BlePairingTimeout;
4331
+ err.code = import_hwk_adapter_core13.HardwareErrorCode.BlePairingTimeout;
4901
4332
  reject(err);
4902
4333
  }, HANG_CEILING_MS);
4903
4334
  });
@@ -4930,7 +4361,7 @@ var LedgerConnectorBase = class {
4930
4361
  "Ledger device is not currently advertising. Wake up and unlock the device, keep it nearby, then try again."
4931
4362
  );
4932
4363
  err._tag = ERROR_TAG.DeviceNotAdvertising;
4933
- err.code = import_hwk_adapter_core12.HardwareErrorCode.DeviceNotFound;
4364
+ err.code = import_hwk_adapter_core13.HardwareErrorCode.DeviceNotFound;
4934
4365
  throw err;
4935
4366
  };
4936
4367
  const doConnect = async (path) => {
@@ -4994,7 +4425,7 @@ var LedgerConnectorBase = class {
4994
4425
  "Ledger Bluetooth pairing failed. Make sure the device is unlocked and nearby, then try again."
4995
4426
  );
4996
4427
  wrapped._tag = ERROR_TAG.BleGattBondingFailed;
4997
- wrapped.code = import_hwk_adapter_core12.HardwareErrorCode.BlePairingTimeout;
4428
+ wrapped.code = import_hwk_adapter_core13.HardwareErrorCode.BlePairingTimeout;
4998
4429
  wrapped.originalError = err;
4999
4430
  throw wrapped;
5000
4431
  }
@@ -5072,7 +4503,7 @@ var LedgerConnectorBase = class {
5072
4503
  this._unwatchSessionState(sessionId);
5073
4504
  this._signerManager?.invalidate(sessionId);
5074
4505
  this._cancellers.get(sessionId)?.({
5075
- code: import_hwk_adapter_core12.HardwareErrorCode.DeviceDisconnected,
4506
+ code: import_hwk_adapter_core13.HardwareErrorCode.DeviceDisconnected,
5076
4507
  tag: "DeviceDisconnected",
5077
4508
  message: "Device disconnected"
5078
4509
  });
@@ -5096,9 +4527,9 @@ var LedgerConnectorBase = class {
5096
4527
  if (isAppStuckByApdu(err)) {
5097
4528
  return {
5098
4529
  success: false,
5099
- error: (0, import_hwk_adapter_core12.serializeConnectorError)(
4530
+ error: (0, import_hwk_adapter_core13.serializeConnectorError)(
5100
4531
  Object.assign(new Error("Ledger app is unresponsive"), {
5101
- code: import_hwk_adapter_core12.HardwareErrorCode.DeviceAppStuck,
4532
+ code: import_hwk_adapter_core13.HardwareErrorCode.DeviceAppStuck,
5102
4533
  _tag: ERROR_TAG.DeviceAppStuck,
5103
4534
  originalError: err
5104
4535
  })
@@ -5108,16 +4539,16 @@ var LedgerConnectorBase = class {
5108
4539
  if (isTransportStuck(err)) {
5109
4540
  return {
5110
4541
  success: false,
5111
- error: (0, import_hwk_adapter_core12.serializeConnectorError)(
4542
+ error: (0, import_hwk_adapter_core13.serializeConnectorError)(
5112
4543
  Object.assign(new Error("Device communication interrupted, please retry"), {
5113
- code: import_hwk_adapter_core12.HardwareErrorCode.TransportError,
4544
+ code: import_hwk_adapter_core13.HardwareErrorCode.TransportError,
5114
4545
  _tag: ERROR_TAG.DeviceTransportStuck,
5115
4546
  originalError: err
5116
4547
  })
5117
4548
  )
5118
4549
  };
5119
4550
  }
5120
- return { success: false, error: (0, import_hwk_adapter_core12.serializeConnectorError)(err) };
4551
+ return { success: false, error: (0, import_hwk_adapter_core13.serializeConnectorError)(err) };
5121
4552
  }
5122
4553
  }
5123
4554
  async _dispatch(sessionId, method, params) {
@@ -5156,11 +4587,6 @@ var LedgerConnectorBase = class {
5156
4587
  return solSignTransaction(ctx, sessionId, params);
5157
4588
  case "solSignMessage":
5158
4589
  return solSignMessage(ctx, sessionId, params);
5159
- // ZCASH
5160
- case "zcashGetFullViewingKey":
5161
- return zcashGetFullViewingKey(ctx, sessionId, params);
5162
- case "zcashGetShieldedAddress":
5163
- return zcashGetShieldedAddress(ctx, sessionId, params);
5164
4590
  // TRON
5165
4591
  case "tronGetAddress":
5166
4592
  return tronGetAddress(ctx, sessionId, params);
@@ -5185,7 +4611,7 @@ var LedgerConnectorBase = class {
5185
4611
  try {
5186
4612
  return await apps.install(p.appName, ({ progress }) => {
5187
4613
  ctx.emit("ui-event", {
5188
- type: import_hwk_adapter_core12.EConnectorInteraction.AppInstallProgress,
4614
+ type: import_hwk_adapter_core13.EConnectorInteraction.AppInstallProgress,
5189
4615
  payload: {
5190
4616
  sessionId,
5191
4617
  appName: p.appName,
@@ -5490,7 +4916,7 @@ var LedgerConnectorBase = class {
5490
4916
  * at every catch site. Falls through unchanged for unknown methods.
5491
4917
  */
5492
4918
  _ctxForMethod(method) {
5493
- const prefix = /^(evm|btc|sol|tron|zcash)/.exec(method)?.[1];
4919
+ const prefix = /^(evm|btc|sol|tron)/.exec(method)?.[1];
5494
4920
  const defaultAppName = prefix ? METHOD_PREFIX_TO_APP_NAME[prefix] : void 0;
5495
4921
  if (!defaultAppName) return this._ctx;
5496
4922
  return {
@@ -5524,204 +4950,6 @@ var LedgerConnectorBase = class {
5524
4950
  return error;
5525
4951
  }
5526
4952
  };
5527
-
5528
- // src/transport/DmkTransport.ts
5529
- var import_hw_transport = __toESM(require("@ledgerhq/hw-transport"));
5530
- var DmkTransport = class extends import_hw_transport.default {
5531
- constructor(dmk, sessionId) {
5532
- super();
5533
- this._dmk = dmk;
5534
- this._sessionId = sessionId;
5535
- }
5536
- async exchange(apdu) {
5537
- const response = await this._dmk.sendApdu({
5538
- sessionId: this._sessionId,
5539
- apdu: new Uint8Array(apdu)
5540
- });
5541
- const { data, statusCode } = response;
5542
- const result = Buffer.alloc(data.length + 2);
5543
- if (data.length > 0) {
5544
- result.set(data, 0);
5545
- }
5546
- result.set(statusCode, data.length);
5547
- return result;
5548
- }
5549
- async close() {
5550
- }
5551
- };
5552
-
5553
- // src/app/AppManager.ts
5554
- var import_device_management_kit3 = require("@ledgerhq/device-management-kit");
5555
- var import_hwk_adapter_core13 = require("@onekeyfe/hwk-adapter-core");
5556
- var APP_NAME_MAP = {
5557
- ETH: "Ethereum",
5558
- BTC: "Bitcoin",
5559
- SOL: "Solana",
5560
- TRX: "Tron",
5561
- ZEC: "Zcash",
5562
- XRP: "XRP",
5563
- ADA: "Cardano",
5564
- DOT: "Polkadot",
5565
- ATOM: "Cosmos"
5566
- };
5567
- var DASHBOARD_APP_NAME = "BOLOS";
5568
- var AppManager = class {
5569
- constructor(dmk, options) {
5570
- this._dmk = dmk;
5571
- this._waitMs = options?.waitMs ?? 1e3;
5572
- this._maxRetries = options?.maxRetries ?? 10;
5573
- }
5574
- /**
5575
- * Return the Ledger app name for a given chain ticker,
5576
- * or undefined if the chain is not supported.
5577
- */
5578
- static getAppName(chain) {
5579
- return APP_NAME_MAP[chain];
5580
- }
5581
- /**
5582
- * Ensure the target app is open on the device identified by `sessionId`.
5583
- *
5584
- * Flow:
5585
- * 1. Check the currently running app.
5586
- * 2. If it is already the target, return immediately.
5587
- * 3. If a different app is running (not dashboard), close it first.
5588
- * 4. Open the target app.
5589
- * 5. Poll until the device confirms the target app is running.
5590
- */
5591
- /**
5592
- * @param onConfirmOnDevice Called BEFORE OpenAppCommand is issued — the
5593
- * device is about to display "Open <app>" on screen and wait for the
5594
- * user's button press. UI consumers should show their "open app" prompt
5595
- * in response. NOT called when the target app is already open (no user
5596
- * interaction needed in that case).
5597
- *
5598
- * Important: OpenAppCommand is blocking. It does not resolve until the user
5599
- * has physically confirmed on the device, so anything that runs AFTER
5600
- * `await this._openApp(...)` lands AFTER the prompt is already gone.
5601
- * Hence the callback must fire BEFORE that await.
5602
- */
5603
- async ensureAppOpen(sessionId, targetAppName, onConfirmOnDevice) {
5604
- const currentApp = await this._getCurrentApp(sessionId);
5605
- if (currentApp === targetAppName) {
5606
- return;
5607
- }
5608
- if (!this._isDashboard(currentApp)) {
5609
- await this._closeCurrentApp(sessionId);
5610
- await this._waitForApp(sessionId, DASHBOARD_APP_NAME);
5611
- }
5612
- onConfirmOnDevice?.();
5613
- await this._openApp(sessionId, targetAppName);
5614
- await this._waitForApp(sessionId, targetAppName);
5615
- }
5616
- // ---------------------------------------------------------------------------
5617
- // Private helpers
5618
- // ---------------------------------------------------------------------------
5619
- async _getCurrentApp(sessionId) {
5620
- const result = await this._dmk.sendCommand({
5621
- sessionId,
5622
- command: new import_device_management_kit3.GetAppAndVersionCommand()
5623
- });
5624
- if ((0, import_device_management_kit3.isSuccessCommandResult)(result)) {
5625
- debugLog("[AppManager] currentApp:", result.data.name);
5626
- return result.data.name;
5627
- }
5628
- const errResult = result;
5629
- const dmkErr = errResult.error ?? {};
5630
- const original = dmkErr.originalError;
5631
- debugLog(
5632
- "[AppManager] _getCurrentApp failed sessionId=",
5633
- sessionId,
5634
- "tag=",
5635
- dmkErr._tag,
5636
- "errorCode=",
5637
- dmkErr.errorCode,
5638
- "message=",
5639
- dmkErr.message,
5640
- "originalErrorMessage=",
5641
- original?.message ?? String(original ?? "")
5642
- );
5643
- throw Object.assign(
5644
- new Error(
5645
- dmkErr.message ?? "Failed to get current app from device"
5646
- ),
5647
- {
5648
- _tag: dmkErr._tag,
5649
- errorCode: dmkErr.errorCode,
5650
- originalError: original
5651
- }
5652
- );
5653
- }
5654
- async _openApp(sessionId, appName) {
5655
- const result = await this._dmk.sendCommand({
5656
- sessionId,
5657
- command: new import_device_management_kit3.OpenAppCommand({ appName })
5658
- });
5659
- if (!(0, import_device_management_kit3.isSuccessCommandResult)(result)) {
5660
- const dmkErr = result.error;
5661
- const errorCode = "errorCode" in dmkErr && dmkErr.errorCode != null ? String(dmkErr.errorCode) : "";
5662
- const message = "message" in dmkErr && typeof dmkErr.message === "string" ? dmkErr.message : "";
5663
- debugLog(
5664
- "[AppManager] openApp failed:",
5665
- appName,
5666
- "errorCode:",
5667
- errorCode,
5668
- "tag:",
5669
- dmkErr._tag
5670
- );
5671
- let code;
5672
- if (errorCode === "6807" || /unknown application/i.test(message)) {
5673
- code = import_hwk_adapter_core13.HardwareErrorCode.AppNotInstalled;
5674
- } else if (errorCode === "5501" || dmkErr._tag === "ActionRefusedError") {
5675
- code = import_hwk_adapter_core13.HardwareErrorCode.UserRejected;
5676
- }
5677
- throw Object.assign(new Error(`Failed to open "${appName}"`), {
5678
- _tag: ERROR_TAG.OpenAppCommand,
5679
- code,
5680
- errorCode,
5681
- statusCode: errorCode,
5682
- appName,
5683
- originalError: dmkErr
5684
- });
5685
- }
5686
- }
5687
- async _closeCurrentApp(sessionId) {
5688
- debugLog("[AppManager] closeCurrentApp");
5689
- await this._dmk.sendCommand({
5690
- sessionId,
5691
- command: new import_device_management_kit3.CloseAppCommand()
5692
- });
5693
- }
5694
- /**
5695
- * Poll the device until the expected app is reported as running,
5696
- * or throw after `_maxRetries` attempts.
5697
- */
5698
- async _waitForApp(sessionId, expectedAppName) {
5699
- let lastSeen = "";
5700
- for (let i = 0; i < this._maxRetries; i++) {
5701
- await this._wait();
5702
- const current = await this._getCurrentApp(sessionId);
5703
- lastSeen = current;
5704
- if (current === expectedAppName) {
5705
- return;
5706
- }
5707
- }
5708
- debugLog(
5709
- "[AppManager] waitForApp exhausted: expected=",
5710
- expectedAppName,
5711
- "lastSeen=",
5712
- lastSeen
5713
- );
5714
- throw new Error(
5715
- `Ledger: failed to open "${expectedAppName}" after ${this._maxRetries} retries (last seen: ${lastSeen})`
5716
- );
5717
- }
5718
- _isDashboard(appName) {
5719
- return appName === DASHBOARD_APP_NAME;
5720
- }
5721
- _wait() {
5722
- return new Promise((resolve) => setTimeout(resolve, this._waitMs));
5723
- }
5724
- };
5725
4953
  // Annotate the CommonJS export names for ESM import in node:
5726
4954
  0 && (module.exports = {
5727
4955
  AppManager,
@@ -5733,7 +4961,6 @@ var AppManager = class {
5733
4961
  SignerEth,
5734
4962
  SignerManager,
5735
4963
  SignerSol,
5736
- SignerZcash,
5737
4964
  debugLog,
5738
4965
  deviceActionToPromise,
5739
4966
  isDeviceLockedError,