@onetokenfe/hd-core 1.1.23
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/.eslintrc +6 -0
- package/README.md +32 -0
- package/__tests__/benfen.test.ts +68 -0
- package/__tests__/checkBootloaderReleast.test.ts +115 -0
- package/__tests__/evmSignTransaction.test.ts +419 -0
- package/jest.config.js +6 -0
- package/package.json +48 -0
- package/src/api/BaseMethod.ts +275 -0
- package/src/api/CheckAllFirmwareRelease.ts +73 -0
- package/src/api/CheckBLEFirmwareRelease.ts +23 -0
- package/src/api/CheckBootloaderRelease.ts +32 -0
- package/src/api/CheckBridgeRelease.ts +28 -0
- package/src/api/CheckBridgeStatus.ts +32 -0
- package/src/api/CheckFirmwareRelease.ts +31 -0
- package/src/api/CheckFirmwareTypeAvailable.tsx +30 -0
- package/src/api/CipherKeyValue.ts +68 -0
- package/src/api/FirmwareUpdate.ts +219 -0
- package/src/api/FirmwareUpdateV2.ts +408 -0
- package/src/api/FirmwareUpdateV3.ts +560 -0
- package/src/api/GetFeatures.ts +23 -0
- package/src/api/GetLogs.ts +40 -0
- package/src/api/GetOnetokenFeatures.ts +25 -0
- package/src/api/GetPassphraseState.ts +28 -0
- package/src/api/PromptWebDeviceAccess.ts +77 -0
- package/src/api/SearchDevices.ts +50 -0
- package/src/api/alephium/AlephiumGetAddress.ts +84 -0
- package/src/api/alephium/AlephiumSignMessage.ts +51 -0
- package/src/api/alephium/AlephiumSignTransaction.ts +135 -0
- package/src/api/algo/AlgoGetAddress.ts +73 -0
- package/src/api/algo/AlgoSignTransaction.ts +52 -0
- package/src/api/allnetwork/AllNetworkGetAddress.ts +88 -0
- package/src/api/allnetwork/AllNetworkGetAddressBase.ts +529 -0
- package/src/api/allnetwork/AllNetworkGetAddressByLoop.ts +162 -0
- package/src/api/aptos/AptosGetAddress.ts +129 -0
- package/src/api/aptos/AptosGetPublicKey.ts +64 -0
- package/src/api/aptos/AptosSignInMessage.ts +55 -0
- package/src/api/aptos/AptosSignMessage.ts +79 -0
- package/src/api/aptos/AptosSignTransaction.ts +72 -0
- package/src/api/benfen/BenfenGetAddress.ts +122 -0
- package/src/api/benfen/BenfenGetPublicKey.ts +68 -0
- package/src/api/benfen/BenfenSignMessage.ts +50 -0
- package/src/api/benfen/BenfenSignTransaction.ts +105 -0
- package/src/api/benfen/normalize.ts +51 -0
- package/src/api/btc/BTCGetAddress.ts +91 -0
- package/src/api/btc/BTCGetPublicKey.ts +174 -0
- package/src/api/btc/BTCSignMessage.ts +73 -0
- package/src/api/btc/BTCSignPsbt.ts +65 -0
- package/src/api/btc/BTCSignTransaction.ts +148 -0
- package/src/api/btc/BTCVerifyMessage.ts +46 -0
- package/src/api/btc/helpers/btcParamsUtils.ts +64 -0
- package/src/api/btc/helpers/signtx.ts +251 -0
- package/src/api/btc/helpers/signtxLegacy.ts +227 -0
- package/src/api/btc/helpers/versionLimit.ts +25 -0
- package/src/api/btc/helpers/xpubUtils.ts +132 -0
- package/src/api/cardano/CardanoGetAddress.ts +139 -0
- package/src/api/cardano/CardanoGetPublicKey.ts +72 -0
- package/src/api/cardano/CardanoSignMessage.ts +73 -0
- package/src/api/cardano/CardanoSignTransaction.ts +404 -0
- package/src/api/cardano/helper/addressParameters.ts +120 -0
- package/src/api/cardano/helper/auxiliaryData.ts +133 -0
- package/src/api/cardano/helper/cardanoInputs.ts +55 -0
- package/src/api/cardano/helper/cardanoOutputs.ts +89 -0
- package/src/api/cardano/helper/certificate.ts +246 -0
- package/src/api/cardano/helper/token.ts +44 -0
- package/src/api/cardano/helper/utils.ts +17 -0
- package/src/api/cardano/helper/witnesses.ts +62 -0
- package/src/api/conflux/ConfluxGetAddress.ts +78 -0
- package/src/api/conflux/ConfluxSignMessage.ts +49 -0
- package/src/api/conflux/ConfluxSignMessageCIP23.ts +49 -0
- package/src/api/conflux/ConfluxSignTransaction.ts +135 -0
- package/src/api/cosmos/CosmosGetAddress.ts +80 -0
- package/src/api/cosmos/CosmosGetPublicKey.ts +77 -0
- package/src/api/cosmos/CosmosSignTransaction.ts +68 -0
- package/src/api/device/DeviceBackup.ts +15 -0
- package/src/api/device/DeviceCancel.ts +15 -0
- package/src/api/device/DeviceChangePin.ts +25 -0
- package/src/api/device/DeviceFlags.ts +26 -0
- package/src/api/device/DeviceFullyUploadResource.ts +80 -0
- package/src/api/device/DeviceLock.ts +15 -0
- package/src/api/device/DeviceRebootToBoardloader.ts +30 -0
- package/src/api/device/DeviceRebootToBootloader.ts +28 -0
- package/src/api/device/DeviceRecovery.ts +44 -0
- package/src/api/device/DeviceReset.ts +46 -0
- package/src/api/device/DeviceSettings.ts +96 -0
- package/src/api/device/DeviceSupportFeatures.ts +29 -0
- package/src/api/device/DeviceUnlock.ts +13 -0
- package/src/api/device/DeviceUpdateBootloader.ts +111 -0
- package/src/api/device/DeviceUpdateReboot.ts +17 -0
- package/src/api/device/DeviceUploadResource.ts +204 -0
- package/src/api/device/DeviceVerify.ts +65 -0
- package/src/api/device/DeviceWipe.ts +15 -0
- package/src/api/dynex/DnxGetAddress.ts +75 -0
- package/src/api/dynex/DnxSignTransaction.ts +126 -0
- package/src/api/evm/EVMGetAddress.ts +88 -0
- package/src/api/evm/EVMGetPublicKey.ts +116 -0
- package/src/api/evm/EVMSignMessage.ts +49 -0
- package/src/api/evm/EVMSignMessageEIP712.ts +56 -0
- package/src/api/evm/EVMSignTransaction.ts +141 -0
- package/src/api/evm/EVMSignTypedData.ts +477 -0
- package/src/api/evm/EVMVerifyMessage.ts +46 -0
- package/src/api/evm/latest/getAddress.ts +13 -0
- package/src/api/evm/latest/getPublicKey.ts +17 -0
- package/src/api/evm/latest/signMessage.ts +19 -0
- package/src/api/evm/latest/signTransaction.ts +303 -0
- package/src/api/evm/latest/signTypedData.ts +34 -0
- package/src/api/evm/latest/signTypedHash.ts +46 -0
- package/src/api/evm/latest/verifyMessage.ts +15 -0
- package/src/api/evm/legacyV1/getAddress.ts +16 -0
- package/src/api/evm/legacyV1/getPublicKey.ts +20 -0
- package/src/api/evm/legacyV1/signMessage.ts +22 -0
- package/src/api/evm/legacyV1/signTransaction.ts +37 -0
- package/src/api/evm/legacyV1/signTypedData.ts +37 -0
- package/src/api/evm/legacyV1/signTypedHash.ts +50 -0
- package/src/api/evm/legacyV1/verifyMessage.ts +19 -0
- package/src/api/filecoin/FilecoinGetAddress.ts +80 -0
- package/src/api/filecoin/FilecoinSignTransaction.ts +57 -0
- package/src/api/firmware/FirmwareUpdateBaseMethod.ts +476 -0
- package/src/api/firmware/bootloaderHelper.ts +46 -0
- package/src/api/firmware/getBinary.ts +99 -0
- package/src/api/firmware/releaseHelper.ts +78 -0
- package/src/api/firmware/updateBootloader.ts +82 -0
- package/src/api/firmware/uploadFirmware.ts +541 -0
- package/src/api/helpers/batchGetPublickeys.ts +84 -0
- package/src/api/helpers/bigNumberUtils.ts +58 -0
- package/src/api/helpers/hexUtils.ts +111 -0
- package/src/api/helpers/paramsValidator.ts +165 -0
- package/src/api/helpers/pathUtils.ts +145 -0
- package/src/api/helpers/stringUtils.ts +11 -0
- package/src/api/helpers/typeNameUtils.ts +137 -0
- package/src/api/index.ts +161 -0
- package/src/api/kaspa/KaspaGetAddress.ts +103 -0
- package/src/api/kaspa/KaspaSignTransaction.ts +182 -0
- package/src/api/kaspa/helpers/BufferWriter.ts +177 -0
- package/src/api/kaspa/helpers/HashWriter.ts +74 -0
- package/src/api/kaspa/helpers/SignatureType.ts +7 -0
- package/src/api/kaspa/helpers/TransferSerialize.ts +144 -0
- package/src/api/lightning/LnurlAuth.ts +52 -0
- package/src/api/near/NearGetAddress.ts +75 -0
- package/src/api/near/NearSignTransaction.ts +46 -0
- package/src/api/nem/NEMGetAddress.ts +72 -0
- package/src/api/nem/NEMSignTransaction.ts +251 -0
- package/src/api/neo/NeoGetAddress.ts +80 -0
- package/src/api/neo/NeoSignTransaction.ts +59 -0
- package/src/api/nervos/NervosGetAddress.ts +80 -0
- package/src/api/nervos/NervosSignTransaction.ts +116 -0
- package/src/api/nexa/NexaGetAddress.ts +88 -0
- package/src/api/nexa/NexaSignTransaction.ts +107 -0
- package/src/api/nostr/NostrDecryptMessage.ts +57 -0
- package/src/api/nostr/NostrEncryptMessage.ts +57 -0
- package/src/api/nostr/NostrGetPublicKey.ts +74 -0
- package/src/api/nostr/NostrSignEvent.ts +65 -0
- package/src/api/nostr/NostrSignSchnorr.ts +52 -0
- package/src/api/nostr/helper/index.ts +28 -0
- package/src/api/polkadot/PolkadotGetAddress.ts +83 -0
- package/src/api/polkadot/PolkadotSignTransaction.ts +53 -0
- package/src/api/polkadot/networks.ts +72 -0
- package/src/api/scdo/ScdoGetAddress.ts +76 -0
- package/src/api/scdo/ScdoSignMessage.ts +45 -0
- package/src/api/scdo/ScdoSignTransaction.ts +106 -0
- package/src/api/solana/SolGetAddress.ts +68 -0
- package/src/api/solana/SolSignMessage.ts +61 -0
- package/src/api/solana/SolSignOffchainMessage.ts +61 -0
- package/src/api/solana/SolSignTransaction.ts +108 -0
- package/src/api/starcoin/StarcoinGetAddress.ts +69 -0
- package/src/api/starcoin/StarcoinGetPublicKey.ts +70 -0
- package/src/api/starcoin/StarcoinSignMessage.ts +42 -0
- package/src/api/starcoin/StarcoinSignTransaction.ts +38 -0
- package/src/api/starcoin/StarcoinVerifyMessage.ts +35 -0
- package/src/api/stellar/StellarGetAddress.ts +68 -0
- package/src/api/stellar/StellarSignTransaction.ts +220 -0
- package/src/api/sui/SuiGetAddress.ts +117 -0
- package/src/api/sui/SuiGetPublicKey.ts +66 -0
- package/src/api/sui/SuiSignMessage.ts +48 -0
- package/src/api/sui/SuiSignTransaction.ts +126 -0
- package/src/api/sui/normalize.ts +28 -0
- package/src/api/test/TestInitializeDeviceDuration.ts +22 -0
- package/src/api/ton/TonGetAddress.ts +96 -0
- package/src/api/ton/TonSignMessage.ts +217 -0
- package/src/api/ton/TonSignProof.ts +62 -0
- package/src/api/tron/TronGetAddress.ts +75 -0
- package/src/api/tron/TronSignMessage.ts +89 -0
- package/src/api/tron/TronSignTransaction.ts +214 -0
- package/src/api/u2f/GetNextU2FCounter.ts +15 -0
- package/src/api/u2f/SetU2FCounter.ts +19 -0
- package/src/api/utils.ts +23 -0
- package/src/api/xrp/XrpGetAddress.ts +96 -0
- package/src/api/xrp/XrpSignTransaction.ts +71 -0
- package/src/constants/errors.ts +15 -0
- package/src/constants/index.ts +2 -0
- package/src/constants/ui-request.ts +3 -0
- package/src/core/RequestQueue.ts +134 -0
- package/src/core/index.ts +1320 -0
- package/src/data/coins/bitcoin.json +44 -0
- package/src/data/config.ts +25 -0
- package/src/data/messages/messages.json +13167 -0
- package/src/data/messages/messages_legacy_v1.json +10282 -0
- package/src/data-manager/CoinManager.ts +31 -0
- package/src/data-manager/DataManager.ts +499 -0
- package/src/data-manager/MessagesConfig.ts +28 -0
- package/src/data-manager/TransportManager.ts +140 -0
- package/src/data-manager/connectSettings.ts +121 -0
- package/src/data-manager/index.ts +3 -0
- package/src/device/Device.ts +884 -0
- package/src/device/DeviceCommands.ts +631 -0
- package/src/device/DeviceConnector.ts +124 -0
- package/src/device/DeviceList.ts +39 -0
- package/src/device/DevicePool.ts +266 -0
- package/src/events/call.ts +95 -0
- package/src/events/core.ts +65 -0
- package/src/events/device.ts +92 -0
- package/src/events/firmware.ts +43 -0
- package/src/events/iframe.ts +55 -0
- package/src/events/index.ts +10 -0
- package/src/events/log.ts +23 -0
- package/src/events/logBlockEvent.ts +6 -0
- package/src/events/ui-promise.ts +14 -0
- package/src/events/ui-request.ts +216 -0
- package/src/events/ui-response.ts +59 -0
- package/src/events/utils.ts +19 -0
- package/src/index.ts +70 -0
- package/src/inject.ts +408 -0
- package/src/lowLevelInject.ts +61 -0
- package/src/topLevelInject.ts +62 -0
- package/src/types/api/alephiumGetAddress.ts +31 -0
- package/src/types/api/alephiumSignMessage.ts +14 -0
- package/src/types/api/alephiumSignTransaction.ts +18 -0
- package/src/types/api/algoGetAddress.ts +23 -0
- package/src/types/api/algoSignTransaction.ts +17 -0
- package/src/types/api/allNetworkGetAddress.ts +130 -0
- package/src/types/api/aptosGetAddress.ts +28 -0
- package/src/types/api/aptosGetPublicKey.ts +27 -0
- package/src/types/api/aptosSignInMessage.ts +17 -0
- package/src/types/api/aptosSignMessage.ts +26 -0
- package/src/types/api/aptosSignTransaction.ts +18 -0
- package/src/types/api/benfenGetAddress.ts +24 -0
- package/src/types/api/benfenGetPublicKey.ts +23 -0
- package/src/types/api/benfenSignMessage.ts +13 -0
- package/src/types/api/benfenSignTransaction.ts +19 -0
- package/src/types/api/btcGetAddress.ts +26 -0
- package/src/types/api/btcGetPublicKey.ts +26 -0
- package/src/types/api/btcSignMessage.ts +16 -0
- package/src/types/api/btcSignPsbt.ts +13 -0
- package/src/types/api/btcSignTransaction.ts +98 -0
- package/src/types/api/btcVerifyMessage.ts +15 -0
- package/src/types/api/cardano.ts +212 -0
- package/src/types/api/cardanoGetAddress.ts +49 -0
- package/src/types/api/cardanoGetPublicKey.ts +33 -0
- package/src/types/api/cardanoSignMessage.ts +31 -0
- package/src/types/api/cardanoSignTransaction.ts +8 -0
- package/src/types/api/checkAllFirmwareRelease.ts +34 -0
- package/src/types/api/checkBLEFirmwareRelease.ts +15 -0
- package/src/types/api/checkBootloaderRelease.ts +19 -0
- package/src/types/api/checkBridgeRelease.ts +14 -0
- package/src/types/api/checkBridgeStatus.ts +3 -0
- package/src/types/api/checkFirmwareRelease.ts +23 -0
- package/src/types/api/checkFirmwareTypeAvailable.ts +12 -0
- package/src/types/api/cipherKeyValue.ts +28 -0
- package/src/types/api/confluxGetAddress.ts +24 -0
- package/src/types/api/confluxSignMessage.ts +13 -0
- package/src/types/api/confluxSignMessageCIP23.ts +14 -0
- package/src/types/api/confluxSignTransaction.ts +32 -0
- package/src/types/api/cosmosGetAddress.ts +24 -0
- package/src/types/api/cosmosGetPublicKey.ts +28 -0
- package/src/types/api/cosmosSignTransaction.ts +17 -0
- package/src/types/api/deviceBackup.ts +4 -0
- package/src/types/api/deviceCancel.ts +4 -0
- package/src/types/api/deviceChangePin.ts +11 -0
- package/src/types/api/deviceFlags.ts +11 -0
- package/src/types/api/deviceFullyUploadResource.ts +15 -0
- package/src/types/api/deviceLock.ts +4 -0
- package/src/types/api/deviceRebootToBoardloader.ts +6 -0
- package/src/types/api/deviceRebootToBootloader.ts +4 -0
- package/src/types/api/deviceRecovery.ts +19 -0
- package/src/types/api/deviceReset.ts +20 -0
- package/src/types/api/deviceSettings.ts +23 -0
- package/src/types/api/deviceSupportFeatures.ts +6 -0
- package/src/types/api/deviceUnlock.ts +4 -0
- package/src/types/api/deviceUpdateBootloader.ts +13 -0
- package/src/types/api/deviceUpdateReboot.ts +3 -0
- package/src/types/api/deviceUploadResource.ts +21 -0
- package/src/types/api/deviceVerify.ts +15 -0
- package/src/types/api/deviceWipe.ts +4 -0
- package/src/types/api/dnxGetAddress.ts +23 -0
- package/src/types/api/dnxSignTransaction.ts +36 -0
- package/src/types/api/event.ts +8 -0
- package/src/types/api/evmGetAddress.ts +24 -0
- package/src/types/api/evmGetPublicKey.ts +36 -0
- package/src/types/api/evmSignMessage.ts +14 -0
- package/src/types/api/evmSignMessageEIP712.ts +14 -0
- package/src/types/api/evmSignTransaction.ts +80 -0
- package/src/types/api/evmSignTypedData.ts +42 -0
- package/src/types/api/evmVerifyMessage.ts +15 -0
- package/src/types/api/export.ts +194 -0
- package/src/types/api/filecoinGetAddress.ts +24 -0
- package/src/types/api/filecoinSignTransaction.ts +24 -0
- package/src/types/api/firmwareUpdate.ts +66 -0
- package/src/types/api/getFeatures.ts +4 -0
- package/src/types/api/getLogs.ts +3 -0
- package/src/types/api/getNextU2FCounter.ts +7 -0
- package/src/types/api/getOnetokenFeatures.ts +7 -0
- package/src/types/api/getPassphraseState.ts +6 -0
- package/src/types/api/index.ts +404 -0
- package/src/types/api/init.ts +11 -0
- package/src/types/api/kaspaGetAddress.ts +26 -0
- package/src/types/api/kaspaSignTransaction.ts +44 -0
- package/src/types/api/lnurlAuth.ts +22 -0
- package/src/types/api/nearGetAddress.ts +23 -0
- package/src/types/api/nearSignTransaction.ts +13 -0
- package/src/types/api/nemGetAddress.ts +24 -0
- package/src/types/api/nemSignTransaction.ts +118 -0
- package/src/types/api/neoGetAddress.ts +24 -0
- package/src/types/api/neoSignTransaction.ts +18 -0
- package/src/types/api/nervosGetAddress.ts +24 -0
- package/src/types/api/nervosSignTransaction.ts +19 -0
- package/src/types/api/nexaGetAddress.ts +26 -0
- package/src/types/api/nexaSignTransaction.ts +28 -0
- package/src/types/api/nostrDecryptMessage.ts +25 -0
- package/src/types/api/nostrEncryptMessage.ts +25 -0
- package/src/types/api/nostrGetPublicKey.ts +28 -0
- package/src/types/api/nostrSignEvent.ts +52 -0
- package/src/types/api/nostrSignSchnorr.ts +22 -0
- package/src/types/api/polkadotGetAddress.ts +30 -0
- package/src/types/api/polkadotSignTransaction.ts +19 -0
- package/src/types/api/promptWebDeviceAccess.ts +6 -0
- package/src/types/api/scdoGetAddress.ts +23 -0
- package/src/types/api/scdoSignMessage.ts +13 -0
- package/src/types/api/scdoSignTransaction.ts +24 -0
- package/src/types/api/searchDevices.ts +4 -0
- package/src/types/api/setU2FCounter.ts +7 -0
- package/src/types/api/solGetAddress.ts +23 -0
- package/src/types/api/solSignMessage.ts +17 -0
- package/src/types/api/solSignOffchainMessage.ts +24 -0
- package/src/types/api/solSignTransaction.ts +27 -0
- package/src/types/api/starcoinGetAddress.ts +23 -0
- package/src/types/api/starcoinGetPublicKey.ts +23 -0
- package/src/types/api/starcoinSignMessage.ts +13 -0
- package/src/types/api/starcoinSignTransaction.ts +13 -0
- package/src/types/api/starcoinVerifyMessage.ts +14 -0
- package/src/types/api/stellarGetAddress.ts +23 -0
- package/src/types/api/stellarSignTransaction.ts +154 -0
- package/src/types/api/suiGetAddress.ts +28 -0
- package/src/types/api/suiGetPublicKey.ts +27 -0
- package/src/types/api/suiSignMessage.ts +13 -0
- package/src/types/api/suiSignTransaction.ts +17 -0
- package/src/types/api/testInitializeDeviceDuration.ts +6 -0
- package/src/types/api/tonGetAddress.ts +34 -0
- package/src/types/api/tonSignMessage.ts +42 -0
- package/src/types/api/tonSignProof.ts +25 -0
- package/src/types/api/tronGetAddress.ts +23 -0
- package/src/types/api/tronSignMessage.ts +14 -0
- package/src/types/api/tronSignTransaction.ts +89 -0
- package/src/types/api/uiResponse.ts +3 -0
- package/src/types/api/xrpGetAddress.ts +28 -0
- package/src/types/api/xrpSignTransaction.ts +29 -0
- package/src/types/device.ts +194 -0
- package/src/types/firmware.ts +41 -0
- package/src/types/global.d.ts +3 -0
- package/src/types/index.ts +5 -0
- package/src/types/params.ts +64 -0
- package/src/types/settings.ts +144 -0
- package/src/utils/arrayUtils.ts +7 -0
- package/src/utils/assets.ts +5 -0
- package/src/utils/bridgeUpdate.ts +80 -0
- package/src/utils/capabilitieUtils.ts +12 -0
- package/src/utils/deviceFeaturesUtils.ts +352 -0
- package/src/utils/deviceInfoUtils.ts +167 -0
- package/src/utils/deviceSettings.ts +109 -0
- package/src/utils/deviceVersionUtils.ts +79 -0
- package/src/utils/findDefectiveBatchDevice.ts +39 -0
- package/src/utils/getMutex.ts +41 -0
- package/src/utils/getSynchronize.ts +25 -0
- package/src/utils/homescreen.ts +345 -0
- package/src/utils/index.ts +44 -0
- package/src/utils/logger.ts +190 -0
- package/src/utils/networkUtils.ts +25 -0
- package/src/utils/patch.ts +14 -0
- package/src/utils/promiseUtils.ts +4 -0
- package/src/utils/release.ts +42 -0
- package/src/utils/semver.test.js +53 -0
- package/src/utils/tracing.ts +238 -0
- package/src/utils/versionUtils.ts +120 -0
- package/tsconfig.json +11 -0
|
@@ -0,0 +1,1320 @@
|
|
|
1
|
+
import semver from 'semver';
|
|
2
|
+
import EventEmitter from 'events';
|
|
3
|
+
import {
|
|
4
|
+
ERRORS,
|
|
5
|
+
ERROR_CODES_REQUIRE_RELEASE,
|
|
6
|
+
HardwareError,
|
|
7
|
+
HardwareErrorCode,
|
|
8
|
+
createDefectiveFirmwareError,
|
|
9
|
+
createDeferred,
|
|
10
|
+
createDeprecatedHardwareError,
|
|
11
|
+
createDeviceNotSupportMethodError,
|
|
12
|
+
createNeedUpgradeFirmwareHardwareError,
|
|
13
|
+
createNewFirmwareForceUpdateHardwareError,
|
|
14
|
+
createNewFirmwareUnReleaseHardwareError,
|
|
15
|
+
} from '@onetokenfe/hd-shared';
|
|
16
|
+
|
|
17
|
+
import {
|
|
18
|
+
LoggerNames,
|
|
19
|
+
enableLog,
|
|
20
|
+
getDeviceBLEFirmwareVersion,
|
|
21
|
+
getDeviceFirmwareVersion,
|
|
22
|
+
getFirmwareType,
|
|
23
|
+
getLogger,
|
|
24
|
+
getMethodVersionRange,
|
|
25
|
+
setLoggerPostMessage,
|
|
26
|
+
wait,
|
|
27
|
+
} from '../utils';
|
|
28
|
+
import {
|
|
29
|
+
findDefectiveBatchDevice,
|
|
30
|
+
getDefectiveDeviceInfo,
|
|
31
|
+
} from '../utils/findDefectiveBatchDevice';
|
|
32
|
+
import { supportNewPassphrase } from '../utils/deviceFeaturesUtils';
|
|
33
|
+
import {
|
|
34
|
+
cleanupSdkInstance,
|
|
35
|
+
completeRequestContext,
|
|
36
|
+
createRequestContext,
|
|
37
|
+
createSdkTracingContext,
|
|
38
|
+
formatRequestContext,
|
|
39
|
+
getActiveRequestsByDeviceInstance,
|
|
40
|
+
updateRequestContext,
|
|
41
|
+
} from '../utils/tracing';
|
|
42
|
+
import { Device } from '../device/Device';
|
|
43
|
+
import { DeviceList } from '../device/DeviceList';
|
|
44
|
+
import { DevicePool } from '../device/DevicePool';
|
|
45
|
+
import { findMethod } from '../api/utils';
|
|
46
|
+
import { DataManager } from '../data-manager';
|
|
47
|
+
import { UI_REQUEST as UI_REQUEST_CONST } from '../constants/ui-request';
|
|
48
|
+
import {
|
|
49
|
+
CORE_EVENT,
|
|
50
|
+
DEVICE,
|
|
51
|
+
IFRAME,
|
|
52
|
+
UI_REQUEST,
|
|
53
|
+
UI_RESPONSE,
|
|
54
|
+
createDeviceMessage,
|
|
55
|
+
createResponseMessage,
|
|
56
|
+
createUiMessage,
|
|
57
|
+
} from '../events';
|
|
58
|
+
import TransportManager from '../data-manager/TransportManager';
|
|
59
|
+
import DeviceConnector from '../device/DeviceConnector';
|
|
60
|
+
import RequestQueue from './RequestQueue';
|
|
61
|
+
import { getSynchronize } from '../utils/getSynchronize';
|
|
62
|
+
|
|
63
|
+
import type { ConnectSettings, KnownDevice } from '../types';
|
|
64
|
+
import type { CoreMessage, IFrameCallMessage, UiPromise, UiPromiseResponse } from '../events';
|
|
65
|
+
import type { DeviceEvents, InitOptions, RunOptions } from '../device/Device';
|
|
66
|
+
import type { SdkTracingContext } from '../utils/tracing';
|
|
67
|
+
import type { Deferred } from '@onetokenfe/hd-shared';
|
|
68
|
+
import type {
|
|
69
|
+
Features,
|
|
70
|
+
LowlevelTransportSharedPlugin,
|
|
71
|
+
OneTokenDeviceInfo,
|
|
72
|
+
} from '@onetokenfe/hd-transport';
|
|
73
|
+
import type { BaseMethod } from '../api/BaseMethod';
|
|
74
|
+
|
|
75
|
+
const Log = getLogger(LoggerNames.Core);
|
|
76
|
+
|
|
77
|
+
export type CoreContext = ReturnType<Core['getCoreContext']>;
|
|
78
|
+
|
|
79
|
+
function hasDeriveCardano(method: BaseMethod): boolean {
|
|
80
|
+
if (
|
|
81
|
+
method.name.startsWith('allNetworkGetAddress') &&
|
|
82
|
+
method.payload &&
|
|
83
|
+
method.payload.bundle &&
|
|
84
|
+
// @ts-expect-error
|
|
85
|
+
method.payload.bundle.some(net => net && net.network === 'ada')
|
|
86
|
+
) {
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return method.name.startsWith('cardano') || method.payload?.deriveCardano;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const parseInitOptions = (method?: BaseMethod): InitOptions => ({
|
|
94
|
+
initSession: method?.payload.initSession,
|
|
95
|
+
passphraseState: method?.payload.passphraseState,
|
|
96
|
+
deviceId: method?.payload.deviceId,
|
|
97
|
+
deriveCardano: method && hasDeriveCardano(method),
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
let _core: Core;
|
|
101
|
+
let _deviceList: DeviceList | undefined;
|
|
102
|
+
let _connector: DeviceConnector | undefined;
|
|
103
|
+
let _uiPromises: UiPromise<UiPromiseResponse['type']>[] = []; // Waiting for ui response
|
|
104
|
+
|
|
105
|
+
const deviceCacheMap = new Map<string, Device>();
|
|
106
|
+
let pollingId = 1;
|
|
107
|
+
const pollingState: Record<number, boolean> = {};
|
|
108
|
+
|
|
109
|
+
let preConnectCache: {
|
|
110
|
+
passphraseState: string | undefined;
|
|
111
|
+
} = {
|
|
112
|
+
passphraseState: undefined,
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const toError = (error: unknown): Error | undefined => {
|
|
116
|
+
if (error instanceof Error) return error;
|
|
117
|
+
if (error == null) return undefined;
|
|
118
|
+
if (typeof error === 'string') return new Error(error);
|
|
119
|
+
try {
|
|
120
|
+
return new Error(JSON.stringify(error));
|
|
121
|
+
} catch {
|
|
122
|
+
return new Error(String(error));
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const updateMethodRequestContext = (method: BaseMethod, updates: any) => {
|
|
127
|
+
if (method.requestContext) {
|
|
128
|
+
updateRequestContext(method.requestContext.responseID, updates);
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const completeMethodRequestContext = (method: BaseMethod, error?: unknown) => {
|
|
133
|
+
if (!method.requestContext) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
completeRequestContext(method.requestContext.responseID, toError(error));
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
export const callAPI = async (context: CoreContext, message: CoreMessage) => {
|
|
140
|
+
if (!message.id || !message.payload || message.type !== IFRAME.CALL) {
|
|
141
|
+
return Promise.reject(ERRORS.TypedError('on call: message.id or message.payload is missing'));
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// find api method
|
|
145
|
+
let method: BaseMethod;
|
|
146
|
+
try {
|
|
147
|
+
method = findMethod(message as IFrameCallMessage);
|
|
148
|
+
method.connector = _connector;
|
|
149
|
+
method.postMessage = postMessage;
|
|
150
|
+
method.setContext?.(context);
|
|
151
|
+
|
|
152
|
+
method.requestContext = createRequestContext(method.responseID, method.name, {
|
|
153
|
+
sdkInstanceId: context.sdkInstanceId,
|
|
154
|
+
connectId: method.connectId,
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
Log.debug(`[${context.sdkInstanceId}] callAPI: ${formatRequestContext(method.requestContext)}`);
|
|
158
|
+
|
|
159
|
+
method.init();
|
|
160
|
+
} catch (error) {
|
|
161
|
+
return Promise.reject(error);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
DevicePool.emitter.on(DEVICE.CONNECT, onDeviceConnectHandler);
|
|
165
|
+
|
|
166
|
+
if (!method.useDevice) {
|
|
167
|
+
updateMethodRequestContext(method, { status: 'running' });
|
|
168
|
+
try {
|
|
169
|
+
const response = await method.run();
|
|
170
|
+
completeMethodRequestContext(method);
|
|
171
|
+
return createResponseMessage(method.responseID, true, response);
|
|
172
|
+
} catch (error) {
|
|
173
|
+
completeMethodRequestContext(method, error);
|
|
174
|
+
return createResponseMessage(method.responseID, false, { error });
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
// push method to queue
|
|
178
|
+
// callApiQueue.push(method);
|
|
179
|
+
|
|
180
|
+
// if (callApiQueue.length > 1) {
|
|
181
|
+
// Log.debug(
|
|
182
|
+
// 'should cancel the previous method execution: ',
|
|
183
|
+
// callApiQueue.map(m => m.name)
|
|
184
|
+
// );
|
|
185
|
+
// }
|
|
186
|
+
|
|
187
|
+
const { requestQueue, methodSynchronize } = context;
|
|
188
|
+
const error = await methodSynchronize(() => {
|
|
189
|
+
for (const requestId of requestQueue.getRequestTasksId()) {
|
|
190
|
+
const task = requestQueue.getTask(requestId);
|
|
191
|
+
Log.debug(
|
|
192
|
+
'pre request task: ',
|
|
193
|
+
`task?.id: ${task?.id},
|
|
194
|
+
task?.method.connectId: ${task?.method.connectId},
|
|
195
|
+
task?.method.deviceId: ${task?.method.deviceId},
|
|
196
|
+
task?.method.name: ${task?.method.name}`
|
|
197
|
+
);
|
|
198
|
+
// if (task) {
|
|
199
|
+
// return Promise.reject(ERRORS.TypedError(HardwareErrorCode.DeviceBusy));
|
|
200
|
+
// }
|
|
201
|
+
}
|
|
202
|
+
return null;
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
if (error) {
|
|
206
|
+
return createResponseMessage(method.responseID, false, { error });
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return onCallDevice(context, message, method);
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
const waitWithTimeout = async (promise: Promise<any>, timeout: number) => {
|
|
213
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
214
|
+
setTimeout(() => reject(new Error('Request timeout')), timeout);
|
|
215
|
+
});
|
|
216
|
+
return Promise.race([promise, timeoutPromise]);
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
const waitForPendingPromise = async (
|
|
220
|
+
getPrePendingCallPromise: () => Promise<void> | undefined,
|
|
221
|
+
removePrePendingCallPromise?: (promise: Promise<void> | undefined) => void
|
|
222
|
+
) => {
|
|
223
|
+
const pendingPromise = getPrePendingCallPromise();
|
|
224
|
+
if (pendingPromise) {
|
|
225
|
+
Log.debug('pre pending call promise before call method, wait for it');
|
|
226
|
+
try {
|
|
227
|
+
await waitWithTimeout(pendingPromise, 5 * 1000);
|
|
228
|
+
} catch (error) {
|
|
229
|
+
// ignore timeout error
|
|
230
|
+
}
|
|
231
|
+
removePrePendingCallPromise?.(pendingPromise);
|
|
232
|
+
Log.debug('pre pending call promise before call method done');
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
const onCallDevice = async (
|
|
237
|
+
context: CoreContext,
|
|
238
|
+
message: CoreMessage,
|
|
239
|
+
method: BaseMethod
|
|
240
|
+
): Promise<any> => {
|
|
241
|
+
let messageResponse: any;
|
|
242
|
+
|
|
243
|
+
const { requestQueue, getPrePendingCallPromise, setPrePendingCallPromise } = context;
|
|
244
|
+
|
|
245
|
+
updateMethodRequestContext(method, { status: 'running' });
|
|
246
|
+
|
|
247
|
+
const connectStateChange = preConnectCache.passphraseState !== method.payload.passphraseState;
|
|
248
|
+
|
|
249
|
+
preConnectCache = {
|
|
250
|
+
passphraseState: method.payload.passphraseState,
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
if (connectStateChange || method.payload.initSession) {
|
|
254
|
+
Log.debug('passphrase state change, clear device cache');
|
|
255
|
+
DevicePool.clearDeviceCache(method.payload.connectId);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// wait for previous callback tasks to complete (ensure device does not call concurrently)
|
|
259
|
+
if (method.connectId) {
|
|
260
|
+
await context.waitForCallbackTasks(method.connectId);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
await waitForPendingPromise(getPrePendingCallPromise, setPrePendingCallPromise);
|
|
264
|
+
|
|
265
|
+
const task = requestQueue.createTask(method);
|
|
266
|
+
|
|
267
|
+
let device: Device;
|
|
268
|
+
try {
|
|
269
|
+
/**
|
|
270
|
+
* Polling to ensure successful connection
|
|
271
|
+
*/
|
|
272
|
+
if (pollingState[pollingId]) {
|
|
273
|
+
pollingState[pollingId] = false;
|
|
274
|
+
}
|
|
275
|
+
pollingId += 1;
|
|
276
|
+
|
|
277
|
+
device = await ensureConnected(context, method, pollingId, task.abortController?.signal);
|
|
278
|
+
} catch (e) {
|
|
279
|
+
console.log('ensureConnected error: ', e);
|
|
280
|
+
|
|
281
|
+
completeMethodRequestContext(method, e);
|
|
282
|
+
|
|
283
|
+
if (e.name === 'AbortError' || e.message === 'Request aborted') {
|
|
284
|
+
requestQueue.releaseTask(method.responseID);
|
|
285
|
+
return createResponseMessage(method.responseID, false, {
|
|
286
|
+
error: ERRORS.TypedError(HardwareErrorCode.ActionCancelled, 'Request cancelled by user'),
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
requestQueue.releaseTask(method.responseID);
|
|
290
|
+
return createResponseMessage(method.responseID, false, { error: e });
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
if (method.payload?.onlyConnectBleDevice) {
|
|
294
|
+
Log.debug('Call API - only connect ble device: ', device?.mainId);
|
|
295
|
+
return createResponseMessage(method.responseID, true, null);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
Log.debug('Call API - setDevice: ', device.mainId);
|
|
299
|
+
method.setDevice?.(device);
|
|
300
|
+
method.context = context;
|
|
301
|
+
|
|
302
|
+
updateMethodRequestContext(method, {
|
|
303
|
+
deviceInstanceId: device.instanceId,
|
|
304
|
+
commandsInstanceId: device.commands?.instanceId,
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
const activeRequests = getActiveRequestsByDeviceInstance(device.instanceId);
|
|
308
|
+
if (activeRequests.length > 0) {
|
|
309
|
+
Log.warn(
|
|
310
|
+
`[${method.instanceId}] Device ${device.instanceId} has ${activeRequests.length} active requests:`,
|
|
311
|
+
activeRequests.map(formatRequestContext)
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
device.on(DEVICE.PIN, onDevicePinHandler);
|
|
316
|
+
device.on(DEVICE.BUTTON, onDeviceButtonHandler);
|
|
317
|
+
device.on(
|
|
318
|
+
DEVICE.PASSPHRASE,
|
|
319
|
+
message.payload.useEmptyPassphrase ? onEmptyPassphraseHandler : onDevicePassphraseHandler
|
|
320
|
+
);
|
|
321
|
+
device.on(DEVICE.PASSPHRASE_ON_DEVICE, onEnterPassphraseOnDeviceHandler);
|
|
322
|
+
device.on(DEVICE.FEATURES, onDeviceFeaturesHandler);
|
|
323
|
+
device.on(
|
|
324
|
+
DEVICE.SELECT_DEVICE_IN_BOOTLOADER_FOR_WEB_DEVICE,
|
|
325
|
+
onSelectDeviceInBootloaderForWebDeviceHandler
|
|
326
|
+
);
|
|
327
|
+
device.on(
|
|
328
|
+
DEVICE.SELECT_DEVICE_FOR_SWITCH_FIRMWARE_WEB_DEVICE,
|
|
329
|
+
onSelectDeviceForSwitchFirmwareWebDeviceHandler
|
|
330
|
+
);
|
|
331
|
+
|
|
332
|
+
try {
|
|
333
|
+
if (method.connectId) {
|
|
334
|
+
await context.waitForCallbackTasks(method.connectId);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
await waitForPendingPromise(getPrePendingCallPromise, setPrePendingCallPromise);
|
|
338
|
+
|
|
339
|
+
const inner = async (): Promise<void> => {
|
|
340
|
+
// check firmware version
|
|
341
|
+
const versionRange = getMethodVersionRange(
|
|
342
|
+
device.features,
|
|
343
|
+
type => method.getVersionRange()[type]
|
|
344
|
+
);
|
|
345
|
+
|
|
346
|
+
if (device.features) {
|
|
347
|
+
await DataManager.checkAndReloadData();
|
|
348
|
+
|
|
349
|
+
// 检测故障固件设备
|
|
350
|
+
if (findDefectiveBatchDevice(device.features)) {
|
|
351
|
+
const defectiveInfo = getDefectiveDeviceInfo(device.features);
|
|
352
|
+
if (defectiveInfo) {
|
|
353
|
+
throw createDefectiveFirmwareError(
|
|
354
|
+
defectiveInfo.serialNo,
|
|
355
|
+
defectiveInfo.seVersion || 'Unknown',
|
|
356
|
+
defectiveInfo.deviceType,
|
|
357
|
+
method.connectId,
|
|
358
|
+
method.deviceId
|
|
359
|
+
);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
const deviceFirmwareType = getFirmwareType(device.features);
|
|
364
|
+
const newVersionStatus = DataManager.getFirmwareStatus(device.features, deviceFirmwareType);
|
|
365
|
+
const bleVersionStatus = DataManager.getBLEFirmwareStatus(device.features);
|
|
366
|
+
|
|
367
|
+
const currentFirmwareVersion = getDeviceFirmwareVersion(device.features).join('.');
|
|
368
|
+
const currentBleVersion = getDeviceBLEFirmwareVersion(device.features).join('.');
|
|
369
|
+
if (
|
|
370
|
+
(newVersionStatus === 'required' || bleVersionStatus === 'required') &&
|
|
371
|
+
method.skipForceUpdateCheck === false
|
|
372
|
+
) {
|
|
373
|
+
// Get current version information for error reporting
|
|
374
|
+
const currentVersions = {
|
|
375
|
+
firmware: currentFirmwareVersion,
|
|
376
|
+
ble: currentBleVersion,
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
// Provide more specific error message based on which version check failed
|
|
380
|
+
const requiredUpdates: ('firmware' | 'ble')[] = [];
|
|
381
|
+
if (newVersionStatus === 'required') {
|
|
382
|
+
requiredUpdates.push('firmware');
|
|
383
|
+
}
|
|
384
|
+
if (bleVersionStatus === 'required') {
|
|
385
|
+
requiredUpdates.push('ble');
|
|
386
|
+
}
|
|
387
|
+
throw createNewFirmwareForceUpdateHardwareError(
|
|
388
|
+
method.connectId,
|
|
389
|
+
method.deviceId,
|
|
390
|
+
requiredUpdates,
|
|
391
|
+
currentVersions
|
|
392
|
+
);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
if (versionRange) {
|
|
396
|
+
if (
|
|
397
|
+
semver.valid(versionRange.min) &&
|
|
398
|
+
semver.lt(currentFirmwareVersion, versionRange.min)
|
|
399
|
+
) {
|
|
400
|
+
if (newVersionStatus === 'none' || newVersionStatus === 'valid') {
|
|
401
|
+
throw createNewFirmwareUnReleaseHardwareError({
|
|
402
|
+
currentVersion: currentFirmwareVersion,
|
|
403
|
+
requireVersion: versionRange.min,
|
|
404
|
+
methodName: method.name,
|
|
405
|
+
firmwareType: getFirmwareType(device.features),
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
return Promise.reject(
|
|
410
|
+
createNeedUpgradeFirmwareHardwareError({
|
|
411
|
+
currentVersion: currentFirmwareVersion,
|
|
412
|
+
requireVersion: versionRange.min,
|
|
413
|
+
methodName: method.name,
|
|
414
|
+
firmwareType: getFirmwareType(device.features),
|
|
415
|
+
})
|
|
416
|
+
);
|
|
417
|
+
}
|
|
418
|
+
if (
|
|
419
|
+
versionRange.max &&
|
|
420
|
+
semver.valid(versionRange.max) &&
|
|
421
|
+
semver.gte(currentFirmwareVersion, versionRange.max)
|
|
422
|
+
) {
|
|
423
|
+
return Promise.reject(
|
|
424
|
+
createDeprecatedHardwareError(currentFirmwareVersion, versionRange.max, method.name)
|
|
425
|
+
);
|
|
426
|
+
}
|
|
427
|
+
} else if (method.strictCheckDeviceSupport) {
|
|
428
|
+
throw createDeviceNotSupportMethodError(method.name, getFirmwareType(device.features));
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
// check call method mode
|
|
433
|
+
const unexpectedMode = device.hasUnexpectedMode(
|
|
434
|
+
method.allowDeviceMode,
|
|
435
|
+
method.requireDeviceMode
|
|
436
|
+
);
|
|
437
|
+
if (unexpectedMode) {
|
|
438
|
+
if (unexpectedMode === UI_REQUEST_CONST.NOT_IN_BOOTLOADER) {
|
|
439
|
+
return Promise.reject(ERRORS.TypedError(HardwareErrorCode.RequiredButInBootloaderMode));
|
|
440
|
+
}
|
|
441
|
+
if (unexpectedMode === UI_REQUEST_CONST.BOOTLOADER) {
|
|
442
|
+
return Promise.reject(ERRORS.TypedError(HardwareErrorCode.NotAllowInBootloaderMode));
|
|
443
|
+
}
|
|
444
|
+
return Promise.reject(
|
|
445
|
+
ERRORS.TypedError(HardwareErrorCode.DeviceUnexpectedMode, unexpectedMode)
|
|
446
|
+
);
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
if (method.deviceId && method.checkDeviceId) {
|
|
450
|
+
const isSameDeviceID = device.checkDeviceId(method.deviceId);
|
|
451
|
+
if (!isSameDeviceID) {
|
|
452
|
+
return Promise.reject(ERRORS.TypedError(HardwareErrorCode.DeviceCheckDeviceIdError));
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* check firmware release info
|
|
458
|
+
*/
|
|
459
|
+
method.checkFirmwareRelease();
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* check additional supported feature
|
|
463
|
+
*/
|
|
464
|
+
method.checkDeviceSupportFeature();
|
|
465
|
+
|
|
466
|
+
// reconfigure messages
|
|
467
|
+
if (_deviceList) {
|
|
468
|
+
await TransportManager.reconfigure(device.features);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// Check to see if it is safe to use Passphrase
|
|
472
|
+
checkPassphraseEnableState(method, device.features);
|
|
473
|
+
|
|
474
|
+
if (device.hasUsePassphrase() && method.useDevicePassphraseState) {
|
|
475
|
+
// check version
|
|
476
|
+
const support = supportNewPassphrase(device.features);
|
|
477
|
+
if (!support.support) {
|
|
478
|
+
return Promise.reject(
|
|
479
|
+
ERRORS.TypedError(
|
|
480
|
+
HardwareErrorCode.DeviceNotSupportPassphrase,
|
|
481
|
+
`Device not support passphrase, please update to ${support.require}`,
|
|
482
|
+
{
|
|
483
|
+
require: support.require,
|
|
484
|
+
}
|
|
485
|
+
)
|
|
486
|
+
);
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
// Check Device passphrase State
|
|
490
|
+
const passphraseStateSafety = await device.checkPassphraseStateSafety(
|
|
491
|
+
method.payload?.passphraseState,
|
|
492
|
+
method.payload?.useEmptyPassphrase,
|
|
493
|
+
method.payload?.skipPassphraseCheck
|
|
494
|
+
);
|
|
495
|
+
|
|
496
|
+
// Double check, handles the special case of Touch/Pro
|
|
497
|
+
checkPassphraseEnableState(method, device.features);
|
|
498
|
+
|
|
499
|
+
if (!passphraseStateSafety) {
|
|
500
|
+
DevicePool.clearDeviceCache(method.payload.connectId);
|
|
501
|
+
return Promise.reject(
|
|
502
|
+
ERRORS.TypedError(HardwareErrorCode.DeviceCheckPassphraseStateError)
|
|
503
|
+
);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
// close pin popup window
|
|
507
|
+
postMessage(createUiMessage(UI_REQUEST.CLOSE_UI_PIN_WINDOW));
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// Automatic check safety_check level for Kovan, Ropsten, Rinkeby, Goerli test networks.
|
|
511
|
+
try {
|
|
512
|
+
await method.checkSafetyLevelOnTestNet();
|
|
513
|
+
} catch (e) {
|
|
514
|
+
const error =
|
|
515
|
+
e instanceof HardwareError
|
|
516
|
+
? e
|
|
517
|
+
: ERRORS.TypedError(HardwareErrorCode.RuntimeError, 'open safety check failed.');
|
|
518
|
+
// messageResponse = createResponseMessage(method.responseID, false, { error });
|
|
519
|
+
// requestQueue.resolveRequest(method.responseID, messageResponse);
|
|
520
|
+
// return;
|
|
521
|
+
throw error;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
method.device?.commands?.checkDisposed();
|
|
525
|
+
|
|
526
|
+
try {
|
|
527
|
+
const response: object = await method.run();
|
|
528
|
+
Log.debug('Call API - Inner Method Run: ');
|
|
529
|
+
messageResponse = createResponseMessage(method.responseID, true, response);
|
|
530
|
+
requestQueue.resolveRequest(method.responseID, messageResponse);
|
|
531
|
+
completeMethodRequestContext(method);
|
|
532
|
+
} catch (error) {
|
|
533
|
+
Log.debug(`Call API - Inner Method Run Error`, error);
|
|
534
|
+
messageResponse = createResponseMessage(method.responseID, false, { error });
|
|
535
|
+
requestQueue.resolveRequest(method.responseID, messageResponse);
|
|
536
|
+
completeMethodRequestContext(method, error);
|
|
537
|
+
|
|
538
|
+
// Re-throw errors that need to trigger device release/disconnect in Device._runInner
|
|
539
|
+
if (
|
|
540
|
+
error instanceof HardwareError &&
|
|
541
|
+
ERROR_CODES_REQUIRE_RELEASE.includes(error.errorCode as any)
|
|
542
|
+
) {
|
|
543
|
+
throw error;
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
};
|
|
547
|
+
Log.debug('Call API - Device Run: ', device.mainId);
|
|
548
|
+
|
|
549
|
+
const runOptions: RunOptions = {
|
|
550
|
+
keepSession: method.payload.keepSession,
|
|
551
|
+
...parseInitOptions(method),
|
|
552
|
+
};
|
|
553
|
+
const deviceRun = () => device.run(inner, runOptions);
|
|
554
|
+
task.callPromise = createDeferred<any>(deviceRun);
|
|
555
|
+
|
|
556
|
+
try {
|
|
557
|
+
return await task.callPromise.promise;
|
|
558
|
+
} catch (e) {
|
|
559
|
+
Log.debug('Device Run Error: ', e);
|
|
560
|
+
completeMethodRequestContext(method, e);
|
|
561
|
+
return createResponseMessage(method.responseID, false, { error: e });
|
|
562
|
+
}
|
|
563
|
+
} catch (error) {
|
|
564
|
+
messageResponse = createResponseMessage(method.responseID, false, { error });
|
|
565
|
+
requestQueue.rejectRequest(
|
|
566
|
+
method.responseID,
|
|
567
|
+
ERRORS.TypedError(HardwareErrorCode.CallMethodError, error.message)
|
|
568
|
+
);
|
|
569
|
+
Log.debug('Call API - Run Error: ', error);
|
|
570
|
+
completeMethodRequestContext(method, error);
|
|
571
|
+
} finally {
|
|
572
|
+
const response = messageResponse;
|
|
573
|
+
|
|
574
|
+
if (response) {
|
|
575
|
+
if (method) {
|
|
576
|
+
method.dispose();
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
// remove method from queue
|
|
581
|
+
// const index = method.responseID
|
|
582
|
+
// ? callApiQueue.findIndex(m => m.responseID === method.responseID)
|
|
583
|
+
// : -1;
|
|
584
|
+
// if (index > -1) {
|
|
585
|
+
// callApiQueue.splice(index, 1);
|
|
586
|
+
// Log.debug(
|
|
587
|
+
// 'Remove the finished method from the queue: ',
|
|
588
|
+
// callApiQueue.map(m => m.name)
|
|
589
|
+
// );
|
|
590
|
+
// }
|
|
591
|
+
|
|
592
|
+
requestQueue.releaseTask(method.responseID);
|
|
593
|
+
|
|
594
|
+
closePopup();
|
|
595
|
+
|
|
596
|
+
cleanup();
|
|
597
|
+
|
|
598
|
+
if (device) {
|
|
599
|
+
const stillActive = getActiveRequestsByDeviceInstance(device.instanceId);
|
|
600
|
+
if (stillActive.length > 1) {
|
|
601
|
+
Log.warn(
|
|
602
|
+
`[${method.instanceId}] Removing listeners while ${stillActive.length} requests are active!`,
|
|
603
|
+
{
|
|
604
|
+
deviceInstanceId: device.instanceId,
|
|
605
|
+
activeRequests: stillActive.map(formatRequestContext),
|
|
606
|
+
pinListeners: device.listenerCount(DEVICE.PIN),
|
|
607
|
+
}
|
|
608
|
+
);
|
|
609
|
+
} else {
|
|
610
|
+
removeDeviceListener(device);
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
};
|
|
615
|
+
|
|
616
|
+
async function initDeviceList(method: BaseMethod) {
|
|
617
|
+
const env = DataManager.getSettings('env');
|
|
618
|
+
if (DataManager.isBleConnect(env) && method.connectId) {
|
|
619
|
+
await TransportManager.configure();
|
|
620
|
+
return;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
if (!_deviceList) {
|
|
624
|
+
_deviceList = new DeviceList();
|
|
625
|
+
await TransportManager.configure();
|
|
626
|
+
_deviceList.connector = _connector;
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
await _deviceList.getDeviceLists(method.connectId, parseInitOptions(method));
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
function initDevice(method: BaseMethod) {
|
|
633
|
+
if (!_deviceList) {
|
|
634
|
+
throw ERRORS.TypedError(HardwareErrorCode.DeviceListNotInitialized);
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
let device: Device | typeof undefined;
|
|
638
|
+
const allDevices = _deviceList.allDevices();
|
|
639
|
+
|
|
640
|
+
if (method.payload?.detectBootloaderDevice && allDevices.some(d => d.features?.bootloader_mode)) {
|
|
641
|
+
throw ERRORS.TypedError(HardwareErrorCode.DeviceDetectInBootloaderMode);
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
if (method.connectId) {
|
|
645
|
+
device = _deviceList.getDevice(method.connectId);
|
|
646
|
+
} else if (allDevices.length === 1) {
|
|
647
|
+
[device] = allDevices;
|
|
648
|
+
} else if (allDevices.length > 1) {
|
|
649
|
+
throw ERRORS.TypedError(
|
|
650
|
+
[
|
|
651
|
+
'firmwareUpdateV3',
|
|
652
|
+
'firmwareUpdateV2',
|
|
653
|
+
'checkFirmwareRelease',
|
|
654
|
+
'checkBootloaderRelease',
|
|
655
|
+
'checkBLEFirmwareRelease',
|
|
656
|
+
].includes(method.name)
|
|
657
|
+
? HardwareErrorCode.FirmwareUpdateLimitOneDevice
|
|
658
|
+
: HardwareErrorCode.SelectDevice
|
|
659
|
+
);
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
if (!device) {
|
|
663
|
+
const env = DataManager.getSettings('env');
|
|
664
|
+
// Browser WebUSB needs permission prompt, desktop WebUSB doesn't
|
|
665
|
+
if (DataManager.isBrowserWebUsb(env)) {
|
|
666
|
+
throw ERRORS.TypedError(HardwareErrorCode.WebDeviceNotFoundOrNeedsPermission);
|
|
667
|
+
}
|
|
668
|
+
throw ERRORS.TypedError(HardwareErrorCode.DeviceNotFound);
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
// inject properties
|
|
672
|
+
device.deviceConnector = _connector;
|
|
673
|
+
|
|
674
|
+
return device;
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
function initDeviceForBle(method: BaseMethod) {
|
|
678
|
+
if (!method.connectId && !_deviceList) {
|
|
679
|
+
throw ERRORS.TypedError(HardwareErrorCode.DeviceListNotInitialized);
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
if (!method.connectId) {
|
|
683
|
+
return initDevice(method);
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
let device: Device;
|
|
687
|
+
if (deviceCacheMap.has(method.connectId)) {
|
|
688
|
+
device = deviceCacheMap.get(method.connectId) as Device;
|
|
689
|
+
} else {
|
|
690
|
+
device = Device.fromDescriptor(
|
|
691
|
+
{ id: method.connectId } as OneTokenDeviceInfo,
|
|
692
|
+
method.sdkInstanceId
|
|
693
|
+
);
|
|
694
|
+
deviceCacheMap.set(method.connectId, device);
|
|
695
|
+
}
|
|
696
|
+
device.deviceConnector = _connector;
|
|
697
|
+
return device;
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
/**
|
|
701
|
+
* If the Bluetooth connection times out, retry 6 times
|
|
702
|
+
*/
|
|
703
|
+
let bleTimeoutRetry = 0;
|
|
704
|
+
|
|
705
|
+
async function connectDeviceForBle(method: BaseMethod, device: Device) {
|
|
706
|
+
try {
|
|
707
|
+
await device.acquire();
|
|
708
|
+
if (method.payload?.onlyConnectBleDevice) {
|
|
709
|
+
return;
|
|
710
|
+
}
|
|
711
|
+
await device.initialize(parseInitOptions(method));
|
|
712
|
+
} catch (err) {
|
|
713
|
+
if (err.errorCode === HardwareErrorCode.BleTimeoutError && bleTimeoutRetry <= 5) {
|
|
714
|
+
bleTimeoutRetry += 1;
|
|
715
|
+
Log.debug(`Bletooth connect timeout and will retry, retry count: ${bleTimeoutRetry}`);
|
|
716
|
+
await wait(3000);
|
|
717
|
+
await connectDeviceForBle(method, device);
|
|
718
|
+
} else {
|
|
719
|
+
throw err;
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
type IPollFn<T> = (time?: number) => T;
|
|
725
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
726
|
+
const ensureConnected = async (
|
|
727
|
+
_context: CoreContext,
|
|
728
|
+
method: BaseMethod,
|
|
729
|
+
pollingId: number,
|
|
730
|
+
abortSignal?: AbortSignal
|
|
731
|
+
) => {
|
|
732
|
+
let tryCount = 0;
|
|
733
|
+
const MAX_RETRY_COUNT =
|
|
734
|
+
method.payload && typeof method.payload.retryCount === 'number' ? method.payload.retryCount : 5;
|
|
735
|
+
const POLL_INTERVAL_TIME = (method.payload && method.payload.pollIntervalTime) || 1000;
|
|
736
|
+
const TIME_OUT = (method.payload && method.payload.timeout) || 10000;
|
|
737
|
+
let timer: ReturnType<typeof setTimeout> | null = null;
|
|
738
|
+
Log.debug(
|
|
739
|
+
`EnsureConnected function start, MAX_RETRY_COUNT=${MAX_RETRY_COUNT}, POLL_INTERVAL_TIME=${POLL_INTERVAL_TIME} `
|
|
740
|
+
);
|
|
741
|
+
|
|
742
|
+
const poll: IPollFn<Promise<Device>> = async (time = POLL_INTERVAL_TIME) =>
|
|
743
|
+
// eslint-disable-next-line no-async-promise-executor
|
|
744
|
+
new Promise(async (resolve, reject) => {
|
|
745
|
+
const abort = () => {
|
|
746
|
+
if (abortSignal && abortSignal.aborted) {
|
|
747
|
+
if (timer) {
|
|
748
|
+
clearTimeout(timer);
|
|
749
|
+
}
|
|
750
|
+
reject(ERRORS.TypedError(HardwareErrorCode.CallQueueActionCancelled));
|
|
751
|
+
return true;
|
|
752
|
+
}
|
|
753
|
+
return false;
|
|
754
|
+
};
|
|
755
|
+
|
|
756
|
+
if (abort()) {
|
|
757
|
+
return;
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
if (!pollingState[pollingId]) {
|
|
761
|
+
Log.debug('EnsureConnected function stop, polling id: ', pollingId);
|
|
762
|
+
reject(ERRORS.TypedError(HardwareErrorCode.PollingStop));
|
|
763
|
+
return;
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
// 单次连接确保不超时
|
|
767
|
+
if (timer) {
|
|
768
|
+
clearTimeout(timer);
|
|
769
|
+
}
|
|
770
|
+
timer = setTimeout(() => {
|
|
771
|
+
reject(ERRORS.TypedError(HardwareErrorCode.PollingTimeout));
|
|
772
|
+
}, TIME_OUT);
|
|
773
|
+
|
|
774
|
+
tryCount += 1;
|
|
775
|
+
Log.debug('EnsureConnected function try count: ', tryCount, ' poll interval time: ', time);
|
|
776
|
+
try {
|
|
777
|
+
await initDeviceList(method);
|
|
778
|
+
} catch (error) {
|
|
779
|
+
Log.debug('device list error: ', error);
|
|
780
|
+
if (
|
|
781
|
+
[
|
|
782
|
+
HardwareErrorCode.BridgeNotInstalled,
|
|
783
|
+
HardwareErrorCode.BridgeTimeoutError,
|
|
784
|
+
HardwareErrorCode.BridgeNeedsPermission,
|
|
785
|
+
].includes(error.errorCode)
|
|
786
|
+
) {
|
|
787
|
+
_deviceList = undefined;
|
|
788
|
+
reject(error);
|
|
789
|
+
return;
|
|
790
|
+
}
|
|
791
|
+
if (error.errorCode === HardwareErrorCode.TransportNotConfigured) {
|
|
792
|
+
await TransportManager.configure();
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
if (abort()) {
|
|
797
|
+
return;
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
const env = DataManager.getSettings('env');
|
|
801
|
+
let device: Device;
|
|
802
|
+
try {
|
|
803
|
+
if (DataManager.isBleConnect(env)) {
|
|
804
|
+
device = initDeviceForBle(method);
|
|
805
|
+
} else {
|
|
806
|
+
device = initDevice(method);
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
if (device) {
|
|
810
|
+
if (timer) {
|
|
811
|
+
clearTimeout(timer);
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
/**
|
|
815
|
+
* Bluetooth should call initialize here
|
|
816
|
+
*/
|
|
817
|
+
if (DataManager.isBleConnect(env)) {
|
|
818
|
+
bleTimeoutRetry = 0;
|
|
819
|
+
|
|
820
|
+
if (abort()) {
|
|
821
|
+
return;
|
|
822
|
+
}
|
|
823
|
+
await connectDeviceForBle(method, device);
|
|
824
|
+
}
|
|
825
|
+
resolve(device);
|
|
826
|
+
return;
|
|
827
|
+
}
|
|
828
|
+
} catch (error) {
|
|
829
|
+
Log.debug('device error: ', error);
|
|
830
|
+
if ([HardwareErrorCode.BleCharacteristicNotifyChangeFailure].includes(error.errorCode)) {
|
|
831
|
+
postMessage(createUiMessage(UI_REQUEST.BLUETOOTH_CHARACTERISTIC_NOTIFY_CHANGE_FAILURE));
|
|
832
|
+
}
|
|
833
|
+
if (
|
|
834
|
+
[
|
|
835
|
+
HardwareErrorCode.BlePoweredOff,
|
|
836
|
+
HardwareErrorCode.BleUnsupported,
|
|
837
|
+
HardwareErrorCode.BlePermissionError,
|
|
838
|
+
HardwareErrorCode.BleLocationError,
|
|
839
|
+
HardwareErrorCode.BleLocationServicesDisabled,
|
|
840
|
+
HardwareErrorCode.BleDeviceNotBonded,
|
|
841
|
+
HardwareErrorCode.BleDeviceBondError,
|
|
842
|
+
HardwareErrorCode.BleDeviceBondedCanceled,
|
|
843
|
+
HardwareErrorCode.BleCharacteristicNotifyError,
|
|
844
|
+
HardwareErrorCode.BleTimeoutError,
|
|
845
|
+
HardwareErrorCode.BleWriteCharacteristicError,
|
|
846
|
+
HardwareErrorCode.BleAlreadyConnected,
|
|
847
|
+
HardwareErrorCode.FirmwareUpdateLimitOneDevice,
|
|
848
|
+
HardwareErrorCode.SelectDevice,
|
|
849
|
+
HardwareErrorCode.DeviceDetectInBootloaderMode,
|
|
850
|
+
HardwareErrorCode.BleCharacteristicNotifyChangeFailure,
|
|
851
|
+
HardwareErrorCode.BridgeNeedsPermission,
|
|
852
|
+
].includes(error.errorCode)
|
|
853
|
+
) {
|
|
854
|
+
reject(error);
|
|
855
|
+
return;
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
if (tryCount > MAX_RETRY_COUNT) {
|
|
860
|
+
if (timer) {
|
|
861
|
+
clearTimeout(timer);
|
|
862
|
+
}
|
|
863
|
+
Log.debug('EnsureConnected get to max try count, will return: ', tryCount);
|
|
864
|
+
// Browser WebUSB needs permission prompt, desktop WebUSB doesn't
|
|
865
|
+
// skipWebDevicePrompt can override this behavior for special cases
|
|
866
|
+
if (DataManager.isBrowserWebUsb(env) && !method.payload?.skipWebDevicePrompt) {
|
|
867
|
+
postMessage(createUiMessage(UI_REQUEST.WEB_DEVICE_PROMPT_ACCESS_PERMISSION));
|
|
868
|
+
reject(ERRORS.TypedError(HardwareErrorCode.WebDeviceNotFoundOrNeedsPermission));
|
|
869
|
+
} else {
|
|
870
|
+
reject(ERRORS.TypedError(HardwareErrorCode.DeviceNotFound));
|
|
871
|
+
}
|
|
872
|
+
return;
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
if (abort()) {
|
|
876
|
+
return;
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
// eslint-disable-next-line no-promise-executor-return
|
|
880
|
+
return setTimeout(() => resolve(poll(time * 1.5)), time);
|
|
881
|
+
});
|
|
882
|
+
pollingState[pollingId] = true;
|
|
883
|
+
return poll();
|
|
884
|
+
};
|
|
885
|
+
|
|
886
|
+
export const cancel = (context: CoreContext, connectId?: string) => {
|
|
887
|
+
const { requestQueue, setPrePendingCallPromise } = context;
|
|
888
|
+
if (connectId) {
|
|
889
|
+
try {
|
|
890
|
+
// let device;
|
|
891
|
+
// if (DataManager.isBleConnect(env)) {
|
|
892
|
+
// device = initDeviceForBle({ connectId } as BaseMethod);
|
|
893
|
+
// } else {
|
|
894
|
+
// device = initDevice({ connectId } as BaseMethod);
|
|
895
|
+
// }
|
|
896
|
+
// setPrePendingCallPromise(device?.interruptionFromUser());
|
|
897
|
+
// requestQueue.abortRequestsByConnectId(connectId);
|
|
898
|
+
|
|
899
|
+
// cancel callback tasks
|
|
900
|
+
requestQueue.cancelCallbackTasks(connectId);
|
|
901
|
+
|
|
902
|
+
const requestIds = requestQueue.getRequestTasksId();
|
|
903
|
+
Log.debug(
|
|
904
|
+
`Cancel Api connect requestQueues: length:${requestIds.length} requestIds:${requestIds.join(
|
|
905
|
+
','
|
|
906
|
+
)}`
|
|
907
|
+
);
|
|
908
|
+
const canceledDevices: Device[] = [];
|
|
909
|
+
for (const requestId of requestIds) {
|
|
910
|
+
const task = requestQueue.getTask(requestId);
|
|
911
|
+
Log.debug('Cancel Api connect task: ', task);
|
|
912
|
+
if (task && task.method?.device) {
|
|
913
|
+
if (!canceledDevices.includes(task.method.device)) {
|
|
914
|
+
const { device } = task.method;
|
|
915
|
+
setPrePendingCallPromise(device?.interruptionFromUser());
|
|
916
|
+
canceledDevices.push(device);
|
|
917
|
+
}
|
|
918
|
+
requestQueue.rejectRequest(
|
|
919
|
+
requestId,
|
|
920
|
+
ERRORS.TypedError(HardwareErrorCode.CallQueueActionCancelled)
|
|
921
|
+
);
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
requestQueue.abortRequestsByConnectId(connectId);
|
|
925
|
+
} catch (e) {
|
|
926
|
+
Log.error('Cancel API Error: ', e);
|
|
927
|
+
}
|
|
928
|
+
} else {
|
|
929
|
+
const env = DataManager.getSettings('env');
|
|
930
|
+
if (DataManager.isBleConnect(env)) {
|
|
931
|
+
Log.debug('Cancel Api all _deviceList: ');
|
|
932
|
+
const canceledDevices: Device[] = [];
|
|
933
|
+
for (const requestId of requestQueue.getRequestTasksId()) {
|
|
934
|
+
const task = requestQueue.getTask(requestId);
|
|
935
|
+
Log.debug('Cancel Api connect task: ', task);
|
|
936
|
+
if (task && task.method?.device) {
|
|
937
|
+
if (!canceledDevices.includes(task.method.device)) {
|
|
938
|
+
const { device } = task.method;
|
|
939
|
+
device?.interruptionFromUser();
|
|
940
|
+
canceledDevices.push(device);
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
requestQueue.rejectRequest(
|
|
944
|
+
requestId,
|
|
945
|
+
ERRORS.TypedError(HardwareErrorCode.CallQueueActionCancelled)
|
|
946
|
+
);
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
} else {
|
|
950
|
+
_deviceList?.allDevices().forEach(device => {
|
|
951
|
+
Log.debug('device: ', device, ' device.hasDeviceAcquire: ', device.hasDeviceAcquire());
|
|
952
|
+
if (device.hasDeviceAcquire()) {
|
|
953
|
+
device?.interruptionFromUser();
|
|
954
|
+
}
|
|
955
|
+
});
|
|
956
|
+
|
|
957
|
+
requestQueue.getRequestTasksId().forEach(requestId => {
|
|
958
|
+
requestQueue.rejectRequest(
|
|
959
|
+
requestId,
|
|
960
|
+
ERRORS.TypedError(HardwareErrorCode.CallQueueActionCancelled)
|
|
961
|
+
);
|
|
962
|
+
});
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
cleanup();
|
|
967
|
+
closePopup();
|
|
968
|
+
};
|
|
969
|
+
|
|
970
|
+
const checkPassphraseEnableState = (method: BaseMethod, features?: Features) => {
|
|
971
|
+
if (!method.useDevicePassphraseState) return;
|
|
972
|
+
|
|
973
|
+
if (features?.passphrase_protection === true) {
|
|
974
|
+
const hasNoPassphraseState =
|
|
975
|
+
method.payload.passphraseState == null || method.payload.passphraseState === '';
|
|
976
|
+
const shouldRequirePassphrase =
|
|
977
|
+
!method.payload.useEmptyPassphrase && !method.payload.skipPassphraseCheck;
|
|
978
|
+
|
|
979
|
+
if (hasNoPassphraseState && shouldRequirePassphrase) {
|
|
980
|
+
DevicePool.clearDeviceCache(method.payload.connectId);
|
|
981
|
+
throw ERRORS.TypedError(HardwareErrorCode.DeviceOpenedPassphrase);
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
if (features?.passphrase_protection === false && method.payload.passphraseState) {
|
|
986
|
+
DevicePool.clearDeviceCache(method.payload.connectId);
|
|
987
|
+
throw ERRORS.TypedError(HardwareErrorCode.DeviceNotOpenedPassphrase);
|
|
988
|
+
}
|
|
989
|
+
};
|
|
990
|
+
|
|
991
|
+
const cleanup = () => {
|
|
992
|
+
_uiPromises = [];
|
|
993
|
+
Log.debug('Cleanup...');
|
|
994
|
+
};
|
|
995
|
+
|
|
996
|
+
const removeDeviceListener = (device: Device) => {
|
|
997
|
+
device.removeAllListeners();
|
|
998
|
+
DevicePool.emitter.removeAllListeners(DEVICE.CONNECT);
|
|
999
|
+
// DevicePool.emitter.removeListener(DEVICE.DISCONNECT, onDeviceDisconnectHandler);
|
|
1000
|
+
};
|
|
1001
|
+
|
|
1002
|
+
/**
|
|
1003
|
+
* Force close popup
|
|
1004
|
+
*/
|
|
1005
|
+
const closePopup = () => {
|
|
1006
|
+
postMessage(createUiMessage(UI_REQUEST.CLOSE_UI_WINDOW));
|
|
1007
|
+
};
|
|
1008
|
+
|
|
1009
|
+
const onDeviceConnectHandler = (device: Device) => {
|
|
1010
|
+
const env = DataManager.getSettings('env');
|
|
1011
|
+
const deviceObject = DataManager.isBleConnect(env) ? device : device.toMessageObject();
|
|
1012
|
+
postMessage(createDeviceMessage(DEVICE.CONNECT, { device: deviceObject as KnownDevice }));
|
|
1013
|
+
};
|
|
1014
|
+
|
|
1015
|
+
const onDeviceDisconnectHandler = (device: Device) => {
|
|
1016
|
+
const env = DataManager.getSettings('env');
|
|
1017
|
+
const deviceObject = DataManager.isBleConnect(env) ? device : device.toMessageObject();
|
|
1018
|
+
postMessage(createDeviceMessage(DEVICE.DISCONNECT, { device: deviceObject as KnownDevice }));
|
|
1019
|
+
};
|
|
1020
|
+
|
|
1021
|
+
const onDevicePinHandler = async (...[device, type, callback]: DeviceEvents['pin']) => {
|
|
1022
|
+
Log.log('request Input PIN');
|
|
1023
|
+
// create ui promise
|
|
1024
|
+
const uiPromise = createUiPromise(UI_RESPONSE.RECEIVE_PIN, device);
|
|
1025
|
+
// request pin view
|
|
1026
|
+
postMessage(
|
|
1027
|
+
createUiMessage(UI_REQUEST.REQUEST_PIN, {
|
|
1028
|
+
device: device.toMessageObject() as unknown as KnownDevice,
|
|
1029
|
+
type,
|
|
1030
|
+
})
|
|
1031
|
+
);
|
|
1032
|
+
// wait for pin
|
|
1033
|
+
const uiResp = await uiPromise.promise;
|
|
1034
|
+
// callback.apply(null, [null, pin]);
|
|
1035
|
+
callback(null, uiResp.payload);
|
|
1036
|
+
};
|
|
1037
|
+
|
|
1038
|
+
export const onDeviceButtonHandler = (...[device, request]: [...DeviceEvents['button']]) => {
|
|
1039
|
+
postMessage(createDeviceMessage(DEVICE.BUTTON, { ...request, device: device.toMessageObject() }));
|
|
1040
|
+
|
|
1041
|
+
if (request.code === 'ButtonRequest_PinEntry' || request.code === 'ButtonRequest_AttachPin') {
|
|
1042
|
+
Log.log('request Confirm Input PIN or Attach PIN');
|
|
1043
|
+
postMessage(
|
|
1044
|
+
createUiMessage(UI_REQUEST.REQUEST_PIN, {
|
|
1045
|
+
device: device.toMessageObject() as KnownDevice,
|
|
1046
|
+
type: request.code,
|
|
1047
|
+
})
|
|
1048
|
+
);
|
|
1049
|
+
} else {
|
|
1050
|
+
Log.log('request Confirm Button');
|
|
1051
|
+
postMessage(createUiMessage(UI_REQUEST.REQUEST_BUTTON, { device: device.toMessageObject() }));
|
|
1052
|
+
}
|
|
1053
|
+
};
|
|
1054
|
+
|
|
1055
|
+
const onDeviceFeaturesHandler = (...[_, features]: [...DeviceEvents['features']]) => {
|
|
1056
|
+
postMessage(createDeviceMessage(DEVICE.FEATURES, { ...features }));
|
|
1057
|
+
};
|
|
1058
|
+
|
|
1059
|
+
const onDevicePassphraseHandler = async (
|
|
1060
|
+
...[device, requestPayload, callback]: DeviceEvents['passphrase']
|
|
1061
|
+
) => {
|
|
1062
|
+
Log.debug('onDevicePassphraseHandler');
|
|
1063
|
+
const uiPromise = createUiPromise(UI_RESPONSE.RECEIVE_PASSPHRASE, device);
|
|
1064
|
+
postMessage(
|
|
1065
|
+
createUiMessage(UI_REQUEST.REQUEST_PASSPHRASE, {
|
|
1066
|
+
device: device.toMessageObject() as KnownDevice,
|
|
1067
|
+
passphraseState: device.passphraseState,
|
|
1068
|
+
existsAttachPinUser: requestPayload.existsAttachPinUser,
|
|
1069
|
+
})
|
|
1070
|
+
);
|
|
1071
|
+
// wait for passphrase
|
|
1072
|
+
const uiResp = await uiPromise.promise;
|
|
1073
|
+
const { value, passphraseOnDevice, save, attachPinOnDevice } = uiResp.payload;
|
|
1074
|
+
// send as PassphrasePromptResponse
|
|
1075
|
+
callback({
|
|
1076
|
+
passphrase: value.normalize('NFKD'),
|
|
1077
|
+
passphraseOnDevice,
|
|
1078
|
+
attachPinOnDevice,
|
|
1079
|
+
cache: save,
|
|
1080
|
+
});
|
|
1081
|
+
};
|
|
1082
|
+
|
|
1083
|
+
const onEmptyPassphraseHandler = (...[_, , callback]: DeviceEvents['passphrase']) => {
|
|
1084
|
+
Log.debug('onEmptyPassphraseHandler');
|
|
1085
|
+
// send as PassphrasePromptResponse
|
|
1086
|
+
callback({ passphrase: '' });
|
|
1087
|
+
};
|
|
1088
|
+
|
|
1089
|
+
const onEnterPassphraseOnDeviceHandler = (
|
|
1090
|
+
...[device]: [...DeviceEvents['passphrase_on_device']]
|
|
1091
|
+
) => {
|
|
1092
|
+
postMessage(
|
|
1093
|
+
createUiMessage(UI_REQUEST.REQUEST_PASSPHRASE_ON_DEVICE, {
|
|
1094
|
+
device: device.toMessageObject() as KnownDevice,
|
|
1095
|
+
passphraseState: device.passphraseState,
|
|
1096
|
+
})
|
|
1097
|
+
);
|
|
1098
|
+
};
|
|
1099
|
+
|
|
1100
|
+
const onSelectDeviceInBootloaderForWebDeviceHandler = async (
|
|
1101
|
+
...[device, callback]: [...DeviceEvents['select_device_in_bootloader_for_web_device']]
|
|
1102
|
+
) => {
|
|
1103
|
+
Log.debug('onSelectDeviceInBootloaderForWebDeviceHandler');
|
|
1104
|
+
const uiPromise = createUiPromise(UI_RESPONSE.SELECT_DEVICE_IN_BOOTLOADER_FOR_WEB_DEVICE, device);
|
|
1105
|
+
postMessage(
|
|
1106
|
+
createUiMessage(UI_REQUEST.REQUEST_DEVICE_IN_BOOTLOADER_FOR_WEB_DEVICE, {
|
|
1107
|
+
device: device.toMessageObject() as KnownDevice,
|
|
1108
|
+
})
|
|
1109
|
+
);
|
|
1110
|
+
const uiResp = await uiPromise.promise;
|
|
1111
|
+
callback(null, uiResp.payload.deviceId);
|
|
1112
|
+
};
|
|
1113
|
+
|
|
1114
|
+
const onSelectDeviceForSwitchFirmwareWebDeviceHandler = async (
|
|
1115
|
+
...[device, callback]: [...DeviceEvents['select_device_for_switch_firmware_web_device']]
|
|
1116
|
+
) => {
|
|
1117
|
+
Log.debug('onSelectDeviceForSwitchFirmwareWebDeviceHandler');
|
|
1118
|
+
const uiPromise = createUiPromise(
|
|
1119
|
+
UI_RESPONSE.SELECT_DEVICE_FOR_SWITCH_FIRMWARE_WEB_DEVICE,
|
|
1120
|
+
device
|
|
1121
|
+
);
|
|
1122
|
+
postMessage(
|
|
1123
|
+
createUiMessage(UI_REQUEST.REQUEST_DEVICE_FOR_SWITCH_FIRMWARE_WEB_DEVICE, {
|
|
1124
|
+
device: device.toMessageObject() as KnownDevice,
|
|
1125
|
+
})
|
|
1126
|
+
);
|
|
1127
|
+
const uiResp = await uiPromise.promise;
|
|
1128
|
+
callback(null, uiResp.payload.deviceId);
|
|
1129
|
+
};
|
|
1130
|
+
|
|
1131
|
+
/**
|
|
1132
|
+
* Emit message to listener (parent).
|
|
1133
|
+
* Clear method reference from _callMethods
|
|
1134
|
+
* @param {CoreMessage} message
|
|
1135
|
+
* @returns {void}
|
|
1136
|
+
* @memberof Core
|
|
1137
|
+
*/
|
|
1138
|
+
const postMessage = (message: CoreMessage) => {
|
|
1139
|
+
if (!_core) {
|
|
1140
|
+
return;
|
|
1141
|
+
}
|
|
1142
|
+
_core.emit(CORE_EVENT, message);
|
|
1143
|
+
};
|
|
1144
|
+
|
|
1145
|
+
const createUiPromise = <T extends UiPromiseResponse['type']>(promiseEvent: T, device?: Device) => {
|
|
1146
|
+
const uiPromise: UiPromise<T> = createDeferred(promiseEvent, device);
|
|
1147
|
+
_uiPromises.push(uiPromise as any);
|
|
1148
|
+
|
|
1149
|
+
return uiPromise;
|
|
1150
|
+
};
|
|
1151
|
+
|
|
1152
|
+
const findUiPromise = <T extends UiPromiseResponse['type']>(promiseEvent: T) =>
|
|
1153
|
+
_uiPromises.find(p => p.id === promiseEvent);
|
|
1154
|
+
|
|
1155
|
+
const removeUiPromise = (promise: Deferred<any>) => {
|
|
1156
|
+
_uiPromises = _uiPromises.filter(p => p !== promise);
|
|
1157
|
+
};
|
|
1158
|
+
|
|
1159
|
+
export default class Core extends EventEmitter {
|
|
1160
|
+
private tracingContext: SdkTracingContext;
|
|
1161
|
+
|
|
1162
|
+
public readonly sdkInstanceId: string;
|
|
1163
|
+
|
|
1164
|
+
private requestQueue = new RequestQueue();
|
|
1165
|
+
|
|
1166
|
+
// background task
|
|
1167
|
+
private prePendingCallPromise: Promise<void> | undefined;
|
|
1168
|
+
|
|
1169
|
+
private methodSynchronize = getSynchronize();
|
|
1170
|
+
|
|
1171
|
+
constructor() {
|
|
1172
|
+
super();
|
|
1173
|
+
this.tracingContext = createSdkTracingContext();
|
|
1174
|
+
this.sdkInstanceId = this.tracingContext.sdkInstanceId;
|
|
1175
|
+
Log.debug(`[Core] Created SDK instance: ${this.sdkInstanceId}`);
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
private getCoreContext() {
|
|
1179
|
+
return {
|
|
1180
|
+
sdkInstanceId: this.sdkInstanceId,
|
|
1181
|
+
tracingContext: this.tracingContext,
|
|
1182
|
+
requestQueue: this.requestQueue,
|
|
1183
|
+
methodSynchronize: this.methodSynchronize,
|
|
1184
|
+
getPrePendingCallPromise: () => this.prePendingCallPromise,
|
|
1185
|
+
setPrePendingCallPromise: (promise: Promise<void> | undefined) => {
|
|
1186
|
+
this.prePendingCallPromise = promise;
|
|
1187
|
+
},
|
|
1188
|
+
// callback 任务管理
|
|
1189
|
+
registerCallbackTask: (connectId: string, callbackPromise: Deferred<any>) => {
|
|
1190
|
+
this.requestQueue.registerPendingCallbackTask(connectId, callbackPromise);
|
|
1191
|
+
},
|
|
1192
|
+
waitForCallbackTasks: (connectId: string) =>
|
|
1193
|
+
this.requestQueue.waitForPendingCallbackTasks(connectId),
|
|
1194
|
+
cancelCallbackTasks: (connectId: string) => this.requestQueue.cancelCallbackTasks(connectId),
|
|
1195
|
+
};
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
async handleMessage(message: CoreMessage) {
|
|
1199
|
+
switch (message.type) {
|
|
1200
|
+
case UI_RESPONSE.RECEIVE_PIN:
|
|
1201
|
+
case UI_RESPONSE.RECEIVE_PASSPHRASE:
|
|
1202
|
+
case UI_RESPONSE.SELECT_DEVICE_IN_BOOTLOADER_FOR_WEB_DEVICE:
|
|
1203
|
+
case UI_RESPONSE.SELECT_DEVICE_FOR_SWITCH_FIRMWARE_WEB_DEVICE: {
|
|
1204
|
+
const uiPromise = findUiPromise(message.type);
|
|
1205
|
+
if (uiPromise) {
|
|
1206
|
+
Log.log('receive UI Response: ', message.type);
|
|
1207
|
+
uiPromise.resolve(message);
|
|
1208
|
+
removeUiPromise(uiPromise);
|
|
1209
|
+
}
|
|
1210
|
+
break;
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
case UI_REQUEST.BLUETOOTH_UNSUPPORTED:
|
|
1214
|
+
case UI_REQUEST.BLUETOOTH_POWERED_OFF:
|
|
1215
|
+
case UI_REQUEST.BLUETOOTH_PERMISSION:
|
|
1216
|
+
case UI_REQUEST.BLUETOOTH_CHARACTERISTIC_NOTIFY_CHANGE_FAILURE:
|
|
1217
|
+
case UI_REQUEST.LOCATION_PERMISSION:
|
|
1218
|
+
case UI_REQUEST.LOCATION_SERVICE_PERMISSION: {
|
|
1219
|
+
postMessage(message);
|
|
1220
|
+
break;
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
case IFRAME.CALL: {
|
|
1224
|
+
Log.log('call API: ', message);
|
|
1225
|
+
const response = await callAPI(this.getCoreContext(), message);
|
|
1226
|
+
const { success, payload } = response;
|
|
1227
|
+
Log.log('call API Response: ', response);
|
|
1228
|
+
if (success) {
|
|
1229
|
+
return response;
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1232
|
+
return {
|
|
1233
|
+
...response,
|
|
1234
|
+
payload: {
|
|
1235
|
+
...payload,
|
|
1236
|
+
connectId: message.payload?.connectId ?? '',
|
|
1237
|
+
deviceId: message.payload?.deviceId ?? '',
|
|
1238
|
+
},
|
|
1239
|
+
};
|
|
1240
|
+
}
|
|
1241
|
+
case IFRAME.CANCEL: {
|
|
1242
|
+
Log.log('cancel API: ', message);
|
|
1243
|
+
cancel(this.getCoreContext(), message.payload.connectId);
|
|
1244
|
+
break;
|
|
1245
|
+
}
|
|
1246
|
+
case IFRAME.CALLBACK: {
|
|
1247
|
+
Log.log('callback message: ', message);
|
|
1248
|
+
postMessage(message);
|
|
1249
|
+
break;
|
|
1250
|
+
}
|
|
1251
|
+
default:
|
|
1252
|
+
break;
|
|
1253
|
+
}
|
|
1254
|
+
return Promise.resolve(message);
|
|
1255
|
+
}
|
|
1256
|
+
|
|
1257
|
+
dispose() {
|
|
1258
|
+
_deviceList = undefined;
|
|
1259
|
+
_connector = undefined;
|
|
1260
|
+
Log.debug(`[Core] Disposing SDK instance: ${this.sdkInstanceId}`);
|
|
1261
|
+
cleanupSdkInstance(this.sdkInstanceId);
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1265
|
+
export const initCore = () => {
|
|
1266
|
+
_core = new Core();
|
|
1267
|
+
return _core;
|
|
1268
|
+
};
|
|
1269
|
+
|
|
1270
|
+
export const initConnector = () => {
|
|
1271
|
+
_connector = new DeviceConnector();
|
|
1272
|
+
DevicePool.emitter.on(DEVICE.DISCONNECT, onDeviceDisconnectHandler);
|
|
1273
|
+
return _connector;
|
|
1274
|
+
};
|
|
1275
|
+
|
|
1276
|
+
const initTransport = (Transport: any, plugin?: LowlevelTransportSharedPlugin) => {
|
|
1277
|
+
TransportManager.setTransport(Transport, plugin);
|
|
1278
|
+
};
|
|
1279
|
+
|
|
1280
|
+
export const init = async (
|
|
1281
|
+
settings: ConnectSettings,
|
|
1282
|
+
Transport: any,
|
|
1283
|
+
plugin?: LowlevelTransportSharedPlugin
|
|
1284
|
+
) => {
|
|
1285
|
+
try {
|
|
1286
|
+
try {
|
|
1287
|
+
await DataManager.load(settings);
|
|
1288
|
+
initTransport(Transport, plugin);
|
|
1289
|
+
} catch {
|
|
1290
|
+
Log.error('DataManager.load error');
|
|
1291
|
+
}
|
|
1292
|
+
enableLog(DataManager.getSettings('debug'));
|
|
1293
|
+
if (DataManager.getSettings('env') !== 'react-native') {
|
|
1294
|
+
setLoggerPostMessage(postMessage);
|
|
1295
|
+
}
|
|
1296
|
+
initCore();
|
|
1297
|
+
initConnector();
|
|
1298
|
+
|
|
1299
|
+
return _core;
|
|
1300
|
+
} catch (error) {
|
|
1301
|
+
Log.error('core init', error);
|
|
1302
|
+
}
|
|
1303
|
+
};
|
|
1304
|
+
|
|
1305
|
+
export const switchTransport = ({
|
|
1306
|
+
env,
|
|
1307
|
+
Transport,
|
|
1308
|
+
plugin,
|
|
1309
|
+
}: {
|
|
1310
|
+
env: ConnectSettings['env'];
|
|
1311
|
+
Transport: any;
|
|
1312
|
+
plugin?: LowlevelTransportSharedPlugin;
|
|
1313
|
+
}) => {
|
|
1314
|
+
DataManager.updateEnv(env);
|
|
1315
|
+
TransportManager.setTransport(Transport, plugin);
|
|
1316
|
+
_deviceList = undefined;
|
|
1317
|
+
DevicePool.resetState();
|
|
1318
|
+
_connector = undefined;
|
|
1319
|
+
initConnector();
|
|
1320
|
+
};
|