@onekeyfe/hwk-ledger-adapter 1.2.0-alpha.12 → 1.2.0-alpha.13
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 +28 -17
- package/dist/index.d.ts +28 -17
- package/dist/index.js +773 -286
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +699 -209
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -2,15 +2,17 @@
|
|
|
2
2
|
import {
|
|
3
3
|
CHAIN_FINGERPRINT_PATHS,
|
|
4
4
|
DEVICE,
|
|
5
|
+
DEVICE_CONNECT_RETRY_DELAY_MS,
|
|
5
6
|
DeviceJobQueue,
|
|
6
7
|
EConnectorInteraction,
|
|
7
|
-
HardwareErrorCode as
|
|
8
|
+
HardwareErrorCode as HardwareErrorCode3,
|
|
8
9
|
TypedEventEmitter,
|
|
9
10
|
UI_REQUEST,
|
|
10
11
|
UI_REQUEST_PREEMPTED_TAG,
|
|
11
12
|
UiRequestRegistry,
|
|
13
|
+
createHwkError,
|
|
12
14
|
deriveDeviceFingerprint,
|
|
13
|
-
failure,
|
|
15
|
+
failure as failure2,
|
|
14
16
|
rehydrateConnectorError,
|
|
15
17
|
success
|
|
16
18
|
} from "@onekeyfe/hwk-adapter-core";
|
|
@@ -35,30 +37,37 @@ var USER_REJECTED_CODES = /* @__PURE__ */ new Set(["6985", "27013"]);
|
|
|
35
37
|
var WRONG_APP_CODES = /* @__PURE__ */ new Set(["6e00", "28160", "6d00", "27904", "6a83", "27267"]);
|
|
36
38
|
var APP_NOT_INSTALLED_CODES = /* @__PURE__ */ new Set(["6807", "26631"]);
|
|
37
39
|
var STEP_BLIND_SIGN_TRANSACTION_FALLBACK = "signer.eth.steps.blindSignTransactionFallback";
|
|
40
|
+
var STEP_DETECT_BLIND_SIGNING = "signer.eth.steps.detectBlindSigning";
|
|
41
|
+
var BLIND_SIGNING_STEPS = /* @__PURE__ */ new Set([
|
|
42
|
+
STEP_BLIND_SIGN_TRANSACTION_FALLBACK,
|
|
43
|
+
STEP_DETECT_BLIND_SIGNING
|
|
44
|
+
]);
|
|
45
|
+
function normalizeApduHex(value) {
|
|
46
|
+
if (typeof value === "number" && Number.isInteger(value) && value >= 0 && value <= 65535) {
|
|
47
|
+
return value.toString(16).padStart(4, "0");
|
|
48
|
+
}
|
|
49
|
+
if (typeof value !== "string") return null;
|
|
50
|
+
const raw = value.toLowerCase().replace(/^0x/, "");
|
|
51
|
+
return /^[0-9a-f]{1,4}$/i.test(raw) ? raw.padStart(4, "0") : null;
|
|
52
|
+
}
|
|
38
53
|
function getEthAppErrorCode(err) {
|
|
39
54
|
if (!err || typeof err !== "object") return null;
|
|
40
55
|
const e = err;
|
|
41
|
-
if (e._tag === ERROR_TAG.EthAppCommand
|
|
42
|
-
|
|
56
|
+
if (e._tag === ERROR_TAG.EthAppCommand) {
|
|
57
|
+
const code = normalizeApduHex(e.errorCode) ?? normalizeApduHex(e.statusCode) ?? normalizeApduHex(e.code);
|
|
58
|
+
if (code) return code;
|
|
43
59
|
}
|
|
44
60
|
const orig = e.originalError;
|
|
45
|
-
if (orig?._tag === ERROR_TAG.EthAppCommand
|
|
46
|
-
return orig.errorCode.
|
|
61
|
+
if (orig?._tag === ERROR_TAG.EthAppCommand) {
|
|
62
|
+
return normalizeApduHex(orig.errorCode) ?? normalizeApduHex(orig.statusCode) ?? normalizeApduHex(orig.code);
|
|
47
63
|
}
|
|
48
64
|
return null;
|
|
49
65
|
}
|
|
50
66
|
function extractApduHex(err) {
|
|
51
67
|
if (!err || typeof err !== "object") return null;
|
|
52
68
|
const e = err;
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
if (typeof e.statusCode === "number" && Number.isFinite(e.statusCode)) {
|
|
57
|
-
return e.statusCode.toString(16).padStart(4, "0");
|
|
58
|
-
}
|
|
59
|
-
if (typeof e.statusCode === "string" && /^[0-9a-f]+$/i.test(e.statusCode)) {
|
|
60
|
-
return e.statusCode.toLowerCase();
|
|
61
|
-
}
|
|
69
|
+
const direct = normalizeApduHex(e.errorCode) ?? normalizeApduHex(e.statusCode);
|
|
70
|
+
if (direct) return direct;
|
|
62
71
|
if (e.originalError != null) {
|
|
63
72
|
const nested = extractApduHex(e.originalError);
|
|
64
73
|
if (nested) return nested;
|
|
@@ -117,10 +126,15 @@ function classifyEthAppError(err) {
|
|
|
117
126
|
const ethCode = getEthAppErrorCode(err);
|
|
118
127
|
if (!ethCode) return null;
|
|
119
128
|
if (ethCode === "6a80") {
|
|
120
|
-
return
|
|
129
|
+
return hasBlindSigningStep(err) ? HardwareErrorCode.EvmBlindSigningRequired : null;
|
|
121
130
|
}
|
|
122
131
|
return mapEthAppErrorCode(ethCode);
|
|
123
132
|
}
|
|
133
|
+
function classifyBlindSigningDetectionError(err) {
|
|
134
|
+
if (!hasBlindSigningStep(err)) return null;
|
|
135
|
+
if (hasInvalidArgumentCode(err)) return HardwareErrorCode.EvmBlindSigningRequired;
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
124
138
|
var ERROR_TAG = {
|
|
125
139
|
// SDK-mint
|
|
126
140
|
DeviceNotAdvertising: "DeviceNotAdvertisingError",
|
|
@@ -136,6 +150,10 @@ var ERROR_TAG = {
|
|
|
136
150
|
// chain app wedged (APDU 0x6901)
|
|
137
151
|
DeviceTransportStuck: "DeviceTransportStuck",
|
|
138
152
|
// DMK transport queue wedged
|
|
153
|
+
// installApp resolved success but the app is still missing on device —
|
|
154
|
+
// DMK quirk. Surfaced as a distinct tag so callers can tell it apart from
|
|
155
|
+
// the original DMK-thrown AppNotInstalled.
|
|
156
|
+
AppInstallVerifyFailed: "AppInstallVerifyFailedError",
|
|
139
157
|
// DMK-reuse (DMK throws same string; we synthesize too)
|
|
140
158
|
DeviceLocked: "DeviceLockedError",
|
|
141
159
|
DeviceNotRecognized: "DeviceNotRecognizedError",
|
|
@@ -161,7 +179,11 @@ var ERROR_TAG = {
|
|
|
161
179
|
// ble-plx surfaces this when GATT notification setup fails — typical
|
|
162
180
|
// outcome when the user doesn't confirm pairing on the device, or the
|
|
163
181
|
// existing bond is invalid. Observed in production after ~30s.
|
|
164
|
-
PairingRefused: "PairingRefusedError"
|
|
182
|
+
PairingRefused: "PairingRefusedError",
|
|
183
|
+
// DMK remote-network failures (manager-api HTTP / secure-channel WS).
|
|
184
|
+
WebSocketConnection: "WebSocketConnectionError",
|
|
185
|
+
HttpFetch: "FetchError",
|
|
186
|
+
InvalidFirmwareMetadataResponse: "InvalidGetFirmwareMetadataResponseError"
|
|
165
187
|
};
|
|
166
188
|
function isDeviceLockedError(err) {
|
|
167
189
|
if (!err || typeof err !== "object") return false;
|
|
@@ -249,15 +271,30 @@ function hasStatusCode(err, codeSet) {
|
|
|
249
271
|
if (e.error != null && e._tag && hasStatusCode(e.error, codeSet)) return true;
|
|
250
272
|
return false;
|
|
251
273
|
}
|
|
252
|
-
function
|
|
274
|
+
function hasDeviceActionStep(err, step) {
|
|
253
275
|
if (!err || typeof err !== "object") return false;
|
|
254
276
|
const e = err;
|
|
255
|
-
if (e._lastStep ===
|
|
256
|
-
if (Array.isArray(e._deviceActionSteps) && e._deviceActionSteps.includes(
|
|
277
|
+
if (e._lastStep === step) return true;
|
|
278
|
+
if (Array.isArray(e._deviceActionSteps) && e._deviceActionSteps.includes(step)) {
|
|
257
279
|
return true;
|
|
258
280
|
}
|
|
259
|
-
if (e.originalError != null &&
|
|
260
|
-
if (e.error != null && e._tag &&
|
|
281
|
+
if (e.originalError != null && hasDeviceActionStep(e.originalError, step)) return true;
|
|
282
|
+
if (e.error != null && e._tag && hasDeviceActionStep(e.error, step)) return true;
|
|
283
|
+
return false;
|
|
284
|
+
}
|
|
285
|
+
function hasBlindSigningStep(err) {
|
|
286
|
+
for (const step of BLIND_SIGNING_STEPS) {
|
|
287
|
+
if (hasDeviceActionStep(err, step)) return true;
|
|
288
|
+
}
|
|
289
|
+
return false;
|
|
290
|
+
}
|
|
291
|
+
function hasInvalidArgumentCode(err) {
|
|
292
|
+
if (!err || typeof err !== "object") return false;
|
|
293
|
+
const e = err;
|
|
294
|
+
if (e.code === "INVALID_ARGUMENT") return true;
|
|
295
|
+
if (typeof e.message === "string" && e.message.includes("code=INVALID_ARGUMENT")) return true;
|
|
296
|
+
if (e.originalError != null && hasInvalidArgumentCode(e.originalError)) return true;
|
|
297
|
+
if (e.error != null && e._tag && hasInvalidArgumentCode(e.error)) return true;
|
|
261
298
|
return false;
|
|
262
299
|
}
|
|
263
300
|
function isDeviceNotFoundError(err) {
|
|
@@ -286,6 +323,11 @@ function isUserRejectedError(err) {
|
|
|
286
323
|
if (hasStatusCode(err, USER_REJECTED_CODES)) return true;
|
|
287
324
|
return false;
|
|
288
325
|
}
|
|
326
|
+
function isUserAbortedError(err) {
|
|
327
|
+
if (!err || typeof err !== "object") return false;
|
|
328
|
+
const e = err;
|
|
329
|
+
return e._tag === ERROR_TAG.UserAborted;
|
|
330
|
+
}
|
|
289
331
|
function isWrongAppError(err) {
|
|
290
332
|
if (!err || typeof err !== "object") return false;
|
|
291
333
|
const e = err;
|
|
@@ -312,6 +354,20 @@ function isOutOfMemoryError(err) {
|
|
|
312
354
|
const e = err;
|
|
313
355
|
return e._tag === "OutOfMemoryDAError";
|
|
314
356
|
}
|
|
357
|
+
var NETWORK_ERROR_TAGS = /* @__PURE__ */ new Set([
|
|
358
|
+
ERROR_TAG.WebSocketConnection,
|
|
359
|
+
ERROR_TAG.HttpFetch,
|
|
360
|
+
ERROR_TAG.InvalidFirmwareMetadataResponse
|
|
361
|
+
]);
|
|
362
|
+
function isNetworkError(err) {
|
|
363
|
+
if (!err || typeof err !== "object") return false;
|
|
364
|
+
const e = err;
|
|
365
|
+
const tag = e._tag;
|
|
366
|
+
if (typeof tag === "string" && NETWORK_ERROR_TAGS.has(tag)) return true;
|
|
367
|
+
if (e.originalError != null && isNetworkError(e.originalError)) return true;
|
|
368
|
+
if (e.error != null && isNetworkError(e.error)) return true;
|
|
369
|
+
return false;
|
|
370
|
+
}
|
|
315
371
|
function isDeviceDisconnectedError(err) {
|
|
316
372
|
if (!err || typeof err !== "object") return false;
|
|
317
373
|
const e = err;
|
|
@@ -368,6 +424,8 @@ function mapLedgerError(err, opts) {
|
|
|
368
424
|
code = HardwareErrorCode.DeviceBusy;
|
|
369
425
|
} else if (isBlePairingFailureError(err)) {
|
|
370
426
|
code = HardwareErrorCode.BlePairingTimeout;
|
|
427
|
+
} else if (isUserAbortedError(err)) {
|
|
428
|
+
code = HardwareErrorCode.UserAborted;
|
|
371
429
|
} else if (isUserRejectedError(err)) {
|
|
372
430
|
code = HardwareErrorCode.UserRejected;
|
|
373
431
|
} else if (isWrongAppError(err)) {
|
|
@@ -376,12 +434,14 @@ function mapLedgerError(err, opts) {
|
|
|
376
434
|
code = HardwareErrorCode.AppNotInstalled;
|
|
377
435
|
} else if (isOutOfMemoryError(err)) {
|
|
378
436
|
code = HardwareErrorCode.DeviceOutOfMemory;
|
|
437
|
+
} else if (isNetworkError(err)) {
|
|
438
|
+
code = HardwareErrorCode.NetworkError;
|
|
379
439
|
} else if (isDeviceDisconnectedError(err)) {
|
|
380
440
|
code = HardwareErrorCode.DeviceDisconnected;
|
|
381
441
|
} else if (isTimeoutError(err)) {
|
|
382
442
|
code = HardwareErrorCode.OperationTimeout;
|
|
383
443
|
} else {
|
|
384
|
-
const ethMapped = classifyEthAppError(err);
|
|
444
|
+
const ethMapped = classifyEthAppError(err) ?? classifyBlindSigningDetectionError(err);
|
|
385
445
|
const apduHex = ethMapped ? null : extractApduHex(err);
|
|
386
446
|
const chainMapped = apduHex ? mapSolanaAppError(apduHex) ?? mapTronAppError(apduHex) ?? mapBtcAppError(apduHex) : null;
|
|
387
447
|
code = ethMapped ?? chainMapped ?? HardwareErrorCode.UnknownError;
|
|
@@ -391,17 +451,8 @@ function mapLedgerError(err, opts) {
|
|
|
391
451
|
return { code, message: enrichErrorMessage(code, originalMessage), appName };
|
|
392
452
|
}
|
|
393
453
|
|
|
394
|
-
// src/
|
|
395
|
-
|
|
396
|
-
const normalized = transport?.toUpperCase();
|
|
397
|
-
return normalized === "BLE" || normalized?.endsWith("_BLE") === true;
|
|
398
|
-
}
|
|
399
|
-
function isLedgerBleConnectionType(connectionType) {
|
|
400
|
-
return connectionType === "ble";
|
|
401
|
-
}
|
|
402
|
-
function isLedgerBleDescriptor(connectionType, descriptor) {
|
|
403
|
-
return isLedgerBleConnectionType(connectionType) || isLedgerDmkBleTransport(descriptor.transport);
|
|
404
|
-
}
|
|
454
|
+
// src/adapter/methods/allNetworkGetAddress.ts
|
|
455
|
+
import { HardwareErrorCode as HardwareErrorCode2, failure, runAllNetworkGetAddress } from "@onekeyfe/hwk-adapter-core";
|
|
405
456
|
|
|
406
457
|
// src/utils/sdkEventBus.ts
|
|
407
458
|
var listeners = /* @__PURE__ */ new Set();
|
|
@@ -448,6 +499,216 @@ function debugError(...args) {
|
|
|
448
499
|
emitLog("error", ...args);
|
|
449
500
|
}
|
|
450
501
|
|
|
502
|
+
// src/adapter/methods/allNetworkGetAddress.ts
|
|
503
|
+
var LEDGER_BTC_NETWORK_COIN_MAP = {
|
|
504
|
+
tbtc: "Testnet",
|
|
505
|
+
bch: "Bcash",
|
|
506
|
+
ltc: "Litecoin",
|
|
507
|
+
neurai: "Neurai"
|
|
508
|
+
};
|
|
509
|
+
var LEDGER_UNSUPPORTED_ALLNETWORK_NETWORKS = /* @__PURE__ */ new Set(["doge", "dogecoin"]);
|
|
510
|
+
function createAllNetworkGetAddress({
|
|
511
|
+
callChain,
|
|
512
|
+
getChainFingerprint
|
|
513
|
+
}) {
|
|
514
|
+
return async function allNetworkGetAddress(connectId, _deviceId, params) {
|
|
515
|
+
debugLog("[LedgerAdapter][REQ]", { method: "allNetworkGetAddress", connectId, params });
|
|
516
|
+
const installContext = {};
|
|
517
|
+
const commonParams = {
|
|
518
|
+
autoInstallApp: params.autoInstallApp
|
|
519
|
+
};
|
|
520
|
+
const chainFingerprints = /* @__PURE__ */ new Map();
|
|
521
|
+
const result = await runAllNetworkGetAddress({
|
|
522
|
+
connectId,
|
|
523
|
+
deviceId: _deviceId,
|
|
524
|
+
params,
|
|
525
|
+
normalizeItem: normalizeLedgerAllNetworkItem,
|
|
526
|
+
buildUnsupportedNetworkResponse: (item) => isUnsupportedLedgerAllNetworkNetwork(item) ? buildUnsupportedNetworkResponse(item) : void 0,
|
|
527
|
+
callItem: async ({ method, chain, item }) => {
|
|
528
|
+
const itemDeviceId = getItemDeviceId(item) ?? chainFingerprints.get(chain) ?? "";
|
|
529
|
+
return callAllNetworkMethod(
|
|
530
|
+
callChain,
|
|
531
|
+
connectId,
|
|
532
|
+
itemDeviceId,
|
|
533
|
+
method,
|
|
534
|
+
item,
|
|
535
|
+
commonParams,
|
|
536
|
+
installContext
|
|
537
|
+
);
|
|
538
|
+
},
|
|
539
|
+
attachIdentity: async ({ item, chain, payload }) => attachLedgerIdentity(
|
|
540
|
+
getChainFingerprint,
|
|
541
|
+
connectId,
|
|
542
|
+
item,
|
|
543
|
+
chain,
|
|
544
|
+
payload,
|
|
545
|
+
chainFingerprints
|
|
546
|
+
),
|
|
547
|
+
shouldAbortBundle: isTopLevelAllNetworkFailure,
|
|
548
|
+
buildTopLevelFailure: (response) => {
|
|
549
|
+
const code = response.payload?.code ?? HardwareErrorCode2.DeviceMismatch;
|
|
550
|
+
return failure(
|
|
551
|
+
code,
|
|
552
|
+
response.payload?.error ?? "All-network get-address aborted",
|
|
553
|
+
response.payload?.params
|
|
554
|
+
);
|
|
555
|
+
}
|
|
556
|
+
});
|
|
557
|
+
debugLog("[LedgerAdapter][RES]", {
|
|
558
|
+
method: "allNetworkGetAddress",
|
|
559
|
+
success: result.success,
|
|
560
|
+
payload: result
|
|
561
|
+
});
|
|
562
|
+
return result;
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
function isTopLevelAllNetworkFailure(response) {
|
|
566
|
+
if (response.success) {
|
|
567
|
+
return false;
|
|
568
|
+
}
|
|
569
|
+
const code = response.payload?.code;
|
|
570
|
+
return code === HardwareErrorCode2.DeviceMismatch || code === HardwareErrorCode2.UserAborted || code === HardwareErrorCode2.UserRejected;
|
|
571
|
+
}
|
|
572
|
+
function getItemDeviceId(item) {
|
|
573
|
+
const { deviceId } = item;
|
|
574
|
+
return typeof deviceId === "string" && deviceId.length > 0 ? deviceId : void 0;
|
|
575
|
+
}
|
|
576
|
+
function isUnsupportedLedgerAllNetworkNetwork(item) {
|
|
577
|
+
return LEDGER_UNSUPPORTED_ALLNETWORK_NETWORKS.has(item.network.toLowerCase());
|
|
578
|
+
}
|
|
579
|
+
function buildUnsupportedNetworkResponse(item) {
|
|
580
|
+
return {
|
|
581
|
+
...item,
|
|
582
|
+
success: false,
|
|
583
|
+
payload: {
|
|
584
|
+
code: HardwareErrorCode2.ChainNotSupported,
|
|
585
|
+
error: `Ledger allNetwork does not support ${item.network.toLowerCase() === "doge" ? "Dogecoin" : item.network}`
|
|
586
|
+
}
|
|
587
|
+
};
|
|
588
|
+
}
|
|
589
|
+
function normalizeLedgerAllNetworkItem(method, item) {
|
|
590
|
+
if (method !== "btcGetAddress" && method !== "btcGetPublicKey") {
|
|
591
|
+
return item;
|
|
592
|
+
}
|
|
593
|
+
const itemWithCoin = item;
|
|
594
|
+
if (itemWithCoin.coin) {
|
|
595
|
+
return item;
|
|
596
|
+
}
|
|
597
|
+
const coin = LEDGER_BTC_NETWORK_COIN_MAP[item.network];
|
|
598
|
+
return coin ? { ...item, coin } : item;
|
|
599
|
+
}
|
|
600
|
+
async function attachLedgerIdentity(getChainFingerprint, connectId, item, chain, payload, chainFingerprints) {
|
|
601
|
+
const fingerprint = getItemDeviceId(item) || chainFingerprints.get(chain) || await bootstrapChainFingerprint(getChainFingerprint, connectId, chain);
|
|
602
|
+
if (!fingerprint) {
|
|
603
|
+
return buildFingerprintBootstrapFailure(item, chain);
|
|
604
|
+
}
|
|
605
|
+
chainFingerprints.set(chain, fingerprint);
|
|
606
|
+
return {
|
|
607
|
+
...item,
|
|
608
|
+
success: true,
|
|
609
|
+
payload: {
|
|
610
|
+
...payload,
|
|
611
|
+
deviceIdentity: {
|
|
612
|
+
vendor: "ledger",
|
|
613
|
+
type: "chainFingerprint",
|
|
614
|
+
chain,
|
|
615
|
+
value: fingerprint
|
|
616
|
+
},
|
|
617
|
+
chainFingerprint: fingerprint,
|
|
618
|
+
chainFingerprintChain: chain
|
|
619
|
+
}
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
async function bootstrapChainFingerprint(getChainFingerprint, connectId, chain) {
|
|
623
|
+
const response = await getChainFingerprint(connectId, chain);
|
|
624
|
+
return response.success ? response.payload : "";
|
|
625
|
+
}
|
|
626
|
+
function buildFingerprintBootstrapFailure(item, chain) {
|
|
627
|
+
return {
|
|
628
|
+
...item,
|
|
629
|
+
success: false,
|
|
630
|
+
payload: {
|
|
631
|
+
code: HardwareErrorCode2.DeviceMismatch,
|
|
632
|
+
error: `Could not establish chain fingerprint for ${chain} after device call; refusing to return unverifiable result. Please retry.`
|
|
633
|
+
}
|
|
634
|
+
};
|
|
635
|
+
}
|
|
636
|
+
async function callAllNetworkMethod(callChain, connectId, deviceId, method, item, commonParams, installContext) {
|
|
637
|
+
switch (method) {
|
|
638
|
+
case "evmGetAddress":
|
|
639
|
+
return callChain(
|
|
640
|
+
connectId,
|
|
641
|
+
deviceId,
|
|
642
|
+
"evm",
|
|
643
|
+
"evmGetAddress",
|
|
644
|
+
item,
|
|
645
|
+
commonParams,
|
|
646
|
+
false,
|
|
647
|
+
installContext
|
|
648
|
+
);
|
|
649
|
+
case "btcGetAddress":
|
|
650
|
+
return callChain(
|
|
651
|
+
connectId,
|
|
652
|
+
deviceId,
|
|
653
|
+
"btc",
|
|
654
|
+
"btcGetAddress",
|
|
655
|
+
item,
|
|
656
|
+
commonParams,
|
|
657
|
+
false,
|
|
658
|
+
installContext
|
|
659
|
+
);
|
|
660
|
+
case "btcGetPublicKey":
|
|
661
|
+
return callChain(
|
|
662
|
+
connectId,
|
|
663
|
+
deviceId,
|
|
664
|
+
"btc",
|
|
665
|
+
"btcGetPublicKey",
|
|
666
|
+
item,
|
|
667
|
+
commonParams,
|
|
668
|
+
false,
|
|
669
|
+
installContext
|
|
670
|
+
);
|
|
671
|
+
case "solGetAddress":
|
|
672
|
+
return callChain(
|
|
673
|
+
connectId,
|
|
674
|
+
deviceId,
|
|
675
|
+
"sol",
|
|
676
|
+
"solGetAddress",
|
|
677
|
+
item,
|
|
678
|
+
commonParams,
|
|
679
|
+
false,
|
|
680
|
+
installContext
|
|
681
|
+
);
|
|
682
|
+
case "tronGetAddress":
|
|
683
|
+
return callChain(
|
|
684
|
+
connectId,
|
|
685
|
+
deviceId,
|
|
686
|
+
"tron",
|
|
687
|
+
"tronGetAddress",
|
|
688
|
+
item,
|
|
689
|
+
commonParams,
|
|
690
|
+
false,
|
|
691
|
+
installContext
|
|
692
|
+
);
|
|
693
|
+
default:
|
|
694
|
+
throw Object.assign(new Error(`Unsupported allNetwork method: ${method}`), {
|
|
695
|
+
code: HardwareErrorCode2.InvalidParams
|
|
696
|
+
});
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
// src/utils/ledgerDmkTransport.ts
|
|
701
|
+
function isLedgerDmkBleTransport(transport) {
|
|
702
|
+
const normalized = transport?.toUpperCase();
|
|
703
|
+
return normalized === "BLE" || normalized?.endsWith("_BLE") === true;
|
|
704
|
+
}
|
|
705
|
+
function isLedgerBleConnectionType(connectionType) {
|
|
706
|
+
return connectionType === "ble";
|
|
707
|
+
}
|
|
708
|
+
function isLedgerBleDescriptor(connectionType, descriptor) {
|
|
709
|
+
return isLedgerBleConnectionType(connectionType) || isLedgerDmkBleTransport(descriptor.transport);
|
|
710
|
+
}
|
|
711
|
+
|
|
451
712
|
// src/adapter/LedgerAdapter.ts
|
|
452
713
|
function formatDeviceMismatchError(expected, actual) {
|
|
453
714
|
return `Wrong device: expected ${expected}, got ${actual}`;
|
|
@@ -475,6 +736,11 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
475
736
|
this._btcHighIndexConfirmedThisSession = false;
|
|
476
737
|
// Shared across concurrent callers — only `cancel()` aborts.
|
|
477
738
|
this._doConnectAbortController = null;
|
|
739
|
+
this._installProgressLastEmittedValue = -Infinity;
|
|
740
|
+
this.allNetworkGetAddress = createAllNetworkGetAddress({
|
|
741
|
+
callChain: this.callChain.bind(this),
|
|
742
|
+
getChainFingerprint: (connectId, chain) => this.getChainFingerprint(connectId, "", chain)
|
|
743
|
+
});
|
|
478
744
|
// ---------------------------------------------------------------------------
|
|
479
745
|
// Private helpers
|
|
480
746
|
// ---------------------------------------------------------------------------
|
|
@@ -528,12 +794,23 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
528
794
|
);
|
|
529
795
|
return;
|
|
530
796
|
}
|
|
797
|
+
const { appName, progress } = event.payload;
|
|
798
|
+
const key = `${connectId}:${appName}`;
|
|
799
|
+
if (this._installProgressLastKey !== key || this._installProgressLastEmittedValue >= 1) {
|
|
800
|
+
this._installProgressLastEmittedValue = -Infinity;
|
|
801
|
+
this._installProgressLastKey = key;
|
|
802
|
+
}
|
|
803
|
+
const delta = progress - this._installProgressLastEmittedValue;
|
|
804
|
+
if (delta < _LedgerAdapter.APP_INSTALL_PROGRESS_MIN_DELTA && progress < 1) {
|
|
805
|
+
return;
|
|
806
|
+
}
|
|
807
|
+
this._installProgressLastEmittedValue = progress;
|
|
531
808
|
this.emitter.emit("ui-event", {
|
|
532
809
|
type: EConnectorInteraction.AppInstallProgress,
|
|
533
810
|
payload: {
|
|
534
811
|
connectId,
|
|
535
|
-
appName
|
|
536
|
-
progress
|
|
812
|
+
appName,
|
|
813
|
+
progress
|
|
537
814
|
}
|
|
538
815
|
});
|
|
539
816
|
return;
|
|
@@ -590,30 +867,42 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
590
867
|
// Device management
|
|
591
868
|
// ---------------------------------------------------------------------------
|
|
592
869
|
async searchDevices(options) {
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
const devices = await this.connector.searchDevices();
|
|
602
|
-
this._discoveredDevices.clear();
|
|
603
|
-
for (const d of devices) {
|
|
604
|
-
if (d.connectId) {
|
|
605
|
-
this._discoveredDevices.set(d.connectId, this.connectorDeviceToDeviceInfo(d));
|
|
870
|
+
debugLog("[LedgerAdapter][REQ]", { method: "searchDevices", params: options });
|
|
871
|
+
try {
|
|
872
|
+
if (options?.resetSession) {
|
|
873
|
+
this._doConnectAbortController?.abort();
|
|
874
|
+
this._sessions.clear();
|
|
875
|
+
this._connectingPromise = null;
|
|
876
|
+
this._doConnectAbortController = null;
|
|
877
|
+
this._btcHighIndexConfirmedThisSession = false;
|
|
606
878
|
}
|
|
607
|
-
}
|
|
608
|
-
if (this._discoveredDevices.size === 0) {
|
|
609
879
|
await this._ensureDevicePermission();
|
|
880
|
+
const devices = await this.connector.searchDevices();
|
|
881
|
+
this._discoveredDevices.clear();
|
|
882
|
+
for (const d of devices) {
|
|
883
|
+
if (d.connectId) {
|
|
884
|
+
this._discoveredDevices.set(d.connectId, this.connectorDeviceToDeviceInfo(d));
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
if (this._discoveredDevices.size === 0) {
|
|
888
|
+
await this._ensureDevicePermission();
|
|
889
|
+
}
|
|
890
|
+
const result = Array.from(this._discoveredDevices.values());
|
|
891
|
+
debugLog("[LedgerAdapter][RES]", {
|
|
892
|
+
method: "searchDevices",
|
|
893
|
+
success: true,
|
|
894
|
+
payload: result
|
|
895
|
+
});
|
|
896
|
+
return result;
|
|
897
|
+
} catch (err) {
|
|
898
|
+
const e = err;
|
|
899
|
+
debugLog("[LedgerAdapter][RES]", {
|
|
900
|
+
method: "searchDevices",
|
|
901
|
+
success: false,
|
|
902
|
+
error: { message: e?.message, _tag: e?._tag, code: e?.code ?? e?.errorCode }
|
|
903
|
+
});
|
|
904
|
+
throw err;
|
|
610
905
|
}
|
|
611
|
-
debugLog(
|
|
612
|
-
`[LedgerAdapter] searchDevices() return count=${this._discoveredDevices.size} ids=[${[
|
|
613
|
-
...this._discoveredDevices.keys()
|
|
614
|
-
].join(",")}]`
|
|
615
|
-
);
|
|
616
|
-
return Array.from(this._discoveredDevices.values());
|
|
617
906
|
}
|
|
618
907
|
// USB single-session invariant: evict all sessions, best-effort (see connectDevice).
|
|
619
908
|
async _evictAllSessions() {
|
|
@@ -629,14 +918,15 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
629
918
|
}
|
|
630
919
|
static _createDeviceBusyError(method) {
|
|
631
920
|
return Object.assign(new Error(`Ledger device is busy while calling ${method}`), {
|
|
632
|
-
code:
|
|
921
|
+
code: HardwareErrorCode3.DeviceBusy
|
|
633
922
|
});
|
|
634
923
|
}
|
|
635
924
|
async connectDevice(connectId) {
|
|
925
|
+
debugLog("[LedgerAdapter][REQ]", { method: "connectDevice", connectId, params: { connectId } });
|
|
636
926
|
try {
|
|
637
927
|
if (isLedgerBleConnectionType(this.connector.connectionType) && !connectId) {
|
|
638
928
|
throw Object.assign(new Error("Ledger BLE connectId is required."), {
|
|
639
|
-
code:
|
|
929
|
+
code: HardwareErrorCode3.DeviceNotFound
|
|
640
930
|
});
|
|
641
931
|
}
|
|
642
932
|
if (!isLedgerBleConnectionType(this.connector.connectionType)) {
|
|
@@ -648,28 +938,79 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
648
938
|
if (session.deviceInfo) {
|
|
649
939
|
this._discoveredDevices.set(connectId, session.deviceInfo);
|
|
650
940
|
}
|
|
651
|
-
|
|
941
|
+
const result = success(connectId);
|
|
942
|
+
debugLog("[LedgerAdapter][RES]", { method: "connectDevice", success: true, payload: result });
|
|
943
|
+
return result;
|
|
652
944
|
} catch (err) {
|
|
653
|
-
|
|
945
|
+
const failureResult = this.errorToFailure(err);
|
|
946
|
+
debugLog("[LedgerAdapter][RES]", {
|
|
947
|
+
method: "connectDevice",
|
|
948
|
+
success: false,
|
|
949
|
+
payload: failureResult
|
|
950
|
+
});
|
|
951
|
+
return failureResult;
|
|
654
952
|
}
|
|
655
953
|
}
|
|
656
954
|
async disconnectDevice(connectId) {
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
955
|
+
debugLog("[LedgerAdapter][REQ]", {
|
|
956
|
+
method: "disconnectDevice",
|
|
957
|
+
connectId,
|
|
958
|
+
params: { connectId }
|
|
959
|
+
});
|
|
960
|
+
try {
|
|
961
|
+
const sessionId = this._sessions.get(connectId);
|
|
962
|
+
if (sessionId) {
|
|
963
|
+
await this.connector.disconnect(sessionId);
|
|
964
|
+
this._sessions.delete(connectId);
|
|
965
|
+
}
|
|
966
|
+
debugLog("[LedgerAdapter][RES]", { method: "disconnectDevice", success: true });
|
|
967
|
+
} catch (err) {
|
|
968
|
+
const e = err;
|
|
969
|
+
debugLog("[LedgerAdapter][RES]", {
|
|
970
|
+
method: "disconnectDevice",
|
|
971
|
+
success: false,
|
|
972
|
+
error: { message: e?.message, _tag: e?._tag, code: e?.code ?? e?.errorCode }
|
|
973
|
+
});
|
|
974
|
+
throw err;
|
|
661
975
|
}
|
|
662
976
|
}
|
|
663
977
|
async getDeviceInfo(connectId, deviceId) {
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
978
|
+
debugLog("[LedgerAdapter][REQ]", {
|
|
979
|
+
method: "getDeviceInfo",
|
|
980
|
+
connectId,
|
|
981
|
+
params: { connectId, deviceId }
|
|
982
|
+
});
|
|
983
|
+
try {
|
|
984
|
+
await this._ensureDevicePermission(connectId, deviceId);
|
|
985
|
+
const cached = this._discoveredDevices.get(connectId) ?? Array.from(this._discoveredDevices.values()).find((d) => d.deviceId === deviceId);
|
|
986
|
+
if (cached) {
|
|
987
|
+
const result = success(cached);
|
|
988
|
+
debugLog("[LedgerAdapter][RES]", {
|
|
989
|
+
method: "getDeviceInfo",
|
|
990
|
+
success: true,
|
|
991
|
+
payload: result
|
|
992
|
+
});
|
|
993
|
+
return result;
|
|
994
|
+
}
|
|
995
|
+
const notFound = failure2(
|
|
996
|
+
HardwareErrorCode3.DeviceNotFound,
|
|
997
|
+
"Device not found in cache. Call searchDevices() or wait for a device-connected event first."
|
|
998
|
+
);
|
|
999
|
+
debugLog("[LedgerAdapter][RES]", {
|
|
1000
|
+
method: "getDeviceInfo",
|
|
1001
|
+
success: false,
|
|
1002
|
+
payload: notFound
|
|
1003
|
+
});
|
|
1004
|
+
return notFound;
|
|
1005
|
+
} catch (err) {
|
|
1006
|
+
const e = err;
|
|
1007
|
+
debugLog("[LedgerAdapter][RES]", {
|
|
1008
|
+
method: "getDeviceInfo",
|
|
1009
|
+
success: false,
|
|
1010
|
+
error: { message: e?.message, _tag: e?._tag, code: e?.code ?? e?.errorCode }
|
|
1011
|
+
});
|
|
1012
|
+
throw err;
|
|
668
1013
|
}
|
|
669
|
-
return failure(
|
|
670
|
-
HardwareErrorCode2.DeviceNotFound,
|
|
671
|
-
"Device not found in cache. Call searchDevices() or wait for a device-connected event first."
|
|
672
|
-
);
|
|
673
1014
|
}
|
|
674
1015
|
getSupportedChains() {
|
|
675
1016
|
return ["evm", "btc", "sol", "tron"];
|
|
@@ -677,7 +1018,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
677
1018
|
// ---------------------------------------------------------------------------
|
|
678
1019
|
// Chain call helper
|
|
679
1020
|
// ---------------------------------------------------------------------------
|
|
680
|
-
async callChain(connectId, deviceId, chain, method, params, commonParams, skipFingerprint = false) {
|
|
1021
|
+
async callChain(connectId, deviceId, chain, method, params, commonParams, skipFingerprint = false, installContext) {
|
|
681
1022
|
try {
|
|
682
1023
|
const result = await this.connectorCall(
|
|
683
1024
|
connectId,
|
|
@@ -689,183 +1030,204 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
689
1030
|
skipFingerprint
|
|
690
1031
|
},
|
|
691
1032
|
void 0,
|
|
692
|
-
commonParams
|
|
1033
|
+
commonParams,
|
|
1034
|
+
installContext
|
|
693
1035
|
);
|
|
694
1036
|
return success(result);
|
|
695
1037
|
} catch (err) {
|
|
696
1038
|
return this.errorToFailure(err);
|
|
697
1039
|
}
|
|
698
1040
|
}
|
|
1041
|
+
static normalizeCallArgs(connectId, deviceId, params) {
|
|
1042
|
+
return {
|
|
1043
|
+
connectId: connectId ?? "",
|
|
1044
|
+
deviceId: deviceId ?? "",
|
|
1045
|
+
params: params ?? {}
|
|
1046
|
+
};
|
|
1047
|
+
}
|
|
1048
|
+
static splitCommonParams(params) {
|
|
1049
|
+
if (params && typeof params === "object") {
|
|
1050
|
+
const {
|
|
1051
|
+
autoInstallApp,
|
|
1052
|
+
passphraseState: _passphraseState,
|
|
1053
|
+
useEmptyPassphrase: _useEmptyPassphrase,
|
|
1054
|
+
...rest
|
|
1055
|
+
} = params;
|
|
1056
|
+
return {
|
|
1057
|
+
commonParams: {
|
|
1058
|
+
autoInstallApp: typeof autoInstallApp === "boolean" ? autoInstallApp : void 0
|
|
1059
|
+
},
|
|
1060
|
+
rest
|
|
1061
|
+
};
|
|
1062
|
+
}
|
|
1063
|
+
return { commonParams: {}, rest: params ?? {} };
|
|
1064
|
+
}
|
|
1065
|
+
callChainWithMergedParams(connectId, deviceId, chain, method, params) {
|
|
1066
|
+
const normalized = _LedgerAdapter.normalizeCallArgs(connectId, deviceId, params);
|
|
1067
|
+
const { commonParams, rest } = _LedgerAdapter.splitCommonParams(normalized.params);
|
|
1068
|
+
return this.callChain(
|
|
1069
|
+
normalized.connectId,
|
|
1070
|
+
normalized.deviceId,
|
|
1071
|
+
chain,
|
|
1072
|
+
method,
|
|
1073
|
+
rest,
|
|
1074
|
+
commonParams
|
|
1075
|
+
);
|
|
1076
|
+
}
|
|
699
1077
|
// ---------------------------------------------------------------------------
|
|
700
1078
|
// EVM chain methods
|
|
701
1079
|
// ---------------------------------------------------------------------------
|
|
702
|
-
evmGetAddress(connectId, deviceId, params
|
|
703
|
-
return this.
|
|
1080
|
+
evmGetAddress(connectId, deviceId, params) {
|
|
1081
|
+
return this.callChainWithMergedParams(
|
|
704
1082
|
connectId,
|
|
705
1083
|
deviceId,
|
|
706
1084
|
"evm",
|
|
707
1085
|
"evmGetAddress",
|
|
708
|
-
params
|
|
709
|
-
commonParams
|
|
1086
|
+
params
|
|
710
1087
|
);
|
|
711
1088
|
}
|
|
712
|
-
evmSignTransaction(connectId, deviceId, params
|
|
713
|
-
return this.
|
|
1089
|
+
evmSignTransaction(connectId, deviceId, params) {
|
|
1090
|
+
return this.callChainWithMergedParams(
|
|
714
1091
|
connectId,
|
|
715
1092
|
deviceId,
|
|
716
1093
|
"evm",
|
|
717
1094
|
"evmSignTransaction",
|
|
718
|
-
params
|
|
719
|
-
commonParams
|
|
1095
|
+
params
|
|
720
1096
|
);
|
|
721
1097
|
}
|
|
722
|
-
evmSignMessage(connectId, deviceId, params
|
|
723
|
-
return this.
|
|
1098
|
+
evmSignMessage(connectId, deviceId, params) {
|
|
1099
|
+
return this.callChainWithMergedParams(
|
|
724
1100
|
connectId,
|
|
725
1101
|
deviceId,
|
|
726
1102
|
"evm",
|
|
727
1103
|
"evmSignMessage",
|
|
728
|
-
params
|
|
729
|
-
commonParams
|
|
1104
|
+
params
|
|
730
1105
|
);
|
|
731
1106
|
}
|
|
732
|
-
evmSignTypedData(connectId, deviceId, params
|
|
733
|
-
return this.
|
|
1107
|
+
evmSignTypedData(connectId, deviceId, params) {
|
|
1108
|
+
return this.callChainWithMergedParams(
|
|
734
1109
|
connectId,
|
|
735
1110
|
deviceId,
|
|
736
1111
|
"evm",
|
|
737
1112
|
"evmSignTypedData",
|
|
738
|
-
params
|
|
739
|
-
commonParams
|
|
1113
|
+
params
|
|
740
1114
|
);
|
|
741
1115
|
}
|
|
742
1116
|
// ---------------------------------------------------------------------------
|
|
743
1117
|
// BTC chain methods
|
|
744
1118
|
// ---------------------------------------------------------------------------
|
|
745
|
-
btcGetAddress(connectId, deviceId, params
|
|
746
|
-
return this.
|
|
1119
|
+
btcGetAddress(connectId, deviceId, params) {
|
|
1120
|
+
return this.callChainWithMergedParams(
|
|
747
1121
|
connectId,
|
|
748
1122
|
deviceId,
|
|
749
1123
|
"btc",
|
|
750
1124
|
"btcGetAddress",
|
|
751
|
-
params
|
|
752
|
-
commonParams
|
|
1125
|
+
params
|
|
753
1126
|
);
|
|
754
1127
|
}
|
|
755
|
-
btcGetPublicKey(connectId, deviceId, params
|
|
756
|
-
return this.
|
|
1128
|
+
btcGetPublicKey(connectId, deviceId, params) {
|
|
1129
|
+
return this.callChainWithMergedParams(
|
|
757
1130
|
connectId,
|
|
758
1131
|
deviceId,
|
|
759
1132
|
"btc",
|
|
760
1133
|
"btcGetPublicKey",
|
|
761
|
-
params
|
|
762
|
-
commonParams
|
|
1134
|
+
params
|
|
763
1135
|
);
|
|
764
1136
|
}
|
|
765
|
-
btcSignTransaction(connectId, deviceId, params
|
|
766
|
-
return this.
|
|
1137
|
+
btcSignTransaction(connectId, deviceId, params) {
|
|
1138
|
+
return this.callChainWithMergedParams(
|
|
767
1139
|
connectId,
|
|
768
1140
|
deviceId,
|
|
769
1141
|
"btc",
|
|
770
1142
|
"btcSignTransaction",
|
|
771
|
-
params
|
|
772
|
-
commonParams
|
|
1143
|
+
params
|
|
773
1144
|
);
|
|
774
1145
|
}
|
|
775
|
-
btcSignPsbt(connectId, deviceId, params
|
|
776
|
-
return this.
|
|
1146
|
+
btcSignPsbt(connectId, deviceId, params) {
|
|
1147
|
+
return this.callChainWithMergedParams(
|
|
777
1148
|
connectId,
|
|
778
1149
|
deviceId,
|
|
779
1150
|
"btc",
|
|
780
1151
|
"btcSignPsbt",
|
|
781
|
-
params
|
|
782
|
-
commonParams
|
|
1152
|
+
params
|
|
783
1153
|
);
|
|
784
1154
|
}
|
|
785
|
-
btcSignMessage(connectId, deviceId, params
|
|
786
|
-
return this.
|
|
1155
|
+
btcSignMessage(connectId, deviceId, params) {
|
|
1156
|
+
return this.callChainWithMergedParams(
|
|
787
1157
|
connectId,
|
|
788
1158
|
deviceId,
|
|
789
1159
|
"btc",
|
|
790
1160
|
"btcSignMessage",
|
|
791
|
-
params
|
|
792
|
-
commonParams
|
|
1161
|
+
params
|
|
793
1162
|
);
|
|
794
1163
|
}
|
|
795
|
-
btcGetMasterFingerprint(connectId, deviceId,
|
|
796
|
-
return this.
|
|
1164
|
+
btcGetMasterFingerprint(connectId, deviceId, params) {
|
|
1165
|
+
return this.callChainWithMergedParams(
|
|
797
1166
|
connectId,
|
|
798
1167
|
deviceId,
|
|
799
1168
|
"btc",
|
|
800
1169
|
"btcGetMasterFingerprint",
|
|
801
|
-
|
|
802
|
-
commonParams
|
|
1170
|
+
params
|
|
803
1171
|
);
|
|
804
1172
|
}
|
|
805
1173
|
// ---------------------------------------------------------------------------
|
|
806
1174
|
// SOL chain methods
|
|
807
1175
|
// ---------------------------------------------------------------------------
|
|
808
|
-
solGetAddress(connectId, deviceId, params
|
|
809
|
-
return this.
|
|
1176
|
+
solGetAddress(connectId, deviceId, params) {
|
|
1177
|
+
return this.callChainWithMergedParams(
|
|
810
1178
|
connectId,
|
|
811
1179
|
deviceId,
|
|
812
1180
|
"sol",
|
|
813
1181
|
"solGetAddress",
|
|
814
|
-
params
|
|
815
|
-
commonParams
|
|
1182
|
+
params
|
|
816
1183
|
);
|
|
817
1184
|
}
|
|
818
|
-
solSignTransaction(connectId, deviceId, params
|
|
819
|
-
return this.
|
|
1185
|
+
solSignTransaction(connectId, deviceId, params) {
|
|
1186
|
+
return this.callChainWithMergedParams(
|
|
820
1187
|
connectId,
|
|
821
1188
|
deviceId,
|
|
822
1189
|
"sol",
|
|
823
1190
|
"solSignTransaction",
|
|
824
|
-
params
|
|
825
|
-
commonParams
|
|
1191
|
+
params
|
|
826
1192
|
);
|
|
827
1193
|
}
|
|
828
|
-
solSignMessage(connectId, deviceId, params
|
|
829
|
-
return this.
|
|
1194
|
+
solSignMessage(connectId, deviceId, params) {
|
|
1195
|
+
return this.callChainWithMergedParams(
|
|
830
1196
|
connectId,
|
|
831
1197
|
deviceId,
|
|
832
1198
|
"sol",
|
|
833
1199
|
"solSignMessage",
|
|
834
|
-
params
|
|
835
|
-
commonParams
|
|
1200
|
+
params
|
|
836
1201
|
);
|
|
837
1202
|
}
|
|
838
1203
|
// ---------------------------------------------------------------------------
|
|
839
1204
|
// TRON chain methods
|
|
840
1205
|
// ---------------------------------------------------------------------------
|
|
841
|
-
tronGetAddress(connectId, deviceId, params
|
|
842
|
-
return this.
|
|
1206
|
+
tronGetAddress(connectId, deviceId, params) {
|
|
1207
|
+
return this.callChainWithMergedParams(
|
|
843
1208
|
connectId,
|
|
844
1209
|
deviceId,
|
|
845
1210
|
"tron",
|
|
846
1211
|
"tronGetAddress",
|
|
847
|
-
params
|
|
848
|
-
commonParams
|
|
1212
|
+
params
|
|
849
1213
|
);
|
|
850
1214
|
}
|
|
851
|
-
tronSignTransaction(connectId, deviceId, params
|
|
852
|
-
return this.
|
|
1215
|
+
tronSignTransaction(connectId, deviceId, params) {
|
|
1216
|
+
return this.callChainWithMergedParams(
|
|
853
1217
|
connectId,
|
|
854
1218
|
deviceId,
|
|
855
1219
|
"tron",
|
|
856
1220
|
"tronSignTransaction",
|
|
857
|
-
params
|
|
858
|
-
commonParams
|
|
1221
|
+
params
|
|
859
1222
|
);
|
|
860
1223
|
}
|
|
861
|
-
tronSignMessage(connectId, deviceId, params
|
|
862
|
-
return this.
|
|
1224
|
+
tronSignMessage(connectId, deviceId, params) {
|
|
1225
|
+
return this.callChainWithMergedParams(
|
|
863
1226
|
connectId,
|
|
864
1227
|
deviceId,
|
|
865
1228
|
"tron",
|
|
866
1229
|
"tronSignMessage",
|
|
867
|
-
params
|
|
868
|
-
commonParams
|
|
1230
|
+
params
|
|
869
1231
|
);
|
|
870
1232
|
}
|
|
871
1233
|
// ---------------------------------------------------------------------------
|
|
@@ -889,6 +1251,15 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
889
1251
|
return this.errorToFailure(err);
|
|
890
1252
|
}
|
|
891
1253
|
}
|
|
1254
|
+
// Offline app-presence + unlock probe. No manager-api catalog (unlike listInstalledApps).
|
|
1255
|
+
async listInstalledNames(connectId) {
|
|
1256
|
+
try {
|
|
1257
|
+
const result = await this.connectorCall(connectId, "listInstalledNames", {});
|
|
1258
|
+
return success(result);
|
|
1259
|
+
} catch (err) {
|
|
1260
|
+
return this.errorToFailure(err);
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
892
1263
|
async listAvailableApps(connectId) {
|
|
893
1264
|
try {
|
|
894
1265
|
const result = await this.connectorCall(connectId, "listAvailableApps", {});
|
|
@@ -921,7 +1292,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
921
1292
|
}
|
|
922
1293
|
cancel(connectId) {
|
|
923
1294
|
const userAbortReason = Object.assign(new Error("User aborted operation"), {
|
|
924
|
-
code:
|
|
1295
|
+
code: HardwareErrorCode3.UserAborted,
|
|
925
1296
|
_tag: ERROR_TAG.UserAborted
|
|
926
1297
|
});
|
|
927
1298
|
this._lastCancelReason = userAbortReason;
|
|
@@ -978,7 +1349,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
978
1349
|
return { success: false, expected: deviceId, actual: fingerprint };
|
|
979
1350
|
} catch (err) {
|
|
980
1351
|
const mapped = mapLedgerError(err);
|
|
981
|
-
if (mapped.code ===
|
|
1352
|
+
if (mapped.code === HardwareErrorCode3.WrongApp || mapped.code === HardwareErrorCode3.DeviceLocked) {
|
|
982
1353
|
return { success: true };
|
|
983
1354
|
}
|
|
984
1355
|
throw err;
|
|
@@ -1058,14 +1429,14 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1058
1429
|
});
|
|
1059
1430
|
throw Object.assign(new Error("User cancelled Ledger connection"), {
|
|
1060
1431
|
_tag: ERROR_TAG.UserAborted,
|
|
1061
|
-
code:
|
|
1432
|
+
code: HardwareErrorCode3.UserAborted,
|
|
1062
1433
|
cause: err
|
|
1063
1434
|
});
|
|
1064
1435
|
}
|
|
1065
1436
|
if (!payload?.confirmed) {
|
|
1066
1437
|
throw Object.assign(new Error("User cancelled Ledger connection"), {
|
|
1067
1438
|
_tag: ERROR_TAG.UserAborted,
|
|
1068
|
-
code:
|
|
1439
|
+
code: HardwareErrorCode3.UserAborted
|
|
1069
1440
|
});
|
|
1070
1441
|
}
|
|
1071
1442
|
await new Promise((resolve) => {
|
|
@@ -1144,7 +1515,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1144
1515
|
if (signal.aborted) _LedgerAdapter._throwIfAborted(signal);
|
|
1145
1516
|
if (isLedgerBleConnectionType(this.connector.connectionType) && !connectId) {
|
|
1146
1517
|
throw Object.assign(new Error("Ledger BLE connectId is required."), {
|
|
1147
|
-
code:
|
|
1518
|
+
code: HardwareErrorCode3.DeviceNotFound
|
|
1148
1519
|
});
|
|
1149
1520
|
}
|
|
1150
1521
|
if (connectId && this._sessions.has(connectId)) return connectId;
|
|
@@ -1154,7 +1525,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1154
1525
|
new Error(
|
|
1155
1526
|
"Ledger USB session invariant violated: more than one session is active. Please reconnect the device."
|
|
1156
1527
|
),
|
|
1157
|
-
{ code:
|
|
1528
|
+
{ code: HardwareErrorCode3.DeviceOneDeviceOnly }
|
|
1158
1529
|
);
|
|
1159
1530
|
}
|
|
1160
1531
|
return this._sessions.keys().next().value;
|
|
@@ -1203,7 +1574,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1203
1574
|
if (devices.length === 0) {
|
|
1204
1575
|
for (let i = 0; i < 3 && !internalSignal.aborted; i += 1) {
|
|
1205
1576
|
await new Promise((resolve) => {
|
|
1206
|
-
setTimeout(resolve,
|
|
1577
|
+
setTimeout(resolve, DEVICE_CONNECT_RETRY_DELAY_MS);
|
|
1207
1578
|
});
|
|
1208
1579
|
devices = await this.searchDevices();
|
|
1209
1580
|
if (devices.length > 0) break;
|
|
@@ -1234,7 +1605,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1234
1605
|
new Error(
|
|
1235
1606
|
"Device not connected after multiple attempts. Please ensure your Ledger is awake, unlocked, and in range, then try again."
|
|
1236
1607
|
),
|
|
1237
|
-
{ code:
|
|
1608
|
+
{ code: HardwareErrorCode3.DeviceNotFound }
|
|
1238
1609
|
);
|
|
1239
1610
|
}
|
|
1240
1611
|
await this._waitForDeviceConnect(internalSignal);
|
|
@@ -1258,7 +1629,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1258
1629
|
return this._connectDeviceOrThrow(devices[0].connectId);
|
|
1259
1630
|
}
|
|
1260
1631
|
const err = Object.assign(new Error(`Target Ledger unavailable: ${targetConnectId}`), {
|
|
1261
|
-
code:
|
|
1632
|
+
code: HardwareErrorCode3.DeviceNotFound
|
|
1262
1633
|
});
|
|
1263
1634
|
if (isLedgerBleConnectionType(this.connector.connectionType)) {
|
|
1264
1635
|
err._tag = ERROR_TAG.DeviceNotAdvertising;
|
|
@@ -1267,7 +1638,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1267
1638
|
}
|
|
1268
1639
|
if (isLedgerBleConnectionType(this.connector.connectionType)) {
|
|
1269
1640
|
throw Object.assign(new Error("Ledger BLE connectId is required."), {
|
|
1270
|
-
code:
|
|
1641
|
+
code: HardwareErrorCode3.DeviceNotFound
|
|
1271
1642
|
});
|
|
1272
1643
|
}
|
|
1273
1644
|
if (devices.length > 1) {
|
|
@@ -1275,7 +1646,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1275
1646
|
}
|
|
1276
1647
|
if (devices.length !== 1) {
|
|
1277
1648
|
throw Object.assign(new Error("Ledger device not found."), {
|
|
1278
|
-
code:
|
|
1649
|
+
code: HardwareErrorCode3.DeviceNotFound
|
|
1279
1650
|
});
|
|
1280
1651
|
}
|
|
1281
1652
|
return this._connectDeviceOrThrow(devices[0].connectId);
|
|
@@ -1326,26 +1697,43 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1326
1697
|
const result = signal ? await this._abortable(signal, promise) : await promise;
|
|
1327
1698
|
return this._unwrapConnectorResult(result);
|
|
1328
1699
|
}
|
|
1329
|
-
async connectorCall(connectId, method, params, fingerprint, permissionDeviceId, commonParams) {
|
|
1330
|
-
debugLog("[LedgerAdapter]
|
|
1700
|
+
async connectorCall(connectId, method, params, fingerprint, permissionDeviceId, commonParams, installContext) {
|
|
1701
|
+
debugLog("[LedgerAdapter][REQ]", { method, connectId: connectId || "(empty)", params });
|
|
1331
1702
|
const queueKey = connectId || "__ledger_default__";
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1703
|
+
try {
|
|
1704
|
+
const result = await this._jobQueue.enqueue(
|
|
1705
|
+
queueKey,
|
|
1706
|
+
async (signal) => this._runConnectorCall(
|
|
1707
|
+
connectId,
|
|
1708
|
+
method,
|
|
1709
|
+
params,
|
|
1710
|
+
signal,
|
|
1711
|
+
fingerprint,
|
|
1712
|
+
permissionDeviceId,
|
|
1713
|
+
commonParams,
|
|
1714
|
+
installContext
|
|
1715
|
+
),
|
|
1716
|
+
{
|
|
1717
|
+
label: method,
|
|
1718
|
+
rejectIfBusy: true,
|
|
1719
|
+
busyError: _LedgerAdapter._createDeviceBusyError(method)
|
|
1720
|
+
}
|
|
1721
|
+
);
|
|
1722
|
+
debugLog("[LedgerAdapter][RES]", { method, success: true, payload: result });
|
|
1723
|
+
return result;
|
|
1724
|
+
} catch (err) {
|
|
1725
|
+
const e = err;
|
|
1726
|
+
debugLog("[LedgerAdapter][RES]", {
|
|
1336
1727
|
method,
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
busyError: _LedgerAdapter._createDeviceBusyError(method)
|
|
1347
|
-
}
|
|
1348
|
-
);
|
|
1728
|
+
success: false,
|
|
1729
|
+
error: {
|
|
1730
|
+
message: e?.message,
|
|
1731
|
+
_tag: e?._tag,
|
|
1732
|
+
code: e?.code ?? e?.errorCode
|
|
1733
|
+
}
|
|
1734
|
+
});
|
|
1735
|
+
throw err;
|
|
1736
|
+
}
|
|
1349
1737
|
}
|
|
1350
1738
|
/**
|
|
1351
1739
|
* Race a promise against an abort signal. On abort, rejects with
|
|
@@ -1380,7 +1768,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1380
1768
|
}
|
|
1381
1769
|
}
|
|
1382
1770
|
/** Actual work done under the job queue — connection, fingerprint, call, and recovery. */
|
|
1383
|
-
async _runConnectorCall(connectId, method, params, signal, fingerprint, permissionDeviceId, commonParams) {
|
|
1771
|
+
async _runConnectorCall(connectId, method, params, signal, fingerprint, permissionDeviceId, commonParams, installContext) {
|
|
1384
1772
|
_LedgerAdapter._throwIfAborted(signal);
|
|
1385
1773
|
await this._ensureDevicePermission(
|
|
1386
1774
|
connectId,
|
|
@@ -1394,7 +1782,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1394
1782
|
if (gatedParams === null) {
|
|
1395
1783
|
throw Object.assign(new Error("User cancelled BTC high-index confirmation"), {
|
|
1396
1784
|
_tag: ERROR_TAG.UserAborted,
|
|
1397
|
-
code:
|
|
1785
|
+
code: HardwareErrorCode3.UserAborted
|
|
1398
1786
|
});
|
|
1399
1787
|
}
|
|
1400
1788
|
effectiveParams = gatedParams;
|
|
@@ -1423,7 +1811,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1423
1811
|
);
|
|
1424
1812
|
if (!fp.success) {
|
|
1425
1813
|
throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {
|
|
1426
|
-
code:
|
|
1814
|
+
code: HardwareErrorCode3.DeviceMismatch
|
|
1427
1815
|
});
|
|
1428
1816
|
}
|
|
1429
1817
|
}
|
|
@@ -1442,22 +1830,62 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1442
1830
|
isStuckApp: isStuckAppStateError(err)
|
|
1443
1831
|
});
|
|
1444
1832
|
const autoInstallApp = commonParams?.autoInstallApp ?? this._defaultAutoInstallApp;
|
|
1445
|
-
const isAppMissing = isAppNotInstalledError(err) || err?.code ===
|
|
1833
|
+
const isAppMissing = isAppNotInstalledError(err) || err?.code === HardwareErrorCode3.AppNotInstalled;
|
|
1446
1834
|
if (autoInstallApp && isAppMissing) {
|
|
1835
|
+
if (installContext?.deviceOutOfMemoryError) {
|
|
1836
|
+
throw installContext.deviceOutOfMemoryError;
|
|
1837
|
+
}
|
|
1447
1838
|
const appName = err?.appName ?? mapLedgerError(err).appName;
|
|
1448
1839
|
if (appName) {
|
|
1840
|
+
if (installContext?.installAttemptedAppNames?.has(appName)) {
|
|
1841
|
+
throw createHwkError({
|
|
1842
|
+
code: HardwareErrorCode3.AppNotInstalled,
|
|
1843
|
+
message: `${appName} install reported success but the app is still missing on device`,
|
|
1844
|
+
_tag: ERROR_TAG.AppInstallVerifyFailed,
|
|
1845
|
+
appName
|
|
1846
|
+
});
|
|
1847
|
+
}
|
|
1449
1848
|
const confirmed = await this._waitForInstallAppConfirm(appName);
|
|
1450
|
-
if (!confirmed)
|
|
1849
|
+
if (!confirmed) {
|
|
1850
|
+
throw createHwkError({
|
|
1851
|
+
code: HardwareErrorCode3.UserAborted,
|
|
1852
|
+
message: `User declined to install ${appName}`,
|
|
1853
|
+
_tag: ERROR_TAG.UserAborted,
|
|
1854
|
+
appName
|
|
1855
|
+
});
|
|
1856
|
+
}
|
|
1451
1857
|
this.emitter.emit("ui-event", {
|
|
1452
1858
|
type: EConnectorInteraction.AppInstallProgress,
|
|
1453
1859
|
payload: { connectId: resolvedConnectId, appName, progress: 0 }
|
|
1454
1860
|
});
|
|
1455
|
-
|
|
1861
|
+
try {
|
|
1862
|
+
await this._callConnector(sessionId, "installApp", { appName }, signal);
|
|
1863
|
+
} catch (installErr) {
|
|
1864
|
+
if (mapLedgerError(installErr).code === HardwareErrorCode3.DeviceOutOfMemory) {
|
|
1865
|
+
if (installContext) {
|
|
1866
|
+
installContext.deviceOutOfMemoryError = installErr;
|
|
1867
|
+
}
|
|
1868
|
+
}
|
|
1869
|
+
throw installErr;
|
|
1870
|
+
}
|
|
1871
|
+
if (installContext) {
|
|
1872
|
+
installContext.installAttemptedAppNames = installContext.installAttemptedAppNames ?? /* @__PURE__ */ new Set();
|
|
1873
|
+
installContext.installAttemptedAppNames.add(appName);
|
|
1874
|
+
}
|
|
1456
1875
|
this.emitter.emit(UI_REQUEST.CLOSE_UI_WINDOW, {
|
|
1457
1876
|
type: UI_REQUEST.CLOSE_UI_WINDOW,
|
|
1458
1877
|
payload: {}
|
|
1459
1878
|
});
|
|
1460
|
-
return await this.
|
|
1879
|
+
return await this._runConnectorCall(
|
|
1880
|
+
resolvedConnectId,
|
|
1881
|
+
method,
|
|
1882
|
+
effectiveParams,
|
|
1883
|
+
signal,
|
|
1884
|
+
fingerprint,
|
|
1885
|
+
permissionDeviceId,
|
|
1886
|
+
commonParams,
|
|
1887
|
+
installContext
|
|
1888
|
+
);
|
|
1461
1889
|
}
|
|
1462
1890
|
}
|
|
1463
1891
|
if (isStuckAppStateError(err)) {
|
|
@@ -1532,7 +1960,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1532
1960
|
);
|
|
1533
1961
|
if (!fp.success) {
|
|
1534
1962
|
throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {
|
|
1535
|
-
code:
|
|
1963
|
+
code: HardwareErrorCode3.DeviceMismatch
|
|
1536
1964
|
});
|
|
1537
1965
|
}
|
|
1538
1966
|
}
|
|
@@ -1567,7 +1995,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1567
1995
|
this.connector.reset();
|
|
1568
1996
|
const codeNum = err?.code;
|
|
1569
1997
|
throw Object.assign(err, {
|
|
1570
|
-
code: codeNum ??
|
|
1998
|
+
code: codeNum ?? HardwareErrorCode3.DeviceDisconnected
|
|
1571
1999
|
});
|
|
1572
2000
|
}
|
|
1573
2001
|
throw err;
|
|
@@ -1601,7 +2029,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1601
2029
|
);
|
|
1602
2030
|
if (!fp.success) {
|
|
1603
2031
|
throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {
|
|
1604
|
-
code:
|
|
2032
|
+
code: HardwareErrorCode3.DeviceMismatch
|
|
1605
2033
|
});
|
|
1606
2034
|
}
|
|
1607
2035
|
}
|
|
@@ -1658,7 +2086,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1658
2086
|
);
|
|
1659
2087
|
if (!fp.success) {
|
|
1660
2088
|
throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {
|
|
1661
|
-
code:
|
|
2089
|
+
code: HardwareErrorCode3.DeviceMismatch
|
|
1662
2090
|
});
|
|
1663
2091
|
}
|
|
1664
2092
|
}
|
|
@@ -1699,7 +2127,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1699
2127
|
);
|
|
1700
2128
|
if (!fp.success) {
|
|
1701
2129
|
throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {
|
|
1702
|
-
code:
|
|
2130
|
+
code: HardwareErrorCode3.DeviceMismatch
|
|
1703
2131
|
});
|
|
1704
2132
|
}
|
|
1705
2133
|
}
|
|
@@ -1749,7 +2177,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1749
2177
|
});
|
|
1750
2178
|
throw Object.assign(new Error("Device permission request superseded"), {
|
|
1751
2179
|
_tag: ERROR_TAG.UserAborted,
|
|
1752
|
-
code:
|
|
2180
|
+
code: HardwareErrorCode3.UserAborted,
|
|
1753
2181
|
cause: err
|
|
1754
2182
|
});
|
|
1755
2183
|
}
|
|
@@ -1760,7 +2188,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1760
2188
|
const { granted, reason, message } = response;
|
|
1761
2189
|
if (!granted) {
|
|
1762
2190
|
throw Object.assign(new Error(message ?? "Device permission denied"), {
|
|
1763
|
-
code:
|
|
2191
|
+
code: HardwareErrorCode3.DevicePermissionDenied,
|
|
1764
2192
|
reason
|
|
1765
2193
|
});
|
|
1766
2194
|
}
|
|
@@ -1774,7 +2202,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1774
2202
|
const tag = err && typeof err === "object" ? err._tag : void 0;
|
|
1775
2203
|
if (err && typeof err === "object" && "code" in err && typeof err.code === "number") {
|
|
1776
2204
|
const e = err;
|
|
1777
|
-
const params = e.code ===
|
|
2205
|
+
const params = e.code === HardwareErrorCode3.DevicePermissionDenied && e.reason ? { permissionDeniedReason: e.reason } : e.params;
|
|
1778
2206
|
return ledgerFailure(e.code, e.message ?? "Unknown error", e.appName, tag, params);
|
|
1779
2207
|
}
|
|
1780
2208
|
const mapped = mapLedgerError(err);
|
|
@@ -1821,12 +2249,16 @@ _LedgerAdapter.STUCK_APP_RETRY_DELAY_MS = 500;
|
|
|
1821
2249
|
// Confirm but device never shows up / never unlocks), throw DeviceNotFound
|
|
1822
2250
|
// instead of looping forever.
|
|
1823
2251
|
_LedgerAdapter.MAX_DOCONNECT_CONFIRMS = 3;
|
|
2252
|
+
// Throttle AppInstallProgress by progress delta — DMK streams much faster
|
|
2253
|
+
// than UIs need. Final frame (progress >= 1) always passes.
|
|
2254
|
+
_LedgerAdapter.APP_INSTALL_PROGRESS_MIN_DELTA = 0.05;
|
|
1824
2255
|
var LedgerAdapter = _LedgerAdapter;
|
|
1825
2256
|
|
|
1826
2257
|
// src/connector/LedgerConnectorBase.ts
|
|
1827
2258
|
import {
|
|
1828
2259
|
EConnectorInteraction as EConnectorInteraction4,
|
|
1829
|
-
HardwareErrorCode as
|
|
2260
|
+
HardwareErrorCode as HardwareErrorCode8,
|
|
2261
|
+
isKnownNonTargetHardwareVendor,
|
|
1830
2262
|
serializeConnectorError
|
|
1831
2263
|
} from "@onekeyfe/hwk-adapter-core";
|
|
1832
2264
|
|
|
@@ -2383,7 +2815,7 @@ var SignerManager = class _SignerManager {
|
|
|
2383
2815
|
};
|
|
2384
2816
|
|
|
2385
2817
|
// src/connector/chains/evm.ts
|
|
2386
|
-
import { HardwareErrorCode as
|
|
2818
|
+
import { HardwareErrorCode as HardwareErrorCode4, padHex64, stripHex } from "@onekeyfe/hwk-adapter-core";
|
|
2387
2819
|
|
|
2388
2820
|
// src/connector/chains/utils.ts
|
|
2389
2821
|
import { EConnectorInteraction as EConnectorInteraction2 } from "@onekeyfe/hwk-adapter-core";
|
|
@@ -2425,7 +2857,7 @@ async function evmSignTransaction(ctx, sessionId, params) {
|
|
|
2425
2857
|
new Error(
|
|
2426
2858
|
"Ledger requires a pre-serialized transaction (serializedTx). Provide an RLP-encoded hex string."
|
|
2427
2859
|
),
|
|
2428
|
-
{ code:
|
|
2860
|
+
{ code: HardwareErrorCode4.InvalidParams }
|
|
2429
2861
|
);
|
|
2430
2862
|
}
|
|
2431
2863
|
const signer = await _getEthSigner(ctx, sessionId);
|
|
@@ -2466,7 +2898,7 @@ async function evmSignTypedData(ctx, sessionId, params) {
|
|
|
2466
2898
|
new Error(
|
|
2467
2899
|
'Ledger does not support hash-only EIP-712 signing. Use mode "full" with the complete typed data structure.'
|
|
2468
2900
|
),
|
|
2469
|
-
{ code:
|
|
2901
|
+
{ code: HardwareErrorCode4.MethodNotSupported }
|
|
2470
2902
|
);
|
|
2471
2903
|
}
|
|
2472
2904
|
const signer = await _getEthSigner(ctx, sessionId);
|
|
@@ -2501,7 +2933,7 @@ async function _getEthSigner(ctx, sessionId) {
|
|
|
2501
2933
|
}
|
|
2502
2934
|
|
|
2503
2935
|
// src/connector/chains/btc.ts
|
|
2504
|
-
import { HardwareErrorCode as
|
|
2936
|
+
import { HardwareErrorCode as HardwareErrorCode5, stripHex as stripHex2 } from "@onekeyfe/hwk-adapter-core";
|
|
2505
2937
|
import { Psbt } from "bitcoinjs-lib";
|
|
2506
2938
|
|
|
2507
2939
|
// src/signer/SignerBtc.ts
|
|
@@ -2622,7 +3054,7 @@ function _purposeToTemplate(purpose, DDT) {
|
|
|
2622
3054
|
return DDT.TAPROOT;
|
|
2623
3055
|
default:
|
|
2624
3056
|
throw Object.assign(new Error(`Unsupported BTC purpose: m/${purpose ?? "<undefined>"}'`), {
|
|
2625
|
-
code:
|
|
3057
|
+
code: HardwareErrorCode5.InvalidParams
|
|
2626
3058
|
});
|
|
2627
3059
|
}
|
|
2628
3060
|
}
|
|
@@ -2678,7 +3110,7 @@ async function btcSignTransaction(ctx, sessionId, params) {
|
|
|
2678
3110
|
if (!params.psbt) {
|
|
2679
3111
|
throw Object.assign(
|
|
2680
3112
|
new Error("Ledger requires PSBT format for BTC transaction signing. Provide params.psbt."),
|
|
2681
|
-
{ code:
|
|
3113
|
+
{ code: HardwareErrorCode5.InvalidParams }
|
|
2682
3114
|
);
|
|
2683
3115
|
}
|
|
2684
3116
|
const btcSigner = await _createBtcSigner(ctx, sessionId);
|
|
@@ -2703,7 +3135,7 @@ async function btcSignTransaction(ctx, sessionId, params) {
|
|
|
2703
3135
|
async function btcSignPsbt(ctx, sessionId, params) {
|
|
2704
3136
|
if (!params.psbt) {
|
|
2705
3137
|
throw Object.assign(new Error("btcSignPsbt requires params.psbt"), {
|
|
2706
|
-
code:
|
|
3138
|
+
code: HardwareErrorCode5.InvalidParams
|
|
2707
3139
|
});
|
|
2708
3140
|
}
|
|
2709
3141
|
const btcSigner = await _createBtcSigner(ctx, sessionId);
|
|
@@ -2948,7 +3380,7 @@ async function _createSolSigner(ctx, sessionId) {
|
|
|
2948
3380
|
}
|
|
2949
3381
|
|
|
2950
3382
|
// src/connector/chains/tron.ts
|
|
2951
|
-
import { HardwareErrorCode as
|
|
3383
|
+
import { HardwareErrorCode as HardwareErrorCode7 } from "@onekeyfe/hwk-adapter-core";
|
|
2952
3384
|
import Trx from "@ledgerhq/hw-app-trx";
|
|
2953
3385
|
|
|
2954
3386
|
// src/connector/chains/legacyChainCall.ts
|
|
@@ -2961,7 +3393,7 @@ import {
|
|
|
2961
3393
|
OpenAppCommand,
|
|
2962
3394
|
isSuccessCommandResult
|
|
2963
3395
|
} from "@ledgerhq/device-management-kit";
|
|
2964
|
-
import { HardwareErrorCode as
|
|
3396
|
+
import { HardwareErrorCode as HardwareErrorCode6 } from "@onekeyfe/hwk-adapter-core";
|
|
2965
3397
|
var APP_NAME_MAP = {
|
|
2966
3398
|
ETH: "Ethereum",
|
|
2967
3399
|
BTC: "Bitcoin",
|
|
@@ -3065,15 +3497,30 @@ var AppManager = class {
|
|
|
3065
3497
|
command: new OpenAppCommand({ appName })
|
|
3066
3498
|
});
|
|
3067
3499
|
if (!isSuccessCommandResult(result)) {
|
|
3068
|
-
const
|
|
3069
|
-
const
|
|
3070
|
-
|
|
3500
|
+
const dmkErr = result.error;
|
|
3501
|
+
const errorCode = "errorCode" in dmkErr && dmkErr.errorCode != null ? String(dmkErr.errorCode) : "";
|
|
3502
|
+
const message = "message" in dmkErr && typeof dmkErr.message === "string" ? dmkErr.message : "";
|
|
3503
|
+
debugLog(
|
|
3504
|
+
"[AppManager] openApp failed:",
|
|
3505
|
+
appName,
|
|
3506
|
+
"errorCode:",
|
|
3507
|
+
errorCode,
|
|
3508
|
+
"tag:",
|
|
3509
|
+
dmkErr._tag
|
|
3510
|
+
);
|
|
3511
|
+
let code;
|
|
3512
|
+
if (errorCode === "6807" || /unknown application/i.test(message)) {
|
|
3513
|
+
code = HardwareErrorCode6.AppNotInstalled;
|
|
3514
|
+
} else if (errorCode === "5501" || dmkErr._tag === "ActionRefusedError") {
|
|
3515
|
+
code = HardwareErrorCode6.UserRejected;
|
|
3516
|
+
}
|
|
3071
3517
|
throw Object.assign(new Error(`Failed to open "${appName}"`), {
|
|
3072
3518
|
_tag: ERROR_TAG.OpenAppCommand,
|
|
3073
|
-
code
|
|
3074
|
-
errorCode
|
|
3075
|
-
statusCode,
|
|
3076
|
-
appName
|
|
3519
|
+
code,
|
|
3520
|
+
errorCode,
|
|
3521
|
+
statusCode: errorCode,
|
|
3522
|
+
appName,
|
|
3523
|
+
originalError: dmkErr
|
|
3077
3524
|
});
|
|
3078
3525
|
}
|
|
3079
3526
|
}
|
|
@@ -3252,7 +3699,7 @@ async function tronSignTransaction(ctx, sessionId, params) {
|
|
|
3252
3699
|
if (!params.rawTxHex) {
|
|
3253
3700
|
throw Object.assign(
|
|
3254
3701
|
new Error("TRON signing requires a protobuf-encoded raw transaction hex (rawTxHex)."),
|
|
3255
|
-
{ code:
|
|
3702
|
+
{ code: HardwareErrorCode7.InvalidParams }
|
|
3256
3703
|
);
|
|
3257
3704
|
}
|
|
3258
3705
|
const path = normalizePath(params.path);
|
|
@@ -3413,6 +3860,22 @@ var DeviceApps = class {
|
|
|
3413
3860
|
);
|
|
3414
3861
|
return result.filter((a) => a !== null).map(applicationToMetadata);
|
|
3415
3862
|
}
|
|
3863
|
+
/** Installed app names via ListApps APDU. Offline (no manager-api), but still requires unlock + dashboard. */
|
|
3864
|
+
async listInstalledNames(options) {
|
|
3865
|
+
const action = this._dmk.executeDeviceAction({
|
|
3866
|
+
sessionId: this._sessionId,
|
|
3867
|
+
deviceAction: new this._ledgerKit.ListAppsDeviceAction({
|
|
3868
|
+
input: { unlockTimeout: options?.unlockTimeout }
|
|
3869
|
+
})
|
|
3870
|
+
});
|
|
3871
|
+
const result = await deviceActionToPromise(
|
|
3872
|
+
action,
|
|
3873
|
+
this.onInteraction,
|
|
3874
|
+
void 0,
|
|
3875
|
+
this.onRegisterCanceller
|
|
3876
|
+
);
|
|
3877
|
+
return result.map((entry) => entry?.appName).filter((name) => typeof name === "string" && name.length > 0);
|
|
3878
|
+
}
|
|
3416
3879
|
// Catalog lookup via custom device action — DMK has no typed wrapper for this.
|
|
3417
3880
|
async listAvailable() {
|
|
3418
3881
|
const customAction = new ListAvailableAppsDeviceAction({
|
|
@@ -3476,6 +3939,22 @@ var DeviceApps = class {
|
|
|
3476
3939
|
async install(appName, onProgress, options) {
|
|
3477
3940
|
if (!appName) throw new Error("DeviceApps.install: appName is required");
|
|
3478
3941
|
debugLog("[DeviceApps] install:", appName);
|
|
3942
|
+
const refreshAction = this._dmk.executeDeviceAction({
|
|
3943
|
+
sessionId: this._sessionId,
|
|
3944
|
+
deviceAction: new this._ledgerKit.GetDeviceMetadataDeviceAction({
|
|
3945
|
+
input: {
|
|
3946
|
+
useSecureChannel: true,
|
|
3947
|
+
forceUpdate: true,
|
|
3948
|
+
unlockTimeout: options?.unlockTimeout
|
|
3949
|
+
}
|
|
3950
|
+
})
|
|
3951
|
+
});
|
|
3952
|
+
await deviceActionToPromise(
|
|
3953
|
+
refreshAction,
|
|
3954
|
+
this.onInteraction,
|
|
3955
|
+
INSTALL_TIMEOUT_MS,
|
|
3956
|
+
this.onRegisterCanceller
|
|
3957
|
+
);
|
|
3479
3958
|
const action = this._dmk.executeDeviceAction({
|
|
3480
3959
|
sessionId: this._sessionId,
|
|
3481
3960
|
deviceAction: new this._ledgerKit.InstallOrUpdateAppsDeviceAction({
|
|
@@ -3553,7 +4032,7 @@ var METHOD_PREFIX_TO_APP_NAME = {
|
|
|
3553
4032
|
tron: "Tron"
|
|
3554
4033
|
};
|
|
3555
4034
|
var HARDWARE_ERROR_CODE_VALUES = new Set(
|
|
3556
|
-
Object.values(
|
|
4035
|
+
Object.values(HardwareErrorCode8).filter((value) => typeof value === "number")
|
|
3557
4036
|
);
|
|
3558
4037
|
var BLE_CONNECT_SCAN_TIMEOUT_MS = 1500;
|
|
3559
4038
|
async function defaultLedgerKitImporter(pkg) {
|
|
@@ -3676,7 +4155,7 @@ var LedgerConnectorBase = class {
|
|
|
3676
4155
|
async searchDevices() {
|
|
3677
4156
|
const dm = await this._getDeviceManager();
|
|
3678
4157
|
const descriptors = await this._discoverDescriptors(dm);
|
|
3679
|
-
const resolvedDescriptors = descriptors.map((d) => ({
|
|
4158
|
+
const resolvedDescriptors = descriptors.filter((d) => !isKnownNonTargetHardwareVendor(d, "ledger")).map((d) => ({
|
|
3680
4159
|
descriptor: d,
|
|
3681
4160
|
connectId: this._resolveConnectId(d)
|
|
3682
4161
|
}));
|
|
@@ -3724,7 +4203,7 @@ var LedgerConnectorBase = class {
|
|
|
3724
4203
|
`Ledger BLE connect did not return within ${HANG_CEILING_MS / 6e4}min \u2014 DMK hang fallback.`
|
|
3725
4204
|
);
|
|
3726
4205
|
err._tag = ERROR_TAG.BlePairingTimeout;
|
|
3727
|
-
err.code =
|
|
4206
|
+
err.code = HardwareErrorCode8.BlePairingTimeout;
|
|
3728
4207
|
reject(err);
|
|
3729
4208
|
}, HANG_CEILING_MS);
|
|
3730
4209
|
});
|
|
@@ -3757,7 +4236,7 @@ var LedgerConnectorBase = class {
|
|
|
3757
4236
|
"Ledger device is not currently advertising. Wake up and unlock the device, keep it nearby, then try again."
|
|
3758
4237
|
);
|
|
3759
4238
|
err._tag = ERROR_TAG.DeviceNotAdvertising;
|
|
3760
|
-
err.code =
|
|
4239
|
+
err.code = HardwareErrorCode8.DeviceNotFound;
|
|
3761
4240
|
throw err;
|
|
3762
4241
|
};
|
|
3763
4242
|
const doConnect = async (path) => {
|
|
@@ -3821,7 +4300,7 @@ var LedgerConnectorBase = class {
|
|
|
3821
4300
|
"Ledger Bluetooth pairing failed. Make sure the device is unlocked and nearby, then try again."
|
|
3822
4301
|
);
|
|
3823
4302
|
wrapped._tag = ERROR_TAG.BleGattBondingFailed;
|
|
3824
|
-
wrapped.code =
|
|
4303
|
+
wrapped.code = HardwareErrorCode8.BlePairingTimeout;
|
|
3825
4304
|
wrapped.originalError = err;
|
|
3826
4305
|
throw wrapped;
|
|
3827
4306
|
}
|
|
@@ -3899,7 +4378,7 @@ var LedgerConnectorBase = class {
|
|
|
3899
4378
|
this._unwatchSessionState(sessionId);
|
|
3900
4379
|
this._signerManager?.invalidate(sessionId);
|
|
3901
4380
|
this._cancellers.get(sessionId)?.({
|
|
3902
|
-
code:
|
|
4381
|
+
code: HardwareErrorCode8.DeviceDisconnected,
|
|
3903
4382
|
tag: "DeviceDisconnected",
|
|
3904
4383
|
message: "Device disconnected"
|
|
3905
4384
|
});
|
|
@@ -3925,7 +4404,7 @@ var LedgerConnectorBase = class {
|
|
|
3925
4404
|
success: false,
|
|
3926
4405
|
error: serializeConnectorError(
|
|
3927
4406
|
Object.assign(new Error("Ledger app is unresponsive"), {
|
|
3928
|
-
code:
|
|
4407
|
+
code: HardwareErrorCode8.DeviceAppStuck,
|
|
3929
4408
|
_tag: ERROR_TAG.DeviceAppStuck,
|
|
3930
4409
|
originalError: err
|
|
3931
4410
|
})
|
|
@@ -3937,7 +4416,7 @@ var LedgerConnectorBase = class {
|
|
|
3937
4416
|
success: false,
|
|
3938
4417
|
error: serializeConnectorError(
|
|
3939
4418
|
Object.assign(new Error("Device communication interrupted, please retry"), {
|
|
3940
|
-
code:
|
|
4419
|
+
code: HardwareErrorCode8.TransportError,
|
|
3941
4420
|
_tag: ERROR_TAG.DeviceTransportStuck,
|
|
3942
4421
|
originalError: err
|
|
3943
4422
|
})
|
|
@@ -4033,6 +4512,17 @@ var LedgerConnectorBase = class {
|
|
|
4033
4512
|
ctx.clearCanceller(sessionId);
|
|
4034
4513
|
}
|
|
4035
4514
|
}
|
|
4515
|
+
case "listInstalledNames": {
|
|
4516
|
+
const apps = await _getDeviceApps(ctx, sessionId);
|
|
4517
|
+
try {
|
|
4518
|
+
return await apps.listInstalledNames(params);
|
|
4519
|
+
} catch (err) {
|
|
4520
|
+
ctx.invalidateSession(sessionId);
|
|
4521
|
+
throw ctx.wrapError(err);
|
|
4522
|
+
} finally {
|
|
4523
|
+
ctx.clearCanceller(sessionId);
|
|
4524
|
+
}
|
|
4525
|
+
}
|
|
4036
4526
|
case "listAvailableApps": {
|
|
4037
4527
|
const apps = await _getDeviceApps(ctx, sessionId);
|
|
4038
4528
|
try {
|