@onekeyfe/hwk-trezor-adapter 1.2.0-alpha.74 → 1.2.0-alpha.76

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 CHANGED
@@ -28,7 +28,10 @@ declare class TrezorAdapter implements IHardwareWallet {
28
28
  private static _normalizeCallArgs;
29
29
  private static _splitCommonParams;
30
30
  private static _withAllNetworkRequestCommonParams;
31
+ private static readonly _sensitiveLogKeys;
32
+ private static _normalizeLogKey;
31
33
  private static _sanitizeForLog;
34
+ private static _redactForLog;
32
35
  private static _errorForLog;
33
36
  private _setPassphraseRequestContext;
34
37
  private static _trezorFailureMessage;
@@ -87,14 +90,13 @@ declare class TrezorAdapter implements IHardwareWallet {
87
90
  */
88
91
  uiResponse(response: UiResponseEvent): void;
89
92
  /**
90
- * Returns a stable per-seed identifier suitable for device-match verification.
91
- *
92
- * Trezor exposes `device_id` in Features a server-generated UUID written
93
- * during `wipe_device` and stable for the life of the seed. Unlike Ledger
94
- * (no native id, so a per-chain address is hashed), Trezor's id is global
95
- * across chains, so the `chain` argument is accepted for API parity but
96
- * ignored. For unsupported chains we still surface the id (since it would
97
- * be the same value anyway).
93
+ * Returns the Trezor `device_id` from Features a random 12-byte value the
94
+ * device stores and regenerates on `wipe_device`. It identifies the PHYSICAL
95
+ * DEVICE, not a seed/wallet: it is shared across passphrase wallets and
96
+ * changes after wipe/restore, so it suits device-match checks but must NOT be
97
+ * used as a wallet fingerprint (use `passphraseState` for wallet identity).
98
+ * Unlike Ledger (which hashes a per-chain address), it is chain-global, so
99
+ * `chain` is accepted for API parity but ignored.
98
100
  */
99
101
  getChainFingerprint(connectId: string, _deviceId: string, _chain: ChainForFingerprint): Promise<Response<string>>;
100
102
  /**
package/dist/index.d.ts CHANGED
@@ -28,7 +28,10 @@ declare class TrezorAdapter implements IHardwareWallet {
28
28
  private static _normalizeCallArgs;
29
29
  private static _splitCommonParams;
30
30
  private static _withAllNetworkRequestCommonParams;
31
+ private static readonly _sensitiveLogKeys;
32
+ private static _normalizeLogKey;
31
33
  private static _sanitizeForLog;
34
+ private static _redactForLog;
32
35
  private static _errorForLog;
33
36
  private _setPassphraseRequestContext;
34
37
  private static _trezorFailureMessage;
@@ -87,14 +90,13 @@ declare class TrezorAdapter implements IHardwareWallet {
87
90
  */
88
91
  uiResponse(response: UiResponseEvent): void;
89
92
  /**
90
- * Returns a stable per-seed identifier suitable for device-match verification.
91
- *
92
- * Trezor exposes `device_id` in Features a server-generated UUID written
93
- * during `wipe_device` and stable for the life of the seed. Unlike Ledger
94
- * (no native id, so a per-chain address is hashed), Trezor's id is global
95
- * across chains, so the `chain` argument is accepted for API parity but
96
- * ignored. For unsupported chains we still surface the id (since it would
97
- * be the same value anyway).
93
+ * Returns the Trezor `device_id` from Features a random 12-byte value the
94
+ * device stores and regenerates on `wipe_device`. It identifies the PHYSICAL
95
+ * DEVICE, not a seed/wallet: it is shared across passphrase wallets and
96
+ * changes after wipe/restore, so it suits device-match checks but must NOT be
97
+ * used as a wallet fingerprint (use `passphraseState` for wallet identity).
98
+ * Unlike Ledger (which hashes a per-chain address), it is chain-global, so
99
+ * `chain` is accepted for API parity but ignored.
98
100
  */
99
101
  getChainFingerprint(connectId: string, _deviceId: string, _chain: ChainForFingerprint): Promise<Response<string>>;
100
102
  /**
package/dist/index.js CHANGED
@@ -74,7 +74,7 @@ var TREZOR_BTC_NETWORK_COIN_MAP = {
74
74
  bcash: "Bcash",
75
75
  dash: "Dash"
76
76
  };
77
- var TrezorAdapter = class _TrezorAdapter {
77
+ var _TrezorAdapter = class _TrezorAdapter {
78
78
  constructor(connector) {
79
79
  this.vendor = "trezor";
80
80
  this._emitter = new (0, _hwkadaptercore.TypedEventEmitter)();
@@ -122,8 +122,8 @@ var TrezorAdapter = class _TrezorAdapter {
122
122
  ...data,
123
123
  payload: {
124
124
  ...payload,
125
- ..._optionalChain([context, 'optionalAccess', _ => _.passphraseState]) !== void 0 ? { passphraseState: context.passphraseState } : {},
126
- ..._optionalChain([context, 'optionalAccess', _2 => _2.useEmptyPassphrase]) !== void 0 ? { useEmptyPassphrase: context.useEmptyPassphrase } : {}
125
+ ..._optionalChain([context, 'optionalAccess', _2 => _2.passphraseState]) !== void 0 ? { passphraseState: context.passphraseState } : {},
126
+ ..._optionalChain([context, 'optionalAccess', _3 => _3.useEmptyPassphrase]) !== void 0 ? { useEmptyPassphrase: context.useEmptyPassphrase } : {}
127
127
  }
128
128
  }
129
129
  );
@@ -177,9 +177,9 @@ var TrezorAdapter = class _TrezorAdapter {
177
177
  return { rest: _nullishCoalesce(params, () => ( {})) };
178
178
  }
179
179
  static _withAllNetworkRequestCommonParams(item, commonParams) {
180
- const autoInstallApp = _optionalChain([commonParams, 'optionalAccess', _3 => _3.autoInstallApp]);
181
- const passphraseState = _optionalChain([commonParams, 'optionalAccess', _4 => _4.passphraseState]);
182
- const useEmptyPassphrase = _optionalChain([commonParams, 'optionalAccess', _5 => _5.useEmptyPassphrase]);
180
+ const autoInstallApp = _optionalChain([commonParams, 'optionalAccess', _4 => _4.autoInstallApp]);
181
+ const passphraseState = _optionalChain([commonParams, 'optionalAccess', _5 => _5.passphraseState]);
182
+ const useEmptyPassphrase = _optionalChain([commonParams, 'optionalAccess', _6 => _6.useEmptyPassphrase]);
183
183
  if (autoInstallApp === void 0 && passphraseState === void 0 && useEmptyPassphrase === void 0) {
184
184
  return item;
185
185
  }
@@ -190,26 +190,30 @@ var TrezorAdapter = class _TrezorAdapter {
190
190
  ...useEmptyPassphrase !== void 0 ? { useEmptyPassphrase } : {}
191
191
  };
192
192
  }
193
- static _sanitizeForLog(value) {
194
- if (!value || typeof value !== "object") return value;
195
- if (Array.isArray(value)) {
196
- return value.map((item) => _TrezorAdapter._sanitizeForLog(item));
193
+ static _normalizeLogKey(key) {
194
+ return key.replace(/[_-]/g, "").toLowerCase();
195
+ }
196
+ // Mirrors hd-core's logBlockEvent: a signing method's body is the user's
197
+ // transaction, so it is dropped wholesale; other methods redact by key.
198
+ static _sanitizeForLog(value, methodName) {
199
+ if (methodName && /sign/i.test(methodName)) return "[redacted]";
200
+ return _TrezorAdapter._redactForLog(value, /* @__PURE__ */ new WeakSet());
201
+ }
202
+ static _redactForLog(value, seen) {
203
+ if (ArrayBuffer.isView(value) || value instanceof ArrayBuffer) {
204
+ return `[BINARY:${value.byteLength}]`;
197
205
  }
198
- const sensitiveKeys = /* @__PURE__ */ new Set([
199
- "credential",
200
- "credentials",
201
- "host_static_key",
202
- "passphrase",
203
- "passphraseState",
204
- "pin",
205
- "trezor_static_public_key"
206
- ]);
207
- return Object.fromEntries(
206
+ if (!value || typeof value !== "object") return value;
207
+ if (seen.has(value)) return "[CIRCULAR]";
208
+ seen.add(value);
209
+ const out = Array.isArray(value) ? value.map((item) => _TrezorAdapter._redactForLog(item, seen)) : Object.fromEntries(
208
210
  Object.entries(value).map(([key, item]) => [
209
211
  key,
210
- sensitiveKeys.has(key) ? "[redacted]" : _TrezorAdapter._sanitizeForLog(item)
212
+ _TrezorAdapter._sensitiveLogKeys.has(_TrezorAdapter._normalizeLogKey(key)) && item !== null && item !== void 0 ? "[redacted]" : _TrezorAdapter._redactForLog(item, seen)
211
213
  ])
212
214
  );
215
+ seen.delete(value);
216
+ return out;
213
217
  }
214
218
  static _errorForLog(error) {
215
219
  if (!error || typeof error !== "object") return error;
@@ -239,8 +243,8 @@ var TrezorAdapter = class _TrezorAdapter {
239
243
  };
240
244
  }
241
245
  static _trezorFailureMessage(error) {
242
- const response = _optionalChain([error, 'optionalAccess', _6 => _6.response]);
243
- const message = _optionalChain([response, 'optionalAccess', _7 => _7.message]);
246
+ const response = _optionalChain([error, 'optionalAccess', _7 => _7.response]);
247
+ const message = _optionalChain([response, 'optionalAccess', _8 => _8.message]);
244
248
  if (!message || typeof message !== "object") return {};
245
249
  const failureMessage = message;
246
250
  return {
@@ -249,7 +253,7 @@ var TrezorAdapter = class _TrezorAdapter {
249
253
  };
250
254
  }
251
255
  static _mapTrezorFailureCode(error) {
252
- const directCode = _optionalChain([error, 'optionalAccess', _8 => _8.code]);
256
+ const directCode = _optionalChain([error, 'optionalAccess', _9 => _9.code]);
253
257
  if (directCode === "Device_InitializeFailed") {
254
258
  return _hwkadaptercore.HardwareErrorCode.PinCancelled;
255
259
  }
@@ -262,7 +266,7 @@ var TrezorAdapter = class _TrezorAdapter {
262
266
  if (directCode === "Failure_UnexpectedMessage") {
263
267
  return _hwkadaptercore.HardwareErrorCode.MethodNotSupported;
264
268
  }
265
- const message = _optionalChain([error, 'optionalAccess', _9 => _9.message]);
269
+ const message = _optionalChain([error, 'optionalAccess', _10 => _10.message]);
266
270
  if (typeof message === "string" && message.includes("Failed to execute 'transfer") && message.includes("on 'USBDevice'")) {
267
271
  return _hwkadaptercore.HardwareErrorCode.TransportError;
268
272
  }
@@ -410,7 +414,7 @@ var TrezorAdapter = class _TrezorAdapter {
410
414
  async searchDevices(options) {
411
415
  await this._ensureDevicePermission();
412
416
  const scanned = await this._connector.searchDevices(
413
- _optionalChain([options, 'optionalAccess', _10 => _10.waitForAllTransports]) ? { waitForAll: true } : void 0
417
+ _optionalChain([options, 'optionalAccess', _11 => _11.waitForAllTransports]) ? { waitForAll: true } : void 0
414
418
  );
415
419
  const scannedIds = new Set(scanned.map((d) => d.connectId));
416
420
  for (const connectId of [...this._devices.keys()]) {
@@ -457,7 +461,7 @@ var TrezorAdapter = class _TrezorAdapter {
457
461
  let liveDeviceId = "";
458
462
  const topLevelFailureIndexes = /* @__PURE__ */ new Set();
459
463
  const isSingleNetworkBundle = params.bundle.every(
460
- (item) => item.network === _optionalChain([params, 'access', _11 => _11.bundle, 'access', _12 => _12[0], 'optionalAccess', _13 => _13.network])
464
+ (item) => item.network === _optionalChain([params, 'access', _12 => _12.bundle, 'access', _13 => _13[0], 'optionalAccess', _14 => _14.network])
461
465
  );
462
466
  const getLiveDeviceId = async () => {
463
467
  if (liveDeviceId) return _hwkadaptercore.success.call(void 0, liveDeviceId);
@@ -517,7 +521,7 @@ var TrezorAdapter = class _TrezorAdapter {
517
521
  // One named boolean per abort reason.
518
522
  shouldAbortBundle: (response, { index }) => {
519
523
  const isSessionLevelFailure = topLevelFailureIndexes.has(index);
520
- const isWholeChainForbidden = isSingleNetworkBundle && _optionalChain([response, 'access', _14 => _14.payload, 'optionalAccess', _15 => _15.code]) === _hwkadaptercore.HardwareErrorCode.DevicePathForbidden;
524
+ const isWholeChainForbidden = isSingleNetworkBundle && _optionalChain([response, 'access', _15 => _15.payload, 'optionalAccess', _16 => _16.code]) === _hwkadaptercore.HardwareErrorCode.DevicePathForbidden;
521
525
  return isSessionLevelFailure || isWholeChainForbidden;
522
526
  }
523
527
  });
@@ -583,14 +587,13 @@ var TrezorAdapter = class _TrezorAdapter {
583
587
  this._connector.uiResponse(response);
584
588
  }
585
589
  /**
586
- * Returns a stable per-seed identifier suitable for device-match verification.
587
- *
588
- * Trezor exposes `device_id` in Features a server-generated UUID written
589
- * during `wipe_device` and stable for the life of the seed. Unlike Ledger
590
- * (no native id, so a per-chain address is hashed), Trezor's id is global
591
- * across chains, so the `chain` argument is accepted for API parity but
592
- * ignored. For unsupported chains we still surface the id (since it would
593
- * be the same value anyway).
590
+ * Returns the Trezor `device_id` from Features a random 12-byte value the
591
+ * device stores and regenerates on `wipe_device`. It identifies the PHYSICAL
592
+ * DEVICE, not a seed/wallet: it is shared across passphrase wallets and
593
+ * changes after wipe/restore, so it suits device-match checks but must NOT be
594
+ * used as a wallet fingerprint (use `passphraseState` for wallet identity).
595
+ * Unlike Ledger (which hashes a per-chain address), it is chain-global, so
596
+ * `chain` is accepted for API parity but ignored.
594
597
  */
595
598
  async getChainFingerprint(connectId, _deviceId, _chain) {
596
599
  return this._getTrezorDeviceId(connectId);
@@ -746,7 +749,7 @@ var TrezorAdapter = class _TrezorAdapter {
746
749
  method: methodName,
747
750
  connectId: call.connectId || "(empty)",
748
751
  deviceId: deviceId || void 0,
749
- params: _TrezorAdapter._sanitizeForLog(call.params)
752
+ params: _TrezorAdapter._sanitizeForLog(call.params, methodName)
750
753
  });
751
754
  try {
752
755
  const response = await this._jobQueue.enqueue(
@@ -768,7 +771,7 @@ var TrezorAdapter = class _TrezorAdapter {
768
771
  debugLog("[TrezorAdapter][RES]", {
769
772
  method: methodName,
770
773
  success: response.success,
771
- payload: _TrezorAdapter._sanitizeForLog(response.payload)
774
+ payload: _TrezorAdapter._sanitizeForLog(response.payload, methodName)
772
775
  });
773
776
  return response;
774
777
  } catch (error) {
@@ -776,7 +779,7 @@ var TrezorAdapter = class _TrezorAdapter {
776
779
  debugLog("[TrezorAdapter][RES]", {
777
780
  method: methodName,
778
781
  success: false,
779
- payload: _TrezorAdapter._sanitizeForLog(response.payload)
782
+ payload: _TrezorAdapter._sanitizeForLog(response.payload, methodName)
780
783
  });
781
784
  return response;
782
785
  }
@@ -855,7 +858,7 @@ var TrezorAdapter = class _TrezorAdapter {
855
858
  if (pending) return pending;
856
859
  const promise = (async () => {
857
860
  try {
858
- if (_optionalChain([signal, 'optionalAccess', _16 => _16.aborted])) {
861
+ if (_optionalChain([signal, 'optionalAccess', _17 => _17.aborted])) {
859
862
  throw Object.assign(new Error("Trezor connection aborted"), {
860
863
  code: _hwkadaptercore.HardwareErrorCode.UserAborted
861
864
  });
@@ -901,8 +904,8 @@ var TrezorAdapter = class _TrezorAdapter {
901
904
  passphraseMode: "prompt"
902
905
  })
903
906
  );
904
- if (_optionalChain([created, 'optionalAccess', _17 => _17.protocol]) === "thp" && !created.thpSessionId) return;
905
- if (_optionalChain([created, 'optionalAccess', _18 => _18.protocol]) !== "thp" && _optionalChain([created, 'optionalAccess', _19 => _19.protocol]) !== "v1") return;
907
+ if (_optionalChain([created, 'optionalAccess', _18 => _18.protocol]) === "thp" && !created.thpSessionId) return;
908
+ if (_optionalChain([created, 'optionalAccess', _19 => _19.protocol]) !== "thp" && _optionalChain([created, 'optionalAccess', _20 => _20.protocol]) !== "v1") return;
906
909
  const state = await this._deriveState(sessionId, signal);
907
910
  if (state !== passphraseState) {
908
911
  throw Object.assign(
@@ -916,13 +919,13 @@ var TrezorAdapter = class _TrezorAdapter {
916
919
  }
917
920
  _rememberVerifiedPassphraseSession(connectId, passphraseState, sessionId, created) {
918
921
  let session;
919
- if (_optionalChain([created, 'optionalAccess', _20 => _20.protocol]) === "thp" && typeof created.thpSessionId === "string") {
922
+ if (_optionalChain([created, 'optionalAccess', _21 => _21.protocol]) === "thp" && typeof created.thpSessionId === "string") {
920
923
  session = {
921
924
  sessionId,
922
925
  protocol: "thp",
923
926
  thpSessionId: created.thpSessionId
924
927
  };
925
- } else if (_optionalChain([created, 'optionalAccess', _21 => _21.protocol]) === "v1") {
928
+ } else if (_optionalChain([created, 'optionalAccess', _22 => _22.protocol]) === "v1") {
926
929
  session = {
927
930
  sessionId,
928
931
  protocol: "v1"
@@ -942,7 +945,7 @@ var TrezorAdapter = class _TrezorAdapter {
942
945
  }
943
946
  }
944
947
  async _reuseVerifiedPassphraseSession(connectId, sessionId, passphraseState, signal) {
945
- const cached = _optionalChain([this, 'access', _22 => _22._verifiedPassphraseSessionsByConnectId, 'access', _23 => _23.get, 'call', _24 => _24(connectId), 'optionalAccess', _25 => _25.get, 'call', _26 => _26(passphraseState)]);
948
+ const cached = _optionalChain([this, 'access', _23 => _23._verifiedPassphraseSessionsByConnectId, 'access', _24 => _24.get, 'call', _25 => _25(connectId), 'optionalAccess', _26 => _26.get, 'call', _27 => _27(passphraseState)]);
946
949
  if (!cached || cached.sessionId !== sessionId) {
947
950
  this._forgetVerifiedPassphraseSession(connectId, passphraseState);
948
951
  return false;
@@ -994,7 +997,7 @@ var TrezorAdapter = class _TrezorAdapter {
994
997
  showOnDevice: false
995
998
  })
996
999
  );
997
- const state = _optionalChain([derived, 'optionalAccess', _27 => _27.publicKey]);
1000
+ const state = _optionalChain([derived, 'optionalAccess', _28 => _28.publicKey]);
998
1001
  if (!state) {
999
1002
  throw Object.assign(new Error("Failed to derive passphrase state (wallet public key)"), {
1000
1003
  code: _hwkadaptercore.HardwareErrorCode.UnknownError
@@ -1020,7 +1023,7 @@ var TrezorAdapter = class _TrezorAdapter {
1020
1023
  signal,
1021
1024
  _TrezorAdapter._callConnector(this._connector, sessionId, "getFeatures", { refresh: true })
1022
1025
  );
1023
- if (_optionalChain([features, 'optionalAccess', _28 => _28.passphrase_protection]) !== true) {
1026
+ if (_optionalChain([features, 'optionalAccess', _29 => _29.passphrase_protection]) !== true) {
1024
1027
  return _hwkadaptercore.success.call(void 0, null);
1025
1028
  }
1026
1029
  this._rememberVerifiedPassphraseSession(connectId, state, sessionId, created);
@@ -1104,9 +1107,46 @@ var TrezorAdapter = class _TrezorAdapter {
1104
1107
  }
1105
1108
  }
1106
1109
  };
1110
+ // Keys are matched after normalizeLogKey, so snake_case/camelCase both hit.
1111
+ _TrezorAdapter._sensitiveLogKeys = /* @__PURE__ */ new Set([
1112
+ "credential",
1113
+ "credentials",
1114
+ "entropy",
1115
+ "hoststatickey",
1116
+ "mnemonic",
1117
+ "mnemonics",
1118
+ "passphrase",
1119
+ "passphrasestate",
1120
+ "password",
1121
+ "pin",
1122
+ "privatekey",
1123
+ "seed",
1124
+ "session",
1125
+ "sessionid",
1126
+ "trezorstaticpublickey",
1127
+ "word",
1128
+ "words",
1129
+ "xprv"
1130
+ ]);
1131
+ var TrezorAdapter = _TrezorAdapter;
1107
1132
 
1108
1133
  // src/utils/ethereumDefinitions.ts
1109
1134
  var DEFAULT_ETHEREUM_DEFINITIONS_BASE_URL = "https://data.trezor.io/firmware/eth-definitions";
1135
+ var DEFINITIONS_FETCH_TIMEOUT_MS = 2e4;
1136
+ async function runWithTimeout(run, timeoutMs = DEFINITIONS_FETCH_TIMEOUT_MS) {
1137
+ let timer;
1138
+ const deadline = new Promise((_, reject) => {
1139
+ timer = setTimeout(
1140
+ () => reject(new Error(`definitions fetch timed out after ${timeoutMs}ms`)),
1141
+ timeoutMs
1142
+ );
1143
+ });
1144
+ try {
1145
+ return await Promise.race([run(), deadline]);
1146
+ } finally {
1147
+ if (timer) clearTimeout(timer);
1148
+ }
1149
+ }
1110
1150
  function getSlip44FromPath(path) {
1111
1151
  const segments = path.trim().replace(/^m\//i, "").split("/");
1112
1152
  const coinType = segments[1];
@@ -1180,11 +1220,13 @@ async function buildEthereumDefinitionsForSignTx({
1180
1220
  }
1181
1221
  async function fetchDefinitionHex(url, fetchImpl) {
1182
1222
  try {
1183
- const response = await fetchImpl(url);
1184
- if (response.status !== 200) {
1185
- return void 0;
1186
- }
1187
- return arrayBufferToHex(await response.arrayBuffer());
1223
+ return await runWithTimeout(async () => {
1224
+ const response = await fetchImpl(url);
1225
+ if (response.status !== 200) {
1226
+ return void 0;
1227
+ }
1228
+ return arrayBufferToHex(await response.arrayBuffer());
1229
+ });
1188
1230
  } catch (e3) {
1189
1231
  return void 0;
1190
1232
  }
@@ -1207,11 +1249,13 @@ async function fetchSolanaTokenDefinition({
1207
1249
  return void 0;
1208
1250
  }
1209
1251
  try {
1210
- const response = await fetchImpl(`${baseUrl}/${tokenMint}.dat`);
1211
- if (response.status !== 200) {
1212
- return void 0;
1213
- }
1214
- return Buffer.from(await response.arrayBuffer()).toString("hex");
1252
+ return await runWithTimeout(async () => {
1253
+ const response = await fetchImpl(`${baseUrl}/${tokenMint}.dat`);
1254
+ if (response.status !== 200) {
1255
+ return void 0;
1256
+ }
1257
+ return Buffer.from(await response.arrayBuffer()).toString("hex");
1258
+ });
1215
1259
  } catch (e4) {
1216
1260
  return void 0;
1217
1261
  }