@onekeyfe/hwk-trezor-adapter 1.2.2-alpha.9 → 1.2.3-alpha.2
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 +53 -25
- package/dist/index.d.ts +53 -25
- package/dist/index.js +1030 -205
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1013 -188
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -7,6 +7,18 @@
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
10
22
|
|
|
11
23
|
|
|
12
24
|
|
|
@@ -782,9 +794,21 @@ var TREZOR_BTC_NETWORK_COIN_MAP = {
|
|
|
782
794
|
dash: "Dash"
|
|
783
795
|
};
|
|
784
796
|
var _TrezorAdapter = class _TrezorAdapter {
|
|
785
|
-
constructor(connector) {
|
|
797
|
+
constructor(connector, options) {
|
|
786
798
|
this.vendor = "trezor";
|
|
787
799
|
this._emitter = new (0, _hwkadaptercore.TypedEventEmitter)();
|
|
800
|
+
this._operations = new (0, _hwkadaptercore.OperationRegistry)({
|
|
801
|
+
vendor: "trezor",
|
|
802
|
+
onEnded: (operation, reason) => {
|
|
803
|
+
this._emitter.emit(_hwkadaptercore.SDK.OPERATION_ENDED, {
|
|
804
|
+
type: _hwkadaptercore.SDK.OPERATION_ENDED,
|
|
805
|
+
payload: { operationId: operation.operationId, reason }
|
|
806
|
+
});
|
|
807
|
+
if (reason === "timeout") {
|
|
808
|
+
void this._releaseOperationConnection(operation).catch(() => void 0);
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
});
|
|
788
812
|
this._devices = /* @__PURE__ */ new Map();
|
|
789
813
|
this._sessions = /* @__PURE__ */ new Map();
|
|
790
814
|
this._connectingPromises = /* @__PURE__ */ new Map();
|
|
@@ -793,12 +817,21 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
793
817
|
this._uiRegistry = new (0, _hwkadaptercore.UiRequestRegistry)();
|
|
794
818
|
this._passphraseRequestContextByConnectId = /* @__PURE__ */ new Map();
|
|
795
819
|
this._verifiedPassphraseSessionsByConnectId = /* @__PURE__ */ new Map();
|
|
820
|
+
/** Raw connector calls that outlive an aborted caller, keyed by session. */
|
|
821
|
+
this._unsettledConnectorOperations = /* @__PURE__ */ new Map();
|
|
822
|
+
this._connectorIdleWaiters = /* @__PURE__ */ new Set();
|
|
823
|
+
this._resetPromise = null;
|
|
824
|
+
this._connectorTeardownTail = Promise.resolve();
|
|
825
|
+
this._pendingConnectorTeardowns = 0;
|
|
826
|
+
this._stateGeneration = 0;
|
|
827
|
+
this._knownDeviceConnections = /* @__PURE__ */ new Map();
|
|
796
828
|
this._onDeviceConnect = (data) => {
|
|
797
829
|
const device = this._connectorDeviceToDeviceInfo(data.device);
|
|
798
830
|
this._devices.set(device.connectId, device);
|
|
799
831
|
this._emitter.emit(_hwkadaptercore.DEVICE.CONNECT, { type: _hwkadaptercore.DEVICE.CONNECT, payload: device });
|
|
800
832
|
};
|
|
801
833
|
this._onDeviceDisconnect = (data) => {
|
|
834
|
+
this._operations.endByConnectionKey(data.connectId, "disconnect");
|
|
802
835
|
this._sessions.delete(data.connectId);
|
|
803
836
|
this._verifiedPassphraseSessionsByConnectId.delete(data.connectId);
|
|
804
837
|
this._devices.delete(data.connectId);
|
|
@@ -848,6 +881,11 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
848
881
|
});
|
|
849
882
|
};
|
|
850
883
|
this._connector = connector;
|
|
884
|
+
for (const connection of _nullishCoalesce(_optionalChain([options, 'optionalAccess', _15 => _15.knownDeviceConnections]), () => ( []))) {
|
|
885
|
+
if (connection.deviceId) {
|
|
886
|
+
this._knownDeviceConnections.set(connection.deviceId, { ...connection });
|
|
887
|
+
}
|
|
888
|
+
}
|
|
851
889
|
this._jobQueue = new (0, _hwkadaptercore.DeviceJobQueue)();
|
|
852
890
|
this._registerConnectorEvents();
|
|
853
891
|
}
|
|
@@ -872,29 +910,47 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
872
910
|
const {
|
|
873
911
|
passphraseState,
|
|
874
912
|
autoInstallApp: _autoInstallApp,
|
|
913
|
+
operationId,
|
|
875
914
|
useEmptyPassphrase,
|
|
915
|
+
knownConnections,
|
|
916
|
+
extra,
|
|
917
|
+
allowDeviceSelection,
|
|
876
918
|
...rest
|
|
877
919
|
} = params;
|
|
878
920
|
return {
|
|
879
921
|
passphraseState: typeof passphraseState === "string" ? passphraseState : void 0,
|
|
880
922
|
useEmptyPassphrase: typeof useEmptyPassphrase === "boolean" ? useEmptyPassphrase : void 0,
|
|
923
|
+
operationId: typeof operationId === "string" ? operationId : void 0,
|
|
924
|
+
connectionContext: {
|
|
925
|
+
knownConnections,
|
|
926
|
+
extra,
|
|
927
|
+
allowDeviceSelection: typeof allowDeviceSelection === "boolean" ? allowDeviceSelection : void 0
|
|
928
|
+
},
|
|
881
929
|
rest
|
|
882
930
|
};
|
|
883
931
|
}
|
|
884
932
|
return { rest: _nullishCoalesce(params, () => ( {})) };
|
|
885
933
|
}
|
|
886
934
|
static _withAllNetworkRequestCommonParams(item, commonParams) {
|
|
887
|
-
const autoInstallApp = _optionalChain([commonParams, 'optionalAccess',
|
|
888
|
-
const passphraseState = _optionalChain([commonParams, 'optionalAccess',
|
|
889
|
-
const useEmptyPassphrase = _optionalChain([commonParams, 'optionalAccess',
|
|
890
|
-
|
|
935
|
+
const autoInstallApp = _optionalChain([commonParams, 'optionalAccess', _16 => _16.autoInstallApp]);
|
|
936
|
+
const passphraseState = _optionalChain([commonParams, 'optionalAccess', _17 => _17.passphraseState]);
|
|
937
|
+
const useEmptyPassphrase = _optionalChain([commonParams, 'optionalAccess', _18 => _18.useEmptyPassphrase]);
|
|
938
|
+
const operationId = _optionalChain([commonParams, 'optionalAccess', _19 => _19.operationId]);
|
|
939
|
+
const knownConnections = _optionalChain([commonParams, 'optionalAccess', _20 => _20.knownConnections]);
|
|
940
|
+
const extra = _optionalChain([commonParams, 'optionalAccess', _21 => _21.extra]);
|
|
941
|
+
const allowDeviceSelection = _optionalChain([commonParams, 'optionalAccess', _22 => _22.allowDeviceSelection]);
|
|
942
|
+
if (autoInstallApp === void 0 && passphraseState === void 0 && useEmptyPassphrase === void 0 && operationId === void 0 && knownConnections === void 0 && extra === void 0 && allowDeviceSelection === void 0) {
|
|
891
943
|
return item;
|
|
892
944
|
}
|
|
893
945
|
return {
|
|
894
946
|
...item,
|
|
895
947
|
...autoInstallApp !== void 0 ? { autoInstallApp } : {},
|
|
896
948
|
...passphraseState !== void 0 ? { passphraseState } : {},
|
|
897
|
-
...useEmptyPassphrase !== void 0 ? { useEmptyPassphrase } : {}
|
|
949
|
+
...useEmptyPassphrase !== void 0 ? { useEmptyPassphrase } : {},
|
|
950
|
+
...operationId !== void 0 ? { operationId } : {},
|
|
951
|
+
...knownConnections !== void 0 ? { knownConnections } : {},
|
|
952
|
+
...extra !== void 0 ? { extra } : {},
|
|
953
|
+
...allowDeviceSelection !== void 0 ? { allowDeviceSelection } : {}
|
|
898
954
|
};
|
|
899
955
|
}
|
|
900
956
|
static _normalizeLogKey(key) {
|
|
@@ -950,8 +1006,8 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
950
1006
|
};
|
|
951
1007
|
}
|
|
952
1008
|
static _trezorFailureMessage(error) {
|
|
953
|
-
const response = _optionalChain([error, 'optionalAccess',
|
|
954
|
-
const message = _optionalChain([response, 'optionalAccess',
|
|
1009
|
+
const response = _optionalChain([error, 'optionalAccess', _23 => _23.response]);
|
|
1010
|
+
const message = _optionalChain([response, 'optionalAccess', _24 => _24.message]);
|
|
955
1011
|
if (!message || typeof message !== "object") return {};
|
|
956
1012
|
const failureMessage = message;
|
|
957
1013
|
return {
|
|
@@ -960,7 +1016,7 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
960
1016
|
};
|
|
961
1017
|
}
|
|
962
1018
|
static _mapTrezorFailureCode(error) {
|
|
963
|
-
const directCode = _optionalChain([error, 'optionalAccess',
|
|
1019
|
+
const directCode = _optionalChain([error, 'optionalAccess', _25 => _25.code]);
|
|
964
1020
|
if (directCode === "Device_InitializeFailed") {
|
|
965
1021
|
return _hwkadaptercore.HardwareErrorCode.PinCancelled;
|
|
966
1022
|
}
|
|
@@ -973,7 +1029,7 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
973
1029
|
if (directCode === "Failure_UnexpectedMessage") {
|
|
974
1030
|
return _hwkadaptercore.HardwareErrorCode.MethodNotSupported;
|
|
975
1031
|
}
|
|
976
|
-
const message = _optionalChain([error, 'optionalAccess',
|
|
1032
|
+
const message = _optionalChain([error, 'optionalAccess', _26 => _26.message]);
|
|
977
1033
|
if (typeof message === "string" && message.includes("Failed to execute 'transfer") && message.includes("on 'USBDevice'")) {
|
|
978
1034
|
return _hwkadaptercore.HardwareErrorCode.TransportError;
|
|
979
1035
|
}
|
|
@@ -996,6 +1052,9 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
996
1052
|
if (failure2.code === "Failure_DataError" && failure2.message === "Forbidden key path") {
|
|
997
1053
|
return _hwkadaptercore.HardwareErrorCode.DevicePathForbidden;
|
|
998
1054
|
}
|
|
1055
|
+
if (failure2.code === "Failure_DataError" && typeof failure2.message === "string" && failure2.message.includes("PASSPHRASE_ALWAYS_ON_DEVICE")) {
|
|
1056
|
+
return _hwkadaptercore.HardwareErrorCode.PassphraseAlwaysOnDevice;
|
|
1057
|
+
}
|
|
999
1058
|
if (failure2.code === "Failure_FirmwareError") {
|
|
1000
1059
|
return _hwkadaptercore.HardwareErrorCode.MethodNotSupported;
|
|
1001
1060
|
}
|
|
@@ -1015,13 +1074,11 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
1015
1074
|
* selected is gone (the device evicted it from its limited slot pool). The
|
|
1016
1075
|
* caller drops the stale cache entry and recreates from scratch.
|
|
1017
1076
|
*
|
|
1018
|
-
*
|
|
1019
|
-
*
|
|
1020
|
-
* (which would silently re-prompt the passphrase).
|
|
1077
|
+
* Match only the protocol's explicit unallocated-channel code. Guessing from
|
|
1078
|
+
* an error message could replay a request after an unrelated business error.
|
|
1021
1079
|
*/
|
|
1022
1080
|
static _isStaleSessionError(code) {
|
|
1023
|
-
|
|
1024
|
-
return code === "ThpUnallocatedChannel" || /invalid.?session|unallocated.?session|session.?not.?found/i.test(code);
|
|
1081
|
+
return code === "ThpUnallocatedChannel";
|
|
1025
1082
|
}
|
|
1026
1083
|
static _errorCode(error) {
|
|
1027
1084
|
return _nullishCoalesce(error.code, () => ( _TrezorAdapter._trezorFailureMessage(error).code));
|
|
@@ -1035,13 +1092,13 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
1035
1092
|
return protocolError.name === "TrezorProtocolError" && protocolError.code === "Malformed protocol format" && protocolError.message === "Malformed protocol format";
|
|
1036
1093
|
}
|
|
1037
1094
|
/**
|
|
1038
|
-
* Race a promise against an abort signal.
|
|
1039
|
-
*
|
|
1040
|
-
*
|
|
1041
|
-
* uselessly in the background.
|
|
1095
|
+
* Race a promise against an abort signal. IConnector.call() can't actually
|
|
1096
|
+
* be cancelled at the protocol level, so the caller gets the abort while the
|
|
1097
|
+
* adapter keeps the transport exclusively reserved until the raw call drains.
|
|
1042
1098
|
*/
|
|
1043
1099
|
static _abortable(signal, promise) {
|
|
1044
1100
|
if (signal.aborted) {
|
|
1101
|
+
void promise.catch(() => void 0);
|
|
1045
1102
|
return Promise.reject(
|
|
1046
1103
|
_nullishCoalesce(signal.reason, () => ( new Error("Aborted")))
|
|
1047
1104
|
);
|
|
@@ -1063,17 +1120,37 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
1063
1120
|
);
|
|
1064
1121
|
});
|
|
1065
1122
|
}
|
|
1066
|
-
async _connectSession(connectId, signal) {
|
|
1123
|
+
async _connectSession(connectId, signal, stateGeneration, transportType) {
|
|
1067
1124
|
const connectOnce = async () => {
|
|
1068
|
-
|
|
1069
|
-
|
|
1125
|
+
if (_optionalChain([signal, 'optionalAccess', _27 => _27.aborted])) {
|
|
1126
|
+
throw _nullishCoalesce(signal.reason, () => ( new Error("Aborted")));
|
|
1127
|
+
}
|
|
1128
|
+
this._assertConnectorIdle("connectDevice");
|
|
1129
|
+
const releaseOperation = this._retainConnectorOperation(`connect:${connectId}`);
|
|
1130
|
+
let connectPromise;
|
|
1070
1131
|
try {
|
|
1071
|
-
|
|
1132
|
+
connectPromise = transportType ? this._connector.connect(connectId, { transportType }) : this._connector.connect(connectId);
|
|
1072
1133
|
} catch (error) {
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1134
|
+
releaseOperation();
|
|
1135
|
+
throw error;
|
|
1136
|
+
}
|
|
1137
|
+
if (!signal) {
|
|
1138
|
+
try {
|
|
1139
|
+
return await connectPromise;
|
|
1140
|
+
} finally {
|
|
1141
|
+
releaseOperation();
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
try {
|
|
1145
|
+
const session2 = await _TrezorAdapter._abortable(signal, connectPromise);
|
|
1146
|
+
releaseOperation();
|
|
1147
|
+
return session2;
|
|
1148
|
+
} catch (error) {
|
|
1149
|
+
if (signal.aborted) {
|
|
1150
|
+
void connectPromise.then((orphan) => this._connector.disconnect(orphan.sessionId).catch(() => void 0)).catch(() => void 0).finally(releaseOperation);
|
|
1151
|
+
} else {
|
|
1152
|
+
releaseOperation();
|
|
1153
|
+
}
|
|
1077
1154
|
throw error;
|
|
1078
1155
|
}
|
|
1079
1156
|
};
|
|
@@ -1081,7 +1158,7 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
1081
1158
|
try {
|
|
1082
1159
|
session = await connectOnce();
|
|
1083
1160
|
} catch (error) {
|
|
1084
|
-
if (_optionalChain([signal, 'optionalAccess',
|
|
1161
|
+
if (_optionalChain([signal, 'optionalAccess', _28 => _28.aborted]) || !_TrezorAdapter._isRecoverableProtocolResidueError(error)) {
|
|
1085
1162
|
throw error;
|
|
1086
1163
|
}
|
|
1087
1164
|
debugLog("[TrezorAdapter] retrying connect after draining a stale THP frame", {
|
|
@@ -1089,8 +1166,13 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
1089
1166
|
});
|
|
1090
1167
|
session = await connectOnce();
|
|
1091
1168
|
}
|
|
1092
|
-
if (this._disconnectRequested.delete(connectId)) {
|
|
1093
|
-
|
|
1169
|
+
if (stateGeneration !== this._stateGeneration || this._disconnectRequested.delete(connectId)) {
|
|
1170
|
+
const releaseCleanup = this._retainConnectorOperation(`disconnect:${session.sessionId}`);
|
|
1171
|
+
try {
|
|
1172
|
+
await this._connector.disconnect(session.sessionId).catch(() => void 0);
|
|
1173
|
+
} finally {
|
|
1174
|
+
releaseCleanup();
|
|
1175
|
+
}
|
|
1094
1176
|
throw Object.assign(new Error("Trezor connection aborted"), {
|
|
1095
1177
|
code: _hwkadaptercore.HardwareErrorCode.UserAborted
|
|
1096
1178
|
});
|
|
@@ -1106,14 +1188,9 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
1106
1188
|
async init(_config) {
|
|
1107
1189
|
}
|
|
1108
1190
|
async dispose() {
|
|
1191
|
+
await this._resetStateAndDisconnectSessions();
|
|
1109
1192
|
this._unregisterConnectorEvents();
|
|
1110
|
-
this._uiRegistry.reset();
|
|
1111
|
-
this._jobQueue.clear();
|
|
1112
1193
|
this._connector.reset();
|
|
1113
|
-
this._devices.clear();
|
|
1114
|
-
this._sessions.clear();
|
|
1115
|
-
this._verifiedPassphraseSessionsByConnectId.clear();
|
|
1116
|
-
this._connectingPromises.clear();
|
|
1117
1194
|
this._emitter.removeAllListeners();
|
|
1118
1195
|
}
|
|
1119
1196
|
/**
|
|
@@ -1122,12 +1199,30 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
1122
1199
|
* error flows. Aborts active jobs and releases UI waits.
|
|
1123
1200
|
*/
|
|
1124
1201
|
resetState() {
|
|
1202
|
+
void this._resetStateAndDisconnectSessions();
|
|
1203
|
+
}
|
|
1204
|
+
_resetStateAndDisconnectSessions() {
|
|
1205
|
+
if (this._resetPromise) return this._resetPromise;
|
|
1206
|
+
const sessionIds = new Set(this._sessions.values());
|
|
1207
|
+
this._stateGeneration += 1;
|
|
1208
|
+
this._operations.endAll("runtime-reset");
|
|
1125
1209
|
this._uiRegistry.reset();
|
|
1126
1210
|
this._jobQueue.clear();
|
|
1127
1211
|
this._devices.clear();
|
|
1128
1212
|
this._sessions.clear();
|
|
1129
1213
|
this._verifiedPassphraseSessionsByConnectId.clear();
|
|
1130
1214
|
this._connectingPromises.clear();
|
|
1215
|
+
const resetPromise = this._runConnectorTeardown(async () => {
|
|
1216
|
+
for (const sessionId of sessionIds) {
|
|
1217
|
+
await this._connector.disconnect(sessionId).catch(() => void 0);
|
|
1218
|
+
}
|
|
1219
|
+
});
|
|
1220
|
+
this._resetPromise = resetPromise;
|
|
1221
|
+
return resetPromise.finally(() => {
|
|
1222
|
+
if (this._resetPromise === resetPromise) {
|
|
1223
|
+
this._resetPromise = null;
|
|
1224
|
+
}
|
|
1225
|
+
});
|
|
1131
1226
|
}
|
|
1132
1227
|
getAvailableTransports() {
|
|
1133
1228
|
return this.activeTransport ? [this.activeTransport] : [];
|
|
@@ -1135,32 +1230,151 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
1135
1230
|
async switchTransport(_type) {
|
|
1136
1231
|
}
|
|
1137
1232
|
async searchDevices(options) {
|
|
1138
|
-
|
|
1233
|
+
return this._searchDevices(options);
|
|
1234
|
+
}
|
|
1235
|
+
async _searchDevices(options, signal) {
|
|
1236
|
+
if (_optionalChain([options, 'optionalAccess', _29 => _29.transportType]) && !(_nullishCoalesce(this._connector.availableTransports, () => ( [this._connector.connectionType]))).includes(
|
|
1237
|
+
options.transportType
|
|
1238
|
+
))
|
|
1239
|
+
return [];
|
|
1240
|
+
if (_optionalChain([options, 'optionalAccess', _30 => _30.resetSession])) {
|
|
1241
|
+
await this._resetStateAndDisconnectSessions();
|
|
1242
|
+
} else {
|
|
1243
|
+
await this._connectorTeardownTail;
|
|
1244
|
+
}
|
|
1245
|
+
if (_optionalChain([signal, 'optionalAccess', _31 => _31.aborted])) throw signal.reason;
|
|
1246
|
+
const stateGeneration = this._stateGeneration;
|
|
1139
1247
|
const scanned = await this._connector.searchDevices(
|
|
1140
|
-
_optionalChain([options, 'optionalAccess',
|
|
1248
|
+
_optionalChain([options, 'optionalAccess', _32 => _32.waitForAllTransports]) || _optionalChain([options, 'optionalAccess', _33 => _33.transportType]) ? {
|
|
1249
|
+
...options.waitForAllTransports ? { waitForAll: true } : {},
|
|
1250
|
+
...options.transportType ? { transportType: options.transportType } : {}
|
|
1251
|
+
} : void 0
|
|
1141
1252
|
);
|
|
1253
|
+
if (_optionalChain([signal, 'optionalAccess', _34 => _34.aborted])) throw signal.reason;
|
|
1254
|
+
if (stateGeneration !== this._stateGeneration) {
|
|
1255
|
+
throw _hwkadaptercore.createHwkError.call(void 0, {
|
|
1256
|
+
code: _hwkadaptercore.HardwareErrorCode.UserAborted,
|
|
1257
|
+
message: "Trezor discovery belongs to an ended operation"
|
|
1258
|
+
});
|
|
1259
|
+
}
|
|
1142
1260
|
const scannedIds = new Set(scanned.map((d) => d.connectId));
|
|
1143
1261
|
for (const connectId of [...this._devices.keys()]) {
|
|
1144
|
-
if (!scannedIds.has(connectId) && !this._sessions.has(connectId)) {
|
|
1262
|
+
if ((!_optionalChain([options, 'optionalAccess', _35 => _35.transportType]) || _optionalChain([this, 'access', _36 => _36._devices, 'access', _37 => _37.get, 'call', _38 => _38(connectId), 'optionalAccess', _39 => _39.connectionType]) === options.transportType) && !scannedIds.has(connectId) && !this._sessions.has(connectId)) {
|
|
1145
1263
|
this._devices.delete(connectId);
|
|
1146
1264
|
}
|
|
1147
1265
|
}
|
|
1148
1266
|
for (const device of scanned) {
|
|
1149
1267
|
const info = this._connectorDeviceToDeviceInfo(device);
|
|
1150
|
-
this._devices.set(info.connectId, info);
|
|
1268
|
+
if (!this._sessions.has(info.connectId)) this._devices.set(info.connectId, info);
|
|
1269
|
+
}
|
|
1270
|
+
return Array.from(this._devices.values()).filter(
|
|
1271
|
+
(device) => !_optionalChain([options, 'optionalAccess', _40 => _40.transportType]) || device.connectionType === options.transportType
|
|
1272
|
+
);
|
|
1273
|
+
}
|
|
1274
|
+
async searchDeviceTargets(options) {
|
|
1275
|
+
const devices = await this.searchDevices(options);
|
|
1276
|
+
return devices.map((device) => ({
|
|
1277
|
+
searchTargetId: device.connectId,
|
|
1278
|
+
searchTargetReusePolicy: _hwkadaptercore.resolveSearchTargetReusePolicy.call(void 0, device),
|
|
1279
|
+
vendor: "trezor",
|
|
1280
|
+
connectionType: device.connectionType,
|
|
1281
|
+
kind: "physical",
|
|
1282
|
+
label: device.label,
|
|
1283
|
+
model: device.model,
|
|
1284
|
+
modelName: device.modelName,
|
|
1285
|
+
serialNumber: device.serialNumber
|
|
1286
|
+
}));
|
|
1287
|
+
}
|
|
1288
|
+
async listConnectionTargets(options) {
|
|
1289
|
+
const targets = await this.searchDeviceTargets(options);
|
|
1290
|
+
return targets.map(({ searchTargetId, ...target }) => ({
|
|
1291
|
+
...target,
|
|
1292
|
+
targetId: searchTargetId
|
|
1293
|
+
}));
|
|
1294
|
+
}
|
|
1295
|
+
async bindBleDevice(params) {
|
|
1296
|
+
if (params.identity.vendor !== "trezor" || !params.identity.value) {
|
|
1297
|
+
return _hwkadaptercore.failure.call(void 0, _hwkadaptercore.HardwareErrorCode.InvalidParams, "Trezor device identity is required");
|
|
1298
|
+
}
|
|
1299
|
+
const { value: deviceId } = params.identity;
|
|
1300
|
+
try {
|
|
1301
|
+
return await this._jobQueue.enqueue(
|
|
1302
|
+
deviceId,
|
|
1303
|
+
async (signal) => {
|
|
1304
|
+
const selected = await this._selectBleDeviceForBinding(
|
|
1305
|
+
deviceId,
|
|
1306
|
+
signal,
|
|
1307
|
+
{ extra: params.extra },
|
|
1308
|
+
"manual-rebind"
|
|
1309
|
+
);
|
|
1310
|
+
try {
|
|
1311
|
+
const persisted = await this._emitVerifiedBinding(
|
|
1312
|
+
deviceId,
|
|
1313
|
+
selected.connectId,
|
|
1314
|
+
selected.selectionRequestId,
|
|
1315
|
+
{ extra: params.extra },
|
|
1316
|
+
signal
|
|
1317
|
+
);
|
|
1318
|
+
if (!persisted) {
|
|
1319
|
+
throw _hwkadaptercore.createHwkError.call(void 0, {
|
|
1320
|
+
code: _hwkadaptercore.HardwareErrorCode.UnknownError,
|
|
1321
|
+
message: "Bluetooth binding could not be saved",
|
|
1322
|
+
origin: "host"
|
|
1323
|
+
});
|
|
1324
|
+
}
|
|
1325
|
+
this._rememberVerifiedConnection(deviceId, selected.connectId);
|
|
1326
|
+
return _hwkadaptercore.success.call(void 0, selected.connectId);
|
|
1327
|
+
} catch (error) {
|
|
1328
|
+
await this._releaseProvisionalConnection(selected.connectId, signal);
|
|
1329
|
+
throw error;
|
|
1330
|
+
}
|
|
1331
|
+
},
|
|
1332
|
+
{
|
|
1333
|
+
label: "bindBleDevice",
|
|
1334
|
+
rejectIfBusy: true,
|
|
1335
|
+
busyError: _TrezorAdapter._createDeviceBusyError("bindBleDevice")
|
|
1336
|
+
}
|
|
1337
|
+
);
|
|
1338
|
+
} catch (error) {
|
|
1339
|
+
return this._errorToFailure(error);
|
|
1151
1340
|
}
|
|
1152
|
-
return Array.from(this._devices.values());
|
|
1153
1341
|
}
|
|
1154
|
-
async connectDevice(
|
|
1342
|
+
async connectDevice(searchTargetId) {
|
|
1155
1343
|
try {
|
|
1156
|
-
await this._ensureDevicePermission(
|
|
1157
|
-
|
|
1158
|
-
|
|
1344
|
+
await this._ensureDevicePermission(
|
|
1345
|
+
searchTargetId,
|
|
1346
|
+
void 0,
|
|
1347
|
+
_optionalChain([this, 'access', _41 => _41._devices, 'access', _42 => _42.get, 'call', _43 => _43(searchTargetId), 'optionalAccess', _44 => _44.connectionType])
|
|
1348
|
+
);
|
|
1349
|
+
await this._ensureSession(searchTargetId);
|
|
1350
|
+
const device = this._devices.get(searchTargetId);
|
|
1351
|
+
if (!device) {
|
|
1352
|
+
return _hwkadaptercore.failure.call(void 0, _hwkadaptercore.HardwareErrorCode.DeviceNotFound, "Trezor device not found after connect");
|
|
1353
|
+
}
|
|
1354
|
+
this._operations.endByConnectionKey(searchTargetId, "explicit");
|
|
1355
|
+
const operation = this._operations.create({
|
|
1356
|
+
searchTargetId,
|
|
1357
|
+
connectId: searchTargetId,
|
|
1358
|
+
device,
|
|
1359
|
+
connectionKeys: [_nullishCoalesce(this._sessions.get(searchTargetId), () => ( ""))]
|
|
1360
|
+
});
|
|
1361
|
+
return _hwkadaptercore.success.call(void 0, operation.operationId);
|
|
1159
1362
|
} catch (error) {
|
|
1160
1363
|
return this._errorToFailure(error);
|
|
1161
1364
|
}
|
|
1162
1365
|
}
|
|
1163
|
-
async
|
|
1366
|
+
async releaseOperation(operationId) {
|
|
1367
|
+
const operation = this._operations.find(operationId);
|
|
1368
|
+
if (!operation) {
|
|
1369
|
+
this._operations.resolve(operationId);
|
|
1370
|
+
return;
|
|
1371
|
+
}
|
|
1372
|
+
const endedOperation = this._operations.end(operationId, "explicit");
|
|
1373
|
+
if (!endedOperation) return;
|
|
1374
|
+
await this._releaseOperationConnection(endedOperation);
|
|
1375
|
+
}
|
|
1376
|
+
async _releaseOperationConnection(operation) {
|
|
1377
|
+
const { connectId } = operation;
|
|
1164
1378
|
const connecting = this._connectingPromises.has(connectId);
|
|
1165
1379
|
this._connectingPromises.delete(connectId);
|
|
1166
1380
|
const sessionId = this._sessions.get(connectId);
|
|
@@ -1170,87 +1384,119 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
1170
1384
|
}
|
|
1171
1385
|
this._sessions.delete(connectId);
|
|
1172
1386
|
this._verifiedPassphraseSessionsByConnectId.delete(connectId);
|
|
1173
|
-
await this._connector.disconnect(sessionId);
|
|
1387
|
+
await this._runConnectorTeardown(() => this._connector.disconnect(sessionId));
|
|
1174
1388
|
}
|
|
1175
|
-
async getDeviceInfo(
|
|
1389
|
+
async getDeviceInfo(connectIdOrOperationId, deviceId) {
|
|
1390
|
+
let connectId;
|
|
1391
|
+
try {
|
|
1392
|
+
connectId = _hwkadaptercore.isHardwareOperationId.call(void 0, connectIdOrOperationId) ? this._operations.resolve(connectIdOrOperationId).connectId : connectIdOrOperationId;
|
|
1393
|
+
} catch (error) {
|
|
1394
|
+
return this._errorToFailure(error);
|
|
1395
|
+
}
|
|
1176
1396
|
const device = _nullishCoalesce(this._devices.get(connectId), () => ( Array.from(this._devices.values()).find((item) => item.deviceId === deviceId)));
|
|
1177
1397
|
if (!device) return _hwkadaptercore.failure.call(void 0, _hwkadaptercore.HardwareErrorCode.DeviceNotFound, "Trezor device not found");
|
|
1178
1398
|
return _hwkadaptercore.success.call(void 0, device);
|
|
1179
1399
|
}
|
|
1180
|
-
getSupportedChains() {
|
|
1181
|
-
return ["btc", "evm", "sol", "tron"];
|
|
1182
|
-
}
|
|
1183
1400
|
async allNetworkGetAddress(connectId, deviceId, params) {
|
|
1401
|
+
const target = _hwkadaptercore.resolveHardwareOperationTarget.call(void 0, connectId, params.operationId, "trezor");
|
|
1402
|
+
if (!target.success) return target;
|
|
1403
|
+
let effectiveTargetId = _nullishCoalesce(target.payload.targetId, () => ( ""));
|
|
1404
|
+
let releaseOperationRetention;
|
|
1405
|
+
try {
|
|
1406
|
+
releaseOperationRetention = target.payload.operationId ? this._operations.retain(target.payload.operationId) : void 0;
|
|
1407
|
+
} catch (error) {
|
|
1408
|
+
return this._errorToFailure(error);
|
|
1409
|
+
}
|
|
1184
1410
|
let liveDeviceId = "";
|
|
1411
|
+
const bundleContext = {};
|
|
1185
1412
|
const topLevelFailureIndexes = /* @__PURE__ */ new Set();
|
|
1186
1413
|
const isSingleNetworkBundle = params.bundle.every(
|
|
1187
|
-
(item) => item.network === _optionalChain([params, 'access',
|
|
1414
|
+
(item) => item.network === _optionalChain([params, 'access', _45 => _45.bundle, 'access', _46 => _46[0], 'optionalAccess', _47 => _47.network])
|
|
1188
1415
|
);
|
|
1189
|
-
const getLiveDeviceId = async () => {
|
|
1416
|
+
const getLiveDeviceId = async (expectedDeviceId) => {
|
|
1190
1417
|
if (liveDeviceId) return _hwkadaptercore.success.call(void 0, liveDeviceId);
|
|
1191
|
-
const deviceIdResponse = await this._getTrezorDeviceId(
|
|
1418
|
+
const deviceIdResponse = await this._getTrezorDeviceId(
|
|
1419
|
+
effectiveTargetId,
|
|
1420
|
+
expectedDeviceId || deviceId,
|
|
1421
|
+
params,
|
|
1422
|
+
bundleContext
|
|
1423
|
+
);
|
|
1192
1424
|
if (deviceIdResponse.success) {
|
|
1193
1425
|
liveDeviceId = deviceIdResponse.payload;
|
|
1426
|
+
if (!target.payload.operationId) {
|
|
1427
|
+
effectiveTargetId = _nullishCoalesce(_optionalChain([bundleContext, 'access', _48 => _48.connection, 'optionalAccess', _49 => _49.connectId]), () => ( effectiveTargetId));
|
|
1428
|
+
}
|
|
1194
1429
|
}
|
|
1195
1430
|
return deviceIdResponse;
|
|
1196
1431
|
};
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
_hwkadaptercore.
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1432
|
+
try {
|
|
1433
|
+
return await _hwkadaptercore.runAllNetworkGetAddress.call(void 0, {
|
|
1434
|
+
connectId: effectiveTargetId,
|
|
1435
|
+
deviceId,
|
|
1436
|
+
params,
|
|
1437
|
+
normalizeItem: _TrezorAdapter._normalizeAllNetworkItem,
|
|
1438
|
+
callItem: async ({ method, item, index }) => {
|
|
1439
|
+
const expectedDeviceId = _nullishCoalesce(_TrezorAdapter._getItemDeviceId(item), () => ( deviceId));
|
|
1440
|
+
if (expectedDeviceId) {
|
|
1441
|
+
const fingerprint = await getLiveDeviceId(expectedDeviceId);
|
|
1442
|
+
if (!fingerprint.success) {
|
|
1443
|
+
topLevelFailureIndexes.add(index);
|
|
1444
|
+
return fingerprint;
|
|
1445
|
+
}
|
|
1446
|
+
if (expectedDeviceId !== fingerprint.payload) {
|
|
1447
|
+
topLevelFailureIndexes.add(index);
|
|
1448
|
+
return _hwkadaptercore.failure.call(void 0,
|
|
1449
|
+
_hwkadaptercore.HardwareErrorCode.DeviceMismatch,
|
|
1450
|
+
`Wrong device: expected ${expectedDeviceId}, got ${fingerprint.payload}`,
|
|
1451
|
+
{ expected: expectedDeviceId, actual: fingerprint.payload }
|
|
1452
|
+
);
|
|
1453
|
+
}
|
|
1217
1454
|
}
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1455
|
+
const callItem = _TrezorAdapter._withAllNetworkRequestCommonParams(item, params);
|
|
1456
|
+
return this._callAllNetworkMethod(effectiveTargetId, method, callItem, bundleContext);
|
|
1457
|
+
},
|
|
1458
|
+
attachIdentity: async ({ item, chain, payload }) => {
|
|
1459
|
+
if (!liveDeviceId) {
|
|
1460
|
+
const fingerprint = await getLiveDeviceId(deviceId);
|
|
1461
|
+
if (!fingerprint.success) {
|
|
1462
|
+
return { ...item, success: false, payload: fingerprint.payload };
|
|
1463
|
+
}
|
|
1227
1464
|
}
|
|
1465
|
+
return {
|
|
1466
|
+
...item,
|
|
1467
|
+
success: true,
|
|
1468
|
+
payload: {
|
|
1469
|
+
...payload,
|
|
1470
|
+
deviceIdentity: {
|
|
1471
|
+
vendor: "trezor",
|
|
1472
|
+
type: "deviceId",
|
|
1473
|
+
value: liveDeviceId
|
|
1474
|
+
},
|
|
1475
|
+
chainFingerprint: liveDeviceId,
|
|
1476
|
+
chainFingerprintChain: chain
|
|
1477
|
+
}
|
|
1478
|
+
};
|
|
1479
|
+
},
|
|
1480
|
+
// One named boolean per abort reason.
|
|
1481
|
+
shouldAbortBundle: (response, { index }) => {
|
|
1482
|
+
const isSessionLevelFailure = topLevelFailureIndexes.has(index);
|
|
1483
|
+
const isWholeChainForbidden = isSingleNetworkBundle && _optionalChain([response, 'access', _50 => _50.payload, 'optionalAccess', _51 => _51.code]) === _hwkadaptercore.HardwareErrorCode.DevicePathForbidden;
|
|
1484
|
+
const isPassphrasePolicyFailure = _optionalChain([response, 'access', _52 => _52.payload, 'optionalAccess', _53 => _53.code]) === _hwkadaptercore.HardwareErrorCode.PassphraseAlwaysOnDevice;
|
|
1485
|
+
const isConnectionLost = _optionalChain([response, 'access', _54 => _54.payload, 'optionalAccess', _55 => _55.code]) === _hwkadaptercore.HardwareErrorCode.DeviceDisconnected || _optionalChain([response, 'access', _56 => _56.payload, 'optionalAccess', _57 => _57.code]) === _hwkadaptercore.HardwareErrorCode.OperationTimeout || _optionalChain([response, 'access', _58 => _58.payload, 'optionalAccess', _59 => _59.code]) === _hwkadaptercore.HardwareErrorCode.TransportError || _optionalChain([response, 'access', _60 => _60.payload, 'optionalAccess', _61 => _61.code]) === _hwkadaptercore.HardwareErrorCode.OperationEnded || _optionalChain([response, 'access', _62 => _62.payload, 'optionalAccess', _63 => _63.code]) === _hwkadaptercore.HardwareErrorCode.OperationNotFound;
|
|
1486
|
+
return isSessionLevelFailure || isWholeChainForbidden || isPassphrasePolicyFailure || isConnectionLost;
|
|
1228
1487
|
}
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
...payload,
|
|
1234
|
-
deviceIdentity: {
|
|
1235
|
-
vendor: "trezor",
|
|
1236
|
-
type: "deviceId",
|
|
1237
|
-
value: liveDeviceId
|
|
1238
|
-
},
|
|
1239
|
-
chainFingerprint: liveDeviceId,
|
|
1240
|
-
chainFingerprintChain: chain
|
|
1241
|
-
}
|
|
1242
|
-
};
|
|
1243
|
-
},
|
|
1244
|
-
// One named boolean per abort reason.
|
|
1245
|
-
shouldAbortBundle: (response, { index }) => {
|
|
1246
|
-
const isSessionLevelFailure = topLevelFailureIndexes.has(index);
|
|
1247
|
-
const isWholeChainForbidden = isSingleNetworkBundle && _optionalChain([response, 'access', _27 => _27.payload, 'optionalAccess', _28 => _28.code]) === _hwkadaptercore.HardwareErrorCode.DevicePathForbidden;
|
|
1248
|
-
return isSessionLevelFailure || isWholeChainForbidden;
|
|
1249
|
-
}
|
|
1250
|
-
});
|
|
1488
|
+
});
|
|
1489
|
+
} finally {
|
|
1490
|
+
_optionalChain([releaseOperationRetention, 'optionalCall', _64 => _64()]);
|
|
1491
|
+
}
|
|
1251
1492
|
}
|
|
1252
|
-
getFeatures(connectId) {
|
|
1253
|
-
return this._callDeviceManagerMethod(
|
|
1493
|
+
getFeatures(connectId, operationContext) {
|
|
1494
|
+
return this._callDeviceManagerMethod(
|
|
1495
|
+
"getFeatures",
|
|
1496
|
+
connectId,
|
|
1497
|
+
{},
|
|
1498
|
+
operationContext
|
|
1499
|
+
);
|
|
1254
1500
|
}
|
|
1255
1501
|
/**
|
|
1256
1502
|
* Device authenticity attestation. Sends a host-generated challenge, has the
|
|
@@ -1285,7 +1531,7 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
1285
1531
|
if (!internalModel) {
|
|
1286
1532
|
return _hwkadaptercore.failure.call(void 0, _hwkadaptercore.HardwareErrorCode.UnknownError, "Device internal_model unavailable");
|
|
1287
1533
|
}
|
|
1288
|
-
const challengeHex = _nullishCoalesce(_optionalChain([params, 'access',
|
|
1534
|
+
const challengeHex = _nullishCoalesce(_optionalChain([params, 'access', _65 => _65.challenge, 'optionalAccess', _66 => _66.toLowerCase, 'call', _67 => _67()]), () => ( Buffer.from(_utils.randomBytes.call(void 0, 32)).toString("hex")));
|
|
1289
1535
|
const challenge = Buffer.from(challengeHex, "hex");
|
|
1290
1536
|
const proofRes = await this._callDeviceManagerMethod(
|
|
1291
1537
|
"authenticateDevice",
|
|
@@ -1310,28 +1556,64 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
1310
1556
|
}
|
|
1311
1557
|
});
|
|
1312
1558
|
}
|
|
1313
|
-
deviceSettings(connectId, params) {
|
|
1559
|
+
deviceSettings(connectId, params, operationContext) {
|
|
1314
1560
|
return this._callDeviceManagerMethod(
|
|
1315
1561
|
"deviceSettings",
|
|
1316
1562
|
connectId,
|
|
1317
|
-
params
|
|
1563
|
+
params,
|
|
1564
|
+
operationContext
|
|
1318
1565
|
);
|
|
1319
1566
|
}
|
|
1320
|
-
setBrightness(connectId, params = {}) {
|
|
1567
|
+
setBrightness(connectId, params = {}, operationContext) {
|
|
1321
1568
|
return this._callDeviceManagerMethod(
|
|
1322
1569
|
"setBrightness",
|
|
1323
1570
|
connectId,
|
|
1324
|
-
params
|
|
1571
|
+
params,
|
|
1572
|
+
operationContext
|
|
1325
1573
|
);
|
|
1326
1574
|
}
|
|
1327
|
-
changePin(connectId, params = {}) {
|
|
1328
|
-
return this._callDeviceManagerMethod(
|
|
1575
|
+
changePin(connectId, params = {}, operationContext) {
|
|
1576
|
+
return this._callDeviceManagerMethod(
|
|
1577
|
+
"changePin",
|
|
1578
|
+
connectId,
|
|
1579
|
+
params,
|
|
1580
|
+
operationContext
|
|
1581
|
+
);
|
|
1329
1582
|
}
|
|
1330
|
-
wipeDevice(connectId) {
|
|
1331
|
-
return this._callDeviceManagerMethod(
|
|
1583
|
+
wipeDevice(connectId, operationContext) {
|
|
1584
|
+
return this._callDeviceManagerMethod(
|
|
1585
|
+
"wipeDevice",
|
|
1586
|
+
connectId,
|
|
1587
|
+
{},
|
|
1588
|
+
operationContext
|
|
1589
|
+
);
|
|
1332
1590
|
}
|
|
1333
|
-
async _getTrezorDeviceId(connectId) {
|
|
1334
|
-
const
|
|
1591
|
+
async _getTrezorDeviceId(connectId, expectedDeviceId, commonParams, bundleContext) {
|
|
1592
|
+
const hasConnectionContext = _optionalChain([commonParams, 'optionalAccess', _68 => _68.knownConnections]) !== void 0 || _optionalChain([commonParams, 'optionalAccess', _69 => _69.extra]) !== void 0;
|
|
1593
|
+
const features = bundleContext || hasConnectionContext ? await this._callMethod(
|
|
1594
|
+
"getFeatures",
|
|
1595
|
+
connectId,
|
|
1596
|
+
hasConnectionContext || !connectId ? expectedDeviceId : void 0,
|
|
1597
|
+
hasConnectionContext ? {
|
|
1598
|
+
operationId: commonParams.operationId,
|
|
1599
|
+
knownConnections: commonParams.knownConnections,
|
|
1600
|
+
extra: commonParams.extra,
|
|
1601
|
+
allowDeviceSelection: commonParams.allowDeviceSelection,
|
|
1602
|
+
passphraseState: commonParams.passphraseState,
|
|
1603
|
+
useEmptyPassphrase: commonParams.useEmptyPassphrase
|
|
1604
|
+
} : {},
|
|
1605
|
+
false,
|
|
1606
|
+
bundleContext
|
|
1607
|
+
) : await this.getFeatures(
|
|
1608
|
+
connectId,
|
|
1609
|
+
!connectId && expectedDeviceId ? {
|
|
1610
|
+
expectedDeviceIdentity: {
|
|
1611
|
+
vendor: "trezor",
|
|
1612
|
+
type: "deviceId",
|
|
1613
|
+
value: expectedDeviceId
|
|
1614
|
+
}
|
|
1615
|
+
} : void 0
|
|
1616
|
+
);
|
|
1335
1617
|
if (!features.success) return features;
|
|
1336
1618
|
const liveDeviceId = features.payload.device_id;
|
|
1337
1619
|
if (typeof liveDeviceId !== "string" || liveDeviceId.length === 0) {
|
|
@@ -1345,14 +1627,30 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
1345
1627
|
});
|
|
1346
1628
|
this._uiRegistry.cancel();
|
|
1347
1629
|
this._connector.uiResponse({ type: _hwkadaptercore.UI_RESPONSE.CANCEL });
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1630
|
+
const activeJobId = _optionalChain([this, 'access', _70 => _70._jobQueue, 'access', _71 => _71.getActiveJob, 'call', _72 => _72(), 'optionalAccess', _73 => _73.deviceId]);
|
|
1631
|
+
const targetId = _nullishCoalesce(connectId, () => ( activeJobId));
|
|
1632
|
+
if (targetId) {
|
|
1633
|
+
let resolvedConnectId = targetId;
|
|
1634
|
+
let operationId;
|
|
1635
|
+
if (_hwkadaptercore.isHardwareOperationId.call(void 0, targetId)) {
|
|
1636
|
+
try {
|
|
1637
|
+
operationId = targetId;
|
|
1638
|
+
resolvedConnectId = this._operations.resolve(targetId).connectId;
|
|
1639
|
+
} catch (e5) {
|
|
1640
|
+
resolvedConnectId = "";
|
|
1641
|
+
}
|
|
1642
|
+
}
|
|
1643
|
+
const interactionForPhysicalId = !operationId && connectId ? this._operations.findActiveByConnectionKey(connectId) : void 0;
|
|
1644
|
+
this._jobQueue.cancelActive(
|
|
1645
|
+
_nullishCoalesce(_nullishCoalesce(operationId, () => ( (activeJobId === targetId ? targetId : _optionalChain([interactionForPhysicalId, 'optionalAccess', _74 => _74.operationId])))), () => ( targetId)),
|
|
1646
|
+
userAbortReason
|
|
1647
|
+
);
|
|
1648
|
+
if (resolvedConnectId) {
|
|
1649
|
+
void this._connector.cancel(_nullishCoalesce(this._sessions.get(resolvedConnectId), () => ( resolvedConnectId)));
|
|
1650
|
+
}
|
|
1351
1651
|
return;
|
|
1352
1652
|
}
|
|
1353
|
-
|
|
1354
|
-
this._jobQueue.forceCancelActive(cid, userAbortReason);
|
|
1355
|
-
}
|
|
1653
|
+
this._jobQueue.cancelActive(void 0, userAbortReason);
|
|
1356
1654
|
for (const sessionId of this._sessions.values()) {
|
|
1357
1655
|
void this._connector.cancel(sessionId);
|
|
1358
1656
|
}
|
|
@@ -1365,6 +1663,7 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
1365
1663
|
*/
|
|
1366
1664
|
uiResponse(response) {
|
|
1367
1665
|
this._uiRegistry.resolve(response.type, response.payload);
|
|
1666
|
+
if (response.type === _hwkadaptercore.UI_RESPONSE.RECEIVE_SELECT_DEVICE) return;
|
|
1368
1667
|
this._connector.uiResponse(response);
|
|
1369
1668
|
}
|
|
1370
1669
|
/**
|
|
@@ -1376,8 +1675,8 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
1376
1675
|
* Unlike Ledger (which hashes a per-chain address), it is chain-global, so
|
|
1377
1676
|
* `chain` is accepted for API parity but ignored.
|
|
1378
1677
|
*/
|
|
1379
|
-
async getChainFingerprint(connectId,
|
|
1380
|
-
return this._getTrezorDeviceId(connectId);
|
|
1678
|
+
async getChainFingerprint(connectId, deviceId, _chain) {
|
|
1679
|
+
return this._getTrezorDeviceId(connectId, deviceId);
|
|
1381
1680
|
}
|
|
1382
1681
|
/**
|
|
1383
1682
|
* Resolve the active passphrase wallet identity (`passphraseState`).
|
|
@@ -1387,17 +1686,93 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
1387
1686
|
* can't interleave with a chain call on the same device (which would desync
|
|
1388
1687
|
* the THP session selection).
|
|
1389
1688
|
*/
|
|
1390
|
-
getPassphraseState(connectId, passphraseState) {
|
|
1391
|
-
|
|
1689
|
+
getPassphraseState(connectId, passphraseState, operationContext) {
|
|
1690
|
+
const expectedIdentity = _optionalChain([operationContext, 'optionalAccess', _75 => _75.expectedDeviceIdentity]);
|
|
1691
|
+
if (expectedIdentity && (expectedIdentity.vendor !== "trezor" || expectedIdentity.type !== "deviceId")) {
|
|
1692
|
+
return Promise.resolve(
|
|
1693
|
+
_hwkadaptercore.failure.call(void 0, _hwkadaptercore.HardwareErrorCode.InvalidParams, "Trezor device identity is required")
|
|
1694
|
+
);
|
|
1695
|
+
}
|
|
1696
|
+
const target = _hwkadaptercore.resolveHardwareOperationTarget.call(void 0,
|
|
1392
1697
|
connectId,
|
|
1698
|
+
_optionalChain([operationContext, 'optionalAccess', _76 => _76.operationId]),
|
|
1699
|
+
"trezor"
|
|
1700
|
+
);
|
|
1701
|
+
if (!target.success) return Promise.resolve(target);
|
|
1702
|
+
const { operationId } = target.payload;
|
|
1703
|
+
let resolvedConnectId = _nullishCoalesce(target.payload.targetId, () => ( ""));
|
|
1704
|
+
let releaseOperationRetention;
|
|
1705
|
+
if (operationId) {
|
|
1706
|
+
try {
|
|
1707
|
+
resolvedConnectId = this._operations.resolve(operationId).connectId;
|
|
1708
|
+
releaseOperationRetention = this._operations.retain(operationId);
|
|
1709
|
+
} catch (error) {
|
|
1710
|
+
return Promise.resolve(this._errorToFailure(error));
|
|
1711
|
+
}
|
|
1712
|
+
}
|
|
1713
|
+
return this._jobQueue.enqueue(
|
|
1714
|
+
operationId || resolvedConnectId,
|
|
1393
1715
|
async (signal) => {
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
});
|
|
1716
|
+
let selectionRequestId;
|
|
1717
|
+
let verified = false;
|
|
1397
1718
|
try {
|
|
1398
|
-
|
|
1719
|
+
if (!operationId && _optionalChain([expectedIdentity, 'optionalAccess', _77 => _77.value]) && (!connectId || _optionalChain([operationContext, 'optionalAccess', _78 => _78.knownConnections]) !== void 0)) {
|
|
1720
|
+
const resolved = await this._resolveExpectedDeviceConnectId(
|
|
1721
|
+
expectedIdentity.value,
|
|
1722
|
+
signal,
|
|
1723
|
+
operationContext
|
|
1724
|
+
);
|
|
1725
|
+
resolvedConnectId = resolved.connectId;
|
|
1726
|
+
selectionRequestId = resolved.selectionRequestId;
|
|
1727
|
+
}
|
|
1728
|
+
if (_optionalChain([expectedIdentity, 'optionalAccess', _79 => _79.value])) {
|
|
1729
|
+
if (!operationId) await this._ensureSession(resolvedConnectId, signal);
|
|
1730
|
+
if (_optionalChain([this, 'access', _80 => _80._devices, 'access', _81 => _81.get, 'call', _82 => _82(resolvedConnectId), 'optionalAccess', _83 => _83.deviceId]) !== expectedIdentity.value) {
|
|
1731
|
+
return _hwkadaptercore.failure.call(void 0,
|
|
1732
|
+
_hwkadaptercore.HardwareErrorCode.DeviceMismatch,
|
|
1733
|
+
"Trezor device identity does not match"
|
|
1734
|
+
);
|
|
1735
|
+
}
|
|
1736
|
+
}
|
|
1737
|
+
const restorePassphraseRequestContext = this._setPassphraseRequestContext(
|
|
1738
|
+
resolvedConnectId,
|
|
1739
|
+
{
|
|
1740
|
+
passphraseState
|
|
1741
|
+
}
|
|
1742
|
+
);
|
|
1743
|
+
try {
|
|
1744
|
+
const result = await this._resolvePassphraseState(
|
|
1745
|
+
resolvedConnectId,
|
|
1746
|
+
passphraseState,
|
|
1747
|
+
signal,
|
|
1748
|
+
operationId
|
|
1749
|
+
);
|
|
1750
|
+
if (result.success && _optionalChain([expectedIdentity, 'optionalAccess', _84 => _84.value])) {
|
|
1751
|
+
await this._emitVerifiedBinding(
|
|
1752
|
+
expectedIdentity.value,
|
|
1753
|
+
resolvedConnectId,
|
|
1754
|
+
selectionRequestId,
|
|
1755
|
+
operationContext,
|
|
1756
|
+
signal
|
|
1757
|
+
);
|
|
1758
|
+
verified = true;
|
|
1759
|
+
this._rememberVerifiedConnection(expectedIdentity.value, resolvedConnectId);
|
|
1760
|
+
}
|
|
1761
|
+
return result;
|
|
1762
|
+
} finally {
|
|
1763
|
+
restorePassphraseRequestContext();
|
|
1764
|
+
}
|
|
1399
1765
|
} finally {
|
|
1400
|
-
|
|
1766
|
+
if (selectionRequestId && !verified) {
|
|
1767
|
+
this._emitter.emit(_hwkadaptercore.UI_REQUEST.DEVICE_BINDING_STATUS, {
|
|
1768
|
+
type: _hwkadaptercore.UI_REQUEST.DEVICE_BINDING_STATUS,
|
|
1769
|
+
payload: {
|
|
1770
|
+
selectionRequestId,
|
|
1771
|
+
status: signal.aborted ? "cancelled" : "failed"
|
|
1772
|
+
}
|
|
1773
|
+
});
|
|
1774
|
+
await this._releaseProvisionalConnection(resolvedConnectId, signal);
|
|
1775
|
+
}
|
|
1401
1776
|
}
|
|
1402
1777
|
},
|
|
1403
1778
|
{
|
|
@@ -1405,7 +1780,7 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
1405
1780
|
rejectIfBusy: true,
|
|
1406
1781
|
busyError: _TrezorAdapter._createDeviceBusyError("getPassphraseState")
|
|
1407
1782
|
}
|
|
1408
|
-
).catch((error) => this._errorToFailure(error));
|
|
1783
|
+
).catch((error) => this._errorToFailure(error)).finally(() => _optionalChain([releaseOperationRetention, 'optionalCall', _85 => _85()]));
|
|
1409
1784
|
}
|
|
1410
1785
|
evmGetAddress(connectId, deviceId, params) {
|
|
1411
1786
|
return this._callWalletMethod("evmGetAddress", connectId, deviceId, params);
|
|
@@ -1468,11 +1843,86 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
1468
1843
|
}
|
|
1469
1844
|
return result;
|
|
1470
1845
|
}
|
|
1471
|
-
|
|
1472
|
-
|
|
1846
|
+
async _callConnector(sessionId, method, params, signal) {
|
|
1847
|
+
if (_optionalChain([signal, 'optionalAccess', _86 => _86.aborted])) {
|
|
1848
|
+
throw _nullishCoalesce(signal.reason, () => ( new Error("Aborted")));
|
|
1849
|
+
}
|
|
1850
|
+
this._assertConnectorIdle(method);
|
|
1851
|
+
const releaseOperation = this._retainConnectorOperation(`call:${sessionId}`);
|
|
1852
|
+
let promise;
|
|
1853
|
+
try {
|
|
1854
|
+
promise = this._connector.call(sessionId, method, params).finally(() => {
|
|
1855
|
+
releaseOperation();
|
|
1856
|
+
});
|
|
1857
|
+
} catch (error) {
|
|
1858
|
+
releaseOperation();
|
|
1859
|
+
throw error;
|
|
1860
|
+
}
|
|
1473
1861
|
const result = signal ? await _TrezorAdapter._abortable(signal, promise) : await promise;
|
|
1474
1862
|
return _TrezorAdapter._unwrapConnectorResult(result);
|
|
1475
1863
|
}
|
|
1864
|
+
_assertConnectorIdle(method) {
|
|
1865
|
+
if (this._resetPromise || this._pendingConnectorTeardowns > 0 || this._unsettledConnectorOperations.size > 0) {
|
|
1866
|
+
throw _TrezorAdapter._createDeviceBusyError(method);
|
|
1867
|
+
}
|
|
1868
|
+
}
|
|
1869
|
+
_runConnectorTeardown(task) {
|
|
1870
|
+
const previous = this._connectorTeardownTail;
|
|
1871
|
+
let releaseTail = () => void 0;
|
|
1872
|
+
this._connectorTeardownTail = new Promise((resolve) => {
|
|
1873
|
+
releaseTail = resolve;
|
|
1874
|
+
});
|
|
1875
|
+
this._pendingConnectorTeardowns += 1;
|
|
1876
|
+
return (async () => {
|
|
1877
|
+
try {
|
|
1878
|
+
await previous;
|
|
1879
|
+
await this._waitForConnectorOperationsToDrain();
|
|
1880
|
+
await task();
|
|
1881
|
+
} finally {
|
|
1882
|
+
this._pendingConnectorTeardowns -= 1;
|
|
1883
|
+
releaseTail();
|
|
1884
|
+
}
|
|
1885
|
+
})();
|
|
1886
|
+
}
|
|
1887
|
+
async _releaseProvisionalConnection(connectId, signal) {
|
|
1888
|
+
const sessionId = this._sessions.get(connectId);
|
|
1889
|
+
this._sessions.delete(connectId);
|
|
1890
|
+
this._verifiedPassphraseSessionsByConnectId.delete(connectId);
|
|
1891
|
+
if (!sessionId) return;
|
|
1892
|
+
const teardown = this._runConnectorTeardown(() => this._connector.disconnect(sessionId)).catch(
|
|
1893
|
+
() => void 0
|
|
1894
|
+
);
|
|
1895
|
+
if (!signal.aborted) await teardown;
|
|
1896
|
+
}
|
|
1897
|
+
_waitForConnectorOperationsToDrain() {
|
|
1898
|
+
if (this._unsettledConnectorOperations.size === 0) {
|
|
1899
|
+
return Promise.resolve();
|
|
1900
|
+
}
|
|
1901
|
+
return new Promise((resolve) => {
|
|
1902
|
+
this._connectorIdleWaiters.add(resolve);
|
|
1903
|
+
});
|
|
1904
|
+
}
|
|
1905
|
+
_retainConnectorOperation(key) {
|
|
1906
|
+
this._unsettledConnectorOperations.set(
|
|
1907
|
+
key,
|
|
1908
|
+
(_nullishCoalesce(this._unsettledConnectorOperations.get(key), () => ( 0))) + 1
|
|
1909
|
+
);
|
|
1910
|
+
let released = false;
|
|
1911
|
+
return () => {
|
|
1912
|
+
if (released) return;
|
|
1913
|
+
released = true;
|
|
1914
|
+
const remaining = (_nullishCoalesce(this._unsettledConnectorOperations.get(key), () => ( 1))) - 1;
|
|
1915
|
+
if (remaining > 0) {
|
|
1916
|
+
this._unsettledConnectorOperations.set(key, remaining);
|
|
1917
|
+
} else {
|
|
1918
|
+
this._unsettledConnectorOperations.delete(key);
|
|
1919
|
+
}
|
|
1920
|
+
if (this._unsettledConnectorOperations.size === 0) {
|
|
1921
|
+
for (const resolve of this._connectorIdleWaiters) resolve();
|
|
1922
|
+
this._connectorIdleWaiters.clear();
|
|
1923
|
+
}
|
|
1924
|
+
};
|
|
1925
|
+
}
|
|
1476
1926
|
static _normalizeAllNetworkItem(method, item) {
|
|
1477
1927
|
if (method !== "btcGetAddress" && method !== "btcGetPublicKey") {
|
|
1478
1928
|
return item;
|
|
@@ -1491,18 +1941,14 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
1491
1941
|
const { deviceId } = item;
|
|
1492
1942
|
return typeof deviceId === "string" && deviceId.length > 0 ? deviceId : void 0;
|
|
1493
1943
|
}
|
|
1494
|
-
_callAllNetworkMethod(connectId, method, item) {
|
|
1944
|
+
_callAllNetworkMethod(connectId, method, item, bundleContext) {
|
|
1495
1945
|
switch (method) {
|
|
1496
1946
|
case "evmGetAddress":
|
|
1497
|
-
return this.evmGetAddress(connectId, "", item);
|
|
1498
1947
|
case "btcGetAddress":
|
|
1499
|
-
return this.btcGetAddress(connectId, "", item);
|
|
1500
1948
|
case "btcGetPublicKey":
|
|
1501
|
-
return this.btcGetPublicKey(connectId, "", item);
|
|
1502
1949
|
case "solGetAddress":
|
|
1503
|
-
return this.solGetAddress(connectId, "", item);
|
|
1504
1950
|
case "tronGetAddress":
|
|
1505
|
-
return this.
|
|
1951
|
+
return this._callMethod(method, connectId, "", item, true, bundleContext);
|
|
1506
1952
|
default:
|
|
1507
1953
|
return Promise.resolve(
|
|
1508
1954
|
_hwkadaptercore.failure.call(void 0,
|
|
@@ -1521,11 +1967,50 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
1521
1967
|
_callWalletMethod(methodName, connectId, deviceId, params) {
|
|
1522
1968
|
return this._callMethod(methodName, connectId, deviceId, params, true);
|
|
1523
1969
|
}
|
|
1524
|
-
_callDeviceManagerMethod(methodName, connectId, params) {
|
|
1525
|
-
|
|
1970
|
+
_callDeviceManagerMethod(methodName, connectId, params, operationContext) {
|
|
1971
|
+
const expectedIdentity = _optionalChain([operationContext, 'optionalAccess', _87 => _87.expectedDeviceIdentity]);
|
|
1972
|
+
if (expectedIdentity && (expectedIdentity.vendor !== "trezor" || expectedIdentity.type !== "deviceId")) {
|
|
1973
|
+
return Promise.resolve(
|
|
1974
|
+
_hwkadaptercore.failure.call(void 0,
|
|
1975
|
+
_hwkadaptercore.HardwareErrorCode.InvalidParams,
|
|
1976
|
+
"Trezor device-manager operations require a Trezor deviceId identity"
|
|
1977
|
+
)
|
|
1978
|
+
);
|
|
1979
|
+
}
|
|
1980
|
+
return this._callMethod(
|
|
1981
|
+
methodName,
|
|
1982
|
+
connectId,
|
|
1983
|
+
_optionalChain([expectedIdentity, 'optionalAccess', _88 => _88.value]),
|
|
1984
|
+
{
|
|
1985
|
+
...params && typeof params === "object" ? params : {},
|
|
1986
|
+
knownConnections: _optionalChain([operationContext, 'optionalAccess', _89 => _89.knownConnections]),
|
|
1987
|
+
extra: _optionalChain([operationContext, 'optionalAccess', _90 => _90.extra]),
|
|
1988
|
+
allowDeviceSelection: _optionalChain([operationContext, 'optionalAccess', _91 => _91.allowDeviceSelection]),
|
|
1989
|
+
..._optionalChain([operationContext, 'optionalAccess', _92 => _92.operationId]) ? { operationId: operationContext.operationId } : {}
|
|
1990
|
+
},
|
|
1991
|
+
false
|
|
1992
|
+
);
|
|
1526
1993
|
}
|
|
1527
|
-
async _callMethod(methodName, connectId, deviceId, params, requiresWalletIntent) {
|
|
1994
|
+
async _callMethod(methodName, connectId, deviceId, params, requiresWalletIntent, bundleContext) {
|
|
1528
1995
|
const call = _TrezorAdapter._normalizeCallArgs(connectId, deviceId, params);
|
|
1996
|
+
const commonParams = _TrezorAdapter._splitCommonParams(call.params);
|
|
1997
|
+
const positionalOperationId = _hwkadaptercore.isHardwareOperationId.call(void 0, call.connectId) ? call.connectId : void 0;
|
|
1998
|
+
if (positionalOperationId && commonParams.operationId && positionalOperationId !== commonParams.operationId) {
|
|
1999
|
+
return _hwkadaptercore.failure.call(void 0, _hwkadaptercore.HardwareErrorCode.InvalidParams, "Conflicting Trezor operation ids", {
|
|
2000
|
+
positionalOperationId,
|
|
2001
|
+
commonOperationId: commonParams.operationId
|
|
2002
|
+
});
|
|
2003
|
+
}
|
|
2004
|
+
const operationId = _nullishCoalesce(commonParams.operationId, () => ( positionalOperationId));
|
|
2005
|
+
let releaseOperationRetention;
|
|
2006
|
+
try {
|
|
2007
|
+
if (operationId) {
|
|
2008
|
+
call.connectId = this._operations.resolve(operationId).connectId;
|
|
2009
|
+
releaseOperationRetention = this._operations.retain(operationId);
|
|
2010
|
+
}
|
|
2011
|
+
} catch (error) {
|
|
2012
|
+
return this._errorToFailure(error);
|
|
2013
|
+
}
|
|
1529
2014
|
debugLog("[TrezorAdapter][REQ]", {
|
|
1530
2015
|
method: methodName,
|
|
1531
2016
|
connectId: call.connectId || "(empty)",
|
|
@@ -1534,15 +2019,40 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
1534
2019
|
});
|
|
1535
2020
|
try {
|
|
1536
2021
|
const response = await this._jobQueue.enqueue(
|
|
1537
|
-
call.connectId,
|
|
1538
|
-
(signal) =>
|
|
1539
|
-
call.connectId
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
2022
|
+
_nullishCoalesce(operationId, () => ( call.connectId)),
|
|
2023
|
+
async (signal) => {
|
|
2024
|
+
let effectiveConnectId = call.connectId;
|
|
2025
|
+
let selectionRequestId;
|
|
2026
|
+
try {
|
|
2027
|
+
if (!_optionalChain([bundleContext, 'optionalAccess', _93 => _93.connection]) && !operationId && deviceId && (!connectId || _optionalChain([commonParams, 'access', _94 => _94.connectionContext, 'optionalAccess', _95 => _95.knownConnections]) !== void 0)) {
|
|
2028
|
+
const resolved = await this._resolveExpectedDeviceConnectId(
|
|
2029
|
+
deviceId,
|
|
2030
|
+
signal,
|
|
2031
|
+
commonParams.connectionContext
|
|
2032
|
+
);
|
|
2033
|
+
effectiveConnectId = resolved.connectId;
|
|
2034
|
+
selectionRequestId = resolved.selectionRequestId;
|
|
2035
|
+
}
|
|
2036
|
+
} catch (error) {
|
|
2037
|
+
return this._errorToFailure(error);
|
|
2038
|
+
}
|
|
2039
|
+
const response2 = await this._callWithRetry(
|
|
2040
|
+
_nullishCoalesce(_optionalChain([bundleContext, 'optionalAccess', _96 => _96.connection, 'optionalAccess', _97 => _97.connectId]), () => ( effectiveConnectId)),
|
|
2041
|
+
methodName,
|
|
2042
|
+
call.params,
|
|
2043
|
+
deviceId || "",
|
|
2044
|
+
requiresWalletIntent,
|
|
2045
|
+
true,
|
|
2046
|
+
signal,
|
|
2047
|
+
operationId,
|
|
2048
|
+
selectionRequestId,
|
|
2049
|
+
bundleContext
|
|
2050
|
+
);
|
|
2051
|
+
if (!response2.success && selectionRequestId) {
|
|
2052
|
+
await this._releaseProvisionalConnection(effectiveConnectId, signal);
|
|
2053
|
+
}
|
|
2054
|
+
return response2;
|
|
2055
|
+
},
|
|
1546
2056
|
{
|
|
1547
2057
|
label: methodName,
|
|
1548
2058
|
rejectIfBusy: true,
|
|
@@ -1563,16 +2073,53 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
1563
2073
|
payload: _TrezorAdapter._sanitizeForLog(response.payload, methodName)
|
|
1564
2074
|
});
|
|
1565
2075
|
return response;
|
|
2076
|
+
} finally {
|
|
2077
|
+
_optionalChain([releaseOperationRetention, 'optionalCall', _98 => _98()]);
|
|
1566
2078
|
}
|
|
1567
2079
|
}
|
|
1568
|
-
async _callWithRetry(connectId, methodName, params, requiresWalletIntent, allowRetry, signal) {
|
|
1569
|
-
const { passphraseState, useEmptyPassphrase, rest } = _TrezorAdapter._splitCommonParams(params);
|
|
2080
|
+
async _callWithRetry(connectId, methodName, params, expectedDeviceId, requiresWalletIntent, allowRetry, signal, operationId, selectionRequestId, bundleContext) {
|
|
2081
|
+
const { passphraseState, useEmptyPassphrase, rest, connectionContext } = _TrezorAdapter._splitCommonParams(params);
|
|
2082
|
+
let pendingBindingRequestId = selectionRequestId;
|
|
2083
|
+
let businessCallStarted = false;
|
|
1570
2084
|
const restorePassphraseRequestContext = this._setPassphraseRequestContext(connectId, {
|
|
1571
2085
|
passphraseState,
|
|
1572
2086
|
useEmptyPassphrase
|
|
1573
2087
|
});
|
|
1574
2088
|
try {
|
|
1575
|
-
|
|
2089
|
+
if (_optionalChain([bundleContext, 'optionalAccess', _99 => _99.connection])) {
|
|
2090
|
+
const pinned = bundleContext.connection;
|
|
2091
|
+
if (this._sessions.get(pinned.connectId) !== pinned.sessionId) {
|
|
2092
|
+
return _hwkadaptercore.failure.call(void 0,
|
|
2093
|
+
_hwkadaptercore.HardwareErrorCode.DeviceDisconnected,
|
|
2094
|
+
"Trezor all-network connection ended"
|
|
2095
|
+
);
|
|
2096
|
+
}
|
|
2097
|
+
}
|
|
2098
|
+
const sessionId = operationId ? this._sessions.get(this._operations.resolve(operationId).connectId) : await this._ensureSession(connectId, signal);
|
|
2099
|
+
if (!sessionId) {
|
|
2100
|
+
if (operationId) {
|
|
2101
|
+
this._operations.end(operationId, "disconnect");
|
|
2102
|
+
return _hwkadaptercore.failure.call(void 0,
|
|
2103
|
+
_hwkadaptercore.HardwareErrorCode.OperationEnded,
|
|
2104
|
+
"Trezor operation connection is no longer active",
|
|
2105
|
+
{ operationId, reason: "disconnect" }
|
|
2106
|
+
);
|
|
2107
|
+
}
|
|
2108
|
+
return _hwkadaptercore.failure.call(void 0, _hwkadaptercore.HardwareErrorCode.DeviceNotFound, "Trezor session was not found");
|
|
2109
|
+
}
|
|
2110
|
+
if (bundleContext && !bundleContext.connection) {
|
|
2111
|
+
bundleContext.connection = { connectId, sessionId };
|
|
2112
|
+
}
|
|
2113
|
+
if (expectedDeviceId) {
|
|
2114
|
+
const actualDeviceId = _optionalChain([this, 'access', _100 => _100._devices, 'access', _101 => _101.get, 'call', _102 => _102(connectId), 'optionalAccess', _103 => _103.deviceId]);
|
|
2115
|
+
if (!actualDeviceId || actualDeviceId !== expectedDeviceId) {
|
|
2116
|
+
return _hwkadaptercore.failure.call(void 0,
|
|
2117
|
+
_hwkadaptercore.HardwareErrorCode.DeviceMismatch,
|
|
2118
|
+
`Wrong device: expected ${expectedDeviceId}, got ${actualDeviceId || "unknown"}`,
|
|
2119
|
+
{ expected: expectedDeviceId, actual: actualDeviceId || "" }
|
|
2120
|
+
);
|
|
2121
|
+
}
|
|
2122
|
+
}
|
|
1576
2123
|
if (requiresWalletIntent && !passphraseState && useEmptyPassphrase !== true) {
|
|
1577
2124
|
return _hwkadaptercore.failure.call(void 0,
|
|
1578
2125
|
_hwkadaptercore.HardwareErrorCode.InvalidParams,
|
|
@@ -1587,28 +2134,68 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
1587
2134
|
} else if (useEmptyPassphrase === true) {
|
|
1588
2135
|
await _TrezorAdapter._abortable(signal, this._createFreshAppSession(sessionId, signal));
|
|
1589
2136
|
}
|
|
2137
|
+
if (expectedDeviceId) {
|
|
2138
|
+
await this._emitVerifiedBinding(
|
|
2139
|
+
expectedDeviceId,
|
|
2140
|
+
connectId,
|
|
2141
|
+
pendingBindingRequestId,
|
|
2142
|
+
connectionContext,
|
|
2143
|
+
signal
|
|
2144
|
+
);
|
|
2145
|
+
pendingBindingRequestId = void 0;
|
|
2146
|
+
this._rememberVerifiedConnection(expectedDeviceId, connectId);
|
|
2147
|
+
}
|
|
2148
|
+
businessCallStarted = true;
|
|
1590
2149
|
const result = await _TrezorAdapter._abortable(
|
|
1591
2150
|
signal,
|
|
1592
|
-
|
|
2151
|
+
this._callConnector(sessionId, methodName, rest)
|
|
1593
2152
|
);
|
|
1594
2153
|
return _hwkadaptercore.success.call(void 0, result);
|
|
1595
2154
|
} catch (error) {
|
|
1596
2155
|
if (signal.aborted) {
|
|
2156
|
+
if (pendingBindingRequestId)
|
|
2157
|
+
this._emitter.emit(_hwkadaptercore.UI_REQUEST.DEVICE_BINDING_STATUS, {
|
|
2158
|
+
type: _hwkadaptercore.UI_REQUEST.DEVICE_BINDING_STATUS,
|
|
2159
|
+
payload: { selectionRequestId: pendingBindingRequestId, status: "cancelled" }
|
|
2160
|
+
});
|
|
1597
2161
|
return this._errorToFailure(error);
|
|
1598
2162
|
}
|
|
1599
2163
|
const code = _TrezorAdapter._errorCode(error);
|
|
1600
|
-
if (allowRetry &&
|
|
2164
|
+
if (pendingBindingRequestId && !(allowRetry && (passphraseState || useEmptyPassphrase === true) && _TrezorAdapter._isStaleSessionError(code))) {
|
|
2165
|
+
this._emitter.emit(_hwkadaptercore.UI_REQUEST.DEVICE_BINDING_STATUS, {
|
|
2166
|
+
type: _hwkadaptercore.UI_REQUEST.DEVICE_BINDING_STATUS,
|
|
2167
|
+
payload: { selectionRequestId: pendingBindingRequestId, status: "failed" }
|
|
2168
|
+
});
|
|
2169
|
+
}
|
|
2170
|
+
const ambiguousTransportFailure = code === _hwkadaptercore.HardwareErrorCode.DeviceDisconnected || code === _hwkadaptercore.HardwareErrorCode.OperationTimeout || code === _hwkadaptercore.HardwareErrorCode.TransportError;
|
|
2171
|
+
if (operationId && ambiguousTransportFailure) {
|
|
1601
2172
|
this._sessions.delete(connectId);
|
|
1602
2173
|
this._verifiedPassphraseSessionsByConnectId.delete(connectId);
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
2174
|
+
this._operations.end(operationId, "disconnect");
|
|
2175
|
+
return _hwkadaptercore.failure.call(void 0,
|
|
2176
|
+
_hwkadaptercore.HardwareErrorCode.OperationEnded,
|
|
2177
|
+
businessCallStarted && !_hwkadaptercore.canReplayHardwareMethodAfterTransportFailure.call(void 0, methodName) ? `Trezor ${methodName} may have completed before the connection was lost` : "Trezor operation connection was lost",
|
|
2178
|
+
businessCallStarted && !_hwkadaptercore.canReplayHardwareMethodAfterTransportFailure.call(void 0, methodName) ? _hwkadaptercore.operationMayHaveCompletedParams.call(void 0, methodName, {
|
|
2179
|
+
operationId,
|
|
2180
|
+
reason: "disconnect"
|
|
2181
|
+
}) : { operationId, reason: "disconnect" },
|
|
2182
|
+
void 0,
|
|
2183
|
+
businessCallStarted && !_hwkadaptercore.canReplayHardwareMethodAfterTransportFailure.call(void 0, methodName) ? { scope: "unknown" } : void 0
|
|
1610
2184
|
);
|
|
1611
2185
|
}
|
|
2186
|
+
if (!operationId && ambiguousTransportFailure) {
|
|
2187
|
+
this._sessions.delete(connectId);
|
|
2188
|
+
this._verifiedPassphraseSessionsByConnectId.delete(connectId);
|
|
2189
|
+
if (businessCallStarted && !_hwkadaptercore.canReplayHardwareMethodAfterTransportFailure.call(void 0, methodName)) {
|
|
2190
|
+
return _hwkadaptercore.failure.call(void 0,
|
|
2191
|
+
code,
|
|
2192
|
+
`Trezor ${methodName} may have completed before the connection was lost`,
|
|
2193
|
+
_hwkadaptercore.operationMayHaveCompletedParams.call(void 0, methodName),
|
|
2194
|
+
void 0,
|
|
2195
|
+
{ scope: "unknown" }
|
|
2196
|
+
);
|
|
2197
|
+
}
|
|
2198
|
+
}
|
|
1612
2199
|
if (allowRetry && (passphraseState || useEmptyPassphrase === true) && _TrezorAdapter._isStaleSessionError(code)) {
|
|
1613
2200
|
if (passphraseState) {
|
|
1614
2201
|
this._forgetVerifiedPassphraseSession(connectId, passphraseState);
|
|
@@ -1617,9 +2204,13 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
1617
2204
|
connectId,
|
|
1618
2205
|
methodName,
|
|
1619
2206
|
params,
|
|
2207
|
+
expectedDeviceId,
|
|
1620
2208
|
requiresWalletIntent,
|
|
1621
2209
|
false,
|
|
1622
|
-
signal
|
|
2210
|
+
signal,
|
|
2211
|
+
operationId,
|
|
2212
|
+
pendingBindingRequestId,
|
|
2213
|
+
bundleContext
|
|
1623
2214
|
);
|
|
1624
2215
|
}
|
|
1625
2216
|
debugLog("[TrezorAdapter][ERROR]", {
|
|
@@ -1632,34 +2223,247 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
1632
2223
|
restorePassphraseRequestContext();
|
|
1633
2224
|
}
|
|
1634
2225
|
}
|
|
1635
|
-
async _ensureSession(connectId, signal) {
|
|
2226
|
+
async _ensureSession(connectId, signal, transportType) {
|
|
1636
2227
|
const existing = this._sessions.get(connectId);
|
|
1637
2228
|
if (existing) return existing;
|
|
1638
2229
|
const pending = this._connectingPromises.get(connectId);
|
|
1639
2230
|
if (pending) return pending;
|
|
2231
|
+
const stateGeneration = this._stateGeneration;
|
|
1640
2232
|
const promise = (async () => {
|
|
2233
|
+
if (_optionalChain([signal, 'optionalAccess', _104 => _104.aborted])) {
|
|
2234
|
+
throw Object.assign(new Error("Trezor connection aborted"), {
|
|
2235
|
+
code: _hwkadaptercore.HardwareErrorCode.UserAborted
|
|
2236
|
+
});
|
|
2237
|
+
}
|
|
1641
2238
|
try {
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
try {
|
|
1648
|
-
return await this._connectSession(connectId, signal);
|
|
1649
|
-
} catch (error) {
|
|
1650
|
-
if (_TrezorAdapter._isConnectionUnavailableError(error)) {
|
|
1651
|
-
this._sessions.delete(connectId);
|
|
1652
|
-
this._verifiedPassphraseSessionsByConnectId.delete(connectId);
|
|
1653
|
-
}
|
|
1654
|
-
throw error;
|
|
2239
|
+
return await this._connectSession(connectId, signal, stateGeneration, transportType);
|
|
2240
|
+
} catch (error) {
|
|
2241
|
+
if (_TrezorAdapter._isConnectionUnavailableError(error)) {
|
|
2242
|
+
this._sessions.delete(connectId);
|
|
2243
|
+
this._verifiedPassphraseSessionsByConnectId.delete(connectId);
|
|
1655
2244
|
}
|
|
1656
|
-
|
|
1657
|
-
this._connectingPromises.delete(connectId);
|
|
1658
|
-
this._disconnectRequested.delete(connectId);
|
|
2245
|
+
throw error;
|
|
1659
2246
|
}
|
|
1660
2247
|
})();
|
|
1661
2248
|
this._connectingPromises.set(connectId, promise);
|
|
1662
|
-
|
|
2249
|
+
try {
|
|
2250
|
+
return await promise;
|
|
2251
|
+
} finally {
|
|
2252
|
+
if (this._connectingPromises.get(connectId) === promise) {
|
|
2253
|
+
this._connectingPromises.delete(connectId);
|
|
2254
|
+
}
|
|
2255
|
+
this._disconnectRequested.delete(connectId);
|
|
2256
|
+
}
|
|
2257
|
+
}
|
|
2258
|
+
async _resolveExpectedDeviceConnectId(expectedDeviceId, signal, context) {
|
|
2259
|
+
const connectedMatch = Array.from(this._devices.values()).find(
|
|
2260
|
+
(device) => device.deviceId === expectedDeviceId && this._sessions.has(device.connectId)
|
|
2261
|
+
);
|
|
2262
|
+
if (connectedMatch) return { connectId: connectedMatch.connectId };
|
|
2263
|
+
const availableTransports = _nullishCoalesce(this._connector.availableTransports, () => ( [
|
|
2264
|
+
this._connector.connectionType
|
|
2265
|
+
]));
|
|
2266
|
+
if (availableTransports.includes("usb")) {
|
|
2267
|
+
await _TrezorAdapter._abortable(
|
|
2268
|
+
signal,
|
|
2269
|
+
this._ensureDevicePermission(void 0, expectedDeviceId, "usb")
|
|
2270
|
+
);
|
|
2271
|
+
}
|
|
2272
|
+
const candidates = await _TrezorAdapter._abortable(
|
|
2273
|
+
signal,
|
|
2274
|
+
this._searchDevices({ transportType: "usb" }, signal)
|
|
2275
|
+
);
|
|
2276
|
+
const mismatchedDeviceIds = [];
|
|
2277
|
+
const knownConnection = this._knownDeviceConnections.get(expectedDeviceId);
|
|
2278
|
+
const knownUsbIds = _optionalChain([context, 'optionalAccess', _105 => _105.knownConnections]) !== void 0 ? context.knownConnections.flatMap(
|
|
2279
|
+
(connection) => connection.transport === "usb" ? [connection.connectId] : []
|
|
2280
|
+
) : [_optionalChain([knownConnection, 'optionalAccess', _106 => _106.usbConnectId])].filter((id) => Boolean(id));
|
|
2281
|
+
const suppliedBleIds = _optionalChain([context, 'optionalAccess', _107 => _107.knownConnections, 'optionalAccess', _108 => _108.flatMap, 'call', _109 => _109(
|
|
2282
|
+
(connection) => connection.transport === "ble" ? [connection.connectId] : []
|
|
2283
|
+
)]);
|
|
2284
|
+
const knownBleIds = _optionalChain([suppliedBleIds, 'optionalAccess', _110 => _110.length]) ? suppliedBleIds : [_optionalChain([knownConnection, 'optionalAccess', _111 => _111.bleConnectId])].filter((id) => Boolean(id));
|
|
2285
|
+
const usbCandidates = candidates.filter(
|
|
2286
|
+
(device) => device.connectionType === "usb" && (!knownUsbIds.length || knownUsbIds.includes(device.connectId))
|
|
2287
|
+
);
|
|
2288
|
+
for (const candidate of usbCandidates) {
|
|
2289
|
+
let sessionId;
|
|
2290
|
+
try {
|
|
2291
|
+
sessionId = await this._ensureSession(candidate.connectId, signal, "usb");
|
|
2292
|
+
const actualDeviceId = _nullishCoalesce(_optionalChain([this, 'access', _112 => _112._devices, 'access', _113 => _113.get, 'call', _114 => _114(candidate.connectId), 'optionalAccess', _115 => _115.deviceId]), () => ( ""));
|
|
2293
|
+
if (actualDeviceId === expectedDeviceId) return { connectId: candidate.connectId };
|
|
2294
|
+
mismatchedDeviceIds.push(actualDeviceId || "unknown");
|
|
2295
|
+
} catch (error) {
|
|
2296
|
+
if (signal.aborted) throw error;
|
|
2297
|
+
if (!_TrezorAdapter._isConnectionUnavailableError(error)) throw error;
|
|
2298
|
+
}
|
|
2299
|
+
if (sessionId) {
|
|
2300
|
+
const mismatchedSessionId = sessionId;
|
|
2301
|
+
this._sessions.delete(candidate.connectId);
|
|
2302
|
+
this._verifiedPassphraseSessionsByConnectId.delete(candidate.connectId);
|
|
2303
|
+
await this._runConnectorTeardown(() => this._connector.disconnect(mismatchedSessionId));
|
|
2304
|
+
}
|
|
2305
|
+
}
|
|
2306
|
+
if (mismatchedDeviceIds.length) {
|
|
2307
|
+
throw _hwkadaptercore.createHwkError.call(void 0, {
|
|
2308
|
+
code: _hwkadaptercore.HardwareErrorCode.DeviceSearchMismatch,
|
|
2309
|
+
message: "The connected Trezor is not the wallet this operation needs. Unplug it and connect the right device.",
|
|
2310
|
+
params: { connectedDeviceIds: mismatchedDeviceIds }
|
|
2311
|
+
});
|
|
2312
|
+
}
|
|
2313
|
+
if (usbCandidates.length > 0) {
|
|
2314
|
+
throw _hwkadaptercore.createHwkError.call(void 0, {
|
|
2315
|
+
code: _hwkadaptercore.HardwareErrorCode.DeviceNotFound,
|
|
2316
|
+
message: "Trezor devices are present but none could be opened to check its identity."
|
|
2317
|
+
});
|
|
2318
|
+
}
|
|
2319
|
+
const [knownBleConnectId] = knownBleIds;
|
|
2320
|
+
if (knownBleConnectId && availableTransports.includes("ble")) {
|
|
2321
|
+
await _TrezorAdapter._abortable(
|
|
2322
|
+
signal,
|
|
2323
|
+
this._ensureDevicePermission(knownBleConnectId, expectedDeviceId, "ble")
|
|
2324
|
+
);
|
|
2325
|
+
await this._ensureSession(knownBleConnectId, signal, "ble");
|
|
2326
|
+
const actualDeviceId = _optionalChain([this, 'access', _116 => _116._devices, 'access', _117 => _117.get, 'call', _118 => _118(knownBleConnectId), 'optionalAccess', _119 => _119.deviceId]);
|
|
2327
|
+
if (actualDeviceId === expectedDeviceId) return { connectId: knownBleConnectId };
|
|
2328
|
+
const sessionId = this._sessions.get(knownBleConnectId);
|
|
2329
|
+
this._sessions.delete(knownBleConnectId);
|
|
2330
|
+
this._verifiedPassphraseSessionsByConnectId.delete(knownBleConnectId);
|
|
2331
|
+
if (sessionId) {
|
|
2332
|
+
await this._runConnectorTeardown(() => this._connector.disconnect(sessionId));
|
|
2333
|
+
}
|
|
2334
|
+
throw _hwkadaptercore.createHwkError.call(void 0, {
|
|
2335
|
+
code: _hwkadaptercore.HardwareErrorCode.DeviceMismatch,
|
|
2336
|
+
message: "The bound Trezor Bluetooth device has a different identity"
|
|
2337
|
+
});
|
|
2338
|
+
}
|
|
2339
|
+
if (_optionalChain([context, 'optionalAccess', _120 => _120.allowDeviceSelection]) === false) {
|
|
2340
|
+
throw _hwkadaptercore.createHwkError.call(void 0, {
|
|
2341
|
+
code: _hwkadaptercore.HardwareErrorCode.DeviceNotFound,
|
|
2342
|
+
message: "No known Trezor connection is available"
|
|
2343
|
+
});
|
|
2344
|
+
}
|
|
2345
|
+
return this._selectBleDeviceForBinding(expectedDeviceId, signal, context, "missing-binding");
|
|
2346
|
+
}
|
|
2347
|
+
async _selectBleDeviceForBinding(expectedDeviceId, signal, context, reason) {
|
|
2348
|
+
const availableTransports = _nullishCoalesce(this._connector.availableTransports, () => ( [
|
|
2349
|
+
this._connector.connectionType
|
|
2350
|
+
]));
|
|
2351
|
+
const allowUsbFallback = reason !== "manual-rebind" && availableTransports.includes("usb");
|
|
2352
|
+
const knownUsbIds = _optionalChain([context, 'optionalAccess', _121 => _121.knownConnections]) ? context.knownConnections.flatMap(
|
|
2353
|
+
(connection) => connection.transport === "usb" ? [connection.connectId] : []
|
|
2354
|
+
) : [_optionalChain([this, 'access', _122 => _122._knownDeviceConnections, 'access', _123 => _123.get, 'call', _124 => _124(expectedDeviceId), 'optionalAccess', _125 => _125.usbConnectId])];
|
|
2355
|
+
if (availableTransports.includes("ble")) {
|
|
2356
|
+
await _TrezorAdapter._abortable(
|
|
2357
|
+
signal,
|
|
2358
|
+
this._ensureDevicePermission(void 0, expectedDeviceId, "ble")
|
|
2359
|
+
);
|
|
2360
|
+
}
|
|
2361
|
+
const bleCandidates = (await _TrezorAdapter._abortable(
|
|
2362
|
+
signal,
|
|
2363
|
+
this._searchDevices({ transportType: "ble", waitForAllTransports: true }, signal)
|
|
2364
|
+
)).filter((device) => device.connectionType === "ble");
|
|
2365
|
+
if (signal.aborted) throw signal.reason;
|
|
2366
|
+
const rejectedConnectIds = /* @__PURE__ */ new Set();
|
|
2367
|
+
const bindingSessionId = this._uiRegistry.createRequestId();
|
|
2368
|
+
let rejectedConnectId;
|
|
2369
|
+
while (availableTransports.includes("ble") && this._emitter.listenerCount(_hwkadaptercore.UI_REQUEST.REQUEST_SELECT_DEVICE)) {
|
|
2370
|
+
const { device: selected, requestId } = await _hwkadaptercore.requestBleDeviceSelection.call(void 0, {
|
|
2371
|
+
emitter: this._emitter,
|
|
2372
|
+
registry: this._uiRegistry,
|
|
2373
|
+
signal,
|
|
2374
|
+
allowUsbFallback,
|
|
2375
|
+
scan: async () => {
|
|
2376
|
+
if (allowUsbFallback) {
|
|
2377
|
+
const usbCandidates = (await this._searchDevices({ transportType: "usb" }, signal)).filter(
|
|
2378
|
+
(device) => device.connectionType === "usb" && !rejectedConnectIds.has(device.connectId)
|
|
2379
|
+
);
|
|
2380
|
+
const candidate = _nullishCoalesce(usbCandidates.find((device) => knownUsbIds.includes(device.connectId)), () => ( usbCandidates[0]));
|
|
2381
|
+
if (candidate) return [candidate];
|
|
2382
|
+
}
|
|
2383
|
+
return (await this._searchDevices({ transportType: "ble", waitForAllTransports: true }, signal)).filter(
|
|
2384
|
+
(device) => device.connectionType === "ble" && !rejectedConnectIds.has(device.connectId)
|
|
2385
|
+
);
|
|
2386
|
+
},
|
|
2387
|
+
request: {
|
|
2388
|
+
devices: bleCandidates.filter((device) => !rejectedConnectIds.has(device.connectId)),
|
|
2389
|
+
bindingSessionId,
|
|
2390
|
+
rejectedConnectId,
|
|
2391
|
+
context: {
|
|
2392
|
+
kind: "bind-connection",
|
|
2393
|
+
transport: "ble",
|
|
2394
|
+
reason
|
|
2395
|
+
},
|
|
2396
|
+
extra: _optionalChain([context, 'optionalAccess', _126 => _126.extra])
|
|
2397
|
+
}
|
|
2398
|
+
});
|
|
2399
|
+
try {
|
|
2400
|
+
if (reason === "manual-rebind") {
|
|
2401
|
+
this._operations.endByConnectionKey(selected.connectId, "explicit");
|
|
2402
|
+
await this._releaseProvisionalConnection(selected.connectId, signal);
|
|
2403
|
+
}
|
|
2404
|
+
await this._ensureSession(selected.connectId, signal, selected.connectionType);
|
|
2405
|
+
} catch (error) {
|
|
2406
|
+
this._emitter.emit(_hwkadaptercore.UI_REQUEST.DEVICE_BINDING_STATUS, {
|
|
2407
|
+
type: _hwkadaptercore.UI_REQUEST.DEVICE_BINDING_STATUS,
|
|
2408
|
+
payload: {
|
|
2409
|
+
selectionRequestId: requestId,
|
|
2410
|
+
status: signal.aborted ? "cancelled" : "failed"
|
|
2411
|
+
}
|
|
2412
|
+
});
|
|
2413
|
+
throw error;
|
|
2414
|
+
}
|
|
2415
|
+
if (_optionalChain([this, 'access', _127 => _127._devices, 'access', _128 => _128.get, 'call', _129 => _129(selected.connectId), 'optionalAccess', _130 => _130.deviceId]) !== expectedDeviceId) {
|
|
2416
|
+
const sessionId = this._sessions.get(selected.connectId);
|
|
2417
|
+
this._sessions.delete(selected.connectId);
|
|
2418
|
+
this._verifiedPassphraseSessionsByConnectId.delete(selected.connectId);
|
|
2419
|
+
if (sessionId) {
|
|
2420
|
+
await this._runConnectorTeardown(() => this._connector.disconnect(sessionId));
|
|
2421
|
+
}
|
|
2422
|
+
rejectedConnectId = selected.connectId;
|
|
2423
|
+
rejectedConnectIds.add(selected.connectId);
|
|
2424
|
+
continue;
|
|
2425
|
+
}
|
|
2426
|
+
if (selected.connectionType === "usb") {
|
|
2427
|
+
this._emitter.emit(_hwkadaptercore.UI_REQUEST.DEVICE_BINDING_STATUS, {
|
|
2428
|
+
type: _hwkadaptercore.UI_REQUEST.DEVICE_BINDING_STATUS,
|
|
2429
|
+
payload: { selectionRequestId: requestId, status: "cancelled" }
|
|
2430
|
+
});
|
|
2431
|
+
return { connectId: selected.connectId };
|
|
2432
|
+
}
|
|
2433
|
+
return { connectId: selected.connectId, selectionRequestId: requestId };
|
|
2434
|
+
}
|
|
2435
|
+
throw _hwkadaptercore.createHwkError.call(void 0, {
|
|
2436
|
+
code: _hwkadaptercore.HardwareErrorCode.DeviceNotFound,
|
|
2437
|
+
message: "No readable Trezor device is available"
|
|
2438
|
+
});
|
|
2439
|
+
}
|
|
2440
|
+
_rememberVerifiedConnection(deviceId, connectId) {
|
|
2441
|
+
const device = this._devices.get(connectId);
|
|
2442
|
+
if (!device || device.deviceId !== deviceId) return;
|
|
2443
|
+
const known = _nullishCoalesce(this._knownDeviceConnections.get(deviceId), () => ( { deviceId }));
|
|
2444
|
+
if (device.connectionType === "ble") {
|
|
2445
|
+
known.bleConnectId = connectId;
|
|
2446
|
+
} else if (device.connectionType === "usb" && _optionalChain([device, 'access', _131 => _131.capabilities, 'optionalAccess', _132 => _132.persistentDeviceIdentity])) {
|
|
2447
|
+
known.usbConnectId = connectId;
|
|
2448
|
+
}
|
|
2449
|
+
this._knownDeviceConnections.set(deviceId, known);
|
|
2450
|
+
}
|
|
2451
|
+
async _emitVerifiedBinding(deviceId, connectId, selectionRequestId, context, signal) {
|
|
2452
|
+
if (!selectionRequestId) return false;
|
|
2453
|
+
const device = this._devices.get(connectId);
|
|
2454
|
+
if (!device || device.deviceId !== deviceId || device.connectionType !== "ble") return false;
|
|
2455
|
+
const outcome = await _hwkadaptercore.requestSaveDeviceBinding.call(void 0,
|
|
2456
|
+
this._emitter,
|
|
2457
|
+
this._uiRegistry,
|
|
2458
|
+
{
|
|
2459
|
+
selectionRequestId,
|
|
2460
|
+
connection: { transport: "ble", connectId },
|
|
2461
|
+
identity: { vendor: "trezor", type: "deviceId", value: deviceId },
|
|
2462
|
+
extra: _optionalChain([context, 'optionalAccess', _133 => _133.extra])
|
|
2463
|
+
},
|
|
2464
|
+
signal
|
|
2465
|
+
);
|
|
2466
|
+
return outcome.saved;
|
|
1663
2467
|
}
|
|
1664
2468
|
/**
|
|
1665
2469
|
* Pin the device's active wallet session to `passphraseState` (the target
|
|
@@ -1681,12 +2485,16 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
1681
2485
|
if (reused) return;
|
|
1682
2486
|
const created = await _TrezorAdapter._abortable(
|
|
1683
2487
|
signal,
|
|
1684
|
-
|
|
2488
|
+
this._callConnector(sessionId, "__thpCreateSession", {
|
|
1685
2489
|
passphraseMode: "prompt"
|
|
1686
2490
|
})
|
|
1687
2491
|
);
|
|
1688
|
-
if (_optionalChain([created, 'optionalAccess',
|
|
1689
|
-
|
|
2492
|
+
if (_optionalChain([created, 'optionalAccess', _134 => _134.protocol]) === "thp" && !created.thpSessionId || _optionalChain([created, 'optionalAccess', _135 => _135.protocol]) !== "thp" && _optionalChain([created, 'optionalAccess', _136 => _136.protocol]) !== "v1") {
|
|
2493
|
+
throw _hwkadaptercore.createHwkError.call(void 0, {
|
|
2494
|
+
code: _hwkadaptercore.HardwareErrorCode.TransportError,
|
|
2495
|
+
message: "Cannot verify the requested Trezor wallet session"
|
|
2496
|
+
});
|
|
2497
|
+
}
|
|
1690
2498
|
const state = await this._deriveState(sessionId, signal);
|
|
1691
2499
|
if (state !== passphraseState) {
|
|
1692
2500
|
throw Object.assign(
|
|
@@ -1700,13 +2508,13 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
1700
2508
|
}
|
|
1701
2509
|
_rememberVerifiedPassphraseSession(connectId, passphraseState, sessionId, created) {
|
|
1702
2510
|
let session;
|
|
1703
|
-
if (_optionalChain([created, 'optionalAccess',
|
|
2511
|
+
if (_optionalChain([created, 'optionalAccess', _137 => _137.protocol]) === "thp" && typeof created.thpSessionId === "string") {
|
|
1704
2512
|
session = {
|
|
1705
2513
|
sessionId,
|
|
1706
2514
|
protocol: "thp",
|
|
1707
2515
|
thpSessionId: created.thpSessionId
|
|
1708
2516
|
};
|
|
1709
|
-
} else if (_optionalChain([created, 'optionalAccess',
|
|
2517
|
+
} else if (_optionalChain([created, 'optionalAccess', _138 => _138.protocol]) === "v1") {
|
|
1710
2518
|
session = {
|
|
1711
2519
|
sessionId,
|
|
1712
2520
|
protocol: "v1"
|
|
@@ -1726,7 +2534,7 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
1726
2534
|
}
|
|
1727
2535
|
}
|
|
1728
2536
|
async _reuseVerifiedPassphraseSession(connectId, sessionId, passphraseState, signal) {
|
|
1729
|
-
const cached = _optionalChain([this, 'access',
|
|
2537
|
+
const cached = _optionalChain([this, 'access', _139 => _139._verifiedPassphraseSessionsByConnectId, 'access', _140 => _140.get, 'call', _141 => _141(connectId), 'optionalAccess', _142 => _142.get, 'call', _143 => _143(passphraseState)]);
|
|
1730
2538
|
if (!cached || cached.sessionId !== sessionId) {
|
|
1731
2539
|
this._forgetVerifiedPassphraseSession(connectId, passphraseState);
|
|
1732
2540
|
return false;
|
|
@@ -1736,7 +2544,7 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
1736
2544
|
if (!cached.thpSessionId) return false;
|
|
1737
2545
|
await _TrezorAdapter._abortable(
|
|
1738
2546
|
signal,
|
|
1739
|
-
|
|
2547
|
+
this._callConnector(sessionId, "__thpSelectSession", {
|
|
1740
2548
|
thpSessionId: cached.thpSessionId
|
|
1741
2549
|
})
|
|
1742
2550
|
);
|
|
@@ -1756,7 +2564,7 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
1756
2564
|
async _createFreshAppSession(sessionId, signal) {
|
|
1757
2565
|
await _TrezorAdapter._abortable(
|
|
1758
2566
|
signal,
|
|
1759
|
-
|
|
2567
|
+
this._callConnector(sessionId, "__thpCreateSession", {
|
|
1760
2568
|
passphraseMode: "empty"
|
|
1761
2569
|
})
|
|
1762
2570
|
);
|
|
@@ -1773,12 +2581,12 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
1773
2581
|
async _deriveState(sessionId, signal) {
|
|
1774
2582
|
const derived = await _TrezorAdapter._abortable(
|
|
1775
2583
|
signal,
|
|
1776
|
-
|
|
2584
|
+
this._callConnector(sessionId, "btcGetPublicKey", {
|
|
1777
2585
|
path: "m/44'/0'/0'",
|
|
1778
2586
|
showOnDevice: false
|
|
1779
2587
|
})
|
|
1780
2588
|
);
|
|
1781
|
-
const state = _optionalChain([derived, 'optionalAccess',
|
|
2589
|
+
const state = _optionalChain([derived, 'optionalAccess', _144 => _144.publicKey]);
|
|
1782
2590
|
if (!state) {
|
|
1783
2591
|
throw Object.assign(new Error("Failed to derive passphrase state (wallet public key)"), {
|
|
1784
2592
|
code: _hwkadaptercore.HardwareErrorCode.UnknownError
|
|
@@ -1786,25 +2594,31 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
1786
2594
|
}
|
|
1787
2595
|
return state;
|
|
1788
2596
|
}
|
|
1789
|
-
async _resolvePassphraseState(connectId, passphraseState, signal) {
|
|
2597
|
+
async _resolvePassphraseState(connectId, passphraseState, signal, operationId) {
|
|
1790
2598
|
try {
|
|
1791
|
-
const sessionId = await this._ensureSession(connectId, signal);
|
|
2599
|
+
const sessionId = operationId ? this._sessions.get(this._operations.resolve(operationId).connectId) : await this._ensureSession(connectId, signal);
|
|
2600
|
+
if (!sessionId) {
|
|
2601
|
+
return _hwkadaptercore.failure.call(void 0,
|
|
2602
|
+
_hwkadaptercore.HardwareErrorCode.OperationEnded,
|
|
2603
|
+
"Trezor operation connection is no longer active"
|
|
2604
|
+
);
|
|
2605
|
+
}
|
|
1792
2606
|
if (passphraseState) {
|
|
1793
2607
|
await this._alignAppSession(connectId, sessionId, passphraseState, signal);
|
|
1794
2608
|
return _hwkadaptercore.success.call(void 0, passphraseState);
|
|
1795
2609
|
}
|
|
1796
2610
|
const created = await _TrezorAdapter._abortable(
|
|
1797
2611
|
signal,
|
|
1798
|
-
|
|
2612
|
+
this._callConnector(sessionId, "__thpCreateSession", {
|
|
1799
2613
|
passphraseMode: "prompt"
|
|
1800
2614
|
})
|
|
1801
2615
|
);
|
|
1802
2616
|
const state = await this._deriveState(sessionId, signal);
|
|
1803
2617
|
const features = await _TrezorAdapter._abortable(
|
|
1804
2618
|
signal,
|
|
1805
|
-
|
|
2619
|
+
this._callConnector(sessionId, "getFeatures", { refresh: true })
|
|
1806
2620
|
);
|
|
1807
|
-
if (_optionalChain([features, 'optionalAccess',
|
|
2621
|
+
if (_optionalChain([features, 'optionalAccess', _145 => _145.passphrase_protection]) !== true) {
|
|
1808
2622
|
return _hwkadaptercore.success.call(void 0, null);
|
|
1809
2623
|
}
|
|
1810
2624
|
this._rememberVerifiedPassphraseSession(connectId, state, sessionId, created);
|
|
@@ -1852,7 +2666,16 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
1852
2666
|
}
|
|
1853
2667
|
const trustedNumericCode = typeof typed.code === "number" && KNOWN_HARDWARE_ERROR_CODES.has(typed.code) ? typed.code : void 0;
|
|
1854
2668
|
const code = _nullishCoalesce(_nullishCoalesce(trustedNumericCode, () => ( _TrezorAdapter._mapTrezorFailureCode(error))), () => ( _hwkadaptercore.HardwareErrorCode.UnknownError));
|
|
1855
|
-
|
|
2669
|
+
const stampedOrigin = _optionalChain([error, 'optionalAccess', _146 => _146.origin]);
|
|
2670
|
+
const origin = stampedOrigin === "device" || stampedOrigin === "transport" || stampedOrigin === "host" ? stampedOrigin : _hwkadaptercore.defaultOriginForCode.call(void 0, code);
|
|
2671
|
+
const params = typed.params && typeof typed.params === "object" ? typed.params : void 0;
|
|
2672
|
+
return _hwkadaptercore.failure.call(void 0,
|
|
2673
|
+
code,
|
|
2674
|
+
_nullishCoalesce(typed.message, () => ( String(error))),
|
|
2675
|
+
params,
|
|
2676
|
+
origin,
|
|
2677
|
+
_hwkadaptercore.isHwkRecoveryHint.call(void 0, typed.recovery) ? typed.recovery : void 0
|
|
2678
|
+
);
|
|
1856
2679
|
}
|
|
1857
2680
|
/**
|
|
1858
2681
|
* Emit `REQUEST_DEVICE_PERMISSION` and await the host's
|
|
@@ -1867,11 +2690,11 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
1867
2690
|
* - no `connectId` → environment-level check (scan / picker)
|
|
1868
2691
|
* - with `connectId` → device-level check (per-call gating)
|
|
1869
2692
|
*/
|
|
1870
|
-
async _ensureDevicePermission(connectId, deviceId) {
|
|
2693
|
+
async _ensureDevicePermission(connectId, deviceId, requestedTransport) {
|
|
1871
2694
|
if (!this._emitter.listenerCount(_hwkadaptercore.UI_REQUEST.REQUEST_DEVICE_PERMISSION)) {
|
|
1872
2695
|
return;
|
|
1873
2696
|
}
|
|
1874
|
-
const transportType = _nullishCoalesce(this.activeTransport, () => ( "usb"));
|
|
2697
|
+
const transportType = _nullishCoalesce(_nullishCoalesce(requestedTransport, () => ( this.activeTransport)), () => ( "usb"));
|
|
1875
2698
|
const waitPromise = this._uiRegistry.wait(
|
|
1876
2699
|
_hwkadaptercore.UI_REQUEST.REQUEST_DEVICE_PERMISSION,
|
|
1877
2700
|
{ timeoutMs: 6e4 }
|
|
@@ -1890,6 +2713,8 @@ var _TrezorAdapter = class _TrezorAdapter {
|
|
|
1890
2713
|
};
|
|
1891
2714
|
// Keys are matched after normalizeLogKey, so snake_case/camelCase both hit.
|
|
1892
2715
|
_TrezorAdapter._sensitiveLogKeys = /* @__PURE__ */ new Set([
|
|
2716
|
+
"extra",
|
|
2717
|
+
"knownconnections",
|
|
1893
2718
|
"credential",
|
|
1894
2719
|
"credentials",
|
|
1895
2720
|
"entropy",
|
|
@@ -2008,7 +2833,7 @@ async function fetchDefinitionHex(url, fetchImpl) {
|
|
|
2008
2833
|
}
|
|
2009
2834
|
return arrayBufferToHex(await response.arrayBuffer());
|
|
2010
2835
|
});
|
|
2011
|
-
} catch (
|
|
2836
|
+
} catch (e6) {
|
|
2012
2837
|
return void 0;
|
|
2013
2838
|
}
|
|
2014
2839
|
}
|
|
@@ -2037,7 +2862,7 @@ async function fetchSolanaTokenDefinition({
|
|
|
2037
2862
|
}
|
|
2038
2863
|
return Buffer.from(await response.arrayBuffer()).toString("hex");
|
|
2039
2864
|
});
|
|
2040
|
-
} catch (
|
|
2865
|
+
} catch (e7) {
|
|
2041
2866
|
return void 0;
|
|
2042
2867
|
}
|
|
2043
2868
|
}
|