@onekeyfe/hwk-ledger-adapter 1.1.26-alpha.100 → 1.1.26-alpha.101

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
@@ -1,4 +1,4 @@
1
- import { IHardwareWallet, IConnector, TransportType, IUiHandler, DeviceInfo, Response, ChainCapability, EvmGetAddressParams, EvmAddress, ProgressCallback, EvmGetPublicKeyParams, EvmPublicKey, EvmSignTxParams, EvmSignedTx, EvmSignMsgParams, EvmSignature, EvmSignTypedDataParams, BtcGetAddressParams, BtcAddress, BtcGetPublicKeyParams, BtcPublicKey, BtcSignTxParams, BtcSignedTx, BtcSignMsgParams, BtcSignature, SolGetAddressParams, SolAddress, SolGetPublicKeyParams, SolPublicKey, SolSignTxParams, SolSignedTx, SolSignMsgParams, SolSignature, TronGetAddressParams, TronAddress, TronSignTxParams, TronSignedTx, TronSignMsgParams, TronSignature, HardwareEventMap, DeviceEventListener, ChainForFingerprint, ConnectionType, DeviceDescriptor, ConnectorDevice, ConnectorSession, ConnectorEventType, ConnectorEventMap, DeviceChangeEvent, HardwareErrorCode } from '@onekeyfe/hwk-adapter-core';
1
+ import { IHardwareWallet, IConnector, TransportType, IUiHandler, DeviceInfo, Response, ChainCapability, EvmGetAddressParams, EvmAddress, ProgressCallback, EvmGetPublicKeyParams, EvmPublicKey, EvmSignTxParams, EvmSignedTx, EvmSignMsgParams, EvmSignature, EvmSignTypedDataParams, BtcGetAddressParams, BtcAddress, BtcGetPublicKeyParams, BtcPublicKey, BtcSignTxParams, BtcSignedTx, BtcSignPsbtParams, BtcSignedPsbt, BtcSignMsgParams, BtcSignature, SolGetAddressParams, SolAddress, SolGetPublicKeyParams, SolPublicKey, SolSignTxParams, SolSignedTx, SolSignMsgParams, SolSignature, TronGetAddressParams, TronAddress, TronSignTxParams, TronSignedTx, TronSignMsgParams, TronSignature, HardwareEventMap, DeviceEventListener, ChainForFingerprint, ConnectionType, DeviceDescriptor, ConnectorDevice, ConnectorSession, ConnectorEventType, ConnectorEventMap, DeviceChangeEvent, HardwareErrorCode } from '@onekeyfe/hwk-adapter-core';
2
2
  import { DeviceManagementKit, DeviceActionState as DeviceActionState$1, DiscoveredDevice, ExecuteDeviceActionReturnType } from '@ledgerhq/device-management-kit';
3
3
  import { Address, Signature, SignerEth as SignerEth$1, TypedData } from '@ledgerhq/device-signer-kit-ethereum';
4
4
  import { SignerBtc as SignerBtc$1 } from '@ledgerhq/device-signer-kit-bitcoin';
@@ -56,6 +56,7 @@ declare class LedgerAdapter implements IHardwareWallet {
56
56
  btcGetAddresses(connectId: string, deviceId: string, params: BtcGetAddressParams[], onProgress?: ProgressCallback): Promise<Response<BtcAddress[]>>;
57
57
  btcGetPublicKey(connectId: string, deviceId: string, params: BtcGetPublicKeyParams): Promise<Response<BtcPublicKey>>;
58
58
  btcSignTransaction(connectId: string, deviceId: string, params: BtcSignTxParams): Promise<Response<BtcSignedTx>>;
59
+ btcSignPsbt(connectId: string, deviceId: string, params: BtcSignPsbtParams): Promise<Response<BtcSignedPsbt>>;
59
60
  btcSignMessage(connectId: string, deviceId: string, params: BtcSignMsgParams): Promise<Response<BtcSignature>>;
60
61
  btcGetMasterFingerprint(connectId: string, deviceId: string): Promise<Response<{
61
62
  masterFingerprint: string;
@@ -78,8 +79,10 @@ declare class LedgerAdapter implements IHardwareWallet {
78
79
  /**
79
80
  * Verify that the connected device matches the expected fingerprint.
80
81
  *
81
- * - If deviceId is empty, verification is skipped (returns true).
82
+ * - If deviceId is empty, verification is skipped (returns { success: true }).
82
83
  * - deviceId is used here as the stored fingerprint to compare against.
84
+ * - On mismatch, returns both expected and actual fingerprints so the caller
85
+ * can surface an informative error (e.g. for logs / bug reports).
83
86
  */
84
87
  private _verifyDeviceFingerprint;
85
88
  /**
@@ -464,6 +467,11 @@ declare class DmkTransport extends Transport {
464
467
  * Convert a DMK DeviceAction (Observable-based) into a Promise.
465
468
  * Handles pending -> completed/error state transitions and interaction callbacks.
466
469
  *
470
+ * Tracks the last DMK step observed (e.g. `signer.eth.steps.blindSignTransactionFallback`)
471
+ * and attaches it to the rejected error as a non-enumerable `_lastStep` property,
472
+ * so upstream error classifiers can distinguish failure contexts (e.g. Blind signing
473
+ * disabled vs. generic Invalid data).
474
+ *
467
475
  * @param timeoutMs Timeout in ms. Resets each time the Observable emits (device is alive).
468
476
  * Pass 0 to disable. Default: 30s.
469
477
  */
@@ -524,6 +532,7 @@ declare function isDeviceLockedError(err: unknown): boolean;
524
532
  declare function mapLedgerError(err: unknown): {
525
533
  code: HardwareErrorCode;
526
534
  message: string;
535
+ appName?: string;
527
536
  };
528
537
 
529
538
  export { AppManager, type DeviceActionState, type DmkDiscoveredDevice, DmkTransport, LedgerAdapter, LedgerConnectorBase, type LedgerConnectorBaseOptions, LedgerDeviceManager, SignerBtc, type SignerBtcAddress, SignerEth, type SignerEvmAddress, type SignerEvmSignature, SignerManager, SignerSol, type TransportFactory, deviceActionToPromise, isDeviceLockedError, mapLedgerError };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { IHardwareWallet, IConnector, TransportType, IUiHandler, DeviceInfo, Response, ChainCapability, EvmGetAddressParams, EvmAddress, ProgressCallback, EvmGetPublicKeyParams, EvmPublicKey, EvmSignTxParams, EvmSignedTx, EvmSignMsgParams, EvmSignature, EvmSignTypedDataParams, BtcGetAddressParams, BtcAddress, BtcGetPublicKeyParams, BtcPublicKey, BtcSignTxParams, BtcSignedTx, BtcSignMsgParams, BtcSignature, SolGetAddressParams, SolAddress, SolGetPublicKeyParams, SolPublicKey, SolSignTxParams, SolSignedTx, SolSignMsgParams, SolSignature, TronGetAddressParams, TronAddress, TronSignTxParams, TronSignedTx, TronSignMsgParams, TronSignature, HardwareEventMap, DeviceEventListener, ChainForFingerprint, ConnectionType, DeviceDescriptor, ConnectorDevice, ConnectorSession, ConnectorEventType, ConnectorEventMap, DeviceChangeEvent, HardwareErrorCode } from '@onekeyfe/hwk-adapter-core';
1
+ import { IHardwareWallet, IConnector, TransportType, IUiHandler, DeviceInfo, Response, ChainCapability, EvmGetAddressParams, EvmAddress, ProgressCallback, EvmGetPublicKeyParams, EvmPublicKey, EvmSignTxParams, EvmSignedTx, EvmSignMsgParams, EvmSignature, EvmSignTypedDataParams, BtcGetAddressParams, BtcAddress, BtcGetPublicKeyParams, BtcPublicKey, BtcSignTxParams, BtcSignedTx, BtcSignPsbtParams, BtcSignedPsbt, BtcSignMsgParams, BtcSignature, SolGetAddressParams, SolAddress, SolGetPublicKeyParams, SolPublicKey, SolSignTxParams, SolSignedTx, SolSignMsgParams, SolSignature, TronGetAddressParams, TronAddress, TronSignTxParams, TronSignedTx, TronSignMsgParams, TronSignature, HardwareEventMap, DeviceEventListener, ChainForFingerprint, ConnectionType, DeviceDescriptor, ConnectorDevice, ConnectorSession, ConnectorEventType, ConnectorEventMap, DeviceChangeEvent, HardwareErrorCode } from '@onekeyfe/hwk-adapter-core';
2
2
  import { DeviceManagementKit, DeviceActionState as DeviceActionState$1, DiscoveredDevice, ExecuteDeviceActionReturnType } from '@ledgerhq/device-management-kit';
3
3
  import { Address, Signature, SignerEth as SignerEth$1, TypedData } from '@ledgerhq/device-signer-kit-ethereum';
4
4
  import { SignerBtc as SignerBtc$1 } from '@ledgerhq/device-signer-kit-bitcoin';
@@ -56,6 +56,7 @@ declare class LedgerAdapter implements IHardwareWallet {
56
56
  btcGetAddresses(connectId: string, deviceId: string, params: BtcGetAddressParams[], onProgress?: ProgressCallback): Promise<Response<BtcAddress[]>>;
57
57
  btcGetPublicKey(connectId: string, deviceId: string, params: BtcGetPublicKeyParams): Promise<Response<BtcPublicKey>>;
58
58
  btcSignTransaction(connectId: string, deviceId: string, params: BtcSignTxParams): Promise<Response<BtcSignedTx>>;
59
+ btcSignPsbt(connectId: string, deviceId: string, params: BtcSignPsbtParams): Promise<Response<BtcSignedPsbt>>;
59
60
  btcSignMessage(connectId: string, deviceId: string, params: BtcSignMsgParams): Promise<Response<BtcSignature>>;
60
61
  btcGetMasterFingerprint(connectId: string, deviceId: string): Promise<Response<{
61
62
  masterFingerprint: string;
@@ -78,8 +79,10 @@ declare class LedgerAdapter implements IHardwareWallet {
78
79
  /**
79
80
  * Verify that the connected device matches the expected fingerprint.
80
81
  *
81
- * - If deviceId is empty, verification is skipped (returns true).
82
+ * - If deviceId is empty, verification is skipped (returns { success: true }).
82
83
  * - deviceId is used here as the stored fingerprint to compare against.
84
+ * - On mismatch, returns both expected and actual fingerprints so the caller
85
+ * can surface an informative error (e.g. for logs / bug reports).
83
86
  */
84
87
  private _verifyDeviceFingerprint;
85
88
  /**
@@ -464,6 +467,11 @@ declare class DmkTransport extends Transport {
464
467
  * Convert a DMK DeviceAction (Observable-based) into a Promise.
465
468
  * Handles pending -> completed/error state transitions and interaction callbacks.
466
469
  *
470
+ * Tracks the last DMK step observed (e.g. `signer.eth.steps.blindSignTransactionFallback`)
471
+ * and attaches it to the rejected error as a non-enumerable `_lastStep` property,
472
+ * so upstream error classifiers can distinguish failure contexts (e.g. Blind signing
473
+ * disabled vs. generic Invalid data).
474
+ *
467
475
  * @param timeoutMs Timeout in ms. Resets each time the Observable emits (device is alive).
468
476
  * Pass 0 to disable. Default: 30s.
469
477
  */
@@ -524,6 +532,7 @@ declare function isDeviceLockedError(err: unknown): boolean;
524
532
  declare function mapLedgerError(err: unknown): {
525
533
  code: HardwareErrorCode;
526
534
  message: string;
535
+ appName?: string;
527
536
  };
528
537
 
529
538
  export { AppManager, type DeviceActionState, type DmkDiscoveredDevice, DmkTransport, LedgerAdapter, LedgerConnectorBase, type LedgerConnectorBaseOptions, LedgerDeviceManager, SignerBtc, type SignerBtcAddress, SignerEth, type SignerEvmAddress, type SignerEvmSignature, SignerManager, SignerSol, type TransportFactory, deviceActionToPromise, isDeviceLockedError, mapLedgerError };
package/dist/index.js CHANGED
@@ -54,6 +54,38 @@ var LOCKED_ERROR_CODES = /* @__PURE__ */ new Set(["5515", "21781", "6982", "2701
54
54
  var USER_REJECTED_CODES = /* @__PURE__ */ new Set(["6985", "27013"]);
55
55
  var WRONG_APP_CODES = /* @__PURE__ */ new Set(["6e00", "28160", "6d00", "27904", "6a83", "27267"]);
56
56
  var APP_NOT_INSTALLED_CODES = /* @__PURE__ */ new Set(["6807", "26631"]);
57
+ var STEP_BLIND_SIGN_FALLBACK = "signer.eth.steps.blindSignTransactionFallback";
58
+ function getEthAppErrorCode(err) {
59
+ if (!err || typeof err !== "object") return null;
60
+ const e = err;
61
+ if (e._tag === "EthAppCommandError" && typeof e.errorCode === "string") {
62
+ return e.errorCode.toLowerCase();
63
+ }
64
+ const orig = e.originalError;
65
+ if (orig?._tag === "EthAppCommandError" && typeof orig.errorCode === "string") {
66
+ return orig.errorCode.toLowerCase();
67
+ }
68
+ return null;
69
+ }
70
+ function mapEthAppError(ethCode, lastStep) {
71
+ switch (ethCode) {
72
+ case "6a80":
73
+ if (lastStep === STEP_BLIND_SIGN_FALLBACK) {
74
+ return import_hwk_adapter_core.HardwareErrorCode.EvmBlindSigningRequired;
75
+ }
76
+ return null;
77
+ case "6984":
78
+ return import_hwk_adapter_core.HardwareErrorCode.EvmClearSignPluginMissing;
79
+ case "6a84":
80
+ return import_hwk_adapter_core.HardwareErrorCode.EvmDataTooLarge;
81
+ case "6501":
82
+ return import_hwk_adapter_core.HardwareErrorCode.EvmTxTypeNotSupported;
83
+ case "911c":
84
+ return import_hwk_adapter_core.HardwareErrorCode.AppTooOld;
85
+ default:
86
+ return null;
87
+ }
88
+ }
57
89
  function isDeviceLockedError(err) {
58
90
  if (!err || typeof err !== "object") return false;
59
91
  const e = err;
@@ -145,12 +177,32 @@ function mapLedgerError(err) {
145
177
  } else if (isTimeoutError(err)) {
146
178
  code = import_hwk_adapter_core.HardwareErrorCode.OperationTimeout;
147
179
  } else {
148
- code = import_hwk_adapter_core.HardwareErrorCode.UnknownError;
180
+ const ethCode = getEthAppErrorCode(err);
181
+ const lastStep = err && typeof err === "object" ? err._lastStep : void 0;
182
+ const mapped = ethCode ? mapEthAppError(ethCode, lastStep) : null;
183
+ code = mapped ?? import_hwk_adapter_core.HardwareErrorCode.UnknownError;
184
+ }
185
+ const appName = err && typeof err === "object" ? err.appName : void 0;
186
+ return { code, message: (0, import_hwk_adapter_core.enrichErrorMessage)(code, originalMessage), appName };
187
+ }
188
+
189
+ // src/utils/debugLog.ts
190
+ var DEBUG = false;
191
+ function debugLog(...args) {
192
+ if (DEBUG) {
193
+ console.debug(...args);
194
+ }
195
+ }
196
+ function debugError(...args) {
197
+ if (DEBUG) {
198
+ console.error(...args);
149
199
  }
150
- return { code, message: (0, import_hwk_adapter_core.enrichErrorMessage)(code, originalMessage) };
151
200
  }
152
201
 
153
202
  // src/adapter/LedgerAdapter.ts
203
+ function formatDeviceMismatchError(expected, actual) {
204
+ return `Wrong device: expected ${expected}, got ${actual}`;
205
+ }
154
206
  var _LedgerAdapter = class _LedgerAdapter {
155
207
  constructor(connector) {
156
208
  this.vendor = "ledger";
@@ -243,7 +295,7 @@ var _LedgerAdapter = class _LedgerAdapter {
243
295
  async searchDevices() {
244
296
  await this._ensureDevicePermission();
245
297
  const devices = await this.connector.searchDevices();
246
- console.log("[DMK] adapter.searchDevices raw:", JSON.stringify(devices));
298
+ debugLog("[DMK] adapter.searchDevices raw:", JSON.stringify(devices));
247
299
  for (const d of devices) {
248
300
  if (d.connectId) {
249
301
  this._discoveredDevices.set(d.connectId, this.connectorDeviceToDeviceInfo(d));
@@ -293,8 +345,18 @@ var _LedgerAdapter = class _LedgerAdapter {
293
345
  // ---------------------------------------------------------------------------
294
346
  async callChain(connectId, deviceId, chain, method, params, skipFingerprint = false) {
295
347
  await this._ensureDevicePermission(connectId, deviceId);
296
- if (!skipFingerprint && !await this._verifyDeviceFingerprint(connectId, deviceId, chain)) {
297
- return (0, import_hwk_adapter_core2.failure)(import_hwk_adapter_core2.HardwareErrorCode.DeviceMismatch, "Wrong device connected");
348
+ if (!skipFingerprint) {
349
+ const fp = await this._verifyDeviceFingerprint(
350
+ connectId,
351
+ deviceId,
352
+ chain
353
+ );
354
+ if (!fp.success) {
355
+ return (0, import_hwk_adapter_core2.failure)(
356
+ import_hwk_adapter_core2.HardwareErrorCode.DeviceMismatch,
357
+ formatDeviceMismatchError(fp.expected, fp.actual)
358
+ );
359
+ }
298
360
  }
299
361
  try {
300
362
  const result = await this.connectorCall(connectId, method, params);
@@ -309,8 +371,18 @@ var _LedgerAdapter = class _LedgerAdapter {
309
371
  */
310
372
  async callChainBatch(connectId, deviceId, chain, method, params, onProgress, skipFingerprint = false) {
311
373
  await this._ensureDevicePermission(connectId, deviceId);
312
- if (!skipFingerprint && !await this._verifyDeviceFingerprint(connectId, deviceId, chain)) {
313
- return (0, import_hwk_adapter_core2.failure)(import_hwk_adapter_core2.HardwareErrorCode.DeviceMismatch, "Wrong device connected");
374
+ if (!skipFingerprint) {
375
+ const fp = await this._verifyDeviceFingerprint(
376
+ connectId,
377
+ deviceId,
378
+ chain
379
+ );
380
+ if (!fp.success) {
381
+ return (0, import_hwk_adapter_core2.failure)(
382
+ import_hwk_adapter_core2.HardwareErrorCode.DeviceMismatch,
383
+ formatDeviceMismatchError(fp.expected, fp.actual)
384
+ );
385
+ }
314
386
  }
315
387
  const results = [];
316
388
  for (let i = 0; i < params.length; i++) {
@@ -374,6 +446,9 @@ var _LedgerAdapter = class _LedgerAdapter {
374
446
  btcSignTransaction(connectId, deviceId, params) {
375
447
  return this.callChain(connectId, deviceId, "btc", "btcSignTransaction", params);
376
448
  }
449
+ btcSignPsbt(connectId, deviceId, params) {
450
+ return this.callChain(connectId, deviceId, "btc", "btcSignPsbt", params);
451
+ }
377
452
  btcSignMessage(connectId, deviceId, params) {
378
453
  return this.callChain(connectId, deviceId, "btc", "btcSignMessage", params);
379
454
  }
@@ -476,7 +551,7 @@ var _LedgerAdapter = class _LedgerAdapter {
476
551
  );
477
552
  try {
478
553
  const address = await this._deriveAddressForFingerprint(connectId, chain);
479
- console.log("[LedgerAdapter] getChainFingerprint address:", address?.substring(0, 20));
554
+ debugLog("[LedgerAdapter] getChainFingerprint address:", address?.substring(0, 20));
480
555
  return (0, import_hwk_adapter_core2.success)((0, import_hwk_adapter_core2.deriveDeviceFingerprint)(address));
481
556
  } catch (err) {
482
557
  console.error(
@@ -490,19 +565,24 @@ var _LedgerAdapter = class _LedgerAdapter {
490
565
  /**
491
566
  * Verify that the connected device matches the expected fingerprint.
492
567
  *
493
- * - If deviceId is empty, verification is skipped (returns true).
568
+ * - If deviceId is empty, verification is skipped (returns { success: true }).
494
569
  * - deviceId is used here as the stored fingerprint to compare against.
570
+ * - On mismatch, returns both expected and actual fingerprints so the caller
571
+ * can surface an informative error (e.g. for logs / bug reports).
495
572
  */
496
573
  async _verifyDeviceFingerprint(connectId, deviceId, chain) {
497
- if (!deviceId) return true;
574
+ if (!deviceId) return { success: true };
498
575
  try {
499
576
  const address = await this._deriveAddressForFingerprint(connectId, chain);
500
577
  const fingerprint = (0, import_hwk_adapter_core2.deriveDeviceFingerprint)(address);
501
- return fingerprint === deviceId;
578
+ if (fingerprint === deviceId) {
579
+ return { success: true };
580
+ }
581
+ return { success: false, expected: deviceId, actual: fingerprint };
502
582
  } catch (err) {
503
583
  const mapped = mapLedgerError(err);
504
584
  if (mapped.code === import_hwk_adapter_core2.HardwareErrorCode.WrongApp || mapped.code === import_hwk_adapter_core2.HardwareErrorCode.DeviceLocked) {
505
- return true;
585
+ return { success: true };
506
586
  }
507
587
  throw err;
508
588
  }
@@ -658,7 +738,7 @@ var _LedgerAdapter = class _LedgerAdapter {
658
738
  * 4. On disconnect error: clears stale session, re-connects, retries once
659
739
  */
660
740
  async connectorCall(connectId, method, params) {
661
- console.log("[LedgerAdapter] connectorCall:", method, "connectId:", connectId || "(empty)");
741
+ debugLog("[LedgerAdapter] connectorCall:", method, "connectId:", connectId || "(empty)");
662
742
  const resolvedConnectId = await this.ensureConnected(connectId);
663
743
  const sessionId = this._sessions.get(resolvedConnectId);
664
744
  console.log(
@@ -678,7 +758,7 @@ var _LedgerAdapter = class _LedgerAdapter {
678
758
  return await this.connector.call(sessionId, method, params);
679
759
  } catch (err) {
680
760
  const errObj = err;
681
- console.log("[LedgerAdapter] connectorCall error:", method, {
761
+ debugLog("[LedgerAdapter] connectorCall error:", method, {
682
762
  message: errObj?.message,
683
763
  _tag: errObj?._tag,
684
764
  errorCode: errObj?.errorCode,
@@ -687,7 +767,7 @@ var _LedgerAdapter = class _LedgerAdapter {
687
767
  isLocked: isDeviceLockedError(err)
688
768
  });
689
769
  if (isDeviceDisconnectedError(err)) {
690
- console.log("[LedgerAdapter] disconnected, retrying with fresh connection...");
770
+ debugLog("[LedgerAdapter] disconnected, retrying with fresh connection...");
691
771
  this._discoveredDevices.clear();
692
772
  return this._retryWithFreshConnection(resolvedConnectId, method, params, err);
693
773
  }
@@ -696,7 +776,7 @@ var _LedgerAdapter = class _LedgerAdapter {
696
776
  return this.connector.call(sessionId, method, params);
697
777
  }
698
778
  if (isTimeoutError(err)) {
699
- console.log("[LedgerAdapter] timeout, retrying with fresh connection...");
779
+ debugLog("[LedgerAdapter] timeout, retrying with fresh connection...");
700
780
  this._discoveredDevices.delete(resolvedConnectId);
701
781
  return this._retryWithFreshConnection(resolvedConnectId, method, params, err);
702
782
  }
@@ -748,13 +828,13 @@ var _LedgerAdapter = class _LedgerAdapter {
748
828
  * Uses mapLedgerError to parse Ledger DMK error codes into HardwareErrorCode values.
749
829
  */
750
830
  errorToFailure(err) {
751
- console.error("[LedgerAdapter] error:", err);
831
+ debugError("[LedgerAdapter] error:", err);
752
832
  if (err && typeof err === "object" && "code" in err && typeof err.code === "number") {
753
833
  const e = err;
754
- return (0, import_hwk_adapter_core2.failure)(e.code, e.message ?? "Unknown error");
834
+ return (0, import_hwk_adapter_core2.failure)(e.code, e.message ?? "Unknown error", e.appName);
755
835
  }
756
836
  const mapped = mapLedgerError(err);
757
- return (0, import_hwk_adapter_core2.failure)(mapped.code, mapped.message);
837
+ return (0, import_hwk_adapter_core2.failure)(mapped.code, mapped.message, mapped.appName);
758
838
  }
759
839
  registerEventListeners() {
760
840
  this.connector.on("device-connect", this.deviceConnectHandler);
@@ -975,14 +1055,14 @@ var LedgerDeviceManager = class {
975
1055
  if (this._discoverySub) {
976
1056
  return Promise.resolve();
977
1057
  }
978
- console.log("[DMK] requestDevice() starting persistent BLE scan");
1058
+ debugLog("[DMK] requestDevice() starting persistent BLE scan");
979
1059
  this._discoverySub = this._dmk.startDiscovering({}).subscribe({
980
1060
  next: (d) => {
981
- console.log("[DMK] BLE discovered:", d.name || d.id);
1061
+ debugLog("[DMK] BLE discovered:", d.name || d.id);
982
1062
  this._discovered.set(d.id, d);
983
1063
  },
984
1064
  error: (err) => {
985
- console.error("[DMK] BLE scan error:", err);
1065
+ debugError("[DMK] BLE scan error:", err);
986
1066
  this._discoverySub = null;
987
1067
  }
988
1068
  });
@@ -1033,12 +1113,23 @@ var LedgerDeviceManager = class {
1033
1113
  }
1034
1114
  };
1035
1115
 
1116
+ // src/signer/SignerManager.ts
1117
+ var import_device_signer_kit_ethereum = require("@ledgerhq/device-signer-kit-ethereum");
1118
+ var import_context_module = require("@ledgerhq/context-module");
1119
+
1036
1120
  // src/signer/deviceActionToPromise.ts
1037
1121
  var import_device_management_kit = require("@ledgerhq/device-management-kit");
1038
1122
  var DEFAULT_TIMEOUT_MS = 3e4;
1123
+ var DEBUG_DMK_OBSERVABLE = false;
1124
+ function debugLog2(...args) {
1125
+ if (DEBUG_DMK_OBSERVABLE) {
1126
+ console.debug(...args);
1127
+ }
1128
+ }
1039
1129
  function deviceActionToPromise(action, onInteraction, timeoutMs = DEFAULT_TIMEOUT_MS) {
1040
1130
  return new Promise((resolve, reject) => {
1041
1131
  let settled = false;
1132
+ let lastStep;
1042
1133
  let sub;
1043
1134
  let timer = null;
1044
1135
  const resetTimer = () => {
@@ -1054,12 +1145,13 @@ function deviceActionToPromise(action, onInteraction, timeoutMs = DEFAULT_TIMEOU
1054
1145
  }
1055
1146
  };
1056
1147
  resetTimer();
1057
- console.log("[DMK-Observable] subscribing to action.observable...");
1148
+ debugLog2("[DMK-Observable] subscribing to action.observable...");
1058
1149
  sub = action.observable.subscribe({
1059
1150
  next: (state) => {
1060
- console.log("[DMK-Observable] next received");
1061
1151
  resetTimer();
1062
- console.log(
1152
+ const step = state?.intermediateValue?.step;
1153
+ if (step) lastStep = step;
1154
+ debugLog2(
1063
1155
  "[DMK-Observable] state:",
1064
1156
  JSON.stringify({
1065
1157
  status: state.status,
@@ -1080,7 +1172,7 @@ function deviceActionToPromise(action, onInteraction, timeoutMs = DEFAULT_TIMEOU
1080
1172
  if (timer) clearTimeout(timer);
1081
1173
  onInteraction?.("interaction-complete");
1082
1174
  sub?.unsubscribe();
1083
- reject(state.error);
1175
+ rejectWithLastStep(state.error, lastStep, reject);
1084
1176
  } else if (state.status === import_device_management_kit.DeviceActionStatus.Pending && onInteraction) {
1085
1177
  const interaction = state.intermediateValue?.requiredUserInteraction;
1086
1178
  if (interaction && interaction !== "none") {
@@ -1093,7 +1185,7 @@ function deviceActionToPromise(action, onInteraction, timeoutMs = DEFAULT_TIMEOU
1093
1185
  settled = true;
1094
1186
  if (timer) clearTimeout(timer);
1095
1187
  sub?.unsubscribe();
1096
- reject(err);
1188
+ rejectWithLastStep(err, lastStep, reject);
1097
1189
  }
1098
1190
  },
1099
1191
  complete: () => {
@@ -1106,6 +1198,20 @@ function deviceActionToPromise(action, onInteraction, timeoutMs = DEFAULT_TIMEOU
1106
1198
  });
1107
1199
  });
1108
1200
  }
1201
+ function rejectWithLastStep(err, lastStep, reject) {
1202
+ if (err && typeof err === "object" && lastStep) {
1203
+ try {
1204
+ Object.defineProperty(err, "_lastStep", {
1205
+ value: lastStep,
1206
+ configurable: true,
1207
+ enumerable: false,
1208
+ writable: true
1209
+ });
1210
+ } catch {
1211
+ }
1212
+ }
1213
+ reject(err);
1214
+ }
1109
1215
 
1110
1216
  // src/signer/SignerEth.ts
1111
1217
  function hexToBytes(hex) {
@@ -1123,7 +1229,7 @@ var SignerEth = class {
1123
1229
  }
1124
1230
  async getAddress(derivationPath, options) {
1125
1231
  const checkOnDevice = options?.checkOnDevice ?? false;
1126
- console.log("[DMK] getAddress \u2192 DMK:", { derivationPath, checkOnDevice });
1232
+ debugLog("[DMK] getAddress \u2192 DMK:", { derivationPath, checkOnDevice });
1127
1233
  const action = this._sdk.getAddress(derivationPath, {
1128
1234
  checkOnDevice
1129
1235
  });
@@ -1166,10 +1272,10 @@ var SignerManager = class _SignerManager {
1166
1272
  async getOrCreate(sessionId) {
1167
1273
  const hadCached = this._cache.has(sessionId);
1168
1274
  this._cache.delete(sessionId);
1169
- console.log("[DMK] SignerManager.getOrCreate:", { sessionId, hadCached, creating: true });
1275
+ debugLog("[DMK] SignerManager.getOrCreate:", { sessionId, hadCached, creating: true });
1170
1276
  const builder = await this._builderFn({ dmk: this._dmk, sessionId });
1171
1277
  const sdkSigner = builder.build();
1172
- console.log("[DMK] SignerManager: new signer built");
1278
+ debugLog("[DMK] SignerManager: new signer built");
1173
1279
  const signer = new SignerEth(sdkSigner);
1174
1280
  this._cache.set(sessionId, signer);
1175
1281
  return signer;
@@ -1181,13 +1287,9 @@ var SignerManager = class _SignerManager {
1181
1287
  this._cache.clear();
1182
1288
  }
1183
1289
  static _defaultBuilder() {
1184
- let BuilderClass = null;
1185
- return async (args) => {
1186
- if (!BuilderClass) {
1187
- const mod = await import("@ledgerhq/device-signer-kit-ethereum");
1188
- BuilderClass = mod.SignerEthBuilder;
1189
- }
1190
- return new BuilderClass(args);
1290
+ return (args) => {
1291
+ const contextModule = new import_context_module.ContextModuleBuilder({}).removeDefaultLoaders().build();
1292
+ return new import_device_signer_kit_ethereum.SignerEthBuilder(args).withContextModule(contextModule);
1191
1293
  };
1192
1294
  }
1193
1295
  };
@@ -1205,7 +1307,7 @@ async function evmGetAddress(ctx, sessionId, params) {
1205
1307
  const signer = await _getEthSigner(ctx, sessionId);
1206
1308
  const path = normalizePath(params.path);
1207
1309
  const checkOnDevice = params.showOnDevice ?? false;
1208
- console.log("[DMK] evmGetAddress -> signer.getAddress:", { path, checkOnDevice });
1310
+ debugLog("[DMK] evmGetAddress -> signer.getAddress:", { path, checkOnDevice });
1209
1311
  try {
1210
1312
  const result = await signer.getAddress(path, { checkOnDevice });
1211
1313
  return { address: result.address, publicKey: result.publicKey };
@@ -1486,6 +1588,33 @@ async function btcSignTransaction(ctx, sessionId, params) {
1486
1588
  throw ctx.wrapError(err);
1487
1589
  }
1488
1590
  }
1591
+ async function btcSignPsbt(ctx, sessionId, params) {
1592
+ if (!params.psbt) {
1593
+ throw Object.assign(
1594
+ new Error("btcSignPsbt requires params.psbt"),
1595
+ { code: import_hwk_adapter_core4.HardwareErrorCode.InvalidParams }
1596
+ );
1597
+ }
1598
+ const btcSigner = await _createBtcSigner(ctx, sessionId);
1599
+ try {
1600
+ const { DefaultWallet, DefaultDescriptorTemplate } = await ctx.importLedgerKit(
1601
+ "@ledgerhq/device-signer-kit-bitcoin"
1602
+ );
1603
+ const path = normalizePath(params.path || "84'/0'/0'");
1604
+ const purpose = path.split("/")[0]?.replace("'", "");
1605
+ let template = DefaultDescriptorTemplate.NATIVE_SEGWIT;
1606
+ if (purpose === "44") template = DefaultDescriptorTemplate.LEGACY;
1607
+ else if (purpose === "49") template = DefaultDescriptorTemplate.NESTED_SEGWIT;
1608
+ else if (purpose === "86") template = DefaultDescriptorTemplate.TAPROOT;
1609
+ const wallet = new DefaultWallet(path, template);
1610
+ const signatures = await btcSigner.signPsbt(wallet, params.psbt);
1611
+ const signedPsbtHex = _applySignaturesToPsbt(params.psbt, signatures);
1612
+ return { signedPsbt: signedPsbtHex };
1613
+ } catch (err) {
1614
+ ctx.invalidateSession(sessionId);
1615
+ throw ctx.wrapError(err);
1616
+ }
1617
+ }
1489
1618
  async function btcSignMessage(ctx, sessionId, params) {
1490
1619
  const btcSigner = await _createBtcSigner(ctx, sessionId);
1491
1620
  const path = normalizePath(params.path);
@@ -1526,6 +1655,52 @@ async function _createBtcSigner(ctx, sessionId) {
1526
1655
  };
1527
1656
  return signer;
1528
1657
  }
1658
+ function _applySignaturesToPsbt(psbtHex, signatures) {
1659
+ const raw = (0, import_hwk_adapter_core4.hexToBytes)(psbtHex);
1660
+ const result = [];
1661
+ let pos = 0;
1662
+ for (let i = 0; i < 5; i++) result.push(raw[pos++]);
1663
+ while (pos < raw.length && raw[pos] !== 0) {
1664
+ const { bytes: kv, end } = readKeyValue(raw, pos);
1665
+ kv.forEach((b) => result.push(b));
1666
+ pos = end;
1667
+ }
1668
+ result.push(raw[pos++]);
1669
+ const sigsByInput = /* @__PURE__ */ new Map();
1670
+ for (const sig of signatures) {
1671
+ if (!sigsByInput.has(sig.inputIndex)) sigsByInput.set(sig.inputIndex, []);
1672
+ sigsByInput.get(sig.inputIndex).push(sig);
1673
+ }
1674
+ for (let inputIdx = 0; pos < raw.length; inputIdx++) {
1675
+ while (pos < raw.length && raw[pos] !== 0) {
1676
+ const { bytes: kv, end } = readKeyValue(raw, pos);
1677
+ kv.forEach((b) => result.push(b));
1678
+ pos = end;
1679
+ }
1680
+ const inputSigs = sigsByInput.get(inputIdx) || [];
1681
+ for (const sig of inputSigs) {
1682
+ if (sig.tapleafHash && sig.tapleafHash.length > 0) {
1683
+ const key = new Uint8Array(1 + 32 + 32);
1684
+ key[0] = 20;
1685
+ key.set(sig.pubkey.subarray(0, 32), 1);
1686
+ key.set(sig.tapleafHash, 33);
1687
+ writeKv(result, key, new Uint8Array(sig.signature));
1688
+ } else if (sig.pubkey.length === 32) {
1689
+ writeKv(result, new Uint8Array([19]), new Uint8Array(sig.signature));
1690
+ } else {
1691
+ const key = new Uint8Array(1 + sig.pubkey.length);
1692
+ key[0] = 2;
1693
+ key.set(sig.pubkey, 1);
1694
+ writeKv(result, key, new Uint8Array(sig.signature));
1695
+ }
1696
+ }
1697
+ result.push(raw[pos++]);
1698
+ }
1699
+ while (pos < raw.length) {
1700
+ result.push(raw[pos++]);
1701
+ }
1702
+ return (0, import_hwk_adapter_core4.bytesToHex)(new Uint8Array(result));
1703
+ }
1529
1704
  async function _enrichTaprootPsbt(btcSigner, psbtHex, inputDerivations) {
1530
1705
  const masterFp = await btcSigner.getMasterFingerprint({ skipOpenApp: true });
1531
1706
  const fpBytes = masterFp.length === 4 ? masterFp : new Uint8Array([0, 0, 0, 0]);
@@ -1589,6 +1764,8 @@ async function _enrichTaprootPsbt(btcSigner, psbtHex, inputDerivations) {
1589
1764
 
1590
1765
  // src/connector/chains/sol.ts
1591
1766
  var import_hwk_adapter_core5 = require("@onekeyfe/hwk-adapter-core");
1767
+ var import_device_signer_kit_solana = require("@ledgerhq/device-signer-kit-solana");
1768
+ var import_context_module2 = require("@ledgerhq/context-module");
1592
1769
 
1593
1770
  // src/signer/SignerSol.ts
1594
1771
  var SignerSol = class {
@@ -1661,8 +1838,8 @@ async function solSignMessage(ctx, sessionId, params) {
1661
1838
  }
1662
1839
  async function _createSolSigner(ctx, sessionId) {
1663
1840
  const dmk = await ctx.getOrCreateDmk();
1664
- const { SignerSolanaBuilder } = await ctx.importLedgerKit("@ledgerhq/device-signer-kit-solana");
1665
- const sdkSigner = new SignerSolanaBuilder({ dmk, sessionId }).build();
1841
+ const contextModule = new import_context_module2.ContextModuleBuilder({}).removeDefaultLoaders().build();
1842
+ const sdkSigner = new import_device_signer_kit_solana.SignerSolanaBuilder({ dmk, sessionId }).withContextModule(contextModule).build();
1666
1843
  const signer = new SignerSol(sdkSigner);
1667
1844
  signer.onInteraction = (interaction) => {
1668
1845
  ctx.emit("ui-event", {
@@ -1755,8 +1932,8 @@ var AppManager = class {
1755
1932
  if (!(0, import_device_management_kit2.isSuccessCommandResult)(result)) {
1756
1933
  const statusCode = result.statusCode;
1757
1934
  throw Object.assign(
1758
- new Error(`Failed to open "${appName}": app may not be installed`),
1759
- { _tag: "OpenAppCommandError", errorCode: String(statusCode ?? ""), statusCode }
1935
+ new Error(`Failed to open "${appName}"`),
1936
+ { _tag: "OpenAppCommandError", errorCode: String(statusCode ?? ""), statusCode, appName }
1760
1937
  );
1761
1938
  }
1762
1939
  }
@@ -2118,7 +2295,7 @@ var LedgerConnectorBase = class {
2118
2295
  // IConnector -- Method dispatch
2119
2296
  // ---------------------------------------------------------------------------
2120
2297
  async call(sessionId, method, params) {
2121
- console.log("[DMK] call:", method, JSON.stringify(params));
2298
+ debugLog("[DMK] call:", method, JSON.stringify(params));
2122
2299
  switch (method) {
2123
2300
  // EVM
2124
2301
  case "evmGetAddress":
@@ -2136,6 +2313,8 @@ var LedgerConnectorBase = class {
2136
2313
  return btcGetPublicKey(this._ctx, sessionId, params);
2137
2314
  case "btcSignTransaction":
2138
2315
  return btcSignTransaction(this._ctx, sessionId, params);
2316
+ case "btcSignPsbt":
2317
+ return btcSignPsbt(this._ctx, sessionId, params);
2139
2318
  case "btcSignMessage":
2140
2319
  return btcSignMessage(this._ctx, sessionId, params);
2141
2320
  case "btcGetMasterFingerprint":
@@ -2316,7 +2495,15 @@ var LedgerConnectorBase = class {
2316
2495
  _wrapError(err) {
2317
2496
  const mapped = mapLedgerError(err);
2318
2497
  const error = new Error(mapped.message);
2319
- Object.assign(error, { code: mapped.code });
2498
+ const src = err && typeof err === "object" ? err : {};
2499
+ Object.assign(error, {
2500
+ code: mapped.code,
2501
+ appName: mapped.appName,
2502
+ _tag: src._tag,
2503
+ errorCode: src.errorCode,
2504
+ _lastStep: src._lastStep,
2505
+ originalError: err
2506
+ });
2320
2507
  return error;
2321
2508
  }
2322
2509
  };