@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.mjs
CHANGED
|
@@ -6,41 +6,30 @@ import {
|
|
|
6
6
|
DeviceJobQueue,
|
|
7
7
|
EConnectorInteraction,
|
|
8
8
|
HardwareErrorCode as HardwareErrorCode3,
|
|
9
|
-
InteractionRegistry,
|
|
10
|
-
SDK,
|
|
11
9
|
TypedEventEmitter,
|
|
12
10
|
UI_REQUEST,
|
|
13
11
|
UI_REQUEST_PREEMPTED_TAG,
|
|
14
12
|
UiRequestRegistry,
|
|
15
|
-
canReplayHardwareMethodAfterTransportFailure,
|
|
16
13
|
createHwkError,
|
|
17
14
|
deriveDeviceFingerprint,
|
|
18
15
|
failure as failure2,
|
|
19
|
-
isHardwareInteractionId,
|
|
20
|
-
isHwkRecoveryHint,
|
|
21
|
-
operationMayHaveCompletedParams,
|
|
22
16
|
rehydrateConnectorError,
|
|
23
|
-
requestBleDeviceSelection,
|
|
24
|
-
requestSaveDeviceBinding,
|
|
25
|
-
resolveSearchTargetReusePolicy,
|
|
26
17
|
success
|
|
27
18
|
} from "@onekeyfe/hwk-adapter-core";
|
|
28
19
|
|
|
29
20
|
// src/errors.ts
|
|
30
|
-
import {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
|
|
21
|
+
import { HardwareErrorCode, enrichErrorMessage } from "@onekeyfe/hwk-adapter-core";
|
|
22
|
+
var MULTIPLE_USB_LEDGER_DEVICES_ERROR_MESSAGE = "Multiple Ledger USB devices are connected. Please connect only one Ledger device and try again.";
|
|
23
|
+
function createMultipleUsbLedgerDevicesError() {
|
|
24
|
+
return Object.assign(new Error(MULTIPLE_USB_LEDGER_DEVICES_ERROR_MESSAGE), {
|
|
25
|
+
code: HardwareErrorCode.DeviceOneDeviceOnly
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
function ledgerFailure(code, error, appName, tag, params) {
|
|
37
29
|
const payload = { error, code };
|
|
38
30
|
if (appName !== void 0) payload.appName = appName;
|
|
39
31
|
if (tag !== void 0) payload._tag = tag;
|
|
40
32
|
if (params !== void 0) payload.params = params;
|
|
41
|
-
const resolvedOrigin = origin ?? defaultOriginForCode(code);
|
|
42
|
-
if (resolvedOrigin !== void 0) payload.origin = resolvedOrigin;
|
|
43
|
-
payload.recovery = recovery ?? defaultRecoveryForCode(code);
|
|
44
33
|
return { success: false, payload };
|
|
45
34
|
}
|
|
46
35
|
var LOCKED_ERROR_CODES = /* @__PURE__ */ new Set(["5515", "21781", "6982", "27010", "5303", "21251"]);
|
|
@@ -224,6 +213,7 @@ function isBlePairingFailureError(err) {
|
|
|
224
213
|
return false;
|
|
225
214
|
}
|
|
226
215
|
var CONNECTION_LEVEL_TAGS = /* @__PURE__ */ new Set([
|
|
216
|
+
ERROR_TAG.DeviceLocked,
|
|
227
217
|
ERROR_TAG.DeviceNotAdvertising,
|
|
228
218
|
ERROR_TAG.BlePairingTimeout,
|
|
229
219
|
ERROR_TAG.BleGattBondingFailed,
|
|
@@ -458,21 +448,11 @@ function mapLedgerError(err, opts) {
|
|
|
458
448
|
}
|
|
459
449
|
const errAppName = err && typeof err === "object" ? err.appName : void 0;
|
|
460
450
|
const appName = errAppName ?? opts?.defaultAppName;
|
|
461
|
-
return {
|
|
462
|
-
code,
|
|
463
|
-
message: enrichErrorMessage(code, originalMessage),
|
|
464
|
-
origin: defaultOriginForCode(code),
|
|
465
|
-
appName
|
|
466
|
-
};
|
|
451
|
+
return { code, message: enrichErrorMessage(code, originalMessage), appName };
|
|
467
452
|
}
|
|
468
453
|
|
|
469
454
|
// src/adapter/methods/allNetworkGetAddress.ts
|
|
470
|
-
import {
|
|
471
|
-
HardwareErrorCode as HardwareErrorCode2,
|
|
472
|
-
failure,
|
|
473
|
-
resolveHardwareOperationTarget,
|
|
474
|
-
runAllNetworkGetAddress
|
|
475
|
-
} from "@onekeyfe/hwk-adapter-core";
|
|
455
|
+
import { HardwareErrorCode as HardwareErrorCode2, failure, runAllNetworkGetAddress } from "@onekeyfe/hwk-adapter-core";
|
|
476
456
|
|
|
477
457
|
// src/utils/sdkEventBus.ts
|
|
478
458
|
var listeners = /* @__PURE__ */ new Set();
|
|
@@ -529,81 +509,57 @@ var LEDGER_BTC_NETWORK_COIN_MAP = {
|
|
|
529
509
|
var LEDGER_UNSUPPORTED_ALLNETWORK_NETWORKS = /* @__PURE__ */ new Set(["doge", "dogecoin"]);
|
|
530
510
|
function createAllNetworkGetAddress({
|
|
531
511
|
callChain,
|
|
532
|
-
getChainFingerprint
|
|
533
|
-
retainInteraction,
|
|
534
|
-
errorToFailure
|
|
512
|
+
getChainFingerprint
|
|
535
513
|
}) {
|
|
536
514
|
return async function allNetworkGetAddress(connectId, _deviceId, params) {
|
|
537
|
-
debugLog("[LedgerAdapter][REQ]", {
|
|
538
|
-
method: "allNetworkGetAddress",
|
|
539
|
-
connectId,
|
|
540
|
-
itemCount: params.bundle.length
|
|
541
|
-
});
|
|
542
|
-
const target = resolveHardwareOperationTarget(connectId, params.interactionId, "ledger");
|
|
543
|
-
if (!target.success) return target;
|
|
544
|
-
const effectiveTargetId = target.payload.targetId ?? "";
|
|
545
|
-
let releaseInteractionRetention;
|
|
546
|
-
try {
|
|
547
|
-
releaseInteractionRetention = target.payload.interactionId ? retainInteraction(target.payload.interactionId) : void 0;
|
|
548
|
-
} catch (error) {
|
|
549
|
-
return errorToFailure(error);
|
|
550
|
-
}
|
|
515
|
+
debugLog("[LedgerAdapter][REQ]", { method: "allNetworkGetAddress", connectId, params });
|
|
551
516
|
const installContext = {};
|
|
552
517
|
const commonParams = {
|
|
553
|
-
autoInstallApp: params.autoInstallApp
|
|
554
|
-
interactionId: target.payload.interactionId,
|
|
555
|
-
knownConnections: params.knownConnections,
|
|
556
|
-
extra: params.extra,
|
|
557
|
-
allowDeviceSelection: params.allowDeviceSelection
|
|
518
|
+
autoInstallApp: params.autoInstallApp
|
|
558
519
|
};
|
|
559
520
|
const chainFingerprints = /* @__PURE__ */ new Map();
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
method,
|
|
574
|
-
item,
|
|
575
|
-
commonParams,
|
|
576
|
-
installContext
|
|
577
|
-
);
|
|
578
|
-
},
|
|
579
|
-
attachIdentity: async ({ item, chain, payload }) => attachLedgerIdentity(
|
|
580
|
-
getChainFingerprint,
|
|
581
|
-
effectiveTargetId,
|
|
521
|
+
const result = await runAllNetworkGetAddress({
|
|
522
|
+
connectId,
|
|
523
|
+
deviceId: _deviceId,
|
|
524
|
+
params,
|
|
525
|
+
normalizeItem: normalizeLedgerAllNetworkItem,
|
|
526
|
+
buildUnsupportedNetworkResponse: (item) => isUnsupportedLedgerAllNetworkNetwork(item) ? buildUnsupportedNetworkResponse(item) : void 0,
|
|
527
|
+
callItem: async ({ method, chain, item }) => {
|
|
528
|
+
const itemDeviceId = getItemDeviceId(item) ?? chainFingerprints.get(chain) ?? "";
|
|
529
|
+
return callAllNetworkMethod(
|
|
530
|
+
callChain,
|
|
531
|
+
connectId,
|
|
532
|
+
itemDeviceId,
|
|
533
|
+
method,
|
|
582
534
|
item,
|
|
583
|
-
|
|
584
|
-
payload,
|
|
585
|
-
chainFingerprints,
|
|
535
|
+
commonParams,
|
|
586
536
|
installContext
|
|
587
|
-
)
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
}
|
|
537
|
+
);
|
|
538
|
+
},
|
|
539
|
+
attachIdentity: async ({ item, chain, payload }) => attachLedgerIdentity(
|
|
540
|
+
getChainFingerprint,
|
|
541
|
+
connectId,
|
|
542
|
+
item,
|
|
543
|
+
chain,
|
|
544
|
+
payload,
|
|
545
|
+
chainFingerprints
|
|
546
|
+
),
|
|
547
|
+
shouldAbortBundle: isTopLevelAllNetworkFailure,
|
|
548
|
+
buildTopLevelFailure: (response) => {
|
|
549
|
+
const code = response.payload?.code ?? HardwareErrorCode2.DeviceMismatch;
|
|
550
|
+
return failure(
|
|
551
|
+
code,
|
|
552
|
+
response.payload?.error ?? "All-network get-address aborted",
|
|
553
|
+
response.payload?.params
|
|
554
|
+
);
|
|
555
|
+
}
|
|
556
|
+
});
|
|
557
|
+
debugLog("[LedgerAdapter][RES]", {
|
|
558
|
+
method: "allNetworkGetAddress",
|
|
559
|
+
success: result.success,
|
|
560
|
+
payload: result
|
|
561
|
+
});
|
|
562
|
+
return result;
|
|
607
563
|
};
|
|
608
564
|
}
|
|
609
565
|
function isTopLevelAllNetworkFailure(response) {
|
|
@@ -611,7 +567,7 @@ function isTopLevelAllNetworkFailure(response) {
|
|
|
611
567
|
return false;
|
|
612
568
|
}
|
|
613
569
|
const code = response.payload?.code;
|
|
614
|
-
return code === HardwareErrorCode2.DeviceMismatch || code === HardwareErrorCode2.
|
|
570
|
+
return code === HardwareErrorCode2.DeviceMismatch || code === HardwareErrorCode2.UserAborted || code === HardwareErrorCode2.UserRejected;
|
|
615
571
|
}
|
|
616
572
|
function getItemDeviceId(item) {
|
|
617
573
|
const { deviceId } = item;
|
|
@@ -641,13 +597,8 @@ function normalizeLedgerAllNetworkItem(method, item) {
|
|
|
641
597
|
const coin = LEDGER_BTC_NETWORK_COIN_MAP[item.network];
|
|
642
598
|
return coin ? { ...item, coin } : item;
|
|
643
599
|
}
|
|
644
|
-
async function attachLedgerIdentity(getChainFingerprint, connectId, item, chain, payload, chainFingerprints
|
|
645
|
-
const fingerprint = getItemDeviceId(item) || chainFingerprints.get(chain) || await bootstrapChainFingerprint(
|
|
646
|
-
getChainFingerprint,
|
|
647
|
-
context.connection?.connectId ?? connectId,
|
|
648
|
-
chain,
|
|
649
|
-
context
|
|
650
|
-
);
|
|
600
|
+
async function attachLedgerIdentity(getChainFingerprint, connectId, item, chain, payload, chainFingerprints) {
|
|
601
|
+
const fingerprint = getItemDeviceId(item) || chainFingerprints.get(chain) || await bootstrapChainFingerprint(getChainFingerprint, connectId, chain);
|
|
651
602
|
if (!fingerprint) {
|
|
652
603
|
return buildFingerprintBootstrapFailure(item, chain);
|
|
653
604
|
}
|
|
@@ -668,8 +619,8 @@ async function attachLedgerIdentity(getChainFingerprint, connectId, item, chain,
|
|
|
668
619
|
}
|
|
669
620
|
};
|
|
670
621
|
}
|
|
671
|
-
async function bootstrapChainFingerprint(getChainFingerprint, connectId, chain
|
|
672
|
-
const response = await getChainFingerprint(connectId, chain
|
|
622
|
+
async function bootstrapChainFingerprint(getChainFingerprint, connectId, chain) {
|
|
623
|
+
const response = await getChainFingerprint(connectId, chain);
|
|
673
624
|
return response.success ? response.payload : "";
|
|
674
625
|
}
|
|
675
626
|
function buildFingerprintBootstrapFailure(item, chain) {
|
|
@@ -774,27 +725,8 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
774
725
|
constructor(connector, options) {
|
|
775
726
|
this.vendor = "ledger";
|
|
776
727
|
this.emitter = new TypedEventEmitter();
|
|
777
|
-
this._interactions = new InteractionRegistry({
|
|
778
|
-
vendor: "ledger",
|
|
779
|
-
onEnded: (interaction, reason) => {
|
|
780
|
-
const binding = this._pendingInteractionBindings.get(interaction.interactionId);
|
|
781
|
-
if (binding?.selectedConnection?.requestId === this._bindingSelectionRequestId) {
|
|
782
|
-
this._finishBleBinding("cancelled");
|
|
783
|
-
}
|
|
784
|
-
this._pendingInteractionBindings.delete(interaction.interactionId);
|
|
785
|
-
this.emitter.emit(SDK.INTERACTION_ENDED, {
|
|
786
|
-
type: SDK.INTERACTION_ENDED,
|
|
787
|
-
payload: { interactionId: interaction.interactionId, reason }
|
|
788
|
-
});
|
|
789
|
-
if (reason === "timeout") {
|
|
790
|
-
void this._releaseInteractionConnection(interaction);
|
|
791
|
-
}
|
|
792
|
-
}
|
|
793
|
-
});
|
|
794
728
|
this._discoveredDevices = /* @__PURE__ */ new Map();
|
|
795
729
|
this._sessions = /* @__PURE__ */ new Map();
|
|
796
|
-
this._pendingInteractionBindings = /* @__PURE__ */ new Map();
|
|
797
|
-
this._verifiedBleReconnectTargets = /* @__PURE__ */ new Map();
|
|
798
730
|
this._uiRegistry = new UiRequestRegistry();
|
|
799
731
|
// BTC App rejects account index >= 100 unless display=true. Cached per
|
|
800
732
|
// adapter instance: first 100+ path asks the user once via UI request,
|
|
@@ -808,30 +740,10 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
808
740
|
this._deviceAuthenticityQueueTail = Promise.resolve();
|
|
809
741
|
// Shared across concurrent callers — only `cancel()` aborts.
|
|
810
742
|
this._doConnectAbortController = null;
|
|
811
|
-
this._unsettledConnectorOperations = /* @__PURE__ */ new Map();
|
|
812
|
-
this._connectorIdleWaiters = /* @__PURE__ */ new Set();
|
|
813
|
-
this._resetPromise = null;
|
|
814
|
-
this._stateGeneration = 0;
|
|
815
|
-
this._connectorTeardownTail = Promise.resolve();
|
|
816
|
-
this._pendingConnectorTeardowns = 0;
|
|
817
|
-
this._activeInteractionJobs = /* @__PURE__ */ new Set();
|
|
818
|
-
this._pendingInteractionDisconnects = /* @__PURE__ */ new Set();
|
|
819
743
|
this._installProgressLastEmittedValue = -Infinity;
|
|
820
744
|
this.allNetworkGetAddress = createAllNetworkGetAddress({
|
|
821
745
|
callChain: this.callChain.bind(this),
|
|
822
|
-
getChainFingerprint:
|
|
823
|
-
try {
|
|
824
|
-
const fingerprint = await this._computeChainFingerprint(
|
|
825
|
-
chain,
|
|
826
|
-
(method, params) => this.connectorCall(connectId, method, params, void 0, void 0, void 0, context)
|
|
827
|
-
);
|
|
828
|
-
return success(fingerprint);
|
|
829
|
-
} catch (error) {
|
|
830
|
-
return this.errorToFailure(error);
|
|
831
|
-
}
|
|
832
|
-
},
|
|
833
|
-
retainInteraction: (interactionId) => this._interactions.retain(interactionId),
|
|
834
|
-
errorToFailure: (error) => this.errorToFailure(error)
|
|
746
|
+
getChainFingerprint: (connectId, chain) => this.getChainFingerprint(connectId, "", chain)
|
|
835
747
|
});
|
|
836
748
|
// ---------------------------------------------------------------------------
|
|
837
749
|
// Private helpers
|
|
@@ -841,7 +753,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
841
753
|
*
|
|
842
754
|
* - If a session already exists for the given connectId, reuse it.
|
|
843
755
|
* - If ANY session exists (Ledger IDs are ephemeral), reuse it.
|
|
844
|
-
* - Otherwise: search →
|
|
756
|
+
* - Otherwise: search → exactly 1 USB device auto-connects; multiple or none throws.
|
|
845
757
|
*/
|
|
846
758
|
// Mutex for ensureConnected — prevents concurrent calls from establishing duplicate connections
|
|
847
759
|
this._connectingPromise = null;
|
|
@@ -858,12 +770,6 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
858
770
|
});
|
|
859
771
|
};
|
|
860
772
|
this.deviceDisconnectHandler = (data) => {
|
|
861
|
-
const activeInteraction = this._interactions.findActiveByConnectionKey(data.connectId);
|
|
862
|
-
if (activeInteraction && this._activeInteractionJobs.has(activeInteraction.interactionId)) {
|
|
863
|
-
this._pendingInteractionDisconnects.add(activeInteraction.interactionId);
|
|
864
|
-
} else {
|
|
865
|
-
this._interactions.endByConnectionKey(data.connectId, "disconnect");
|
|
866
|
-
}
|
|
867
773
|
this._discoveredDevices.delete(data.connectId);
|
|
868
774
|
this._sessions.delete(data.connectId);
|
|
869
775
|
this.emitter.emit(DEVICE.DISCONNECT, {
|
|
@@ -920,28 +826,11 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
920
826
|
this._jobQueue = new DeviceJobQueue();
|
|
921
827
|
this.registerEventListeners();
|
|
922
828
|
}
|
|
923
|
-
_finishBleBinding(status) {
|
|
924
|
-
const selectionRequestId = this._bindingSelectionRequestId;
|
|
925
|
-
this._bindingSelectionRequestId = void 0;
|
|
926
|
-
if (selectionRequestId)
|
|
927
|
-
this.emitter.emit(UI_REQUEST.DEVICE_BINDING_STATUS, {
|
|
928
|
-
type: UI_REQUEST.DEVICE_BINDING_STATUS,
|
|
929
|
-
payload: { selectionRequestId, status }
|
|
930
|
-
});
|
|
931
|
-
}
|
|
932
|
-
_isBleConnection() {
|
|
933
|
-
return isLedgerBleConnectionType(this._activeConnectionType ?? this.connector.connectionType);
|
|
934
|
-
}
|
|
935
829
|
// Transport
|
|
936
830
|
get activeTransport() {
|
|
937
|
-
return this.
|
|
831
|
+
return isLedgerBleConnectionType(this.connector.connectionType) ? "ble" : "hid";
|
|
938
832
|
}
|
|
939
833
|
getAvailableTransports() {
|
|
940
|
-
if (this.connector.availableTransports) {
|
|
941
|
-
return this.connector.availableTransports.map(
|
|
942
|
-
(transport) => transport === "ble" ? "ble" : "hid"
|
|
943
|
-
);
|
|
944
|
-
}
|
|
945
834
|
return this.activeTransport ? [this.activeTransport] : [];
|
|
946
835
|
}
|
|
947
836
|
// Connector is bound at construction; switching requires a new adapter.
|
|
@@ -958,39 +847,21 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
958
847
|
* The next operation will re-discover and re-connect automatically.
|
|
959
848
|
*/
|
|
960
849
|
resetState() {
|
|
961
|
-
void this._resetStateAndDisconnectSessions();
|
|
962
|
-
}
|
|
963
|
-
_resetStateAndDisconnectSessions() {
|
|
964
|
-
if (this._resetPromise) return this._resetPromise;
|
|
965
|
-
const sessionIds = new Set(this._sessions.values());
|
|
966
|
-
this._stateGeneration += 1;
|
|
967
|
-
this._finishBleBinding("cancelled");
|
|
968
|
-
this._interactions.endAll("runtime-reset");
|
|
969
|
-
this._doConnectAbortController?.abort();
|
|
970
850
|
this._discoveredDevices.clear();
|
|
971
851
|
this._sessions.clear();
|
|
972
|
-
this._verifiedBleReconnectTargets.clear();
|
|
973
852
|
this._connectingPromise = null;
|
|
974
|
-
this._doConnectAbortController = null;
|
|
975
853
|
this._uiRegistry.reset();
|
|
976
854
|
this._jobQueue.clear();
|
|
977
855
|
this._btcHighIndexConfirmedThisSession = false;
|
|
978
|
-
const resetPromise = this._runConnectorTeardown(async () => {
|
|
979
|
-
for (const sessionId of sessionIds) {
|
|
980
|
-
await this.connector.disconnect(sessionId).catch(() => void 0);
|
|
981
|
-
}
|
|
982
|
-
});
|
|
983
|
-
this._resetPromise = resetPromise;
|
|
984
|
-
return resetPromise.finally(() => {
|
|
985
|
-
if (this._resetPromise === resetPromise) {
|
|
986
|
-
this._resetPromise = null;
|
|
987
|
-
}
|
|
988
|
-
});
|
|
989
856
|
}
|
|
990
857
|
async dispose() {
|
|
991
|
-
|
|
858
|
+
this._uiRegistry.reset();
|
|
859
|
+
this._jobQueue.clear();
|
|
992
860
|
this.unregisterEventListeners();
|
|
993
861
|
this.connector.reset();
|
|
862
|
+
this._discoveredDevices.clear();
|
|
863
|
+
this._sessions.clear();
|
|
864
|
+
this._btcHighIndexConfirmedThisSession = false;
|
|
994
865
|
this.emitter.removeAllListeners();
|
|
995
866
|
}
|
|
996
867
|
uiResponse(response) {
|
|
@@ -1000,32 +871,17 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1000
871
|
// Device management
|
|
1001
872
|
// ---------------------------------------------------------------------------
|
|
1002
873
|
async searchDevices(options) {
|
|
1003
|
-
return this._searchDevices(options);
|
|
1004
|
-
}
|
|
1005
|
-
async _searchDevices(options, signal) {
|
|
1006
874
|
debugLog("[LedgerAdapter][REQ]", { method: "searchDevices", params: options });
|
|
1007
875
|
try {
|
|
1008
876
|
if (options?.resetSession) {
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
if (signal) _LedgerAdapter._throwIfAborted(signal);
|
|
1015
|
-
const stateGeneration = this._stateGeneration;
|
|
1016
|
-
const devices = await this.connector.searchDevices(
|
|
1017
|
-
options?.transportType ? {
|
|
1018
|
-
transportType: options.transportType,
|
|
1019
|
-
waitForAll: options.waitForAllTransports
|
|
1020
|
-
} : void 0
|
|
1021
|
-
);
|
|
1022
|
-
if (signal) _LedgerAdapter._throwIfAborted(signal);
|
|
1023
|
-
if (stateGeneration !== this._stateGeneration) {
|
|
1024
|
-
throw createHwkError({
|
|
1025
|
-
code: HardwareErrorCode3.UserAborted,
|
|
1026
|
-
message: "Ledger discovery was reset"
|
|
1027
|
-
});
|
|
877
|
+
this._doConnectAbortController?.abort();
|
|
878
|
+
this._sessions.clear();
|
|
879
|
+
this._connectingPromise = null;
|
|
880
|
+
this._doConnectAbortController = null;
|
|
881
|
+
this._btcHighIndexConfirmedThisSession = false;
|
|
1028
882
|
}
|
|
883
|
+
await this._ensureDevicePermission();
|
|
884
|
+
const devices = await this.connector.searchDevices();
|
|
1029
885
|
this._discoveredDevices.clear();
|
|
1030
886
|
for (const d of devices) {
|
|
1031
887
|
if (d.connectId) {
|
|
@@ -1033,7 +889,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1033
889
|
}
|
|
1034
890
|
}
|
|
1035
891
|
if (this._discoveredDevices.size === 0) {
|
|
1036
|
-
await this._ensureDevicePermission(
|
|
892
|
+
await this._ensureDevicePermission();
|
|
1037
893
|
}
|
|
1038
894
|
const result = Array.from(this._discoveredDevices.values());
|
|
1039
895
|
debugLog("[LedgerAdapter][RES]", {
|
|
@@ -1052,172 +908,41 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1052
908
|
throw err;
|
|
1053
909
|
}
|
|
1054
910
|
}
|
|
1055
|
-
async searchDeviceTargets(options) {
|
|
1056
|
-
const devices = await this.searchDevices(options);
|
|
1057
|
-
return devices.map((device) => ({
|
|
1058
|
-
searchTargetId: device.connectId,
|
|
1059
|
-
searchTargetReusePolicy: resolveSearchTargetReusePolicy(device),
|
|
1060
|
-
vendor: "ledger",
|
|
1061
|
-
connectionType: device.connectionType,
|
|
1062
|
-
kind: "physical",
|
|
1063
|
-
label: device.label,
|
|
1064
|
-
model: device.model,
|
|
1065
|
-
modelName: device.modelName,
|
|
1066
|
-
serialNumber: device.serialNumber
|
|
1067
|
-
}));
|
|
1068
|
-
}
|
|
1069
|
-
async listConnectionTargets(options) {
|
|
1070
|
-
const targets = await this.searchDeviceTargets(options);
|
|
1071
|
-
return targets.map(({ searchTargetId, ...target }) => ({
|
|
1072
|
-
...target,
|
|
1073
|
-
targetId: searchTargetId
|
|
1074
|
-
}));
|
|
1075
|
-
}
|
|
1076
911
|
// USB single-session invariant: evict all sessions, best-effort (see connectDevice).
|
|
1077
|
-
async _evictAllSessions(
|
|
1078
|
-
this._interactions.endAll("explicit", preserveInteractionId);
|
|
912
|
+
async _evictAllSessions() {
|
|
1079
913
|
if (this._sessions.size === 0) return;
|
|
1080
914
|
const stale = [...this._sessions.values()];
|
|
1081
915
|
this._sessions.clear();
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
} catch {
|
|
1087
|
-
}
|
|
916
|
+
for (const sid of stale) {
|
|
917
|
+
try {
|
|
918
|
+
await this.connector.disconnect(sid);
|
|
919
|
+
} catch {
|
|
1088
920
|
}
|
|
1089
|
-
}
|
|
921
|
+
}
|
|
1090
922
|
}
|
|
1091
923
|
static _createDeviceBusyError(method) {
|
|
1092
924
|
return Object.assign(new Error(`Ledger device is busy while calling ${method}`), {
|
|
1093
925
|
code: HardwareErrorCode3.DeviceBusy
|
|
1094
926
|
});
|
|
1095
927
|
}
|
|
1096
|
-
async connectDevice(
|
|
1097
|
-
const connected = await this._connectTarget(searchTargetId);
|
|
1098
|
-
if (!connected.success) return connected;
|
|
1099
|
-
return this._createInteraction(searchTargetId, connected.payload);
|
|
1100
|
-
}
|
|
1101
|
-
async acquireInteraction(connectId, context) {
|
|
1102
|
-
try {
|
|
1103
|
-
return await this._jobQueue.enqueue(
|
|
1104
|
-
connectId || "__ledger_acquire__",
|
|
1105
|
-
async (signal) => {
|
|
1106
|
-
const transport = this._isBleConnection() ? "ble" : "usb";
|
|
1107
|
-
const hint = context.knownConnections?.find(
|
|
1108
|
-
(connection) => connection.transport === transport
|
|
1109
|
-
);
|
|
1110
|
-
const target = hint && hint.transport !== "qr" ? hint.connectId : connectId;
|
|
1111
|
-
await this._ensureDevicePermission(target, void 0, signal);
|
|
1112
|
-
const attempt = {
|
|
1113
|
-
...context,
|
|
1114
|
-
extra: context.extra ? { ...context.extra } : void 0,
|
|
1115
|
-
previousConnectId: target
|
|
1116
|
-
};
|
|
1117
|
-
try {
|
|
1118
|
-
const resolvedConnectId = await this.ensureConnected(
|
|
1119
|
-
target,
|
|
1120
|
-
signal,
|
|
1121
|
-
true,
|
|
1122
|
-
void 0,
|
|
1123
|
-
attempt
|
|
1124
|
-
);
|
|
1125
|
-
_LedgerAdapter._throwIfAborted(signal);
|
|
1126
|
-
const result = this._createInteraction(connectId, resolvedConnectId);
|
|
1127
|
-
if (result.success && attempt.selectedConnection) {
|
|
1128
|
-
this._pendingInteractionBindings.set(result.payload, attempt);
|
|
1129
|
-
}
|
|
1130
|
-
return result;
|
|
1131
|
-
} catch (error) {
|
|
1132
|
-
this._finishBleBinding(signal.aborted ? "cancelled" : "failed");
|
|
1133
|
-
throw error;
|
|
1134
|
-
}
|
|
1135
|
-
},
|
|
1136
|
-
{
|
|
1137
|
-
label: "acquireInteraction",
|
|
1138
|
-
rejectIfBusy: true,
|
|
1139
|
-
busyError: _LedgerAdapter._createDeviceBusyError("acquireInteraction")
|
|
1140
|
-
}
|
|
1141
|
-
);
|
|
1142
|
-
} catch (error) {
|
|
1143
|
-
return this.errorToFailure(error);
|
|
1144
|
-
}
|
|
1145
|
-
}
|
|
1146
|
-
_createInteraction(searchTargetId, resolvedConnectId) {
|
|
1147
|
-
this._interactions.endByConnectionKey(resolvedConnectId, "explicit");
|
|
1148
|
-
const sessionId = this._sessions.get(resolvedConnectId);
|
|
1149
|
-
if (sessionId) this._interactions.endByConnectionKey(sessionId, "explicit");
|
|
1150
|
-
const device = this._discoveredDevices.get(resolvedConnectId) ?? {
|
|
1151
|
-
vendor: "ledger",
|
|
1152
|
-
model: "unknown",
|
|
1153
|
-
firmwareVersion: "",
|
|
1154
|
-
deviceId: "",
|
|
1155
|
-
connectId: resolvedConnectId,
|
|
1156
|
-
connectionType: this.connector.connectionType
|
|
1157
|
-
};
|
|
1158
|
-
const interaction = this._interactions.create({
|
|
1159
|
-
searchTargetId,
|
|
1160
|
-
connectId: resolvedConnectId,
|
|
1161
|
-
device,
|
|
1162
|
-
connectionKeys: [this._sessions.get(resolvedConnectId) ?? ""]
|
|
1163
|
-
});
|
|
1164
|
-
return success(interaction.interactionId);
|
|
1165
|
-
}
|
|
1166
|
-
async _connectTarget(connectId, preserveInteractionId, signal) {
|
|
928
|
+
async connectDevice(connectId) {
|
|
1167
929
|
debugLog("[LedgerAdapter][REQ]", { method: "connectDevice", connectId, params: { connectId } });
|
|
1168
930
|
try {
|
|
1169
|
-
this.
|
|
1170
|
-
const discoveredType = this._discoveredDevices.get(connectId)?.connectionType;
|
|
1171
|
-
if (discoveredType === "usb" || discoveredType === "ble") {
|
|
1172
|
-
this._activeConnectionType = discoveredType;
|
|
1173
|
-
}
|
|
1174
|
-
if (this._isBleConnection() && !connectId) {
|
|
931
|
+
if (isLedgerBleConnectionType(this.connector.connectionType) && !connectId) {
|
|
1175
932
|
throw Object.assign(new Error("Ledger BLE connectId is required."), {
|
|
1176
933
|
code: HardwareErrorCode3.DeviceNotFound
|
|
1177
934
|
});
|
|
1178
935
|
}
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
if (this.connector.availableTransports && this.connector.availableTransports.length > 1) {
|
|
1182
|
-
await this._evictAllSessions(preserveInteractionId);
|
|
1183
|
-
} else if (this._isBleConnection()) {
|
|
1184
|
-
const previousSessionId = this._sessions.get(connectId);
|
|
1185
|
-
this._interactions.endByConnectionKey(connectId, "explicit", preserveInteractionId);
|
|
1186
|
-
if (previousSessionId) {
|
|
1187
|
-
this._interactions.endByConnectionKey(
|
|
1188
|
-
previousSessionId,
|
|
1189
|
-
"explicit",
|
|
1190
|
-
preserveInteractionId
|
|
1191
|
-
);
|
|
1192
|
-
this._sessions.delete(connectId);
|
|
1193
|
-
await this.connector.disconnect(previousSessionId).catch(() => void 0);
|
|
1194
|
-
}
|
|
1195
|
-
} else {
|
|
1196
|
-
await this._evictAllSessions(preserveInteractionId);
|
|
1197
|
-
}
|
|
1198
|
-
if (signal) _LedgerAdapter._throwIfAborted(signal);
|
|
1199
|
-
const stateGeneration = this._stateGeneration;
|
|
1200
|
-
const releaseOperation = this._retainConnectorOperation(`connect:${connectId}`);
|
|
1201
|
-
let session;
|
|
1202
|
-
try {
|
|
1203
|
-
session = this.connector.availableTransports?.length ? await this.connector.connect(connectId, {
|
|
1204
|
-
transportType: this._activeConnectionType ?? "usb"
|
|
1205
|
-
}) : await this.connector.connect(connectId);
|
|
1206
|
-
if (signal?.aborted || stateGeneration !== this._stateGeneration) {
|
|
1207
|
-
await this.connector.disconnect(session.sessionId).catch(() => void 0);
|
|
1208
|
-
throw Object.assign(new Error("Ledger connection aborted"), {
|
|
1209
|
-
code: HardwareErrorCode3.UserAborted
|
|
1210
|
-
});
|
|
1211
|
-
}
|
|
1212
|
-
} finally {
|
|
1213
|
-
releaseOperation();
|
|
936
|
+
if (!isLedgerBleConnectionType(this.connector.connectionType)) {
|
|
937
|
+
await this._evictAllSessions();
|
|
1214
938
|
}
|
|
1215
|
-
|
|
1216
|
-
this.
|
|
939
|
+
await this._ensureDevicePermission(connectId);
|
|
940
|
+
const session = await this.connector.connect(connectId);
|
|
941
|
+
this._sessions.set(connectId, session.sessionId);
|
|
1217
942
|
if (session.deviceInfo) {
|
|
1218
|
-
this._discoveredDevices.set(
|
|
943
|
+
this._discoveredDevices.set(connectId, session.deviceInfo);
|
|
1219
944
|
}
|
|
1220
|
-
const result = success(
|
|
945
|
+
const result = success(connectId);
|
|
1221
946
|
debugLog("[LedgerAdapter][RES]", { method: "connectDevice", success: true, payload: result });
|
|
1222
947
|
return result;
|
|
1223
948
|
} catch (err) {
|
|
@@ -1230,60 +955,30 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1230
955
|
return failureResult;
|
|
1231
956
|
}
|
|
1232
957
|
}
|
|
1233
|
-
async
|
|
1234
|
-
const interaction = this._interactions.find(interactionId);
|
|
1235
|
-
if (!interaction) {
|
|
1236
|
-
this._interactions.resolve(interactionId);
|
|
1237
|
-
return;
|
|
1238
|
-
}
|
|
1239
|
-
const endedInteraction = this._interactions.end(interactionId, "explicit");
|
|
1240
|
-
if (!endedInteraction) return;
|
|
1241
|
-
const { connectId } = interaction;
|
|
958
|
+
async disconnectDevice(connectId) {
|
|
1242
959
|
debugLog("[LedgerAdapter][REQ]", {
|
|
1243
|
-
method: "
|
|
960
|
+
method: "disconnectDevice",
|
|
1244
961
|
connectId,
|
|
1245
962
|
params: { connectId }
|
|
1246
963
|
});
|
|
1247
964
|
try {
|
|
1248
|
-
|
|
1249
|
-
|
|
965
|
+
const sessionId = this._sessions.get(connectId);
|
|
966
|
+
if (sessionId) {
|
|
967
|
+
await this.connector.disconnect(sessionId);
|
|
968
|
+
this._sessions.delete(connectId);
|
|
969
|
+
}
|
|
970
|
+
debugLog("[LedgerAdapter][RES]", { method: "disconnectDevice", success: true });
|
|
1250
971
|
} catch (err) {
|
|
1251
972
|
const e = err;
|
|
1252
973
|
debugLog("[LedgerAdapter][RES]", {
|
|
1253
|
-
method: "
|
|
974
|
+
method: "disconnectDevice",
|
|
1254
975
|
success: false,
|
|
1255
976
|
error: { message: e?.message, _tag: e?._tag, code: e?.code ?? e?.errorCode }
|
|
1256
977
|
});
|
|
1257
978
|
throw err;
|
|
1258
979
|
}
|
|
1259
980
|
}
|
|
1260
|
-
async
|
|
1261
|
-
const sessionIds = /* @__PURE__ */ new Set();
|
|
1262
|
-
for (const [connectId, sessionId] of this._sessions) {
|
|
1263
|
-
if (connectId === interaction.connectId || interaction.connectionKeys.includes(connectId) || interaction.connectionKeys.includes(sessionId)) {
|
|
1264
|
-
this._sessions.delete(connectId);
|
|
1265
|
-
sessionIds.add(sessionId);
|
|
1266
|
-
}
|
|
1267
|
-
}
|
|
1268
|
-
for (const sessionId of sessionIds) {
|
|
1269
|
-
await this._runConnectorTeardown(
|
|
1270
|
-
() => this.connector.disconnect(sessionId).catch(() => void 0)
|
|
1271
|
-
);
|
|
1272
|
-
}
|
|
1273
|
-
}
|
|
1274
|
-
async _releaseLostInteractionConnection(interactionId) {
|
|
1275
|
-
const endedInteraction = this._interactions.end(interactionId, "disconnect");
|
|
1276
|
-
if (!endedInteraction) return;
|
|
1277
|
-
this._discoveredDevices.delete(endedInteraction.connectId);
|
|
1278
|
-
await this._releaseInteractionConnection(endedInteraction);
|
|
1279
|
-
}
|
|
1280
|
-
async getDeviceInfo(connectIdOrInteractionId, deviceId) {
|
|
1281
|
-
let connectId;
|
|
1282
|
-
try {
|
|
1283
|
-
connectId = isHardwareInteractionId(connectIdOrInteractionId) ? this._interactions.resolve(connectIdOrInteractionId).connectId : connectIdOrInteractionId;
|
|
1284
|
-
} catch (error) {
|
|
1285
|
-
return this.errorToFailure(error);
|
|
1286
|
-
}
|
|
981
|
+
async getDeviceInfo(connectId, deviceId) {
|
|
1287
982
|
debugLog("[LedgerAdapter][REQ]", {
|
|
1288
983
|
method: "getDeviceInfo",
|
|
1289
984
|
connectId,
|
|
@@ -1322,7 +1017,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1322
1017
|
}
|
|
1323
1018
|
}
|
|
1324
1019
|
getSupportedChains() {
|
|
1325
|
-
return ["evm", "btc", "sol", "tron"
|
|
1020
|
+
return ["evm", "btc", "sol", "tron"];
|
|
1326
1021
|
}
|
|
1327
1022
|
// ---------------------------------------------------------------------------
|
|
1328
1023
|
// Chain call helper
|
|
@@ -1358,21 +1053,13 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1358
1053
|
if (params && typeof params === "object") {
|
|
1359
1054
|
const {
|
|
1360
1055
|
autoInstallApp,
|
|
1361
|
-
interactionId,
|
|
1362
1056
|
passphraseState: _passphraseState,
|
|
1363
1057
|
useEmptyPassphrase: _useEmptyPassphrase,
|
|
1364
|
-
knownConnections,
|
|
1365
|
-
extra,
|
|
1366
|
-
allowDeviceSelection,
|
|
1367
1058
|
...rest
|
|
1368
1059
|
} = params;
|
|
1369
1060
|
return {
|
|
1370
1061
|
commonParams: {
|
|
1371
|
-
autoInstallApp: typeof autoInstallApp === "boolean" ? autoInstallApp : void 0
|
|
1372
|
-
interactionId: typeof interactionId === "string" ? interactionId : void 0,
|
|
1373
|
-
knownConnections,
|
|
1374
|
-
extra,
|
|
1375
|
-
allowDeviceSelection: typeof allowDeviceSelection === "boolean" ? allowDeviceSelection : void 0
|
|
1062
|
+
autoInstallApp: typeof autoInstallApp === "boolean" ? autoInstallApp : void 0
|
|
1376
1063
|
},
|
|
1377
1064
|
rest
|
|
1378
1065
|
};
|
|
@@ -1548,27 +1235,6 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1548
1235
|
);
|
|
1549
1236
|
}
|
|
1550
1237
|
// ---------------------------------------------------------------------------
|
|
1551
|
-
// Zcash chain methods (viewing key + shielded address reads; Zcash app >= 3.8.0)
|
|
1552
|
-
// ---------------------------------------------------------------------------
|
|
1553
|
-
zcashGetFullViewingKey(connectId, deviceId, params) {
|
|
1554
|
-
return this.callChainWithMergedParams(
|
|
1555
|
-
connectId,
|
|
1556
|
-
deviceId,
|
|
1557
|
-
"zcash",
|
|
1558
|
-
"zcashGetFullViewingKey",
|
|
1559
|
-
params
|
|
1560
|
-
);
|
|
1561
|
-
}
|
|
1562
|
-
zcashGetShieldedAddress(connectId, deviceId, params) {
|
|
1563
|
-
return this.callChainWithMergedParams(
|
|
1564
|
-
connectId,
|
|
1565
|
-
deviceId,
|
|
1566
|
-
"zcash",
|
|
1567
|
-
"zcashGetShieldedAddress",
|
|
1568
|
-
params
|
|
1569
|
-
);
|
|
1570
|
-
}
|
|
1571
|
-
// ---------------------------------------------------------------------------
|
|
1572
1238
|
// App management — OS-level Ledger app install / list. Bypasses fingerprint
|
|
1573
1239
|
// and chain-handler dispatch; installApp progress is forwarded to the adapter
|
|
1574
1240
|
// emitter via 'ui-event' AppInstallProgress events.
|
|
@@ -1657,7 +1323,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1657
1323
|
);
|
|
1658
1324
|
}
|
|
1659
1325
|
await this.connector.configure({ ledgerGenuineCheckWebSocketUrl: relayUrl });
|
|
1660
|
-
|
|
1326
|
+
this.resetState();
|
|
1661
1327
|
}
|
|
1662
1328
|
const result = await this.connectorCall(connectId, "getDeviceGenuineCheck", {});
|
|
1663
1329
|
if (!result.isGenuine) {
|
|
@@ -1683,10 +1349,10 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1683
1349
|
if (relayUrl) {
|
|
1684
1350
|
try {
|
|
1685
1351
|
await this.connector.configure?.({ ledgerGenuineCheckWebSocketUrl: void 0 });
|
|
1686
|
-
|
|
1352
|
+
this.resetState();
|
|
1687
1353
|
} catch {
|
|
1688
1354
|
this.connector.reset();
|
|
1689
|
-
|
|
1355
|
+
this.resetState();
|
|
1690
1356
|
}
|
|
1691
1357
|
}
|
|
1692
1358
|
}
|
|
@@ -1709,36 +1375,13 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1709
1375
|
}
|
|
1710
1376
|
}, 2e3);
|
|
1711
1377
|
this._uiRegistry.cancel();
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
let interactionId;
|
|
1715
|
-
if (isHardwareInteractionId(connectId)) {
|
|
1716
|
-
interactionId = connectId;
|
|
1717
|
-
} else if (!connectId && isHardwareInteractionId(activeJobId)) {
|
|
1718
|
-
interactionId = activeJobId;
|
|
1719
|
-
}
|
|
1720
|
-
let resolvedConnectId = connectId;
|
|
1721
|
-
if (interactionId) {
|
|
1722
|
-
try {
|
|
1723
|
-
resolvedConnectId = this._interactions.resolve(interactionId).connectId;
|
|
1724
|
-
} catch {
|
|
1725
|
-
resolvedConnectId = void 0;
|
|
1726
|
-
}
|
|
1727
|
-
}
|
|
1728
|
-
const interactionForPhysicalId = !interactionId && connectId ? this._interactions.findActiveByConnectionKey(connectId) : void 0;
|
|
1729
|
-
const queueKey = interactionId ?? (activeJobId === connectId ? connectId : interactionForPhysicalId?.interactionId) ?? connectId;
|
|
1730
|
-
const pendingInteractionId = interactionId ?? interactionForPhysicalId?.interactionId;
|
|
1731
|
-
if (!connectId) this._pendingInteractionBindings.clear();
|
|
1732
|
-
else if (pendingInteractionId) {
|
|
1733
|
-
this._pendingInteractionBindings.delete(pendingInteractionId);
|
|
1734
|
-
}
|
|
1735
|
-
if (queueKey) {
|
|
1736
|
-
this._jobQueue.cancelActiveAndPending(queueKey, userAbortReason);
|
|
1378
|
+
if (connectId) {
|
|
1379
|
+
this._jobQueue.cancelActiveAndPending(connectId, userAbortReason);
|
|
1737
1380
|
} else {
|
|
1738
1381
|
this._jobQueue.cancelActiveAndPending(void 0, userAbortReason);
|
|
1739
1382
|
}
|
|
1740
|
-
if (
|
|
1741
|
-
const sessionId = this._sessions.get(
|
|
1383
|
+
if (connectId) {
|
|
1384
|
+
const sessionId = this._sessions.get(connectId) ?? connectId;
|
|
1742
1385
|
void this.connector.cancel(sessionId);
|
|
1743
1386
|
} else {
|
|
1744
1387
|
for (const sid of this._sessions.values()) void this.connector.cancel(sid);
|
|
@@ -1750,83 +1393,40 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1750
1393
|
// ---------------------------------------------------------------------------
|
|
1751
1394
|
// Chain fingerprint
|
|
1752
1395
|
// ---------------------------------------------------------------------------
|
|
1753
|
-
/** A non-empty deviceId is an expected chain fingerprint, not a transport identifier. */
|
|
1754
1396
|
async getChainFingerprint(connectId, deviceId, chain) {
|
|
1755
1397
|
try {
|
|
1756
1398
|
const fingerprint = await this._computeChainFingerprint(
|
|
1757
1399
|
chain,
|
|
1758
1400
|
(method, params) => this.connectorCall(connectId, method, params, void 0, deviceId)
|
|
1759
1401
|
);
|
|
1760
|
-
if (deviceId) {
|
|
1761
|
-
if (fingerprint !== deviceId) {
|
|
1762
|
-
return failure2(
|
|
1763
|
-
HardwareErrorCode3.DeviceMismatch,
|
|
1764
|
-
formatDeviceMismatchError(deviceId, fingerprint)
|
|
1765
|
-
);
|
|
1766
|
-
}
|
|
1767
|
-
if (isHardwareInteractionId(connectId)) {
|
|
1768
|
-
const interaction = this._interactions.resolve(connectId);
|
|
1769
|
-
await this._publishVerifiedBleBinding(
|
|
1770
|
-
interaction.connectId,
|
|
1771
|
-
chain,
|
|
1772
|
-
fingerprint,
|
|
1773
|
-
void 0,
|
|
1774
|
-
connectId
|
|
1775
|
-
);
|
|
1776
|
-
}
|
|
1777
|
-
}
|
|
1778
1402
|
return success(fingerprint);
|
|
1779
1403
|
} catch (err) {
|
|
1780
1404
|
debugError("[LedgerAdapter] getChainFingerprint error:", chain, err);
|
|
1781
1405
|
return this.errorToFailure(err);
|
|
1782
1406
|
}
|
|
1783
1407
|
}
|
|
1784
|
-
/**
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
const acknowledged = await requestSaveDeviceBinding(
|
|
1789
|
-
this.emitter,
|
|
1790
|
-
this._uiRegistry,
|
|
1791
|
-
{
|
|
1792
|
-
selectionRequestId: binding.selectedConnection.requestId,
|
|
1793
|
-
connection: { transport: "ble", connectId },
|
|
1794
|
-
identity: { vendor: "ledger", type: "chainFingerprint", chain, value: fingerprint },
|
|
1795
|
-
extra: binding.extra
|
|
1796
|
-
},
|
|
1797
|
-
signal
|
|
1798
|
-
);
|
|
1799
|
-
if (this._bindingSelectionRequestId === binding.selectedConnection.requestId) {
|
|
1800
|
-
this._bindingSelectionRequestId = void 0;
|
|
1801
|
-
}
|
|
1802
|
-
if (interactionId) {
|
|
1803
|
-
this._interactions.resolve(interactionId);
|
|
1804
|
-
this._pendingInteractionBindings.delete(interactionId);
|
|
1805
|
-
}
|
|
1806
|
-
if (acknowledged) return;
|
|
1807
|
-
this.emitter.emit(DEVICE.LEDGER_CONNECTION_VERIFIED, {
|
|
1808
|
-
type: DEVICE.LEDGER_CONNECTION_VERIFIED,
|
|
1809
|
-
payload: {
|
|
1810
|
-
previousConnectId: binding.previousConnectId ?? previousConnectId,
|
|
1811
|
-
connectId,
|
|
1812
|
-
chain,
|
|
1813
|
-
fingerprint,
|
|
1814
|
-
extra: binding.extra,
|
|
1815
|
-
selectionRequestId: binding.selectedConnection.requestId
|
|
1816
|
-
}
|
|
1817
|
-
});
|
|
1818
|
-
}
|
|
1819
|
-
/** Verify on the acquired session without re-entering the job queue. */
|
|
1408
|
+
/**
|
|
1409
|
+
* Verify fingerprint using an existing sessionId directly.
|
|
1410
|
+
* Safe to call inside connectorCall without causing queue deadlock.
|
|
1411
|
+
*/
|
|
1820
1412
|
async _verifyDeviceFingerprintWithSession(sessionId, deviceId, chain) {
|
|
1821
1413
|
if (!deviceId) return { success: true };
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1414
|
+
try {
|
|
1415
|
+
const fingerprint = await this._computeChainFingerprint(
|
|
1416
|
+
chain,
|
|
1417
|
+
(method, params) => this._callConnector(sessionId, method, params)
|
|
1418
|
+
);
|
|
1419
|
+
if (fingerprint === deviceId) {
|
|
1420
|
+
return { success: true };
|
|
1421
|
+
}
|
|
1422
|
+
return { success: false, expected: deviceId, actual: fingerprint };
|
|
1423
|
+
} catch (err) {
|
|
1424
|
+
const mapped = mapLedgerError(err);
|
|
1425
|
+
if (mapped.code === HardwareErrorCode3.WrongApp || mapped.code === HardwareErrorCode3.DeviceLocked) {
|
|
1426
|
+
return { success: true };
|
|
1427
|
+
}
|
|
1428
|
+
throw err;
|
|
1828
1429
|
}
|
|
1829
|
-
return { success: false, expected: deviceId, actual: fingerprint };
|
|
1830
1430
|
}
|
|
1831
1431
|
/**
|
|
1832
1432
|
* Compute the chain fingerprint via a caller-supplied call strategy.
|
|
@@ -1855,8 +1455,6 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1855
1455
|
address = (await callMethod("solGetAddress", { path, showOnDevice: false })).address;
|
|
1856
1456
|
} else if (chain === "tron") {
|
|
1857
1457
|
address = (await callMethod("tronGetAddress", { path, showOnDevice: false })).address;
|
|
1858
|
-
} else if (chain === "zcash") {
|
|
1859
|
-
address = (await callMethod("zcashGetShieldedAddress", { path, showOnDevice: false })).address;
|
|
1860
1458
|
} else {
|
|
1861
1459
|
throw new Error(`Unsupported chain for fingerprint: ${chain}`);
|
|
1862
1460
|
}
|
|
@@ -1986,17 +1584,16 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1986
1584
|
// Layer 1 entry. Caller signal only races the outer awaiter; the shared
|
|
1987
1585
|
// `_doConnect` runs under its own internal controller so caller A's cancel
|
|
1988
1586
|
// doesn't kill caller B's await.
|
|
1989
|
-
async ensureConnected(connectId, signal, allowUsbEphemeralFallback = false
|
|
1587
|
+
async ensureConnected(connectId, signal, allowUsbEphemeralFallback = false) {
|
|
1990
1588
|
if (signal.aborted) _LedgerAdapter._throwIfAborted(signal);
|
|
1991
|
-
this.
|
|
1992
|
-
if (this._isBleConnection() && !connectId && !allowUsbEphemeralFallback) {
|
|
1589
|
+
if (isLedgerBleConnectionType(this.connector.connectionType) && !connectId) {
|
|
1993
1590
|
throw Object.assign(new Error("Ledger BLE connectId is required."), {
|
|
1994
1591
|
code: HardwareErrorCode3.DeviceNotFound
|
|
1995
1592
|
});
|
|
1996
1593
|
}
|
|
1997
1594
|
if (connectId && this._sessions.has(connectId)) return connectId;
|
|
1998
1595
|
if (!connectId && this._sessions.size > 0) {
|
|
1999
|
-
if (!this.
|
|
1596
|
+
if (!isLedgerBleConnectionType(this.connector.connectionType) && this._sessions.size > 1) {
|
|
2000
1597
|
throw Object.assign(
|
|
2001
1598
|
new Error(
|
|
2002
1599
|
"Ledger USB session invariant violated: more than one session is active. Please reconnect the device."
|
|
@@ -2006,24 +1603,15 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
2006
1603
|
}
|
|
2007
1604
|
return this._sessions.keys().next().value;
|
|
2008
1605
|
}
|
|
2009
|
-
if (!this._connectingPromise
|
|
2010
|
-
|
|
2011
|
-
this._doConnectAbortController
|
|
2012
|
-
const innerSignal = controller.signal;
|
|
1606
|
+
if (!this._connectingPromise) {
|
|
1607
|
+
this._doConnectAbortController = new AbortController();
|
|
1608
|
+
const innerSignal = this._doConnectAbortController.signal;
|
|
2013
1609
|
this._connectingPromise = (async () => {
|
|
2014
1610
|
try {
|
|
2015
|
-
return await this._doConnect(
|
|
2016
|
-
innerSignal,
|
|
2017
|
-
connectId,
|
|
2018
|
-
allowUsbEphemeralFallback,
|
|
2019
|
-
preserveInteractionId,
|
|
2020
|
-
context
|
|
2021
|
-
);
|
|
1611
|
+
return await this._doConnect(innerSignal, connectId, allowUsbEphemeralFallback);
|
|
2022
1612
|
} finally {
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
this._doConnectAbortController = null;
|
|
2026
|
-
}
|
|
1613
|
+
this._connectingPromise = null;
|
|
1614
|
+
this._doConnectAbortController = null;
|
|
2027
1615
|
}
|
|
2028
1616
|
})();
|
|
2029
1617
|
}
|
|
@@ -2032,49 +1620,22 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
2032
1620
|
// Layer 1 main loop — the ONLY place in SDK that emits unlock dialog.
|
|
2033
1621
|
// Bounded by MAX_DOCONNECT_CONFIRMS — after N Confirms with no progress,
|
|
2034
1622
|
// throw DeviceNotFound so the user is kicked out of the loop.
|
|
2035
|
-
async _doConnect(internalSignal, targetConnectId, allowUsbEphemeralFallback = false
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
)
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
preserveInteractionId,
|
|
2051
|
-
context,
|
|
2052
|
-
internalSignal
|
|
2053
|
-
);
|
|
2054
|
-
}
|
|
2055
|
-
this._activeConnectionType = "ble";
|
|
2056
|
-
const knownBle = context?.knownConnections?.find(
|
|
2057
|
-
(connection) => connection.transport === "ble"
|
|
2058
|
-
);
|
|
2059
|
-
if (knownBle?.transport === "ble") {
|
|
2060
|
-
return this._connectDeviceOrThrow(
|
|
2061
|
-
knownBle.connectId,
|
|
2062
|
-
preserveInteractionId,
|
|
2063
|
-
internalSignal
|
|
2064
|
-
);
|
|
1623
|
+
async _doConnect(internalSignal, targetConnectId, allowUsbEphemeralFallback = false) {
|
|
1624
|
+
if (isLedgerBleConnectionType(this.connector.connectionType) && targetConnectId) {
|
|
1625
|
+
try {
|
|
1626
|
+
return await this._connectDeviceOrThrow(targetConnectId);
|
|
1627
|
+
} catch (err) {
|
|
1628
|
+
if (!isDeviceLockedError(err) && !isDeviceNotAdvertisingError(err) && !isDeviceDisconnectedError(err)) {
|
|
1629
|
+
throw err;
|
|
1630
|
+
}
|
|
1631
|
+
this._discoveredDevices.delete(targetConnectId);
|
|
1632
|
+
if (isDeviceDisconnectedError(err)) {
|
|
1633
|
+
try {
|
|
1634
|
+
this.connector.reset?.();
|
|
1635
|
+
} catch {
|
|
1636
|
+
}
|
|
1637
|
+
}
|
|
2065
1638
|
}
|
|
2066
|
-
const bleDevices = await this._searchDevices({ transportType: "ble" }, internalSignal);
|
|
2067
|
-
return this._connectFirstOrSelect(
|
|
2068
|
-
bleDevices,
|
|
2069
|
-
void 0,
|
|
2070
|
-
allowUsbEphemeralFallback,
|
|
2071
|
-
preserveInteractionId,
|
|
2072
|
-
context,
|
|
2073
|
-
internalSignal
|
|
2074
|
-
);
|
|
2075
|
-
}
|
|
2076
|
-
if (this._isBleConnection() && targetConnectId) {
|
|
2077
|
-
return this._connectDeviceOrThrow(targetConnectId, preserveInteractionId, internalSignal);
|
|
2078
1639
|
}
|
|
2079
1640
|
let confirms = 0;
|
|
2080
1641
|
while (!internalSignal.aborted) {
|
|
@@ -2082,28 +1643,22 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
2082
1643
|
type: EConnectorInteraction.Searching,
|
|
2083
1644
|
payload: { sessionId: "" }
|
|
2084
1645
|
});
|
|
2085
|
-
let devices = await this.
|
|
2086
|
-
_LedgerAdapter._throwIfAborted(internalSignal);
|
|
1646
|
+
let devices = await this.searchDevices();
|
|
2087
1647
|
if (devices.length === 0) {
|
|
2088
1648
|
for (let i = 0; i < 3 && !internalSignal.aborted; i += 1) {
|
|
2089
1649
|
await new Promise((resolve) => {
|
|
2090
1650
|
setTimeout(resolve, DEVICE_CONNECT_RETRY_DELAY_MS);
|
|
2091
1651
|
});
|
|
2092
|
-
|
|
2093
|
-
devices = await this._searchDevices(void 0, internalSignal);
|
|
2094
|
-
_LedgerAdapter._throwIfAborted(internalSignal);
|
|
1652
|
+
devices = await this.searchDevices();
|
|
2095
1653
|
if (devices.length > 0) break;
|
|
2096
1654
|
}
|
|
2097
1655
|
}
|
|
2098
|
-
if (devices.length > 0
|
|
1656
|
+
if (devices.length > 0) {
|
|
2099
1657
|
try {
|
|
2100
1658
|
return await this._connectFirstOrSelect(
|
|
2101
1659
|
devices,
|
|
2102
1660
|
targetConnectId,
|
|
2103
|
-
allowUsbEphemeralFallback
|
|
2104
|
-
preserveInteractionId,
|
|
2105
|
-
context,
|
|
2106
|
-
internalSignal
|
|
1661
|
+
allowUsbEphemeralFallback
|
|
2107
1662
|
);
|
|
2108
1663
|
} catch (err) {
|
|
2109
1664
|
if (!isDeviceLockedError(err) && !isDeviceNotAdvertisingError(err) && !isDeviceDisconnectedError(err)) {
|
|
@@ -2132,107 +1687,45 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
2132
1687
|
_LedgerAdapter._throwIfAborted(internalSignal);
|
|
2133
1688
|
throw new Error("_doConnect aborted");
|
|
2134
1689
|
}
|
|
2135
|
-
async _connectFirstOrSelect(devices, targetConnectId, allowUsbEphemeralFallback = false
|
|
2136
|
-
if (signal) _LedgerAdapter._throwIfAborted(signal);
|
|
1690
|
+
async _connectFirstOrSelect(devices, targetConnectId, allowUsbEphemeralFallback = false) {
|
|
2137
1691
|
if (targetConnectId) {
|
|
2138
1692
|
const target = devices.find(
|
|
2139
1693
|
(d) => d.connectId === targetConnectId || d.deviceId === targetConnectId
|
|
2140
1694
|
);
|
|
2141
1695
|
if (target) {
|
|
2142
|
-
return this._connectDeviceOrThrow(target.connectId
|
|
1696
|
+
return this._connectDeviceOrThrow(target.connectId);
|
|
2143
1697
|
}
|
|
2144
|
-
if (!this.
|
|
1698
|
+
if (!isLedgerBleConnectionType(this.connector.connectionType) && devices.length === 1 && allowUsbEphemeralFallback) {
|
|
2145
1699
|
debugLog(
|
|
2146
1700
|
`[LedgerAdapter] target ${targetConnectId} not in fresh enumeration; accepting sole USB device ${devices[0].connectId} for fingerprint-verified recovery`
|
|
2147
1701
|
);
|
|
2148
|
-
return this._connectDeviceOrThrow(devices[0].connectId
|
|
1702
|
+
return this._connectDeviceOrThrow(devices[0].connectId);
|
|
2149
1703
|
}
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
err._tag = ERROR_TAG.DeviceNotAdvertising;
|
|
2156
|
-
}
|
|
2157
|
-
throw err;
|
|
1704
|
+
const err = Object.assign(new Error(`Target Ledger unavailable: ${targetConnectId}`), {
|
|
1705
|
+
code: HardwareErrorCode3.DeviceNotFound
|
|
1706
|
+
});
|
|
1707
|
+
if (isLedgerBleConnectionType(this.connector.connectionType)) {
|
|
1708
|
+
err._tag = ERROR_TAG.DeviceNotAdvertising;
|
|
2158
1709
|
}
|
|
1710
|
+
throw err;
|
|
2159
1711
|
}
|
|
2160
|
-
|
|
2161
|
-
if (requiresBleSelection && !allowUsbEphemeralFallback) {
|
|
1712
|
+
if (isLedgerBleConnectionType(this.connector.connectionType)) {
|
|
2162
1713
|
throw Object.assign(new Error("Ledger BLE connectId is required."), {
|
|
2163
1714
|
code: HardwareErrorCode3.DeviceNotFound
|
|
2164
1715
|
});
|
|
2165
1716
|
}
|
|
2166
|
-
if (
|
|
2167
|
-
|
|
2168
|
-
if (context) context.bindingSessionId = bindingSessionId;
|
|
2169
|
-
const { device, requestId } = await requestBleDeviceSelection({
|
|
2170
|
-
emitter: this.emitter,
|
|
2171
|
-
registry: this._uiRegistry,
|
|
2172
|
-
signal: signal ?? new AbortController().signal,
|
|
2173
|
-
scan: async () => (await this._searchDevices({ transportType: "ble", waitForAllTransports: true }, signal)).filter((device2) => !context?.rejectedConnectIds?.has(device2.connectId)),
|
|
2174
|
-
request: {
|
|
2175
|
-
devices: devices.filter((device2) => !context?.rejectedConnectIds?.has(device2.connectId)),
|
|
2176
|
-
bindingSessionId,
|
|
2177
|
-
rejectedConnectId: context?.rejectedConnectId,
|
|
2178
|
-
context: {
|
|
2179
|
-
kind: "bind-connection",
|
|
2180
|
-
transport: "ble",
|
|
2181
|
-
reason: targetConnectId ? "known-connection-unavailable" : "missing-binding"
|
|
2182
|
-
},
|
|
2183
|
-
extra: context?.extra
|
|
2184
|
-
}
|
|
2185
|
-
});
|
|
2186
|
-
if (context) context.selectedConnection = { connectId: device.connectId, requestId };
|
|
2187
|
-
this._bindingSelectionRequestId = requestId;
|
|
2188
|
-
return this._connectDeviceOrThrow(device.connectId, preserveInteractionId, signal);
|
|
2189
|
-
}
|
|
2190
|
-
if (devices.length > 0 && (devices.length > 1 || requiresBleSelection)) {
|
|
2191
|
-
if (context?.allowDeviceSelection === false || !this.emitter.listenerCount(UI_REQUEST.REQUEST_SELECT_DEVICE)) {
|
|
2192
|
-
throw createHwkError({
|
|
2193
|
-
code: HardwareErrorCode3.DeviceNotFound,
|
|
2194
|
-
message: "Select a Ledger device before continuing"
|
|
2195
|
-
});
|
|
2196
|
-
}
|
|
2197
|
-
const requestId = this._uiRegistry.createRequestId();
|
|
2198
|
-
const waitPromise = this._uiRegistry.wait(
|
|
2199
|
-
UI_REQUEST.REQUEST_SELECT_DEVICE,
|
|
2200
|
-
{ requestId }
|
|
2201
|
-
);
|
|
2202
|
-
this.emitter.emit(UI_REQUEST.REQUEST_SELECT_DEVICE, {
|
|
2203
|
-
type: UI_REQUEST.REQUEST_SELECT_DEVICE,
|
|
2204
|
-
payload: {
|
|
2205
|
-
devices,
|
|
2206
|
-
requestId,
|
|
2207
|
-
context: requiresBleSelection ? {
|
|
2208
|
-
kind: "bind-connection",
|
|
2209
|
-
transport: "ble",
|
|
2210
|
-
reason: targetConnectId ? "known-connection-unavailable" : "missing-binding"
|
|
2211
|
-
} : { kind: "select-device", transport: "usb", reason: "multiple-candidates" },
|
|
2212
|
-
extra: context?.extra
|
|
2213
|
-
}
|
|
2214
|
-
});
|
|
2215
|
-
const { sdkConnectId } = await (signal ? this._abortable(signal, waitPromise) : waitPromise);
|
|
2216
|
-
if (signal) _LedgerAdapter._throwIfAborted(signal);
|
|
2217
|
-
const selected = devices.find((device) => device.connectId === sdkConnectId);
|
|
2218
|
-
if (!selected) {
|
|
2219
|
-
throw Object.assign(new Error("Selected Ledger is no longer available"), {
|
|
2220
|
-
code: HardwareErrorCode3.DeviceNotFound
|
|
2221
|
-
});
|
|
2222
|
-
}
|
|
2223
|
-
if (context && requiresBleSelection)
|
|
2224
|
-
context.selectedConnection = { connectId: selected.connectId, requestId };
|
|
2225
|
-
return this._connectDeviceOrThrow(selected.connectId, preserveInteractionId, signal);
|
|
1717
|
+
if (devices.length > 1) {
|
|
1718
|
+
throw createMultipleUsbLedgerDevicesError();
|
|
2226
1719
|
}
|
|
2227
1720
|
if (devices.length !== 1) {
|
|
2228
1721
|
throw Object.assign(new Error("Ledger device not found."), {
|
|
2229
1722
|
code: HardwareErrorCode3.DeviceNotFound
|
|
2230
1723
|
});
|
|
2231
1724
|
}
|
|
2232
|
-
return this._connectDeviceOrThrow(devices[0].connectId
|
|
1725
|
+
return this._connectDeviceOrThrow(devices[0].connectId);
|
|
2233
1726
|
}
|
|
2234
|
-
async _connectDeviceOrThrow(chosenConnectId
|
|
2235
|
-
const result = await this.
|
|
1727
|
+
async _connectDeviceOrThrow(chosenConnectId) {
|
|
1728
|
+
const result = await this.connectDevice(chosenConnectId);
|
|
2236
1729
|
if (!result.success) {
|
|
2237
1730
|
const payload = result.payload;
|
|
2238
1731
|
const rethrow = Object.assign(new Error(payload.error), {
|
|
@@ -2243,7 +1736,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
2243
1736
|
}
|
|
2244
1737
|
throw rethrow;
|
|
2245
1738
|
}
|
|
2246
|
-
return
|
|
1739
|
+
return chosenConnectId;
|
|
2247
1740
|
}
|
|
2248
1741
|
/**
|
|
2249
1742
|
* Call the connector with automatic session resolution and disconnect retry.
|
|
@@ -2273,121 +1766,26 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
2273
1766
|
* lives in one place.
|
|
2274
1767
|
*/
|
|
2275
1768
|
async _callConnector(sessionId, method, params, signal) {
|
|
2276
|
-
this.
|
|
2277
|
-
const releaseOperation = this._retainConnectorOperation(`call:${sessionId}`);
|
|
2278
|
-
let promise;
|
|
2279
|
-
try {
|
|
2280
|
-
promise = this.connector.call(sessionId, method, params).finally(releaseOperation);
|
|
2281
|
-
} catch (error) {
|
|
2282
|
-
releaseOperation();
|
|
2283
|
-
throw error;
|
|
2284
|
-
}
|
|
1769
|
+
const promise = this.connector.call(sessionId, method, params);
|
|
2285
1770
|
const result = signal ? await this._abortable(signal, promise) : await promise;
|
|
2286
1771
|
return this._unwrapConnectorResult(result);
|
|
2287
1772
|
}
|
|
2288
|
-
_assertConnectorReady(method) {
|
|
2289
|
-
if (this._resetPromise || this._pendingConnectorTeardowns > 0 || this._unsettledConnectorOperations.size > 0) {
|
|
2290
|
-
throw _LedgerAdapter._createDeviceBusyError(method);
|
|
2291
|
-
}
|
|
2292
|
-
}
|
|
2293
|
-
_runConnectorTeardown(task) {
|
|
2294
|
-
const previous = this._connectorTeardownTail;
|
|
2295
|
-
let releaseTail = () => void 0;
|
|
2296
|
-
this._connectorTeardownTail = new Promise((resolve) => {
|
|
2297
|
-
releaseTail = resolve;
|
|
2298
|
-
});
|
|
2299
|
-
this._pendingConnectorTeardowns += 1;
|
|
2300
|
-
return (async () => {
|
|
2301
|
-
try {
|
|
2302
|
-
await previous;
|
|
2303
|
-
await this._waitForConnectorOperationsToDrain();
|
|
2304
|
-
await task();
|
|
2305
|
-
} finally {
|
|
2306
|
-
this._pendingConnectorTeardowns -= 1;
|
|
2307
|
-
releaseTail();
|
|
2308
|
-
}
|
|
2309
|
-
})();
|
|
2310
|
-
}
|
|
2311
|
-
_waitForConnectorOperationsToDrain() {
|
|
2312
|
-
if (this._unsettledConnectorOperations.size === 0) {
|
|
2313
|
-
return Promise.resolve();
|
|
2314
|
-
}
|
|
2315
|
-
return new Promise((resolve) => {
|
|
2316
|
-
this._connectorIdleWaiters.add(resolve);
|
|
2317
|
-
});
|
|
2318
|
-
}
|
|
2319
|
-
_retainConnectorOperation(key) {
|
|
2320
|
-
this._unsettledConnectorOperations.set(
|
|
2321
|
-
key,
|
|
2322
|
-
(this._unsettledConnectorOperations.get(key) ?? 0) + 1
|
|
2323
|
-
);
|
|
2324
|
-
let released = false;
|
|
2325
|
-
return () => {
|
|
2326
|
-
if (released) return;
|
|
2327
|
-
released = true;
|
|
2328
|
-
const remaining = (this._unsettledConnectorOperations.get(key) ?? 1) - 1;
|
|
2329
|
-
if (remaining > 0) {
|
|
2330
|
-
this._unsettledConnectorOperations.set(key, remaining);
|
|
2331
|
-
} else {
|
|
2332
|
-
this._unsettledConnectorOperations.delete(key);
|
|
2333
|
-
}
|
|
2334
|
-
if (this._unsettledConnectorOperations.size === 0) {
|
|
2335
|
-
for (const resolve of this._connectorIdleWaiters) resolve();
|
|
2336
|
-
this._connectorIdleWaiters.clear();
|
|
2337
|
-
}
|
|
2338
|
-
};
|
|
2339
|
-
}
|
|
2340
1773
|
async connectorCall(connectId, method, params, fingerprint, permissionDeviceId, commonParams, installContext) {
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
throw createHwkError({
|
|
2344
|
-
code: HardwareErrorCode3.InvalidParams,
|
|
2345
|
-
message: "Conflicting Ledger interaction ids",
|
|
2346
|
-
params: {
|
|
2347
|
-
positionalInteractionId,
|
|
2348
|
-
commonInteractionId: commonParams.interactionId
|
|
2349
|
-
}
|
|
2350
|
-
});
|
|
2351
|
-
}
|
|
2352
|
-
const interactionId = commonParams?.interactionId ?? positionalInteractionId;
|
|
2353
|
-
const interaction = interactionId ? this._interactions.resolve(interactionId) : void 0;
|
|
2354
|
-
const releaseInteractionRetention = interactionId ? this._interactions.retain(interactionId) : void 0;
|
|
2355
|
-
const effectiveConnectId = interaction?.connectId ?? connectId;
|
|
2356
|
-
debugLog("[LedgerAdapter][REQ]", {
|
|
2357
|
-
method,
|
|
2358
|
-
connectId: effectiveConnectId || "(empty)",
|
|
2359
|
-
params
|
|
2360
|
-
});
|
|
2361
|
-
const queueKey = (interactionId ?? effectiveConnectId) || "__ledger_default__";
|
|
1774
|
+
debugLog("[LedgerAdapter][REQ]", { method, connectId: connectId || "(empty)", params });
|
|
1775
|
+
const queueKey = connectId || "__ledger_default__";
|
|
2362
1776
|
try {
|
|
2363
1777
|
const result = await this._jobQueue.enqueue(
|
|
2364
1778
|
queueKey,
|
|
2365
|
-
async (signal) =>
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
commonParams,
|
|
2376
|
-
installContext ?? {},
|
|
2377
|
-
interactionId
|
|
2378
|
-
);
|
|
2379
|
-
} catch (error) {
|
|
2380
|
-
this._finishBleBinding(signal.aborted ? "cancelled" : "failed");
|
|
2381
|
-
throw error;
|
|
2382
|
-
} finally {
|
|
2383
|
-
if (interactionId) {
|
|
2384
|
-
this._activeInteractionJobs.delete(interactionId);
|
|
2385
|
-
if (this._pendingInteractionDisconnects.delete(interactionId)) {
|
|
2386
|
-
await this._releaseLostInteractionConnection(interactionId);
|
|
2387
|
-
}
|
|
2388
|
-
}
|
|
2389
|
-
}
|
|
2390
|
-
},
|
|
1779
|
+
async (signal) => this._runConnectorCall(
|
|
1780
|
+
connectId,
|
|
1781
|
+
method,
|
|
1782
|
+
params,
|
|
1783
|
+
signal,
|
|
1784
|
+
fingerprint,
|
|
1785
|
+
permissionDeviceId,
|
|
1786
|
+
commonParams,
|
|
1787
|
+
installContext
|
|
1788
|
+
),
|
|
2391
1789
|
{
|
|
2392
1790
|
label: method,
|
|
2393
1791
|
rejectIfBusy: true,
|
|
@@ -2408,8 +1806,6 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
2408
1806
|
}
|
|
2409
1807
|
});
|
|
2410
1808
|
throw err;
|
|
2411
|
-
} finally {
|
|
2412
|
-
releaseInteractionRetention?.();
|
|
2413
1809
|
}
|
|
2414
1810
|
}
|
|
2415
1811
|
/**
|
|
@@ -2419,7 +1815,6 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
2419
1815
|
_abortable(signal, promise) {
|
|
2420
1816
|
const getAbortReason = () => signal.reason ?? this._lastCancelReason ?? new Error("Aborted");
|
|
2421
1817
|
if (signal.aborted) {
|
|
2422
|
-
void promise.catch(() => void 0);
|
|
2423
1818
|
return Promise.reject(getAbortReason());
|
|
2424
1819
|
}
|
|
2425
1820
|
return new Promise((resolve, reject) => {
|
|
@@ -2446,15 +1841,13 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
2446
1841
|
}
|
|
2447
1842
|
}
|
|
2448
1843
|
/** Actual work done under the job queue — connection, fingerprint, call, and recovery. */
|
|
2449
|
-
async _runConnectorCall(connectId, method, params, signal, fingerprint, permissionDeviceId, commonParams, installContext
|
|
1844
|
+
async _runConnectorCall(connectId, method, params, signal, fingerprint, permissionDeviceId, commonParams, installContext) {
|
|
2450
1845
|
_LedgerAdapter._throwIfAborted(signal);
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
);
|
|
2457
|
-
}
|
|
1846
|
+
await this._ensureDevicePermission(
|
|
1847
|
+
connectId,
|
|
1848
|
+
permissionDeviceId ?? fingerprint?.deviceId,
|
|
1849
|
+
signal
|
|
1850
|
+
);
|
|
2458
1851
|
_LedgerAdapter._throwIfAborted(signal);
|
|
2459
1852
|
let effectiveParams = params;
|
|
2460
1853
|
if (method === "btcGetPublicKey") {
|
|
@@ -2468,133 +1861,36 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
2468
1861
|
effectiveParams = gatedParams;
|
|
2469
1862
|
}
|
|
2470
1863
|
const allowUsbEphemeralFallback = !!fingerprint?.deviceId && !fingerprint.skipFingerprint;
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
const knownTransport = this._isBleConnection() ? "ble" : "usb";
|
|
2474
|
-
const hintedConnectId = commonParams?.knownConnections?.find(
|
|
2475
|
-
(connection) => connection.transport === knownTransport
|
|
2476
|
-
);
|
|
2477
|
-
const inputConnectId = hintedConnectId && hintedConnectId.transport !== "qr" ? hintedConnectId.connectId : connectId;
|
|
2478
|
-
const preferredConnectId = fingerprint && !fingerprint.skipFingerprint && verifiedBleTarget?.chain === fingerprint.chain && verifiedBleTarget.fingerprint === fingerprint.deviceId ? verifiedBleTarget.connectId : inputConnectId;
|
|
2479
|
-
const connectionAttempt = { ...commonParams };
|
|
2480
|
-
const bundleConnection = installContext?.connection;
|
|
2481
|
-
if (bundleConnection && this._sessions.get(bundleConnection.connectId) !== bundleConnection.sessionId) {
|
|
2482
|
-
throw createHwkError({
|
|
2483
|
-
code: HardwareErrorCode3.DeviceDisconnected,
|
|
2484
|
-
message: "Ledger all-network connection ended"
|
|
2485
|
-
});
|
|
2486
|
-
}
|
|
2487
|
-
let resolvedConnectId = interactionId ? this._interactions.resolve(interactionId).connectId : bundleConnection?.connectId ?? await this.ensureConnected(
|
|
2488
|
-
preferredConnectId,
|
|
1864
|
+
const resolvedConnectId = await this.ensureConnected(
|
|
1865
|
+
connectId,
|
|
2489
1866
|
signal,
|
|
2490
|
-
allowUsbEphemeralFallback
|
|
2491
|
-
void 0,
|
|
2492
|
-
connectionAttempt
|
|
1867
|
+
allowUsbEphemeralFallback
|
|
2493
1868
|
);
|
|
2494
|
-
|
|
2495
|
-
if (sessionId && installContext && !installContext.connection) {
|
|
2496
|
-
installContext.connection = { connectId: resolvedConnectId, sessionId };
|
|
2497
|
-
}
|
|
1869
|
+
const sessionId = this._sessions.get(resolvedConnectId);
|
|
2498
1870
|
if (!sessionId) {
|
|
2499
|
-
if (interactionId) {
|
|
2500
|
-
this._interactions.end(interactionId, "disconnect");
|
|
2501
|
-
throw createHwkError({
|
|
2502
|
-
code: HardwareErrorCode3.InteractionEnded,
|
|
2503
|
-
message: "Ledger interaction connection is no longer active",
|
|
2504
|
-
params: { interactionId, reason: "disconnect" }
|
|
2505
|
-
});
|
|
2506
|
-
}
|
|
2507
1871
|
throw Object.assign(new Error("Auto-connect succeeded but no session found"), {
|
|
2508
1872
|
_tag: ERROR_TAG.DeviceSessionNotFound
|
|
2509
1873
|
});
|
|
2510
1874
|
}
|
|
2511
1875
|
try {
|
|
2512
1876
|
if (fingerprint && !fingerprint.skipFingerprint && fingerprint.deviceId) {
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
if (!this._isBleConnection() || binding?.selectedConnection?.connectId !== resolvedConnectId) {
|
|
2525
|
-
throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {
|
|
2526
|
-
code: HardwareErrorCode3.DeviceMismatch
|
|
2527
|
-
});
|
|
2528
|
-
}
|
|
2529
|
-
binding.rejectedConnectIds ?? (binding.rejectedConnectIds = /* @__PURE__ */ new Set());
|
|
2530
|
-
binding.rejectedConnectIds.add(resolvedConnectId);
|
|
2531
|
-
binding.rejectedConnectId = resolvedConnectId;
|
|
2532
|
-
this._sessions.delete(resolvedConnectId);
|
|
2533
|
-
await this.connector.disconnect(sessionId);
|
|
2534
|
-
if (interactionId) this._pendingInteractionDisconnects.delete(interactionId);
|
|
2535
|
-
_LedgerAdapter._throwIfAborted(signal);
|
|
2536
|
-
resolvedConnectId = await this._connectFirstOrSelect(
|
|
2537
|
-
[],
|
|
2538
|
-
void 0,
|
|
2539
|
-
true,
|
|
2540
|
-
interactionId,
|
|
2541
|
-
binding,
|
|
2542
|
-
signal
|
|
2543
|
-
);
|
|
2544
|
-
const selectedSession = this._sessions.get(resolvedConnectId);
|
|
2545
|
-
const selectedDevice = this._discoveredDevices.get(resolvedConnectId);
|
|
2546
|
-
if (!selectedSession || !selectedDevice)
|
|
2547
|
-
throw createHwkError({
|
|
2548
|
-
code: HardwareErrorCode3.DeviceDisconnected,
|
|
2549
|
-
message: "Selected Ledger connection ended"
|
|
2550
|
-
});
|
|
2551
|
-
sessionId = selectedSession;
|
|
2552
|
-
if (interactionId)
|
|
2553
|
-
this._interactions.rebind(interactionId, {
|
|
2554
|
-
connectId: resolvedConnectId,
|
|
2555
|
-
device: selectedDevice,
|
|
2556
|
-
connectionKeys: [sessionId]
|
|
2557
|
-
});
|
|
2558
|
-
if (installContext)
|
|
2559
|
-
installContext.connection = { connectId: resolvedConnectId, sessionId };
|
|
2560
|
-
}
|
|
2561
|
-
if (!interactionId && connectionAttempt.selectedConnection?.connectId === resolvedConnectId && this._isBleConnection()) {
|
|
2562
|
-
this._verifiedBleReconnectTargets.set(connectId, {
|
|
2563
|
-
connectId: resolvedConnectId,
|
|
2564
|
-
chain: fingerprint.chain,
|
|
2565
|
-
fingerprint: fingerprint.deviceId
|
|
1877
|
+
const fp = await this._abortable(
|
|
1878
|
+
signal,
|
|
1879
|
+
this._verifyDeviceFingerprintWithSession(
|
|
1880
|
+
sessionId,
|
|
1881
|
+
fingerprint.deviceId,
|
|
1882
|
+
fingerprint.chain
|
|
1883
|
+
)
|
|
1884
|
+
);
|
|
1885
|
+
if (!fp.success) {
|
|
1886
|
+
throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {
|
|
1887
|
+
code: HardwareErrorCode3.DeviceMismatch
|
|
2566
1888
|
});
|
|
2567
1889
|
}
|
|
2568
|
-
await this._publishVerifiedBleBinding(
|
|
2569
|
-
resolvedConnectId,
|
|
2570
|
-
fingerprint.chain,
|
|
2571
|
-
fingerprint.deviceId,
|
|
2572
|
-
connectionAttempt,
|
|
2573
|
-
interactionId,
|
|
2574
|
-
connectId,
|
|
2575
|
-
signal
|
|
2576
|
-
);
|
|
2577
1890
|
}
|
|
2578
|
-
businessCallStarted = true;
|
|
2579
1891
|
return await this._callConnector(sessionId, method, effectiveParams, signal);
|
|
2580
1892
|
} catch (err) {
|
|
2581
1893
|
if (signal.aborted) throw err;
|
|
2582
|
-
if (isDeviceDisconnectedError(err) || isDeviceNotAdvertisingError(err) || isTimeoutError(err) || isConnectionLevelError(err)) {
|
|
2583
|
-
this._discoveredDevices.delete(resolvedConnectId);
|
|
2584
|
-
if (interactionId) await this._releaseLostInteractionConnection(interactionId);
|
|
2585
|
-
else {
|
|
2586
|
-
this._sessions.delete(resolvedConnectId);
|
|
2587
|
-
await this.connector.disconnect(sessionId).catch(() => void 0);
|
|
2588
|
-
}
|
|
2589
|
-
const ambiguous = businessCallStarted && !canReplayHardwareMethodAfterTransportFailure(method);
|
|
2590
|
-
const interactionParams = interactionId ? { interactionId, reason: "disconnect" } : void 0;
|
|
2591
|
-
throw createHwkError({
|
|
2592
|
-
code: interactionId ? HardwareErrorCode3.InteractionEnded : mapLedgerError(err).code,
|
|
2593
|
-
message: "Ledger operation connection was lost; start a new operation",
|
|
2594
|
-
params: ambiguous ? operationMayHaveCompletedParams(method, { interactionId }) : interactionParams,
|
|
2595
|
-
recovery: ambiguous ? { scope: "unknown" } : void 0
|
|
2596
|
-
});
|
|
2597
|
-
}
|
|
2598
1894
|
const errObj = err;
|
|
2599
1895
|
debugLog("[LedgerAdapter] connectorCall error:", method, {
|
|
2600
1896
|
message: errObj?.message,
|
|
@@ -2606,65 +1902,6 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
2606
1902
|
isNotAdvertising: isDeviceNotAdvertisingError(err),
|
|
2607
1903
|
isStuckApp: isStuckAppStateError(err)
|
|
2608
1904
|
});
|
|
2609
|
-
if ((isDeviceLockedError(err) || errObj?.code === HardwareErrorCode3.DeviceLocked) && lockedRetryBudget > 0) {
|
|
2610
|
-
await this._waitForDeviceConnect(signal);
|
|
2611
|
-
if (this._sessions.get(resolvedConnectId) !== sessionId) {
|
|
2612
|
-
throw createHwkError({
|
|
2613
|
-
code: interactionId ? HardwareErrorCode3.InteractionEnded : HardwareErrorCode3.DeviceDisconnected,
|
|
2614
|
-
message: "Ledger connection ended while waiting for unlock"
|
|
2615
|
-
});
|
|
2616
|
-
}
|
|
2617
|
-
return this._runConnectorCall(
|
|
2618
|
-
resolvedConnectId,
|
|
2619
|
-
method,
|
|
2620
|
-
effectiveParams,
|
|
2621
|
-
signal,
|
|
2622
|
-
fingerprint,
|
|
2623
|
-
permissionDeviceId,
|
|
2624
|
-
commonParams,
|
|
2625
|
-
installContext,
|
|
2626
|
-
interactionId,
|
|
2627
|
-
lockedRetryBudget - 1
|
|
2628
|
-
);
|
|
2629
|
-
}
|
|
2630
|
-
if (businessCallStarted && isStuckAppStateError(err)) {
|
|
2631
|
-
await this._sleepAbortable(_LedgerAdapter.STUCK_APP_RETRY_DELAY_MS, signal);
|
|
2632
|
-
if (this._sessions.get(resolvedConnectId) !== sessionId) {
|
|
2633
|
-
throw createHwkError({
|
|
2634
|
-
code: interactionId ? HardwareErrorCode3.InteractionEnded : HardwareErrorCode3.DeviceDisconnected,
|
|
2635
|
-
message: "Ledger connection ended during the app transition"
|
|
2636
|
-
});
|
|
2637
|
-
}
|
|
2638
|
-
try {
|
|
2639
|
-
return await this._callConnector(sessionId, method, effectiveParams, signal);
|
|
2640
|
-
} catch (retryErr) {
|
|
2641
|
-
if (isStuckAppStateError(retryErr)) throw err;
|
|
2642
|
-
if (isDeviceDisconnectedError(retryErr) || isDeviceNotAdvertisingError(retryErr) || isTimeoutError(retryErr) || isConnectionLevelError(retryErr)) {
|
|
2643
|
-
if (interactionId) await this._releaseLostInteractionConnection(interactionId);
|
|
2644
|
-
else {
|
|
2645
|
-
this._sessions.delete(resolvedConnectId);
|
|
2646
|
-
this._discoveredDevices.delete(resolvedConnectId);
|
|
2647
|
-
await this.connector.disconnect(sessionId).catch(() => void 0);
|
|
2648
|
-
}
|
|
2649
|
-
throw createHwkError({
|
|
2650
|
-
code: interactionId ? HardwareErrorCode3.InteractionEnded : mapLedgerError(retryErr).code,
|
|
2651
|
-
message: `Ledger ${method} may have completed before the connection was lost`,
|
|
2652
|
-
params: !canReplayHardwareMethodAfterTransportFailure(method) ? operationMayHaveCompletedParams(method, {
|
|
2653
|
-
interactionId,
|
|
2654
|
-
reason: "disconnect"
|
|
2655
|
-
}) : { interactionId, reason: "disconnect" },
|
|
2656
|
-
recovery: !canReplayHardwareMethodAfterTransportFailure(method) ? { scope: "unknown" } : void 0
|
|
2657
|
-
});
|
|
2658
|
-
}
|
|
2659
|
-
throw retryErr;
|
|
2660
|
-
}
|
|
2661
|
-
}
|
|
2662
|
-
if (!interactionId && err?.code === HardwareErrorCode3.DeviceMismatch) {
|
|
2663
|
-
this._sessions.delete(resolvedConnectId);
|
|
2664
|
-
this._discoveredDevices.delete(resolvedConnectId);
|
|
2665
|
-
await this.connector.disconnect(sessionId).catch(() => void 0);
|
|
2666
|
-
throw err;
|
|
2667
|
-
}
|
|
2668
1905
|
const autoInstallApp = commonParams?.autoInstallApp ?? this._defaultAutoInstallApp;
|
|
2669
1906
|
const isAppMissing = isAppNotInstalledError(err) || err?.code === HardwareErrorCode3.AppNotInstalled;
|
|
2670
1907
|
if (autoInstallApp && isAppMissing) {
|
|
@@ -2720,14 +1957,157 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
2720
1957
|
fingerprint,
|
|
2721
1958
|
permissionDeviceId,
|
|
2722
1959
|
commonParams,
|
|
2723
|
-
installContext
|
|
2724
|
-
interactionId
|
|
1960
|
+
installContext
|
|
2725
1961
|
);
|
|
2726
1962
|
}
|
|
2727
1963
|
}
|
|
1964
|
+
if (isStuckAppStateError(err)) {
|
|
1965
|
+
try {
|
|
1966
|
+
this._sessions.delete(resolvedConnectId);
|
|
1967
|
+
this._discoveredDevices.delete(resolvedConnectId);
|
|
1968
|
+
this.connector.reset?.();
|
|
1969
|
+
} catch {
|
|
1970
|
+
}
|
|
1971
|
+
debugLog(
|
|
1972
|
+
"[LedgerAdapter] stuck-app retry: method=",
|
|
1973
|
+
method,
|
|
1974
|
+
"delayMs=",
|
|
1975
|
+
_LedgerAdapter.STUCK_APP_RETRY_DELAY_MS,
|
|
1976
|
+
"_tag=",
|
|
1977
|
+
err?._tag
|
|
1978
|
+
);
|
|
1979
|
+
try {
|
|
1980
|
+
const retryResult = await this._retryAfterStuckApp(
|
|
1981
|
+
resolvedConnectId,
|
|
1982
|
+
method,
|
|
1983
|
+
effectiveParams,
|
|
1984
|
+
signal,
|
|
1985
|
+
err,
|
|
1986
|
+
fingerprint
|
|
1987
|
+
);
|
|
1988
|
+
debugLog("[LedgerAdapter] stuck-app retry succeeded: method=", method);
|
|
1989
|
+
return retryResult;
|
|
1990
|
+
} catch (retryErr) {
|
|
1991
|
+
if (signal.aborted) throw retryErr;
|
|
1992
|
+
if (isStuckAppStateError(retryErr)) {
|
|
1993
|
+
debugLog("[LedgerAdapter] stuck-app retry exhausted (2nd 6901): method=", method);
|
|
1994
|
+
throw err;
|
|
1995
|
+
}
|
|
1996
|
+
debugLog(
|
|
1997
|
+
"[LedgerAdapter] stuck-app retry threw non-stuck error: method=",
|
|
1998
|
+
method,
|
|
1999
|
+
"retryErrTag=",
|
|
2000
|
+
retryErr?._tag
|
|
2001
|
+
);
|
|
2002
|
+
throw retryErr;
|
|
2003
|
+
}
|
|
2004
|
+
}
|
|
2005
|
+
if (isDeviceLockedError(err) || isDeviceNotAdvertisingError(err) || isDeviceDisconnectedError(err)) {
|
|
2006
|
+
let lastErr = err;
|
|
2007
|
+
for (let attempt = 0; attempt < _LedgerAdapter.MAX_BUSINESS_RETRY_BUDGET; attempt += 1) {
|
|
2008
|
+
if (signal.aborted) throw lastErr;
|
|
2009
|
+
try {
|
|
2010
|
+
this._sessions.delete(resolvedConnectId);
|
|
2011
|
+
this._discoveredDevices.delete(resolvedConnectId);
|
|
2012
|
+
if (isDeviceDisconnectedError(lastErr)) {
|
|
2013
|
+
try {
|
|
2014
|
+
this.connector.reset?.();
|
|
2015
|
+
} catch {
|
|
2016
|
+
}
|
|
2017
|
+
}
|
|
2018
|
+
const reConnectId = await this.ensureConnected(
|
|
2019
|
+
resolvedConnectId,
|
|
2020
|
+
signal,
|
|
2021
|
+
allowUsbEphemeralFallback
|
|
2022
|
+
);
|
|
2023
|
+
const reSessionId = this._sessions.get(reConnectId);
|
|
2024
|
+
if (!reSessionId) throw lastErr;
|
|
2025
|
+
if (fingerprint && !fingerprint.skipFingerprint && fingerprint.deviceId) {
|
|
2026
|
+
const fp = await this._abortable(
|
|
2027
|
+
signal,
|
|
2028
|
+
this._verifyDeviceFingerprintWithSession(
|
|
2029
|
+
reSessionId,
|
|
2030
|
+
fingerprint.deviceId,
|
|
2031
|
+
fingerprint.chain
|
|
2032
|
+
)
|
|
2033
|
+
);
|
|
2034
|
+
if (!fp.success) {
|
|
2035
|
+
throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {
|
|
2036
|
+
code: HardwareErrorCode3.DeviceMismatch
|
|
2037
|
+
});
|
|
2038
|
+
}
|
|
2039
|
+
}
|
|
2040
|
+
return await this._callConnector(reSessionId, method, effectiveParams, signal);
|
|
2041
|
+
} catch (retryErr) {
|
|
2042
|
+
if (signal.aborted) throw retryErr;
|
|
2043
|
+
lastErr = retryErr;
|
|
2044
|
+
const canRetry = attempt < _LedgerAdapter.MAX_BUSINESS_RETRY_BUDGET - 1 && (isDeviceLockedError(retryErr) || isDeviceNotAdvertisingError(retryErr) || isDeviceDisconnectedError(retryErr));
|
|
2045
|
+
if (!canRetry) {
|
|
2046
|
+
throw retryErr;
|
|
2047
|
+
}
|
|
2048
|
+
}
|
|
2049
|
+
}
|
|
2050
|
+
throw lastErr;
|
|
2051
|
+
}
|
|
2052
|
+
if (isTimeoutError(err)) {
|
|
2053
|
+
debugLog("[LedgerAdapter] timeout, retrying with fresh connection...");
|
|
2054
|
+
this._discoveredDevices.delete(resolvedConnectId);
|
|
2055
|
+
return this._retryWithFreshConnection(
|
|
2056
|
+
resolvedConnectId,
|
|
2057
|
+
method,
|
|
2058
|
+
effectiveParams,
|
|
2059
|
+
signal,
|
|
2060
|
+
err,
|
|
2061
|
+
fingerprint
|
|
2062
|
+
);
|
|
2063
|
+
}
|
|
2064
|
+
if (isConnectionLevelError(err)) {
|
|
2065
|
+
debugLog("[LedgerAdapter] connection-level fail-closed reset");
|
|
2066
|
+
this._sessions.delete(resolvedConnectId);
|
|
2067
|
+
this._discoveredDevices.delete(resolvedConnectId);
|
|
2068
|
+
this.connector.reset();
|
|
2069
|
+
const codeNum = err?.code;
|
|
2070
|
+
throw Object.assign(err, {
|
|
2071
|
+
code: codeNum ?? HardwareErrorCode3.DeviceDisconnected
|
|
2072
|
+
});
|
|
2073
|
+
}
|
|
2728
2074
|
throw err;
|
|
2729
2075
|
}
|
|
2730
2076
|
}
|
|
2077
|
+
/**
|
|
2078
|
+
* Stuck-app recovery: pause for the device's UI transition, then retry once.
|
|
2079
|
+
*
|
|
2080
|
+
* Caller has already cleared the session + reset connector. We wait so Stax
|
|
2081
|
+
* finishes its post-CloseApp animation, then go through ensureConnected +
|
|
2082
|
+
* fingerprint check + call exactly once. Caller decides what to do on a
|
|
2083
|
+
* second stuck-app hit.
|
|
2084
|
+
*/
|
|
2085
|
+
async _retryAfterStuckApp(resolvedConnectId, method, params, signal, originalErr, fingerprint) {
|
|
2086
|
+
await this._sleepAbortable(_LedgerAdapter.STUCK_APP_RETRY_DELAY_MS, signal);
|
|
2087
|
+
const retryConnectId = await this.ensureConnected(
|
|
2088
|
+
resolvedConnectId,
|
|
2089
|
+
signal,
|
|
2090
|
+
!!fingerprint?.deviceId && !fingerprint.skipFingerprint
|
|
2091
|
+
);
|
|
2092
|
+
const retrySessionId = this._sessions.get(retryConnectId);
|
|
2093
|
+
if (!retrySessionId) throw originalErr;
|
|
2094
|
+
if (fingerprint && !fingerprint.skipFingerprint && fingerprint.deviceId) {
|
|
2095
|
+
const fp = await this._abortable(
|
|
2096
|
+
signal,
|
|
2097
|
+
this._verifyDeviceFingerprintWithSession(
|
|
2098
|
+
retrySessionId,
|
|
2099
|
+
fingerprint.deviceId,
|
|
2100
|
+
fingerprint.chain
|
|
2101
|
+
)
|
|
2102
|
+
);
|
|
2103
|
+
if (!fp.success) {
|
|
2104
|
+
throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {
|
|
2105
|
+
code: HardwareErrorCode3.DeviceMismatch
|
|
2106
|
+
});
|
|
2107
|
+
}
|
|
2108
|
+
}
|
|
2109
|
+
return this._callConnector(retrySessionId, method, params, signal);
|
|
2110
|
+
}
|
|
2731
2111
|
_sleepAbortable(ms, signal) {
|
|
2732
2112
|
return new Promise((resolve, reject) => {
|
|
2733
2113
|
if (signal.aborted) {
|
|
@@ -2745,6 +2125,88 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
2745
2125
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
2746
2126
|
});
|
|
2747
2127
|
}
|
|
2128
|
+
/**
|
|
2129
|
+
* Clear stale session, reconnect, and retry the call.
|
|
2130
|
+
*
|
|
2131
|
+
* Timeout recovery starts with a full connector reset. After an APDU
|
|
2132
|
+
* timeout, DMK/transport state may still emit malformed responses; retrying
|
|
2133
|
+
* on the same DMK can poison the next chain switch.
|
|
2134
|
+
*/
|
|
2135
|
+
async _retryWithFreshConnection(targetConnectId, method, params, signal, originalErr, fingerprint) {
|
|
2136
|
+
this.connector.reset();
|
|
2137
|
+
this._sessions.clear();
|
|
2138
|
+
this._discoveredDevices.clear();
|
|
2139
|
+
this._connectingPromise = null;
|
|
2140
|
+
const allowUsbEphemeralFallback = !!fingerprint?.deviceId && !fingerprint.skipFingerprint;
|
|
2141
|
+
const retryConnectId = await this.ensureConnected(
|
|
2142
|
+
targetConnectId,
|
|
2143
|
+
signal,
|
|
2144
|
+
allowUsbEphemeralFallback
|
|
2145
|
+
);
|
|
2146
|
+
const retrySessionId = this._sessions.get(retryConnectId);
|
|
2147
|
+
if (!retrySessionId) {
|
|
2148
|
+
throw originalErr;
|
|
2149
|
+
}
|
|
2150
|
+
try {
|
|
2151
|
+
if (fingerprint && !fingerprint.skipFingerprint && fingerprint.deviceId) {
|
|
2152
|
+
const fp = await this._abortable(
|
|
2153
|
+
signal,
|
|
2154
|
+
this._verifyDeviceFingerprintWithSession(
|
|
2155
|
+
retrySessionId,
|
|
2156
|
+
fingerprint.deviceId,
|
|
2157
|
+
fingerprint.chain
|
|
2158
|
+
)
|
|
2159
|
+
);
|
|
2160
|
+
if (!fp.success) {
|
|
2161
|
+
throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {
|
|
2162
|
+
code: HardwareErrorCode3.DeviceMismatch
|
|
2163
|
+
});
|
|
2164
|
+
}
|
|
2165
|
+
}
|
|
2166
|
+
return await this._callConnector(retrySessionId, method, params, signal);
|
|
2167
|
+
} catch (retryErr) {
|
|
2168
|
+
if (signal.aborted) throw retryErr;
|
|
2169
|
+
this.connector.reset();
|
|
2170
|
+
this._sessions.clear();
|
|
2171
|
+
this._discoveredDevices.clear();
|
|
2172
|
+
this._connectingPromise = null;
|
|
2173
|
+
if (!isDeviceDisconnectedError(retryErr) && !isTimeoutError(retryErr)) {
|
|
2174
|
+
throw retryErr;
|
|
2175
|
+
}
|
|
2176
|
+
debugLog(
|
|
2177
|
+
"[LedgerAdapter] fresh-session retry still failed; resetting connector and rebuilding DMK"
|
|
2178
|
+
);
|
|
2179
|
+
this.connector.reset();
|
|
2180
|
+
this._sessions.clear();
|
|
2181
|
+
this._discoveredDevices.clear();
|
|
2182
|
+
this._connectingPromise = null;
|
|
2183
|
+
const finalConnectId = await this.ensureConnected(
|
|
2184
|
+
targetConnectId,
|
|
2185
|
+
signal,
|
|
2186
|
+
allowUsbEphemeralFallback
|
|
2187
|
+
);
|
|
2188
|
+
const finalSessionId = this._sessions.get(finalConnectId);
|
|
2189
|
+
if (!finalSessionId) {
|
|
2190
|
+
throw originalErr;
|
|
2191
|
+
}
|
|
2192
|
+
if (fingerprint && !fingerprint.skipFingerprint && fingerprint.deviceId) {
|
|
2193
|
+
const fp = await this._abortable(
|
|
2194
|
+
signal,
|
|
2195
|
+
this._verifyDeviceFingerprintWithSession(
|
|
2196
|
+
finalSessionId,
|
|
2197
|
+
fingerprint.deviceId,
|
|
2198
|
+
fingerprint.chain
|
|
2199
|
+
)
|
|
2200
|
+
);
|
|
2201
|
+
if (!fp.success) {
|
|
2202
|
+
throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {
|
|
2203
|
+
code: HardwareErrorCode3.DeviceMismatch
|
|
2204
|
+
});
|
|
2205
|
+
}
|
|
2206
|
+
}
|
|
2207
|
+
return this._callConnector(finalSessionId, method, params, signal);
|
|
2208
|
+
}
|
|
2209
|
+
}
|
|
2748
2210
|
/**
|
|
2749
2211
|
* Ensure OS-level device permission (Bluetooth / USB) before proceeding.
|
|
2750
2212
|
*
|
|
@@ -2814,15 +2276,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
2814
2276
|
if (err && typeof err === "object" && "code" in err && typeof err.code === "number") {
|
|
2815
2277
|
const e = err;
|
|
2816
2278
|
const params = e.code === HardwareErrorCode3.DevicePermissionDenied && e.reason ? { permissionDeniedReason: e.reason } : e.params;
|
|
2817
|
-
return ledgerFailure(
|
|
2818
|
-
e.code,
|
|
2819
|
-
e.message ?? "Unknown error",
|
|
2820
|
-
e.appName,
|
|
2821
|
-
tag,
|
|
2822
|
-
params,
|
|
2823
|
-
void 0,
|
|
2824
|
-
isHwkRecoveryHint(e.recovery) ? e.recovery : void 0
|
|
2825
|
-
);
|
|
2279
|
+
return ledgerFailure(e.code, e.message ?? "Unknown error", e.appName, tag, params);
|
|
2826
2280
|
}
|
|
2827
2281
|
const mapped = mapLedgerError(err);
|
|
2828
2282
|
return ledgerFailure(mapped.code, mapped.message, mapped.appName, tag);
|
|
@@ -2849,7 +2303,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
2849
2303
|
deviceId: device.deviceId,
|
|
2850
2304
|
connectId: device.connectId,
|
|
2851
2305
|
label: device.name,
|
|
2852
|
-
connectionType:
|
|
2306
|
+
connectionType: this.connector.connectionType,
|
|
2853
2307
|
rssi: device.rssi,
|
|
2854
2308
|
isConnectable: device.isConnectable,
|
|
2855
2309
|
serialNumber: device.serialNumber,
|
|
@@ -3149,7 +2603,7 @@ var LedgerDeviceManager = class {
|
|
|
3149
2603
|
|
|
3150
2604
|
// src/signer/SignerManager.ts
|
|
3151
2605
|
import { SignerEthBuilder } from "@ledgerhq/device-signer-kit-ethereum";
|
|
3152
|
-
import { ContextModuleBuilder
|
|
2606
|
+
import { ContextModuleBuilder } from "@ledgerhq/context-module";
|
|
3153
2607
|
|
|
3154
2608
|
// src/signer/SignerEth.ts
|
|
3155
2609
|
import { hexToBytes } from "@onekeyfe/hwk-adapter-core";
|
|
@@ -3415,7 +2869,7 @@ var SignerManager = class _SignerManager {
|
|
|
3415
2869
|
return (args) => new SignerEthBuilder(args);
|
|
3416
2870
|
}
|
|
3417
2871
|
static _createContextModule() {
|
|
3418
|
-
const contextModule = new ContextModuleBuilder({}).
|
|
2872
|
+
const contextModule = new ContextModuleBuilder({}).removeDefaultLoaders().build();
|
|
3419
2873
|
return _SignerManager.wrapBlindSigningReportNonBlocking(contextModule);
|
|
3420
2874
|
}
|
|
3421
2875
|
static wrapBlindSigningReportNonBlocking(contextModule) {
|
|
@@ -3885,8 +3339,7 @@ function _applySignaturesToPsbt(psbtHex, signatures) {
|
|
|
3885
3339
|
}
|
|
3886
3340
|
|
|
3887
3341
|
// src/connector/chains/sol.ts
|
|
3888
|
-
import { bytesToHex, hexToBytes as hexToBytes3
|
|
3889
|
-
import bs58 from "bs58";
|
|
3342
|
+
import { bytesToHex, hexToBytes as hexToBytes3 } from "@onekeyfe/hwk-adapter-core";
|
|
3890
3343
|
|
|
3891
3344
|
// src/signer/SignerSol.ts
|
|
3892
3345
|
var SignerSol = class {
|
|
@@ -3970,21 +3423,8 @@ async function solSignMessage(ctx, sessionId, params) {
|
|
|
3970
3423
|
const path = normalizePath(params.path);
|
|
3971
3424
|
const messageBytes = hexToBytes3(params.message);
|
|
3972
3425
|
try {
|
|
3973
|
-
if (params.messageVersion === 1) {
|
|
3974
|
-
const preparedMessage = prepareSolanaOffchainMessageV1({
|
|
3975
|
-
message: messageBytes,
|
|
3976
|
-
requiredSigners: params.requiredSigners
|
|
3977
|
-
});
|
|
3978
|
-
const { SignMessageVersion } = await ctx.importLedgerKit(
|
|
3979
|
-
"@ledgerhq/device-signer-kit-solana"
|
|
3980
|
-
);
|
|
3981
|
-
const result2 = await solSigner.signMessage(path, preparedMessage.serializedMessage, {
|
|
3982
|
-
version: SignMessageVersion.Raw
|
|
3983
|
-
});
|
|
3984
|
-
return { signature: decodeBase58Signature(result2.signature) };
|
|
3985
|
-
}
|
|
3986
3426
|
const result = await solSigner.signMessage(path, messageBytes);
|
|
3987
|
-
return { signature:
|
|
3427
|
+
return { signature: result.signature };
|
|
3988
3428
|
} catch (err) {
|
|
3989
3429
|
ctx.invalidateSession(sessionId);
|
|
3990
3430
|
throw ctx.wrapError(err);
|
|
@@ -3992,27 +3432,11 @@ async function solSignMessage(ctx, sessionId, params) {
|
|
|
3992
3432
|
ctx.clearCanceller(sessionId);
|
|
3993
3433
|
}
|
|
3994
3434
|
}
|
|
3995
|
-
function decodeBase58Signature(signature) {
|
|
3996
|
-
const bytes = bs58.decode(signature);
|
|
3997
|
-
if (bytes.length !== 64) {
|
|
3998
|
-
throw new Error(`Ledger Solana signature must be 64 bytes, received ${bytes.length}`);
|
|
3999
|
-
}
|
|
4000
|
-
return bytesToHex(bytes);
|
|
4001
|
-
}
|
|
4002
|
-
function decodeBase58EnvelopeSignature(envelope) {
|
|
4003
|
-
const bytes = bs58.decode(envelope);
|
|
4004
|
-
if (bytes.length < 65 || bytes[0] !== 1) {
|
|
4005
|
-
throw new Error("Ledger Solana signature envelope is invalid");
|
|
4006
|
-
}
|
|
4007
|
-
return bytesToHex(bytes.subarray(1, 65));
|
|
4008
|
-
}
|
|
4009
3435
|
async function _createSolSigner(ctx, sessionId) {
|
|
4010
3436
|
const dmk = await ctx.getOrCreateDmk();
|
|
4011
|
-
const { ContextModuleBuilder: ContextModuleBuilder2
|
|
4012
|
-
"@ledgerhq/context-module"
|
|
4013
|
-
);
|
|
3437
|
+
const { ContextModuleBuilder: ContextModuleBuilder2 } = await ctx.importLedgerKit("@ledgerhq/context-module");
|
|
4014
3438
|
const { SignerSolanaBuilder } = await ctx.importLedgerKit("@ledgerhq/device-signer-kit-solana");
|
|
4015
|
-
const contextModule = new ContextModuleBuilder2({}).
|
|
3439
|
+
const contextModule = new ContextModuleBuilder2({}).removeDefaultLoaders().build();
|
|
4016
3440
|
const sdkSigner = new SignerSolanaBuilder({ dmk, sessionId }).withContextModule(contextModule).build();
|
|
4017
3441
|
const signer = new SignerSol(sdkSigner);
|
|
4018
3442
|
signer.onInteraction = (interaction) => {
|
|
@@ -4028,86 +3452,6 @@ async function _createSolSigner(ctx, sessionId) {
|
|
|
4028
3452
|
return signer;
|
|
4029
3453
|
}
|
|
4030
3454
|
|
|
4031
|
-
// src/connector/chains/zcash.ts
|
|
4032
|
-
import { bytesToHex as bytesToHex2 } from "@onekeyfe/hwk-adapter-core";
|
|
4033
|
-
|
|
4034
|
-
// src/signer/SignerZcash.ts
|
|
4035
|
-
var SignerZcash = class {
|
|
4036
|
-
// eslint-disable-next-line no-useless-constructor, no-empty-function
|
|
4037
|
-
constructor(_sdk) {
|
|
4038
|
-
this._sdk = _sdk;
|
|
4039
|
-
}
|
|
4040
|
-
/** GET_VK: UFVK string (default) or raw 96-byte Orchard FVK. */
|
|
4041
|
-
async getFullViewingKey(derivationPath, options) {
|
|
4042
|
-
const action = this._sdk.getFullViewingKey(derivationPath, options);
|
|
4043
|
-
return deviceActionToPromise(
|
|
4044
|
-
action,
|
|
4045
|
-
this.onInteraction,
|
|
4046
|
-
void 0,
|
|
4047
|
-
this.onRegisterCanceller
|
|
4048
|
-
);
|
|
4049
|
-
}
|
|
4050
|
-
/** GET_SHIELDED_ADDRESS: single-Orchard-receiver UA for a 5-level transparent path. */
|
|
4051
|
-
async getShieldedAddress(derivationPath, options) {
|
|
4052
|
-
const action = this._sdk.getShieldedAddress(derivationPath, options);
|
|
4053
|
-
return deviceActionToPromise(
|
|
4054
|
-
action,
|
|
4055
|
-
this.onInteraction,
|
|
4056
|
-
void 0,
|
|
4057
|
-
this.onRegisterCanceller
|
|
4058
|
-
);
|
|
4059
|
-
}
|
|
4060
|
-
};
|
|
4061
|
-
|
|
4062
|
-
// src/connector/chains/zcash.ts
|
|
4063
|
-
async function zcashGetFullViewingKey(ctx, sessionId, params) {
|
|
4064
|
-
const signer = await _createZcashSigner(ctx, sessionId);
|
|
4065
|
-
const path = normalizePath(params.path);
|
|
4066
|
-
const mode = params.mode ?? "ufvk";
|
|
4067
|
-
try {
|
|
4068
|
-
const result = await signer.getFullViewingKey(path, { mode });
|
|
4069
|
-
if (result.mode === "ufvk") {
|
|
4070
|
-
return { path: params.path, mode, ufvk: result.fullViewingKey };
|
|
4071
|
-
}
|
|
4072
|
-
return { path: params.path, mode, orchardFvk: bytesToHex2(result.fullViewingKey) };
|
|
4073
|
-
} catch (err) {
|
|
4074
|
-
ctx.invalidateSession(sessionId);
|
|
4075
|
-
throw ctx.wrapError(err);
|
|
4076
|
-
} finally {
|
|
4077
|
-
ctx.clearCanceller(sessionId);
|
|
4078
|
-
}
|
|
4079
|
-
}
|
|
4080
|
-
async function zcashGetShieldedAddress(ctx, sessionId, params) {
|
|
4081
|
-
const signer = await _createZcashSigner(ctx, sessionId);
|
|
4082
|
-
const path = normalizePath(params.path);
|
|
4083
|
-
try {
|
|
4084
|
-
const result = await signer.getShieldedAddress(path, {
|
|
4085
|
-
checkOnDevice: params.showOnDevice ?? false
|
|
4086
|
-
});
|
|
4087
|
-
return { address: result.address, path: params.path };
|
|
4088
|
-
} catch (err) {
|
|
4089
|
-
ctx.invalidateSession(sessionId);
|
|
4090
|
-
throw ctx.wrapError(err);
|
|
4091
|
-
} finally {
|
|
4092
|
-
ctx.clearCanceller(sessionId);
|
|
4093
|
-
}
|
|
4094
|
-
}
|
|
4095
|
-
async function _createZcashSigner(ctx, sessionId) {
|
|
4096
|
-
const dmk = await ctx.getOrCreateDmk();
|
|
4097
|
-
const { SignerZcashBuilder } = await ctx.importLedgerKit("@ledgerhq/device-signer-kit-zcash");
|
|
4098
|
-
const sdkSigner = new SignerZcashBuilder({ dmk, sessionId }).build();
|
|
4099
|
-
const signer = new SignerZcash(sdkSigner);
|
|
4100
|
-
signer.onInteraction = (interaction) => {
|
|
4101
|
-
debugLog("[LedgerConnector] zcash.onInteraction:", interaction);
|
|
4102
|
-
ctx.emit("ui-event", {
|
|
4103
|
-
type: collapseSignerInteraction(interaction),
|
|
4104
|
-
payload: { sessionId }
|
|
4105
|
-
});
|
|
4106
|
-
};
|
|
4107
|
-
signer.onRegisterCanceller = (cancel) => ctx.registerCanceller(sessionId, cancel);
|
|
4108
|
-
return signer;
|
|
4109
|
-
}
|
|
4110
|
-
|
|
4111
3455
|
// src/connector/chains/tron.ts
|
|
4112
3456
|
import { HardwareErrorCode as HardwareErrorCode7 } from "@onekeyfe/hwk-adapter-core";
|
|
4113
3457
|
import Trx from "@ledgerhq/hw-app-trx";
|
|
@@ -4128,7 +3472,6 @@ var APP_NAME_MAP = {
|
|
|
4128
3472
|
BTC: "Bitcoin",
|
|
4129
3473
|
SOL: "Solana",
|
|
4130
3474
|
TRX: "Tron",
|
|
4131
|
-
ZEC: "Zcash",
|
|
4132
3475
|
XRP: "XRP",
|
|
4133
3476
|
ADA: "Cardano",
|
|
4134
3477
|
DOT: "Polkadot",
|
|
@@ -4642,7 +3985,7 @@ var DeviceApps = class {
|
|
|
4642
3985
|
seTargetId: v.seTargetId,
|
|
4643
3986
|
mcuTargetId: v.mcuTargetId,
|
|
4644
3987
|
seVersion: v.seVersion,
|
|
4645
|
-
seFlagsHex:
|
|
3988
|
+
seFlagsHex: bytesToHex2(v.seFlags),
|
|
4646
3989
|
mcuSephVersion: v.mcuSephVersion,
|
|
4647
3990
|
mcuBootloaderVersion: v.mcuBootloaderVersion,
|
|
4648
3991
|
hwVersion: v.hwVersion
|
|
@@ -4716,7 +4059,7 @@ var DeviceApps = class {
|
|
|
4716
4059
|
}
|
|
4717
4060
|
}
|
|
4718
4061
|
};
|
|
4719
|
-
function
|
|
4062
|
+
function bytesToHex2(bytes) {
|
|
4720
4063
|
if (!bytes) return "";
|
|
4721
4064
|
return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
4722
4065
|
}
|
|
@@ -4759,8 +4102,7 @@ var METHOD_PREFIX_TO_APP_NAME = {
|
|
|
4759
4102
|
evm: "Ethereum",
|
|
4760
4103
|
btc: "Bitcoin",
|
|
4761
4104
|
sol: "Solana",
|
|
4762
|
-
tron: "Tron"
|
|
4763
|
-
zcash: "Zcash"
|
|
4105
|
+
tron: "Tron"
|
|
4764
4106
|
};
|
|
4765
4107
|
var HARDWARE_ERROR_CODE_VALUES = new Set(
|
|
4766
4108
|
Object.values(HardwareErrorCode8).filter((value) => typeof value === "number")
|
|
@@ -4800,8 +4142,6 @@ async function defaultLedgerKitImporter(pkg) {
|
|
|
4800
4142
|
return import("@ledgerhq/device-signer-kit-bitcoin");
|
|
4801
4143
|
case "@ledgerhq/device-signer-kit-solana":
|
|
4802
4144
|
return import("@ledgerhq/device-signer-kit-solana");
|
|
4803
|
-
case "@ledgerhq/device-signer-kit-zcash":
|
|
4804
|
-
return import("@ledgerhq/device-signer-kit-zcash");
|
|
4805
4145
|
case "@ledgerhq/context-module":
|
|
4806
4146
|
return import("@ledgerhq/context-module");
|
|
4807
4147
|
default:
|
|
@@ -5219,11 +4559,6 @@ var LedgerConnectorBase = class {
|
|
|
5219
4559
|
return solSignTransaction(ctx, sessionId, params);
|
|
5220
4560
|
case "solSignMessage":
|
|
5221
4561
|
return solSignMessage(ctx, sessionId, params);
|
|
5222
|
-
// ZCASH
|
|
5223
|
-
case "zcashGetFullViewingKey":
|
|
5224
|
-
return zcashGetFullViewingKey(ctx, sessionId, params);
|
|
5225
|
-
case "zcashGetShieldedAddress":
|
|
5226
|
-
return zcashGetShieldedAddress(ctx, sessionId, params);
|
|
5227
4562
|
// TRON
|
|
5228
4563
|
case "tronGetAddress":
|
|
5229
4564
|
return tronGetAddress(ctx, sessionId, params);
|
|
@@ -5553,7 +4888,7 @@ var LedgerConnectorBase = class {
|
|
|
5553
4888
|
* at every catch site. Falls through unchanged for unknown methods.
|
|
5554
4889
|
*/
|
|
5555
4890
|
_ctxForMethod(method) {
|
|
5556
|
-
const prefix = /^(evm|btc|sol|tron
|
|
4891
|
+
const prefix = /^(evm|btc|sol|tron)/.exec(method)?.[1];
|
|
5557
4892
|
const defaultAppName = prefix ? METHOD_PREFIX_TO_APP_NAME[prefix] : void 0;
|
|
5558
4893
|
if (!defaultAppName) return this._ctx;
|
|
5559
4894
|
return {
|
|
@@ -5597,7 +4932,6 @@ export {
|
|
|
5597
4932
|
SignerEth,
|
|
5598
4933
|
SignerManager,
|
|
5599
4934
|
SignerSol,
|
|
5600
|
-
SignerZcash,
|
|
5601
4935
|
debugLog,
|
|
5602
4936
|
deviceActionToPromise,
|
|
5603
4937
|
isDeviceLockedError,
|