@onekeyfe/hwk-ledger-adapter 1.2.2-alpha.100 → 1.2.2-alpha.3

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,5 +1,5 @@
1
1
  import * as _onekeyfe_hwk_adapter_core from '@onekeyfe/hwk-adapter-core';
2
- import { IHardwareWallet, IConnector, TransportType, UiResponseEvent, SearchDevicesOptions, DeviceInfo, Response, ChainCapability, NullableCallArg, IHardwareCallParams, EvmGetAddressParams, EvmAddress, EvmSignTxLedgerParams, EvmSignedTx, EvmSignMsgParams, EvmSignature, EvmSignTypedDataParams, BtcGetAddressParams, BtcAddress, BtcGetPublicKeyParams, BtcPublicKey, BtcSignTxParams, BtcSignedTx, BtcSignPsbtParams, BtcSignedPsbt, BtcSignMsgParams, BtcSignature, IHardwareCommonCallParams, SolGetAddressParams, SolAddress, SolSignTxParams, SolSignedTx, SolSignMsgParams, SolSignature, TronGetAddressParams, TronAddress, TronSignTxParams, TronSignedTx, TronSignMsgParams, TronSignature, HardwareEventMap, DeviceEventListener, ChainForFingerprint, DeviceDescriptor, DeviceChangeEvent, ConnectionType, ConnectorDevice, ConnectorSession, ConnectorCallResult, ConnectorEventType, ConnectorEventMap, Failure, HardwareErrorCode } from '@onekeyfe/hwk-adapter-core';
2
+ import { IHardwareWallet, IConnector, TransportType, UiResponseEvent, SearchDevicesOptions, DeviceInfo, Response, ChainCapability, NullableCallArg, IHardwareCallParams, EvmGetAddressParams, EvmAddress, EvmSignTxLedgerParams, EvmSignedTx, EvmSignMsgParams, EvmSignature, EvmSignTypedDataParams, BtcGetAddressParams, BtcAddress, BtcGetPublicKeyParams, BtcPublicKey, BtcSignTxParams, BtcSignedTx, BtcSignPsbtParams, BtcSignedPsbt, BtcSignMsgParams, BtcSignature, IHardwareCommonCallParams, SolGetAddressParams, SolAddress, SolSignTxParams, SolSignedTx, SolSignMsgParams, SolSignature, TronGetAddressParams, TronAddress, TronSignTxParams, TronSignedTx, TronSignMsgParams, TronSignature, DeviceAuthenticityParams, DeviceAuthenticityResult, HardwareEventMap, DeviceEventListener, ChainForFingerprint, DeviceDescriptor, DeviceChangeEvent, ConnectionType, ConnectorDevice, ConnectorSession, ConnectorCallResult, ConnectorEventType, ConnectorEventMap, ConnectorConfig, Failure, HardwareErrorCode } from '@onekeyfe/hwk-adapter-core';
3
3
  import { DeviceActionState as DeviceActionState$1, DiscoveredDevice, ExecuteDeviceActionReturnType, DeviceManagementKit } from '@ledgerhq/device-management-kit';
4
4
  import { Address, Signature, SignerEth as SignerEth$1, TypedData } from '@ledgerhq/device-signer-kit-ethereum';
5
5
  import { ContextModule } from '@ledgerhq/context-module';
@@ -102,6 +102,7 @@ declare class LedgerAdapter implements IHardwareWallet {
102
102
  private readonly _uiRegistry;
103
103
  private _btcHighIndexConfirmedThisSession;
104
104
  private readonly _jobQueue;
105
+ private _deviceAuthenticityQueueTail;
105
106
  private _doConnectAbortController;
106
107
  private readonly _defaultAutoInstallApp;
107
108
  constructor(connector: IConnector, options?: {
@@ -162,6 +163,19 @@ declare class LedgerAdapter implements IHardwareWallet {
162
163
  listAvailableApps(connectId: string): Promise<Response<AppMetadata[]>>;
163
164
  getLedgerFirmwareVersion(connectId: string): Promise<Response<FirmwareVersion>>;
164
165
  getLedgerDeviceInfo(connectId: string): Promise<Response<LedgerDeviceInfo>>;
166
+ /**
167
+ * Runs Ledger's official genuine check (DMK GenuineCheckDeviceAction) over the
168
+ * SAME secure-channel backend as app install
169
+ * (wss://scriptrunner.api.live.ledger.com/update/genuine). It returns Ledger's
170
+ * HSM verdict (`verified`) and a stable per-device id = sha3-256 of the device
171
+ * attestation public key, which DMK reads inside that session. The id survives
172
+ * wipe/recovery and cannot be forged from a seed.
173
+ *
174
+ * Requires network access to Ledger's backend and an on-device
175
+ * "Allow secure connection" confirmation the first time.
176
+ */
177
+ verifyDeviceAuthenticity(connectId: string, params?: DeviceAuthenticityParams): Promise<Response<DeviceAuthenticityResult>>;
178
+ private _verifyDeviceAuthenticityExclusive;
165
179
  on<K extends keyof HardwareEventMap>(event: K, listener: (event: HardwareEventMap[K]) => void): void;
166
180
  on(event: string, listener: DeviceEventListener): void;
167
181
  off<K extends keyof HardwareEventMap>(event: K, listener: (event: HardwareEventMap[K]) => void): void;
@@ -410,6 +424,7 @@ declare class LedgerConnectorBase implements IConnector {
410
424
  private readonly _eventHandlers;
411
425
  private readonly _providedDmk;
412
426
  private readonly _createTransport;
427
+ private _ledgerGenuineCheckWebSocketUrl;
413
428
  readonly connectionType: ConnectionType;
414
429
  private readonly _cancellers;
415
430
  private readonly _sessionStateSubs;
@@ -471,6 +486,7 @@ declare class LedgerConnectorBase implements IConnector {
471
486
  on<K extends ConnectorEventType>(event: K, handler: (data: ConnectorEventMap[K]) => void): void;
472
487
  off<K extends ConnectorEventType>(event: K, handler: (data: ConnectorEventMap[K]) => void): void;
473
488
  reset(): void;
489
+ configure(config: ConnectorConfig): Promise<void>;
474
490
  /**
475
491
  * Lazily create or return the DMK instance.
476
492
  * If a DMK was provided via constructor, it is used directly.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as _onekeyfe_hwk_adapter_core from '@onekeyfe/hwk-adapter-core';
2
- import { IHardwareWallet, IConnector, TransportType, UiResponseEvent, SearchDevicesOptions, DeviceInfo, Response, ChainCapability, NullableCallArg, IHardwareCallParams, EvmGetAddressParams, EvmAddress, EvmSignTxLedgerParams, EvmSignedTx, EvmSignMsgParams, EvmSignature, EvmSignTypedDataParams, BtcGetAddressParams, BtcAddress, BtcGetPublicKeyParams, BtcPublicKey, BtcSignTxParams, BtcSignedTx, BtcSignPsbtParams, BtcSignedPsbt, BtcSignMsgParams, BtcSignature, IHardwareCommonCallParams, SolGetAddressParams, SolAddress, SolSignTxParams, SolSignedTx, SolSignMsgParams, SolSignature, TronGetAddressParams, TronAddress, TronSignTxParams, TronSignedTx, TronSignMsgParams, TronSignature, HardwareEventMap, DeviceEventListener, ChainForFingerprint, DeviceDescriptor, DeviceChangeEvent, ConnectionType, ConnectorDevice, ConnectorSession, ConnectorCallResult, ConnectorEventType, ConnectorEventMap, Failure, HardwareErrorCode } from '@onekeyfe/hwk-adapter-core';
2
+ import { IHardwareWallet, IConnector, TransportType, UiResponseEvent, SearchDevicesOptions, DeviceInfo, Response, ChainCapability, NullableCallArg, IHardwareCallParams, EvmGetAddressParams, EvmAddress, EvmSignTxLedgerParams, EvmSignedTx, EvmSignMsgParams, EvmSignature, EvmSignTypedDataParams, BtcGetAddressParams, BtcAddress, BtcGetPublicKeyParams, BtcPublicKey, BtcSignTxParams, BtcSignedTx, BtcSignPsbtParams, BtcSignedPsbt, BtcSignMsgParams, BtcSignature, IHardwareCommonCallParams, SolGetAddressParams, SolAddress, SolSignTxParams, SolSignedTx, SolSignMsgParams, SolSignature, TronGetAddressParams, TronAddress, TronSignTxParams, TronSignedTx, TronSignMsgParams, TronSignature, DeviceAuthenticityParams, DeviceAuthenticityResult, HardwareEventMap, DeviceEventListener, ChainForFingerprint, DeviceDescriptor, DeviceChangeEvent, ConnectionType, ConnectorDevice, ConnectorSession, ConnectorCallResult, ConnectorEventType, ConnectorEventMap, ConnectorConfig, Failure, HardwareErrorCode } from '@onekeyfe/hwk-adapter-core';
3
3
  import { DeviceActionState as DeviceActionState$1, DiscoveredDevice, ExecuteDeviceActionReturnType, DeviceManagementKit } from '@ledgerhq/device-management-kit';
4
4
  import { Address, Signature, SignerEth as SignerEth$1, TypedData } from '@ledgerhq/device-signer-kit-ethereum';
5
5
  import { ContextModule } from '@ledgerhq/context-module';
@@ -102,6 +102,7 @@ declare class LedgerAdapter implements IHardwareWallet {
102
102
  private readonly _uiRegistry;
103
103
  private _btcHighIndexConfirmedThisSession;
104
104
  private readonly _jobQueue;
105
+ private _deviceAuthenticityQueueTail;
105
106
  private _doConnectAbortController;
106
107
  private readonly _defaultAutoInstallApp;
107
108
  constructor(connector: IConnector, options?: {
@@ -162,6 +163,19 @@ declare class LedgerAdapter implements IHardwareWallet {
162
163
  listAvailableApps(connectId: string): Promise<Response<AppMetadata[]>>;
163
164
  getLedgerFirmwareVersion(connectId: string): Promise<Response<FirmwareVersion>>;
164
165
  getLedgerDeviceInfo(connectId: string): Promise<Response<LedgerDeviceInfo>>;
166
+ /**
167
+ * Runs Ledger's official genuine check (DMK GenuineCheckDeviceAction) over the
168
+ * SAME secure-channel backend as app install
169
+ * (wss://scriptrunner.api.live.ledger.com/update/genuine). It returns Ledger's
170
+ * HSM verdict (`verified`) and a stable per-device id = sha3-256 of the device
171
+ * attestation public key, which DMK reads inside that session. The id survives
172
+ * wipe/recovery and cannot be forged from a seed.
173
+ *
174
+ * Requires network access to Ledger's backend and an on-device
175
+ * "Allow secure connection" confirmation the first time.
176
+ */
177
+ verifyDeviceAuthenticity(connectId: string, params?: DeviceAuthenticityParams): Promise<Response<DeviceAuthenticityResult>>;
178
+ private _verifyDeviceAuthenticityExclusive;
165
179
  on<K extends keyof HardwareEventMap>(event: K, listener: (event: HardwareEventMap[K]) => void): void;
166
180
  on(event: string, listener: DeviceEventListener): void;
167
181
  off<K extends keyof HardwareEventMap>(event: K, listener: (event: HardwareEventMap[K]) => void): void;
@@ -410,6 +424,7 @@ declare class LedgerConnectorBase implements IConnector {
410
424
  private readonly _eventHandlers;
411
425
  private readonly _providedDmk;
412
426
  private readonly _createTransport;
427
+ private _ledgerGenuineCheckWebSocketUrl;
413
428
  readonly connectionType: ConnectionType;
414
429
  private readonly _cancellers;
415
430
  private readonly _sessionStateSubs;
@@ -471,6 +486,7 @@ declare class LedgerConnectorBase implements IConnector {
471
486
  on<K extends ConnectorEventType>(event: K, handler: (data: ConnectorEventMap[K]) => void): void;
472
487
  off<K extends ConnectorEventType>(event: K, handler: (data: ConnectorEventMap[K]) => void): void;
473
488
  reset(): void;
489
+ configure(config: ConnectorConfig): Promise<void>;
474
490
  /**
475
491
  * Lazily create or return the DMK instance.
476
492
  * If a DMK was provided via constructor, it is used directly.
package/dist/index.js CHANGED
@@ -772,6 +772,10 @@ var _LedgerAdapter = class _LedgerAdapter {
772
772
  // The Ledger device itself still requires a per-call confirmation — that's
773
773
  // the Ledger app's safety boundary, not ours to bypass.
774
774
  this._btcHighIndexConfirmedThisSession = false;
775
+ // Runtime relay configuration mutates connector-wide DMK state. Serialize
776
+ // the complete configure → genuine check → clear lifecycle so concurrent
777
+ // callers cannot reset or overwrite each other's one-shot relay.
778
+ this._deviceAuthenticityQueueTail = Promise.resolve();
775
779
  // Shared across concurrent callers — only `cancel()` aborts.
776
780
  this._doConnectAbortController = null;
777
781
  this._installProgressLastEmittedValue = -Infinity;
@@ -1322,6 +1326,75 @@ var _LedgerAdapter = class _LedgerAdapter {
1322
1326
  return this.errorToFailure(err);
1323
1327
  }
1324
1328
  }
1329
+ /**
1330
+ * Runs Ledger's official genuine check (DMK GenuineCheckDeviceAction) over the
1331
+ * SAME secure-channel backend as app install
1332
+ * (wss://scriptrunner.api.live.ledger.com/update/genuine). It returns Ledger's
1333
+ * HSM verdict (`verified`) and a stable per-device id = sha3-256 of the device
1334
+ * attestation public key, which DMK reads inside that session. The id survives
1335
+ * wipe/recovery and cannot be forged from a seed.
1336
+ *
1337
+ * Requires network access to Ledger's backend and an on-device
1338
+ * "Allow secure connection" confirmation the first time.
1339
+ */
1340
+ async verifyDeviceAuthenticity(connectId, params = {}) {
1341
+ const waitForPrevious = this._deviceAuthenticityQueueTail;
1342
+ let releaseQueue = () => void 0;
1343
+ this._deviceAuthenticityQueueTail = new Promise((resolve) => {
1344
+ releaseQueue = resolve;
1345
+ });
1346
+ await waitForPrevious;
1347
+ try {
1348
+ return await this._verifyDeviceAuthenticityExclusive(connectId, params);
1349
+ } finally {
1350
+ releaseQueue();
1351
+ }
1352
+ }
1353
+ async _verifyDeviceAuthenticityExclusive(connectId, params) {
1354
+ const relayUrl = params.ledgerGenuineCheckWebSocketUrl;
1355
+ try {
1356
+ if (relayUrl) {
1357
+ if (!this.connector.configure) {
1358
+ return (0, import_hwk_adapter_core3.failure)(
1359
+ import_hwk_adapter_core3.HardwareErrorCode.MethodNotSupported,
1360
+ "This Ledger connector does not support genuine-check relay configuration"
1361
+ );
1362
+ }
1363
+ await this.connector.configure({ ledgerGenuineCheckWebSocketUrl: relayUrl });
1364
+ this.resetState();
1365
+ }
1366
+ const result = await this.connectorCall(connectId, "getDeviceGenuineCheck", {});
1367
+ if (!result.isGenuine) {
1368
+ return (0, import_hwk_adapter_core3.success)({
1369
+ vendor: "ledger",
1370
+ verified: false
1371
+ });
1372
+ }
1373
+ if (!result.deviceId) {
1374
+ return (0, import_hwk_adapter_core3.failure)(
1375
+ import_hwk_adapter_core3.HardwareErrorCode.UnknownError,
1376
+ `Genuine check completed (isGenuine=${result.isGenuine}) but no deviceId was captured`
1377
+ );
1378
+ }
1379
+ return (0, import_hwk_adapter_core3.success)({
1380
+ vendor: "ledger",
1381
+ verified: result.isGenuine,
1382
+ deviceId: result.deviceId
1383
+ });
1384
+ } catch (err) {
1385
+ return this.errorToFailure(err);
1386
+ } finally {
1387
+ if (relayUrl) {
1388
+ try {
1389
+ await this.connector.configure?.({ ledgerGenuineCheckWebSocketUrl: void 0 });
1390
+ this.resetState();
1391
+ } catch {
1392
+ this.connector.reset();
1393
+ this.resetState();
1394
+ }
1395
+ }
1396
+ }
1397
+ }
1325
1398
  on(event, listener) {
1326
1399
  this.emitter.on(event, listener);
1327
1400
  }
@@ -4063,6 +4136,30 @@ var HARDWARE_ERROR_CODE_VALUES = new Set(
4063
4136
  Object.values(import_hwk_adapter_core13.HardwareErrorCode).filter((value) => typeof value === "number")
4064
4137
  );
4065
4138
  var BLE_CONNECT_SCAN_TIMEOUT_MS = 1500;
4139
+ var LEDGER_RELAY_ALLOWED_ROOT_DOMAINS = ["onekeytest.com", "onekey.com"];
4140
+ function isAllowedLedgerRelayHost(hostname) {
4141
+ return LEDGER_RELAY_ALLOWED_ROOT_DOMAINS.some(
4142
+ (root) => hostname === root || hostname.endsWith(`.${root}`)
4143
+ );
4144
+ }
4145
+ var LEDGER_RELAY_PATH_PREFIX = "/v1/ledger/session/";
4146
+ var LEDGER_RELAY_TOKEN_PATTERN = /^[A-Za-z0-9_-]{32,256}$/;
4147
+ var MAX_LEDGER_RELAY_URL_LENGTH = 2048;
4148
+ function assertAllowedLedgerRelayUrl(rawUrl) {
4149
+ if (!rawUrl || rawUrl.length > MAX_LEDGER_RELAY_URL_LENGTH) {
4150
+ throw new Error("Ledger genuine-check relay URL is invalid");
4151
+ }
4152
+ let parsed;
4153
+ try {
4154
+ parsed = new URL(rawUrl);
4155
+ } catch {
4156
+ throw new Error("Ledger genuine-check relay URL is invalid");
4157
+ }
4158
+ const token = parsed.pathname.startsWith(LEDGER_RELAY_PATH_PREFIX) ? parsed.pathname.slice(LEDGER_RELAY_PATH_PREFIX.length) : "";
4159
+ if (parsed.protocol !== "wss:" || !isAllowedLedgerRelayHost(parsed.hostname) || parsed.port !== "" || parsed.username !== "" || parsed.password !== "" || parsed.search !== "" || parsed.hash !== "" || !LEDGER_RELAY_TOKEN_PATTERN.test(token)) {
4160
+ throw new Error("Ledger genuine-check relay URL is not allowed");
4161
+ }
4162
+ }
4066
4163
  async function defaultLedgerKitImporter(pkg) {
4067
4164
  switch (pkg) {
4068
4165
  case "@ledgerhq/device-management-kit":
@@ -4584,6 +4681,41 @@ var LedgerConnectorBase = class {
4584
4681
  ctx.clearCanceller(sessionId);
4585
4682
  }
4586
4683
  }
4684
+ case "getDeviceGenuineCheck": {
4685
+ try {
4686
+ const dmk = await ctx.getOrCreateDmk();
4687
+ const kit = await ctx.importLedgerKit("@ledgerhq/device-management-kit");
4688
+ const action = dmk.executeDeviceAction({
4689
+ sessionId,
4690
+ deviceAction: new kit.GenuineCheckDeviceAction({ input: {} })
4691
+ });
4692
+ let deviceId;
4693
+ const output = await deviceActionToPromise(
4694
+ action,
4695
+ (interaction) => ctx.emit("ui-event", {
4696
+ type: collapseSignerInteraction(interaction),
4697
+ payload: { sessionId }
4698
+ }),
4699
+ // Generous timeout: covers websocket round-trips + the on-device
4700
+ // "Allow secure connection" tap (the idle watchdog does not pause
4701
+ // for it, only for unlock-device).
4702
+ 5 * 6e4,
4703
+ (cancel) => ctx.registerCanceller(sessionId, cancel),
4704
+ (intermediateValue) => {
4705
+ const iv = intermediateValue;
4706
+ if (iv?.deviceId instanceof Uint8Array && iv.deviceId.length === 32 && !deviceId) {
4707
+ deviceId = Buffer.from(iv.deviceId).toString("hex");
4708
+ }
4709
+ }
4710
+ );
4711
+ return { isGenuine: output.isGenuine, deviceId };
4712
+ } catch (err) {
4713
+ ctx.invalidateSession(sessionId);
4714
+ throw ctx.wrapError(err);
4715
+ } finally {
4716
+ ctx.clearCanceller(sessionId);
4717
+ }
4718
+ }
4587
4719
  default:
4588
4720
  throw new Error(`LedgerConnector: unknown method "${method}"`);
4589
4721
  }
@@ -4616,8 +4748,23 @@ var LedgerConnectorBase = class {
4616
4748
  // IConnector -- Reset
4617
4749
  // ---------------------------------------------------------------------------
4618
4750
  reset() {
4751
+ this._ledgerGenuineCheckWebSocketUrl = void 0;
4619
4752
  this._resetAll();
4620
4753
  }
4754
+ async configure(config) {
4755
+ const nextUrl = config.ledgerGenuineCheckWebSocketUrl;
4756
+ if (nextUrl) {
4757
+ assertAllowedLedgerRelayUrl(nextUrl);
4758
+ if (this._providedDmk) {
4759
+ throw new Error("Cannot change Ledger genuine-check relay on a pre-built DMK");
4760
+ }
4761
+ }
4762
+ if (nextUrl === this._ledgerGenuineCheckWebSocketUrl) {
4763
+ return;
4764
+ }
4765
+ this._resetAll();
4766
+ this._ledgerGenuineCheckWebSocketUrl = nextUrl;
4767
+ }
4621
4768
  // ---------------------------------------------------------------------------
4622
4769
  // Private -- DMK / Manager lifecycle
4623
4770
  // ---------------------------------------------------------------------------
@@ -4643,7 +4790,11 @@ var LedgerConnectorBase = class {
4643
4790
  );
4644
4791
  const transportFactory = await this._createTransport();
4645
4792
  debugLog("[DMK] _getOrCreateDmk: transportFactory type:", typeof transportFactory);
4646
- const dmk = new DeviceManagementKitBuilder().addTransport(transportFactory).build();
4793
+ const builder = new DeviceManagementKitBuilder().addTransport(transportFactory);
4794
+ if (this._ledgerGenuineCheckWebSocketUrl) {
4795
+ builder.addConfig({ webSocketUrl: this._ledgerGenuineCheckWebSocketUrl });
4796
+ }
4797
+ const dmk = builder.build();
4647
4798
  this._dmk = dmk;
4648
4799
  debugLog("[DMK] _getOrCreateDmk: DMK created");
4649
4800
  return dmk;