@onekeyfe/hd-core 1.2.0-alpha.21 → 1.2.0-alpha.22
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 +87 -2
- package/__tests__/connectSettings.test.ts +47 -5
- package/__tests__/device-identity.test.ts +24 -2
- package/__tests__/device-settings.test.ts +1 -1
- package/__tests__/device-wallet-session-store.test.ts +111 -7
- package/__tests__/firmware-update/firmware-artifact-source.test.ts +119 -0
- package/__tests__/firmware-update/firmware-host-binding.test.ts +70 -0
- package/__tests__/firmware-update/firmware-update-capabilities.test.ts +13 -0
- package/__tests__/firmware-update/firmware-update-plan.test.ts +326 -0
- package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +200 -0
- package/__tests__/firmware-update/firmware-update-v2-download-before-boot.test.ts +39 -30
- package/__tests__/firmware-update/firmware-upload-source.test.ts +70 -0
- package/__tests__/open-wallet-session.test.ts +253 -13
- package/__tests__/pro2Wallpaper.test.ts +7 -18
- package/__tests__/protocol-v2-unlock-policy.test.ts +45 -0
- package/__tests__/protocol-v2.test.ts +415 -145
- package/__tests__/public-device-state-api.test.ts +69 -62
- package/__tests__/public-pro2-api-boundary.test.ts +8 -34
- package/dist/api/BaseMethod.d.ts +2 -1
- package/dist/api/BaseMethod.d.ts.map +1 -1
- package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
- package/dist/api/ClearSessionCache.d.ts.map +1 -1
- package/dist/api/FirmwareUpdate.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV2.d.ts +11 -0
- package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV3.d.ts +7 -3
- package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV4.d.ts +29 -10
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/OpenWalletSession.d.ts.map +1 -1
- package/dist/api/conflux/ConfluxGetAddress.d.ts +1 -0
- package/dist/api/conflux/ConfluxGetAddress.d.ts.map +1 -1
- package/dist/api/conflux/ConfluxSignMessage.d.ts +1 -0
- package/dist/api/conflux/ConfluxSignMessage.d.ts.map +1 -1
- package/dist/api/conflux/ConfluxSignMessageCIP23.d.ts +1 -0
- package/dist/api/conflux/ConfluxSignMessageCIP23.d.ts.map +1 -1
- package/dist/api/conflux/ConfluxSignTransaction.d.ts +1 -0
- package/dist/api/conflux/ConfluxSignTransaction.d.ts.map +1 -1
- package/dist/api/device/DeviceUnlock.d.ts +1 -1
- package/dist/api/device/DeviceUnlock.d.ts.map +1 -1
- package/dist/api/device/DeviceUpdateBootloader.d.ts +5 -1
- package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareArtifactSource.d.ts +26 -0
- package/dist/api/firmware/FirmwareArtifactSource.d.ts.map +1 -0
- package/dist/api/firmware/FirmwareHostBinding.d.ts +6 -0
- package/dist/api/firmware/FirmwareHostBinding.d.ts.map +1 -0
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +7 -0
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts +3 -0
- package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts.map +1 -0
- package/dist/api/firmware/FirmwareUpdatePlan.d.ts +24 -0
- package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +1 -0
- package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts +25 -0
- package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +1 -0
- package/dist/api/firmware/getBinary.d.ts +7 -0
- package/dist/api/firmware/getBinary.d.ts.map +1 -1
- package/dist/api/firmware/updateBootloader.d.ts +2 -0
- package/dist/api/firmware/updateBootloader.d.ts.map +1 -1
- package/dist/api/firmware/uploadFirmware.d.ts +9 -1
- package/dist/api/firmware/uploadFirmware.d.ts.map +1 -1
- package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -1
- package/dist/api/index.d.ts +0 -17
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/nexa/NexaSignTransaction.d.ts +1 -0
- package/dist/api/nexa/NexaSignTransaction.d.ts.map +1 -1
- package/dist/api/stellar/StellarSignTransaction.d.ts +1 -1
- package/dist/data-manager/DataManager.d.ts +1 -0
- package/dist/data-manager/DataManager.d.ts.map +1 -1
- package/dist/data-manager/connectSettings.d.ts.map +1 -1
- package/dist/device/Device.d.ts.map +1 -1
- package/dist/device/DeviceCommands.d.ts.map +1 -1
- package/dist/device/DeviceStateMapper.d.ts.map +1 -1
- package/dist/device/DeviceStateProjector.d.ts.map +1 -1
- package/dist/events/logBlockEvent.d.ts.map +1 -1
- package/dist/index.d.ts +265 -226
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3045 -1550
- package/dist/inject.d.ts.map +1 -1
- package/dist/lowLevelInject.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/settingsUnlockPolicy.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/unlockPolicy.d.ts +4 -0
- package/dist/protocols/protocol-v2/unlockPolicy.d.ts.map +1 -0
- package/dist/protocols/protocol-v2/unlockRetry.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
- package/dist/topLevelInject.d.ts.map +1 -1
- package/dist/types/api/checkAllFirmwareRelease.d.ts +3 -0
- package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
- package/dist/types/api/deviceUnlock.d.ts +2 -2
- package/dist/types/api/deviceUnlock.d.ts.map +1 -1
- package/dist/types/api/deviceUpdateBootloader.d.ts +6 -0
- package/dist/types/api/deviceUpdateBootloader.d.ts.map +1 -1
- package/dist/types/api/export.d.ts +4 -1
- package/dist/types/api/export.d.ts.map +1 -1
- package/dist/types/api/firmwareUpdate.d.ts +69 -0
- package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
- package/dist/types/api/firmwareUpdateCapabilities.d.ts +9 -0
- package/dist/types/api/firmwareUpdateCapabilities.d.ts.map +1 -0
- package/dist/types/api/firmwareUpdatePlan.d.ts +27 -0
- package/dist/types/api/firmwareUpdatePlan.d.ts.map +1 -0
- package/dist/types/api/firmwareUpdatePreparedPlan.d.ts +42 -0
- package/dist/types/api/firmwareUpdatePreparedPlan.d.ts.map +1 -0
- package/dist/types/api/index.d.ts +10 -19
- package/dist/types/api/index.d.ts.map +1 -1
- package/dist/types/api/openWalletSession.d.ts +1 -0
- package/dist/types/api/openWalletSession.d.ts.map +1 -1
- package/dist/types/api/protocolV2.d.ts +3 -76
- package/dist/types/api/protocolV2.d.ts.map +1 -1
- package/dist/types/api/sessionCache.d.ts +4 -1
- package/dist/types/api/sessionCache.d.ts.map +1 -1
- package/dist/types/settings.d.ts +13 -0
- package/dist/types/settings.d.ts.map +1 -1
- package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
- package/dist/utils/patch.d.ts +1 -1
- package/dist/utils/patch.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/api/BaseMethod.ts +8 -3
- package/src/api/CheckAllFirmwareRelease.ts +16 -3
- package/src/api/ClearSessionCache.ts +4 -0
- package/src/api/FirmwareUpdate.ts +8 -1
- package/src/api/FirmwareUpdateV2.ts +284 -119
- package/src/api/FirmwareUpdateV3.ts +248 -55
- package/src/api/FirmwareUpdateV4.ts +816 -328
- package/src/api/OpenWalletSession.ts +74 -25
- package/src/api/UploadPortfolio.ts +1 -1
- package/src/api/conflux/ConfluxGetAddress.ts +2 -0
- package/src/api/conflux/ConfluxSignMessage.ts +2 -0
- package/src/api/conflux/ConfluxSignMessageCIP23.ts +2 -0
- package/src/api/conflux/ConfluxSignTransaction.ts +2 -0
- package/src/api/device/DeviceChangePin.ts +1 -1
- package/src/api/device/DeviceUnlock.ts +1 -2
- package/src/api/device/DeviceUpdateBootloader.ts +114 -6
- package/src/api/device/DeviceWipe.ts +1 -1
- package/src/api/firmware/FirmwareArtifactSource.ts +278 -0
- package/src/api/firmware/FirmwareHostBinding.ts +100 -0
- package/src/api/firmware/FirmwareUpdateBaseMethod.ts +50 -0
- package/src/api/firmware/FirmwareUpdateCapabilities.ts +9 -0
- package/src/api/firmware/FirmwareUpdatePlan.ts +621 -0
- package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +378 -0
- package/src/api/firmware/updateBootloader.ts +19 -4
- package/src/api/firmware/uploadFirmware.ts +140 -22
- package/src/api/helpers/protocolV2FileWrite.ts +6 -0
- package/src/api/index.ts +0 -18
- package/src/api/nexa/NexaSignTransaction.ts +2 -0
- package/src/api/protocol-v2/DeviceUploadWallpaper.ts +1 -1
- package/src/data/messages/messages-protocol-v2.json +77 -4
- package/src/data-manager/DataManager.ts +33 -33
- package/src/data-manager/connectSettings.ts +11 -0
- package/src/device/Device.ts +50 -60
- package/src/device/DeviceCommands.ts +58 -14
- package/src/device/DeviceStateMapper.ts +18 -1
- package/src/device/DeviceStateProjector.ts +7 -1
- package/src/events/logBlockEvent.ts +1 -0
- package/src/index.ts +5 -0
- package/src/inject.ts +22 -25
- package/src/lowLevelInject.ts +5 -1
- package/src/protocols/protocol-v2/deviceSession.ts +1 -1
- package/src/protocols/protocol-v2/settingsUnlockPolicy.ts +2 -2
- package/src/protocols/protocol-v2/unlockPolicy.ts +105 -0
- package/src/protocols/protocol-v2/unlockRetry.ts +1 -3
- package/src/protocols/protocol-v2/walletSession.ts +68 -12
- package/src/topLevelInject.ts +5 -1
- package/src/types/api/checkAllFirmwareRelease.ts +3 -0
- package/src/types/api/deviceUnlock.ts +2 -5
- package/src/types/api/deviceUpdateBootloader.ts +6 -0
- package/src/types/api/export.ts +18 -0
- package/src/types/api/firmwareUpdate.ts +76 -0
- package/src/types/api/firmwareUpdateCapabilities.ts +9 -0
- package/src/types/api/firmwareUpdatePlan.ts +36 -0
- package/src/types/api/firmwareUpdatePreparedPlan.ts +53 -0
- package/src/types/api/index.ts +14 -34
- package/src/types/api/openWalletSession.ts +2 -0
- package/src/types/api/protocolV2.ts +3 -156
- package/src/types/api/sessionCache.ts +9 -4
- package/src/types/settings.ts +13 -0
- package/src/utils/deviceFeaturesUtils.ts +5 -1
|
@@ -152,6 +152,12 @@ export async function writeProtocolV2File(options: ProtocolV2FileWriteOptions) {
|
|
|
152
152
|
options.throwIfAborted?.();
|
|
153
153
|
}
|
|
154
154
|
}
|
|
155
|
+
if (!response) {
|
|
156
|
+
throw ERRORS.TypedError(
|
|
157
|
+
HardwareErrorCode.RuntimeError,
|
|
158
|
+
'FilesystemFileWrite completed without a response'
|
|
159
|
+
);
|
|
160
|
+
}
|
|
155
161
|
options.throwIfAborted?.();
|
|
156
162
|
lastMessage = response.message;
|
|
157
163
|
const rawProcessedByte = response.message?.processed_byte;
|
package/src/api/index.ts
CHANGED
|
@@ -48,24 +48,6 @@ export { default as promptWebDeviceAccess } from './PromptWebDeviceAccess';
|
|
|
48
48
|
export { default as deviceReboot } from './protocol-v2/DeviceReboot';
|
|
49
49
|
export { default as deviceGetOnboardingStatus } from './protocol-v2/DeviceGetOnboardingStatus';
|
|
50
50
|
export { default as deviceUploadWallpaper } from './protocol-v2/DeviceUploadWallpaper';
|
|
51
|
-
// Protocol V2 development APIs. These remain public while Pro2 integration is in development.
|
|
52
|
-
export { default as deviceInfoGet } from './protocol-v2/DeviceInfoGet';
|
|
53
|
-
export { default as deviceStatusGet } from './protocol-v2/DeviceStatusGet';
|
|
54
|
-
export { default as protocolInfoRequest } from './protocol-v2/ProtocolInfoRequest';
|
|
55
|
-
export { default as ping } from './protocol-v2/Ping';
|
|
56
|
-
export { default as deviceFirmwareUpdate } from './protocol-v2/DeviceFirmwareUpdate';
|
|
57
|
-
export { default as deviceGetFirmwareUpdateStatus } from './protocol-v2/DeviceGetFirmwareUpdateStatus';
|
|
58
|
-
export { default as deviceFactoryInfoSet } from './protocol-v2/DeviceFactoryInfoSet';
|
|
59
|
-
export { default as deviceFactoryInfoGet } from './protocol-v2/DeviceFactoryInfoGet';
|
|
60
|
-
export { default as filesystemPermissionFix } from './protocol-v2/FilesystemPermissionFix';
|
|
61
|
-
export { default as filesystemFormat } from './protocol-v2/FilesystemFormat';
|
|
62
|
-
export { default as fileRead } from './FileRead';
|
|
63
|
-
export { default as fileWrite } from './FileWrite';
|
|
64
|
-
export { default as fileDelete } from './FileDelete';
|
|
65
|
-
export { default as dirList } from './DirList';
|
|
66
|
-
export { default as dirMake } from './DirMake';
|
|
67
|
-
export { default as dirRemove } from './DirRemove';
|
|
68
|
-
export { default as pathInfo } from './PathInfo';
|
|
69
51
|
export { default as uploadPortfolio } from './UploadPortfolio';
|
|
70
52
|
|
|
71
53
|
export { default as cipherKeyValue } from './CipherKeyValue';
|
|
@@ -9,6 +9,8 @@ import type { TypedCall } from '@onekeyfe/hd-transport';
|
|
|
9
9
|
import type { DeviceFirmwareRange, NexaSignTransactionParams, NexaSignature } from '../../types';
|
|
10
10
|
|
|
11
11
|
export default class NexaSignTransaction extends BaseMethod<NexaSignTransactionParams> {
|
|
12
|
+
checkDeviceId = true;
|
|
13
|
+
|
|
12
14
|
hasBundle = false;
|
|
13
15
|
|
|
14
16
|
init() {
|
|
@@ -71,7 +71,7 @@ export default class DeviceUploadWallpaper extends BaseMethod<DeviceUploadWallpa
|
|
|
71
71
|
this.path = `${WALLPAPER_DIRECTORY}/${normalizeFileName(fileName, this.encoded.data)}`;
|
|
72
72
|
this.params = { width, height, rgba: rgbaBytes, fileName, chunkSize };
|
|
73
73
|
this.requireProtocolV2 = true;
|
|
74
|
-
this.unlockPolicy = '
|
|
74
|
+
this.unlockPolicy = 'unlock-before-run';
|
|
75
75
|
this.skipForceUpdateCheck = true;
|
|
76
76
|
this.useDevicePassphraseState = false;
|
|
77
77
|
}
|
|
@@ -482,9 +482,9 @@
|
|
|
482
482
|
"MessageType_DeviceStatus": 60603,
|
|
483
483
|
"MessageType_DevGetOnboardingStatus": 60604,
|
|
484
484
|
"MessageType_DevOnboardingStatus": 60605,
|
|
485
|
-
"MessageType_DeviceSessionGet": 60606,
|
|
486
485
|
"MessageType_DeviceSession": 60607,
|
|
487
486
|
"MessageType_DeviceSessionAskPin": 60608,
|
|
487
|
+
"MessageType_DeviceSessionOpen": 60609,
|
|
488
488
|
"MessageType_FilesystemPermissionFix": 60800,
|
|
489
489
|
"MessageType_FilesystemPathInfo": 60801,
|
|
490
490
|
"MessageType_FilesystemPathInfoQuery": 60802,
|
|
@@ -506,7 +506,8 @@
|
|
|
506
506
|
[90, 92],
|
|
507
507
|
[114, 122],
|
|
508
508
|
[300, 304],
|
|
509
|
-
[309, 312]
|
|
509
|
+
[309, 312],
|
|
510
|
+
[60606, 60606]
|
|
510
511
|
]
|
|
511
512
|
},
|
|
512
513
|
"AlephiumGetAddress": {
|
|
@@ -11744,7 +11745,15 @@
|
|
|
11744
11745
|
}
|
|
11745
11746
|
},
|
|
11746
11747
|
"ProtocolInfoRequest": {
|
|
11747
|
-
"fields": {
|
|
11748
|
+
"fields": {
|
|
11749
|
+
"eventless_wallet_session": {
|
|
11750
|
+
"type": "bool",
|
|
11751
|
+
"id": 1,
|
|
11752
|
+
"options": {
|
|
11753
|
+
"default": false
|
|
11754
|
+
}
|
|
11755
|
+
}
|
|
11756
|
+
}
|
|
11748
11757
|
},
|
|
11749
11758
|
"ProtocolInfo": {
|
|
11750
11759
|
"fields": {
|
|
@@ -12427,14 +12436,78 @@
|
|
|
12427
12436
|
}
|
|
12428
12437
|
}
|
|
12429
12438
|
},
|
|
12430
|
-
"
|
|
12439
|
+
"DeviceSessionErrorCode": {
|
|
12440
|
+
"values": {
|
|
12441
|
+
"DeviceSessionError_None": 0,
|
|
12442
|
+
"DeviceSessionError_UserCancelled": 1,
|
|
12443
|
+
"DeviceSessionError_InvalidSession": 2,
|
|
12444
|
+
"DeviceSessionError_AttachPinUnavailable": 3,
|
|
12445
|
+
"DeviceSessionError_PassphraseDisabled": 4,
|
|
12446
|
+
"DeviceSessionError_Busy": 5
|
|
12447
|
+
}
|
|
12448
|
+
},
|
|
12449
|
+
"DeviceSessionResume": {
|
|
12431
12450
|
"fields": {
|
|
12432
12451
|
"session_id": {
|
|
12452
|
+
"rule": "required",
|
|
12433
12453
|
"type": "bytes",
|
|
12434
12454
|
"id": 1
|
|
12435
12455
|
}
|
|
12436
12456
|
}
|
|
12437
12457
|
},
|
|
12458
|
+
"DeviceSessionHostPassphrase": {
|
|
12459
|
+
"fields": {
|
|
12460
|
+
"passphrase": {
|
|
12461
|
+
"rule": "required",
|
|
12462
|
+
"type": "string",
|
|
12463
|
+
"id": 1
|
|
12464
|
+
}
|
|
12465
|
+
}
|
|
12466
|
+
},
|
|
12467
|
+
"DeviceSessionPassphraseOnDevice": {
|
|
12468
|
+
"fields": {}
|
|
12469
|
+
},
|
|
12470
|
+
"DeviceSessionAttachPinOnDevice": {
|
|
12471
|
+
"fields": {}
|
|
12472
|
+
},
|
|
12473
|
+
"DeviceSessionSelect": {
|
|
12474
|
+
"oneofs": {
|
|
12475
|
+
"access": {
|
|
12476
|
+
"oneof": ["host_passphrase", "passphrase_on_device", "attach_pin_on_device"]
|
|
12477
|
+
}
|
|
12478
|
+
},
|
|
12479
|
+
"fields": {
|
|
12480
|
+
"host_passphrase": {
|
|
12481
|
+
"type": "DeviceSessionHostPassphrase",
|
|
12482
|
+
"id": 1
|
|
12483
|
+
},
|
|
12484
|
+
"passphrase_on_device": {
|
|
12485
|
+
"type": "DeviceSessionPassphraseOnDevice",
|
|
12486
|
+
"id": 2
|
|
12487
|
+
},
|
|
12488
|
+
"attach_pin_on_device": {
|
|
12489
|
+
"type": "DeviceSessionAttachPinOnDevice",
|
|
12490
|
+
"id": 3
|
|
12491
|
+
}
|
|
12492
|
+
}
|
|
12493
|
+
},
|
|
12494
|
+
"DeviceSessionOpen": {
|
|
12495
|
+
"oneofs": {
|
|
12496
|
+
"mode": {
|
|
12497
|
+
"oneof": ["resume", "select"]
|
|
12498
|
+
}
|
|
12499
|
+
},
|
|
12500
|
+
"fields": {
|
|
12501
|
+
"resume": {
|
|
12502
|
+
"type": "DeviceSessionResume",
|
|
12503
|
+
"id": 1
|
|
12504
|
+
},
|
|
12505
|
+
"select": {
|
|
12506
|
+
"type": "DeviceSessionSelect",
|
|
12507
|
+
"id": 2
|
|
12508
|
+
}
|
|
12509
|
+
}
|
|
12510
|
+
},
|
|
12438
12511
|
"DeviceSession": {
|
|
12439
12512
|
"fields": {
|
|
12440
12513
|
"session_id": {
|
|
@@ -399,7 +399,17 @@ export default class DataManager {
|
|
|
399
399
|
|
|
400
400
|
static async load(settings: ConnectSettings) {
|
|
401
401
|
this.settings = settings;
|
|
402
|
-
|
|
402
|
+
const manifestMode =
|
|
403
|
+
settings.firmwareManifestMode ?? (settings.fetchConfig ? 'sdk-managed' : undefined);
|
|
404
|
+
if (settings.preloadedConfig) {
|
|
405
|
+
this.applyRemoteConfig(settings.preloadedConfig);
|
|
406
|
+
Log.log('[DataConfig] Preloaded firmware config loaded');
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
if (manifestMode === 'external-only') {
|
|
410
|
+
throw new Error('External firmware config snapshot is required');
|
|
411
|
+
}
|
|
412
|
+
if (manifestMode !== 'sdk-managed') {
|
|
403
413
|
return;
|
|
404
414
|
}
|
|
405
415
|
|
|
@@ -409,60 +419,50 @@ export default class DataManager {
|
|
|
409
419
|
|
|
410
420
|
const urlWithCache = `${url}?noCache=${getTimeStamp()}`;
|
|
411
421
|
let data: RemoteConfigResponse | null = null;
|
|
412
|
-
let fetchMethod: 'configFetcher' | 'axios' | 'none' = 'none';
|
|
413
|
-
|
|
414
|
-
// 1. Try custom configFetcher first (client-side IP direct connection support)
|
|
415
422
|
if (settings.configFetcher) {
|
|
416
|
-
Log.debug('[DataConfig] Trying
|
|
423
|
+
Log.debug('[DataConfig] Trying client configFetcher...');
|
|
417
424
|
try {
|
|
418
425
|
data = await settings.configFetcher(urlWithCache);
|
|
419
|
-
if (data) {
|
|
420
|
-
fetchMethod = 'configFetcher';
|
|
421
|
-
Log.log('[DataConfig] ConfigFetcher success');
|
|
422
|
-
} else {
|
|
423
|
-
Log.debug('[DataConfig] ConfigFetcher returned null, will fallback to axios');
|
|
424
|
-
}
|
|
425
426
|
} catch (e) {
|
|
426
|
-
Log.warn('[DataConfig]
|
|
427
|
+
Log.warn('[DataConfig] Client configFetcher failed:', e);
|
|
427
428
|
}
|
|
428
429
|
}
|
|
429
|
-
|
|
430
|
-
// 2. Fallback to default axios request
|
|
431
430
|
if (!data) {
|
|
432
|
-
Log.debug('[DataConfig] Trying
|
|
431
|
+
Log.debug('[DataConfig] Trying SDK-managed config request...');
|
|
433
432
|
try {
|
|
434
433
|
const response = await axios.get<RemoteConfigResponse>(urlWithCache, {
|
|
435
434
|
// because of iframe timeout is 10000
|
|
436
435
|
timeout: 7000,
|
|
437
436
|
});
|
|
438
437
|
data = response.data;
|
|
439
|
-
|
|
440
|
-
Log.log('[DataConfig] Axios fetch success');
|
|
438
|
+
Log.log('[DataConfig] SDK-managed config request succeeded');
|
|
441
439
|
} catch (e) {
|
|
442
|
-
Log.warn('[DataConfig]
|
|
440
|
+
Log.warn('[DataConfig] SDK-managed config request failed:', e);
|
|
443
441
|
}
|
|
444
442
|
}
|
|
445
443
|
|
|
446
|
-
// 3. Apply config if available
|
|
447
444
|
if (data) {
|
|
448
|
-
|
|
449
|
-
this.deviceMap = {
|
|
450
|
-
[EDeviceType.Classic]: this.enrichFirmwareReleaseInfo(data.classic),
|
|
451
|
-
[EDeviceType.Classic1s]: this.enrichFirmwareReleaseInfo(data.classic1s),
|
|
452
|
-
[EDeviceType.ClassicPure]: this.enrichFirmwareReleaseInfo(data.classicpure),
|
|
453
|
-
[EDeviceType.Mini]: this.enrichFirmwareReleaseInfo(data.mini),
|
|
454
|
-
[EDeviceType.Touch]: this.enrichFirmwareReleaseInfo(data.touch),
|
|
455
|
-
[EDeviceType.Pro]: this.enrichFirmwareReleaseInfo(data.pro),
|
|
456
|
-
[EDeviceType.Pro2]: this.enrichFirmwareReleaseInfo(data.pro2),
|
|
457
|
-
};
|
|
458
|
-
this.assets = {
|
|
459
|
-
bridge: data.bridge,
|
|
460
|
-
};
|
|
445
|
+
this.applyRemoteConfig(data);
|
|
461
446
|
} else {
|
|
462
|
-
Log.warn('[DataConfig]
|
|
447
|
+
Log.warn('[DataConfig] SDK-managed config request failed, using built-in default config');
|
|
463
448
|
}
|
|
464
449
|
}
|
|
465
450
|
|
|
451
|
+
private static applyRemoteConfig(data: RemoteConfigResponse) {
|
|
452
|
+
this.deviceMap = {
|
|
453
|
+
[EDeviceType.Classic]: this.enrichFirmwareReleaseInfo(data.classic),
|
|
454
|
+
[EDeviceType.Classic1s]: this.enrichFirmwareReleaseInfo(data.classic1s),
|
|
455
|
+
[EDeviceType.ClassicPure]: this.enrichFirmwareReleaseInfo(data.classicpure),
|
|
456
|
+
[EDeviceType.Mini]: this.enrichFirmwareReleaseInfo(data.mini),
|
|
457
|
+
[EDeviceType.Touch]: this.enrichFirmwareReleaseInfo(data.touch),
|
|
458
|
+
[EDeviceType.Pro]: this.enrichFirmwareReleaseInfo(data.pro),
|
|
459
|
+
[EDeviceType.Pro2]: this.enrichFirmwareReleaseInfo(data.pro2),
|
|
460
|
+
};
|
|
461
|
+
this.assets = {
|
|
462
|
+
bridge: data.bridge,
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
|
|
466
466
|
static updateEnv(newEnv: ConnectSettings['env']) {
|
|
467
467
|
if (this.settings) {
|
|
468
468
|
const prevEnv = this.settings.env;
|
|
@@ -115,10 +115,21 @@ export const parseConnectSettings = (input: Partial<ConnectSettings> = {}) => {
|
|
|
115
115
|
settings.fetchConfig = input.fetchConfig;
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
+
if (
|
|
119
|
+
input.firmwareManifestMode === 'sdk-managed' ||
|
|
120
|
+
input.firmwareManifestMode === 'external-only'
|
|
121
|
+
) {
|
|
122
|
+
settings.firmwareManifestMode = input.firmwareManifestMode;
|
|
123
|
+
}
|
|
124
|
+
|
|
118
125
|
if (input.configFetcher) {
|
|
119
126
|
settings.configFetcher = input.configFetcher;
|
|
120
127
|
}
|
|
121
128
|
|
|
129
|
+
if (input.preloadedConfig) {
|
|
130
|
+
settings.preloadedConfig = input.preloadedConfig;
|
|
131
|
+
}
|
|
132
|
+
|
|
122
133
|
return settings;
|
|
123
134
|
};
|
|
124
135
|
|
package/src/device/Device.ts
CHANGED
|
@@ -153,7 +153,8 @@ export interface Device {
|
|
|
153
153
|
* This allows short-lived processes (e.g. CLI) to restore a previously
|
|
154
154
|
* obtained session, avoiding the need to re-enter passphrase on every
|
|
155
155
|
* invocation. The session must have been obtained from a prior
|
|
156
|
-
*
|
|
156
|
+
* wallet-session call on the same device. This compatibility hook is intended
|
|
157
|
+
* for a trusted CLI process restoring its own OS-keychain entry.
|
|
157
158
|
*
|
|
158
159
|
* @param deviceId - The device's device_id (from features)
|
|
159
160
|
* @param passphraseState - The passphrase state token
|
|
@@ -222,24 +223,7 @@ export class Device extends EventEmitter {
|
|
|
222
223
|
|
|
223
224
|
get features(): Features | undefined {
|
|
224
225
|
if (!this.state) return undefined;
|
|
225
|
-
|
|
226
|
-
const sessionCacheDeviceKey =
|
|
227
|
-
this.state.identity.deviceId ||
|
|
228
|
-
(this.isProtocolV2()
|
|
229
|
-
? this.originalDescriptor.path || this.originalDescriptor.id
|
|
230
|
-
: undefined);
|
|
231
|
-
const sessionId =
|
|
232
|
-
sessionCacheDeviceKey && this.passphraseState
|
|
233
|
-
? deviceWalletSessionStore.get(sessionCacheDeviceKey, this.passphraseState)
|
|
234
|
-
: undefined;
|
|
235
|
-
return sessionId
|
|
236
|
-
? {
|
|
237
|
-
...features,
|
|
238
|
-
sessionId,
|
|
239
|
-
session_id: sessionId,
|
|
240
|
-
passphraseState: this.passphraseState,
|
|
241
|
-
}
|
|
242
|
-
: features;
|
|
226
|
+
return projectFeatures(this.state);
|
|
243
227
|
}
|
|
244
228
|
|
|
245
229
|
set features(features: Features | undefined) {
|
|
@@ -334,7 +318,7 @@ export class Device extends EventEmitter {
|
|
|
334
318
|
instanceId: this.instanceId,
|
|
335
319
|
createdAt: this.createdAt,
|
|
336
320
|
deviceType,
|
|
337
|
-
/** ID
|
|
321
|
+
/** Wallet-lifecycle ID; changes after the device is wiped or reinitialized. */
|
|
338
322
|
deviceId,
|
|
339
323
|
path: this.originalDescriptor?.path,
|
|
340
324
|
bleName,
|
|
@@ -691,16 +675,14 @@ export class Device extends EventEmitter {
|
|
|
691
675
|
const deviceId = _deviceId || this.getCurrentDeviceId();
|
|
692
676
|
if (deviceId) return deviceId;
|
|
693
677
|
if (this.isProtocolV2()) {
|
|
694
|
-
return this.originalDescriptor.path
|
|
678
|
+
return this.originalDescriptor.path;
|
|
695
679
|
}
|
|
696
680
|
return undefined;
|
|
697
681
|
}
|
|
698
682
|
|
|
699
683
|
private reconcileSessionCacheDeviceIdentity(previousDeviceId?: string) {
|
|
700
684
|
deviceWalletSessionStore.reconcileDeviceIdentity({
|
|
701
|
-
temporaryKey: this.isProtocolV2()
|
|
702
|
-
? this.originalDescriptor.path || this.originalDescriptor.id
|
|
703
|
-
: undefined,
|
|
685
|
+
temporaryKey: this.isProtocolV2() ? this.originalDescriptor.path : undefined,
|
|
704
686
|
previousDeviceId,
|
|
705
687
|
nextDeviceId: this.getCurrentDeviceId(),
|
|
706
688
|
});
|
|
@@ -806,43 +788,55 @@ export class Device extends EventEmitter {
|
|
|
806
788
|
return;
|
|
807
789
|
}
|
|
808
790
|
|
|
809
|
-
|
|
791
|
+
try {
|
|
792
|
+
const callInitialize = async (payload: Record<string, unknown>, initSession?: boolean) => {
|
|
793
|
+
const initStartAt = Date.now();
|
|
794
|
+
const { message } = await this.commands.typedCall('Initialize', 'Features', payload, {
|
|
795
|
+
// iOS BLE bound devices can need close to 20 seconds.
|
|
796
|
+
timeoutMs: 25 * 1000,
|
|
797
|
+
});
|
|
798
|
+
this.setLastInitializeDuration(Date.now() - initStartAt);
|
|
799
|
+
this._updateFeatures(message, initSession);
|
|
800
|
+
await TransportManager.reconfigure(this.features);
|
|
801
|
+
};
|
|
810
802
|
|
|
811
|
-
|
|
803
|
+
const expectedDeviceId = options?.deviceId;
|
|
804
|
+
if (expectedDeviceId) {
|
|
805
|
+
// Establish the live physical identity before sending wallet-bound state.
|
|
806
|
+
this.passphraseState = undefined;
|
|
807
|
+
await callInitialize({ is_contains_attach: true });
|
|
808
|
+
if (!this.checkDeviceId(expectedDeviceId)) {
|
|
809
|
+
throw ERRORS.TypedError(HardwareErrorCode.DeviceCheckDeviceIdError);
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
812
|
|
|
813
|
-
|
|
814
|
-
this.clearInternalState(options?.deviceId);
|
|
815
|
-
}
|
|
813
|
+
this.passphraseState = options?.passphraseState;
|
|
816
814
|
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
payload.session_id = internalState;
|
|
821
|
-
}
|
|
815
|
+
if (options?.initSession) {
|
|
816
|
+
this.clearInternalState(options?.deviceId);
|
|
817
|
+
}
|
|
822
818
|
|
|
823
|
-
|
|
824
|
-
payload
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
819
|
+
const internalState = this.getInternalState(options?.deviceId);
|
|
820
|
+
const payload: Record<string, unknown> = {
|
|
821
|
+
passphrase_state: options?.passphraseState,
|
|
822
|
+
is_contains_attach: true,
|
|
823
|
+
};
|
|
824
|
+
if (internalState) {
|
|
825
|
+
payload.session_id = internalState;
|
|
826
|
+
}
|
|
827
|
+
if (options?.deriveCardano) {
|
|
828
|
+
payload.derive_cardano = true;
|
|
829
|
+
}
|
|
828
830
|
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
}, 25 * 1000);
|
|
839
|
-
}),
|
|
840
|
-
]);
|
|
841
|
-
|
|
842
|
-
const initCostMs = Date.now() - initStartAt;
|
|
843
|
-
this.setLastInitializeDuration(initCostMs);
|
|
844
|
-
this._updateFeatures(message, options?.initSession);
|
|
845
|
-
await TransportManager.reconfigure(this.features);
|
|
831
|
+
const requiresWalletInitialize =
|
|
832
|
+
!expectedDeviceId ||
|
|
833
|
+
Boolean(internalState) ||
|
|
834
|
+
Boolean(options?.passphraseState) ||
|
|
835
|
+
options?.deriveCardano === true ||
|
|
836
|
+
options?.initSession === true;
|
|
837
|
+
if (requiresWalletInitialize) {
|
|
838
|
+
await callInitialize(payload, options?.initSession);
|
|
839
|
+
}
|
|
846
840
|
} catch (error) {
|
|
847
841
|
Log.error('Initialization failed:', error);
|
|
848
842
|
throw error;
|
|
@@ -972,10 +966,6 @@ export class Device extends EventEmitter {
|
|
|
972
966
|
? protoFeatures
|
|
973
967
|
: buildProtocolV1FeaturesPayload(protoFeatures, this.features);
|
|
974
968
|
|
|
975
|
-
// GetFeatures doesn't return 'session_id'
|
|
976
|
-
if (this.features?.sessionId && !feat.sessionId) {
|
|
977
|
-
feat.sessionId = this.features.sessionId;
|
|
978
|
-
}
|
|
979
969
|
feat.unlocked = feat.unlocked ?? true;
|
|
980
970
|
|
|
981
971
|
feat = fixFeaturesFirmwareVersion(feat);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ERRORS, HardwareError, HardwareErrorCode } from '@onekeyfe/hd-shared';
|
|
2
2
|
import {
|
|
3
3
|
DeviceErrorCode,
|
|
4
|
+
DeviceSessionErrorCode,
|
|
4
5
|
type FailureType,
|
|
5
6
|
type Messages,
|
|
6
7
|
type Transport,
|
|
@@ -52,7 +53,7 @@ const HIGH_VOLUME_DEBUG_CALLS = new Set([
|
|
|
52
53
|
'FirmwareUpload',
|
|
53
54
|
'ResourceAck',
|
|
54
55
|
]);
|
|
55
|
-
const SENSITIVE_DEBUG_CALLS = new Set(['
|
|
56
|
+
const SENSITIVE_DEBUG_CALLS = new Set(['DeviceSessionOpen']);
|
|
56
57
|
|
|
57
58
|
function shouldReduceDebugForCall(type: string) {
|
|
58
59
|
return HIGH_VOLUME_DEBUG_CALLS.has(type);
|
|
@@ -337,20 +338,27 @@ export class DeviceCommands {
|
|
|
337
338
|
if (this.disposed) {
|
|
338
339
|
return;
|
|
339
340
|
}
|
|
340
|
-
this.
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
341
|
+
const activeCall = this.callPromise;
|
|
342
|
+
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
343
|
+
const cancellation = (async () => {
|
|
344
|
+
await this.dispose(true);
|
|
345
|
+
await activeCall?.catch(() => undefined);
|
|
346
|
+
})();
|
|
347
|
+
|
|
348
|
+
try {
|
|
349
|
+
await Promise.race([
|
|
350
|
+
cancellation,
|
|
351
|
+
new Promise<void>(resolve => {
|
|
352
|
+
timer = setTimeout(resolve, 10 * 1000);
|
|
353
|
+
}),
|
|
354
|
+
]);
|
|
355
|
+
} finally {
|
|
356
|
+
if (timer) clearTimeout(timer);
|
|
357
|
+
if (this.callPromise === activeCall) {
|
|
352
358
|
this.callPromise = undefined;
|
|
353
359
|
}
|
|
360
|
+
// The cancellation work may finish after the bounded wait.
|
|
361
|
+
cancellation.catch(() => undefined);
|
|
354
362
|
}
|
|
355
363
|
}
|
|
356
364
|
|
|
@@ -451,7 +459,7 @@ export class DeviceCommands {
|
|
|
451
459
|
'PinMatrixAck',
|
|
452
460
|
'PassphraseAck',
|
|
453
461
|
'Cancel',
|
|
454
|
-
'
|
|
462
|
+
'DeviceSessionOpen',
|
|
455
463
|
'BixinPinInputOnDevice',
|
|
456
464
|
'FilesystemFileRead',
|
|
457
465
|
'FilesystemFileWrite',
|
|
@@ -599,6 +607,42 @@ export class DeviceCommands {
|
|
|
599
607
|
const isLegacyProtocolV2LockedFailure =
|
|
600
608
|
this.device.isProtocolV2() && /^device (?:is )?locked$/i.test(normalizedMessage);
|
|
601
609
|
if (
|
|
610
|
+
callType === 'DeviceSessionOpen' &&
|
|
611
|
+
subcode === DeviceSessionErrorCode.DeviceSessionError_InvalidSession
|
|
612
|
+
) {
|
|
613
|
+
error = ERRORS.TypedError(HardwareErrorCode.WalletSessionInvalid, message, {
|
|
614
|
+
failureCode: code,
|
|
615
|
+
subcode,
|
|
616
|
+
firmwareMessage: message,
|
|
617
|
+
});
|
|
618
|
+
} else if (
|
|
619
|
+
callType === 'DeviceSessionOpen' &&
|
|
620
|
+
subcode === DeviceSessionErrorCode.DeviceSessionError_UserCancelled
|
|
621
|
+
) {
|
|
622
|
+
error = ERRORS.TypedError(HardwareErrorCode.ActionCancelled, message, {
|
|
623
|
+
failureCode: code,
|
|
624
|
+
subcode,
|
|
625
|
+
firmwareMessage: message,
|
|
626
|
+
});
|
|
627
|
+
} else if (
|
|
628
|
+
callType === 'DeviceSessionOpen' &&
|
|
629
|
+
subcode === DeviceSessionErrorCode.DeviceSessionError_AttachPinUnavailable
|
|
630
|
+
) {
|
|
631
|
+
error = ERRORS.TypedError(HardwareErrorCode.DeviceCheckUnlockTypeError, message, {
|
|
632
|
+
failureCode: code,
|
|
633
|
+
subcode,
|
|
634
|
+
firmwareMessage: message,
|
|
635
|
+
});
|
|
636
|
+
} else if (
|
|
637
|
+
callType === 'DeviceSessionOpen' &&
|
|
638
|
+
subcode === DeviceSessionErrorCode.DeviceSessionError_PassphraseDisabled
|
|
639
|
+
) {
|
|
640
|
+
error = ERRORS.TypedError(HardwareErrorCode.DeviceNotOpenedPassphrase, message, {
|
|
641
|
+
failureCode: code,
|
|
642
|
+
subcode,
|
|
643
|
+
firmwareMessage: message,
|
|
644
|
+
});
|
|
645
|
+
} else if (
|
|
602
646
|
subcode === DeviceErrorCode.DeviceError_ActionCancelled ||
|
|
603
647
|
isLegacyProtocolV2ActionCancelledFailure
|
|
604
648
|
) {
|
|
@@ -29,6 +29,23 @@ const definedEntries = <T extends Record<string, unknown>>(value: T): T =>
|
|
|
29
29
|
Object.entries(value).filter(([, fieldValue]) => fieldValue !== undefined)
|
|
30
30
|
) as T;
|
|
31
31
|
|
|
32
|
+
const sanitizeRawFeatures = (features: Features): Features['raw'] => {
|
|
33
|
+
if (!features.raw) return undefined;
|
|
34
|
+
|
|
35
|
+
const raw = { ...features.raw };
|
|
36
|
+
if (raw.protocolV1Features) {
|
|
37
|
+
const { session_id: _sessionId, ...protocolV1Features } = raw.protocolV1Features;
|
|
38
|
+
const compatibilityFields = protocolV1Features as typeof protocolV1Features & {
|
|
39
|
+
sessionId?: string;
|
|
40
|
+
passphraseState?: string;
|
|
41
|
+
};
|
|
42
|
+
delete compatibilityFields.sessionId;
|
|
43
|
+
delete compatibilityFields.passphraseState;
|
|
44
|
+
raw.protocolV1Features = compatibilityFields as PROTO.Features;
|
|
45
|
+
}
|
|
46
|
+
return raw;
|
|
47
|
+
};
|
|
48
|
+
|
|
32
49
|
const imageVersion = (image?: DeviceFirmwareImageInfo | null) => image?.version ?? undefined;
|
|
33
50
|
|
|
34
51
|
const bytesToHex = (value: unknown): string | undefined => {
|
|
@@ -127,7 +144,7 @@ export const mapFeaturesToState = (features: Features): DeviceStatePatch => ({
|
|
|
127
144
|
},
|
|
128
145
|
capabilities: features.capabilities,
|
|
129
146
|
verification: definedEntries(features.verify ?? {}),
|
|
130
|
-
raw: features
|
|
147
|
+
raw: sanitizeRawFeatures(features),
|
|
131
148
|
});
|
|
132
149
|
|
|
133
150
|
export const mapProtocolV1FeaturesToState = (
|
|
@@ -16,6 +16,12 @@ export const projectFeatures = (state: StoredDeviceState): Features => {
|
|
|
16
16
|
delete publicRawFeatures.session_id;
|
|
17
17
|
delete publicRawFeatures.sessionId;
|
|
18
18
|
delete publicRawFeatures.passphraseState;
|
|
19
|
+
const publicRaw = snapshot.raw
|
|
20
|
+
? {
|
|
21
|
+
...snapshot.raw,
|
|
22
|
+
protocolV1Features: publicRawFeatures,
|
|
23
|
+
}
|
|
24
|
+
: undefined;
|
|
19
25
|
const rawOneKeyFeatures = snapshot.raw?.protocolV1OneKeyFeatures ?? {};
|
|
20
26
|
const bootloaderMode =
|
|
21
27
|
snapshot.protocol === 'V1'
|
|
@@ -84,7 +90,7 @@ export const projectFeatures = (state: StoredDeviceState): Features => {
|
|
|
84
90
|
se04BootVersion: snapshot.versions.se04Boot,
|
|
85
91
|
seVersion: snapshot.versions.se ?? null,
|
|
86
92
|
verify: snapshot.verification,
|
|
87
|
-
raw:
|
|
93
|
+
raw: publicRaw,
|
|
88
94
|
device_id: snapshot.identity.deviceId ?? undefined,
|
|
89
95
|
ble_name: snapshot.identity.bleName ?? undefined,
|
|
90
96
|
passphrase_protection: snapshot.status.passphraseProtection ?? undefined,
|
package/src/index.ts
CHANGED
|
@@ -19,6 +19,11 @@ export * from './types';
|
|
|
19
19
|
export { whitelist, whitelistExtension } from './data/config';
|
|
20
20
|
export { executeCallback, cleanupCallback };
|
|
21
21
|
export { preloadSessionCache } from './device/Device';
|
|
22
|
+
export {
|
|
23
|
+
getFirmwareUpdateHostBindingGeneration,
|
|
24
|
+
registerFirmwareUpdateHostBinding,
|
|
25
|
+
unregisterFirmwareUpdateHostBinding,
|
|
26
|
+
} from './api/firmware/FirmwareHostBinding';
|
|
22
27
|
|
|
23
28
|
const HardwareSdk = ({
|
|
24
29
|
init,
|