@onekeyfe/hwk-ledger-adapter 1.1.26-alpha.5 → 1.1.26-alpha.7

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, UiResponseEvent, DeviceInfo, Response, ChainCapability, EvmGetAddressParams, EvmAddress, ProgressCallback, EvmSignTxParams, EvmSignedTx, EvmSignMsgParams, EvmSignature, EvmSignTypedDataParams, BtcGetAddressParams, BtcAddress, BtcGetPublicKeyParams, BtcPublicKey, BtcSignTxParams, BtcSignedTx, BtcSignPsbtParams, BtcSignedPsbt, BtcSignMsgParams, BtcSignature, SolGetAddressParams, SolAddress, SolSignTxParams, SolSignedTx, SolSignMsgParams, SolSignature, TronGetAddressParams, TronAddress, TronSignTxParams, TronSignedTx, TronSignMsgParams, TronSignature, HardwareEventMap, DeviceEventListener, ChainForFingerprint, ConnectionType, DeviceDescriptor, ConnectorDevice, ConnectorSession, ConnectorEventType, ConnectorEventMap, DeviceChangeEvent, Failure, HardwareErrorCode } from '@onekeyfe/hwk-adapter-core';
1
+ import { IHardwareWallet, IConnector, TransportType, UiResponseEvent, DeviceInfo, Response, ChainCapability, EvmGetAddressParams, EvmAddress, ProgressCallback, EvmSignTxParams, EvmSignedTx, EvmSignMsgParams, EvmSignature, EvmSignTypedDataParams, BtcGetAddressParams, BtcAddress, BtcGetPublicKeyParams, BtcPublicKey, BtcSignTxParams, BtcSignedTx, BtcSignPsbtParams, BtcSignedPsbt, BtcSignMsgParams, BtcSignature, SolGetAddressParams, SolAddress, SolSignTxParams, SolSignedTx, SolSignMsgParams, SolSignature, TronGetAddressParams, TronAddress, TronSignTxParams, TronSignedTx, TronSignMsgParams, TronSignature, HardwareEventMap, DeviceEventListener, ChainForFingerprint, ConnectionType, DeviceDescriptor, ConnectorDevice, ConnectorSession, ConnectorEventType, ConnectorEventMap, DeviceChangeEvent, Failure, 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';
@@ -21,13 +21,12 @@ interface LedgerAdapterOptions {
21
21
  * - Translates IHardwareWallet method calls to connector.call() invocations
22
22
  * - Maps connector results/errors to our Response<T> format with enriched error messages
23
23
  * - Translates connector events to HardwareEventMap events
24
- * - Integrates with IUiHandler for permission flows
24
+ * - Emits `REQUEST_DEVICE_PERMISSION` for OS-level permission checks
25
25
  */
26
26
  declare class LedgerAdapter implements IHardwareWallet {
27
27
  readonly vendor: "ledger";
28
28
  private readonly connector;
29
29
  private readonly emitter;
30
- private _uiHandler;
31
30
  private readonly _handleSelectDevice;
32
31
  private _discoveredDevices;
33
32
  private _sessions;
@@ -44,7 +43,6 @@ declare class LedgerAdapter implements IHardwareWallet {
44
43
  get activeTransport(): TransportType | null;
45
44
  getAvailableTransports(): TransportType[];
46
45
  switchTransport(_type: TransportType): Promise<void>;
47
- setUiHandler(handler: Partial<IUiHandler>): void;
48
46
  init(_config?: unknown): Promise<void>;
49
47
  /**
50
48
  * Clear cached device/session state without tearing down the adapter.
@@ -149,10 +147,16 @@ declare class LedgerAdapter implements IHardwareWallet {
149
147
  /** Clear stale session, reconnect, and retry the call. */
150
148
  private _retryWithFreshConnection;
151
149
  /**
152
- * Ensure device permission before proceeding.
153
- * - No connectId (searchDevices): check environment-level permission
154
- * - With connectId (business methods): check device-level permission
155
- * If not granted, calls onDevicePermission so the consumer can request access.
150
+ * Ensure OS-level device permission (Bluetooth / USB) before proceeding.
151
+ *
152
+ * Emits `REQUEST_DEVICE_PERMISSION` and awaits the consumer's
153
+ * `RECEIVE_DEVICE_PERMISSION` reply (60s budget covers "probe system
154
+ * prompt → user tap" plus a generous margin). If the consumer never wires
155
+ * a handler or never replies, the wait times out and the operation fails
156
+ * fast so scanners/callers don't hang silently.
157
+ *
158
+ * - No connectId (searchDevices): environment-level permission
159
+ * - With connectId (business methods): device-level permission
156
160
  */
157
161
  private _ensureDevicePermission;
158
162
  /**
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { IHardwareWallet, IConnector, TransportType, IUiHandler, UiResponseEvent, DeviceInfo, Response, ChainCapability, EvmGetAddressParams, EvmAddress, ProgressCallback, EvmSignTxParams, EvmSignedTx, EvmSignMsgParams, EvmSignature, EvmSignTypedDataParams, BtcGetAddressParams, BtcAddress, BtcGetPublicKeyParams, BtcPublicKey, BtcSignTxParams, BtcSignedTx, BtcSignPsbtParams, BtcSignedPsbt, BtcSignMsgParams, BtcSignature, SolGetAddressParams, SolAddress, SolSignTxParams, SolSignedTx, SolSignMsgParams, SolSignature, TronGetAddressParams, TronAddress, TronSignTxParams, TronSignedTx, TronSignMsgParams, TronSignature, HardwareEventMap, DeviceEventListener, ChainForFingerprint, ConnectionType, DeviceDescriptor, ConnectorDevice, ConnectorSession, ConnectorEventType, ConnectorEventMap, DeviceChangeEvent, Failure, HardwareErrorCode } from '@onekeyfe/hwk-adapter-core';
1
+ import { IHardwareWallet, IConnector, TransportType, UiResponseEvent, DeviceInfo, Response, ChainCapability, EvmGetAddressParams, EvmAddress, ProgressCallback, EvmSignTxParams, EvmSignedTx, EvmSignMsgParams, EvmSignature, EvmSignTypedDataParams, BtcGetAddressParams, BtcAddress, BtcGetPublicKeyParams, BtcPublicKey, BtcSignTxParams, BtcSignedTx, BtcSignPsbtParams, BtcSignedPsbt, BtcSignMsgParams, BtcSignature, SolGetAddressParams, SolAddress, SolSignTxParams, SolSignedTx, SolSignMsgParams, SolSignature, TronGetAddressParams, TronAddress, TronSignTxParams, TronSignedTx, TronSignMsgParams, TronSignature, HardwareEventMap, DeviceEventListener, ChainForFingerprint, ConnectionType, DeviceDescriptor, ConnectorDevice, ConnectorSession, ConnectorEventType, ConnectorEventMap, DeviceChangeEvent, Failure, 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';
@@ -21,13 +21,12 @@ interface LedgerAdapterOptions {
21
21
  * - Translates IHardwareWallet method calls to connector.call() invocations
22
22
  * - Maps connector results/errors to our Response<T> format with enriched error messages
23
23
  * - Translates connector events to HardwareEventMap events
24
- * - Integrates with IUiHandler for permission flows
24
+ * - Emits `REQUEST_DEVICE_PERMISSION` for OS-level permission checks
25
25
  */
26
26
  declare class LedgerAdapter implements IHardwareWallet {
27
27
  readonly vendor: "ledger";
28
28
  private readonly connector;
29
29
  private readonly emitter;
30
- private _uiHandler;
31
30
  private readonly _handleSelectDevice;
32
31
  private _discoveredDevices;
33
32
  private _sessions;
@@ -44,7 +43,6 @@ declare class LedgerAdapter implements IHardwareWallet {
44
43
  get activeTransport(): TransportType | null;
45
44
  getAvailableTransports(): TransportType[];
46
45
  switchTransport(_type: TransportType): Promise<void>;
47
- setUiHandler(handler: Partial<IUiHandler>): void;
48
46
  init(_config?: unknown): Promise<void>;
49
47
  /**
50
48
  * Clear cached device/session state without tearing down the adapter.
@@ -149,10 +147,16 @@ declare class LedgerAdapter implements IHardwareWallet {
149
147
  /** Clear stale session, reconnect, and retry the call. */
150
148
  private _retryWithFreshConnection;
151
149
  /**
152
- * Ensure device permission before proceeding.
153
- * - No connectId (searchDevices): check environment-level permission
154
- * - With connectId (business methods): check device-level permission
155
- * If not granted, calls onDevicePermission so the consumer can request access.
150
+ * Ensure OS-level device permission (Bluetooth / USB) before proceeding.
151
+ *
152
+ * Emits `REQUEST_DEVICE_PERMISSION` and awaits the consumer's
153
+ * `RECEIVE_DEVICE_PERMISSION` reply (60s budget covers "probe system
154
+ * prompt → user tap" plus a generous margin). If the consumer never wires
155
+ * a handler or never replies, the wait times out and the operation fails
156
+ * fast so scanners/callers don't hang silently.
157
+ *
158
+ * - No connectId (searchDevices): environment-level permission
159
+ * - With connectId (business methods): device-level permission
156
160
  */
157
161
  private _ensureDevicePermission;
158
162
  /**
package/dist/index.js CHANGED
@@ -76,6 +76,58 @@ function getEthAppErrorCode(err) {
76
76
  }
77
77
  return null;
78
78
  }
79
+ function extractApduHex(err) {
80
+ if (!err || typeof err !== "object") return null;
81
+ const e = err;
82
+ if (typeof e.errorCode === "string" && /^[0-9a-f]+$/i.test(e.errorCode)) {
83
+ return e.errorCode.toLowerCase();
84
+ }
85
+ if (typeof e.statusCode === "number" && Number.isFinite(e.statusCode)) {
86
+ return e.statusCode.toString(16).padStart(4, "0");
87
+ }
88
+ if (typeof e.statusCode === "string" && /^[0-9a-f]+$/i.test(e.statusCode)) {
89
+ return e.statusCode.toLowerCase();
90
+ }
91
+ if (e.originalError != null) {
92
+ const nested = extractApduHex(e.originalError);
93
+ if (nested) return nested;
94
+ }
95
+ if (e.error != null && typeof e._tag === "string") {
96
+ const nested = extractApduHex(e.error);
97
+ if (nested) return nested;
98
+ }
99
+ return null;
100
+ }
101
+ function mapSolanaAppError(hex) {
102
+ switch (hex) {
103
+ case "6808":
104
+ return import_hwk_adapter_core.HardwareErrorCode.SolanaBlindSigningRequired;
105
+ default:
106
+ return null;
107
+ }
108
+ }
109
+ function mapTronAppError(hex) {
110
+ switch (hex) {
111
+ case "6a8d":
112
+ return import_hwk_adapter_core.HardwareErrorCode.TronCustomContractRequired;
113
+ case "6a8b":
114
+ return import_hwk_adapter_core.HardwareErrorCode.TronDataSigningRequired;
115
+ case "6a8c":
116
+ return import_hwk_adapter_core.HardwareErrorCode.TronSignByHashRequired;
117
+ default:
118
+ return null;
119
+ }
120
+ }
121
+ function mapBtcAppError(hex) {
122
+ switch (hex) {
123
+ case "b008":
124
+ return import_hwk_adapter_core.HardwareErrorCode.BtcWalletPolicyHmacMismatch;
125
+ case "b007":
126
+ return import_hwk_adapter_core.HardwareErrorCode.BtcUnexpectedState;
127
+ default:
128
+ return null;
129
+ }
130
+ }
79
131
  function mapEthAppError(ethCode, lastStep) {
80
132
  switch (ethCode) {
81
133
  case "6a80":
@@ -191,8 +243,10 @@ function mapLedgerError(err) {
191
243
  } else {
192
244
  const ethCode = getEthAppErrorCode(err);
193
245
  const lastStep = err && typeof err === "object" ? err._lastStep : void 0;
194
- const mapped = ethCode ? mapEthAppError(ethCode, lastStep) : null;
195
- code = mapped ?? import_hwk_adapter_core.HardwareErrorCode.UnknownError;
246
+ const ethMapped = ethCode ? mapEthAppError(ethCode, lastStep) : null;
247
+ const apduHex = ethMapped ? null : extractApduHex(err);
248
+ const chainMapped = apduHex ? mapSolanaAppError(apduHex) ?? mapTronAppError(apduHex) ?? mapBtcAppError(apduHex) : null;
249
+ code = ethMapped ?? chainMapped ?? import_hwk_adapter_core.HardwareErrorCode.UnknownError;
196
250
  }
197
251
  const appName = err && typeof err === "object" ? err.appName : void 0;
198
252
  return { code, message: (0, import_hwk_adapter_core.enrichErrorMessage)(code, originalMessage), appName };
@@ -225,7 +279,6 @@ var _LedgerAdapter = class _LedgerAdapter {
225
279
  constructor(connector, options) {
226
280
  this.vendor = "ledger";
227
281
  this.emitter = new import_hwk_adapter_core2.TypedEventEmitter();
228
- this._uiHandler = null;
229
282
  // Device cache: tracks discovered devices from connector events
230
283
  this._discoveredDevices = /* @__PURE__ */ new Map();
231
284
  // Session tracking: maps connectId -> sessionId
@@ -291,12 +344,6 @@ var _LedgerAdapter = class _LedgerAdapter {
291
344
  async switchTransport(_type) {
292
345
  }
293
346
  // ---------------------------------------------------------------------------
294
- // UI handler
295
- // ---------------------------------------------------------------------------
296
- setUiHandler(handler) {
297
- this._uiHandler = handler;
298
- }
299
- // ---------------------------------------------------------------------------
300
347
  // Lifecycle
301
348
  // ---------------------------------------------------------------------------
302
349
  async init(_config) {
@@ -318,7 +365,6 @@ var _LedgerAdapter = class _LedgerAdapter {
318
365
  this._jobQueue.clear();
319
366
  this.unregisterEventListeners();
320
367
  this.connector.reset();
321
- this._uiHandler = null;
322
368
  this._discoveredDevices.clear();
323
369
  this._sessions.clear();
324
370
  this.emitter.removeAllListeners();
@@ -864,33 +910,32 @@ var _LedgerAdapter = class _LedgerAdapter {
864
910
  return _LedgerAdapter._abortable(signal, this.connector.call(retrySessionId, method, params));
865
911
  }
866
912
  /**
867
- * Ensure device permission before proceeding.
868
- * - No connectId (searchDevices): check environment-level permission
869
- * - With connectId (business methods): check device-level permission
870
- * If not granted, calls onDevicePermission so the consumer can request access.
913
+ * Ensure OS-level device permission (Bluetooth / USB) before proceeding.
914
+ *
915
+ * Emits `REQUEST_DEVICE_PERMISSION` and awaits the consumer's
916
+ * `RECEIVE_DEVICE_PERMISSION` reply (60s budget covers "probe system
917
+ * prompt → user tap" plus a generous margin). If the consumer never wires
918
+ * a handler or never replies, the wait times out and the operation fails
919
+ * fast so scanners/callers don't hang silently.
920
+ *
921
+ * - No connectId (searchDevices): environment-level permission
922
+ * - With connectId (business methods): device-level permission
871
923
  */
872
924
  async _ensureDevicePermission(connectId, deviceId) {
873
- const transportType = "hid";
874
- let granted = false;
875
- let context;
876
- if (this._uiHandler?.checkDevicePermission) {
877
- try {
878
- const result = await this._uiHandler.checkDevicePermission({
879
- transportType,
880
- connectId,
881
- deviceId
882
- });
883
- granted = result.granted;
884
- context = result.context;
885
- } catch {
886
- granted = false;
887
- }
888
- }
925
+ const transportType = this.activeTransport ?? "hid";
926
+ const waitPromise = this._uiRegistry.wait(
927
+ import_hwk_adapter_core2.UI_REQUEST.REQUEST_DEVICE_PERMISSION,
928
+ { timeoutMs: 6e4 }
929
+ );
930
+ this.emitter.emit(import_hwk_adapter_core2.UI_REQUEST.REQUEST_DEVICE_PERMISSION, {
931
+ type: import_hwk_adapter_core2.UI_REQUEST.REQUEST_DEVICE_PERMISSION,
932
+ payload: { transportType, connectId, deviceId }
933
+ });
934
+ const { granted } = await waitPromise;
889
935
  if (!granted) {
890
- try {
891
- await this._uiHandler?.onDevicePermission?.({ transportType, context });
892
- } catch {
893
- }
936
+ throw Object.assign(new Error("Device permission denied"), {
937
+ code: import_hwk_adapter_core2.HardwareErrorCode.DevicePermissionDenied
938
+ });
894
939
  }
895
940
  }
896
941
  /**
@@ -2027,35 +2072,8 @@ var AppManager = class {
2027
2072
  };
2028
2073
 
2029
2074
  // src/connector/chains/legacyAppRetry.ts
2030
- var KNOWN_APP_CODES = {
2031
- Tron: /* @__PURE__ */ new Set([
2032
- 27013,
2033
- // user denied
2034
- 21781,
2035
- // device locked
2036
- 27274,
2037
- // invalid BIP32 path
2038
- 27275,
2039
- 27276,
2040
- 27277,
2041
- // app-specific data errors
2042
- 27264,
2043
- // invalid data
2044
- 27392,
2045
- // wrong parameter
2046
- 26368
2047
- // wrong length
2048
- ])
2049
- };
2050
- function isLegacyWrongAppError(err, appName) {
2051
- if (isWrongAppError(err)) return true;
2052
- const msg = err instanceof Error ? err.message : "";
2053
- const match = msg.match(/0x([0-9a-fA-F]{4})/);
2054
- if (!match) return false;
2055
- const sw = parseInt(match[1], 16);
2056
- const knownCodes = KNOWN_APP_CODES[appName];
2057
- if (knownCodes?.has(sw)) return false;
2058
- return true;
2075
+ function isLegacyWrongAppError(err, _appName) {
2076
+ return isWrongAppError(err);
2059
2077
  }
2060
2078
  async function withLegacyAppRetry(ctx, sessionId, appName, action) {
2061
2079
  try {
@@ -2122,6 +2140,7 @@ var DmkTransport = class extends import_hw_transport.default {
2122
2140
  // src/connector/chains/tron.ts
2123
2141
  async function tronGetAddress(ctx, sessionId, params) {
2124
2142
  const path = normalizePath(params.path);
2143
+ await _ensureTronAppOpen(ctx, sessionId);
2125
2144
  return withLegacyAppRetry(ctx, sessionId, "Tron", async (sid) => {
2126
2145
  const trx = await _createTrx(ctx, sid);
2127
2146
  if (params.showOnDevice) {
@@ -2146,6 +2165,7 @@ async function tronSignTransaction(ctx, sessionId, params) {
2146
2165
  );
2147
2166
  }
2148
2167
  const path = normalizePath(params.path);
2168
+ await _ensureTronAppOpen(ctx, sessionId);
2149
2169
  return withLegacyAppRetry(ctx, sessionId, "Tron", async (sid) => {
2150
2170
  const trx = await _createTrx(ctx, sid);
2151
2171
  ctx.emit("ui-event", {
@@ -2166,6 +2186,7 @@ async function tronSignTransaction(ctx, sessionId, params) {
2166
2186
  }
2167
2187
  async function tronSignMessage(ctx, sessionId, params) {
2168
2188
  const path = normalizePath(params.path);
2189
+ await _ensureTronAppOpen(ctx, sessionId);
2169
2190
  return withLegacyAppRetry(ctx, sessionId, "Tron", async (sid) => {
2170
2191
  const trx = await _createTrx(ctx, sid);
2171
2192
  ctx.emit("ui-event", {
@@ -2184,6 +2205,16 @@ async function _createTrx(ctx, sessionId) {
2184
2205
  const dmk = await ctx.getOrCreateDmk();
2185
2206
  return new import_hw_app_trx.default(new DmkTransport(dmk, sessionId));
2186
2207
  }
2208
+ async function _ensureTronAppOpen(ctx, sessionId) {
2209
+ const dmk = await ctx.getOrCreateDmk();
2210
+ const appManager = new AppManager(dmk);
2211
+ await appManager.ensureAppOpen(sessionId, "Tron", () => {
2212
+ ctx.emit("ui-event", {
2213
+ type: import_hwk_adapter_core10.EConnectorInteraction.ConfirmOpenApp,
2214
+ payload: { sessionId }
2215
+ });
2216
+ });
2217
+ }
2187
2218
 
2188
2219
  // src/connector/LedgerConnectorBase.ts
2189
2220
  async function defaultLedgerKitImporter(pkg) {