@onekeyfe/hd-core 1.2.0-alpha.66 → 1.2.0-alpha.67
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__/AllNetworkGetAddressBase.tracing.test.ts +0 -313
- package/__tests__/DeviceCommands.test.ts +13 -59
- package/__tests__/DeviceEventRegistration.test.ts +0 -6
- package/__tests__/check-all-firmware-release-protocol-v2.test.ts +3 -198
- package/__tests__/connectSettings.test.ts +47 -5
- package/__tests__/device-initialize-timeout.test.ts +56 -0
- package/__tests__/device-lifecycle-events.test.ts +3 -105
- package/__tests__/device-pool-state.test.ts +0 -22
- package/__tests__/device-settings.test.ts +18 -39
- package/__tests__/device-state-contract.test.ts +0 -1
- package/__tests__/device-state-mapper.test.ts +1 -13
- package/__tests__/device-utils.test.ts +1 -48
- package/__tests__/deviceSettings.test.ts +1 -11
- package/__tests__/firmware-update/check-all-firmware-release.test.ts +175 -0
- package/__tests__/firmware-update/device-update-bootloader.test.ts +87 -0
- 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-preparation-error.test.ts +27 -0
- package/__tests__/firmware-update/firmware-update-bootloader-poll.test.ts +200 -0
- package/__tests__/firmware-update/firmware-update-capabilities.test.ts +13 -0
- package/__tests__/firmware-update/firmware-update-plan-bootloader-identity.test.ts +394 -0
- package/__tests__/firmware-update/firmware-update-plan.test.ts +593 -0
- package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +231 -0
- package/__tests__/firmware-update/firmware-update-v2-download-before-boot.test.ts +59 -31
- package/__tests__/firmware-update/firmware-update-v3-reconnect.test.ts +58 -0
- package/__tests__/firmware-update/firmware-upload-source.test.ts +70 -0
- package/__tests__/get-device-state.test.ts +12 -132
- package/__tests__/homescreen.test.ts +1 -41
- package/__tests__/kaspa-use-tweak-pro2.test.ts +2 -2
- package/__tests__/kaspaSignTransaction.test.ts +26 -3
- package/__tests__/logBlockEvent.test.ts +1 -1
- package/__tests__/method-protocol-support.test.ts +0 -19
- package/__tests__/open-wallet-session.test.ts +37 -568
- package/__tests__/protocol-v2-unlock-policy.test.ts +37 -300
- package/__tests__/protocol-v2.test.ts +1153 -1458
- package/__tests__/protocolV2FileWrite.test.ts +0 -152
- package/__tests__/protocolV2UiInteraction.test.ts +0 -63
- package/__tests__/public-pro2-api-boundary.test.ts +0 -1
- package/__tests__/search-devices.test.ts +3 -12
- package/__tests__/tron-sign-message-init.test.ts +2 -2
- package/dist/api/BaseMethod.d.ts +1 -3
- package/dist/api/BaseMethod.d.ts.map +1 -1
- package/dist/api/CheckAllFirmwareRelease.d.ts +1 -2
- package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
- package/dist/api/FirmwareUpdate.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV2.d.ts +10 -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 +27 -13
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/GetPassphraseState.d.ts.map +1 -1
- package/dist/api/OpenWalletSession.d.ts.map +1 -1
- package/dist/api/SearchDevices.d.ts.map +1 -1
- package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
- package/dist/api/device/DeviceSettings.d.ts.map +1 -1
- package/dist/api/device/DeviceUnlock.d.ts +2 -2
- 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 +25 -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/FirmwarePreparationError.d.ts +3 -0
- package/dist/api/firmware/FirmwarePreparationError.d.ts.map +1 -0
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +11 -4
- 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 +25 -0
- package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +1 -0
- package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts +32 -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/progressThrottle.d.ts +3 -0
- package/dist/api/firmware/progressThrottle.d.ts.map +1 -0
- 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 +0 -9
- package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -1
- package/dist/api/index.d.ts +0 -2
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/kaspa/KaspaGetAddress.d.ts +1 -1
- package/dist/api/kaspa/KaspaSignTransaction.d.ts +1 -1
- package/dist/api/kaspa/KaspaSignTransaction.d.ts.map +1 -1
- package/dist/api/polkadot/PolkadotGetAddress.d.ts +1 -1
- package/dist/api/polkadot/networks.d.ts +1 -1
- package/dist/api/protocol-v2/ProtocolInfoRequest.d.ts.map +1 -1
- package/dist/api/protocol-v2/helpers.d.ts.map +1 -1
- package/dist/api/solana/SolSignMessage.d.ts +1 -1
- package/dist/api/solana/SolSignOffchainMessage.d.ts +1 -1
- package/dist/api/solana/SolSignTransaction.d.ts +2 -2
- package/dist/api/stellar/StellarSignTransaction.d.ts +1 -1
- package/dist/api/sui/SuiGetAddress.d.ts +1 -1
- package/dist/api/sui/SuiGetPublicKey.d.ts +1 -1
- package/dist/api/sui/SuiSignMessage.d.ts +1 -1
- package/dist/api/sui/SuiSignTransaction.d.ts +1 -1
- package/dist/api/ton/TonGetAddress.d.ts +1 -1
- package/dist/api/ton/TonSignMessage.d.ts +1 -1
- package/dist/api/ton/TonSignProof.d.ts +1 -1
- package/dist/api/tron/TronSignMessage.d.ts +2 -2
- package/dist/api/tron/TronSignTransaction.d.ts +1 -1
- package/dist/core/deviceEventRegistration.d.ts +0 -2
- package/dist/core/deviceEventRegistration.d.ts.map +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/data-manager/DataManager.d.ts +4 -9
- package/dist/data-manager/DataManager.d.ts.map +1 -1
- package/dist/data-manager/TransportManager.d.ts.map +1 -1
- package/dist/data-manager/connectSettings.d.ts.map +1 -1
- package/dist/device/Device.d.ts +6 -29
- package/dist/device/Device.d.ts.map +1 -1
- package/dist/device/DeviceCommands.d.ts +4 -4
- package/dist/device/DeviceCommands.d.ts.map +1 -1
- package/dist/device/DeviceConnector.d.ts +1 -2
- package/dist/device/DeviceConnector.d.ts.map +1 -1
- package/dist/device/DevicePool.d.ts.map +1 -1
- package/dist/deviceProfile/protocolV2DeviceIdentity.d.ts.map +1 -1
- package/dist/events/device.d.ts +0 -4
- package/dist/events/device.d.ts.map +1 -1
- package/dist/events/logBlockEvent.d.ts.map +1 -1
- package/dist/events/ui-promise.d.ts +2 -4
- package/dist/events/ui-promise.d.ts.map +1 -1
- package/dist/events/ui-request.d.ts +2 -31
- package/dist/events/ui-request.d.ts.map +1 -1
- package/dist/events/ui-response.d.ts +2 -10
- package/dist/events/ui-response.d.ts.map +1 -1
- package/dist/index.d.ts +247 -243
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3773 -3054
- package/dist/inject.d.ts +1 -6
- package/dist/inject.d.ts.map +1 -1
- package/dist/lowLevelInject.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/features.d.ts +4 -0
- package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/firmware.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/lockedError.d.ts +2 -0
- package/dist/protocols/protocol-v2/lockedError.d.ts.map +1 -0
- package/dist/protocols/protocol-v2/uiInteraction.d.ts +4 -7
- package/dist/protocols/protocol-v2/uiInteraction.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/unlockPolicy.d.ts +3 -1
- package/dist/protocols/protocol-v2/unlockPolicy.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/unlockRetry.d.ts +10 -0
- package/dist/protocols/protocol-v2/unlockRetry.d.ts.map +1 -0
- package/dist/protocols/protocol-v2/walletSession.d.ts +1 -6
- 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 +5 -3
- package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
- package/dist/types/api/deviceUnlock.d.ts +1 -5
- 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 -2
- package/dist/types/api/export.d.ts.map +1 -1
- package/dist/types/api/firmwareUpdate.d.ts +70 -4
- 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 +28 -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 -7
- package/dist/types/api/index.d.ts.map +1 -1
- package/dist/types/api/protocolV2.d.ts +0 -3
- package/dist/types/api/protocolV2.d.ts.map +1 -1
- package/dist/types/device.d.ts +2 -2
- package/dist/types/device.d.ts.map +1 -1
- package/dist/types/params.d.ts +0 -1
- package/dist/types/params.d.ts.map +1 -1
- package/dist/types/settings.d.ts +21 -38
- package/dist/types/settings.d.ts.map +1 -1
- package/dist/utils/deviceFeaturesCompat.d.ts +1 -0
- package/dist/utils/deviceFeaturesCompat.d.ts.map +1 -1
- package/dist/utils/deviceFeaturesUtils.d.ts +0 -4
- package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
- package/dist/utils/deviceInfoUtils.d.ts.map +1 -1
- package/dist/utils/deviceSettings.d.ts.map +1 -1
- package/dist/utils/homescreen.d.ts +0 -4
- package/dist/utils/homescreen.d.ts.map +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/patch.d.ts +1 -1
- package/dist/utils/patch.d.ts.map +1 -1
- package/dist/utils/pro2Wallpaper.d.ts +0 -10
- package/dist/utils/pro2Wallpaper.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/api/BaseMethod.ts +10 -8
- package/src/api/CheckAllFirmwareRelease.ts +60 -59
- package/src/api/FirmwareUpdate.ts +15 -7
- package/src/api/FirmwareUpdateV2.ts +298 -126
- package/src/api/FirmwareUpdateV3.ts +265 -63
- package/src/api/FirmwareUpdateV4.ts +1017 -602
- package/src/api/GetPassphraseState.ts +1 -7
- package/src/api/OpenWalletSession.ts +17 -71
- package/src/api/SearchDevices.ts +1 -3
- package/src/api/allnetwork/AllNetworkGetAddress.ts +21 -21
- package/src/api/allnetwork/AllNetworkGetAddressBase.ts +11 -36
- package/src/api/device/DeviceSettings.ts +4 -5
- package/src/api/device/DeviceUnlock.ts +3 -8
- package/src/api/device/DeviceUpdateBootloader.ts +125 -6
- package/src/api/firmware/FirmwareArtifactSource.ts +278 -0
- package/src/api/firmware/FirmwareHostBinding.ts +100 -0
- package/src/api/firmware/FirmwarePreparationError.ts +12 -0
- package/src/api/firmware/FirmwareUpdateBaseMethod.ts +83 -27
- package/src/api/firmware/FirmwareUpdateCapabilities.ts +9 -0
- package/src/api/firmware/FirmwareUpdatePlan.ts +772 -0
- package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +449 -0
- package/src/api/firmware/progressThrottle.ts +44 -0
- package/src/api/firmware/updateBootloader.ts +19 -4
- package/src/api/firmware/uploadFirmware.ts +144 -39
- package/src/api/helpers/protocolV2FileWrite.ts +63 -202
- package/src/api/index.ts +0 -2
- package/src/api/kaspa/KaspaGetAddress.ts +1 -1
- package/src/api/kaspa/KaspaSignTransaction.ts +13 -2
- package/src/api/polkadot/networks.ts +3 -3
- package/src/api/protocol-v2/ProtocolInfoRequest.ts +1 -3
- package/src/api/protocol-v2/helpers.ts +1 -1
- package/src/api/solana/SolSignMessage.ts +1 -1
- package/src/api/solana/SolSignOffchainMessage.ts +1 -1
- package/src/api/solana/SolSignTransaction.ts +2 -2
- package/src/api/sui/SuiGetAddress.ts +1 -1
- package/src/api/sui/SuiGetPublicKey.ts +1 -1
- package/src/api/sui/SuiSignMessage.ts +1 -1
- package/src/api/sui/SuiSignTransaction.ts +1 -1
- package/src/api/ton/TonGetAddress.ts +1 -1
- package/src/api/ton/TonSignMessage.ts +1 -1
- package/src/api/ton/TonSignProof.ts +1 -1
- package/src/api/tron/TronSignMessage.ts +2 -2
- package/src/api/tron/TronSignTransaction.ts +1 -1
- package/src/core/deviceEventRegistration.ts +0 -4
- package/src/core/index.ts +111 -213
- package/src/data/messages/messages-protocol-v2.json +0 -25
- package/src/data-manager/DataManager.ts +41 -113
- package/src/data-manager/TransportManager.ts +0 -6
- package/src/data-manager/connectSettings.ts +11 -0
- package/src/device/Device.ts +49 -274
- package/src/device/DeviceCommands.ts +4 -31
- package/src/device/DeviceConnector.ts +13 -33
- package/src/device/DevicePool.ts +7 -21
- package/src/deviceProfile/buildDeviceFeatures.ts +2 -2
- package/src/deviceProfile/protocolV2DeviceIdentity.ts +0 -3
- package/src/events/device.ts +0 -4
- package/src/events/logBlockEvent.ts +0 -1
- package/src/events/ui-promise.ts +2 -4
- package/src/events/ui-request.ts +2 -36
- package/src/events/ui-response.ts +2 -12
- package/src/index.ts +5 -0
- package/src/inject.ts +24 -60
- package/src/lowLevelInject.ts +8 -7
- package/src/protocols/protocol-v2/features.ts +7 -10
- package/src/protocols/protocol-v2/firmware.ts +0 -2
- package/src/protocols/protocol-v2/lockedError.ts +10 -0
- package/src/protocols/protocol-v2/uiInteraction.ts +6 -46
- package/src/protocols/protocol-v2/unlockPolicy.ts +105 -1
- package/src/protocols/protocol-v2/unlockRetry.ts +109 -0
- package/src/protocols/protocol-v2/walletSession.ts +36 -214
- package/src/topLevelInject.ts +8 -7
- package/src/types/api/checkAllFirmwareRelease.ts +5 -3
- package/src/types/api/deviceUnlock.ts +1 -12
- package/src/types/api/deviceUpdateBootloader.ts +6 -0
- package/src/types/api/export.ts +18 -1
- package/src/types/api/firmwareUpdate.ts +78 -6
- package/src/types/api/firmwareUpdateCapabilities.ts +9 -0
- package/src/types/api/firmwareUpdatePlan.ts +38 -0
- package/src/types/api/firmwareUpdatePreparedPlan.ts +53 -0
- package/src/types/api/index.ts +14 -13
- package/src/types/api/protocolV2.ts +0 -13
- package/src/types/device.ts +3 -15
- package/src/types/params.ts +1 -7
- package/src/types/settings.ts +22 -60
- package/src/utils/deviceFeaturesCompat.ts +6 -5
- package/src/utils/deviceFeaturesUtils.ts +3 -14
- package/src/utils/deviceInfoUtils.ts +0 -2
- package/src/utils/deviceSettings.ts +0 -3
- package/src/utils/homescreen.ts +6 -32
- package/src/utils/index.ts +1 -6
- package/src/utils/pro2Wallpaper.ts +8 -35
- package/__tests__/core-initialization.test.ts +0 -23
- package/__tests__/device-connector-protocol.test.ts +0 -81
- package/__tests__/deviceUploadNft.test.ts +0 -316
- package/__tests__/pro2Nft.test.ts +0 -108
- package/__tests__/protocol-binding.test.ts +0 -89
- package/__tests__/protocol-v2-resources.test.ts +0 -340
- package/__tests__/protocol-v2-ui-lifecycle.test.ts +0 -91
- package/__tests__/uiProgressThrottle.test.ts +0 -74
- package/__tests__/uiPromiseRegistry.test.ts +0 -115
- package/dist/api/DetectDeviceConnectProtocol.d.ts +0 -7
- package/dist/api/DetectDeviceConnectProtocol.d.ts.map +0 -1
- package/dist/api/protocol-v2/DeviceUploadNft.d.ts +0 -31
- package/dist/api/protocol-v2/DeviceUploadNft.d.ts.map +0 -1
- package/dist/core/uiPromiseRegistry.d.ts +0 -6
- package/dist/core/uiPromiseRegistry.d.ts.map +0 -1
- package/dist/protocols/protocol-v2/resources.d.ts +0 -30
- package/dist/protocols/protocol-v2/resources.d.ts.map +0 -1
- package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts +0 -22
- package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts.map +0 -1
- package/dist/types/api/detectDeviceConnectProtocol.d.ts +0 -4
- package/dist/types/api/detectDeviceConnectProtocol.d.ts.map +0 -1
- package/dist/utils/pro2Nft.d.ts +0 -31
- package/dist/utils/pro2Nft.d.ts.map +0 -1
- package/dist/utils/uiProgressThrottle.d.ts +0 -3
- package/dist/utils/uiProgressThrottle.d.ts.map +0 -1
- package/src/api/DetectDeviceConnectProtocol.ts +0 -18
- package/src/api/protocol-v2/DeviceUploadNft.ts +0 -197
- package/src/core/uiPromiseRegistry.ts +0 -63
- package/src/protocols/protocol-v2/resources.ts +0 -390
- package/src/protocols/protocol-v2/unlockPolicyRunner.ts +0 -131
- package/src/types/api/detectDeviceConnectProtocol.ts +0 -6
- package/src/utils/pro2Nft.ts +0 -142
- package/src/utils/uiProgressThrottle.ts +0 -63
|
@@ -10,6 +10,7 @@ import { bytesToHex } from '../helpers/hexUtils';
|
|
|
10
10
|
import { DataManager } from '../../data-manager';
|
|
11
11
|
import { DevicePool } from '../../device/DevicePool';
|
|
12
12
|
import { buildProtocolV1FeaturesPayload } from '../../deviceProfile';
|
|
13
|
+
import { openFirmwareByteSource, readFirmwareByteSourceFully } from './FirmwareArtifactSource';
|
|
13
14
|
|
|
14
15
|
import type { KnownDevice } from '../../types';
|
|
15
16
|
import type { TypedCall, TypedResponseMessage } from '../../device/DeviceCommands';
|
|
@@ -17,6 +18,7 @@ import type { PROTO } from '../../constants';
|
|
|
17
18
|
import type { CoreMessage, IFirmwareUpdateProgressType } from '../../events';
|
|
18
19
|
import type { Success } from '@onekeyfe/hd-transport';
|
|
19
20
|
import type { Device } from '../../device/Device';
|
|
21
|
+
import type { FirmwareByteSource } from './FirmwareArtifactSource';
|
|
20
22
|
|
|
21
23
|
const NEW_BOOT_UPRATE_FIRMWARE_VERSION = '2.4.5';
|
|
22
24
|
const SESSION_ERROR = 'session not found';
|
|
@@ -88,17 +90,20 @@ export const waitBleInstall = async (updateType: string) => {
|
|
|
88
90
|
}
|
|
89
91
|
};
|
|
90
92
|
|
|
91
|
-
|
|
93
|
+
const toArrayBuffer = (payload: ArrayBuffer | Buffer): ArrayBuffer => {
|
|
94
|
+
if (payload instanceof ArrayBuffer) {
|
|
95
|
+
return payload;
|
|
96
|
+
}
|
|
97
|
+
return new Uint8Array(payload.buffer, payload.byteOffset, payload.byteLength).slice().buffer;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
export const uploadFirmwareFromSource = async (
|
|
92
101
|
updateType: 'firmware' | 'ble',
|
|
93
102
|
typedCall: TypedCall,
|
|
94
103
|
postMessage: (message: CoreMessage) => void,
|
|
95
104
|
device: Device,
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
rebootOnSuccess,
|
|
99
|
-
}: PROTO.FirmwareUpload & {
|
|
100
|
-
rebootOnSuccess?: boolean;
|
|
101
|
-
},
|
|
105
|
+
source: FirmwareByteSource,
|
|
106
|
+
rebootOnSuccess?: boolean,
|
|
102
107
|
isUpdateBootloader?: boolean
|
|
103
108
|
) => {
|
|
104
109
|
const deviceType = device.getCurrentDeviceType();
|
|
@@ -119,20 +124,20 @@ export const uploadFirmware = async (
|
|
|
119
124
|
if (supportUpgradeFileHeader) {
|
|
120
125
|
// Extract and validate firmware header (first 1KB)
|
|
121
126
|
const HEADER_SIZE = 1024;
|
|
122
|
-
if (
|
|
127
|
+
if (source.size < HEADER_SIZE) {
|
|
123
128
|
throw ERRORS.TypedError(
|
|
124
129
|
HardwareErrorCode.RuntimeError,
|
|
125
|
-
`firmware payload too small: ${
|
|
130
|
+
`firmware payload too small: ${source.size} bytes, expected at least ${HEADER_SIZE} bytes`
|
|
126
131
|
);
|
|
127
132
|
}
|
|
128
133
|
|
|
129
134
|
Log.debug('Uploading firmware header:', {
|
|
130
135
|
size: HEADER_SIZE,
|
|
131
|
-
totalSize:
|
|
136
|
+
totalSize: source.size,
|
|
132
137
|
});
|
|
133
138
|
postProgressTip(device, 'UploadingFirmwareHeader', postMessage);
|
|
134
139
|
|
|
135
|
-
const header = new Uint8Array(
|
|
140
|
+
const header = new Uint8Array(await source.readAt(0, HEADER_SIZE));
|
|
136
141
|
|
|
137
142
|
try {
|
|
138
143
|
const headerRes = await typedCall('UpgradeFileHeader', 'Success', {
|
|
@@ -169,6 +174,9 @@ export const uploadFirmware = async (
|
|
|
169
174
|
postProgressMessage(device, 0, 'installingFirmware', postMessage);
|
|
170
175
|
let updateResponse: TypedResponseMessage<'Success'>;
|
|
171
176
|
try {
|
|
177
|
+
// Classic/Mini bootloaders accept one protobuf payload and do not expose
|
|
178
|
+
// a request-range protocol. Other device families remain fully streamed.
|
|
179
|
+
const payload = await readFirmwareByteSourceFully(source);
|
|
172
180
|
updateResponse = await typedCall('FirmwareUpload', 'Success', {
|
|
173
181
|
payload,
|
|
174
182
|
});
|
|
@@ -200,9 +208,7 @@ export const uploadFirmware = async (
|
|
|
200
208
|
updateType,
|
|
201
209
|
postMessage,
|
|
202
210
|
device,
|
|
203
|
-
|
|
204
|
-
payload,
|
|
205
|
-
},
|
|
211
|
+
source,
|
|
206
212
|
rebootOnSuccess
|
|
207
213
|
);
|
|
208
214
|
return response.message;
|
|
@@ -211,7 +217,7 @@ export const uploadFirmware = async (
|
|
|
211
217
|
|
|
212
218
|
postConfirmationMessage(device);
|
|
213
219
|
postProgressTip(device, 'ConfirmOnDevice', postMessage);
|
|
214
|
-
const length =
|
|
220
|
+
const length = source.size;
|
|
215
221
|
|
|
216
222
|
let response = await typedCall('FirmwareErase', ['FirmwareRequest', 'Success'], { length });
|
|
217
223
|
postProgressTip(device, 'FirmwareEraseSuccess', postMessage);
|
|
@@ -220,7 +226,7 @@ export const uploadFirmware = async (
|
|
|
220
226
|
const start = response.message.offset!;
|
|
221
227
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
222
228
|
const end = response.message.offset! + response.message.length!;
|
|
223
|
-
const chunk =
|
|
229
|
+
const chunk = await source.readAt(start, end - start);
|
|
224
230
|
|
|
225
231
|
if (start > 0) {
|
|
226
232
|
postProgressMessage(
|
|
@@ -249,11 +255,45 @@ export const uploadFirmware = async (
|
|
|
249
255
|
throw ERRORS.TypedError(HardwareErrorCode.RuntimeError, 'uploadFirmware: unknown device model');
|
|
250
256
|
};
|
|
251
257
|
|
|
258
|
+
export const uploadFirmware = async (
|
|
259
|
+
updateType: 'firmware' | 'ble',
|
|
260
|
+
typedCall: TypedCall,
|
|
261
|
+
postMessage: (message: CoreMessage) => void,
|
|
262
|
+
device: Device,
|
|
263
|
+
{
|
|
264
|
+
payload,
|
|
265
|
+
rebootOnSuccess,
|
|
266
|
+
}: PROTO.FirmwareUpload & {
|
|
267
|
+
rebootOnSuccess?: boolean;
|
|
268
|
+
},
|
|
269
|
+
isUpdateBootloader?: boolean
|
|
270
|
+
) => {
|
|
271
|
+
const source = await openFirmwareByteSource({
|
|
272
|
+
binary: toArrayBuffer(payload),
|
|
273
|
+
});
|
|
274
|
+
if (!source) {
|
|
275
|
+
throw ERRORS.TypedError(HardwareErrorCode.RuntimeError, 'firmware payload is empty');
|
|
276
|
+
}
|
|
277
|
+
try {
|
|
278
|
+
return await uploadFirmwareFromSource(
|
|
279
|
+
updateType,
|
|
280
|
+
typedCall,
|
|
281
|
+
postMessage,
|
|
282
|
+
device,
|
|
283
|
+
source,
|
|
284
|
+
rebootOnSuccess,
|
|
285
|
+
isUpdateBootloader
|
|
286
|
+
);
|
|
287
|
+
} finally {
|
|
288
|
+
await source.close();
|
|
289
|
+
}
|
|
290
|
+
};
|
|
291
|
+
|
|
252
292
|
const newTouchUpdateProcess = async (
|
|
253
293
|
updateType: 'firmware' | 'ble',
|
|
254
294
|
postMessage: (message: CoreMessage) => void,
|
|
255
295
|
device: Device,
|
|
256
|
-
|
|
296
|
+
source: FirmwareByteSource,
|
|
257
297
|
rebootOnSuccess = true
|
|
258
298
|
) => {
|
|
259
299
|
let typedCall = device.getCommands().typedCall.bind(device.getCommands());
|
|
@@ -263,13 +303,13 @@ const newTouchUpdateProcess = async (
|
|
|
263
303
|
const env = DataManager.getSettings('env');
|
|
264
304
|
const perPackageSize = DataManager.isBleConnect(env) ? 16 : 128;
|
|
265
305
|
const chunkSize = 1024 * perPackageSize;
|
|
266
|
-
const totalChunks = Math.ceil(
|
|
306
|
+
const totalChunks = Math.ceil(source.size / chunkSize);
|
|
267
307
|
let offset = 0;
|
|
268
308
|
for (let i = 0; i < totalChunks; i++) {
|
|
269
309
|
const chunkStart = i * chunkSize;
|
|
270
|
-
const chunkEnd = Math.min(chunkStart + chunkSize,
|
|
310
|
+
const chunkEnd = Math.min(chunkStart + chunkSize, source.size);
|
|
271
311
|
const chunkLength = chunkEnd - chunkStart;
|
|
272
|
-
const chunk =
|
|
312
|
+
const chunk = await source.readAt(chunkStart, chunkLength);
|
|
273
313
|
const overwrite = i === 0;
|
|
274
314
|
const progress = Math.round(((i + 1) / totalChunks) * 100);
|
|
275
315
|
const writeRes = await emmcFileWriteWithRetry(
|
|
@@ -322,12 +362,7 @@ const newTouchUpdateProcess = async (
|
|
|
322
362
|
try {
|
|
323
363
|
if (isBleReconnect) {
|
|
324
364
|
try {
|
|
325
|
-
await device.deviceConnector?.acquire(
|
|
326
|
-
device.originalDescriptor.id,
|
|
327
|
-
null,
|
|
328
|
-
true,
|
|
329
|
-
device.originalDescriptor.protocolType
|
|
330
|
-
);
|
|
365
|
+
await device.deviceConnector?.acquire(device.originalDescriptor.id, null, true);
|
|
331
366
|
const typedCall = device.getCommands().typedCall.bind(device.getCommands());
|
|
332
367
|
await Promise.race([
|
|
333
368
|
typedCall('Initialize', 'Features', {}),
|
|
@@ -346,8 +381,7 @@ const newTouchUpdateProcess = async (
|
|
|
346
381
|
const devicesDescriptor = deviceDiff?.descriptors ?? [];
|
|
347
382
|
const { deviceList } = await DevicePool.getDevices(
|
|
348
383
|
devicesDescriptor,
|
|
349
|
-
device.originalDescriptor.id
|
|
350
|
-
{ connectProtocol: device.originalDescriptor.protocolType }
|
|
384
|
+
device.originalDescriptor.id
|
|
351
385
|
);
|
|
352
386
|
if (deviceList.length === 1) {
|
|
353
387
|
device.updateFromCache(deviceList[0]);
|
|
@@ -422,12 +456,7 @@ const emmcFileWriteWithRetry = async (
|
|
|
422
456
|
const env = DataManager.getSettings('env');
|
|
423
457
|
if (DataManager.isBleConnect(env)) {
|
|
424
458
|
await wait(3000);
|
|
425
|
-
await device.deviceConnector?.acquire(
|
|
426
|
-
device.originalDescriptor.id,
|
|
427
|
-
null,
|
|
428
|
-
true,
|
|
429
|
-
device.originalDescriptor.protocolType
|
|
430
|
-
);
|
|
459
|
+
await device.deviceConnector?.acquire(device.originalDescriptor.id, null, true);
|
|
431
460
|
await device.initialize();
|
|
432
461
|
} else if (
|
|
433
462
|
error?.message?.indexOf(SESSION_ERROR) > -1 ||
|
|
@@ -435,9 +464,7 @@ const emmcFileWriteWithRetry = async (
|
|
|
435
464
|
) {
|
|
436
465
|
const deviceDiff = await device.deviceConnector?.enumerate();
|
|
437
466
|
const devicesDescriptor = deviceDiff?.descriptors ?? [];
|
|
438
|
-
const { deviceList } = await DevicePool.getDevices(devicesDescriptor, undefined
|
|
439
|
-
connectProtocol: device.originalDescriptor.protocolType,
|
|
440
|
-
});
|
|
467
|
+
const { deviceList } = await DevicePool.getDevices(devicesDescriptor, undefined);
|
|
441
468
|
if (deviceList.length === 1 && deviceList[0]?.isBootloader()) {
|
|
442
469
|
device.updateFromCache(deviceList[0]);
|
|
443
470
|
await device.acquire();
|
|
@@ -503,6 +530,67 @@ export const updateResource = async (
|
|
|
503
530
|
return processResourceRequest(typedCall, res, data);
|
|
504
531
|
};
|
|
505
532
|
|
|
533
|
+
export const updateResourceFromSource = async (
|
|
534
|
+
typedCall: TypedCall,
|
|
535
|
+
fileName: string,
|
|
536
|
+
source: FirmwareByteSource,
|
|
537
|
+
onConfirmAfter?: () => void
|
|
538
|
+
) => {
|
|
539
|
+
const initialLength = Math.min(INIT_DATA_CHUNK_SIZE, source.size);
|
|
540
|
+
const initialChunk = new Uint8Array(await source.readAt(0, initialLength));
|
|
541
|
+
let response = await typedCall('ResourceUpdate', ['ResourceRequest', 'Success'], {
|
|
542
|
+
file_name: fileName,
|
|
543
|
+
data_length: source.size,
|
|
544
|
+
initial_data_chunk: bytesToHex(initialChunk),
|
|
545
|
+
hash: bytesToHex(blake2s(initialChunk)),
|
|
546
|
+
});
|
|
547
|
+
onConfirmAfter?.();
|
|
548
|
+
|
|
549
|
+
while (response.type !== 'Success') {
|
|
550
|
+
const { offset, data_length: dataLength } = response.message;
|
|
551
|
+
if (
|
|
552
|
+
!Number.isSafeInteger(offset) ||
|
|
553
|
+
offset === undefined ||
|
|
554
|
+
offset < 0 ||
|
|
555
|
+
!Number.isSafeInteger(dataLength) ||
|
|
556
|
+
dataLength === undefined ||
|
|
557
|
+
dataLength <= 0 ||
|
|
558
|
+
offset + dataLength > source.size
|
|
559
|
+
) {
|
|
560
|
+
throw ERRORS.TypedError(
|
|
561
|
+
HardwareErrorCode.RuntimeError,
|
|
562
|
+
'Device requested an invalid firmware resource range'
|
|
563
|
+
);
|
|
564
|
+
}
|
|
565
|
+
const chunk = new Uint8Array(await source.readAt(offset, dataLength));
|
|
566
|
+
response = await typedCall('ResourceAck', ['ResourceRequest', 'Success'], {
|
|
567
|
+
data_chunk: bytesToHex(chunk),
|
|
568
|
+
hash: bytesToHex(blake2s(chunk)),
|
|
569
|
+
});
|
|
570
|
+
}
|
|
571
|
+
return response.message;
|
|
572
|
+
};
|
|
573
|
+
|
|
574
|
+
export const updateResourcesFromSources = async (
|
|
575
|
+
typedCall: TypedCall,
|
|
576
|
+
postMessage: (message: CoreMessage) => void,
|
|
577
|
+
device: Device,
|
|
578
|
+
entries: ReadonlyArray<{ entryName: string; source: FirmwareByteSource }>
|
|
579
|
+
) => {
|
|
580
|
+
postProgressTip(device, 'UpdateSysResource', postMessage);
|
|
581
|
+
for (const [index, entry] of entries.entries()) {
|
|
582
|
+
await updateResourceFromSource(typedCall, entry.entryName, entry.source);
|
|
583
|
+
postProgressMessage(
|
|
584
|
+
device,
|
|
585
|
+
Math.floor(((index + 1) / entries.length) * 100),
|
|
586
|
+
'installingFirmware',
|
|
587
|
+
postMessage
|
|
588
|
+
);
|
|
589
|
+
}
|
|
590
|
+
postProgressTip(device, 'UpdateSysResourceSuccess', postMessage);
|
|
591
|
+
return true;
|
|
592
|
+
};
|
|
593
|
+
|
|
506
594
|
export const updateResources = async (
|
|
507
595
|
typedCall: TypedCall,
|
|
508
596
|
postMessage: (message: CoreMessage) => void,
|
|
@@ -537,11 +625,28 @@ export const updateBootloader = async (
|
|
|
537
625
|
typedCall: TypedCall,
|
|
538
626
|
postMessage: (message: CoreMessage) => void,
|
|
539
627
|
device: Device,
|
|
540
|
-
|
|
628
|
+
data: ArrayBuffer
|
|
629
|
+
) => {
|
|
630
|
+
const source = await openFirmwareByteSource({ binary: data });
|
|
631
|
+
if (!source) {
|
|
632
|
+
throw ERRORS.TypedError(HardwareErrorCode.RuntimeError, 'bootloader payload is empty');
|
|
633
|
+
}
|
|
634
|
+
try {
|
|
635
|
+
return await updateBootloaderFromSource(typedCall, postMessage, device, source);
|
|
636
|
+
} finally {
|
|
637
|
+
await source.close();
|
|
638
|
+
}
|
|
639
|
+
};
|
|
640
|
+
|
|
641
|
+
export const updateBootloaderFromSource = async (
|
|
642
|
+
typedCall: TypedCall,
|
|
643
|
+
postMessage: (message: CoreMessage) => void,
|
|
644
|
+
device: Device,
|
|
645
|
+
source: FirmwareByteSource
|
|
541
646
|
) => {
|
|
542
647
|
postProgressTip(device, 'UpdateBootloader', postMessage);
|
|
543
648
|
postProgressMessage(device, Math.floor(0), 'installingFirmware', postMessage);
|
|
544
|
-
await
|
|
649
|
+
await updateResourceFromSource(typedCall, 'bootloader.bin', source, () => {
|
|
545
650
|
postProcessingMessage('resource', postMessage);
|
|
546
651
|
});
|
|
547
652
|
postProgressMessage(device, Math.floor(100), 'installingFirmware', postMessage);
|
|
@@ -5,12 +5,9 @@ import {
|
|
|
5
5
|
import { ERRORS, HardwareErrorCode } from '@onekeyfe/hd-shared';
|
|
6
6
|
|
|
7
7
|
import { DataManager } from '../../data-manager';
|
|
8
|
-
import { LoggerNames, getLogger } from '../../utils/logger';
|
|
9
8
|
|
|
10
9
|
import type { DeviceCommands } from '../../device/DeviceCommands';
|
|
11
10
|
|
|
12
|
-
const Log = getLogger(LoggerNames.Method);
|
|
13
|
-
|
|
14
11
|
export type ProtocolV2FileWriteData = ArrayBuffer | Uint8Array | Blob | string;
|
|
15
12
|
|
|
16
13
|
export type ProtocolV2FileWriteProgress = {
|
|
@@ -21,12 +18,6 @@ export type ProtocolV2FileWriteProgress = {
|
|
|
21
18
|
elapsedMs: number;
|
|
22
19
|
};
|
|
23
20
|
|
|
24
|
-
export type ProtocolV2FileWriteChunkContext = {
|
|
25
|
-
offset: number;
|
|
26
|
-
chunkLength: number;
|
|
27
|
-
totalSize: number;
|
|
28
|
-
};
|
|
29
|
-
|
|
30
21
|
export type ProtocolV2FileWriteOptions = {
|
|
31
22
|
commands: Pick<DeviceCommands, 'typedCall'>;
|
|
32
23
|
path: string;
|
|
@@ -39,63 +30,20 @@ export type ProtocolV2FileWriteOptions = {
|
|
|
39
30
|
append?: boolean;
|
|
40
31
|
uiPercentage?: number;
|
|
41
32
|
timeoutMs?: number;
|
|
42
|
-
writeWithResponse?: boolean;
|
|
43
33
|
maxChunkRetries?: number;
|
|
44
|
-
paceMs?: number;
|
|
45
34
|
throwIfAborted?: () => void;
|
|
46
|
-
getUiPercentage?: (context: ProtocolV2FileWriteChunkContext) => number | undefined;
|
|
47
35
|
onProgress?: (progress: ProtocolV2FileWriteProgress) => void;
|
|
48
36
|
};
|
|
49
37
|
|
|
50
38
|
const MIN_FILE_CHUNK_SIZE = 64;
|
|
51
|
-
const FILE_TRANSFER_RATE_WINDOW_MS = 1000;
|
|
52
|
-
const FILE_TRANSFER_LOG_INTERVAL_MS = 10_000;
|
|
53
|
-
const SESSION_ERROR = 'session not found';
|
|
54
|
-
|
|
55
|
-
function formatFileTransferRate(bytesPerSecond: number) {
|
|
56
|
-
return (Math.max(bytesPerSecond, 0) / 1024).toFixed(2);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function getAverageFileTransferRate(transferredBytes: number, elapsedMs: number) {
|
|
60
|
-
if (elapsedMs <= 0) return 0;
|
|
61
|
-
return Math.round((Math.max(transferredBytes, 0) / elapsedMs) * 1000);
|
|
62
|
-
}
|
|
63
39
|
|
|
64
|
-
function
|
|
65
|
-
const env = DataManager.getSettings('env');
|
|
66
|
-
return env && DataManager.isBleConnect(env) ? 'BLE' : String(env ?? 'unknown');
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function logFileTransferMetrics({
|
|
70
|
-
transport,
|
|
71
|
-
status,
|
|
72
|
-
transferredBytes,
|
|
73
|
-
totalBytes,
|
|
74
|
-
elapsedMs,
|
|
75
|
-
rateBytesPerSecond,
|
|
76
|
-
}: {
|
|
77
|
-
transport: string;
|
|
78
|
-
status: 'progress' | 'completed' | 'failed';
|
|
79
|
-
transferredBytes: number;
|
|
80
|
-
totalBytes: number;
|
|
81
|
-
elapsedMs: number;
|
|
82
|
-
rateBytesPerSecond: number;
|
|
83
|
-
}) {
|
|
84
|
-
Log.log(
|
|
85
|
-
`[FileWrite] metrics transport=${transport} status=${status} bytes=${transferredBytes}/${totalBytes} elapsed=${(
|
|
86
|
-
elapsedMs / 1000
|
|
87
|
-
).toFixed(2)}s speed=${formatFileTransferRate(rateBytesPerSecond)} KiB/s`
|
|
88
|
-
);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
export function isProtocolV2ResponseTimeout(error: unknown) {
|
|
40
|
+
function isRetryableFileWriteTimeout(error: unknown) {
|
|
92
41
|
if (!error || typeof error !== 'object') return false;
|
|
93
|
-
const candidate = error as { errorCode?: number; code?: number
|
|
42
|
+
const candidate = error as { errorCode?: number; code?: number; message?: string };
|
|
94
43
|
const code = candidate.errorCode ?? candidate.code;
|
|
95
44
|
return (
|
|
96
45
|
code === HardwareErrorCode.BleTimeoutError ||
|
|
97
|
-
|
|
98
|
-
/(?:BLE|Lowlevel|Protocol V2) response timeout/i.test(candidate.message ?? '')
|
|
46
|
+
/Lowlevel response timeout/i.test(candidate.message ?? '')
|
|
99
47
|
);
|
|
100
48
|
}
|
|
101
49
|
|
|
@@ -171,162 +119,75 @@ export async function writeProtocolV2File(options: ProtocolV2FileWriteOptions) {
|
|
|
171
119
|
let chunks = 0;
|
|
172
120
|
let lastMessage: Record<string, unknown> | undefined;
|
|
173
121
|
const startTime = Date.now();
|
|
174
|
-
let rateWindowStartedAt = startTime;
|
|
175
|
-
let rateWindowStartedBytes = 0;
|
|
176
|
-
let rateBytesPerSecond: number | undefined;
|
|
177
|
-
let lastConfirmedAt = startTime;
|
|
178
|
-
let logWindowStartedAt = startTime;
|
|
179
|
-
let logWindowStartedBytes = 0;
|
|
180
|
-
const transport = getFileTransferTransport();
|
|
181
122
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
try {
|
|
207
|
-
const callOptions =
|
|
208
|
-
options.writeWithResponse === undefined
|
|
209
|
-
? { timeoutMs: options.timeoutMs }
|
|
210
|
-
: {
|
|
211
|
-
...(options.timeoutMs === undefined ? {} : { timeoutMs: options.timeoutMs }),
|
|
212
|
-
writeWithResponse: options.writeWithResponse,
|
|
213
|
-
};
|
|
214
|
-
response = await options.commands.typedCall(
|
|
215
|
-
'FilesystemFileWrite',
|
|
216
|
-
'FilesystemFile',
|
|
217
|
-
request,
|
|
218
|
-
callOptions
|
|
219
|
-
);
|
|
220
|
-
isWritePending = false;
|
|
221
|
-
} catch (error) {
|
|
222
|
-
if (retryCount >= maxChunkRetries || !isProtocolV2ResponseTimeout(error)) throw error;
|
|
223
|
-
retryCount += 1;
|
|
224
|
-
options.throwIfAborted?.();
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
if (!response) {
|
|
228
|
-
throw ERRORS.TypedError(
|
|
229
|
-
HardwareErrorCode.RuntimeError,
|
|
230
|
-
'FilesystemFileWrite completed without a response'
|
|
231
|
-
);
|
|
232
|
-
}
|
|
233
|
-
const responseType = (response as { type?: string }).type;
|
|
234
|
-
if (responseType && responseType !== 'FilesystemFile') {
|
|
235
|
-
const responseError = (response as { message?: { error?: unknown } }).message?.error;
|
|
236
|
-
if (typeof responseError === 'string' && responseError.includes(SESSION_ERROR)) {
|
|
237
|
-
throw ERRORS.TypedError(HardwareErrorCode.RuntimeError, SESSION_ERROR);
|
|
238
|
-
}
|
|
239
|
-
throw ERRORS.TypedError(
|
|
240
|
-
HardwareErrorCode.RuntimeError,
|
|
241
|
-
`FilesystemFileWrite received unexpected response ${responseType}`
|
|
242
|
-
);
|
|
243
|
-
}
|
|
244
|
-
options.throwIfAborted?.();
|
|
245
|
-
lastMessage = response.message;
|
|
246
|
-
const rawProcessedByte = response.message?.processed_byte;
|
|
247
|
-
const processedByte = Number(rawProcessedByte);
|
|
248
|
-
if (
|
|
249
|
-
rawProcessedByte !== undefined &&
|
|
250
|
-
(!Number.isFinite(processedByte) ||
|
|
251
|
-
processedByte <= offset ||
|
|
252
|
-
processedByte > offset + chunk.byteLength)
|
|
253
|
-
) {
|
|
254
|
-
throw ERRORS.TypedError(
|
|
255
|
-
HardwareErrorCode.RuntimeError,
|
|
256
|
-
`FilesystemFileWrite invalid processed_byte ${processedByte}`
|
|
123
|
+
while (written < dataLength) {
|
|
124
|
+
options.throwIfAborted?.();
|
|
125
|
+
const chunk = data.slice(written, Math.min(written + chunkSize, dataLength));
|
|
126
|
+
const offset = startOffset + written;
|
|
127
|
+
const progress =
|
|
128
|
+
options.uiPercentage ??
|
|
129
|
+
getDeviceTransferProgress(offset, offset + chunk.byteLength, totalSize);
|
|
130
|
+
const request = {
|
|
131
|
+
file: { path: options.path, offset, total_size: totalSize, data: chunk },
|
|
132
|
+
overwrite: chunks === 0 ? options.overwrite ?? false : false,
|
|
133
|
+
append: options.append ?? false,
|
|
134
|
+
ui_percentage: progress,
|
|
135
|
+
};
|
|
136
|
+
const maxChunkRetries = Math.max(Math.floor(options.maxChunkRetries ?? 0), 0);
|
|
137
|
+
let retryCount = 0;
|
|
138
|
+
let response;
|
|
139
|
+
let isWritePending = true;
|
|
140
|
+
while (isWritePending) {
|
|
141
|
+
try {
|
|
142
|
+
response = await options.commands.typedCall(
|
|
143
|
+
'FilesystemFileWrite',
|
|
144
|
+
'FilesystemFile',
|
|
145
|
+
request,
|
|
146
|
+
{ timeoutMs: options.timeoutMs }
|
|
257
147
|
);
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
lastConfirmedAt = now;
|
|
264
|
-
const elapsedMs = now - startTime;
|
|
265
|
-
const transferredBytes = Math.min(written, dataLength);
|
|
266
|
-
const rateWindowElapsedMs = now - rateWindowStartedAt;
|
|
267
|
-
if (rateWindowElapsedMs >= FILE_TRANSFER_RATE_WINDOW_MS) {
|
|
268
|
-
const rateWindowBytes = Math.max(transferredBytes - rateWindowStartedBytes, 0);
|
|
269
|
-
rateBytesPerSecond = Math.round((rateWindowBytes / rateWindowElapsedMs) * 1000);
|
|
270
|
-
rateWindowStartedAt = now;
|
|
271
|
-
rateWindowStartedBytes = transferredBytes;
|
|
272
|
-
} else if (rateBytesPerSecond === undefined && elapsedMs > 0) {
|
|
273
|
-
rateBytesPerSecond = Math.round((transferredBytes / elapsedMs) * 1000);
|
|
274
|
-
}
|
|
275
|
-
options.onProgress?.({
|
|
276
|
-
progress: getConfirmedProgress(startOffset + written, totalSize, written, dataLength),
|
|
277
|
-
transferredBytes,
|
|
278
|
-
totalBytes: dataLength,
|
|
279
|
-
rateBytesPerSecond,
|
|
280
|
-
elapsedMs,
|
|
281
|
-
});
|
|
282
|
-
const logWindowElapsedMs = now - logWindowStartedAt;
|
|
283
|
-
if (logWindowElapsedMs >= FILE_TRANSFER_LOG_INTERVAL_MS && transferredBytes < dataLength) {
|
|
284
|
-
const logWindowBytes = Math.max(transferredBytes - logWindowStartedBytes, 0);
|
|
285
|
-
logFileTransferMetrics({
|
|
286
|
-
transport,
|
|
287
|
-
status: 'progress',
|
|
288
|
-
transferredBytes,
|
|
289
|
-
totalBytes: dataLength,
|
|
290
|
-
elapsedMs,
|
|
291
|
-
rateBytesPerSecond: getAverageFileTransferRate(logWindowBytes, logWindowElapsedMs),
|
|
292
|
-
});
|
|
293
|
-
logWindowStartedAt = now;
|
|
294
|
-
logWindowStartedBytes = transferredBytes;
|
|
295
|
-
}
|
|
296
|
-
if (options.paceMs && options.paceMs > 0) {
|
|
297
|
-
await new Promise(resolve => {
|
|
298
|
-
setTimeout(resolve, options.paceMs);
|
|
299
|
-
});
|
|
148
|
+
isWritePending = false;
|
|
149
|
+
} catch (error) {
|
|
150
|
+
if (retryCount >= maxChunkRetries || !isRetryableFileWriteTimeout(error)) throw error;
|
|
151
|
+
retryCount += 1;
|
|
152
|
+
options.throwIfAborted?.();
|
|
300
153
|
}
|
|
301
154
|
}
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
155
|
+
if (!response) {
|
|
156
|
+
throw ERRORS.TypedError(
|
|
157
|
+
HardwareErrorCode.RuntimeError,
|
|
158
|
+
'FilesystemFileWrite completed without a response'
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
options.throwIfAborted?.();
|
|
162
|
+
lastMessage = response.message;
|
|
163
|
+
const rawProcessedByte = response.message?.processed_byte;
|
|
164
|
+
const processedByte = Number(rawProcessedByte);
|
|
165
|
+
if (
|
|
166
|
+
rawProcessedByte !== undefined &&
|
|
167
|
+
(!Number.isFinite(processedByte) ||
|
|
168
|
+
processedByte <= offset ||
|
|
169
|
+
processedByte > offset + chunk.byteLength)
|
|
170
|
+
) {
|
|
171
|
+
throw ERRORS.TypedError(
|
|
172
|
+
HardwareErrorCode.RuntimeError,
|
|
173
|
+
`FilesystemFileWrite invalid processed_byte ${processedByte}`
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
written =
|
|
177
|
+
rawProcessedByte === undefined ? written + chunk.byteLength : processedByte - startOffset;
|
|
178
|
+
chunks += 1;
|
|
179
|
+
const elapsedMs = Date.now() - startTime;
|
|
180
|
+
const transferredBytes = Math.min(written, dataLength);
|
|
181
|
+
options.onProgress?.({
|
|
182
|
+
progress: getConfirmedProgress(startOffset + written, totalSize, written, dataLength),
|
|
183
|
+
transferredBytes,
|
|
311
184
|
totalBytes: dataLength,
|
|
185
|
+
rateBytesPerSecond:
|
|
186
|
+
elapsedMs > 0 ? Math.round((transferredBytes / elapsedMs) * 1000) : undefined,
|
|
312
187
|
elapsedMs,
|
|
313
|
-
rateBytesPerSecond: getAverageFileTransferRate(logWindowBytes, logWindowElapsedMs),
|
|
314
188
|
});
|
|
315
|
-
throw error;
|
|
316
189
|
}
|
|
317
190
|
|
|
318
|
-
const elapsedMs = Math.max(lastConfirmedAt - startTime, 0);
|
|
319
|
-
const logWindowElapsedMs = Math.max(lastConfirmedAt - logWindowStartedAt, 0);
|
|
320
|
-
const logWindowBytes = Math.max(written - logWindowStartedBytes, 0);
|
|
321
|
-
logFileTransferMetrics({
|
|
322
|
-
transport,
|
|
323
|
-
status: 'completed',
|
|
324
|
-
transferredBytes: written,
|
|
325
|
-
totalBytes: dataLength,
|
|
326
|
-
elapsedMs,
|
|
327
|
-
rateBytesPerSecond: getAverageFileTransferRate(logWindowBytes, logWindowElapsedMs),
|
|
328
|
-
});
|
|
329
|
-
|
|
330
191
|
return {
|
|
331
192
|
...lastMessage,
|
|
332
193
|
path: options.path,
|
package/src/api/index.ts
CHANGED
|
@@ -3,7 +3,6 @@ export { default as testProtocolV2Ping } from './protocol-v2/Ping';
|
|
|
3
3
|
export { default as preInitialize } from './device/PreInitialize';
|
|
4
4
|
|
|
5
5
|
export { default as searchDevices } from './SearchDevices';
|
|
6
|
-
export { default as detectDeviceConnectProtocol } from './DetectDeviceConnectProtocol';
|
|
7
6
|
export { default as getFeatures } from './GetFeatures';
|
|
8
7
|
export { default as getDeviceState } from './GetDeviceState';
|
|
9
8
|
export { default as getOnekeyFeatures } from './GetOnekeyFeatures';
|
|
@@ -50,7 +49,6 @@ export { default as promptWebDeviceAccess } from './PromptWebDeviceAccess';
|
|
|
50
49
|
export { default as deviceReboot } from './protocol-v2/DeviceReboot';
|
|
51
50
|
export { default as deviceGetOnboardingStatus } from './protocol-v2/DeviceGetOnboardingStatus';
|
|
52
51
|
export { default as deviceUploadWallpaper } from './protocol-v2/DeviceUploadWallpaper';
|
|
53
|
-
export { default as deviceUploadNft } from './protocol-v2/DeviceUploadNft';
|
|
54
52
|
export { default as uploadPortfolio } from './UploadPortfolio';
|
|
55
53
|
|
|
56
54
|
export { default as cipherKeyValue } from './CipherKeyValue';
|
|
@@ -190,7 +190,7 @@ export default class KaspaSignTransaction extends BaseMethod<KaspaSignTransactio
|
|
|
190
190
|
model_classic1s: {
|
|
191
191
|
min: '3.12.0',
|
|
192
192
|
},
|
|
193
|
-
|
|
193
|
+
pro2: {
|
|
194
194
|
min: '0.0.0',
|
|
195
195
|
},
|
|
196
196
|
};
|
|
@@ -506,7 +506,18 @@ export default class KaspaSignTransaction extends BaseMethod<KaspaSignTransactio
|
|
|
506
506
|
'KaspaSignTransaction: device firmware uses the streaming protocol; every output requires address or addressN'
|
|
507
507
|
);
|
|
508
508
|
}
|
|
509
|
-
|
|
509
|
+
try {
|
|
510
|
+
return await this.signTxStream(typedCall, response);
|
|
511
|
+
} catch (error) {
|
|
512
|
+
// Device rejected our refTxs; the caller decides whether to sign without them.
|
|
513
|
+
if (
|
|
514
|
+
error instanceof HardwareError &&
|
|
515
|
+
String(error.message).toLowerCase().includes('previous transaction id mismatch')
|
|
516
|
+
) {
|
|
517
|
+
throw ERRORS.TypedError(HardwareErrorCode.KaspaPrevTxIdMismatch, String(error.message));
|
|
518
|
+
}
|
|
519
|
+
throw error;
|
|
520
|
+
}
|
|
510
521
|
}
|
|
511
522
|
|
|
512
523
|
// Legacy answer to a streaming-only packet: no prehash material exists.
|