@onekeyfe/hwk-ledger-adapter 1.2.3-alpha.1 → 1.2.3-alpha.11
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.d.mts +28 -62
- package/dist/index.d.ts +28 -62
- package/dist/index.js +465 -1113
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +446 -1112
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -12
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
|
-
|
|
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
|
-
retainInteraction,
|
|
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.interactionId, "ledger");
|
|
563
|
-
if (!target.success) return target;
|
|
564
|
-
const effectiveTargetId = target.payload.targetId ?? "";
|
|
565
|
-
let releaseInteractionRetention;
|
|
566
|
-
try {
|
|
567
|
-
releaseInteractionRetention = target.payload.interactionId ? retainInteraction(target.payload.interactionId) : 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
|
-
interactionId: target.payload.interactionId,
|
|
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
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
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
|
-
|
|
604
|
-
payload,
|
|
605
|
-
chainFingerprints,
|
|
573
|
+
commonParams,
|
|
606
574
|
installContext
|
|
607
|
-
)
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
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.
|
|
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
|
|
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
|
|
692
|
-
const response = await getChainFingerprint(connectId, chain
|
|
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._interactions = new import_hwk_adapter_core3.InteractionRegistry({
|
|
798
|
-
vendor: "ledger",
|
|
799
|
-
onEnded: (interaction, reason) => {
|
|
800
|
-
const binding = this._pendingInteractionBindings.get(interaction.interactionId);
|
|
801
|
-
if (binding?.selectedConnection?.requestId === this._bindingSelectionRequestId) {
|
|
802
|
-
this._finishBleBinding("cancelled");
|
|
803
|
-
}
|
|
804
|
-
this._pendingInteractionBindings.delete(interaction.interactionId);
|
|
805
|
-
this.emitter.emit(import_hwk_adapter_core3.SDK.INTERACTION_ENDED, {
|
|
806
|
-
type: import_hwk_adapter_core3.SDK.INTERACTION_ENDED,
|
|
807
|
-
payload: { interactionId: interaction.interactionId, reason }
|
|
808
|
-
});
|
|
809
|
-
if (reason === "timeout") {
|
|
810
|
-
void this._releaseInteractionConnection(interaction);
|
|
811
|
-
}
|
|
812
|
-
}
|
|
813
|
-
});
|
|
814
766
|
this._discoveredDevices = /* @__PURE__ */ new Map();
|
|
815
767
|
this._sessions = /* @__PURE__ */ new Map();
|
|
816
|
-
this._pendingInteractionBindings = /* @__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._activeInteractionJobs = /* @__PURE__ */ new Set();
|
|
838
|
-
this._pendingInteractionDisconnects = /* @__PURE__ */ new Set();
|
|
839
781
|
this._installProgressLastEmittedValue = -Infinity;
|
|
840
782
|
this.allNetworkGetAddress = createAllNetworkGetAddress({
|
|
841
783
|
callChain: this.callChain.bind(this),
|
|
842
|
-
getChainFingerprint:
|
|
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
|
-
retainInteraction: (interactionId) => this._interactions.retain(interactionId),
|
|
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 →
|
|
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 activeInteraction = this._interactions.findActiveByConnectionKey(data.connectId);
|
|
882
|
-
if (activeInteraction && this._activeInteractionJobs.has(activeInteraction.interactionId)) {
|
|
883
|
-
this._pendingInteractionDisconnects.add(activeInteraction.interactionId);
|
|
884
|
-
} else {
|
|
885
|
-
this._interactions.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.
|
|
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._interactions.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
|
-
|
|
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
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
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(
|
|
930
|
+
await this._ensureDevicePermission();
|
|
1057
931
|
}
|
|
1058
932
|
const result = Array.from(this._discoveredDevices.values());
|
|
1059
933
|
debugLog("[LedgerAdapter][RES]", {
|
|
@@ -1072,172 +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(
|
|
1098
|
-
this._interactions.endAll("explicit", preserveInteractionId);
|
|
950
|
+
async _evictAllSessions() {
|
|
1099
951
|
if (this._sessions.size === 0) return;
|
|
1100
952
|
const stale = [...this._sessions.values()];
|
|
1101
953
|
this._sessions.clear();
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
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(
|
|
1117
|
-
const connected = await this._connectTarget(searchTargetId);
|
|
1118
|
-
if (!connected.success) return connected;
|
|
1119
|
-
return this._createInteraction(searchTargetId, connected.payload);
|
|
1120
|
-
}
|
|
1121
|
-
async acquireInteraction(connectId, context) {
|
|
1122
|
-
try {
|
|
1123
|
-
return await this._jobQueue.enqueue(
|
|
1124
|
-
connectId || "__ledger_acquire__",
|
|
1125
|
-
async (signal) => {
|
|
1126
|
-
const transport = this._isBleConnection() ? "ble" : "usb";
|
|
1127
|
-
const hint = context.knownConnections?.find(
|
|
1128
|
-
(connection) => connection.transport === transport
|
|
1129
|
-
);
|
|
1130
|
-
const target = hint && hint.transport !== "qr" ? hint.connectId : connectId;
|
|
1131
|
-
await this._ensureDevicePermission(target, void 0, signal);
|
|
1132
|
-
const attempt = {
|
|
1133
|
-
...context,
|
|
1134
|
-
extra: context.extra ? { ...context.extra } : void 0,
|
|
1135
|
-
previousConnectId: target
|
|
1136
|
-
};
|
|
1137
|
-
try {
|
|
1138
|
-
const resolvedConnectId = await this.ensureConnected(
|
|
1139
|
-
target,
|
|
1140
|
-
signal,
|
|
1141
|
-
true,
|
|
1142
|
-
void 0,
|
|
1143
|
-
attempt
|
|
1144
|
-
);
|
|
1145
|
-
_LedgerAdapter._throwIfAborted(signal);
|
|
1146
|
-
const result = this._createInteraction(connectId, resolvedConnectId);
|
|
1147
|
-
if (result.success && attempt.selectedConnection) {
|
|
1148
|
-
this._pendingInteractionBindings.set(result.payload, attempt);
|
|
1149
|
-
}
|
|
1150
|
-
return result;
|
|
1151
|
-
} catch (error) {
|
|
1152
|
-
this._finishBleBinding(signal.aborted ? "cancelled" : "failed");
|
|
1153
|
-
throw error;
|
|
1154
|
-
}
|
|
1155
|
-
},
|
|
1156
|
-
{
|
|
1157
|
-
label: "acquireInteraction",
|
|
1158
|
-
rejectIfBusy: true,
|
|
1159
|
-
busyError: _LedgerAdapter._createDeviceBusyError("acquireInteraction")
|
|
1160
|
-
}
|
|
1161
|
-
);
|
|
1162
|
-
} catch (error) {
|
|
1163
|
-
return this.errorToFailure(error);
|
|
1164
|
-
}
|
|
1165
|
-
}
|
|
1166
|
-
_createInteraction(searchTargetId, resolvedConnectId) {
|
|
1167
|
-
this._interactions.endByConnectionKey(resolvedConnectId, "explicit");
|
|
1168
|
-
const sessionId = this._sessions.get(resolvedConnectId);
|
|
1169
|
-
if (sessionId) this._interactions.endByConnectionKey(sessionId, "explicit");
|
|
1170
|
-
const device = this._discoveredDevices.get(resolvedConnectId) ?? {
|
|
1171
|
-
vendor: "ledger",
|
|
1172
|
-
model: "unknown",
|
|
1173
|
-
firmwareVersion: "",
|
|
1174
|
-
deviceId: "",
|
|
1175
|
-
connectId: resolvedConnectId,
|
|
1176
|
-
connectionType: this.connector.connectionType
|
|
1177
|
-
};
|
|
1178
|
-
const interaction = this._interactions.create({
|
|
1179
|
-
searchTargetId,
|
|
1180
|
-
connectId: resolvedConnectId,
|
|
1181
|
-
device,
|
|
1182
|
-
connectionKeys: [this._sessions.get(resolvedConnectId) ?? ""]
|
|
1183
|
-
});
|
|
1184
|
-
return (0, import_hwk_adapter_core3.success)(interaction.interactionId);
|
|
1185
|
-
}
|
|
1186
|
-
async _connectTarget(connectId, preserveInteractionId, signal) {
|
|
966
|
+
async connectDevice(connectId) {
|
|
1187
967
|
debugLog("[LedgerAdapter][REQ]", { method: "connectDevice", connectId, params: { connectId } });
|
|
1188
968
|
try {
|
|
1189
|
-
this.
|
|
1190
|
-
const discoveredType = this._discoveredDevices.get(connectId)?.connectionType;
|
|
1191
|
-
if (discoveredType === "usb" || discoveredType === "ble") {
|
|
1192
|
-
this._activeConnectionType = discoveredType;
|
|
1193
|
-
}
|
|
1194
|
-
if (this._isBleConnection() && !connectId) {
|
|
969
|
+
if (isLedgerBleConnectionType(this.connector.connectionType) && !connectId) {
|
|
1195
970
|
throw Object.assign(new Error("Ledger BLE connectId is required."), {
|
|
1196
971
|
code: import_hwk_adapter_core3.HardwareErrorCode.DeviceNotFound
|
|
1197
972
|
});
|
|
1198
973
|
}
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
if (this.connector.availableTransports && this.connector.availableTransports.length > 1) {
|
|
1202
|
-
await this._evictAllSessions(preserveInteractionId);
|
|
1203
|
-
} else if (this._isBleConnection()) {
|
|
1204
|
-
const previousSessionId = this._sessions.get(connectId);
|
|
1205
|
-
this._interactions.endByConnectionKey(connectId, "explicit", preserveInteractionId);
|
|
1206
|
-
if (previousSessionId) {
|
|
1207
|
-
this._interactions.endByConnectionKey(
|
|
1208
|
-
previousSessionId,
|
|
1209
|
-
"explicit",
|
|
1210
|
-
preserveInteractionId
|
|
1211
|
-
);
|
|
1212
|
-
this._sessions.delete(connectId);
|
|
1213
|
-
await this.connector.disconnect(previousSessionId).catch(() => void 0);
|
|
1214
|
-
}
|
|
1215
|
-
} else {
|
|
1216
|
-
await this._evictAllSessions(preserveInteractionId);
|
|
974
|
+
if (!isLedgerBleConnectionType(this.connector.connectionType)) {
|
|
975
|
+
await this._evictAllSessions();
|
|
1217
976
|
}
|
|
1218
|
-
|
|
1219
|
-
const
|
|
1220
|
-
|
|
1221
|
-
let session;
|
|
1222
|
-
try {
|
|
1223
|
-
session = this.connector.availableTransports?.length ? await this.connector.connect(connectId, {
|
|
1224
|
-
transportType: this._activeConnectionType ?? "usb"
|
|
1225
|
-
}) : await this.connector.connect(connectId);
|
|
1226
|
-
if (signal?.aborted || stateGeneration !== this._stateGeneration) {
|
|
1227
|
-
await this.connector.disconnect(session.sessionId).catch(() => void 0);
|
|
1228
|
-
throw Object.assign(new Error("Ledger connection aborted"), {
|
|
1229
|
-
code: import_hwk_adapter_core3.HardwareErrorCode.UserAborted
|
|
1230
|
-
});
|
|
1231
|
-
}
|
|
1232
|
-
} finally {
|
|
1233
|
-
releaseOperation();
|
|
1234
|
-
}
|
|
1235
|
-
const resolvedConnectId = session.deviceInfo?.connectId || connectId;
|
|
1236
|
-
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);
|
|
1237
980
|
if (session.deviceInfo) {
|
|
1238
|
-
this._discoveredDevices.set(
|
|
981
|
+
this._discoveredDevices.set(connectId, session.deviceInfo);
|
|
1239
982
|
}
|
|
1240
|
-
const result = (0, import_hwk_adapter_core3.success)(
|
|
983
|
+
const result = (0, import_hwk_adapter_core3.success)(connectId);
|
|
1241
984
|
debugLog("[LedgerAdapter][RES]", { method: "connectDevice", success: true, payload: result });
|
|
1242
985
|
return result;
|
|
1243
986
|
} catch (err) {
|
|
@@ -1250,60 +993,30 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1250
993
|
return failureResult;
|
|
1251
994
|
}
|
|
1252
995
|
}
|
|
1253
|
-
async
|
|
1254
|
-
const interaction = this._interactions.find(interactionId);
|
|
1255
|
-
if (!interaction) {
|
|
1256
|
-
this._interactions.resolve(interactionId);
|
|
1257
|
-
return;
|
|
1258
|
-
}
|
|
1259
|
-
const endedInteraction = this._interactions.end(interactionId, "explicit");
|
|
1260
|
-
if (!endedInteraction) return;
|
|
1261
|
-
const { connectId } = interaction;
|
|
996
|
+
async disconnectDevice(connectId) {
|
|
1262
997
|
debugLog("[LedgerAdapter][REQ]", {
|
|
1263
|
-
method: "
|
|
998
|
+
method: "disconnectDevice",
|
|
1264
999
|
connectId,
|
|
1265
1000
|
params: { connectId }
|
|
1266
1001
|
});
|
|
1267
1002
|
try {
|
|
1268
|
-
|
|
1269
|
-
|
|
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 });
|
|
1270
1009
|
} catch (err) {
|
|
1271
1010
|
const e = err;
|
|
1272
1011
|
debugLog("[LedgerAdapter][RES]", {
|
|
1273
|
-
method: "
|
|
1012
|
+
method: "disconnectDevice",
|
|
1274
1013
|
success: false,
|
|
1275
1014
|
error: { message: e?.message, _tag: e?._tag, code: e?.code ?? e?.errorCode }
|
|
1276
1015
|
});
|
|
1277
1016
|
throw err;
|
|
1278
1017
|
}
|
|
1279
1018
|
}
|
|
1280
|
-
async
|
|
1281
|
-
const sessionIds = /* @__PURE__ */ new Set();
|
|
1282
|
-
for (const [connectId, sessionId] of this._sessions) {
|
|
1283
|
-
if (connectId === interaction.connectId || interaction.connectionKeys.includes(connectId) || interaction.connectionKeys.includes(sessionId)) {
|
|
1284
|
-
this._sessions.delete(connectId);
|
|
1285
|
-
sessionIds.add(sessionId);
|
|
1286
|
-
}
|
|
1287
|
-
}
|
|
1288
|
-
for (const sessionId of sessionIds) {
|
|
1289
|
-
await this._runConnectorTeardown(
|
|
1290
|
-
() => this.connector.disconnect(sessionId).catch(() => void 0)
|
|
1291
|
-
);
|
|
1292
|
-
}
|
|
1293
|
-
}
|
|
1294
|
-
async _releaseLostInteractionConnection(interactionId) {
|
|
1295
|
-
const endedInteraction = this._interactions.end(interactionId, "disconnect");
|
|
1296
|
-
if (!endedInteraction) return;
|
|
1297
|
-
this._discoveredDevices.delete(endedInteraction.connectId);
|
|
1298
|
-
await this._releaseInteractionConnection(endedInteraction);
|
|
1299
|
-
}
|
|
1300
|
-
async getDeviceInfo(connectIdOrInteractionId, deviceId) {
|
|
1301
|
-
let connectId;
|
|
1302
|
-
try {
|
|
1303
|
-
connectId = (0, import_hwk_adapter_core3.isHardwareInteractionId)(connectIdOrInteractionId) ? this._interactions.resolve(connectIdOrInteractionId).connectId : connectIdOrInteractionId;
|
|
1304
|
-
} catch (error) {
|
|
1305
|
-
return this.errorToFailure(error);
|
|
1306
|
-
}
|
|
1019
|
+
async getDeviceInfo(connectId, deviceId) {
|
|
1307
1020
|
debugLog("[LedgerAdapter][REQ]", {
|
|
1308
1021
|
method: "getDeviceInfo",
|
|
1309
1022
|
connectId,
|
|
@@ -1342,7 +1055,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1342
1055
|
}
|
|
1343
1056
|
}
|
|
1344
1057
|
getSupportedChains() {
|
|
1345
|
-
return ["evm", "btc", "sol", "tron"
|
|
1058
|
+
return ["evm", "btc", "sol", "tron"];
|
|
1346
1059
|
}
|
|
1347
1060
|
// ---------------------------------------------------------------------------
|
|
1348
1061
|
// Chain call helper
|
|
@@ -1378,21 +1091,13 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1378
1091
|
if (params && typeof params === "object") {
|
|
1379
1092
|
const {
|
|
1380
1093
|
autoInstallApp,
|
|
1381
|
-
interactionId,
|
|
1382
1094
|
passphraseState: _passphraseState,
|
|
1383
1095
|
useEmptyPassphrase: _useEmptyPassphrase,
|
|
1384
|
-
knownConnections,
|
|
1385
|
-
extra,
|
|
1386
|
-
allowDeviceSelection,
|
|
1387
1096
|
...rest
|
|
1388
1097
|
} = params;
|
|
1389
1098
|
return {
|
|
1390
1099
|
commonParams: {
|
|
1391
|
-
autoInstallApp: typeof autoInstallApp === "boolean" ? autoInstallApp : void 0
|
|
1392
|
-
interactionId: typeof interactionId === "string" ? interactionId : void 0,
|
|
1393
|
-
knownConnections,
|
|
1394
|
-
extra,
|
|
1395
|
-
allowDeviceSelection: typeof allowDeviceSelection === "boolean" ? allowDeviceSelection : void 0
|
|
1100
|
+
autoInstallApp: typeof autoInstallApp === "boolean" ? autoInstallApp : void 0
|
|
1396
1101
|
},
|
|
1397
1102
|
rest
|
|
1398
1103
|
};
|
|
@@ -1568,27 +1273,6 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1568
1273
|
);
|
|
1569
1274
|
}
|
|
1570
1275
|
// ---------------------------------------------------------------------------
|
|
1571
|
-
// Zcash chain methods (viewing key + shielded address reads; Zcash app >= 3.8.0)
|
|
1572
|
-
// ---------------------------------------------------------------------------
|
|
1573
|
-
zcashGetFullViewingKey(connectId, deviceId, params) {
|
|
1574
|
-
return this.callChainWithMergedParams(
|
|
1575
|
-
connectId,
|
|
1576
|
-
deviceId,
|
|
1577
|
-
"zcash",
|
|
1578
|
-
"zcashGetFullViewingKey",
|
|
1579
|
-
params
|
|
1580
|
-
);
|
|
1581
|
-
}
|
|
1582
|
-
zcashGetShieldedAddress(connectId, deviceId, params) {
|
|
1583
|
-
return this.callChainWithMergedParams(
|
|
1584
|
-
connectId,
|
|
1585
|
-
deviceId,
|
|
1586
|
-
"zcash",
|
|
1587
|
-
"zcashGetShieldedAddress",
|
|
1588
|
-
params
|
|
1589
|
-
);
|
|
1590
|
-
}
|
|
1591
|
-
// ---------------------------------------------------------------------------
|
|
1592
1276
|
// App management — OS-level Ledger app install / list. Bypasses fingerprint
|
|
1593
1277
|
// and chain-handler dispatch; installApp progress is forwarded to the adapter
|
|
1594
1278
|
// emitter via 'ui-event' AppInstallProgress events.
|
|
@@ -1677,7 +1361,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1677
1361
|
);
|
|
1678
1362
|
}
|
|
1679
1363
|
await this.connector.configure({ ledgerGenuineCheckWebSocketUrl: relayUrl });
|
|
1680
|
-
|
|
1364
|
+
this.resetState();
|
|
1681
1365
|
}
|
|
1682
1366
|
const result = await this.connectorCall(connectId, "getDeviceGenuineCheck", {});
|
|
1683
1367
|
if (!result.isGenuine) {
|
|
@@ -1703,10 +1387,10 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1703
1387
|
if (relayUrl) {
|
|
1704
1388
|
try {
|
|
1705
1389
|
await this.connector.configure?.({ ledgerGenuineCheckWebSocketUrl: void 0 });
|
|
1706
|
-
|
|
1390
|
+
this.resetState();
|
|
1707
1391
|
} catch {
|
|
1708
1392
|
this.connector.reset();
|
|
1709
|
-
|
|
1393
|
+
this.resetState();
|
|
1710
1394
|
}
|
|
1711
1395
|
}
|
|
1712
1396
|
}
|
|
@@ -1729,36 +1413,13 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1729
1413
|
}
|
|
1730
1414
|
}, 2e3);
|
|
1731
1415
|
this._uiRegistry.cancel();
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
let interactionId;
|
|
1735
|
-
if ((0, import_hwk_adapter_core3.isHardwareInteractionId)(connectId)) {
|
|
1736
|
-
interactionId = connectId;
|
|
1737
|
-
} else if (!connectId && (0, import_hwk_adapter_core3.isHardwareInteractionId)(activeJobId)) {
|
|
1738
|
-
interactionId = activeJobId;
|
|
1739
|
-
}
|
|
1740
|
-
let resolvedConnectId = connectId;
|
|
1741
|
-
if (interactionId) {
|
|
1742
|
-
try {
|
|
1743
|
-
resolvedConnectId = this._interactions.resolve(interactionId).connectId;
|
|
1744
|
-
} catch {
|
|
1745
|
-
resolvedConnectId = void 0;
|
|
1746
|
-
}
|
|
1747
|
-
}
|
|
1748
|
-
const interactionForPhysicalId = !interactionId && connectId ? this._interactions.findActiveByConnectionKey(connectId) : void 0;
|
|
1749
|
-
const queueKey = interactionId ?? (activeJobId === connectId ? connectId : interactionForPhysicalId?.interactionId) ?? connectId;
|
|
1750
|
-
const pendingInteractionId = interactionId ?? interactionForPhysicalId?.interactionId;
|
|
1751
|
-
if (!connectId) this._pendingInteractionBindings.clear();
|
|
1752
|
-
else if (pendingInteractionId) {
|
|
1753
|
-
this._pendingInteractionBindings.delete(pendingInteractionId);
|
|
1754
|
-
}
|
|
1755
|
-
if (queueKey) {
|
|
1756
|
-
this._jobQueue.cancelActiveAndPending(queueKey, userAbortReason);
|
|
1416
|
+
if (connectId) {
|
|
1417
|
+
this._jobQueue.cancelActiveAndPending(connectId, userAbortReason);
|
|
1757
1418
|
} else {
|
|
1758
1419
|
this._jobQueue.cancelActiveAndPending(void 0, userAbortReason);
|
|
1759
1420
|
}
|
|
1760
|
-
if (
|
|
1761
|
-
const sessionId = this._sessions.get(
|
|
1421
|
+
if (connectId) {
|
|
1422
|
+
const sessionId = this._sessions.get(connectId) ?? connectId;
|
|
1762
1423
|
void this.connector.cancel(sessionId);
|
|
1763
1424
|
} else {
|
|
1764
1425
|
for (const sid of this._sessions.values()) void this.connector.cancel(sid);
|
|
@@ -1770,83 +1431,40 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1770
1431
|
// ---------------------------------------------------------------------------
|
|
1771
1432
|
// Chain fingerprint
|
|
1772
1433
|
// ---------------------------------------------------------------------------
|
|
1773
|
-
/** A non-empty deviceId is an expected chain fingerprint, not a transport identifier. */
|
|
1774
1434
|
async getChainFingerprint(connectId, deviceId, chain) {
|
|
1775
1435
|
try {
|
|
1776
1436
|
const fingerprint = await this._computeChainFingerprint(
|
|
1777
1437
|
chain,
|
|
1778
1438
|
(method, params) => this.connectorCall(connectId, method, params, void 0, deviceId)
|
|
1779
1439
|
);
|
|
1780
|
-
if (deviceId) {
|
|
1781
|
-
if (fingerprint !== deviceId) {
|
|
1782
|
-
return (0, import_hwk_adapter_core3.failure)(
|
|
1783
|
-
import_hwk_adapter_core3.HardwareErrorCode.DeviceMismatch,
|
|
1784
|
-
formatDeviceMismatchError(deviceId, fingerprint)
|
|
1785
|
-
);
|
|
1786
|
-
}
|
|
1787
|
-
if ((0, import_hwk_adapter_core3.isHardwareInteractionId)(connectId)) {
|
|
1788
|
-
const interaction = this._interactions.resolve(connectId);
|
|
1789
|
-
await this._publishVerifiedBleBinding(
|
|
1790
|
-
interaction.connectId,
|
|
1791
|
-
chain,
|
|
1792
|
-
fingerprint,
|
|
1793
|
-
void 0,
|
|
1794
|
-
connectId
|
|
1795
|
-
);
|
|
1796
|
-
}
|
|
1797
|
-
}
|
|
1798
1440
|
return (0, import_hwk_adapter_core3.success)(fingerprint);
|
|
1799
1441
|
} catch (err) {
|
|
1800
1442
|
debugError("[LedgerAdapter] getChainFingerprint error:", chain, err);
|
|
1801
1443
|
return this.errorToFailure(err);
|
|
1802
1444
|
}
|
|
1803
1445
|
}
|
|
1804
|
-
/**
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
const acknowledged = await (0, import_hwk_adapter_core3.requestSaveDeviceBinding)(
|
|
1809
|
-
this.emitter,
|
|
1810
|
-
this._uiRegistry,
|
|
1811
|
-
{
|
|
1812
|
-
selectionRequestId: binding.selectedConnection.requestId,
|
|
1813
|
-
connection: { transport: "ble", connectId },
|
|
1814
|
-
identity: { vendor: "ledger", type: "chainFingerprint", chain, value: fingerprint },
|
|
1815
|
-
extra: binding.extra
|
|
1816
|
-
},
|
|
1817
|
-
signal
|
|
1818
|
-
);
|
|
1819
|
-
if (this._bindingSelectionRequestId === binding.selectedConnection.requestId) {
|
|
1820
|
-
this._bindingSelectionRequestId = void 0;
|
|
1821
|
-
}
|
|
1822
|
-
if (interactionId) {
|
|
1823
|
-
this._interactions.resolve(interactionId);
|
|
1824
|
-
this._pendingInteractionBindings.delete(interactionId);
|
|
1825
|
-
}
|
|
1826
|
-
if (acknowledged) return;
|
|
1827
|
-
this.emitter.emit(import_hwk_adapter_core3.DEVICE.LEDGER_CONNECTION_VERIFIED, {
|
|
1828
|
-
type: import_hwk_adapter_core3.DEVICE.LEDGER_CONNECTION_VERIFIED,
|
|
1829
|
-
payload: {
|
|
1830
|
-
previousConnectId: binding.previousConnectId ?? previousConnectId,
|
|
1831
|
-
connectId,
|
|
1832
|
-
chain,
|
|
1833
|
-
fingerprint,
|
|
1834
|
-
extra: binding.extra,
|
|
1835
|
-
selectionRequestId: binding.selectedConnection.requestId
|
|
1836
|
-
}
|
|
1837
|
-
});
|
|
1838
|
-
}
|
|
1839
|
-
/** Verify on the acquired session without re-entering the job queue. */
|
|
1446
|
+
/**
|
|
1447
|
+
* Verify fingerprint using an existing sessionId directly.
|
|
1448
|
+
* Safe to call inside connectorCall without causing queue deadlock.
|
|
1449
|
+
*/
|
|
1840
1450
|
async _verifyDeviceFingerprintWithSession(sessionId, deviceId, chain) {
|
|
1841
1451
|
if (!deviceId) return { success: true };
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1452
|
+
try {
|
|
1453
|
+
const fingerprint = await this._computeChainFingerprint(
|
|
1454
|
+
chain,
|
|
1455
|
+
(method, params) => this._callConnector(sessionId, method, params)
|
|
1456
|
+
);
|
|
1457
|
+
if (fingerprint === deviceId) {
|
|
1458
|
+
return { success: true };
|
|
1459
|
+
}
|
|
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 };
|
|
1465
|
+
}
|
|
1466
|
+
throw err;
|
|
1848
1467
|
}
|
|
1849
|
-
return { success: false, expected: deviceId, actual: fingerprint };
|
|
1850
1468
|
}
|
|
1851
1469
|
/**
|
|
1852
1470
|
* Compute the chain fingerprint via a caller-supplied call strategy.
|
|
@@ -1875,8 +1493,6 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1875
1493
|
address = (await callMethod("solGetAddress", { path, showOnDevice: false })).address;
|
|
1876
1494
|
} else if (chain === "tron") {
|
|
1877
1495
|
address = (await callMethod("tronGetAddress", { path, showOnDevice: false })).address;
|
|
1878
|
-
} else if (chain === "zcash") {
|
|
1879
|
-
address = (await callMethod("zcashGetShieldedAddress", { path, showOnDevice: false })).address;
|
|
1880
1496
|
} else {
|
|
1881
1497
|
throw new Error(`Unsupported chain for fingerprint: ${chain}`);
|
|
1882
1498
|
}
|
|
@@ -2006,17 +1622,16 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
2006
1622
|
// Layer 1 entry. Caller signal only races the outer awaiter; the shared
|
|
2007
1623
|
// `_doConnect` runs under its own internal controller so caller A's cancel
|
|
2008
1624
|
// doesn't kill caller B's await.
|
|
2009
|
-
async ensureConnected(connectId, signal, allowUsbEphemeralFallback = false
|
|
1625
|
+
async ensureConnected(connectId, signal, allowUsbEphemeralFallback = false) {
|
|
2010
1626
|
if (signal.aborted) _LedgerAdapter._throwIfAborted(signal);
|
|
2011
|
-
this.
|
|
2012
|
-
if (this._isBleConnection() && !connectId && !allowUsbEphemeralFallback) {
|
|
1627
|
+
if (isLedgerBleConnectionType(this.connector.connectionType) && !connectId) {
|
|
2013
1628
|
throw Object.assign(new Error("Ledger BLE connectId is required."), {
|
|
2014
1629
|
code: import_hwk_adapter_core3.HardwareErrorCode.DeviceNotFound
|
|
2015
1630
|
});
|
|
2016
1631
|
}
|
|
2017
1632
|
if (connectId && this._sessions.has(connectId)) return connectId;
|
|
2018
1633
|
if (!connectId && this._sessions.size > 0) {
|
|
2019
|
-
if (!this.
|
|
1634
|
+
if (!isLedgerBleConnectionType(this.connector.connectionType) && this._sessions.size > 1) {
|
|
2020
1635
|
throw Object.assign(
|
|
2021
1636
|
new Error(
|
|
2022
1637
|
"Ledger USB session invariant violated: more than one session is active. Please reconnect the device."
|
|
@@ -2026,24 +1641,15 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
2026
1641
|
}
|
|
2027
1642
|
return this._sessions.keys().next().value;
|
|
2028
1643
|
}
|
|
2029
|
-
if (!this._connectingPromise
|
|
2030
|
-
|
|
2031
|
-
this._doConnectAbortController
|
|
2032
|
-
const innerSignal = controller.signal;
|
|
1644
|
+
if (!this._connectingPromise) {
|
|
1645
|
+
this._doConnectAbortController = new AbortController();
|
|
1646
|
+
const innerSignal = this._doConnectAbortController.signal;
|
|
2033
1647
|
this._connectingPromise = (async () => {
|
|
2034
1648
|
try {
|
|
2035
|
-
return await this._doConnect(
|
|
2036
|
-
innerSignal,
|
|
2037
|
-
connectId,
|
|
2038
|
-
allowUsbEphemeralFallback,
|
|
2039
|
-
preserveInteractionId,
|
|
2040
|
-
context
|
|
2041
|
-
);
|
|
1649
|
+
return await this._doConnect(innerSignal, connectId, allowUsbEphemeralFallback);
|
|
2042
1650
|
} finally {
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
this._doConnectAbortController = null;
|
|
2046
|
-
}
|
|
1651
|
+
this._connectingPromise = null;
|
|
1652
|
+
this._doConnectAbortController = null;
|
|
2047
1653
|
}
|
|
2048
1654
|
})();
|
|
2049
1655
|
}
|
|
@@ -2052,49 +1658,22 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
2052
1658
|
// Layer 1 main loop — the ONLY place in SDK that emits unlock dialog.
|
|
2053
1659
|
// Bounded by MAX_DOCONNECT_CONFIRMS — after N Confirms with no progress,
|
|
2054
1660
|
// throw DeviceNotFound so the user is kicked out of the loop.
|
|
2055
|
-
async _doConnect(internalSignal, targetConnectId, allowUsbEphemeralFallback = false
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
)
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
preserveInteractionId,
|
|
2071
|
-
context,
|
|
2072
|
-
internalSignal
|
|
2073
|
-
);
|
|
2074
|
-
}
|
|
2075
|
-
this._activeConnectionType = "ble";
|
|
2076
|
-
const knownBle = context?.knownConnections?.find(
|
|
2077
|
-
(connection) => connection.transport === "ble"
|
|
2078
|
-
);
|
|
2079
|
-
if (knownBle?.transport === "ble") {
|
|
2080
|
-
return this._connectDeviceOrThrow(
|
|
2081
|
-
knownBle.connectId,
|
|
2082
|
-
preserveInteractionId,
|
|
2083
|
-
internalSignal
|
|
2084
|
-
);
|
|
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
|
+
}
|
|
2085
1676
|
}
|
|
2086
|
-
const bleDevices = await this._searchDevices({ transportType: "ble" }, internalSignal);
|
|
2087
|
-
return this._connectFirstOrSelect(
|
|
2088
|
-
bleDevices,
|
|
2089
|
-
void 0,
|
|
2090
|
-
allowUsbEphemeralFallback,
|
|
2091
|
-
preserveInteractionId,
|
|
2092
|
-
context,
|
|
2093
|
-
internalSignal
|
|
2094
|
-
);
|
|
2095
|
-
}
|
|
2096
|
-
if (this._isBleConnection() && targetConnectId) {
|
|
2097
|
-
return this._connectDeviceOrThrow(targetConnectId, preserveInteractionId, internalSignal);
|
|
2098
1677
|
}
|
|
2099
1678
|
let confirms = 0;
|
|
2100
1679
|
while (!internalSignal.aborted) {
|
|
@@ -2102,28 +1681,22 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
2102
1681
|
type: import_hwk_adapter_core3.EConnectorInteraction.Searching,
|
|
2103
1682
|
payload: { sessionId: "" }
|
|
2104
1683
|
});
|
|
2105
|
-
let devices = await this.
|
|
2106
|
-
_LedgerAdapter._throwIfAborted(internalSignal);
|
|
1684
|
+
let devices = await this.searchDevices();
|
|
2107
1685
|
if (devices.length === 0) {
|
|
2108
1686
|
for (let i = 0; i < 3 && !internalSignal.aborted; i += 1) {
|
|
2109
1687
|
await new Promise((resolve) => {
|
|
2110
1688
|
setTimeout(resolve, import_hwk_adapter_core3.DEVICE_CONNECT_RETRY_DELAY_MS);
|
|
2111
1689
|
});
|
|
2112
|
-
|
|
2113
|
-
devices = await this._searchDevices(void 0, internalSignal);
|
|
2114
|
-
_LedgerAdapter._throwIfAborted(internalSignal);
|
|
1690
|
+
devices = await this.searchDevices();
|
|
2115
1691
|
if (devices.length > 0) break;
|
|
2116
1692
|
}
|
|
2117
1693
|
}
|
|
2118
|
-
if (devices.length > 0
|
|
1694
|
+
if (devices.length > 0) {
|
|
2119
1695
|
try {
|
|
2120
1696
|
return await this._connectFirstOrSelect(
|
|
2121
1697
|
devices,
|
|
2122
1698
|
targetConnectId,
|
|
2123
|
-
allowUsbEphemeralFallback
|
|
2124
|
-
preserveInteractionId,
|
|
2125
|
-
context,
|
|
2126
|
-
internalSignal
|
|
1699
|
+
allowUsbEphemeralFallback
|
|
2127
1700
|
);
|
|
2128
1701
|
} catch (err) {
|
|
2129
1702
|
if (!isDeviceLockedError(err) && !isDeviceNotAdvertisingError(err) && !isDeviceDisconnectedError(err)) {
|
|
@@ -2152,107 +1725,45 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
2152
1725
|
_LedgerAdapter._throwIfAborted(internalSignal);
|
|
2153
1726
|
throw new Error("_doConnect aborted");
|
|
2154
1727
|
}
|
|
2155
|
-
async _connectFirstOrSelect(devices, targetConnectId, allowUsbEphemeralFallback = false
|
|
2156
|
-
if (signal) _LedgerAdapter._throwIfAborted(signal);
|
|
1728
|
+
async _connectFirstOrSelect(devices, targetConnectId, allowUsbEphemeralFallback = false) {
|
|
2157
1729
|
if (targetConnectId) {
|
|
2158
1730
|
const target = devices.find(
|
|
2159
1731
|
(d) => d.connectId === targetConnectId || d.deviceId === targetConnectId
|
|
2160
1732
|
);
|
|
2161
1733
|
if (target) {
|
|
2162
|
-
return this._connectDeviceOrThrow(target.connectId
|
|
1734
|
+
return this._connectDeviceOrThrow(target.connectId);
|
|
2163
1735
|
}
|
|
2164
|
-
if (!this.
|
|
1736
|
+
if (!isLedgerBleConnectionType(this.connector.connectionType) && devices.length === 1 && allowUsbEphemeralFallback) {
|
|
2165
1737
|
debugLog(
|
|
2166
1738
|
`[LedgerAdapter] target ${targetConnectId} not in fresh enumeration; accepting sole USB device ${devices[0].connectId} for fingerprint-verified recovery`
|
|
2167
1739
|
);
|
|
2168
|
-
return this._connectDeviceOrThrow(devices[0].connectId
|
|
1740
|
+
return this._connectDeviceOrThrow(devices[0].connectId);
|
|
2169
1741
|
}
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
err._tag = ERROR_TAG.DeviceNotAdvertising;
|
|
2176
|
-
}
|
|
2177
|
-
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;
|
|
2178
1747
|
}
|
|
1748
|
+
throw err;
|
|
2179
1749
|
}
|
|
2180
|
-
|
|
2181
|
-
if (requiresBleSelection && !allowUsbEphemeralFallback) {
|
|
1750
|
+
if (isLedgerBleConnectionType(this.connector.connectionType)) {
|
|
2182
1751
|
throw Object.assign(new Error("Ledger BLE connectId is required."), {
|
|
2183
1752
|
code: import_hwk_adapter_core3.HardwareErrorCode.DeviceNotFound
|
|
2184
1753
|
});
|
|
2185
1754
|
}
|
|
2186
|
-
if (
|
|
2187
|
-
|
|
2188
|
-
if (context) context.bindingSessionId = bindingSessionId;
|
|
2189
|
-
const { device, requestId } = await (0, import_hwk_adapter_core3.requestBleDeviceSelection)({
|
|
2190
|
-
emitter: this.emitter,
|
|
2191
|
-
registry: this._uiRegistry,
|
|
2192
|
-
signal: signal ?? new AbortController().signal,
|
|
2193
|
-
scan: async () => (await this._searchDevices({ transportType: "ble", waitForAllTransports: true }, signal)).filter((device2) => !context?.rejectedConnectIds?.has(device2.connectId)),
|
|
2194
|
-
request: {
|
|
2195
|
-
devices: devices.filter((device2) => !context?.rejectedConnectIds?.has(device2.connectId)),
|
|
2196
|
-
bindingSessionId,
|
|
2197
|
-
rejectedConnectId: context?.rejectedConnectId,
|
|
2198
|
-
context: {
|
|
2199
|
-
kind: "bind-connection",
|
|
2200
|
-
transport: "ble",
|
|
2201
|
-
reason: targetConnectId ? "known-connection-unavailable" : "missing-binding"
|
|
2202
|
-
},
|
|
2203
|
-
extra: context?.extra
|
|
2204
|
-
}
|
|
2205
|
-
});
|
|
2206
|
-
if (context) context.selectedConnection = { connectId: device.connectId, requestId };
|
|
2207
|
-
this._bindingSelectionRequestId = requestId;
|
|
2208
|
-
return this._connectDeviceOrThrow(device.connectId, preserveInteractionId, signal);
|
|
2209
|
-
}
|
|
2210
|
-
if (devices.length > 0 && (devices.length > 1 || requiresBleSelection)) {
|
|
2211
|
-
if (context?.allowDeviceSelection === false || !this.emitter.listenerCount(import_hwk_adapter_core3.UI_REQUEST.REQUEST_SELECT_DEVICE)) {
|
|
2212
|
-
throw (0, import_hwk_adapter_core3.createHwkError)({
|
|
2213
|
-
code: import_hwk_adapter_core3.HardwareErrorCode.DeviceNotFound,
|
|
2214
|
-
message: "Select a Ledger device before continuing"
|
|
2215
|
-
});
|
|
2216
|
-
}
|
|
2217
|
-
const requestId = this._uiRegistry.createRequestId();
|
|
2218
|
-
const waitPromise = this._uiRegistry.wait(
|
|
2219
|
-
import_hwk_adapter_core3.UI_REQUEST.REQUEST_SELECT_DEVICE,
|
|
2220
|
-
{ requestId }
|
|
2221
|
-
);
|
|
2222
|
-
this.emitter.emit(import_hwk_adapter_core3.UI_REQUEST.REQUEST_SELECT_DEVICE, {
|
|
2223
|
-
type: import_hwk_adapter_core3.UI_REQUEST.REQUEST_SELECT_DEVICE,
|
|
2224
|
-
payload: {
|
|
2225
|
-
devices,
|
|
2226
|
-
requestId,
|
|
2227
|
-
context: requiresBleSelection ? {
|
|
2228
|
-
kind: "bind-connection",
|
|
2229
|
-
transport: "ble",
|
|
2230
|
-
reason: targetConnectId ? "known-connection-unavailable" : "missing-binding"
|
|
2231
|
-
} : { kind: "select-device", transport: "usb", reason: "multiple-candidates" },
|
|
2232
|
-
extra: context?.extra
|
|
2233
|
-
}
|
|
2234
|
-
});
|
|
2235
|
-
const { sdkConnectId } = await (signal ? this._abortable(signal, waitPromise) : waitPromise);
|
|
2236
|
-
if (signal) _LedgerAdapter._throwIfAborted(signal);
|
|
2237
|
-
const selected = devices.find((device) => device.connectId === sdkConnectId);
|
|
2238
|
-
if (!selected) {
|
|
2239
|
-
throw Object.assign(new Error("Selected Ledger is no longer available"), {
|
|
2240
|
-
code: import_hwk_adapter_core3.HardwareErrorCode.DeviceNotFound
|
|
2241
|
-
});
|
|
2242
|
-
}
|
|
2243
|
-
if (context && requiresBleSelection)
|
|
2244
|
-
context.selectedConnection = { connectId: selected.connectId, requestId };
|
|
2245
|
-
return this._connectDeviceOrThrow(selected.connectId, preserveInteractionId, signal);
|
|
1755
|
+
if (devices.length > 1) {
|
|
1756
|
+
throw createMultipleUsbLedgerDevicesError();
|
|
2246
1757
|
}
|
|
2247
1758
|
if (devices.length !== 1) {
|
|
2248
1759
|
throw Object.assign(new Error("Ledger device not found."), {
|
|
2249
1760
|
code: import_hwk_adapter_core3.HardwareErrorCode.DeviceNotFound
|
|
2250
1761
|
});
|
|
2251
1762
|
}
|
|
2252
|
-
return this._connectDeviceOrThrow(devices[0].connectId
|
|
1763
|
+
return this._connectDeviceOrThrow(devices[0].connectId);
|
|
2253
1764
|
}
|
|
2254
|
-
async _connectDeviceOrThrow(chosenConnectId
|
|
2255
|
-
const result = await this.
|
|
1765
|
+
async _connectDeviceOrThrow(chosenConnectId) {
|
|
1766
|
+
const result = await this.connectDevice(chosenConnectId);
|
|
2256
1767
|
if (!result.success) {
|
|
2257
1768
|
const payload = result.payload;
|
|
2258
1769
|
const rethrow = Object.assign(new Error(payload.error), {
|
|
@@ -2263,7 +1774,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
2263
1774
|
}
|
|
2264
1775
|
throw rethrow;
|
|
2265
1776
|
}
|
|
2266
|
-
return
|
|
1777
|
+
return chosenConnectId;
|
|
2267
1778
|
}
|
|
2268
1779
|
/**
|
|
2269
1780
|
* Call the connector with automatic session resolution and disconnect retry.
|
|
@@ -2293,121 +1804,26 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
2293
1804
|
* lives in one place.
|
|
2294
1805
|
*/
|
|
2295
1806
|
async _callConnector(sessionId, method, params, signal) {
|
|
2296
|
-
this.
|
|
2297
|
-
const releaseOperation = this._retainConnectorOperation(`call:${sessionId}`);
|
|
2298
|
-
let promise;
|
|
2299
|
-
try {
|
|
2300
|
-
promise = this.connector.call(sessionId, method, params).finally(releaseOperation);
|
|
2301
|
-
} catch (error) {
|
|
2302
|
-
releaseOperation();
|
|
2303
|
-
throw error;
|
|
2304
|
-
}
|
|
1807
|
+
const promise = this.connector.call(sessionId, method, params);
|
|
2305
1808
|
const result = signal ? await this._abortable(signal, promise) : await promise;
|
|
2306
1809
|
return this._unwrapConnectorResult(result);
|
|
2307
1810
|
}
|
|
2308
|
-
_assertConnectorReady(method) {
|
|
2309
|
-
if (this._resetPromise || this._pendingConnectorTeardowns > 0 || this._unsettledConnectorOperations.size > 0) {
|
|
2310
|
-
throw _LedgerAdapter._createDeviceBusyError(method);
|
|
2311
|
-
}
|
|
2312
|
-
}
|
|
2313
|
-
_runConnectorTeardown(task) {
|
|
2314
|
-
const previous = this._connectorTeardownTail;
|
|
2315
|
-
let releaseTail = () => void 0;
|
|
2316
|
-
this._connectorTeardownTail = new Promise((resolve) => {
|
|
2317
|
-
releaseTail = resolve;
|
|
2318
|
-
});
|
|
2319
|
-
this._pendingConnectorTeardowns += 1;
|
|
2320
|
-
return (async () => {
|
|
2321
|
-
try {
|
|
2322
|
-
await previous;
|
|
2323
|
-
await this._waitForConnectorOperationsToDrain();
|
|
2324
|
-
await task();
|
|
2325
|
-
} finally {
|
|
2326
|
-
this._pendingConnectorTeardowns -= 1;
|
|
2327
|
-
releaseTail();
|
|
2328
|
-
}
|
|
2329
|
-
})();
|
|
2330
|
-
}
|
|
2331
|
-
_waitForConnectorOperationsToDrain() {
|
|
2332
|
-
if (this._unsettledConnectorOperations.size === 0) {
|
|
2333
|
-
return Promise.resolve();
|
|
2334
|
-
}
|
|
2335
|
-
return new Promise((resolve) => {
|
|
2336
|
-
this._connectorIdleWaiters.add(resolve);
|
|
2337
|
-
});
|
|
2338
|
-
}
|
|
2339
|
-
_retainConnectorOperation(key) {
|
|
2340
|
-
this._unsettledConnectorOperations.set(
|
|
2341
|
-
key,
|
|
2342
|
-
(this._unsettledConnectorOperations.get(key) ?? 0) + 1
|
|
2343
|
-
);
|
|
2344
|
-
let released = false;
|
|
2345
|
-
return () => {
|
|
2346
|
-
if (released) return;
|
|
2347
|
-
released = true;
|
|
2348
|
-
const remaining = (this._unsettledConnectorOperations.get(key) ?? 1) - 1;
|
|
2349
|
-
if (remaining > 0) {
|
|
2350
|
-
this._unsettledConnectorOperations.set(key, remaining);
|
|
2351
|
-
} else {
|
|
2352
|
-
this._unsettledConnectorOperations.delete(key);
|
|
2353
|
-
}
|
|
2354
|
-
if (this._unsettledConnectorOperations.size === 0) {
|
|
2355
|
-
for (const resolve of this._connectorIdleWaiters) resolve();
|
|
2356
|
-
this._connectorIdleWaiters.clear();
|
|
2357
|
-
}
|
|
2358
|
-
};
|
|
2359
|
-
}
|
|
2360
1811
|
async connectorCall(connectId, method, params, fingerprint, permissionDeviceId, commonParams, installContext) {
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
throw (0, import_hwk_adapter_core3.createHwkError)({
|
|
2364
|
-
code: import_hwk_adapter_core3.HardwareErrorCode.InvalidParams,
|
|
2365
|
-
message: "Conflicting Ledger interaction ids",
|
|
2366
|
-
params: {
|
|
2367
|
-
positionalInteractionId,
|
|
2368
|
-
commonInteractionId: commonParams.interactionId
|
|
2369
|
-
}
|
|
2370
|
-
});
|
|
2371
|
-
}
|
|
2372
|
-
const interactionId = commonParams?.interactionId ?? positionalInteractionId;
|
|
2373
|
-
const interaction = interactionId ? this._interactions.resolve(interactionId) : void 0;
|
|
2374
|
-
const releaseInteractionRetention = interactionId ? this._interactions.retain(interactionId) : void 0;
|
|
2375
|
-
const effectiveConnectId = interaction?.connectId ?? connectId;
|
|
2376
|
-
debugLog("[LedgerAdapter][REQ]", {
|
|
2377
|
-
method,
|
|
2378
|
-
connectId: effectiveConnectId || "(empty)",
|
|
2379
|
-
params
|
|
2380
|
-
});
|
|
2381
|
-
const queueKey = (interactionId ?? effectiveConnectId) || "__ledger_default__";
|
|
1812
|
+
debugLog("[LedgerAdapter][REQ]", { method, connectId: connectId || "(empty)", params });
|
|
1813
|
+
const queueKey = connectId || "__ledger_default__";
|
|
2382
1814
|
try {
|
|
2383
1815
|
const result = await this._jobQueue.enqueue(
|
|
2384
1816
|
queueKey,
|
|
2385
|
-
async (signal) =>
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
commonParams,
|
|
2396
|
-
installContext ?? {},
|
|
2397
|
-
interactionId
|
|
2398
|
-
);
|
|
2399
|
-
} catch (error) {
|
|
2400
|
-
this._finishBleBinding(signal.aborted ? "cancelled" : "failed");
|
|
2401
|
-
throw error;
|
|
2402
|
-
} finally {
|
|
2403
|
-
if (interactionId) {
|
|
2404
|
-
this._activeInteractionJobs.delete(interactionId);
|
|
2405
|
-
if (this._pendingInteractionDisconnects.delete(interactionId)) {
|
|
2406
|
-
await this._releaseLostInteractionConnection(interactionId);
|
|
2407
|
-
}
|
|
2408
|
-
}
|
|
2409
|
-
}
|
|
2410
|
-
},
|
|
1817
|
+
async (signal) => this._runConnectorCall(
|
|
1818
|
+
connectId,
|
|
1819
|
+
method,
|
|
1820
|
+
params,
|
|
1821
|
+
signal,
|
|
1822
|
+
fingerprint,
|
|
1823
|
+
permissionDeviceId,
|
|
1824
|
+
commonParams,
|
|
1825
|
+
installContext
|
|
1826
|
+
),
|
|
2411
1827
|
{
|
|
2412
1828
|
label: method,
|
|
2413
1829
|
rejectIfBusy: true,
|
|
@@ -2428,8 +1844,6 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
2428
1844
|
}
|
|
2429
1845
|
});
|
|
2430
1846
|
throw err;
|
|
2431
|
-
} finally {
|
|
2432
|
-
releaseInteractionRetention?.();
|
|
2433
1847
|
}
|
|
2434
1848
|
}
|
|
2435
1849
|
/**
|
|
@@ -2439,7 +1853,6 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
2439
1853
|
_abortable(signal, promise) {
|
|
2440
1854
|
const getAbortReason = () => signal.reason ?? this._lastCancelReason ?? new Error("Aborted");
|
|
2441
1855
|
if (signal.aborted) {
|
|
2442
|
-
void promise.catch(() => void 0);
|
|
2443
1856
|
return Promise.reject(getAbortReason());
|
|
2444
1857
|
}
|
|
2445
1858
|
return new Promise((resolve, reject) => {
|
|
@@ -2466,15 +1879,13 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
2466
1879
|
}
|
|
2467
1880
|
}
|
|
2468
1881
|
/** Actual work done under the job queue — connection, fingerprint, call, and recovery. */
|
|
2469
|
-
async _runConnectorCall(connectId, method, params, signal, fingerprint, permissionDeviceId, commonParams, installContext
|
|
1882
|
+
async _runConnectorCall(connectId, method, params, signal, fingerprint, permissionDeviceId, commonParams, installContext) {
|
|
2470
1883
|
_LedgerAdapter._throwIfAborted(signal);
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
);
|
|
2477
|
-
}
|
|
1884
|
+
await this._ensureDevicePermission(
|
|
1885
|
+
connectId,
|
|
1886
|
+
permissionDeviceId ?? fingerprint?.deviceId,
|
|
1887
|
+
signal
|
|
1888
|
+
);
|
|
2478
1889
|
_LedgerAdapter._throwIfAborted(signal);
|
|
2479
1890
|
let effectiveParams = params;
|
|
2480
1891
|
if (method === "btcGetPublicKey") {
|
|
@@ -2488,133 +1899,36 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
2488
1899
|
effectiveParams = gatedParams;
|
|
2489
1900
|
}
|
|
2490
1901
|
const allowUsbEphemeralFallback = !!fingerprint?.deviceId && !fingerprint.skipFingerprint;
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
const knownTransport = this._isBleConnection() ? "ble" : "usb";
|
|
2494
|
-
const hintedConnectId = commonParams?.knownConnections?.find(
|
|
2495
|
-
(connection) => connection.transport === knownTransport
|
|
2496
|
-
);
|
|
2497
|
-
const inputConnectId = hintedConnectId && hintedConnectId.transport !== "qr" ? hintedConnectId.connectId : connectId;
|
|
2498
|
-
const preferredConnectId = fingerprint && !fingerprint.skipFingerprint && verifiedBleTarget?.chain === fingerprint.chain && verifiedBleTarget.fingerprint === fingerprint.deviceId ? verifiedBleTarget.connectId : inputConnectId;
|
|
2499
|
-
const connectionAttempt = { ...commonParams };
|
|
2500
|
-
const bundleConnection = installContext?.connection;
|
|
2501
|
-
if (bundleConnection && this._sessions.get(bundleConnection.connectId) !== bundleConnection.sessionId) {
|
|
2502
|
-
throw (0, import_hwk_adapter_core3.createHwkError)({
|
|
2503
|
-
code: import_hwk_adapter_core3.HardwareErrorCode.DeviceDisconnected,
|
|
2504
|
-
message: "Ledger all-network connection ended"
|
|
2505
|
-
});
|
|
2506
|
-
}
|
|
2507
|
-
let resolvedConnectId = interactionId ? this._interactions.resolve(interactionId).connectId : bundleConnection?.connectId ?? await this.ensureConnected(
|
|
2508
|
-
preferredConnectId,
|
|
1902
|
+
const resolvedConnectId = await this.ensureConnected(
|
|
1903
|
+
connectId,
|
|
2509
1904
|
signal,
|
|
2510
|
-
allowUsbEphemeralFallback
|
|
2511
|
-
void 0,
|
|
2512
|
-
connectionAttempt
|
|
1905
|
+
allowUsbEphemeralFallback
|
|
2513
1906
|
);
|
|
2514
|
-
|
|
2515
|
-
if (sessionId && installContext && !installContext.connection) {
|
|
2516
|
-
installContext.connection = { connectId: resolvedConnectId, sessionId };
|
|
2517
|
-
}
|
|
1907
|
+
const sessionId = this._sessions.get(resolvedConnectId);
|
|
2518
1908
|
if (!sessionId) {
|
|
2519
|
-
if (interactionId) {
|
|
2520
|
-
this._interactions.end(interactionId, "disconnect");
|
|
2521
|
-
throw (0, import_hwk_adapter_core3.createHwkError)({
|
|
2522
|
-
code: import_hwk_adapter_core3.HardwareErrorCode.InteractionEnded,
|
|
2523
|
-
message: "Ledger interaction connection is no longer active",
|
|
2524
|
-
params: { interactionId, reason: "disconnect" }
|
|
2525
|
-
});
|
|
2526
|
-
}
|
|
2527
1909
|
throw Object.assign(new Error("Auto-connect succeeded but no session found"), {
|
|
2528
1910
|
_tag: ERROR_TAG.DeviceSessionNotFound
|
|
2529
1911
|
});
|
|
2530
1912
|
}
|
|
2531
1913
|
try {
|
|
2532
1914
|
if (fingerprint && !fingerprint.skipFingerprint && fingerprint.deviceId) {
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
if (!this._isBleConnection() || binding?.selectedConnection?.connectId !== resolvedConnectId) {
|
|
2545
|
-
throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {
|
|
2546
|
-
code: import_hwk_adapter_core3.HardwareErrorCode.DeviceMismatch
|
|
2547
|
-
});
|
|
2548
|
-
}
|
|
2549
|
-
binding.rejectedConnectIds ?? (binding.rejectedConnectIds = /* @__PURE__ */ new Set());
|
|
2550
|
-
binding.rejectedConnectIds.add(resolvedConnectId);
|
|
2551
|
-
binding.rejectedConnectId = resolvedConnectId;
|
|
2552
|
-
this._sessions.delete(resolvedConnectId);
|
|
2553
|
-
await this.connector.disconnect(sessionId);
|
|
2554
|
-
if (interactionId) this._pendingInteractionDisconnects.delete(interactionId);
|
|
2555
|
-
_LedgerAdapter._throwIfAborted(signal);
|
|
2556
|
-
resolvedConnectId = await this._connectFirstOrSelect(
|
|
2557
|
-
[],
|
|
2558
|
-
void 0,
|
|
2559
|
-
true,
|
|
2560
|
-
interactionId,
|
|
2561
|
-
binding,
|
|
2562
|
-
signal
|
|
2563
|
-
);
|
|
2564
|
-
const selectedSession = this._sessions.get(resolvedConnectId);
|
|
2565
|
-
const selectedDevice = this._discoveredDevices.get(resolvedConnectId);
|
|
2566
|
-
if (!selectedSession || !selectedDevice)
|
|
2567
|
-
throw (0, import_hwk_adapter_core3.createHwkError)({
|
|
2568
|
-
code: import_hwk_adapter_core3.HardwareErrorCode.DeviceDisconnected,
|
|
2569
|
-
message: "Selected Ledger connection ended"
|
|
2570
|
-
});
|
|
2571
|
-
sessionId = selectedSession;
|
|
2572
|
-
if (interactionId)
|
|
2573
|
-
this._interactions.rebind(interactionId, {
|
|
2574
|
-
connectId: resolvedConnectId,
|
|
2575
|
-
device: selectedDevice,
|
|
2576
|
-
connectionKeys: [sessionId]
|
|
2577
|
-
});
|
|
2578
|
-
if (installContext)
|
|
2579
|
-
installContext.connection = { connectId: resolvedConnectId, sessionId };
|
|
2580
|
-
}
|
|
2581
|
-
if (!interactionId && connectionAttempt.selectedConnection?.connectId === resolvedConnectId && this._isBleConnection()) {
|
|
2582
|
-
this._verifiedBleReconnectTargets.set(connectId, {
|
|
2583
|
-
connectId: resolvedConnectId,
|
|
2584
|
-
chain: fingerprint.chain,
|
|
2585
|
-
fingerprint: fingerprint.deviceId
|
|
1915
|
+
const fp = await this._abortable(
|
|
1916
|
+
signal,
|
|
1917
|
+
this._verifyDeviceFingerprintWithSession(
|
|
1918
|
+
sessionId,
|
|
1919
|
+
fingerprint.deviceId,
|
|
1920
|
+
fingerprint.chain
|
|
1921
|
+
)
|
|
1922
|
+
);
|
|
1923
|
+
if (!fp.success) {
|
|
1924
|
+
throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {
|
|
1925
|
+
code: import_hwk_adapter_core3.HardwareErrorCode.DeviceMismatch
|
|
2586
1926
|
});
|
|
2587
1927
|
}
|
|
2588
|
-
await this._publishVerifiedBleBinding(
|
|
2589
|
-
resolvedConnectId,
|
|
2590
|
-
fingerprint.chain,
|
|
2591
|
-
fingerprint.deviceId,
|
|
2592
|
-
connectionAttempt,
|
|
2593
|
-
interactionId,
|
|
2594
|
-
connectId,
|
|
2595
|
-
signal
|
|
2596
|
-
);
|
|
2597
1928
|
}
|
|
2598
|
-
businessCallStarted = true;
|
|
2599
1929
|
return await this._callConnector(sessionId, method, effectiveParams, signal);
|
|
2600
1930
|
} catch (err) {
|
|
2601
1931
|
if (signal.aborted) throw err;
|
|
2602
|
-
if (isDeviceDisconnectedError(err) || isDeviceNotAdvertisingError(err) || isTimeoutError(err) || isConnectionLevelError(err)) {
|
|
2603
|
-
this._discoveredDevices.delete(resolvedConnectId);
|
|
2604
|
-
if (interactionId) await this._releaseLostInteractionConnection(interactionId);
|
|
2605
|
-
else {
|
|
2606
|
-
this._sessions.delete(resolvedConnectId);
|
|
2607
|
-
await this.connector.disconnect(sessionId).catch(() => void 0);
|
|
2608
|
-
}
|
|
2609
|
-
const ambiguous = businessCallStarted && !(0, import_hwk_adapter_core3.canReplayHardwareMethodAfterTransportFailure)(method);
|
|
2610
|
-
const interactionParams = interactionId ? { interactionId, reason: "disconnect" } : void 0;
|
|
2611
|
-
throw (0, import_hwk_adapter_core3.createHwkError)({
|
|
2612
|
-
code: interactionId ? import_hwk_adapter_core3.HardwareErrorCode.InteractionEnded : mapLedgerError(err).code,
|
|
2613
|
-
message: "Ledger operation connection was lost; start a new operation",
|
|
2614
|
-
params: ambiguous ? (0, import_hwk_adapter_core3.operationMayHaveCompletedParams)(method, { interactionId }) : interactionParams,
|
|
2615
|
-
recovery: ambiguous ? { scope: "unknown" } : void 0
|
|
2616
|
-
});
|
|
2617
|
-
}
|
|
2618
1932
|
const errObj = err;
|
|
2619
1933
|
debugLog("[LedgerAdapter] connectorCall error:", method, {
|
|
2620
1934
|
message: errObj?.message,
|
|
@@ -2626,65 +1940,6 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
2626
1940
|
isNotAdvertising: isDeviceNotAdvertisingError(err),
|
|
2627
1941
|
isStuckApp: isStuckAppStateError(err)
|
|
2628
1942
|
});
|
|
2629
|
-
if ((isDeviceLockedError(err) || errObj?.code === import_hwk_adapter_core3.HardwareErrorCode.DeviceLocked) && lockedRetryBudget > 0) {
|
|
2630
|
-
await this._waitForDeviceConnect(signal);
|
|
2631
|
-
if (this._sessions.get(resolvedConnectId) !== sessionId) {
|
|
2632
|
-
throw (0, import_hwk_adapter_core3.createHwkError)({
|
|
2633
|
-
code: interactionId ? import_hwk_adapter_core3.HardwareErrorCode.InteractionEnded : import_hwk_adapter_core3.HardwareErrorCode.DeviceDisconnected,
|
|
2634
|
-
message: "Ledger connection ended while waiting for unlock"
|
|
2635
|
-
});
|
|
2636
|
-
}
|
|
2637
|
-
return this._runConnectorCall(
|
|
2638
|
-
resolvedConnectId,
|
|
2639
|
-
method,
|
|
2640
|
-
effectiveParams,
|
|
2641
|
-
signal,
|
|
2642
|
-
fingerprint,
|
|
2643
|
-
permissionDeviceId,
|
|
2644
|
-
commonParams,
|
|
2645
|
-
installContext,
|
|
2646
|
-
interactionId,
|
|
2647
|
-
lockedRetryBudget - 1
|
|
2648
|
-
);
|
|
2649
|
-
}
|
|
2650
|
-
if (businessCallStarted && isStuckAppStateError(err)) {
|
|
2651
|
-
await this._sleepAbortable(_LedgerAdapter.STUCK_APP_RETRY_DELAY_MS, signal);
|
|
2652
|
-
if (this._sessions.get(resolvedConnectId) !== sessionId) {
|
|
2653
|
-
throw (0, import_hwk_adapter_core3.createHwkError)({
|
|
2654
|
-
code: interactionId ? import_hwk_adapter_core3.HardwareErrorCode.InteractionEnded : import_hwk_adapter_core3.HardwareErrorCode.DeviceDisconnected,
|
|
2655
|
-
message: "Ledger connection ended during the app transition"
|
|
2656
|
-
});
|
|
2657
|
-
}
|
|
2658
|
-
try {
|
|
2659
|
-
return await this._callConnector(sessionId, method, effectiveParams, signal);
|
|
2660
|
-
} catch (retryErr) {
|
|
2661
|
-
if (isStuckAppStateError(retryErr)) throw err;
|
|
2662
|
-
if (isDeviceDisconnectedError(retryErr) || isDeviceNotAdvertisingError(retryErr) || isTimeoutError(retryErr) || isConnectionLevelError(retryErr)) {
|
|
2663
|
-
if (interactionId) await this._releaseLostInteractionConnection(interactionId);
|
|
2664
|
-
else {
|
|
2665
|
-
this._sessions.delete(resolvedConnectId);
|
|
2666
|
-
this._discoveredDevices.delete(resolvedConnectId);
|
|
2667
|
-
await this.connector.disconnect(sessionId).catch(() => void 0);
|
|
2668
|
-
}
|
|
2669
|
-
throw (0, import_hwk_adapter_core3.createHwkError)({
|
|
2670
|
-
code: interactionId ? import_hwk_adapter_core3.HardwareErrorCode.InteractionEnded : mapLedgerError(retryErr).code,
|
|
2671
|
-
message: `Ledger ${method} may have completed before the connection was lost`,
|
|
2672
|
-
params: !(0, import_hwk_adapter_core3.canReplayHardwareMethodAfterTransportFailure)(method) ? (0, import_hwk_adapter_core3.operationMayHaveCompletedParams)(method, {
|
|
2673
|
-
interactionId,
|
|
2674
|
-
reason: "disconnect"
|
|
2675
|
-
}) : { interactionId, reason: "disconnect" },
|
|
2676
|
-
recovery: !(0, import_hwk_adapter_core3.canReplayHardwareMethodAfterTransportFailure)(method) ? { scope: "unknown" } : void 0
|
|
2677
|
-
});
|
|
2678
|
-
}
|
|
2679
|
-
throw retryErr;
|
|
2680
|
-
}
|
|
2681
|
-
}
|
|
2682
|
-
if (!interactionId && err?.code === import_hwk_adapter_core3.HardwareErrorCode.DeviceMismatch) {
|
|
2683
|
-
this._sessions.delete(resolvedConnectId);
|
|
2684
|
-
this._discoveredDevices.delete(resolvedConnectId);
|
|
2685
|
-
await this.connector.disconnect(sessionId).catch(() => void 0);
|
|
2686
|
-
throw err;
|
|
2687
|
-
}
|
|
2688
1943
|
const autoInstallApp = commonParams?.autoInstallApp ?? this._defaultAutoInstallApp;
|
|
2689
1944
|
const isAppMissing = isAppNotInstalledError(err) || err?.code === import_hwk_adapter_core3.HardwareErrorCode.AppNotInstalled;
|
|
2690
1945
|
if (autoInstallApp && isAppMissing) {
|
|
@@ -2740,14 +1995,157 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
2740
1995
|
fingerprint,
|
|
2741
1996
|
permissionDeviceId,
|
|
2742
1997
|
commonParams,
|
|
2743
|
-
installContext
|
|
2744
|
-
|
|
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
|
|
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
|
|
2745
2039
|
);
|
|
2040
|
+
throw retryErr;
|
|
2746
2041
|
}
|
|
2747
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
|
+
}
|
|
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
|
+
});
|
|
2111
|
+
}
|
|
2748
2112
|
throw err;
|
|
2749
2113
|
}
|
|
2750
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
|
+
}
|
|
2751
2149
|
_sleepAbortable(ms, signal) {
|
|
2752
2150
|
return new Promise((resolve, reject) => {
|
|
2753
2151
|
if (signal.aborted) {
|
|
@@ -2765,6 +2163,88 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
2765
2163
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
2766
2164
|
});
|
|
2767
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
|
+
}
|
|
2768
2248
|
/**
|
|
2769
2249
|
* Ensure OS-level device permission (Bluetooth / USB) before proceeding.
|
|
2770
2250
|
*
|
|
@@ -2834,15 +2314,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
2834
2314
|
if (err && typeof err === "object" && "code" in err && typeof err.code === "number") {
|
|
2835
2315
|
const e = err;
|
|
2836
2316
|
const params = e.code === import_hwk_adapter_core3.HardwareErrorCode.DevicePermissionDenied && e.reason ? { permissionDeniedReason: e.reason } : e.params;
|
|
2837
|
-
return ledgerFailure(
|
|
2838
|
-
e.code,
|
|
2839
|
-
e.message ?? "Unknown error",
|
|
2840
|
-
e.appName,
|
|
2841
|
-
tag,
|
|
2842
|
-
params,
|
|
2843
|
-
void 0,
|
|
2844
|
-
(0, import_hwk_adapter_core3.isHwkRecoveryHint)(e.recovery) ? e.recovery : void 0
|
|
2845
|
-
);
|
|
2317
|
+
return ledgerFailure(e.code, e.message ?? "Unknown error", e.appName, tag, params);
|
|
2846
2318
|
}
|
|
2847
2319
|
const mapped = mapLedgerError(err);
|
|
2848
2320
|
return ledgerFailure(mapped.code, mapped.message, mapped.appName, tag);
|
|
@@ -2869,7 +2341,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
2869
2341
|
deviceId: device.deviceId,
|
|
2870
2342
|
connectId: device.connectId,
|
|
2871
2343
|
label: device.name,
|
|
2872
|
-
connectionType:
|
|
2344
|
+
connectionType: this.connector.connectionType,
|
|
2873
2345
|
rssi: device.rssi,
|
|
2874
2346
|
isConnectable: device.isConnectable,
|
|
2875
2347
|
serialNumber: device.serialNumber,
|
|
@@ -2894,7 +2366,7 @@ _LedgerAdapter.APP_INSTALL_PROGRESS_MIN_DELTA = 0.05;
|
|
|
2894
2366
|
var LedgerAdapter = _LedgerAdapter;
|
|
2895
2367
|
|
|
2896
2368
|
// src/connector/LedgerConnectorBase.ts
|
|
2897
|
-
var
|
|
2369
|
+
var import_hwk_adapter_core13 = require("@onekeyfe/hwk-adapter-core");
|
|
2898
2370
|
|
|
2899
2371
|
// src/device/LedgerDeviceManager.ts
|
|
2900
2372
|
var LedgerDeviceManager = class {
|
|
@@ -3430,7 +2902,7 @@ var SignerManager = class _SignerManager {
|
|
|
3430
2902
|
return (args) => new import_device_signer_kit_ethereum.SignerEthBuilder(args);
|
|
3431
2903
|
}
|
|
3432
2904
|
static _createContextModule() {
|
|
3433
|
-
const contextModule = new import_context_module.ContextModuleBuilder({}).
|
|
2905
|
+
const contextModule = new import_context_module.ContextModuleBuilder({}).removeDefaultLoaders().build();
|
|
3434
2906
|
return _SignerManager.wrapBlindSigningReportNonBlocking(contextModule);
|
|
3435
2907
|
}
|
|
3436
2908
|
static wrapBlindSigningReportNonBlocking(contextModule) {
|
|
@@ -3901,7 +3373,6 @@ function _applySignaturesToPsbt(psbtHex, signatures) {
|
|
|
3901
3373
|
|
|
3902
3374
|
// src/connector/chains/sol.ts
|
|
3903
3375
|
var import_hwk_adapter_core9 = require("@onekeyfe/hwk-adapter-core");
|
|
3904
|
-
var import_bs58 = __toESM(require("bs58"));
|
|
3905
3376
|
|
|
3906
3377
|
// src/signer/SignerSol.ts
|
|
3907
3378
|
var SignerSol = class {
|
|
@@ -3985,21 +3456,8 @@ async function solSignMessage(ctx, sessionId, params) {
|
|
|
3985
3456
|
const path = normalizePath(params.path);
|
|
3986
3457
|
const messageBytes = (0, import_hwk_adapter_core9.hexToBytes)(params.message);
|
|
3987
3458
|
try {
|
|
3988
|
-
if (params.messageVersion === 1) {
|
|
3989
|
-
const preparedMessage = (0, import_hwk_adapter_core9.prepareSolanaOffchainMessageV1)({
|
|
3990
|
-
message: messageBytes,
|
|
3991
|
-
requiredSigners: params.requiredSigners
|
|
3992
|
-
});
|
|
3993
|
-
const { SignMessageVersion } = await ctx.importLedgerKit(
|
|
3994
|
-
"@ledgerhq/device-signer-kit-solana"
|
|
3995
|
-
);
|
|
3996
|
-
const result2 = await solSigner.signMessage(path, preparedMessage.serializedMessage, {
|
|
3997
|
-
version: SignMessageVersion.Raw
|
|
3998
|
-
});
|
|
3999
|
-
return { signature: decodeBase58Signature(result2.signature) };
|
|
4000
|
-
}
|
|
4001
3459
|
const result = await solSigner.signMessage(path, messageBytes);
|
|
4002
|
-
return { signature:
|
|
3460
|
+
return { signature: result.signature };
|
|
4003
3461
|
} catch (err) {
|
|
4004
3462
|
ctx.invalidateSession(sessionId);
|
|
4005
3463
|
throw ctx.wrapError(err);
|
|
@@ -4007,27 +3465,11 @@ async function solSignMessage(ctx, sessionId, params) {
|
|
|
4007
3465
|
ctx.clearCanceller(sessionId);
|
|
4008
3466
|
}
|
|
4009
3467
|
}
|
|
4010
|
-
function decodeBase58Signature(signature) {
|
|
4011
|
-
const bytes = import_bs58.default.decode(signature);
|
|
4012
|
-
if (bytes.length !== 64) {
|
|
4013
|
-
throw new Error(`Ledger Solana signature must be 64 bytes, received ${bytes.length}`);
|
|
4014
|
-
}
|
|
4015
|
-
return (0, import_hwk_adapter_core9.bytesToHex)(bytes);
|
|
4016
|
-
}
|
|
4017
|
-
function decodeBase58EnvelopeSignature(envelope) {
|
|
4018
|
-
const bytes = import_bs58.default.decode(envelope);
|
|
4019
|
-
if (bytes.length < 65 || bytes[0] !== 1) {
|
|
4020
|
-
throw new Error("Ledger Solana signature envelope is invalid");
|
|
4021
|
-
}
|
|
4022
|
-
return (0, import_hwk_adapter_core9.bytesToHex)(bytes.subarray(1, 65));
|
|
4023
|
-
}
|
|
4024
3468
|
async function _createSolSigner(ctx, sessionId) {
|
|
4025
3469
|
const dmk = await ctx.getOrCreateDmk();
|
|
4026
|
-
const { ContextModuleBuilder: ContextModuleBuilder2
|
|
4027
|
-
"@ledgerhq/context-module"
|
|
4028
|
-
);
|
|
3470
|
+
const { ContextModuleBuilder: ContextModuleBuilder2 } = await ctx.importLedgerKit("@ledgerhq/context-module");
|
|
4029
3471
|
const { SignerSolanaBuilder } = await ctx.importLedgerKit("@ledgerhq/device-signer-kit-solana");
|
|
4030
|
-
const contextModule = new ContextModuleBuilder2({}).
|
|
3472
|
+
const contextModule = new ContextModuleBuilder2({}).removeDefaultLoaders().build();
|
|
4031
3473
|
const sdkSigner = new SignerSolanaBuilder({ dmk, sessionId }).withContextModule(contextModule).build();
|
|
4032
3474
|
const signer = new SignerSol(sdkSigner);
|
|
4033
3475
|
signer.onInteraction = (interaction) => {
|
|
@@ -4043,102 +3485,21 @@ async function _createSolSigner(ctx, sessionId) {
|
|
|
4043
3485
|
return signer;
|
|
4044
3486
|
}
|
|
4045
3487
|
|
|
4046
|
-
// src/connector/chains/zcash.ts
|
|
4047
|
-
var import_hwk_adapter_core10 = require("@onekeyfe/hwk-adapter-core");
|
|
4048
|
-
|
|
4049
|
-
// src/signer/SignerZcash.ts
|
|
4050
|
-
var SignerZcash = class {
|
|
4051
|
-
// eslint-disable-next-line no-useless-constructor, no-empty-function
|
|
4052
|
-
constructor(_sdk) {
|
|
4053
|
-
this._sdk = _sdk;
|
|
4054
|
-
}
|
|
4055
|
-
/** GET_VK: UFVK string (default) or raw 96-byte Orchard FVK. */
|
|
4056
|
-
async getFullViewingKey(derivationPath, options) {
|
|
4057
|
-
const action = this._sdk.getFullViewingKey(derivationPath, options);
|
|
4058
|
-
return deviceActionToPromise(
|
|
4059
|
-
action,
|
|
4060
|
-
this.onInteraction,
|
|
4061
|
-
void 0,
|
|
4062
|
-
this.onRegisterCanceller
|
|
4063
|
-
);
|
|
4064
|
-
}
|
|
4065
|
-
/** GET_SHIELDED_ADDRESS: single-Orchard-receiver UA for a 5-level transparent path. */
|
|
4066
|
-
async getShieldedAddress(derivationPath, options) {
|
|
4067
|
-
const action = this._sdk.getShieldedAddress(derivationPath, options);
|
|
4068
|
-
return deviceActionToPromise(
|
|
4069
|
-
action,
|
|
4070
|
-
this.onInteraction,
|
|
4071
|
-
void 0,
|
|
4072
|
-
this.onRegisterCanceller
|
|
4073
|
-
);
|
|
4074
|
-
}
|
|
4075
|
-
};
|
|
4076
|
-
|
|
4077
|
-
// src/connector/chains/zcash.ts
|
|
4078
|
-
async function zcashGetFullViewingKey(ctx, sessionId, params) {
|
|
4079
|
-
const signer = await _createZcashSigner(ctx, sessionId);
|
|
4080
|
-
const path = normalizePath(params.path);
|
|
4081
|
-
const mode = params.mode ?? "ufvk";
|
|
4082
|
-
try {
|
|
4083
|
-
const result = await signer.getFullViewingKey(path, { mode });
|
|
4084
|
-
if (result.mode === "ufvk") {
|
|
4085
|
-
return { path: params.path, mode, ufvk: result.fullViewingKey };
|
|
4086
|
-
}
|
|
4087
|
-
return { path: params.path, mode, orchardFvk: (0, import_hwk_adapter_core10.bytesToHex)(result.fullViewingKey) };
|
|
4088
|
-
} catch (err) {
|
|
4089
|
-
ctx.invalidateSession(sessionId);
|
|
4090
|
-
throw ctx.wrapError(err);
|
|
4091
|
-
} finally {
|
|
4092
|
-
ctx.clearCanceller(sessionId);
|
|
4093
|
-
}
|
|
4094
|
-
}
|
|
4095
|
-
async function zcashGetShieldedAddress(ctx, sessionId, params) {
|
|
4096
|
-
const signer = await _createZcashSigner(ctx, sessionId);
|
|
4097
|
-
const path = normalizePath(params.path);
|
|
4098
|
-
try {
|
|
4099
|
-
const result = await signer.getShieldedAddress(path, {
|
|
4100
|
-
checkOnDevice: params.showOnDevice ?? false
|
|
4101
|
-
});
|
|
4102
|
-
return { address: result.address, path: params.path };
|
|
4103
|
-
} catch (err) {
|
|
4104
|
-
ctx.invalidateSession(sessionId);
|
|
4105
|
-
throw ctx.wrapError(err);
|
|
4106
|
-
} finally {
|
|
4107
|
-
ctx.clearCanceller(sessionId);
|
|
4108
|
-
}
|
|
4109
|
-
}
|
|
4110
|
-
async function _createZcashSigner(ctx, sessionId) {
|
|
4111
|
-
const dmk = await ctx.getOrCreateDmk();
|
|
4112
|
-
const { SignerZcashBuilder } = await ctx.importLedgerKit("@ledgerhq/device-signer-kit-zcash");
|
|
4113
|
-
const sdkSigner = new SignerZcashBuilder({ dmk, sessionId }).build();
|
|
4114
|
-
const signer = new SignerZcash(sdkSigner);
|
|
4115
|
-
signer.onInteraction = (interaction) => {
|
|
4116
|
-
debugLog("[LedgerConnector] zcash.onInteraction:", interaction);
|
|
4117
|
-
ctx.emit("ui-event", {
|
|
4118
|
-
type: collapseSignerInteraction(interaction),
|
|
4119
|
-
payload: { sessionId }
|
|
4120
|
-
});
|
|
4121
|
-
};
|
|
4122
|
-
signer.onRegisterCanceller = (cancel) => ctx.registerCanceller(sessionId, cancel);
|
|
4123
|
-
return signer;
|
|
4124
|
-
}
|
|
4125
|
-
|
|
4126
3488
|
// src/connector/chains/tron.ts
|
|
4127
|
-
var
|
|
3489
|
+
var import_hwk_adapter_core12 = require("@onekeyfe/hwk-adapter-core");
|
|
4128
3490
|
var import_hw_app_trx = __toESM(require("@ledgerhq/hw-app-trx"));
|
|
4129
3491
|
|
|
4130
3492
|
// src/connector/chains/legacyChainCall.ts
|
|
4131
|
-
var
|
|
3493
|
+
var import_hwk_adapter_core11 = require("@onekeyfe/hwk-adapter-core");
|
|
4132
3494
|
|
|
4133
3495
|
// src/app/AppManager.ts
|
|
4134
3496
|
var import_device_management_kit2 = require("@ledgerhq/device-management-kit");
|
|
4135
|
-
var
|
|
3497
|
+
var import_hwk_adapter_core10 = require("@onekeyfe/hwk-adapter-core");
|
|
4136
3498
|
var APP_NAME_MAP = {
|
|
4137
3499
|
ETH: "Ethereum",
|
|
4138
3500
|
BTC: "Bitcoin",
|
|
4139
3501
|
SOL: "Solana",
|
|
4140
3502
|
TRX: "Tron",
|
|
4141
|
-
ZEC: "Zcash",
|
|
4142
3503
|
XRP: "XRP",
|
|
4143
3504
|
ADA: "Cardano",
|
|
4144
3505
|
DOT: "Polkadot",
|
|
@@ -4250,9 +3611,9 @@ var AppManager = class {
|
|
|
4250
3611
|
);
|
|
4251
3612
|
let code;
|
|
4252
3613
|
if (errorCode === "6807" || /unknown application/i.test(message)) {
|
|
4253
|
-
code =
|
|
3614
|
+
code = import_hwk_adapter_core10.HardwareErrorCode.AppNotInstalled;
|
|
4254
3615
|
} else if (errorCode === "5501" || dmkErr._tag === "ActionRefusedError") {
|
|
4255
|
-
code =
|
|
3616
|
+
code = import_hwk_adapter_core10.HardwareErrorCode.UserRejected;
|
|
4256
3617
|
}
|
|
4257
3618
|
throw Object.assign(new Error(`Failed to open "${appName}"`), {
|
|
4258
3619
|
_tag: ERROR_TAG.OpenAppCommand,
|
|
@@ -4313,14 +3674,14 @@ async function withLegacyChainCall(ctx, sessionId, options, action) {
|
|
|
4313
3674
|
const onAppOpenPrompt = () => {
|
|
4314
3675
|
openAppPromptShown = true;
|
|
4315
3676
|
ctx.emit("ui-event", {
|
|
4316
|
-
type:
|
|
3677
|
+
type: import_hwk_adapter_core11.EConnectorInteraction.ConfirmOpenApp,
|
|
4317
3678
|
payload: { sessionId }
|
|
4318
3679
|
});
|
|
4319
3680
|
};
|
|
4320
3681
|
const closeOpenAppUiIfShown = () => {
|
|
4321
3682
|
if (openAppPromptShown) {
|
|
4322
3683
|
ctx.emit("ui-event", {
|
|
4323
|
-
type:
|
|
3684
|
+
type: import_hwk_adapter_core11.EConnectorInteraction.InteractionComplete,
|
|
4324
3685
|
payload: { sessionId }
|
|
4325
3686
|
});
|
|
4326
3687
|
openAppPromptShown = false;
|
|
@@ -4341,7 +3702,7 @@ async function withLegacyChainCall(ctx, sessionId, options, action) {
|
|
|
4341
3702
|
let confirmEmitted = false;
|
|
4342
3703
|
if (needsConfirmation) {
|
|
4343
3704
|
ctx.emit("ui-event", {
|
|
4344
|
-
type:
|
|
3705
|
+
type: import_hwk_adapter_core11.EConnectorInteraction.ConfirmOnDevice,
|
|
4345
3706
|
payload: { sessionId }
|
|
4346
3707
|
});
|
|
4347
3708
|
confirmEmitted = true;
|
|
@@ -4351,7 +3712,7 @@ async function withLegacyChainCall(ctx, sessionId, options, action) {
|
|
|
4351
3712
|
} finally {
|
|
4352
3713
|
if (confirmEmitted || openAppPromptShown) {
|
|
4353
3714
|
ctx.emit("ui-event", {
|
|
4354
|
-
type:
|
|
3715
|
+
type: import_hwk_adapter_core11.EConnectorInteraction.InteractionComplete,
|
|
4355
3716
|
payload: { sessionId }
|
|
4356
3717
|
});
|
|
4357
3718
|
openAppPromptShown = false;
|
|
@@ -4439,7 +3800,7 @@ async function tronSignTransaction(ctx, sessionId, params) {
|
|
|
4439
3800
|
if (!params.rawTxHex) {
|
|
4440
3801
|
throw Object.assign(
|
|
4441
3802
|
new Error("TRON signing requires a protobuf-encoded raw transaction hex (rawTxHex)."),
|
|
4442
|
-
{ code:
|
|
3803
|
+
{ code: import_hwk_adapter_core12.HardwareErrorCode.InvalidParams }
|
|
4443
3804
|
);
|
|
4444
3805
|
}
|
|
4445
3806
|
const path = normalizePath(params.path);
|
|
@@ -4652,7 +4013,7 @@ var DeviceApps = class {
|
|
|
4652
4013
|
seTargetId: v.seTargetId,
|
|
4653
4014
|
mcuTargetId: v.mcuTargetId,
|
|
4654
4015
|
seVersion: v.seVersion,
|
|
4655
|
-
seFlagsHex:
|
|
4016
|
+
seFlagsHex: bytesToHex2(v.seFlags),
|
|
4656
4017
|
mcuSephVersion: v.mcuSephVersion,
|
|
4657
4018
|
mcuBootloaderVersion: v.mcuBootloaderVersion,
|
|
4658
4019
|
hwVersion: v.hwVersion
|
|
@@ -4726,7 +4087,7 @@ var DeviceApps = class {
|
|
|
4726
4087
|
}
|
|
4727
4088
|
}
|
|
4728
4089
|
};
|
|
4729
|
-
function
|
|
4090
|
+
function bytesToHex2(bytes) {
|
|
4730
4091
|
if (!bytes) return "";
|
|
4731
4092
|
return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
4732
4093
|
}
|
|
@@ -4769,11 +4130,10 @@ var METHOD_PREFIX_TO_APP_NAME = {
|
|
|
4769
4130
|
evm: "Ethereum",
|
|
4770
4131
|
btc: "Bitcoin",
|
|
4771
4132
|
sol: "Solana",
|
|
4772
|
-
tron: "Tron"
|
|
4773
|
-
zcash: "Zcash"
|
|
4133
|
+
tron: "Tron"
|
|
4774
4134
|
};
|
|
4775
4135
|
var HARDWARE_ERROR_CODE_VALUES = new Set(
|
|
4776
|
-
Object.values(
|
|
4136
|
+
Object.values(import_hwk_adapter_core13.HardwareErrorCode).filter((value) => typeof value === "number")
|
|
4777
4137
|
);
|
|
4778
4138
|
var BLE_CONNECT_SCAN_TIMEOUT_MS = 1500;
|
|
4779
4139
|
var LEDGER_RELAY_ALLOWED_ROOT_DOMAINS = ["onekeytest.com", "onekey.com"];
|
|
@@ -4810,8 +4170,6 @@ async function defaultLedgerKitImporter(pkg) {
|
|
|
4810
4170
|
return import("@ledgerhq/device-signer-kit-bitcoin");
|
|
4811
4171
|
case "@ledgerhq/device-signer-kit-solana":
|
|
4812
4172
|
return import("@ledgerhq/device-signer-kit-solana");
|
|
4813
|
-
case "@ledgerhq/device-signer-kit-zcash":
|
|
4814
|
-
return import("@ledgerhq/device-signer-kit-zcash");
|
|
4815
4173
|
case "@ledgerhq/context-module":
|
|
4816
4174
|
return import("@ledgerhq/context-module");
|
|
4817
4175
|
default:
|
|
@@ -4922,7 +4280,7 @@ var LedgerConnectorBase = class {
|
|
|
4922
4280
|
async searchDevices() {
|
|
4923
4281
|
const dm = await this._getDeviceManager();
|
|
4924
4282
|
const descriptors = await this._discoverDescriptors(dm);
|
|
4925
|
-
const resolvedDescriptors = descriptors.filter((d) => !(0,
|
|
4283
|
+
const resolvedDescriptors = descriptors.filter((d) => !(0, import_hwk_adapter_core13.isKnownNonTargetHardwareVendor)(d, "ledger")).map((d) => ({
|
|
4926
4284
|
descriptor: d,
|
|
4927
4285
|
connectId: this._resolveConnectId(d)
|
|
4928
4286
|
}));
|
|
@@ -4970,7 +4328,7 @@ var LedgerConnectorBase = class {
|
|
|
4970
4328
|
`Ledger BLE connect did not return within ${HANG_CEILING_MS / 6e4}min \u2014 DMK hang fallback.`
|
|
4971
4329
|
);
|
|
4972
4330
|
err._tag = ERROR_TAG.BlePairingTimeout;
|
|
4973
|
-
err.code =
|
|
4331
|
+
err.code = import_hwk_adapter_core13.HardwareErrorCode.BlePairingTimeout;
|
|
4974
4332
|
reject(err);
|
|
4975
4333
|
}, HANG_CEILING_MS);
|
|
4976
4334
|
});
|
|
@@ -5003,7 +4361,7 @@ var LedgerConnectorBase = class {
|
|
|
5003
4361
|
"Ledger device is not currently advertising. Wake up and unlock the device, keep it nearby, then try again."
|
|
5004
4362
|
);
|
|
5005
4363
|
err._tag = ERROR_TAG.DeviceNotAdvertising;
|
|
5006
|
-
err.code =
|
|
4364
|
+
err.code = import_hwk_adapter_core13.HardwareErrorCode.DeviceNotFound;
|
|
5007
4365
|
throw err;
|
|
5008
4366
|
};
|
|
5009
4367
|
const doConnect = async (path) => {
|
|
@@ -5067,7 +4425,7 @@ var LedgerConnectorBase = class {
|
|
|
5067
4425
|
"Ledger Bluetooth pairing failed. Make sure the device is unlocked and nearby, then try again."
|
|
5068
4426
|
);
|
|
5069
4427
|
wrapped._tag = ERROR_TAG.BleGattBondingFailed;
|
|
5070
|
-
wrapped.code =
|
|
4428
|
+
wrapped.code = import_hwk_adapter_core13.HardwareErrorCode.BlePairingTimeout;
|
|
5071
4429
|
wrapped.originalError = err;
|
|
5072
4430
|
throw wrapped;
|
|
5073
4431
|
}
|
|
@@ -5145,7 +4503,7 @@ var LedgerConnectorBase = class {
|
|
|
5145
4503
|
this._unwatchSessionState(sessionId);
|
|
5146
4504
|
this._signerManager?.invalidate(sessionId);
|
|
5147
4505
|
this._cancellers.get(sessionId)?.({
|
|
5148
|
-
code:
|
|
4506
|
+
code: import_hwk_adapter_core13.HardwareErrorCode.DeviceDisconnected,
|
|
5149
4507
|
tag: "DeviceDisconnected",
|
|
5150
4508
|
message: "Device disconnected"
|
|
5151
4509
|
});
|
|
@@ -5169,9 +4527,9 @@ var LedgerConnectorBase = class {
|
|
|
5169
4527
|
if (isAppStuckByApdu(err)) {
|
|
5170
4528
|
return {
|
|
5171
4529
|
success: false,
|
|
5172
|
-
error: (0,
|
|
4530
|
+
error: (0, import_hwk_adapter_core13.serializeConnectorError)(
|
|
5173
4531
|
Object.assign(new Error("Ledger app is unresponsive"), {
|
|
5174
|
-
code:
|
|
4532
|
+
code: import_hwk_adapter_core13.HardwareErrorCode.DeviceAppStuck,
|
|
5175
4533
|
_tag: ERROR_TAG.DeviceAppStuck,
|
|
5176
4534
|
originalError: err
|
|
5177
4535
|
})
|
|
@@ -5181,16 +4539,16 @@ var LedgerConnectorBase = class {
|
|
|
5181
4539
|
if (isTransportStuck(err)) {
|
|
5182
4540
|
return {
|
|
5183
4541
|
success: false,
|
|
5184
|
-
error: (0,
|
|
4542
|
+
error: (0, import_hwk_adapter_core13.serializeConnectorError)(
|
|
5185
4543
|
Object.assign(new Error("Device communication interrupted, please retry"), {
|
|
5186
|
-
code:
|
|
4544
|
+
code: import_hwk_adapter_core13.HardwareErrorCode.TransportError,
|
|
5187
4545
|
_tag: ERROR_TAG.DeviceTransportStuck,
|
|
5188
4546
|
originalError: err
|
|
5189
4547
|
})
|
|
5190
4548
|
)
|
|
5191
4549
|
};
|
|
5192
4550
|
}
|
|
5193
|
-
return { success: false, error: (0,
|
|
4551
|
+
return { success: false, error: (0, import_hwk_adapter_core13.serializeConnectorError)(err) };
|
|
5194
4552
|
}
|
|
5195
4553
|
}
|
|
5196
4554
|
async _dispatch(sessionId, method, params) {
|
|
@@ -5229,11 +4587,6 @@ var LedgerConnectorBase = class {
|
|
|
5229
4587
|
return solSignTransaction(ctx, sessionId, params);
|
|
5230
4588
|
case "solSignMessage":
|
|
5231
4589
|
return solSignMessage(ctx, sessionId, params);
|
|
5232
|
-
// ZCASH
|
|
5233
|
-
case "zcashGetFullViewingKey":
|
|
5234
|
-
return zcashGetFullViewingKey(ctx, sessionId, params);
|
|
5235
|
-
case "zcashGetShieldedAddress":
|
|
5236
|
-
return zcashGetShieldedAddress(ctx, sessionId, params);
|
|
5237
4590
|
// TRON
|
|
5238
4591
|
case "tronGetAddress":
|
|
5239
4592
|
return tronGetAddress(ctx, sessionId, params);
|
|
@@ -5258,7 +4611,7 @@ var LedgerConnectorBase = class {
|
|
|
5258
4611
|
try {
|
|
5259
4612
|
return await apps.install(p.appName, ({ progress }) => {
|
|
5260
4613
|
ctx.emit("ui-event", {
|
|
5261
|
-
type:
|
|
4614
|
+
type: import_hwk_adapter_core13.EConnectorInteraction.AppInstallProgress,
|
|
5262
4615
|
payload: {
|
|
5263
4616
|
sessionId,
|
|
5264
4617
|
appName: p.appName,
|
|
@@ -5563,7 +4916,7 @@ var LedgerConnectorBase = class {
|
|
|
5563
4916
|
* at every catch site. Falls through unchanged for unknown methods.
|
|
5564
4917
|
*/
|
|
5565
4918
|
_ctxForMethod(method) {
|
|
5566
|
-
const prefix = /^(evm|btc|sol|tron
|
|
4919
|
+
const prefix = /^(evm|btc|sol|tron)/.exec(method)?.[1];
|
|
5567
4920
|
const defaultAppName = prefix ? METHOD_PREFIX_TO_APP_NAME[prefix] : void 0;
|
|
5568
4921
|
if (!defaultAppName) return this._ctx;
|
|
5569
4922
|
return {
|
|
@@ -5608,7 +4961,6 @@ var LedgerConnectorBase = class {
|
|
|
5608
4961
|
SignerEth,
|
|
5609
4962
|
SignerManager,
|
|
5610
4963
|
SignerSol,
|
|
5611
|
-
SignerZcash,
|
|
5612
4964
|
debugLog,
|
|
5613
4965
|
deviceActionToPromise,
|
|
5614
4966
|
isDeviceLockedError,
|