@onekeyfe/hd-core 1.2.0-alpha.25 → 1.2.0-alpha.27
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/__tests__/DeviceCommands.test.ts +28 -0
- package/__tests__/device-lifecycle-events.test.ts +21 -0
- package/__tests__/deviceSettings.test.ts +4 -4
- package/__tests__/firmware-update/check-all-firmware-release.test.ts +31 -0
- package/__tests__/firmware-update/firmware-update-plan.test.ts +70 -0
- package/__tests__/kaspa-use-tweak-pro2.test.ts +20 -0
- package/__tests__/protocol-v2.test.ts +129 -6
- package/__tests__/tron-sign-message-init.test.ts +28 -0
- package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareUpdatePlan.d.ts +3 -2
- package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +1 -1
- package/dist/api/kaspa/KaspaGetAddress.d.ts +3 -0
- package/dist/api/kaspa/KaspaGetAddress.d.ts.map +1 -1
- package/dist/api/kaspa/KaspaSignTransaction.d.ts +3 -0
- package/dist/api/kaspa/KaspaSignTransaction.d.ts.map +1 -1
- package/dist/api/tron/TronSignMessage.d.ts +3 -0
- package/dist/api/tron/TronSignMessage.d.ts.map +1 -1
- package/dist/device/Device.d.ts +1 -0
- package/dist/device/Device.d.ts.map +1 -1
- package/dist/device/DeviceCommands.d.ts.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +83 -42
- package/dist/protocols/protocol-v2/unlockRetry.d.ts.map +1 -1
- package/dist/types/api/checkAllFirmwareRelease.d.ts +2 -1
- package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
- package/dist/types/api/export.d.ts +1 -1
- package/dist/types/api/export.d.ts.map +1 -1
- package/dist/types/api/firmwareUpdatePlan.d.ts +1 -0
- package/dist/types/api/firmwareUpdatePlan.d.ts.map +1 -1
- package/dist/types/device.d.ts +1 -0
- package/dist/types/device.d.ts.map +1 -1
- package/dist/utils/deviceSettings.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/api/CheckAllFirmwareRelease.ts +2 -0
- package/src/api/UploadPortfolio.ts +1 -1
- package/src/api/firmware/FirmwareUpdatePlan.ts +47 -37
- package/src/api/kaspa/KaspaGetAddress.ts +3 -0
- package/src/api/kaspa/KaspaSignTransaction.ts +3 -0
- package/src/api/tron/TronSignMessage.ts +3 -0
- package/src/data-manager/TransportManager.ts +1 -1
- package/src/device/Device.ts +7 -0
- package/src/device/DeviceCommands.ts +10 -4
- package/src/protocols/protocol-v2/unlockRetry.ts +18 -11
- package/src/types/api/checkAllFirmwareRelease.ts +2 -1
- package/src/types/api/export.ts +1 -0
- package/src/types/api/firmwareUpdatePlan.ts +2 -0
- package/src/types/device.ts +2 -0
- package/src/utils/deviceSettings.ts +11 -1
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
import type {
|
|
13
13
|
FirmwareUpdatePlan,
|
|
14
14
|
FirmwareUpdatePlanArtifact,
|
|
15
|
+
FirmwareUpdatePlanForceTarget,
|
|
15
16
|
FirmwareUpdatePlanTarget,
|
|
16
17
|
} from '../../types/api/firmwareUpdatePlan';
|
|
17
18
|
import type { Features } from '../../types';
|
|
@@ -498,6 +499,7 @@ export const buildFirmwareUpdatePlan = ({
|
|
|
498
499
|
firmware,
|
|
499
500
|
ble,
|
|
500
501
|
bootloader,
|
|
502
|
+
forceUpdateTargets,
|
|
501
503
|
}: {
|
|
502
504
|
features: Features;
|
|
503
505
|
firmwareType: EFirmwareType;
|
|
@@ -505,18 +507,22 @@ export const buildFirmwareUpdatePlan = ({
|
|
|
505
507
|
firmware: ReleaseSelection;
|
|
506
508
|
ble: ReleaseSelection;
|
|
507
509
|
bootloader?: ReleaseSelection;
|
|
510
|
+
forceUpdateTargets?: FirmwareUpdatePlanForceTarget[];
|
|
508
511
|
}): FirmwareUpdatePlan => {
|
|
509
512
|
const executor = getExecutor(features);
|
|
510
513
|
let artifacts: FirmwareUpdatePlanArtifact[] = [];
|
|
511
514
|
let targetsToUpdate: FirmwareUpdatePlanTarget[] = [];
|
|
512
515
|
const firmwareRelease = asRelease(firmware);
|
|
516
|
+
const forcedTargets = new Set(forceUpdateTargets);
|
|
517
|
+
const shouldUpdateFirmware = isUpgrade(firmware) || forcedTargets.has('firmware');
|
|
518
|
+
const shouldUpdateResource = isUpgrade(firmware) || forcedTargets.has('resource');
|
|
513
519
|
|
|
514
|
-
if (executor === 'v4' &&
|
|
520
|
+
if (executor === 'v4' && (shouldUpdateFirmware || shouldUpdateResource)) {
|
|
515
521
|
const protocolV2 = buildProtocolV2Artifacts(firmwareRelease ?? {});
|
|
516
522
|
artifacts = protocolV2.artifacts;
|
|
517
523
|
targetsToUpdate = protocolV2.targets;
|
|
518
524
|
} else {
|
|
519
|
-
if (isUpgrade(bootloader)) {
|
|
525
|
+
if (isUpgrade(bootloader) || forcedTargets.has('bootloader')) {
|
|
520
526
|
artifacts.push({
|
|
521
527
|
artifactId: 'bootloader',
|
|
522
528
|
role: 'bootloader',
|
|
@@ -534,52 +540,56 @@ export const buildFirmwareUpdatePlan = ({
|
|
|
534
540
|
: {}),
|
|
535
541
|
});
|
|
536
542
|
}
|
|
537
|
-
if (
|
|
543
|
+
if (shouldUpdateFirmware || shouldUpdateResource) {
|
|
538
544
|
if (!firmwareRelease) {
|
|
539
545
|
throw ERRORS.TypedError(HardwareErrorCode.RuntimeError, 'Firmware release is invalid', {
|
|
540
546
|
firmwareUpdateCode: 'FirmwarePlanInvalid',
|
|
541
547
|
});
|
|
542
548
|
}
|
|
543
|
-
|
|
544
|
-
artifactId: 'firmware',
|
|
545
|
-
role: 'firmware',
|
|
546
|
-
target: 'firmware',
|
|
547
|
-
url: assertArtifactUrl(firmwareRelease.url, 'Firmware release'),
|
|
548
|
-
container: 'raw',
|
|
549
|
-
...asIntegrity({
|
|
550
|
-
size: firmwareRelease.expectedSize,
|
|
551
|
-
sha256: firmwareRelease.fingerprint,
|
|
552
|
-
}),
|
|
553
|
-
...(asVersion(firmwareRelease.version)
|
|
554
|
-
? { targetVersion: asVersion(firmwareRelease.version) }
|
|
555
|
-
: {}),
|
|
556
|
-
});
|
|
557
|
-
const resourceUrl = selectResourceUrl({
|
|
558
|
-
release: firmwareRelease,
|
|
559
|
-
features,
|
|
560
|
-
platform,
|
|
561
|
-
});
|
|
562
|
-
if (resourceUrl) {
|
|
549
|
+
if (shouldUpdateFirmware) {
|
|
563
550
|
artifacts.push({
|
|
564
|
-
artifactId: '
|
|
565
|
-
role: '
|
|
566
|
-
target: '
|
|
567
|
-
url: assertArtifactUrl(
|
|
568
|
-
container: '
|
|
551
|
+
artifactId: 'firmware',
|
|
552
|
+
role: 'firmware',
|
|
553
|
+
target: 'firmware',
|
|
554
|
+
url: assertArtifactUrl(firmwareRelease.url, 'Firmware release'),
|
|
555
|
+
container: 'raw',
|
|
569
556
|
...asIntegrity({
|
|
570
|
-
size:
|
|
571
|
-
|
|
572
|
-
? firmwareRelease.fullResourceExpectedSize
|
|
573
|
-
: firmwareRelease.resourceExpectedSize,
|
|
574
|
-
sha256:
|
|
575
|
-
resourceUrl === asString(firmwareRelease.fullResource)
|
|
576
|
-
? firmwareRelease.fullResourceFingerprint
|
|
577
|
-
: firmwareRelease.resourceFingerprint,
|
|
557
|
+
size: firmwareRelease.expectedSize,
|
|
558
|
+
sha256: firmwareRelease.fingerprint,
|
|
578
559
|
}),
|
|
560
|
+
...(asVersion(firmwareRelease.version)
|
|
561
|
+
? { targetVersion: asVersion(firmwareRelease.version) }
|
|
562
|
+
: {}),
|
|
579
563
|
});
|
|
580
564
|
}
|
|
565
|
+
if (shouldUpdateResource) {
|
|
566
|
+
const resourceUrl = selectResourceUrl({
|
|
567
|
+
release: firmwareRelease,
|
|
568
|
+
features,
|
|
569
|
+
platform,
|
|
570
|
+
});
|
|
571
|
+
if (resourceUrl) {
|
|
572
|
+
artifacts.push({
|
|
573
|
+
artifactId: 'resource',
|
|
574
|
+
role: 'resource',
|
|
575
|
+
target: 'resource',
|
|
576
|
+
url: assertArtifactUrl(resourceUrl, 'Firmware resource release'),
|
|
577
|
+
container: 'zip',
|
|
578
|
+
...asIntegrity({
|
|
579
|
+
size:
|
|
580
|
+
resourceUrl === asString(firmwareRelease.fullResource)
|
|
581
|
+
? firmwareRelease.fullResourceExpectedSize
|
|
582
|
+
: firmwareRelease.resourceExpectedSize,
|
|
583
|
+
sha256:
|
|
584
|
+
resourceUrl === asString(firmwareRelease.fullResource)
|
|
585
|
+
? firmwareRelease.fullResourceFingerprint
|
|
586
|
+
: firmwareRelease.resourceFingerprint,
|
|
587
|
+
}),
|
|
588
|
+
});
|
|
589
|
+
}
|
|
590
|
+
}
|
|
581
591
|
}
|
|
582
|
-
if (isUpgrade(ble)) {
|
|
592
|
+
if (isUpgrade(ble) || forcedTargets.has('ble')) {
|
|
583
593
|
const bleRelease = asRelease(ble);
|
|
584
594
|
artifacts.push({
|
|
585
595
|
artifactId: 'ble',
|
|
@@ -17,7 +17,7 @@ const LowLevelLogger = getLogger(LoggerNames.HdTransportLowLevel);
|
|
|
17
17
|
const NodeUsbLogger = getLogger(LoggerNames.HdTransportNodeUsb);
|
|
18
18
|
const WebBleLogger = getLogger(LoggerNames.HdWebBleTransport);
|
|
19
19
|
const WebUsbLogger = getLogger(LoggerNames.HdTransportWebUsb);
|
|
20
|
-
const REACT_NATIVE_BLE_SCAN_TIMEOUT_MS =
|
|
20
|
+
const REACT_NATIVE_BLE_SCAN_TIMEOUT_MS = 3000;
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* transport 在同一个环境中只会存在一个
|
package/src/device/Device.ts
CHANGED
|
@@ -314,6 +314,7 @@ export class Device extends EventEmitter {
|
|
|
314
314
|
// Keep the legacy top-level field string-compatible while preserving
|
|
315
315
|
// the canonical nullable value at state.identity.label.
|
|
316
316
|
label: displayName ?? '',
|
|
317
|
+
status: this.getStatus(),
|
|
317
318
|
mode: this.getMode(),
|
|
318
319
|
features,
|
|
319
320
|
state,
|
|
@@ -1335,6 +1336,12 @@ export class Device extends EventEmitter {
|
|
|
1335
1336
|
return EOneKeyDeviceMode.normal;
|
|
1336
1337
|
}
|
|
1337
1338
|
|
|
1339
|
+
getStatus() {
|
|
1340
|
+
if (this.isUsedElsewhere()) return 'occupied' as const;
|
|
1341
|
+
if (this.isUsedHere()) return 'used' as const;
|
|
1342
|
+
return 'available' as const;
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1338
1345
|
getFirmwareVersion() {
|
|
1339
1346
|
if (!this.state) return null;
|
|
1340
1347
|
return parseDeviceVersion(this.state.versions.firmware);
|
|
@@ -54,6 +54,13 @@ const DEVICE_SESSION_CALLS = new Set([
|
|
|
54
54
|
'DeviceSessionAskPassphrase',
|
|
55
55
|
]);
|
|
56
56
|
|
|
57
|
+
// Protocol V2 subcodes are domain-scoped, so cross-domain cancellation fallback
|
|
58
|
+
// must use explicit firmware cancellation messages instead of a global number map.
|
|
59
|
+
const isProtocolV2ActionCancelledMessage = (message: string) =>
|
|
60
|
+
/^(?:cancel(?:led|ed)(?: on device)?|confirm dismissed|user cancel(?:led|ed)(?:\s+.*)?)$/i.test(
|
|
61
|
+
message
|
|
62
|
+
);
|
|
63
|
+
|
|
57
64
|
function shouldReduceDebugForCall(type: string) {
|
|
58
65
|
return HIGH_VOLUME_DEBUG_CALLS.has(type);
|
|
59
66
|
}
|
|
@@ -474,9 +481,8 @@ export class DeviceCommands {
|
|
|
474
481
|
|
|
475
482
|
if (code === 'Failure_ProcessError') {
|
|
476
483
|
const normalizedMessage = message?.trim() ?? '';
|
|
477
|
-
const
|
|
478
|
-
this.device.isProtocolV2() &&
|
|
479
|
-
/^(?:cancelled on device|confirm dismissed)$/i.test(normalizedMessage);
|
|
484
|
+
const isProtocolV2ActionCancelledFailure =
|
|
485
|
+
this.device.isProtocolV2() && isProtocolV2ActionCancelledMessage(normalizedMessage);
|
|
480
486
|
const isLegacyProtocolV2LockedFailure =
|
|
481
487
|
this.device.isProtocolV2() && /^device (?:is )?locked$/i.test(normalizedMessage);
|
|
482
488
|
if (
|
|
@@ -536,7 +542,7 @@ export class DeviceCommands {
|
|
|
536
542
|
});
|
|
537
543
|
} else if (
|
|
538
544
|
subcode === DeviceErrorCode.DeviceError_ActionCancelled ||
|
|
539
|
-
|
|
545
|
+
isProtocolV2ActionCancelledFailure
|
|
540
546
|
) {
|
|
541
547
|
error = ERRORS.TypedError(HardwareErrorCode.ActionCancelled, message, {
|
|
542
548
|
failureCode: code,
|
|
@@ -24,6 +24,22 @@ type UiInteractionCoordinator = Pick<
|
|
|
24
24
|
'enterMethodInteraction' | 'enterUnlockInteraction' | 'resumeMethodInteraction'
|
|
25
25
|
>;
|
|
26
26
|
|
|
27
|
+
const restoreExpectedWalletSessionAfterUnlock = async (method: RunnableMethod, device: Device) => {
|
|
28
|
+
const expectedPassphraseState = method.payload?.useEmptyPassphrase
|
|
29
|
+
? undefined
|
|
30
|
+
: method.payload?.passphraseState ?? device.passphraseState;
|
|
31
|
+
if (
|
|
32
|
+
!method.useDevicePassphraseState ||
|
|
33
|
+
typeof expectedPassphraseState !== 'string' ||
|
|
34
|
+
expectedPassphraseState.length === 0
|
|
35
|
+
) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
await restoreProtocolV2WalletSession(device, expectedPassphraseState);
|
|
40
|
+
Log.debug('Protocol V2 wallet session restored after unlock', { method: method.name });
|
|
41
|
+
};
|
|
42
|
+
|
|
27
43
|
export async function runMethodWithUnlockRetry(
|
|
28
44
|
method: RunnableMethod,
|
|
29
45
|
device: Device,
|
|
@@ -39,6 +55,7 @@ export async function runMethodWithUnlockRetry(
|
|
|
39
55
|
}
|
|
40
56
|
await device.unlockDevice();
|
|
41
57
|
Log.debug('Protocol V2 pre-unlock completed', { method: method.name });
|
|
58
|
+
await restoreExpectedWalletSessionAfterUnlock(method, device);
|
|
42
59
|
if (shouldEmitUi) {
|
|
43
60
|
uiCoordinator?.enterMethodInteraction(resolveProtocolV2UiInteraction(method));
|
|
44
61
|
}
|
|
@@ -65,17 +82,7 @@ export async function runMethodWithUnlockRetry(
|
|
|
65
82
|
}
|
|
66
83
|
await device.unlockDevice();
|
|
67
84
|
Log.debug('Protocol V2 unlock completed', { method: method.name });
|
|
68
|
-
|
|
69
|
-
? undefined
|
|
70
|
-
: method.payload?.passphraseState ?? device.passphraseState;
|
|
71
|
-
if (
|
|
72
|
-
method.useDevicePassphraseState &&
|
|
73
|
-
typeof expectedPassphraseState === 'string' &&
|
|
74
|
-
expectedPassphraseState.length > 0
|
|
75
|
-
) {
|
|
76
|
-
await restoreProtocolV2WalletSession(device, expectedPassphraseState);
|
|
77
|
-
Log.debug('Protocol V2 wallet session restored after unlock', { method: method.name });
|
|
78
|
-
}
|
|
85
|
+
await restoreExpectedWalletSessionAfterUnlock(method, device);
|
|
79
86
|
if (shouldEmitUi) {
|
|
80
87
|
uiCoordinator?.resumeMethodInteraction();
|
|
81
88
|
}
|
|
@@ -2,7 +2,7 @@ import type { IBLEFirmwareReleaseInfo } from '../settings';
|
|
|
2
2
|
import type { EFirmwareType } from '@onekeyfe/hd-shared';
|
|
3
3
|
import type { CommonParams, Response } from '../params';
|
|
4
4
|
import type { Features, IDeviceBLEFirmwareStatus, IDeviceFirmwareStatus } from '../device';
|
|
5
|
-
import type { FirmwareUpdatePlan } from './firmwareUpdatePlan';
|
|
5
|
+
import type { FirmwareUpdatePlan, FirmwareUpdatePlanForceTarget } from './firmwareUpdatePlan';
|
|
6
6
|
|
|
7
7
|
export type FirmwareRelease = {
|
|
8
8
|
shouldUpdate?: boolean;
|
|
@@ -28,6 +28,7 @@ export type CheckAllFirmwareReleaseParams = {
|
|
|
28
28
|
checkBridgeRelease?: boolean;
|
|
29
29
|
firmwareType?: EFirmwareType;
|
|
30
30
|
platform?: 'native' | 'desktop' | 'ext' | 'web' | 'web-embed';
|
|
31
|
+
forceUpdateTargets?: FirmwareUpdatePlanForceTarget[];
|
|
31
32
|
};
|
|
32
33
|
|
|
33
34
|
export declare function checkAllFirmwareRelease(
|
package/src/types/api/export.ts
CHANGED
|
@@ -11,6 +11,8 @@ export type FirmwareUpdatePlanArtifactRole =
|
|
|
11
11
|
|
|
12
12
|
export type FirmwareUpdatePlanTarget = 'firmware' | 'ble' | 'bootloader' | FirmwareUpdateV4Target;
|
|
13
13
|
|
|
14
|
+
export type FirmwareUpdatePlanForceTarget = 'firmware' | 'ble' | 'bootloader' | 'resource';
|
|
15
|
+
|
|
14
16
|
export interface FirmwareUpdatePlanArtifact {
|
|
15
17
|
artifactId: string;
|
|
16
18
|
role: FirmwareUpdatePlanArtifactRole;
|
package/src/types/device.ts
CHANGED
|
@@ -43,6 +43,8 @@ export type KnownDevice = {
|
|
|
43
43
|
bleName: string | null;
|
|
44
44
|
name: string;
|
|
45
45
|
error?: typeof undefined;
|
|
46
|
+
/** Current SDK/transport usage state for connection indicators. */
|
|
47
|
+
status?: DeviceStatus;
|
|
46
48
|
mode: EOneKeyDeviceMode;
|
|
47
49
|
features?: Features;
|
|
48
50
|
/** Unified SDK device-state snapshot; features remains a legacy projection. */
|
|
@@ -90,8 +90,18 @@ export const mapLanguageFromProtocolV2 = (language?: string) =>
|
|
|
90
90
|
language ? PROTOCOL_V2_LANGUAGE_KEY_BY_TAG[language] ?? language : undefined;
|
|
91
91
|
|
|
92
92
|
const PRO2_LANGUAGE_OPTIONS = [
|
|
93
|
-
|
|
93
|
+
{ code: 'en', label: 'English' },
|
|
94
|
+
{ code: 'zh_cn', label: '简体中文' },
|
|
95
|
+
{ code: 'zh_hk', label: '繁體中文(香港)' },
|
|
94
96
|
{ code: 'zh-Hant-TW', label: '繁體中文(台灣)' },
|
|
97
|
+
{ code: 'ja', label: '日本語' },
|
|
98
|
+
{ code: 'ko', label: '한국어' },
|
|
99
|
+
{ code: 'fr', label: 'Français' },
|
|
100
|
+
{ code: 'de', label: 'Deutsch' },
|
|
101
|
+
{ code: 'ru', label: 'Русский' },
|
|
102
|
+
{ code: 'es', label: 'Español' },
|
|
103
|
+
{ code: 'it', label: 'Italiano' },
|
|
104
|
+
{ code: 'pt_br', label: 'Portuguese (Brazil)' },
|
|
95
105
|
{ code: 'vi-Latn-VN', label: 'Tiếng Việt' },
|
|
96
106
|
{ code: 'tr-Latn-TR', label: 'Türkçe' },
|
|
97
107
|
{ code: 'id-Latn-ID', label: 'Bahasa Indonesia' },
|