@onekeyfe/hd-core 1.1.27-alpha.4 → 1.1.27-alpha.41
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__/evmSignTransaction.test.ts +1 -1
- package/__tests__/evmSignTypedData.test.ts +1 -1
- package/__tests__/protocol-v2.test.ts +1688 -0
- package/dist/api/BaseMethod.d.ts +1 -7
- package/dist/api/BaseMethod.d.ts.map +1 -1
- package/dist/api/DirList.d.ts +10 -0
- package/dist/api/DirList.d.ts.map +1 -0
- package/dist/api/DirMake.d.ts +9 -0
- package/dist/api/DirMake.d.ts.map +1 -0
- package/dist/api/DirRemove.d.ts +9 -0
- package/dist/api/DirRemove.d.ts.map +1 -0
- package/dist/api/FileDelete.d.ts +9 -0
- package/dist/api/FileDelete.d.ts.map +1 -0
- package/dist/api/FileRead.d.ts +19 -0
- package/dist/api/FileRead.d.ts.map +1 -0
- package/dist/api/FileWrite.d.ts +23 -0
- package/dist/api/FileWrite.d.ts.map +1 -0
- package/dist/api/FirmwareUpdateV3.d.ts +1 -0
- package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV4.d.ts +32 -0
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -0
- package/dist/api/GetDeviceInfo.d.ts +9 -0
- package/dist/api/GetDeviceInfo.d.ts.map +1 -0
- package/dist/api/GetFeatures.d.ts +1 -1
- package/dist/api/GetOnekeyFeatures.d.ts.map +1 -1
- package/dist/api/GetPassphraseState.d.ts +6 -1
- package/dist/api/GetPassphraseState.d.ts.map +1 -1
- package/dist/api/PathInfo.d.ts +9 -0
- package/dist/api/PathInfo.d.ts.map +1 -0
- package/dist/api/SearchDevices.d.ts +2 -1
- package/dist/api/SearchDevices.d.ts.map +1 -1
- package/dist/api/alephium/AlephiumGetAddress.d.ts +2 -6
- package/dist/api/alephium/AlephiumGetAddress.d.ts.map +1 -1
- package/dist/api/alephium/AlephiumSignMessage.d.ts +2 -5
- package/dist/api/alephium/AlephiumSignMessage.d.ts.map +1 -1
- package/dist/api/alephium/AlephiumSignTransaction.d.ts +2 -5
- package/dist/api/alephium/AlephiumSignTransaction.d.ts.map +1 -1
- package/dist/api/algo/AlgoSignTransaction.d.ts.map +1 -1
- package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
- package/dist/api/aptos/AptosSignInMessage.d.ts.map +1 -1
- package/dist/api/aptos/AptosSignMessage.d.ts.map +1 -1
- package/dist/api/aptos/AptosSignTransaction.d.ts.map +1 -1
- package/dist/api/benfen/BenfenGetAddress.d.ts +2 -9
- package/dist/api/benfen/BenfenGetAddress.d.ts.map +1 -1
- package/dist/api/benfen/BenfenGetPublicKey.d.ts +2 -9
- package/dist/api/benfen/BenfenGetPublicKey.d.ts.map +1 -1
- package/dist/api/benfen/BenfenSignMessage.d.ts +2 -8
- package/dist/api/benfen/BenfenSignMessage.d.ts.map +1 -1
- package/dist/api/benfen/BenfenSignTransaction.d.ts +2 -8
- package/dist/api/benfen/BenfenSignTransaction.d.ts.map +1 -1
- package/dist/api/btc/BTCGetAddress.d.ts +1 -11
- package/dist/api/btc/BTCGetAddress.d.ts.map +1 -1
- package/dist/api/btc/BTCGetPublicKey.d.ts +1 -11
- package/dist/api/btc/BTCGetPublicKey.d.ts.map +1 -1
- package/dist/api/btc/BTCSignMessage.d.ts +1 -15
- package/dist/api/btc/BTCSignMessage.d.ts.map +1 -1
- package/dist/api/btc/BTCSignPsbt.d.ts.map +1 -1
- package/dist/api/btc/BTCSignTransaction.d.ts +1 -11
- package/dist/api/btc/BTCSignTransaction.d.ts.map +1 -1
- package/dist/api/btc/BTCVerifyMessage.d.ts +1 -11
- package/dist/api/btc/BTCVerifyMessage.d.ts.map +1 -1
- package/dist/api/btc/helpers/versionLimit.d.ts +2 -11
- package/dist/api/btc/helpers/versionLimit.d.ts.map +1 -1
- package/dist/api/cardano/CardanoSignMessage.d.ts.map +1 -1
- package/dist/api/cardano/CardanoSignTransaction.d.ts.map +1 -1
- package/dist/api/conflux/ConfluxSignMessage.d.ts.map +1 -1
- package/dist/api/conflux/ConfluxSignMessageCIP23.d.ts.map +1 -1
- package/dist/api/conflux/ConfluxSignTransaction.d.ts.map +1 -1
- package/dist/api/cosmos/CosmosSignTransaction.d.ts.map +1 -1
- package/dist/api/device/DeviceRebootToBoardloader.d.ts +1 -1
- package/dist/api/device/DeviceRebootToBoardloader.d.ts.map +1 -1
- package/dist/api/device/DeviceRebootToBootloader.d.ts.map +1 -1
- package/dist/api/dynex/DnxGetAddress.d.ts.map +1 -1
- package/dist/api/dynex/DnxSignTransaction.d.ts.map +1 -1
- package/dist/api/evm/EVMSignMessage.d.ts.map +1 -1
- package/dist/api/evm/EVMSignMessageEIP712.d.ts +2 -8
- package/dist/api/evm/EVMSignMessageEIP712.d.ts.map +1 -1
- package/dist/api/evm/EVMSignTransaction.d.ts.map +1 -1
- package/dist/api/evm/EVMSignTypedData.d.ts.map +1 -1
- package/dist/api/evm/latest/signTypedData.d.ts +1 -1
- package/dist/api/evm/latest/signTypedData.d.ts.map +1 -1
- package/dist/api/evm/legacyV1/signTypedData.d.ts +1 -1
- package/dist/api/evm/legacyV1/signTypedData.d.ts.map +1 -1
- package/dist/api/filecoin/FilecoinSignTransaction.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +10 -2
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
- package/dist/api/helpers/deviceInfo.d.ts +15 -0
- package/dist/api/helpers/deviceInfo.d.ts.map +1 -0
- package/dist/api/helpers/filesystemValidation.d.ts +7 -0
- package/dist/api/helpers/filesystemValidation.d.ts.map +1 -0
- package/dist/api/index.d.ts +28 -1
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/kaspa/KaspaSignTransaction.d.ts.map +1 -1
- package/dist/api/near/NearSignTransaction.d.ts.map +1 -1
- package/dist/api/nem/NEMSignTransaction.d.ts.map +1 -1
- package/dist/api/neo/NeoGetAddress.d.ts +2 -8
- package/dist/api/neo/NeoGetAddress.d.ts.map +1 -1
- package/dist/api/neo/NeoSignTransaction.d.ts +2 -8
- package/dist/api/neo/NeoSignTransaction.d.ts.map +1 -1
- package/dist/api/nervos/NervosGetAddress.d.ts +2 -9
- package/dist/api/nervos/NervosGetAddress.d.ts.map +1 -1
- package/dist/api/nervos/NervosSignTransaction.d.ts +2 -9
- package/dist/api/nervos/NervosSignTransaction.d.ts.map +1 -1
- package/dist/api/nexa/NexaGetAddress.d.ts +2 -8
- package/dist/api/nexa/NexaGetAddress.d.ts.map +1 -1
- package/dist/api/nexa/NexaSignTransaction.d.ts +2 -9
- package/dist/api/nexa/NexaSignTransaction.d.ts.map +1 -1
- package/dist/api/nostr/NostrSignEvent.d.ts.map +1 -1
- package/dist/api/nostr/NostrSignSchnorr.d.ts.map +1 -1
- package/dist/api/polkadot/PolkadotSignTransaction.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceFirmwareUpdate.d.ts +7 -0
- package/dist/api/protocol-v2/DeviceFirmwareUpdate.d.ts.map +1 -0
- package/dist/api/protocol-v2/DeviceGetDeviceInfo.d.ts +7 -0
- package/dist/api/protocol-v2/DeviceGetDeviceInfo.d.ts.map +1 -0
- package/dist/api/protocol-v2/DeviceGetFirmwareUpdateStatus.d.ts +6 -0
- package/dist/api/protocol-v2/DeviceGetFirmwareUpdateStatus.d.ts.map +1 -0
- package/dist/api/protocol-v2/DeviceGetOnboardingStatus.d.ts +6 -0
- package/dist/api/protocol-v2/DeviceGetOnboardingStatus.d.ts.map +1 -0
- package/dist/api/protocol-v2/DeviceReboot.d.ts +7 -0
- package/dist/api/protocol-v2/DeviceReboot.d.ts.map +1 -0
- package/dist/api/protocol-v2/FactoryDeviceInfoSettings.d.ts +7 -0
- package/dist/api/protocol-v2/FactoryDeviceInfoSettings.d.ts.map +1 -0
- package/dist/api/protocol-v2/FactoryGetDeviceInfo.d.ts +6 -0
- package/dist/api/protocol-v2/FactoryGetDeviceInfo.d.ts.map +1 -0
- package/dist/api/protocol-v2/FilesystemDiskControl.d.ts +10 -0
- package/dist/api/protocol-v2/FilesystemDiskControl.d.ts.map +1 -0
- package/dist/api/protocol-v2/FilesystemFixPermission.d.ts +6 -0
- package/dist/api/protocol-v2/FilesystemFixPermission.d.ts.map +1 -0
- package/dist/api/protocol-v2/FilesystemFormat.d.ts +6 -0
- package/dist/api/protocol-v2/FilesystemFormat.d.ts.map +1 -0
- package/dist/api/protocol-v2/GetProtoVersion.d.ts +6 -0
- package/dist/api/protocol-v2/GetProtoVersion.d.ts.map +1 -0
- package/dist/api/protocol-v2/Ping.d.ts +8 -0
- package/dist/api/protocol-v2/Ping.d.ts.map +1 -0
- package/dist/api/protocol-v2/helpers.d.ts +49 -0
- package/dist/api/protocol-v2/helpers.d.ts.map +1 -0
- package/dist/api/scdo/ScdoGetAddress.d.ts +2 -6
- package/dist/api/scdo/ScdoGetAddress.d.ts.map +1 -1
- package/dist/api/scdo/ScdoSignMessage.d.ts +2 -5
- package/dist/api/scdo/ScdoSignMessage.d.ts.map +1 -1
- package/dist/api/scdo/ScdoSignTransaction.d.ts +2 -5
- package/dist/api/scdo/ScdoSignTransaction.d.ts.map +1 -1
- package/dist/api/solana/SolGetAddress.d.ts +1 -0
- package/dist/api/solana/SolGetAddress.d.ts.map +1 -1
- package/dist/api/solana/SolSignMessage.d.ts +4 -0
- package/dist/api/solana/SolSignMessage.d.ts.map +1 -1
- package/dist/api/solana/SolSignOffchainMessage.d.ts +4 -0
- package/dist/api/solana/SolSignOffchainMessage.d.ts.map +1 -1
- package/dist/api/solana/SolSignTransaction.d.ts +8 -0
- package/dist/api/solana/SolSignTransaction.d.ts.map +1 -1
- package/dist/api/starcoin/StarcoinSignMessage.d.ts.map +1 -1
- package/dist/api/starcoin/StarcoinSignTransaction.d.ts.map +1 -1
- package/dist/api/stellar/StellarGetAddress.d.ts +2 -1
- package/dist/api/stellar/StellarGetAddress.d.ts.map +1 -1
- package/dist/api/stellar/StellarSignTransaction.d.ts +2 -1
- package/dist/api/stellar/StellarSignTransaction.d.ts.map +1 -1
- package/dist/api/sui/SuiSignMessage.d.ts.map +1 -1
- package/dist/api/sui/SuiSignTransaction.d.ts +2 -2
- package/dist/api/sui/SuiSignTransaction.d.ts.map +1 -1
- package/dist/api/ton/TonSignData.d.ts.map +1 -1
- package/dist/api/ton/TonSignMessage.d.ts.map +1 -1
- package/dist/api/ton/TonSignProof.d.ts.map +1 -1
- package/dist/api/tron/TronSignMessage.d.ts +4 -0
- package/dist/api/tron/TronSignMessage.d.ts.map +1 -1
- package/dist/api/tron/TronSignTransaction.d.ts +4 -0
- package/dist/api/tron/TronSignTransaction.d.ts.map +1 -1
- package/dist/api/xrp/XrpSignTransaction.d.ts.map +1 -1
- package/dist/core/RequestQueue.d.ts +1 -1
- package/dist/core/RequestQueue.d.ts.map +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/data-manager/DataManager.d.ts +7 -4
- package/dist/data-manager/DataManager.d.ts.map +1 -1
- package/dist/data-manager/MessagesConfig.d.ts +2 -2
- package/dist/data-manager/MessagesConfig.d.ts.map +1 -1
- package/dist/data-manager/TransportManager.d.ts +5 -4
- package/dist/data-manager/TransportManager.d.ts.map +1 -1
- package/dist/device/Device.d.ts +5 -18
- package/dist/device/Device.d.ts.map +1 -1
- package/dist/device/DeviceCommands.d.ts +8 -8
- package/dist/device/DeviceCommands.d.ts.map +1 -1
- package/dist/device/DeviceConnector.d.ts +2 -1
- package/dist/device/DeviceConnector.d.ts.map +1 -1
- package/dist/events/ui-request.d.ts +8 -0
- package/dist/events/ui-request.d.ts.map +1 -1
- package/dist/index.d.ts +292 -43
- package/dist/index.js +16693 -1501
- package/dist/inject.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/features.d.ts +104 -0
- package/dist/protocols/protocol-v2/features.d.ts.map +1 -0
- package/dist/protocols/protocol-v2/firmware.d.ts +12 -0
- package/dist/protocols/protocol-v2/firmware.d.ts.map +1 -0
- package/dist/protocols/protocol-v2/index.d.ts +3 -0
- package/dist/protocols/protocol-v2/index.d.ts.map +1 -0
- package/dist/types/api/export.d.ts +1 -1
- package/dist/types/api/export.d.ts.map +1 -1
- package/dist/types/api/firmwareUpdate.d.ts +7 -0
- package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
- package/dist/types/api/getDeviceInfo.d.ts +84 -0
- package/dist/types/api/getDeviceInfo.d.ts.map +1 -0
- package/dist/types/api/getPassphraseState.d.ts +10 -1
- package/dist/types/api/getPassphraseState.d.ts.map +1 -1
- package/dist/types/api/index.d.ts +33 -3
- package/dist/types/api/index.d.ts.map +1 -1
- package/dist/types/api/protocolV2.d.ts +127 -0
- package/dist/types/api/protocolV2.d.ts.map +1 -0
- package/dist/types/api/searchDevices.d.ts +2 -2
- package/dist/types/api/searchDevices.d.ts.map +1 -1
- package/dist/types/device.d.ts +6 -2
- package/dist/types/device.d.ts.map +1 -1
- package/dist/types/params.d.ts +2 -1
- package/dist/types/params.d.ts.map +1 -1
- package/dist/types/settings.d.ts +1 -1
- package/dist/types/settings.d.ts.map +1 -1
- package/dist/utils/deviceFeaturesUtils.d.ts +5 -3
- package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
- package/dist/utils/deviceInfoUtils.d.ts +1 -0
- package/dist/utils/deviceInfoUtils.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/versionUtils.d.ts +1 -1
- package/package.json +4 -4
- package/src/api/BaseMethod.ts +7 -82
- package/src/api/DirList.ts +29 -0
- package/src/api/DirMake.ts +21 -0
- package/src/api/DirRemove.ts +21 -0
- package/src/api/FileDelete.ts +21 -0
- package/src/api/FileRead.ts +165 -0
- package/src/api/FileWrite.ts +203 -0
- package/src/api/FirmwareUpdateV3.ts +21 -4
- package/src/api/FirmwareUpdateV4.ts +810 -0
- package/src/api/GetDeviceInfo.ts +161 -0
- package/src/api/GetOnekeyFeatures.ts +75 -3
- package/src/api/GetPassphraseState.ts +16 -7
- package/src/api/PathInfo.ts +25 -0
- package/src/api/SearchDevices.ts +7 -2
- package/src/api/alephium/AlephiumGetAddress.ts +6 -2
- package/src/api/alephium/AlephiumSignMessage.ts +6 -2
- package/src/api/alephium/AlephiumSignTransaction.ts +6 -3
- package/src/api/algo/AlgoSignTransaction.ts +0 -1
- package/src/api/allnetwork/AllNetworkGetAddressBase.ts +18 -9
- package/src/api/aptos/AptosSignInMessage.ts +0 -1
- package/src/api/aptos/AptosSignMessage.ts +0 -1
- package/src/api/aptos/AptosSignTransaction.ts +0 -1
- package/src/api/benfen/BenfenGetAddress.ts +6 -2
- package/src/api/benfen/BenfenGetPublicKey.ts +6 -2
- package/src/api/benfen/BenfenSignMessage.ts +6 -2
- package/src/api/benfen/BenfenSignTransaction.ts +6 -2
- package/src/api/btc/BTCSignMessage.ts +0 -1
- package/src/api/btc/BTCSignPsbt.ts +0 -1
- package/src/api/btc/BTCSignTransaction.ts +0 -1
- package/src/api/btc/helpers/versionLimit.ts +7 -1
- package/src/api/cardano/CardanoSignMessage.ts +0 -1
- package/src/api/cardano/CardanoSignTransaction.ts +0 -1
- package/src/api/conflux/ConfluxSignMessage.ts +0 -1
- package/src/api/conflux/ConfluxSignMessageCIP23.ts +0 -1
- package/src/api/conflux/ConfluxSignTransaction.ts +5 -3
- package/src/api/cosmos/CosmosSignTransaction.ts +0 -1
- package/src/api/device/DeviceRebootToBoardloader.ts +10 -1
- package/src/api/device/DeviceRebootToBootloader.ts +10 -1
- package/src/api/dynex/DnxGetAddress.ts +7 -0
- package/src/api/dynex/DnxSignTransaction.ts +7 -1
- package/src/api/evm/EVMGetAddress.ts +1 -1
- package/src/api/evm/EVMGetPublicKey.ts +1 -1
- package/src/api/evm/EVMSignMessage.ts +1 -3
- package/src/api/evm/EVMSignMessageEIP712.ts +14 -2
- package/src/api/evm/EVMSignTransaction.ts +1 -3
- package/src/api/evm/EVMSignTypedData.ts +6 -8
- package/src/api/evm/EVMVerifyMessage.ts +1 -1
- package/src/api/filecoin/FilecoinSignTransaction.ts +0 -1
- package/src/api/firmware/FirmwareUpdateBaseMethod.ts +27 -4
- package/src/api/helpers/deviceInfo.ts +205 -0
- package/src/api/helpers/filesystemValidation.ts +51 -0
- package/src/api/index.ts +30 -1
- package/src/api/kaspa/KaspaSignTransaction.ts +0 -1
- package/src/api/near/NearSignTransaction.ts +0 -1
- package/src/api/nem/NEMSignTransaction.ts +0 -1
- package/src/api/neo/NeoGetAddress.ts +6 -1
- package/src/api/neo/NeoSignTransaction.ts +6 -2
- package/src/api/nervos/NervosGetAddress.ts +6 -2
- package/src/api/nervos/NervosSignTransaction.ts +6 -3
- package/src/api/nexa/NexaGetAddress.ts +6 -2
- package/src/api/nexa/NexaSignTransaction.ts +6 -4
- package/src/api/nostr/NostrSignEvent.ts +0 -1
- package/src/api/nostr/NostrSignSchnorr.ts +0 -1
- package/src/api/polkadot/PolkadotSignTransaction.ts +0 -1
- package/src/api/protocol-v2/DeviceFirmwareUpdate.ts +50 -0
- package/src/api/protocol-v2/DeviceGetDeviceInfo.ts +35 -0
- package/src/api/protocol-v2/DeviceGetFirmwareUpdateStatus.ts +18 -0
- package/src/api/protocol-v2/DeviceGetOnboardingStatus.ts +18 -0
- package/src/api/protocol-v2/DeviceReboot.ts +22 -0
- package/src/api/protocol-v2/FactoryDeviceInfoSettings.ts +27 -0
- package/src/api/protocol-v2/FactoryGetDeviceInfo.ts +18 -0
- package/src/api/protocol-v2/FilesystemDiskControl.ts +34 -0
- package/src/api/protocol-v2/FilesystemFixPermission.ts +14 -0
- package/src/api/protocol-v2/FilesystemFormat.ts +14 -0
- package/src/api/protocol-v2/GetProtoVersion.ts +14 -0
- package/src/api/protocol-v2/Ping.ts +16 -0
- package/src/api/protocol-v2/helpers.ts +161 -0
- package/src/api/scdo/ScdoGetAddress.ts +6 -2
- package/src/api/scdo/ScdoSignMessage.ts +6 -2
- package/src/api/scdo/ScdoSignTransaction.ts +6 -3
- package/src/api/solana/SolGetAddress.ts +4 -0
- package/src/api/solana/SolSignMessage.ts +4 -1
- package/src/api/solana/SolSignOffchainMessage.ts +4 -1
- package/src/api/solana/SolSignTransaction.ts +8 -1
- package/src/api/starcoin/StarcoinSignMessage.ts +0 -1
- package/src/api/starcoin/StarcoinSignTransaction.ts +0 -1
- package/src/api/stellar/StellarGetAddress.ts +10 -1
- package/src/api/stellar/StellarSignTransaction.ts +14 -2
- package/src/api/sui/SuiSignMessage.ts +0 -1
- package/src/api/sui/SuiSignTransaction.ts +12 -10
- package/src/api/ton/TonSignData.ts +0 -1
- package/src/api/ton/TonSignMessage.ts +0 -1
- package/src/api/ton/TonSignProof.ts +0 -1
- package/src/api/tron/TronSignMessage.ts +5 -2
- package/src/api/tron/TronSignTransaction.ts +4 -1
- package/src/api/xrp/XrpSignTransaction.ts +1 -2
- package/src/core/RequestQueue.ts +3 -10
- package/src/core/index.ts +62 -153
- package/src/data/messages/messages-protocol-v2.json +13128 -0
- package/src/data-manager/DataManager.ts +12 -7
- package/src/data-manager/MessagesConfig.ts +14 -14
- package/src/data-manager/TransportManager.ts +38 -12
- package/src/device/Device.ts +98 -82
- package/src/device/DeviceCommands.ts +166 -26
- package/src/device/DeviceConnector.ts +29 -4
- package/src/device/DevicePool.ts +1 -1
- package/src/events/ui-request.ts +8 -0
- package/src/inject.ts +46 -2
- package/src/protocols/protocol-v2/features.ts +287 -0
- package/src/protocols/protocol-v2/firmware.ts +26 -0
- package/src/protocols/protocol-v2/index.ts +2 -0
- package/src/types/api/export.ts +1 -0
- package/src/types/api/firmwareUpdate.ts +12 -0
- package/src/types/api/getDeviceInfo.ts +97 -0
- package/src/types/api/getPassphraseState.ts +13 -2
- package/src/types/api/index.ts +80 -3
- package/src/types/api/protocolV2.ts +226 -0
- package/src/types/api/searchDevices.ts +2 -2
- package/src/types/device.ts +33 -2
- package/src/types/params.ts +4 -2
- package/src/types/settings.ts +1 -1
- package/src/utils/deviceFeaturesUtils.ts +62 -21
- package/src/utils/deviceInfoUtils.ts +15 -8
- package/src/utils/index.ts +1 -0
- package/__tests__/DeviceCommands.test.ts +0 -99
- package/__tests__/evmLedgerLegacySafety.test.ts +0 -261
- package/__tests__/preInitialize.test.ts +0 -22
- package/dist/api/device/PreInitialize.d.ts +0 -6
- package/dist/api/device/PreInitialize.d.ts.map +0 -1
- package/dist/core/PollingStateManager.d.ts +0 -8
- package/dist/core/PollingStateManager.d.ts.map +0 -1
- package/dist/types/api/preInitialize.d.ts +0 -3
- package/dist/types/api/preInitialize.d.ts.map +0 -1
- package/src/api/device/PreInitialize.ts +0 -41
- package/src/core/PollingStateManager.ts +0 -47
- package/src/types/api/preInitialize.ts +0 -3
package/src/api/BaseMethod.ts
CHANGED
|
@@ -8,18 +8,16 @@ import { supportInputPinOnSoftware, supportModifyHomescreen } from '../utils/dev
|
|
|
8
8
|
import { createDeviceMessage } from '../events/device';
|
|
9
9
|
import { UI_REQUEST } from '../constants/ui-request';
|
|
10
10
|
import { DEVICE, FIRMWARE, createFirmwareMessage, createUiMessage } from '../events';
|
|
11
|
-
import { getHDPath, toHardened } from './helpers/pathUtils';
|
|
12
11
|
import { getBleFirmwareReleaseInfo, getFirmwareReleaseInfo } from './firmware/releaseHelper';
|
|
13
12
|
import {
|
|
14
13
|
LoggerNames,
|
|
15
14
|
getDeviceFirmwareVersion,
|
|
16
|
-
getDeviceType,
|
|
17
15
|
getFirmwareType,
|
|
18
16
|
getLogger,
|
|
19
17
|
getMethodVersionRange,
|
|
18
|
+
isMethodVersionRangeUnsupported,
|
|
20
19
|
} from '../utils';
|
|
21
20
|
import { generateInstanceId } from '../utils/tracing';
|
|
22
|
-
import { DeviceModelToTypes } from '../types';
|
|
23
21
|
|
|
24
22
|
import type { Device } from '../device/Device';
|
|
25
23
|
import type DeviceConnector from '../device/DeviceConnector';
|
|
@@ -30,31 +28,6 @@ import type { CoreContext } from '../core';
|
|
|
30
28
|
|
|
31
29
|
const Log = getLogger(LoggerNames.Method);
|
|
32
30
|
|
|
33
|
-
const isEvmLedgerLegacyPathWithHighIndex = (path: unknown) => {
|
|
34
|
-
let addressN: number[] | undefined;
|
|
35
|
-
if (typeof path === 'string') {
|
|
36
|
-
try {
|
|
37
|
-
addressN = getHDPath(path);
|
|
38
|
-
} catch {
|
|
39
|
-
return false;
|
|
40
|
-
}
|
|
41
|
-
} else if (Array.isArray(path)) {
|
|
42
|
-
addressN = path.map((item: unknown) => Number(item));
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return (
|
|
46
|
-
Array.isArray(addressN) &&
|
|
47
|
-
addressN.length === 4 &&
|
|
48
|
-
addressN[0] === toHardened(44) &&
|
|
49
|
-
addressN[1] === toHardened(60) &&
|
|
50
|
-
addressN[2] === toHardened(0) &&
|
|
51
|
-
addressN[3] > 1 &&
|
|
52
|
-
addressN[3] < toHardened(0)
|
|
53
|
-
);
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
const EVM_LEDGER_LEGACY_METHODS = ['evmGetAddress', 'evmGetPublicKey'];
|
|
57
|
-
|
|
58
31
|
export abstract class BaseMethod<Params = undefined> {
|
|
59
32
|
responseID: number;
|
|
60
33
|
|
|
@@ -133,28 +106,6 @@ export abstract class BaseMethod<Params = undefined> {
|
|
|
133
106
|
*/
|
|
134
107
|
skipForceUpdateCheck = false;
|
|
135
108
|
|
|
136
|
-
/** Allow skipping Initialize (sign methods only; never getAddress/getPublicKey). @default false */
|
|
137
|
-
allowUsePreInitialize = false;
|
|
138
|
-
|
|
139
|
-
/** Pre-warm signal method (fire-and-forget; core dedups + hangs up). @default false */
|
|
140
|
-
isPreWarmSignal = false;
|
|
141
|
-
|
|
142
|
-
/** Pre-warm dedup TTL (ms) */
|
|
143
|
-
preWarmTtl = 60 * 1000;
|
|
144
|
-
|
|
145
|
-
/** Pre-warm dedup key: connectId + passphraseState + method name */
|
|
146
|
-
getPreWarmKey(): string {
|
|
147
|
-
const payload = (this.payload ?? {}) as {
|
|
148
|
-
connectId?: string;
|
|
149
|
-
passphraseState?: string;
|
|
150
|
-
};
|
|
151
|
-
return [
|
|
152
|
-
this.connectId ?? payload.connectId ?? '',
|
|
153
|
-
payload.passphraseState ?? '',
|
|
154
|
-
this.name,
|
|
155
|
-
].join('|');
|
|
156
|
-
}
|
|
157
|
-
|
|
158
109
|
/**
|
|
159
110
|
* 严格检查设备是否支持该方法,不支持则抛出错误
|
|
160
111
|
* @experiment 默认不严格检查,如果需要严格检查,则需要设置为 true
|
|
@@ -167,8 +118,6 @@ export abstract class BaseMethod<Params = undefined> {
|
|
|
167
118
|
|
|
168
119
|
context?: CoreContext;
|
|
169
120
|
|
|
170
|
-
temporarySafetyCheckPrompted = false;
|
|
171
|
-
|
|
172
121
|
constructor(message: { id?: number; payload: any }) {
|
|
173
122
|
const { payload } = message;
|
|
174
123
|
this.name = payload.method;
|
|
@@ -274,6 +223,10 @@ export abstract class BaseMethod<Params = undefined> {
|
|
|
274
223
|
type => getVersionRange()[type]
|
|
275
224
|
);
|
|
276
225
|
|
|
226
|
+
if (isMethodVersionRangeUnsupported(versionRange)) {
|
|
227
|
+
throw createDeviceNotSupportMethodError(this.name, getFirmwareType(this.device.features));
|
|
228
|
+
}
|
|
229
|
+
|
|
277
230
|
if (!versionRange) {
|
|
278
231
|
if (options?.strictCheckDeviceSupport) {
|
|
279
232
|
throw createDeviceNotSupportMethodError(this.name, getFirmwareType(this.device.features));
|
|
@@ -292,32 +245,11 @@ export abstract class BaseMethod<Params = undefined> {
|
|
|
292
245
|
}
|
|
293
246
|
}
|
|
294
247
|
|
|
295
|
-
private shouldPromptSafetyCheckForEvmLedgerLegacyPath() {
|
|
296
|
-
if (!EVM_LEDGER_LEGACY_METHODS.includes(this.name)) {
|
|
297
|
-
return false;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
const deviceType = getDeviceType(this.device.features);
|
|
301
|
-
if (!DeviceModelToTypes.model_touch.includes(deviceType)) {
|
|
302
|
-
return false;
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
const paths = Array.isArray(this.payload?.bundle)
|
|
306
|
-
? this.payload.bundle.map((item: { path?: unknown }) => item?.path)
|
|
307
|
-
: [this.payload?.path];
|
|
308
|
-
|
|
309
|
-
return paths.some(isEvmLedgerLegacyPathWithHighIndex);
|
|
310
|
-
}
|
|
311
|
-
|
|
312
248
|
/**
|
|
313
|
-
* Automatic check safety_check level for
|
|
314
|
-
* @returns
|
|
249
|
+
* Automatic check safety_check level for Kovan, Ropsten, Rinkeby, Goerli test networks.
|
|
250
|
+
* @returns {void}
|
|
315
251
|
*/
|
|
316
252
|
async checkSafetyLevelOnTestNet() {
|
|
317
|
-
if (this.temporarySafetyCheckPrompted) {
|
|
318
|
-
return false;
|
|
319
|
-
}
|
|
320
|
-
|
|
321
253
|
let checkFlag = false;
|
|
322
254
|
// 3 - Ropsten, 4 - Rinkeby, 5 - Goerli, 420 - Optimism Goerli, 11155111 - zkSync Sepolia
|
|
323
255
|
if (
|
|
@@ -326,19 +258,12 @@ export abstract class BaseMethod<Params = undefined> {
|
|
|
326
258
|
) {
|
|
327
259
|
checkFlag = true;
|
|
328
260
|
}
|
|
329
|
-
if (this.shouldPromptSafetyCheckForEvmLedgerLegacyPath()) {
|
|
330
|
-
checkFlag = true;
|
|
331
|
-
}
|
|
332
261
|
if (checkFlag && this.device.features?.safety_checks === 'Strict') {
|
|
333
262
|
Log.debug('will change safety_checks level');
|
|
334
263
|
await this.device.commands.typedCall('ApplySettings', 'Success', {
|
|
335
264
|
safety_checks: 'PromptTemporarily',
|
|
336
265
|
});
|
|
337
|
-
this.temporarySafetyCheckPrompted = true;
|
|
338
|
-
return true;
|
|
339
266
|
}
|
|
340
|
-
|
|
341
|
-
return false;
|
|
342
267
|
}
|
|
343
268
|
|
|
344
269
|
dispose() {}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { BaseMethod } from './BaseMethod';
|
|
2
|
+
import {
|
|
3
|
+
validateNonEmptyString,
|
|
4
|
+
validateOptionalNonNegativeInteger,
|
|
5
|
+
} from './helpers/filesystemValidation';
|
|
6
|
+
|
|
7
|
+
export type DirListParams = {
|
|
8
|
+
path: string;
|
|
9
|
+
depth?: number;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export default class DirList extends BaseMethod<DirListParams> {
|
|
13
|
+
init() {
|
|
14
|
+
this.skipForceUpdateCheck = true;
|
|
15
|
+
this.useDevicePassphraseState = false;
|
|
16
|
+
this.params = {
|
|
17
|
+
path: validateNonEmptyString(this.payload.path, 'path'),
|
|
18
|
+
depth: validateOptionalNonNegativeInteger(this.payload.depth, 'depth'),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async run() {
|
|
23
|
+
const res = await this.device.commands.typedCall('FilesystemDirList', 'FilesystemDir', {
|
|
24
|
+
path: this.params.path,
|
|
25
|
+
depth: this.params.depth,
|
|
26
|
+
});
|
|
27
|
+
return Promise.resolve(res.message);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { BaseMethod } from './BaseMethod';
|
|
2
|
+
import { validateNonEmptyString } from './helpers/filesystemValidation';
|
|
3
|
+
|
|
4
|
+
export type DirMakeParams = {
|
|
5
|
+
path: string;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export default class DirMake extends BaseMethod<DirMakeParams> {
|
|
9
|
+
init() {
|
|
10
|
+
this.skipForceUpdateCheck = true;
|
|
11
|
+
this.useDevicePassphraseState = false;
|
|
12
|
+
this.params = { path: validateNonEmptyString(this.payload.path, 'path') };
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async run() {
|
|
16
|
+
const res = await this.device.commands.typedCall('FilesystemDirMake', 'Success', {
|
|
17
|
+
path: this.params.path,
|
|
18
|
+
});
|
|
19
|
+
return Promise.resolve(res.message);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { BaseMethod } from './BaseMethod';
|
|
2
|
+
import { validateNonEmptyString } from './helpers/filesystemValidation';
|
|
3
|
+
|
|
4
|
+
export type DirRemoveParams = {
|
|
5
|
+
path: string;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export default class DirRemove extends BaseMethod<DirRemoveParams> {
|
|
9
|
+
init() {
|
|
10
|
+
this.skipForceUpdateCheck = true;
|
|
11
|
+
this.useDevicePassphraseState = false;
|
|
12
|
+
this.params = { path: validateNonEmptyString(this.payload.path, 'path') };
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async run() {
|
|
16
|
+
const res = await this.device.commands.typedCall('FilesystemDirRemove', 'Success', {
|
|
17
|
+
path: this.params.path,
|
|
18
|
+
});
|
|
19
|
+
return Promise.resolve(res.message);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { BaseMethod } from './BaseMethod';
|
|
2
|
+
import { validateNonEmptyString } from './helpers/filesystemValidation';
|
|
3
|
+
|
|
4
|
+
export type FileDeleteParams = {
|
|
5
|
+
path: string;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export default class FileDelete extends BaseMethod<FileDeleteParams> {
|
|
9
|
+
init() {
|
|
10
|
+
this.skipForceUpdateCheck = true;
|
|
11
|
+
this.useDevicePassphraseState = false;
|
|
12
|
+
this.params = { path: validateNonEmptyString(this.payload.path, 'path') };
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async run() {
|
|
16
|
+
const res = await this.device.commands.typedCall('FilesystemFileDelete', 'Success', {
|
|
17
|
+
path: this.params.path,
|
|
18
|
+
});
|
|
19
|
+
return Promise.resolve(res.message);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import {
|
|
2
|
+
PROTOCOL_V2_BLE_FILE_CHUNK_SIZE,
|
|
3
|
+
PROTOCOL_V2_WEBUSB_FILE_CHUNK_SIZE,
|
|
4
|
+
} from '@onekeyfe/hd-transport';
|
|
5
|
+
import { ERRORS, HardwareErrorCode } from '@onekeyfe/hd-shared';
|
|
6
|
+
|
|
7
|
+
import { BaseMethod } from './BaseMethod';
|
|
8
|
+
import {
|
|
9
|
+
validateNonEmptyString,
|
|
10
|
+
validateNonNegativeInteger,
|
|
11
|
+
validateOptionalNonNegativeInteger,
|
|
12
|
+
validateOptionalPercentage,
|
|
13
|
+
} from './helpers/filesystemValidation';
|
|
14
|
+
import { hexToBytes, isHexString, stripHexPrefix } from './helpers/hexUtils';
|
|
15
|
+
import { DataManager } from '../data-manager';
|
|
16
|
+
|
|
17
|
+
export type FileReadParams = {
|
|
18
|
+
path: string;
|
|
19
|
+
offset?: number;
|
|
20
|
+
totalSize?: number;
|
|
21
|
+
chunkLen?: number;
|
|
22
|
+
uiPercentage?: number;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const MIN_FILE_READ_CHUNK_SIZE = 64;
|
|
26
|
+
|
|
27
|
+
function getProtocolV2FileReadChunkLimit() {
|
|
28
|
+
const env = DataManager.getSettings('env');
|
|
29
|
+
if (env && DataManager.isBleConnect(env)) {
|
|
30
|
+
return PROTOCOL_V2_BLE_FILE_CHUNK_SIZE;
|
|
31
|
+
}
|
|
32
|
+
return PROTOCOL_V2_WEBUSB_FILE_CHUNK_SIZE;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function normalizeChunkSize(value: unknown, maxChunkSize: number): number {
|
|
36
|
+
const numeric = Number(value);
|
|
37
|
+
if (!Number.isFinite(numeric) || numeric <= 0) return maxChunkSize;
|
|
38
|
+
return Math.min(Math.max(Math.floor(numeric), MIN_FILE_READ_CHUNK_SIZE), maxChunkSize);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function toFiniteNumber(value: unknown): number | undefined {
|
|
42
|
+
if (typeof value === 'number' && Number.isFinite(value)) return value;
|
|
43
|
+
if (typeof value === 'string') {
|
|
44
|
+
const numeric = Number(value);
|
|
45
|
+
return Number.isFinite(numeric) ? numeric : undefined;
|
|
46
|
+
}
|
|
47
|
+
if (value && typeof value === 'object') {
|
|
48
|
+
const longLike = value as { toNumber?: () => number };
|
|
49
|
+
if (typeof longLike.toNumber === 'function') {
|
|
50
|
+
const numeric = longLike.toNumber();
|
|
51
|
+
return Number.isFinite(numeric) ? numeric : undefined;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function toUint8Array(value: unknown): Uint8Array {
|
|
58
|
+
if (value instanceof Uint8Array) return value;
|
|
59
|
+
if (value instanceof ArrayBuffer) return new Uint8Array(value);
|
|
60
|
+
if (ArrayBuffer.isView(value)) {
|
|
61
|
+
return new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
|
|
62
|
+
}
|
|
63
|
+
if (typeof value === 'string') {
|
|
64
|
+
const hex = stripHexPrefix(value);
|
|
65
|
+
if (!hex) return new Uint8Array(0);
|
|
66
|
+
if (!isHexString(hex) || hex.length % 2 !== 0) return new Uint8Array(0);
|
|
67
|
+
return hexToBytes(hex);
|
|
68
|
+
}
|
|
69
|
+
return new Uint8Array(0);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export default class FileRead extends BaseMethod<FileReadParams> {
|
|
73
|
+
init() {
|
|
74
|
+
this.skipForceUpdateCheck = true;
|
|
75
|
+
this.useDevicePassphraseState = false;
|
|
76
|
+
const path = validateNonEmptyString(this.payload.path, 'path');
|
|
77
|
+
this.params = {
|
|
78
|
+
path,
|
|
79
|
+
offset: validateNonNegativeInteger(this.payload.offset, 'offset', 0),
|
|
80
|
+
totalSize: validateNonNegativeInteger(this.payload.totalSize, 'totalSize', 0),
|
|
81
|
+
chunkLen: validateOptionalNonNegativeInteger(this.payload.chunkLen, 'chunkLen'),
|
|
82
|
+
uiPercentage: validateOptionalPercentage(this.payload.uiPercentage, 'uiPercentage'),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async run() {
|
|
87
|
+
const startOffset = this.params.offset ?? 0;
|
|
88
|
+
const requestedLength = Number(this.params.totalSize);
|
|
89
|
+
const chunkSize = normalizeChunkSize(this.params.chunkLen, getProtocolV2FileReadChunkLimit());
|
|
90
|
+
let totalLength = Number.isFinite(requestedLength) && requestedLength > 0 ? requestedLength : 0;
|
|
91
|
+
|
|
92
|
+
if (totalLength === 0) {
|
|
93
|
+
const pathInfoRes = await this.device.commands.typedCall(
|
|
94
|
+
'FilesystemPathInfoQuery',
|
|
95
|
+
'FilesystemPathInfo',
|
|
96
|
+
{
|
|
97
|
+
path: this.params.path,
|
|
98
|
+
}
|
|
99
|
+
);
|
|
100
|
+
const fileSize = toFiniteNumber(pathInfoRes.message?.size);
|
|
101
|
+
if (!pathInfoRes.message?.exist || pathInfoRes.message?.directory) {
|
|
102
|
+
throw ERRORS.TypedError(
|
|
103
|
+
HardwareErrorCode.RuntimeError,
|
|
104
|
+
`FilesystemFileRead path is not a file: ${this.params.path}`
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
if (fileSize === undefined || fileSize < startOffset) {
|
|
108
|
+
throw ERRORS.TypedError(
|
|
109
|
+
HardwareErrorCode.RuntimeError,
|
|
110
|
+
`FilesystemFileRead invalid offset ${startOffset} for ${this.params.path}`
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
totalLength = fileSize - startOffset;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const chunks: Uint8Array[] = [];
|
|
117
|
+
let read = 0;
|
|
118
|
+
let lastMessage: Record<string, unknown> | undefined;
|
|
119
|
+
|
|
120
|
+
while (read < totalLength) {
|
|
121
|
+
const readLen = Math.min(chunkSize, totalLength - read);
|
|
122
|
+
const offset = startOffset + read;
|
|
123
|
+
const progress =
|
|
124
|
+
this.params.uiPercentage ??
|
|
125
|
+
Math.min(Math.ceil(((read + readLen) / Math.max(totalLength, 1)) * 100), 99);
|
|
126
|
+
const res = await this.device.commands.typedCall('FilesystemFileRead', 'FilesystemFile', {
|
|
127
|
+
file: {
|
|
128
|
+
path: this.params.path,
|
|
129
|
+
offset,
|
|
130
|
+
total_size: 0,
|
|
131
|
+
},
|
|
132
|
+
chunk_len: readLen,
|
|
133
|
+
ui_percentage: progress,
|
|
134
|
+
});
|
|
135
|
+
const data = toUint8Array(res.message?.data);
|
|
136
|
+
lastMessage = res.message;
|
|
137
|
+
|
|
138
|
+
if (data.byteLength === 0) {
|
|
139
|
+
throw ERRORS.TypedError(
|
|
140
|
+
HardwareErrorCode.RuntimeError,
|
|
141
|
+
`FilesystemFileRead received empty data at offset ${offset}`
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
chunks.push(data);
|
|
146
|
+
read += data.byteLength;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const combined = new Uint8Array(read);
|
|
150
|
+
let cursor = 0;
|
|
151
|
+
chunks.forEach(chunk => {
|
|
152
|
+
combined.set(chunk, cursor);
|
|
153
|
+
cursor += chunk.byteLength;
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
return Promise.resolve({
|
|
157
|
+
...lastMessage,
|
|
158
|
+
path: this.params.path,
|
|
159
|
+
offset: startOffset,
|
|
160
|
+
total_size: totalLength,
|
|
161
|
+
data: combined,
|
|
162
|
+
chunks: chunks.length,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import {
|
|
2
|
+
PROTOCOL_V2_BLE_FILE_CHUNK_SIZE,
|
|
3
|
+
PROTOCOL_V2_WEBUSB_FILE_CHUNK_SIZE,
|
|
4
|
+
} from '@onekeyfe/hd-transport';
|
|
5
|
+
import { ERRORS, HardwareErrorCode } from '@onekeyfe/hd-shared';
|
|
6
|
+
|
|
7
|
+
import { BaseMethod } from './BaseMethod';
|
|
8
|
+
import {
|
|
9
|
+
validateNonEmptyString,
|
|
10
|
+
validateNonNegativeInteger,
|
|
11
|
+
validateOptionalNonNegativeInteger,
|
|
12
|
+
validateOptionalPercentage,
|
|
13
|
+
validateRequiredData,
|
|
14
|
+
} from './helpers/filesystemValidation';
|
|
15
|
+
import { UI_REQUEST, createUiMessage } from '../events/ui-request';
|
|
16
|
+
import { DataManager } from '../data-manager';
|
|
17
|
+
|
|
18
|
+
export type FileWriteParams = {
|
|
19
|
+
path: string;
|
|
20
|
+
offset?: number;
|
|
21
|
+
totalSize?: number;
|
|
22
|
+
data: ArrayBuffer | Uint8Array | Blob | string;
|
|
23
|
+
chunkSize?: number;
|
|
24
|
+
chunkLen?: number;
|
|
25
|
+
overwrite?: boolean;
|
|
26
|
+
append?: boolean;
|
|
27
|
+
uiPercentage?: number;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const MIN_FILE_CHUNK_SIZE = 64;
|
|
31
|
+
|
|
32
|
+
function getProtocolV2FileChunkLimit() {
|
|
33
|
+
const env = DataManager.getSettings('env');
|
|
34
|
+
if (env && DataManager.isBleConnect(env)) {
|
|
35
|
+
return PROTOCOL_V2_BLE_FILE_CHUNK_SIZE;
|
|
36
|
+
}
|
|
37
|
+
return PROTOCOL_V2_WEBUSB_FILE_CHUNK_SIZE;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async function dataToUint8Array(data: FileWriteParams['data'] | Blob): Promise<Uint8Array> {
|
|
41
|
+
if (typeof data === 'string') {
|
|
42
|
+
return new TextEncoder().encode(data);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (data instanceof ArrayBuffer) {
|
|
46
|
+
return new Uint8Array(data);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (ArrayBuffer.isView(data)) {
|
|
50
|
+
return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (typeof Blob !== 'undefined' && data instanceof Blob) {
|
|
54
|
+
return new Uint8Array(await data.arrayBuffer());
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
throw ERRORS.TypedError(
|
|
58
|
+
HardwareErrorCode.CallMethodInvalidParameter,
|
|
59
|
+
'Unsupported FilesystemFileWrite data'
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function normalizeChunkSize(value: unknown, maxChunkSize: number): number {
|
|
64
|
+
const numeric = Number(value);
|
|
65
|
+
if (!Number.isFinite(numeric) || numeric <= 0) return maxChunkSize;
|
|
66
|
+
return Math.min(Math.max(Math.floor(numeric), MIN_FILE_CHUNK_SIZE), maxChunkSize);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function getConfirmedProgress(
|
|
70
|
+
processedByte: number,
|
|
71
|
+
totalSize: number,
|
|
72
|
+
written: number,
|
|
73
|
+
dataLength: number
|
|
74
|
+
) {
|
|
75
|
+
if (Number.isFinite(processedByte) && Number.isFinite(totalSize) && totalSize > 0) {
|
|
76
|
+
if (processedByte >= totalSize) return 100;
|
|
77
|
+
return Math.min(Math.max(Math.floor((processedByte / totalSize) * 100), 0), 99);
|
|
78
|
+
}
|
|
79
|
+
if (dataLength > 0) {
|
|
80
|
+
if (written >= dataLength) return 100;
|
|
81
|
+
return Math.min(Math.max(Math.floor((written / dataLength) * 100), 0), 99);
|
|
82
|
+
}
|
|
83
|
+
return 100;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export default class FileWrite extends BaseMethod<FileWriteParams> {
|
|
87
|
+
init() {
|
|
88
|
+
this.skipForceUpdateCheck = true;
|
|
89
|
+
this.useDevicePassphraseState = false;
|
|
90
|
+
validateRequiredData(this.payload.data, 'data');
|
|
91
|
+
const path = validateNonEmptyString(this.payload.path, 'path');
|
|
92
|
+
const offset = validateNonNegativeInteger(this.payload.offset, 'offset', 0);
|
|
93
|
+
this.params = {
|
|
94
|
+
path,
|
|
95
|
+
offset,
|
|
96
|
+
totalSize: validateNonNegativeInteger(this.payload.totalSize, 'totalSize', 0),
|
|
97
|
+
data: this.payload.data,
|
|
98
|
+
chunkSize: validateOptionalNonNegativeInteger(this.payload.chunkSize, 'chunkSize'),
|
|
99
|
+
chunkLen: validateOptionalNonNegativeInteger(this.payload.chunkLen, 'chunkLen'),
|
|
100
|
+
overwrite: this.payload.overwrite ?? offset === 0,
|
|
101
|
+
append: this.payload.append ?? false,
|
|
102
|
+
uiPercentage: validateOptionalPercentage(this.payload.uiPercentage, 'uiPercentage'),
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async run() {
|
|
107
|
+
const data = await dataToUint8Array(this.params.data);
|
|
108
|
+
const dataLength = data.byteLength;
|
|
109
|
+
const offsetValue = Number(this.params.offset ?? 0);
|
|
110
|
+
const startOffset = Number.isFinite(offsetValue) && offsetValue > 0 ? offsetValue : 0;
|
|
111
|
+
const payloadTotalSize = Number(this.params.totalSize);
|
|
112
|
+
const totalSize =
|
|
113
|
+
Number.isFinite(payloadTotalSize) && payloadTotalSize > 0
|
|
114
|
+
? payloadTotalSize
|
|
115
|
+
: startOffset + dataLength;
|
|
116
|
+
|
|
117
|
+
if (totalSize < startOffset + dataLength) {
|
|
118
|
+
throw ERRORS.TypedError(
|
|
119
|
+
HardwareErrorCode.RuntimeError,
|
|
120
|
+
`FilesystemFileWrite totalSize ${totalSize} is smaller than offset + data length ${
|
|
121
|
+
startOffset + dataLength
|
|
122
|
+
}`
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const chunkSize = normalizeChunkSize(
|
|
127
|
+
this.params.chunkSize ?? this.params.chunkLen,
|
|
128
|
+
getProtocolV2FileChunkLimit()
|
|
129
|
+
);
|
|
130
|
+
const overwrite = this.params.overwrite ?? false;
|
|
131
|
+
const append = this.params.append ?? false;
|
|
132
|
+
let written = 0;
|
|
133
|
+
let chunkIndex = 0;
|
|
134
|
+
let lastMessage: Record<string, unknown> | undefined;
|
|
135
|
+
const startTime = Date.now();
|
|
136
|
+
|
|
137
|
+
while (written < dataLength) {
|
|
138
|
+
const chunkEnd = Math.min(written + chunkSize, dataLength);
|
|
139
|
+
const chunk = data.slice(written, chunkEnd);
|
|
140
|
+
const offset = startOffset + written;
|
|
141
|
+
const isFirstChunk = chunkIndex === 0;
|
|
142
|
+
const progress =
|
|
143
|
+
this.params.uiPercentage ??
|
|
144
|
+
Math.min(Math.ceil(((written + chunk.byteLength) / dataLength) * 100), 99);
|
|
145
|
+
|
|
146
|
+
const res = await this.device.commands.typedCall('FilesystemFileWrite', 'FilesystemFile', {
|
|
147
|
+
file: {
|
|
148
|
+
path: this.params.path,
|
|
149
|
+
offset,
|
|
150
|
+
total_size: totalSize,
|
|
151
|
+
data: chunk,
|
|
152
|
+
},
|
|
153
|
+
overwrite: isFirstChunk ? overwrite : false,
|
|
154
|
+
append,
|
|
155
|
+
ui_percentage: progress,
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
lastMessage = res.message;
|
|
159
|
+
const processedByte = Number(res.message?.processed_byte);
|
|
160
|
+
if (Number.isFinite(processedByte) && processedByte > offset) {
|
|
161
|
+
written = processedByte - startOffset;
|
|
162
|
+
} else {
|
|
163
|
+
written += chunk.byteLength;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (written > dataLength) {
|
|
167
|
+
throw ERRORS.TypedError(
|
|
168
|
+
HardwareErrorCode.RuntimeError,
|
|
169
|
+
`FilesystemFileWrite invalid processed_byte ${processedByte}`
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const confirmedProcessedByte =
|
|
174
|
+
Number.isFinite(processedByte) && processedByte > offset
|
|
175
|
+
? processedByte
|
|
176
|
+
: startOffset + written;
|
|
177
|
+
if (typeof this.postMessage === 'function') {
|
|
178
|
+
const elapsedMs = Date.now() - startTime;
|
|
179
|
+
const transferredBytes = Math.min(written, dataLength);
|
|
180
|
+
this.postMessage(
|
|
181
|
+
createUiMessage(UI_REQUEST.DEVICE_PROGRESS, {
|
|
182
|
+
progress: getConfirmedProgress(confirmedProcessedByte, totalSize, written, dataLength),
|
|
183
|
+
transferredBytes,
|
|
184
|
+
totalBytes: dataLength,
|
|
185
|
+
rateBytesPerSecond:
|
|
186
|
+
elapsedMs > 0 ? Math.round((transferredBytes / elapsedMs) * 1000) : undefined,
|
|
187
|
+
elapsedMs,
|
|
188
|
+
})
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
chunkIndex += 1;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return Promise.resolve({
|
|
195
|
+
...lastMessage,
|
|
196
|
+
path: this.params.path,
|
|
197
|
+
offset: startOffset,
|
|
198
|
+
total_size: totalSize,
|
|
199
|
+
processed_byte: startOffset + written,
|
|
200
|
+
chunks: chunkIndex,
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
}
|
|
@@ -79,6 +79,20 @@ export default class FirmwareUpdateV3 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
async run() {
|
|
82
|
+
if (this.device.originalDescriptor?.protocolType === 'V2') {
|
|
83
|
+
throw ERRORS.TypedError(
|
|
84
|
+
HardwareErrorCode.RuntimeError,
|
|
85
|
+
'Protocol V2 firmware update must use firmwareUpdateV4'
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
Log.debug('FirmwareUpdateV3 strategy: Protocol V1');
|
|
89
|
+
return this.runProtocolV1();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Protocol V1 firmware update strategy for existing Pro devices.
|
|
94
|
+
*/
|
|
95
|
+
private async runProtocolV1() {
|
|
82
96
|
const { device } = this;
|
|
83
97
|
const { features } = device;
|
|
84
98
|
|
|
@@ -251,6 +265,8 @@ export default class FirmwareUpdateV3 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
251
265
|
}
|
|
252
266
|
|
|
253
267
|
this.postTipMessage(FirmwareUpdateTipMessage.StartTransferData);
|
|
268
|
+
const transferStartTime = Date.now();
|
|
269
|
+
|
|
254
270
|
// Process resource zip contents
|
|
255
271
|
if (resourceBinary) {
|
|
256
272
|
const file = await JSZip.loadAsync(resourceBinary);
|
|
@@ -264,6 +280,7 @@ export default class FirmwareUpdateV3 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
264
280
|
filePath: `0:res/${name}`,
|
|
265
281
|
processedSize,
|
|
266
282
|
totalSize,
|
|
283
|
+
transferStartTime,
|
|
267
284
|
});
|
|
268
285
|
}
|
|
269
286
|
}
|
|
@@ -275,6 +292,7 @@ export default class FirmwareUpdateV3 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
275
292
|
filePath: `0:boot/bootloader.bin`,
|
|
276
293
|
processedSize,
|
|
277
294
|
totalSize,
|
|
295
|
+
transferStartTime,
|
|
278
296
|
});
|
|
279
297
|
}
|
|
280
298
|
|
|
@@ -287,16 +305,15 @@ export default class FirmwareUpdateV3 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
287
305
|
filePath: `0:updates/${fwbinary.fileName}`,
|
|
288
306
|
processedSize,
|
|
289
307
|
totalSize,
|
|
308
|
+
transferStartTime,
|
|
290
309
|
});
|
|
291
310
|
}
|
|
292
311
|
}
|
|
293
312
|
|
|
294
|
-
// trigger firmware update
|
|
313
|
+
// trigger firmware update
|
|
295
314
|
try {
|
|
296
315
|
this.postTipMessage(FirmwareUpdateTipMessage.ConfirmOnDevice);
|
|
297
|
-
await this.startEmmcFirmwareUpdate({
|
|
298
|
-
path: '0:updates',
|
|
299
|
-
});
|
|
316
|
+
await this.startEmmcFirmwareUpdate({ path: '0:updates' });
|
|
300
317
|
} catch (error) {
|
|
301
318
|
Log.error('triggerFirmwareUpdateEmmc error: ', error);
|
|
302
319
|
// Re-throw errors with specific error codes that should not be ignored
|