@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 +11 -2
- package/dist/index.d.ts +11 -2
- package/dist/index.js +231 -44
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +231 -44
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
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
|
-
|
|
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
|
-
|
|
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
|
|
297
|
-
|
|
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
|
|
313
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1058
|
+
debugLog("[DMK] requestDevice() starting persistent BLE scan");
|
|
979
1059
|
this._discoverySub = this._dmk.startDiscovering({}).subscribe({
|
|
980
1060
|
next: (d) => {
|
|
981
|
-
|
|
1061
|
+
debugLog("[DMK] BLE discovered:", d.name || d.id);
|
|
982
1062
|
this._discovered.set(d.id, d);
|
|
983
1063
|
},
|
|
984
1064
|
error: (err) => {
|
|
985
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
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
|
-
|
|
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
|
|
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}"
|
|
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
|
-
|
|
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
|
-
|
|
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
|
};
|