@onekeyfe/hwk-ledger-adapter 1.2.0-alpha.0 → 1.2.0-alpha.2
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 +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +723 -220
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +655 -151
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -4,15 +4,16 @@ import {
|
|
|
4
4
|
DEVICE,
|
|
5
5
|
DeviceJobQueue,
|
|
6
6
|
EConnectorInteraction,
|
|
7
|
-
HardwareErrorCode as
|
|
7
|
+
HardwareErrorCode as HardwareErrorCode3,
|
|
8
8
|
TypedEventEmitter,
|
|
9
9
|
UI_REQUEST,
|
|
10
10
|
UI_REQUEST_PREEMPTED_TAG,
|
|
11
11
|
UiRequestRegistry,
|
|
12
|
+
createHwkError,
|
|
12
13
|
deriveDeviceFingerprint,
|
|
13
|
-
failure,
|
|
14
|
+
failure as failure2,
|
|
14
15
|
rehydrateConnectorError,
|
|
15
|
-
success
|
|
16
|
+
success as success2
|
|
16
17
|
} from "@onekeyfe/hwk-adapter-core";
|
|
17
18
|
|
|
18
19
|
// src/errors.ts
|
|
@@ -35,30 +36,37 @@ var USER_REJECTED_CODES = /* @__PURE__ */ new Set(["6985", "27013"]);
|
|
|
35
36
|
var WRONG_APP_CODES = /* @__PURE__ */ new Set(["6e00", "28160", "6d00", "27904", "6a83", "27267"]);
|
|
36
37
|
var APP_NOT_INSTALLED_CODES = /* @__PURE__ */ new Set(["6807", "26631"]);
|
|
37
38
|
var STEP_BLIND_SIGN_TRANSACTION_FALLBACK = "signer.eth.steps.blindSignTransactionFallback";
|
|
39
|
+
var STEP_DETECT_BLIND_SIGNING = "signer.eth.steps.detectBlindSigning";
|
|
40
|
+
var BLIND_SIGNING_STEPS = /* @__PURE__ */ new Set([
|
|
41
|
+
STEP_BLIND_SIGN_TRANSACTION_FALLBACK,
|
|
42
|
+
STEP_DETECT_BLIND_SIGNING
|
|
43
|
+
]);
|
|
44
|
+
function normalizeApduHex(value) {
|
|
45
|
+
if (typeof value === "number" && Number.isInteger(value) && value >= 0 && value <= 65535) {
|
|
46
|
+
return value.toString(16).padStart(4, "0");
|
|
47
|
+
}
|
|
48
|
+
if (typeof value !== "string") return null;
|
|
49
|
+
const raw = value.toLowerCase().replace(/^0x/, "");
|
|
50
|
+
return /^[0-9a-f]{1,4}$/i.test(raw) ? raw.padStart(4, "0") : null;
|
|
51
|
+
}
|
|
38
52
|
function getEthAppErrorCode(err) {
|
|
39
53
|
if (!err || typeof err !== "object") return null;
|
|
40
54
|
const e = err;
|
|
41
|
-
if (e._tag === ERROR_TAG.EthAppCommand
|
|
42
|
-
|
|
55
|
+
if (e._tag === ERROR_TAG.EthAppCommand) {
|
|
56
|
+
const code = normalizeApduHex(e.errorCode) ?? normalizeApduHex(e.statusCode) ?? normalizeApduHex(e.code);
|
|
57
|
+
if (code) return code;
|
|
43
58
|
}
|
|
44
59
|
const orig = e.originalError;
|
|
45
|
-
if (orig?._tag === ERROR_TAG.EthAppCommand
|
|
46
|
-
return orig.errorCode.
|
|
60
|
+
if (orig?._tag === ERROR_TAG.EthAppCommand) {
|
|
61
|
+
return normalizeApduHex(orig.errorCode) ?? normalizeApduHex(orig.statusCode) ?? normalizeApduHex(orig.code);
|
|
47
62
|
}
|
|
48
63
|
return null;
|
|
49
64
|
}
|
|
50
65
|
function extractApduHex(err) {
|
|
51
66
|
if (!err || typeof err !== "object") return null;
|
|
52
67
|
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
|
-
}
|
|
68
|
+
const direct = normalizeApduHex(e.errorCode) ?? normalizeApduHex(e.statusCode);
|
|
69
|
+
if (direct) return direct;
|
|
62
70
|
if (e.originalError != null) {
|
|
63
71
|
const nested = extractApduHex(e.originalError);
|
|
64
72
|
if (nested) return nested;
|
|
@@ -117,10 +125,15 @@ function classifyEthAppError(err) {
|
|
|
117
125
|
const ethCode = getEthAppErrorCode(err);
|
|
118
126
|
if (!ethCode) return null;
|
|
119
127
|
if (ethCode === "6a80") {
|
|
120
|
-
return
|
|
128
|
+
return hasBlindSigningStep(err) ? HardwareErrorCode.EvmBlindSigningRequired : null;
|
|
121
129
|
}
|
|
122
130
|
return mapEthAppErrorCode(ethCode);
|
|
123
131
|
}
|
|
132
|
+
function classifyBlindSigningDetectionError(err) {
|
|
133
|
+
if (!hasBlindSigningStep(err)) return null;
|
|
134
|
+
if (hasInvalidArgumentCode(err)) return HardwareErrorCode.EvmBlindSigningRequired;
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
124
137
|
var ERROR_TAG = {
|
|
125
138
|
// SDK-mint
|
|
126
139
|
DeviceNotAdvertising: "DeviceNotAdvertisingError",
|
|
@@ -136,6 +149,10 @@ var ERROR_TAG = {
|
|
|
136
149
|
// chain app wedged (APDU 0x6901)
|
|
137
150
|
DeviceTransportStuck: "DeviceTransportStuck",
|
|
138
151
|
// DMK transport queue wedged
|
|
152
|
+
// installApp resolved success but the app is still missing on device —
|
|
153
|
+
// DMK quirk. Surfaced as a distinct tag so callers can tell it apart from
|
|
154
|
+
// the original DMK-thrown AppNotInstalled.
|
|
155
|
+
AppInstallVerifyFailed: "AppInstallVerifyFailedError",
|
|
139
156
|
// DMK-reuse (DMK throws same string; we synthesize too)
|
|
140
157
|
DeviceLocked: "DeviceLockedError",
|
|
141
158
|
DeviceNotRecognized: "DeviceNotRecognizedError",
|
|
@@ -161,7 +178,11 @@ var ERROR_TAG = {
|
|
|
161
178
|
// ble-plx surfaces this when GATT notification setup fails — typical
|
|
162
179
|
// outcome when the user doesn't confirm pairing on the device, or the
|
|
163
180
|
// existing bond is invalid. Observed in production after ~30s.
|
|
164
|
-
PairingRefused: "PairingRefusedError"
|
|
181
|
+
PairingRefused: "PairingRefusedError",
|
|
182
|
+
// DMK remote-network failures (manager-api HTTP / secure-channel WS).
|
|
183
|
+
WebSocketConnection: "WebSocketConnectionError",
|
|
184
|
+
HttpFetch: "FetchError",
|
|
185
|
+
InvalidFirmwareMetadataResponse: "InvalidGetFirmwareMetadataResponseError"
|
|
165
186
|
};
|
|
166
187
|
function isDeviceLockedError(err) {
|
|
167
188
|
if (!err || typeof err !== "object") return false;
|
|
@@ -249,15 +270,30 @@ function hasStatusCode(err, codeSet) {
|
|
|
249
270
|
if (e.error != null && e._tag && hasStatusCode(e.error, codeSet)) return true;
|
|
250
271
|
return false;
|
|
251
272
|
}
|
|
252
|
-
function
|
|
273
|
+
function hasDeviceActionStep(err, step) {
|
|
253
274
|
if (!err || typeof err !== "object") return false;
|
|
254
275
|
const e = err;
|
|
255
|
-
if (e._lastStep ===
|
|
256
|
-
if (Array.isArray(e._deviceActionSteps) && e._deviceActionSteps.includes(
|
|
276
|
+
if (e._lastStep === step) return true;
|
|
277
|
+
if (Array.isArray(e._deviceActionSteps) && e._deviceActionSteps.includes(step)) {
|
|
257
278
|
return true;
|
|
258
279
|
}
|
|
259
|
-
if (e.originalError != null &&
|
|
260
|
-
if (e.error != null && e._tag &&
|
|
280
|
+
if (e.originalError != null && hasDeviceActionStep(e.originalError, step)) return true;
|
|
281
|
+
if (e.error != null && e._tag && hasDeviceActionStep(e.error, step)) return true;
|
|
282
|
+
return false;
|
|
283
|
+
}
|
|
284
|
+
function hasBlindSigningStep(err) {
|
|
285
|
+
for (const step of BLIND_SIGNING_STEPS) {
|
|
286
|
+
if (hasDeviceActionStep(err, step)) return true;
|
|
287
|
+
}
|
|
288
|
+
return false;
|
|
289
|
+
}
|
|
290
|
+
function hasInvalidArgumentCode(err) {
|
|
291
|
+
if (!err || typeof err !== "object") return false;
|
|
292
|
+
const e = err;
|
|
293
|
+
if (e.code === "INVALID_ARGUMENT") return true;
|
|
294
|
+
if (typeof e.message === "string" && e.message.includes("code=INVALID_ARGUMENT")) return true;
|
|
295
|
+
if (e.originalError != null && hasInvalidArgumentCode(e.originalError)) return true;
|
|
296
|
+
if (e.error != null && e._tag && hasInvalidArgumentCode(e.error)) return true;
|
|
261
297
|
return false;
|
|
262
298
|
}
|
|
263
299
|
function isDeviceNotFoundError(err) {
|
|
@@ -286,6 +322,11 @@ function isUserRejectedError(err) {
|
|
|
286
322
|
if (hasStatusCode(err, USER_REJECTED_CODES)) return true;
|
|
287
323
|
return false;
|
|
288
324
|
}
|
|
325
|
+
function isUserAbortedError(err) {
|
|
326
|
+
if (!err || typeof err !== "object") return false;
|
|
327
|
+
const e = err;
|
|
328
|
+
return e._tag === ERROR_TAG.UserAborted;
|
|
329
|
+
}
|
|
289
330
|
function isWrongAppError(err) {
|
|
290
331
|
if (!err || typeof err !== "object") return false;
|
|
291
332
|
const e = err;
|
|
@@ -312,6 +353,20 @@ function isOutOfMemoryError(err) {
|
|
|
312
353
|
const e = err;
|
|
313
354
|
return e._tag === "OutOfMemoryDAError";
|
|
314
355
|
}
|
|
356
|
+
var NETWORK_ERROR_TAGS = /* @__PURE__ */ new Set([
|
|
357
|
+
ERROR_TAG.WebSocketConnection,
|
|
358
|
+
ERROR_TAG.HttpFetch,
|
|
359
|
+
ERROR_TAG.InvalidFirmwareMetadataResponse
|
|
360
|
+
]);
|
|
361
|
+
function isNetworkError(err) {
|
|
362
|
+
if (!err || typeof err !== "object") return false;
|
|
363
|
+
const e = err;
|
|
364
|
+
const tag = e._tag;
|
|
365
|
+
if (typeof tag === "string" && NETWORK_ERROR_TAGS.has(tag)) return true;
|
|
366
|
+
if (e.originalError != null && isNetworkError(e.originalError)) return true;
|
|
367
|
+
if (e.error != null && isNetworkError(e.error)) return true;
|
|
368
|
+
return false;
|
|
369
|
+
}
|
|
315
370
|
function isDeviceDisconnectedError(err) {
|
|
316
371
|
if (!err || typeof err !== "object") return false;
|
|
317
372
|
const e = err;
|
|
@@ -368,6 +423,8 @@ function mapLedgerError(err, opts) {
|
|
|
368
423
|
code = HardwareErrorCode.DeviceBusy;
|
|
369
424
|
} else if (isBlePairingFailureError(err)) {
|
|
370
425
|
code = HardwareErrorCode.BlePairingTimeout;
|
|
426
|
+
} else if (isUserAbortedError(err)) {
|
|
427
|
+
code = HardwareErrorCode.UserAborted;
|
|
371
428
|
} else if (isUserRejectedError(err)) {
|
|
372
429
|
code = HardwareErrorCode.UserRejected;
|
|
373
430
|
} else if (isWrongAppError(err)) {
|
|
@@ -376,12 +433,14 @@ function mapLedgerError(err, opts) {
|
|
|
376
433
|
code = HardwareErrorCode.AppNotInstalled;
|
|
377
434
|
} else if (isOutOfMemoryError(err)) {
|
|
378
435
|
code = HardwareErrorCode.DeviceOutOfMemory;
|
|
436
|
+
} else if (isNetworkError(err)) {
|
|
437
|
+
code = HardwareErrorCode.NetworkError;
|
|
379
438
|
} else if (isDeviceDisconnectedError(err)) {
|
|
380
439
|
code = HardwareErrorCode.DeviceDisconnected;
|
|
381
440
|
} else if (isTimeoutError(err)) {
|
|
382
441
|
code = HardwareErrorCode.OperationTimeout;
|
|
383
442
|
} else {
|
|
384
|
-
const ethMapped = classifyEthAppError(err);
|
|
443
|
+
const ethMapped = classifyEthAppError(err) ?? classifyBlindSigningDetectionError(err);
|
|
385
444
|
const apduHex = ethMapped ? null : extractApduHex(err);
|
|
386
445
|
const chainMapped = apduHex ? mapSolanaAppError(apduHex) ?? mapTronAppError(apduHex) ?? mapBtcAppError(apduHex) : null;
|
|
387
446
|
code = ethMapped ?? chainMapped ?? HardwareErrorCode.UnknownError;
|
|
@@ -391,17 +450,8 @@ function mapLedgerError(err, opts) {
|
|
|
391
450
|
return { code, message: enrichErrorMessage(code, originalMessage), appName };
|
|
392
451
|
}
|
|
393
452
|
|
|
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
|
-
}
|
|
453
|
+
// src/adapter/methods/allNetworkGetAddress.ts
|
|
454
|
+
import { HardwareErrorCode as HardwareErrorCode2, failure, success } from "@onekeyfe/hwk-adapter-core";
|
|
405
455
|
|
|
406
456
|
// src/utils/sdkEventBus.ts
|
|
407
457
|
var listeners = /* @__PURE__ */ new Set();
|
|
@@ -448,6 +498,252 @@ function debugError(...args) {
|
|
|
448
498
|
emitLog("error", ...args);
|
|
449
499
|
}
|
|
450
500
|
|
|
501
|
+
// src/adapter/methods/allNetworkGetAddress.ts
|
|
502
|
+
var LEDGER_BTC_NETWORK_COIN_MAP = {
|
|
503
|
+
tbtc: "Testnet",
|
|
504
|
+
bch: "Bcash",
|
|
505
|
+
doge: "Dogecoin",
|
|
506
|
+
ltc: "Litecoin",
|
|
507
|
+
neurai: "Neurai"
|
|
508
|
+
};
|
|
509
|
+
function createAllNetworkGetAddress({
|
|
510
|
+
callChain,
|
|
511
|
+
getChainFingerprint
|
|
512
|
+
}) {
|
|
513
|
+
return async function allNetworkGetAddress(connectId, _deviceId, params) {
|
|
514
|
+
debugLog("[LedgerAdapter][REQ]", { method: "allNetworkGetAddress", connectId, params });
|
|
515
|
+
const installContext = {};
|
|
516
|
+
const commonParams = {
|
|
517
|
+
autoInstallApp: params.autoInstallApp
|
|
518
|
+
};
|
|
519
|
+
const responses = [];
|
|
520
|
+
const chainFingerprints = /* @__PURE__ */ new Map();
|
|
521
|
+
for (const item of params.bundle) {
|
|
522
|
+
const method = getAllNetworkMethod(item);
|
|
523
|
+
if (!method) {
|
|
524
|
+
responses.push(buildUnsupportedMethodResponse(item));
|
|
525
|
+
} else {
|
|
526
|
+
const chain = getFingerprintChain(method);
|
|
527
|
+
const itemDeviceId = getItemDeviceId(item) ?? chainFingerprints.get(chain) ?? "";
|
|
528
|
+
const normalizedItem = normalizeLedgerAllNetworkItem(method, item);
|
|
529
|
+
const response = await callAllNetworkItem(
|
|
530
|
+
callChain,
|
|
531
|
+
getChainFingerprint,
|
|
532
|
+
connectId,
|
|
533
|
+
itemDeviceId,
|
|
534
|
+
chain,
|
|
535
|
+
method,
|
|
536
|
+
normalizedItem,
|
|
537
|
+
commonParams,
|
|
538
|
+
installContext,
|
|
539
|
+
chainFingerprints
|
|
540
|
+
);
|
|
541
|
+
if (isTopLevelAllNetworkFailure(response)) {
|
|
542
|
+
const code = response.payload?.code ?? HardwareErrorCode2.DeviceMismatch;
|
|
543
|
+
const result2 = failure(
|
|
544
|
+
code,
|
|
545
|
+
response.payload?.error ?? "All-network get-address aborted",
|
|
546
|
+
response.payload?.params
|
|
547
|
+
);
|
|
548
|
+
debugLog("[LedgerAdapter][RES]", {
|
|
549
|
+
method: "allNetworkGetAddress",
|
|
550
|
+
success: false,
|
|
551
|
+
payload: result2
|
|
552
|
+
});
|
|
553
|
+
return result2;
|
|
554
|
+
}
|
|
555
|
+
responses.push(response);
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
const result = success(responses);
|
|
559
|
+
debugLog("[LedgerAdapter][RES]", {
|
|
560
|
+
method: "allNetworkGetAddress",
|
|
561
|
+
success: true,
|
|
562
|
+
payload: result
|
|
563
|
+
});
|
|
564
|
+
return result;
|
|
565
|
+
};
|
|
566
|
+
}
|
|
567
|
+
function isTopLevelAllNetworkFailure(response) {
|
|
568
|
+
if (response.success) {
|
|
569
|
+
return false;
|
|
570
|
+
}
|
|
571
|
+
const code = response.payload?.code;
|
|
572
|
+
return code === HardwareErrorCode2.DeviceMismatch || code === HardwareErrorCode2.UserAborted || code === HardwareErrorCode2.UserRejected;
|
|
573
|
+
}
|
|
574
|
+
function getItemDeviceId(item) {
|
|
575
|
+
const { deviceId } = item;
|
|
576
|
+
return typeof deviceId === "string" && deviceId.length > 0 ? deviceId : void 0;
|
|
577
|
+
}
|
|
578
|
+
function getAllNetworkMethod(item) {
|
|
579
|
+
switch (item.methodName) {
|
|
580
|
+
case "evmGetAddress":
|
|
581
|
+
case "btcGetAddress":
|
|
582
|
+
case "btcGetPublicKey":
|
|
583
|
+
case "solGetAddress":
|
|
584
|
+
case "tronGetAddress":
|
|
585
|
+
return item.methodName;
|
|
586
|
+
default:
|
|
587
|
+
return void 0;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
function buildUnsupportedMethodResponse(item) {
|
|
591
|
+
return {
|
|
592
|
+
...item,
|
|
593
|
+
success: false,
|
|
594
|
+
payload: {
|
|
595
|
+
code: HardwareErrorCode2.InvalidParams,
|
|
596
|
+
error: `Unsupported allNetwork method: ${String(item.methodName)}`
|
|
597
|
+
}
|
|
598
|
+
};
|
|
599
|
+
}
|
|
600
|
+
function normalizeLedgerAllNetworkItem(method, item) {
|
|
601
|
+
if (method !== "btcGetAddress" && method !== "btcGetPublicKey") {
|
|
602
|
+
return item;
|
|
603
|
+
}
|
|
604
|
+
const itemWithCoin = item;
|
|
605
|
+
if (itemWithCoin.coin) {
|
|
606
|
+
return item;
|
|
607
|
+
}
|
|
608
|
+
const coin = LEDGER_BTC_NETWORK_COIN_MAP[item.network];
|
|
609
|
+
return coin ? { ...item, coin } : item;
|
|
610
|
+
}
|
|
611
|
+
async function callAllNetworkItem(callChain, getChainFingerprint, connectId, deviceId, chain, method, item, commonParams, installContext, chainFingerprints) {
|
|
612
|
+
const response = await callAllNetworkMethod(
|
|
613
|
+
callChain,
|
|
614
|
+
connectId,
|
|
615
|
+
deviceId,
|
|
616
|
+
method,
|
|
617
|
+
item,
|
|
618
|
+
commonParams,
|
|
619
|
+
installContext
|
|
620
|
+
);
|
|
621
|
+
if (!response.success) {
|
|
622
|
+
return { ...item, success: false, payload: response.payload };
|
|
623
|
+
}
|
|
624
|
+
const payload = response.payload;
|
|
625
|
+
const fingerprint = deviceId || chainFingerprints.get(chain) || await bootstrapChainFingerprint(getChainFingerprint, connectId, chain);
|
|
626
|
+
if (!fingerprint) {
|
|
627
|
+
return buildFingerprintBootstrapFailure(item, chain);
|
|
628
|
+
}
|
|
629
|
+
chainFingerprints.set(chain, fingerprint);
|
|
630
|
+
return {
|
|
631
|
+
...item,
|
|
632
|
+
success: true,
|
|
633
|
+
payload: {
|
|
634
|
+
...payload,
|
|
635
|
+
chainFingerprint: fingerprint,
|
|
636
|
+
chainFingerprintChain: chain
|
|
637
|
+
}
|
|
638
|
+
};
|
|
639
|
+
}
|
|
640
|
+
async function bootstrapChainFingerprint(getChainFingerprint, connectId, chain) {
|
|
641
|
+
const response = await getChainFingerprint(connectId, chain);
|
|
642
|
+
return response.success ? response.payload : "";
|
|
643
|
+
}
|
|
644
|
+
function buildFingerprintBootstrapFailure(item, chain) {
|
|
645
|
+
return {
|
|
646
|
+
...item,
|
|
647
|
+
success: false,
|
|
648
|
+
payload: {
|
|
649
|
+
code: HardwareErrorCode2.DeviceMismatch,
|
|
650
|
+
error: `Could not establish chain fingerprint for ${chain} after device call; refusing to return unverifiable result. Please retry.`
|
|
651
|
+
}
|
|
652
|
+
};
|
|
653
|
+
}
|
|
654
|
+
function getFingerprintChain(method) {
|
|
655
|
+
switch (method) {
|
|
656
|
+
case "evmGetAddress":
|
|
657
|
+
return "evm";
|
|
658
|
+
case "btcGetAddress":
|
|
659
|
+
case "btcGetPublicKey":
|
|
660
|
+
return "btc";
|
|
661
|
+
case "solGetAddress":
|
|
662
|
+
return "sol";
|
|
663
|
+
case "tronGetAddress":
|
|
664
|
+
return "tron";
|
|
665
|
+
default:
|
|
666
|
+
throw Object.assign(new Error(`Unsupported allNetwork method: ${method}`), {
|
|
667
|
+
code: HardwareErrorCode2.InvalidParams
|
|
668
|
+
});
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
async function callAllNetworkMethod(callChain, connectId, deviceId, method, item, commonParams, installContext) {
|
|
672
|
+
switch (method) {
|
|
673
|
+
case "evmGetAddress":
|
|
674
|
+
return callChain(
|
|
675
|
+
connectId,
|
|
676
|
+
deviceId,
|
|
677
|
+
"evm",
|
|
678
|
+
"evmGetAddress",
|
|
679
|
+
item,
|
|
680
|
+
commonParams,
|
|
681
|
+
false,
|
|
682
|
+
installContext
|
|
683
|
+
);
|
|
684
|
+
case "btcGetAddress":
|
|
685
|
+
return callChain(
|
|
686
|
+
connectId,
|
|
687
|
+
deviceId,
|
|
688
|
+
"btc",
|
|
689
|
+
"btcGetAddress",
|
|
690
|
+
item,
|
|
691
|
+
commonParams,
|
|
692
|
+
false,
|
|
693
|
+
installContext
|
|
694
|
+
);
|
|
695
|
+
case "btcGetPublicKey":
|
|
696
|
+
return callChain(
|
|
697
|
+
connectId,
|
|
698
|
+
deviceId,
|
|
699
|
+
"btc",
|
|
700
|
+
"btcGetPublicKey",
|
|
701
|
+
item,
|
|
702
|
+
commonParams,
|
|
703
|
+
false,
|
|
704
|
+
installContext
|
|
705
|
+
);
|
|
706
|
+
case "solGetAddress":
|
|
707
|
+
return callChain(
|
|
708
|
+
connectId,
|
|
709
|
+
deviceId,
|
|
710
|
+
"sol",
|
|
711
|
+
"solGetAddress",
|
|
712
|
+
item,
|
|
713
|
+
commonParams,
|
|
714
|
+
false,
|
|
715
|
+
installContext
|
|
716
|
+
);
|
|
717
|
+
case "tronGetAddress":
|
|
718
|
+
return callChain(
|
|
719
|
+
connectId,
|
|
720
|
+
deviceId,
|
|
721
|
+
"tron",
|
|
722
|
+
"tronGetAddress",
|
|
723
|
+
item,
|
|
724
|
+
commonParams,
|
|
725
|
+
false,
|
|
726
|
+
installContext
|
|
727
|
+
);
|
|
728
|
+
default:
|
|
729
|
+
throw Object.assign(new Error(`Unsupported allNetwork method: ${method}`), {
|
|
730
|
+
code: HardwareErrorCode2.InvalidParams
|
|
731
|
+
});
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
// src/utils/ledgerDmkTransport.ts
|
|
736
|
+
function isLedgerDmkBleTransport(transport) {
|
|
737
|
+
const normalized = transport?.toUpperCase();
|
|
738
|
+
return normalized === "BLE" || normalized?.endsWith("_BLE") === true;
|
|
739
|
+
}
|
|
740
|
+
function isLedgerBleConnectionType(connectionType) {
|
|
741
|
+
return connectionType === "ble";
|
|
742
|
+
}
|
|
743
|
+
function isLedgerBleDescriptor(connectionType, descriptor) {
|
|
744
|
+
return isLedgerBleConnectionType(connectionType) || isLedgerDmkBleTransport(descriptor.transport);
|
|
745
|
+
}
|
|
746
|
+
|
|
451
747
|
// src/adapter/LedgerAdapter.ts
|
|
452
748
|
function formatDeviceMismatchError(expected, actual) {
|
|
453
749
|
return `Wrong device: expected ${expected}, got ${actual}`;
|
|
@@ -475,6 +771,11 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
475
771
|
this._btcHighIndexConfirmedThisSession = false;
|
|
476
772
|
// Shared across concurrent callers — only `cancel()` aborts.
|
|
477
773
|
this._doConnectAbortController = null;
|
|
774
|
+
this._installProgressLastEmittedValue = -Infinity;
|
|
775
|
+
this.allNetworkGetAddress = createAllNetworkGetAddress({
|
|
776
|
+
callChain: this.callChain.bind(this),
|
|
777
|
+
getChainFingerprint: (connectId, chain) => this.getChainFingerprint(connectId, "", chain)
|
|
778
|
+
});
|
|
478
779
|
// ---------------------------------------------------------------------------
|
|
479
780
|
// Private helpers
|
|
480
781
|
// ---------------------------------------------------------------------------
|
|
@@ -528,12 +829,23 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
528
829
|
);
|
|
529
830
|
return;
|
|
530
831
|
}
|
|
832
|
+
const { appName, progress } = event.payload;
|
|
833
|
+
const key = `${connectId}:${appName}`;
|
|
834
|
+
if (this._installProgressLastKey !== key || this._installProgressLastEmittedValue >= 1) {
|
|
835
|
+
this._installProgressLastEmittedValue = -Infinity;
|
|
836
|
+
this._installProgressLastKey = key;
|
|
837
|
+
}
|
|
838
|
+
const delta = progress - this._installProgressLastEmittedValue;
|
|
839
|
+
if (delta < _LedgerAdapter.APP_INSTALL_PROGRESS_MIN_DELTA && progress < 1) {
|
|
840
|
+
return;
|
|
841
|
+
}
|
|
842
|
+
this._installProgressLastEmittedValue = progress;
|
|
531
843
|
this.emitter.emit("ui-event", {
|
|
532
844
|
type: EConnectorInteraction.AppInstallProgress,
|
|
533
845
|
payload: {
|
|
534
846
|
connectId,
|
|
535
|
-
appName
|
|
536
|
-
progress
|
|
847
|
+
appName,
|
|
848
|
+
progress
|
|
537
849
|
}
|
|
538
850
|
});
|
|
539
851
|
return;
|
|
@@ -590,30 +902,42 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
590
902
|
// Device management
|
|
591
903
|
// ---------------------------------------------------------------------------
|
|
592
904
|
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));
|
|
905
|
+
debugLog("[LedgerAdapter][REQ]", { method: "searchDevices", params: options });
|
|
906
|
+
try {
|
|
907
|
+
if (options?.resetSession) {
|
|
908
|
+
this._doConnectAbortController?.abort();
|
|
909
|
+
this._sessions.clear();
|
|
910
|
+
this._connectingPromise = null;
|
|
911
|
+
this._doConnectAbortController = null;
|
|
912
|
+
this._btcHighIndexConfirmedThisSession = false;
|
|
606
913
|
}
|
|
607
|
-
}
|
|
608
|
-
if (this._discoveredDevices.size === 0) {
|
|
609
914
|
await this._ensureDevicePermission();
|
|
915
|
+
const devices = await this.connector.searchDevices();
|
|
916
|
+
this._discoveredDevices.clear();
|
|
917
|
+
for (const d of devices) {
|
|
918
|
+
if (d.connectId) {
|
|
919
|
+
this._discoveredDevices.set(d.connectId, this.connectorDeviceToDeviceInfo(d));
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
if (this._discoveredDevices.size === 0) {
|
|
923
|
+
await this._ensureDevicePermission();
|
|
924
|
+
}
|
|
925
|
+
const result = Array.from(this._discoveredDevices.values());
|
|
926
|
+
debugLog("[LedgerAdapter][RES]", {
|
|
927
|
+
method: "searchDevices",
|
|
928
|
+
success: true,
|
|
929
|
+
payload: result
|
|
930
|
+
});
|
|
931
|
+
return result;
|
|
932
|
+
} catch (err) {
|
|
933
|
+
const e = err;
|
|
934
|
+
debugLog("[LedgerAdapter][RES]", {
|
|
935
|
+
method: "searchDevices",
|
|
936
|
+
success: false,
|
|
937
|
+
error: { message: e?.message, _tag: e?._tag, code: e?.code ?? e?.errorCode }
|
|
938
|
+
});
|
|
939
|
+
throw err;
|
|
610
940
|
}
|
|
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
941
|
}
|
|
618
942
|
// USB single-session invariant: evict all sessions, best-effort (see connectDevice).
|
|
619
943
|
async _evictAllSessions() {
|
|
@@ -629,14 +953,15 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
629
953
|
}
|
|
630
954
|
static _createDeviceBusyError(method) {
|
|
631
955
|
return Object.assign(new Error(`Ledger device is busy while calling ${method}`), {
|
|
632
|
-
code:
|
|
956
|
+
code: HardwareErrorCode3.DeviceBusy
|
|
633
957
|
});
|
|
634
958
|
}
|
|
635
959
|
async connectDevice(connectId) {
|
|
960
|
+
debugLog("[LedgerAdapter][REQ]", { method: "connectDevice", connectId, params: { connectId } });
|
|
636
961
|
try {
|
|
637
962
|
if (isLedgerBleConnectionType(this.connector.connectionType) && !connectId) {
|
|
638
963
|
throw Object.assign(new Error("Ledger BLE connectId is required."), {
|
|
639
|
-
code:
|
|
964
|
+
code: HardwareErrorCode3.DeviceNotFound
|
|
640
965
|
});
|
|
641
966
|
}
|
|
642
967
|
if (!isLedgerBleConnectionType(this.connector.connectionType)) {
|
|
@@ -648,28 +973,79 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
648
973
|
if (session.deviceInfo) {
|
|
649
974
|
this._discoveredDevices.set(connectId, session.deviceInfo);
|
|
650
975
|
}
|
|
651
|
-
|
|
976
|
+
const result = success2(connectId);
|
|
977
|
+
debugLog("[LedgerAdapter][RES]", { method: "connectDevice", success: true, payload: result });
|
|
978
|
+
return result;
|
|
652
979
|
} catch (err) {
|
|
653
|
-
|
|
980
|
+
const failureResult = this.errorToFailure(err);
|
|
981
|
+
debugLog("[LedgerAdapter][RES]", {
|
|
982
|
+
method: "connectDevice",
|
|
983
|
+
success: false,
|
|
984
|
+
payload: failureResult
|
|
985
|
+
});
|
|
986
|
+
return failureResult;
|
|
654
987
|
}
|
|
655
988
|
}
|
|
656
989
|
async disconnectDevice(connectId) {
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
990
|
+
debugLog("[LedgerAdapter][REQ]", {
|
|
991
|
+
method: "disconnectDevice",
|
|
992
|
+
connectId,
|
|
993
|
+
params: { connectId }
|
|
994
|
+
});
|
|
995
|
+
try {
|
|
996
|
+
const sessionId = this._sessions.get(connectId);
|
|
997
|
+
if (sessionId) {
|
|
998
|
+
await this.connector.disconnect(sessionId);
|
|
999
|
+
this._sessions.delete(connectId);
|
|
1000
|
+
}
|
|
1001
|
+
debugLog("[LedgerAdapter][RES]", { method: "disconnectDevice", success: true });
|
|
1002
|
+
} catch (err) {
|
|
1003
|
+
const e = err;
|
|
1004
|
+
debugLog("[LedgerAdapter][RES]", {
|
|
1005
|
+
method: "disconnectDevice",
|
|
1006
|
+
success: false,
|
|
1007
|
+
error: { message: e?.message, _tag: e?._tag, code: e?.code ?? e?.errorCode }
|
|
1008
|
+
});
|
|
1009
|
+
throw err;
|
|
661
1010
|
}
|
|
662
1011
|
}
|
|
663
1012
|
async getDeviceInfo(connectId, deviceId) {
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
1013
|
+
debugLog("[LedgerAdapter][REQ]", {
|
|
1014
|
+
method: "getDeviceInfo",
|
|
1015
|
+
connectId,
|
|
1016
|
+
params: { connectId, deviceId }
|
|
1017
|
+
});
|
|
1018
|
+
try {
|
|
1019
|
+
await this._ensureDevicePermission(connectId, deviceId);
|
|
1020
|
+
const cached = this._discoveredDevices.get(connectId) ?? Array.from(this._discoveredDevices.values()).find((d) => d.deviceId === deviceId);
|
|
1021
|
+
if (cached) {
|
|
1022
|
+
const result = success2(cached);
|
|
1023
|
+
debugLog("[LedgerAdapter][RES]", {
|
|
1024
|
+
method: "getDeviceInfo",
|
|
1025
|
+
success: true,
|
|
1026
|
+
payload: result
|
|
1027
|
+
});
|
|
1028
|
+
return result;
|
|
1029
|
+
}
|
|
1030
|
+
const notFound = failure2(
|
|
1031
|
+
HardwareErrorCode3.DeviceNotFound,
|
|
1032
|
+
"Device not found in cache. Call searchDevices() or wait for a device-connected event first."
|
|
1033
|
+
);
|
|
1034
|
+
debugLog("[LedgerAdapter][RES]", {
|
|
1035
|
+
method: "getDeviceInfo",
|
|
1036
|
+
success: false,
|
|
1037
|
+
payload: notFound
|
|
1038
|
+
});
|
|
1039
|
+
return notFound;
|
|
1040
|
+
} catch (err) {
|
|
1041
|
+
const e = err;
|
|
1042
|
+
debugLog("[LedgerAdapter][RES]", {
|
|
1043
|
+
method: "getDeviceInfo",
|
|
1044
|
+
success: false,
|
|
1045
|
+
error: { message: e?.message, _tag: e?._tag, code: e?.code ?? e?.errorCode }
|
|
1046
|
+
});
|
|
1047
|
+
throw err;
|
|
668
1048
|
}
|
|
669
|
-
return failure(
|
|
670
|
-
HardwareErrorCode2.DeviceNotFound,
|
|
671
|
-
"Device not found in cache. Call searchDevices() or wait for a device-connected event first."
|
|
672
|
-
);
|
|
673
1049
|
}
|
|
674
1050
|
getSupportedChains() {
|
|
675
1051
|
return ["evm", "btc", "sol", "tron"];
|
|
@@ -677,7 +1053,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
677
1053
|
// ---------------------------------------------------------------------------
|
|
678
1054
|
// Chain call helper
|
|
679
1055
|
// ---------------------------------------------------------------------------
|
|
680
|
-
async callChain(connectId, deviceId, chain, method, params, commonParams, skipFingerprint = false) {
|
|
1056
|
+
async callChain(connectId, deviceId, chain, method, params, commonParams, skipFingerprint = false, installContext) {
|
|
681
1057
|
try {
|
|
682
1058
|
const result = await this.connectorCall(
|
|
683
1059
|
connectId,
|
|
@@ -689,9 +1065,10 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
689
1065
|
skipFingerprint
|
|
690
1066
|
},
|
|
691
1067
|
void 0,
|
|
692
|
-
commonParams
|
|
1068
|
+
commonParams,
|
|
1069
|
+
installContext
|
|
693
1070
|
);
|
|
694
|
-
return
|
|
1071
|
+
return success2(result);
|
|
695
1072
|
} catch (err) {
|
|
696
1073
|
return this.errorToFailure(err);
|
|
697
1074
|
}
|
|
@@ -876,7 +1253,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
876
1253
|
async installApp(connectId, appName) {
|
|
877
1254
|
try {
|
|
878
1255
|
await this.connectorCall(connectId, "installApp", { appName });
|
|
879
|
-
return
|
|
1256
|
+
return success2(void 0);
|
|
880
1257
|
} catch (err) {
|
|
881
1258
|
return this.errorToFailure(err);
|
|
882
1259
|
}
|
|
@@ -884,7 +1261,16 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
884
1261
|
async listInstalledApps(connectId) {
|
|
885
1262
|
try {
|
|
886
1263
|
const result = await this.connectorCall(connectId, "listInstalledApps", {});
|
|
887
|
-
return
|
|
1264
|
+
return success2(result);
|
|
1265
|
+
} catch (err) {
|
|
1266
|
+
return this.errorToFailure(err);
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
// Offline app-presence + unlock probe. No manager-api catalog (unlike listInstalledApps).
|
|
1270
|
+
async listInstalledNames(connectId) {
|
|
1271
|
+
try {
|
|
1272
|
+
const result = await this.connectorCall(connectId, "listInstalledNames", {});
|
|
1273
|
+
return success2(result);
|
|
888
1274
|
} catch (err) {
|
|
889
1275
|
return this.errorToFailure(err);
|
|
890
1276
|
}
|
|
@@ -892,7 +1278,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
892
1278
|
async listAvailableApps(connectId) {
|
|
893
1279
|
try {
|
|
894
1280
|
const result = await this.connectorCall(connectId, "listAvailableApps", {});
|
|
895
|
-
return
|
|
1281
|
+
return success2(result);
|
|
896
1282
|
} catch (err) {
|
|
897
1283
|
return this.errorToFailure(err);
|
|
898
1284
|
}
|
|
@@ -900,7 +1286,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
900
1286
|
async getLedgerFirmwareVersion(connectId) {
|
|
901
1287
|
try {
|
|
902
1288
|
const result = await this.connectorCall(connectId, "getFirmwareVersion", {});
|
|
903
|
-
return
|
|
1289
|
+
return success2(result);
|
|
904
1290
|
} catch (err) {
|
|
905
1291
|
return this.errorToFailure(err);
|
|
906
1292
|
}
|
|
@@ -908,7 +1294,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
908
1294
|
async getLedgerDeviceInfo(connectId) {
|
|
909
1295
|
try {
|
|
910
1296
|
const result = await this.connectorCall(connectId, "getDeviceInfo", {});
|
|
911
|
-
return
|
|
1297
|
+
return success2(result);
|
|
912
1298
|
} catch (err) {
|
|
913
1299
|
return this.errorToFailure(err);
|
|
914
1300
|
}
|
|
@@ -921,7 +1307,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
921
1307
|
}
|
|
922
1308
|
cancel(connectId) {
|
|
923
1309
|
const userAbortReason = Object.assign(new Error("User aborted operation"), {
|
|
924
|
-
code:
|
|
1310
|
+
code: HardwareErrorCode3.UserAborted,
|
|
925
1311
|
_tag: ERROR_TAG.UserAborted
|
|
926
1312
|
});
|
|
927
1313
|
this._lastCancelReason = userAbortReason;
|
|
@@ -955,7 +1341,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
955
1341
|
chain,
|
|
956
1342
|
(method, params) => this.connectorCall(connectId, method, params, void 0, deviceId)
|
|
957
1343
|
);
|
|
958
|
-
return
|
|
1344
|
+
return success2(fingerprint);
|
|
959
1345
|
} catch (err) {
|
|
960
1346
|
debugError("[LedgerAdapter] getChainFingerprint error:", chain, err);
|
|
961
1347
|
return this.errorToFailure(err);
|
|
@@ -978,7 +1364,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
978
1364
|
return { success: false, expected: deviceId, actual: fingerprint };
|
|
979
1365
|
} catch (err) {
|
|
980
1366
|
const mapped = mapLedgerError(err);
|
|
981
|
-
if (mapped.code ===
|
|
1367
|
+
if (mapped.code === HardwareErrorCode3.WrongApp || mapped.code === HardwareErrorCode3.DeviceLocked) {
|
|
982
1368
|
return { success: true };
|
|
983
1369
|
}
|
|
984
1370
|
throw err;
|
|
@@ -1058,14 +1444,14 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1058
1444
|
});
|
|
1059
1445
|
throw Object.assign(new Error("User cancelled Ledger connection"), {
|
|
1060
1446
|
_tag: ERROR_TAG.UserAborted,
|
|
1061
|
-
code:
|
|
1447
|
+
code: HardwareErrorCode3.UserAborted,
|
|
1062
1448
|
cause: err
|
|
1063
1449
|
});
|
|
1064
1450
|
}
|
|
1065
1451
|
if (!payload?.confirmed) {
|
|
1066
1452
|
throw Object.assign(new Error("User cancelled Ledger connection"), {
|
|
1067
1453
|
_tag: ERROR_TAG.UserAborted,
|
|
1068
|
-
code:
|
|
1454
|
+
code: HardwareErrorCode3.UserAborted
|
|
1069
1455
|
});
|
|
1070
1456
|
}
|
|
1071
1457
|
await new Promise((resolve) => {
|
|
@@ -1144,7 +1530,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1144
1530
|
if (signal.aborted) _LedgerAdapter._throwIfAborted(signal);
|
|
1145
1531
|
if (isLedgerBleConnectionType(this.connector.connectionType) && !connectId) {
|
|
1146
1532
|
throw Object.assign(new Error("Ledger BLE connectId is required."), {
|
|
1147
|
-
code:
|
|
1533
|
+
code: HardwareErrorCode3.DeviceNotFound
|
|
1148
1534
|
});
|
|
1149
1535
|
}
|
|
1150
1536
|
if (connectId && this._sessions.has(connectId)) return connectId;
|
|
@@ -1154,7 +1540,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1154
1540
|
new Error(
|
|
1155
1541
|
"Ledger USB session invariant violated: more than one session is active. Please reconnect the device."
|
|
1156
1542
|
),
|
|
1157
|
-
{ code:
|
|
1543
|
+
{ code: HardwareErrorCode3.DeviceOneDeviceOnly }
|
|
1158
1544
|
);
|
|
1159
1545
|
}
|
|
1160
1546
|
return this._sessions.keys().next().value;
|
|
@@ -1234,7 +1620,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1234
1620
|
new Error(
|
|
1235
1621
|
"Device not connected after multiple attempts. Please ensure your Ledger is awake, unlocked, and in range, then try again."
|
|
1236
1622
|
),
|
|
1237
|
-
{ code:
|
|
1623
|
+
{ code: HardwareErrorCode3.DeviceNotFound }
|
|
1238
1624
|
);
|
|
1239
1625
|
}
|
|
1240
1626
|
await this._waitForDeviceConnect(internalSignal);
|
|
@@ -1258,7 +1644,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1258
1644
|
return this._connectDeviceOrThrow(devices[0].connectId);
|
|
1259
1645
|
}
|
|
1260
1646
|
const err = Object.assign(new Error(`Target Ledger unavailable: ${targetConnectId}`), {
|
|
1261
|
-
code:
|
|
1647
|
+
code: HardwareErrorCode3.DeviceNotFound
|
|
1262
1648
|
});
|
|
1263
1649
|
if (isLedgerBleConnectionType(this.connector.connectionType)) {
|
|
1264
1650
|
err._tag = ERROR_TAG.DeviceNotAdvertising;
|
|
@@ -1267,7 +1653,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1267
1653
|
}
|
|
1268
1654
|
if (isLedgerBleConnectionType(this.connector.connectionType)) {
|
|
1269
1655
|
throw Object.assign(new Error("Ledger BLE connectId is required."), {
|
|
1270
|
-
code:
|
|
1656
|
+
code: HardwareErrorCode3.DeviceNotFound
|
|
1271
1657
|
});
|
|
1272
1658
|
}
|
|
1273
1659
|
if (devices.length > 1) {
|
|
@@ -1275,7 +1661,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1275
1661
|
}
|
|
1276
1662
|
if (devices.length !== 1) {
|
|
1277
1663
|
throw Object.assign(new Error("Ledger device not found."), {
|
|
1278
|
-
code:
|
|
1664
|
+
code: HardwareErrorCode3.DeviceNotFound
|
|
1279
1665
|
});
|
|
1280
1666
|
}
|
|
1281
1667
|
return this._connectDeviceOrThrow(devices[0].connectId);
|
|
@@ -1326,26 +1712,43 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1326
1712
|
const result = signal ? await this._abortable(signal, promise) : await promise;
|
|
1327
1713
|
return this._unwrapConnectorResult(result);
|
|
1328
1714
|
}
|
|
1329
|
-
async connectorCall(connectId, method, params, fingerprint, permissionDeviceId, commonParams) {
|
|
1330
|
-
debugLog("[LedgerAdapter]
|
|
1715
|
+
async connectorCall(connectId, method, params, fingerprint, permissionDeviceId, commonParams, installContext) {
|
|
1716
|
+
debugLog("[LedgerAdapter][REQ]", { method, connectId: connectId || "(empty)", params });
|
|
1331
1717
|
const queueKey = connectId || "__ledger_default__";
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1718
|
+
try {
|
|
1719
|
+
const result = await this._jobQueue.enqueue(
|
|
1720
|
+
queueKey,
|
|
1721
|
+
async (signal) => this._runConnectorCall(
|
|
1722
|
+
connectId,
|
|
1723
|
+
method,
|
|
1724
|
+
params,
|
|
1725
|
+
signal,
|
|
1726
|
+
fingerprint,
|
|
1727
|
+
permissionDeviceId,
|
|
1728
|
+
commonParams,
|
|
1729
|
+
installContext
|
|
1730
|
+
),
|
|
1731
|
+
{
|
|
1732
|
+
label: method,
|
|
1733
|
+
rejectIfBusy: true,
|
|
1734
|
+
busyError: _LedgerAdapter._createDeviceBusyError(method)
|
|
1735
|
+
}
|
|
1736
|
+
);
|
|
1737
|
+
debugLog("[LedgerAdapter][RES]", { method, success: true, payload: result });
|
|
1738
|
+
return result;
|
|
1739
|
+
} catch (err) {
|
|
1740
|
+
const e = err;
|
|
1741
|
+
debugLog("[LedgerAdapter][RES]", {
|
|
1336
1742
|
method,
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
busyError: _LedgerAdapter._createDeviceBusyError(method)
|
|
1347
|
-
}
|
|
1348
|
-
);
|
|
1743
|
+
success: false,
|
|
1744
|
+
error: {
|
|
1745
|
+
message: e?.message,
|
|
1746
|
+
_tag: e?._tag,
|
|
1747
|
+
code: e?.code ?? e?.errorCode
|
|
1748
|
+
}
|
|
1749
|
+
});
|
|
1750
|
+
throw err;
|
|
1751
|
+
}
|
|
1349
1752
|
}
|
|
1350
1753
|
/**
|
|
1351
1754
|
* Race a promise against an abort signal. On abort, rejects with
|
|
@@ -1380,7 +1783,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1380
1783
|
}
|
|
1381
1784
|
}
|
|
1382
1785
|
/** Actual work done under the job queue — connection, fingerprint, call, and recovery. */
|
|
1383
|
-
async _runConnectorCall(connectId, method, params, signal, fingerprint, permissionDeviceId, commonParams) {
|
|
1786
|
+
async _runConnectorCall(connectId, method, params, signal, fingerprint, permissionDeviceId, commonParams, installContext) {
|
|
1384
1787
|
_LedgerAdapter._throwIfAborted(signal);
|
|
1385
1788
|
await this._ensureDevicePermission(
|
|
1386
1789
|
connectId,
|
|
@@ -1394,7 +1797,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1394
1797
|
if (gatedParams === null) {
|
|
1395
1798
|
throw Object.assign(new Error("User cancelled BTC high-index confirmation"), {
|
|
1396
1799
|
_tag: ERROR_TAG.UserAborted,
|
|
1397
|
-
code:
|
|
1800
|
+
code: HardwareErrorCode3.UserAborted
|
|
1398
1801
|
});
|
|
1399
1802
|
}
|
|
1400
1803
|
effectiveParams = gatedParams;
|
|
@@ -1423,7 +1826,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1423
1826
|
);
|
|
1424
1827
|
if (!fp.success) {
|
|
1425
1828
|
throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {
|
|
1426
|
-
code:
|
|
1829
|
+
code: HardwareErrorCode3.DeviceMismatch
|
|
1427
1830
|
});
|
|
1428
1831
|
}
|
|
1429
1832
|
}
|
|
@@ -1442,22 +1845,62 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1442
1845
|
isStuckApp: isStuckAppStateError(err)
|
|
1443
1846
|
});
|
|
1444
1847
|
const autoInstallApp = commonParams?.autoInstallApp ?? this._defaultAutoInstallApp;
|
|
1445
|
-
const isAppMissing = isAppNotInstalledError(err) || err?.code ===
|
|
1848
|
+
const isAppMissing = isAppNotInstalledError(err) || err?.code === HardwareErrorCode3.AppNotInstalled;
|
|
1446
1849
|
if (autoInstallApp && isAppMissing) {
|
|
1850
|
+
if (installContext?.deviceOutOfMemoryError) {
|
|
1851
|
+
throw installContext.deviceOutOfMemoryError;
|
|
1852
|
+
}
|
|
1447
1853
|
const appName = err?.appName ?? mapLedgerError(err).appName;
|
|
1448
1854
|
if (appName) {
|
|
1855
|
+
if (installContext?.installAttemptedAppNames?.has(appName)) {
|
|
1856
|
+
throw createHwkError({
|
|
1857
|
+
code: HardwareErrorCode3.AppNotInstalled,
|
|
1858
|
+
message: `${appName} install reported success but the app is still missing on device`,
|
|
1859
|
+
_tag: ERROR_TAG.AppInstallVerifyFailed,
|
|
1860
|
+
appName
|
|
1861
|
+
});
|
|
1862
|
+
}
|
|
1449
1863
|
const confirmed = await this._waitForInstallAppConfirm(appName);
|
|
1450
|
-
if (!confirmed)
|
|
1864
|
+
if (!confirmed) {
|
|
1865
|
+
throw createHwkError({
|
|
1866
|
+
code: HardwareErrorCode3.UserAborted,
|
|
1867
|
+
message: `User declined to install ${appName}`,
|
|
1868
|
+
_tag: ERROR_TAG.UserAborted,
|
|
1869
|
+
appName
|
|
1870
|
+
});
|
|
1871
|
+
}
|
|
1451
1872
|
this.emitter.emit("ui-event", {
|
|
1452
1873
|
type: EConnectorInteraction.AppInstallProgress,
|
|
1453
1874
|
payload: { connectId: resolvedConnectId, appName, progress: 0 }
|
|
1454
1875
|
});
|
|
1455
|
-
|
|
1876
|
+
try {
|
|
1877
|
+
await this._callConnector(sessionId, "installApp", { appName }, signal);
|
|
1878
|
+
} catch (installErr) {
|
|
1879
|
+
if (mapLedgerError(installErr).code === HardwareErrorCode3.DeviceOutOfMemory) {
|
|
1880
|
+
if (installContext) {
|
|
1881
|
+
installContext.deviceOutOfMemoryError = installErr;
|
|
1882
|
+
}
|
|
1883
|
+
}
|
|
1884
|
+
throw installErr;
|
|
1885
|
+
}
|
|
1886
|
+
if (installContext) {
|
|
1887
|
+
installContext.installAttemptedAppNames = installContext.installAttemptedAppNames ?? /* @__PURE__ */ new Set();
|
|
1888
|
+
installContext.installAttemptedAppNames.add(appName);
|
|
1889
|
+
}
|
|
1456
1890
|
this.emitter.emit(UI_REQUEST.CLOSE_UI_WINDOW, {
|
|
1457
1891
|
type: UI_REQUEST.CLOSE_UI_WINDOW,
|
|
1458
1892
|
payload: {}
|
|
1459
1893
|
});
|
|
1460
|
-
return await this.
|
|
1894
|
+
return await this._runConnectorCall(
|
|
1895
|
+
resolvedConnectId,
|
|
1896
|
+
method,
|
|
1897
|
+
effectiveParams,
|
|
1898
|
+
signal,
|
|
1899
|
+
fingerprint,
|
|
1900
|
+
permissionDeviceId,
|
|
1901
|
+
commonParams,
|
|
1902
|
+
installContext
|
|
1903
|
+
);
|
|
1461
1904
|
}
|
|
1462
1905
|
}
|
|
1463
1906
|
if (isStuckAppStateError(err)) {
|
|
@@ -1532,7 +1975,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1532
1975
|
);
|
|
1533
1976
|
if (!fp.success) {
|
|
1534
1977
|
throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {
|
|
1535
|
-
code:
|
|
1978
|
+
code: HardwareErrorCode3.DeviceMismatch
|
|
1536
1979
|
});
|
|
1537
1980
|
}
|
|
1538
1981
|
}
|
|
@@ -1567,7 +2010,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1567
2010
|
this.connector.reset();
|
|
1568
2011
|
const codeNum = err?.code;
|
|
1569
2012
|
throw Object.assign(err, {
|
|
1570
|
-
code: codeNum ??
|
|
2013
|
+
code: codeNum ?? HardwareErrorCode3.DeviceDisconnected
|
|
1571
2014
|
});
|
|
1572
2015
|
}
|
|
1573
2016
|
throw err;
|
|
@@ -1601,7 +2044,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1601
2044
|
);
|
|
1602
2045
|
if (!fp.success) {
|
|
1603
2046
|
throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {
|
|
1604
|
-
code:
|
|
2047
|
+
code: HardwareErrorCode3.DeviceMismatch
|
|
1605
2048
|
});
|
|
1606
2049
|
}
|
|
1607
2050
|
}
|
|
@@ -1658,7 +2101,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1658
2101
|
);
|
|
1659
2102
|
if (!fp.success) {
|
|
1660
2103
|
throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {
|
|
1661
|
-
code:
|
|
2104
|
+
code: HardwareErrorCode3.DeviceMismatch
|
|
1662
2105
|
});
|
|
1663
2106
|
}
|
|
1664
2107
|
}
|
|
@@ -1699,7 +2142,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1699
2142
|
);
|
|
1700
2143
|
if (!fp.success) {
|
|
1701
2144
|
throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {
|
|
1702
|
-
code:
|
|
2145
|
+
code: HardwareErrorCode3.DeviceMismatch
|
|
1703
2146
|
});
|
|
1704
2147
|
}
|
|
1705
2148
|
}
|
|
@@ -1749,7 +2192,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1749
2192
|
});
|
|
1750
2193
|
throw Object.assign(new Error("Device permission request superseded"), {
|
|
1751
2194
|
_tag: ERROR_TAG.UserAborted,
|
|
1752
|
-
code:
|
|
2195
|
+
code: HardwareErrorCode3.UserAborted,
|
|
1753
2196
|
cause: err
|
|
1754
2197
|
});
|
|
1755
2198
|
}
|
|
@@ -1760,7 +2203,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1760
2203
|
const { granted, reason, message } = response;
|
|
1761
2204
|
if (!granted) {
|
|
1762
2205
|
throw Object.assign(new Error(message ?? "Device permission denied"), {
|
|
1763
|
-
code:
|
|
2206
|
+
code: HardwareErrorCode3.DevicePermissionDenied,
|
|
1764
2207
|
reason
|
|
1765
2208
|
});
|
|
1766
2209
|
}
|
|
@@ -1774,7 +2217,7 @@ var _LedgerAdapter = class _LedgerAdapter {
|
|
|
1774
2217
|
const tag = err && typeof err === "object" ? err._tag : void 0;
|
|
1775
2218
|
if (err && typeof err === "object" && "code" in err && typeof err.code === "number") {
|
|
1776
2219
|
const e = err;
|
|
1777
|
-
const params = e.code ===
|
|
2220
|
+
const params = e.code === HardwareErrorCode3.DevicePermissionDenied && e.reason ? { permissionDeniedReason: e.reason } : e.params;
|
|
1778
2221
|
return ledgerFailure(e.code, e.message ?? "Unknown error", e.appName, tag, params);
|
|
1779
2222
|
}
|
|
1780
2223
|
const mapped = mapLedgerError(err);
|
|
@@ -1821,12 +2264,15 @@ _LedgerAdapter.STUCK_APP_RETRY_DELAY_MS = 500;
|
|
|
1821
2264
|
// Confirm but device never shows up / never unlocks), throw DeviceNotFound
|
|
1822
2265
|
// instead of looping forever.
|
|
1823
2266
|
_LedgerAdapter.MAX_DOCONNECT_CONFIRMS = 3;
|
|
2267
|
+
// Throttle AppInstallProgress by progress delta — DMK streams much faster
|
|
2268
|
+
// than UIs need. Final frame (progress >= 1) always passes.
|
|
2269
|
+
_LedgerAdapter.APP_INSTALL_PROGRESS_MIN_DELTA = 0.05;
|
|
1824
2270
|
var LedgerAdapter = _LedgerAdapter;
|
|
1825
2271
|
|
|
1826
2272
|
// src/connector/LedgerConnectorBase.ts
|
|
1827
2273
|
import {
|
|
1828
2274
|
EConnectorInteraction as EConnectorInteraction4,
|
|
1829
|
-
HardwareErrorCode as
|
|
2275
|
+
HardwareErrorCode as HardwareErrorCode8,
|
|
1830
2276
|
serializeConnectorError
|
|
1831
2277
|
} from "@onekeyfe/hwk-adapter-core";
|
|
1832
2278
|
|
|
@@ -2383,7 +2829,7 @@ var SignerManager = class _SignerManager {
|
|
|
2383
2829
|
};
|
|
2384
2830
|
|
|
2385
2831
|
// src/connector/chains/evm.ts
|
|
2386
|
-
import { HardwareErrorCode as
|
|
2832
|
+
import { HardwareErrorCode as HardwareErrorCode4, padHex64, stripHex } from "@onekeyfe/hwk-adapter-core";
|
|
2387
2833
|
|
|
2388
2834
|
// src/connector/chains/utils.ts
|
|
2389
2835
|
import { EConnectorInteraction as EConnectorInteraction2 } from "@onekeyfe/hwk-adapter-core";
|
|
@@ -2425,7 +2871,7 @@ async function evmSignTransaction(ctx, sessionId, params) {
|
|
|
2425
2871
|
new Error(
|
|
2426
2872
|
"Ledger requires a pre-serialized transaction (serializedTx). Provide an RLP-encoded hex string."
|
|
2427
2873
|
),
|
|
2428
|
-
{ code:
|
|
2874
|
+
{ code: HardwareErrorCode4.InvalidParams }
|
|
2429
2875
|
);
|
|
2430
2876
|
}
|
|
2431
2877
|
const signer = await _getEthSigner(ctx, sessionId);
|
|
@@ -2466,7 +2912,7 @@ async function evmSignTypedData(ctx, sessionId, params) {
|
|
|
2466
2912
|
new Error(
|
|
2467
2913
|
'Ledger does not support hash-only EIP-712 signing. Use mode "full" with the complete typed data structure.'
|
|
2468
2914
|
),
|
|
2469
|
-
{ code:
|
|
2915
|
+
{ code: HardwareErrorCode4.MethodNotSupported }
|
|
2470
2916
|
);
|
|
2471
2917
|
}
|
|
2472
2918
|
const signer = await _getEthSigner(ctx, sessionId);
|
|
@@ -2501,7 +2947,7 @@ async function _getEthSigner(ctx, sessionId) {
|
|
|
2501
2947
|
}
|
|
2502
2948
|
|
|
2503
2949
|
// src/connector/chains/btc.ts
|
|
2504
|
-
import { HardwareErrorCode as
|
|
2950
|
+
import { HardwareErrorCode as HardwareErrorCode5, stripHex as stripHex2 } from "@onekeyfe/hwk-adapter-core";
|
|
2505
2951
|
import { Psbt } from "bitcoinjs-lib";
|
|
2506
2952
|
|
|
2507
2953
|
// src/signer/SignerBtc.ts
|
|
@@ -2622,7 +3068,7 @@ function _purposeToTemplate(purpose, DDT) {
|
|
|
2622
3068
|
return DDT.TAPROOT;
|
|
2623
3069
|
default:
|
|
2624
3070
|
throw Object.assign(new Error(`Unsupported BTC purpose: m/${purpose ?? "<undefined>"}'`), {
|
|
2625
|
-
code:
|
|
3071
|
+
code: HardwareErrorCode5.InvalidParams
|
|
2626
3072
|
});
|
|
2627
3073
|
}
|
|
2628
3074
|
}
|
|
@@ -2678,7 +3124,7 @@ async function btcSignTransaction(ctx, sessionId, params) {
|
|
|
2678
3124
|
if (!params.psbt) {
|
|
2679
3125
|
throw Object.assign(
|
|
2680
3126
|
new Error("Ledger requires PSBT format for BTC transaction signing. Provide params.psbt."),
|
|
2681
|
-
{ code:
|
|
3127
|
+
{ code: HardwareErrorCode5.InvalidParams }
|
|
2682
3128
|
);
|
|
2683
3129
|
}
|
|
2684
3130
|
const btcSigner = await _createBtcSigner(ctx, sessionId);
|
|
@@ -2703,7 +3149,7 @@ async function btcSignTransaction(ctx, sessionId, params) {
|
|
|
2703
3149
|
async function btcSignPsbt(ctx, sessionId, params) {
|
|
2704
3150
|
if (!params.psbt) {
|
|
2705
3151
|
throw Object.assign(new Error("btcSignPsbt requires params.psbt"), {
|
|
2706
|
-
code:
|
|
3152
|
+
code: HardwareErrorCode5.InvalidParams
|
|
2707
3153
|
});
|
|
2708
3154
|
}
|
|
2709
3155
|
const btcSigner = await _createBtcSigner(ctx, sessionId);
|
|
@@ -2948,7 +3394,7 @@ async function _createSolSigner(ctx, sessionId) {
|
|
|
2948
3394
|
}
|
|
2949
3395
|
|
|
2950
3396
|
// src/connector/chains/tron.ts
|
|
2951
|
-
import { HardwareErrorCode as
|
|
3397
|
+
import { HardwareErrorCode as HardwareErrorCode7 } from "@onekeyfe/hwk-adapter-core";
|
|
2952
3398
|
import Trx from "@ledgerhq/hw-app-trx";
|
|
2953
3399
|
|
|
2954
3400
|
// src/connector/chains/legacyChainCall.ts
|
|
@@ -2961,7 +3407,7 @@ import {
|
|
|
2961
3407
|
OpenAppCommand,
|
|
2962
3408
|
isSuccessCommandResult
|
|
2963
3409
|
} from "@ledgerhq/device-management-kit";
|
|
2964
|
-
import { HardwareErrorCode as
|
|
3410
|
+
import { HardwareErrorCode as HardwareErrorCode6 } from "@onekeyfe/hwk-adapter-core";
|
|
2965
3411
|
var APP_NAME_MAP = {
|
|
2966
3412
|
ETH: "Ethereum",
|
|
2967
3413
|
BTC: "Bitcoin",
|
|
@@ -3065,15 +3511,30 @@ var AppManager = class {
|
|
|
3065
3511
|
command: new OpenAppCommand({ appName })
|
|
3066
3512
|
});
|
|
3067
3513
|
if (!isSuccessCommandResult(result)) {
|
|
3068
|
-
const
|
|
3069
|
-
const
|
|
3070
|
-
|
|
3514
|
+
const dmkErr = result.error;
|
|
3515
|
+
const errorCode = "errorCode" in dmkErr && dmkErr.errorCode != null ? String(dmkErr.errorCode) : "";
|
|
3516
|
+
const message = "message" in dmkErr && typeof dmkErr.message === "string" ? dmkErr.message : "";
|
|
3517
|
+
debugLog(
|
|
3518
|
+
"[AppManager] openApp failed:",
|
|
3519
|
+
appName,
|
|
3520
|
+
"errorCode:",
|
|
3521
|
+
errorCode,
|
|
3522
|
+
"tag:",
|
|
3523
|
+
dmkErr._tag
|
|
3524
|
+
);
|
|
3525
|
+
let code;
|
|
3526
|
+
if (errorCode === "6807" || /unknown application/i.test(message)) {
|
|
3527
|
+
code = HardwareErrorCode6.AppNotInstalled;
|
|
3528
|
+
} else if (errorCode === "5501" || dmkErr._tag === "ActionRefusedError") {
|
|
3529
|
+
code = HardwareErrorCode6.UserRejected;
|
|
3530
|
+
}
|
|
3071
3531
|
throw Object.assign(new Error(`Failed to open "${appName}"`), {
|
|
3072
3532
|
_tag: ERROR_TAG.OpenAppCommand,
|
|
3073
|
-
code
|
|
3074
|
-
errorCode
|
|
3075
|
-
statusCode,
|
|
3076
|
-
appName
|
|
3533
|
+
code,
|
|
3534
|
+
errorCode,
|
|
3535
|
+
statusCode: errorCode,
|
|
3536
|
+
appName,
|
|
3537
|
+
originalError: dmkErr
|
|
3077
3538
|
});
|
|
3078
3539
|
}
|
|
3079
3540
|
}
|
|
@@ -3252,7 +3713,7 @@ async function tronSignTransaction(ctx, sessionId, params) {
|
|
|
3252
3713
|
if (!params.rawTxHex) {
|
|
3253
3714
|
throw Object.assign(
|
|
3254
3715
|
new Error("TRON signing requires a protobuf-encoded raw transaction hex (rawTxHex)."),
|
|
3255
|
-
{ code:
|
|
3716
|
+
{ code: HardwareErrorCode7.InvalidParams }
|
|
3256
3717
|
);
|
|
3257
3718
|
}
|
|
3258
3719
|
const path = normalizePath(params.path);
|
|
@@ -3413,6 +3874,22 @@ var DeviceApps = class {
|
|
|
3413
3874
|
);
|
|
3414
3875
|
return result.filter((a) => a !== null).map(applicationToMetadata);
|
|
3415
3876
|
}
|
|
3877
|
+
/** Installed app names via ListApps APDU. Offline (no manager-api), but still requires unlock + dashboard. */
|
|
3878
|
+
async listInstalledNames(options) {
|
|
3879
|
+
const action = this._dmk.executeDeviceAction({
|
|
3880
|
+
sessionId: this._sessionId,
|
|
3881
|
+
deviceAction: new this._ledgerKit.ListAppsDeviceAction({
|
|
3882
|
+
input: { unlockTimeout: options?.unlockTimeout }
|
|
3883
|
+
})
|
|
3884
|
+
});
|
|
3885
|
+
const result = await deviceActionToPromise(
|
|
3886
|
+
action,
|
|
3887
|
+
this.onInteraction,
|
|
3888
|
+
void 0,
|
|
3889
|
+
this.onRegisterCanceller
|
|
3890
|
+
);
|
|
3891
|
+
return result.map((entry) => entry?.appName).filter((name) => typeof name === "string" && name.length > 0);
|
|
3892
|
+
}
|
|
3416
3893
|
// Catalog lookup via custom device action — DMK has no typed wrapper for this.
|
|
3417
3894
|
async listAvailable() {
|
|
3418
3895
|
const customAction = new ListAvailableAppsDeviceAction({
|
|
@@ -3476,6 +3953,22 @@ var DeviceApps = class {
|
|
|
3476
3953
|
async install(appName, onProgress, options) {
|
|
3477
3954
|
if (!appName) throw new Error("DeviceApps.install: appName is required");
|
|
3478
3955
|
debugLog("[DeviceApps] install:", appName);
|
|
3956
|
+
const refreshAction = this._dmk.executeDeviceAction({
|
|
3957
|
+
sessionId: this._sessionId,
|
|
3958
|
+
deviceAction: new this._ledgerKit.GetDeviceMetadataDeviceAction({
|
|
3959
|
+
input: {
|
|
3960
|
+
useSecureChannel: true,
|
|
3961
|
+
forceUpdate: true,
|
|
3962
|
+
unlockTimeout: options?.unlockTimeout
|
|
3963
|
+
}
|
|
3964
|
+
})
|
|
3965
|
+
});
|
|
3966
|
+
await deviceActionToPromise(
|
|
3967
|
+
refreshAction,
|
|
3968
|
+
this.onInteraction,
|
|
3969
|
+
INSTALL_TIMEOUT_MS,
|
|
3970
|
+
this.onRegisterCanceller
|
|
3971
|
+
);
|
|
3479
3972
|
const action = this._dmk.executeDeviceAction({
|
|
3480
3973
|
sessionId: this._sessionId,
|
|
3481
3974
|
deviceAction: new this._ledgerKit.InstallOrUpdateAppsDeviceAction({
|
|
@@ -3553,7 +4046,7 @@ var METHOD_PREFIX_TO_APP_NAME = {
|
|
|
3553
4046
|
tron: "Tron"
|
|
3554
4047
|
};
|
|
3555
4048
|
var HARDWARE_ERROR_CODE_VALUES = new Set(
|
|
3556
|
-
Object.values(
|
|
4049
|
+
Object.values(HardwareErrorCode8).filter((value) => typeof value === "number")
|
|
3557
4050
|
);
|
|
3558
4051
|
var BLE_CONNECT_SCAN_TIMEOUT_MS = 1500;
|
|
3559
4052
|
async function defaultLedgerKitImporter(pkg) {
|
|
@@ -3724,7 +4217,7 @@ var LedgerConnectorBase = class {
|
|
|
3724
4217
|
`Ledger BLE connect did not return within ${HANG_CEILING_MS / 6e4}min \u2014 DMK hang fallback.`
|
|
3725
4218
|
);
|
|
3726
4219
|
err._tag = ERROR_TAG.BlePairingTimeout;
|
|
3727
|
-
err.code =
|
|
4220
|
+
err.code = HardwareErrorCode8.BlePairingTimeout;
|
|
3728
4221
|
reject(err);
|
|
3729
4222
|
}, HANG_CEILING_MS);
|
|
3730
4223
|
});
|
|
@@ -3757,7 +4250,7 @@ var LedgerConnectorBase = class {
|
|
|
3757
4250
|
"Ledger device is not currently advertising. Wake up and unlock the device, keep it nearby, then try again."
|
|
3758
4251
|
);
|
|
3759
4252
|
err._tag = ERROR_TAG.DeviceNotAdvertising;
|
|
3760
|
-
err.code =
|
|
4253
|
+
err.code = HardwareErrorCode8.DeviceNotFound;
|
|
3761
4254
|
throw err;
|
|
3762
4255
|
};
|
|
3763
4256
|
const doConnect = async (path) => {
|
|
@@ -3821,7 +4314,7 @@ var LedgerConnectorBase = class {
|
|
|
3821
4314
|
"Ledger Bluetooth pairing failed. Make sure the device is unlocked and nearby, then try again."
|
|
3822
4315
|
);
|
|
3823
4316
|
wrapped._tag = ERROR_TAG.BleGattBondingFailed;
|
|
3824
|
-
wrapped.code =
|
|
4317
|
+
wrapped.code = HardwareErrorCode8.BlePairingTimeout;
|
|
3825
4318
|
wrapped.originalError = err;
|
|
3826
4319
|
throw wrapped;
|
|
3827
4320
|
}
|
|
@@ -3899,7 +4392,7 @@ var LedgerConnectorBase = class {
|
|
|
3899
4392
|
this._unwatchSessionState(sessionId);
|
|
3900
4393
|
this._signerManager?.invalidate(sessionId);
|
|
3901
4394
|
this._cancellers.get(sessionId)?.({
|
|
3902
|
-
code:
|
|
4395
|
+
code: HardwareErrorCode8.DeviceDisconnected,
|
|
3903
4396
|
tag: "DeviceDisconnected",
|
|
3904
4397
|
message: "Device disconnected"
|
|
3905
4398
|
});
|
|
@@ -3925,7 +4418,7 @@ var LedgerConnectorBase = class {
|
|
|
3925
4418
|
success: false,
|
|
3926
4419
|
error: serializeConnectorError(
|
|
3927
4420
|
Object.assign(new Error("Ledger app is unresponsive"), {
|
|
3928
|
-
code:
|
|
4421
|
+
code: HardwareErrorCode8.DeviceAppStuck,
|
|
3929
4422
|
_tag: ERROR_TAG.DeviceAppStuck,
|
|
3930
4423
|
originalError: err
|
|
3931
4424
|
})
|
|
@@ -3937,7 +4430,7 @@ var LedgerConnectorBase = class {
|
|
|
3937
4430
|
success: false,
|
|
3938
4431
|
error: serializeConnectorError(
|
|
3939
4432
|
Object.assign(new Error("Device communication interrupted, please retry"), {
|
|
3940
|
-
code:
|
|
4433
|
+
code: HardwareErrorCode8.TransportError,
|
|
3941
4434
|
_tag: ERROR_TAG.DeviceTransportStuck,
|
|
3942
4435
|
originalError: err
|
|
3943
4436
|
})
|
|
@@ -4033,6 +4526,17 @@ var LedgerConnectorBase = class {
|
|
|
4033
4526
|
ctx.clearCanceller(sessionId);
|
|
4034
4527
|
}
|
|
4035
4528
|
}
|
|
4529
|
+
case "listInstalledNames": {
|
|
4530
|
+
const apps = await _getDeviceApps(ctx, sessionId);
|
|
4531
|
+
try {
|
|
4532
|
+
return await apps.listInstalledNames(params);
|
|
4533
|
+
} catch (err) {
|
|
4534
|
+
ctx.invalidateSession(sessionId);
|
|
4535
|
+
throw ctx.wrapError(err);
|
|
4536
|
+
} finally {
|
|
4537
|
+
ctx.clearCanceller(sessionId);
|
|
4538
|
+
}
|
|
4539
|
+
}
|
|
4036
4540
|
case "listAvailableApps": {
|
|
4037
4541
|
const apps = await _getDeviceApps(ctx, sessionId);
|
|
4038
4542
|
try {
|