From 51ad70c534f75f2e56f10e2f6d0f8761758a81f9 Mon Sep 17 00:00:00 2001 From: Leon Date: Tue, 11 Apr 2023 10:43:19 +0800 Subject: [PATCH] feat: Improve bulk copy address for hardware wallet (#2814) * feat: support batchGetAddress for hardware keyring * refactor: use batch getaddress for set range copy * feat: fetch hardware wallet accounts * refactor: use hooks to clean code * feat: use redux to handler event * refactor: useFetchWalletAddress hooks * chore: optimize loop * chore: upgrade sdk * fix: cancel progress * chore: revert pod file --- package.json | 10 +- .../src/vaults/impl/ada/KeyringHardware.ts | 36 ++ .../src/vaults/impl/algo/KeyringHardware.ts | 24 + .../src/vaults/impl/apt/KeyringHardware.ts | 23 + .../src/vaults/impl/cfx/KeyringHardware.ts | 25 + .../src/vaults/impl/cosmos/KeyringHardware.ts | 32 ++ .../src/vaults/impl/dot/KeyringHardware.ts | 28 + .../src/vaults/impl/evm/KeyringHardware.ts | 25 + .../src/vaults/impl/fil/KeyringHardware.ts | 25 + .../src/vaults/impl/near/KeyringHardware.ts | 23 + .../src/vaults/impl/sol/KeyringHardware.ts | 23 + .../src/vaults/impl/stc/KeyringHardware.ts | 23 + .../src/vaults/impl/sui/KeyringHardware.ts | 24 + .../src/vaults/impl/tron/KeyringHardware.ts | 23 + .../src/vaults/impl/xrp/KeyringHardware.ts | 23 + .../engine/src/vaults/keyring/KeyringBase.ts | 4 + .../src/vaults/keyring/KeyringHardwareBase.ts | 5 +- .../src/vaults/keyring/KeyringHdBase.ts | 4 + .../src/vaults/keyring/KeyringImportedBase.ts | 4 + .../src/vaults/keyring/KeyringSoftwareBase.ts | 4 + .../src/vaults/keyring/KeyringWatchingBase.ts | 4 + .../utils/btcForkChain/KeyringHardware.ts | 24 + .../src/services/ServiceDerivationPath.ts | 73 +++ .../kit-bg/src/services/ServiceHardware.ts | 5 + packages/kit/src/store/reducers/hardware.ts | 17 + .../BulkCopyAddress/FetchAddressModal.tsx | 483 +++--------------- .../useFetchSetRangeAddress.ts | 269 ++++++++++ .../BulkCopyAddress/useFetchWalletAddress.ts | 387 ++++++++++++++ packages/shared/src/config/appConfig.ts | 2 +- yarn.lock | 104 ++-- 30 files changed, 1280 insertions(+), 476 deletions(-) create mode 100644 packages/kit/src/views/Account/BulkCopyAddress/useFetchSetRangeAddress.ts create mode 100644 packages/kit/src/views/Account/BulkCopyAddress/useFetchWalletAddress.ts diff --git a/package.json b/package.json index 08160b7b6e9..fcd1314dbbe 100644 --- a/package.json +++ b/package.json @@ -62,11 +62,11 @@ "@onekeyfe/cross-inpage-provider-injected": "1.1.24", "@onekeyfe/cross-inpage-provider-types": "1.1.24", "@onekeyfe/extension-bridge-hosted": "1.1.24", - "@onekeyfe/hd-ble-sdk": "0.2.43", - "@onekeyfe/hd-core": "0.2.43", - "@onekeyfe/hd-shared": "0.2.43", - "@onekeyfe/hd-transport": "0.2.43", - "@onekeyfe/hd-web-sdk": "0.2.43", + "@onekeyfe/hd-ble-sdk": "0.2.44", + "@onekeyfe/hd-core": "0.2.44", + "@onekeyfe/hd-shared": "0.2.44", + "@onekeyfe/hd-transport": "0.2.44", + "@onekeyfe/hd-web-sdk": "0.2.44", "@onekeyfe/network-list": "1.6.54", "@onekeyfe/onekey-cross-webview": "1.1.24", "@starcoin/starcoin": "2.1.5", diff --git a/packages/engine/src/vaults/impl/ada/KeyringHardware.ts b/packages/engine/src/vaults/impl/ada/KeyringHardware.ts index 851834b170b..06fcb9913f9 100644 --- a/packages/engine/src/vaults/impl/ada/KeyringHardware.ts +++ b/packages/engine/src/vaults/impl/ada/KeyringHardware.ts @@ -173,6 +173,42 @@ export class KeyringHardware extends KeyringHardwareBase { throw convertDeviceError(response.payload); } + override async batchGetAddress( + params: IHardwareGetAddressParams[], + ): Promise<{ path: string; address: string }[]> { + const HardwareSDK = await this.getHardwareSDKInstance(); + const { connectId, deviceId } = await this.getHardwareInfo(); + const passphraseState = await this.getWalletPassphraseState(); + const { derivationType, addressType, networkId, protocolMagic } = + await getCardanoConstant(); + const response = await HardwareSDK.cardanoGetAddress(connectId, deviceId, { + ...passphraseState, + bundle: params.map(({ path, showOnOneKey }) => { + const stakingPath = `${path.split('/').slice(0, 4).join('/')}/2/0`; + return { + addressParameters: { + addressType, + path, + stakingPath, + }, + networkId, + protocolMagic, + derivationType, + isCheck: true, + showOnOneKey: !!showOnOneKey, + }; + }), + }); + + if (!response.success) { + throw convertDeviceError(response.payload); + } + return response.payload.map((item) => ({ + path: item.serializedPath, + address: item.address, + })); + } + override async signTransaction(unsignedTx: UnsignedTx): Promise { const { PROTO } = await CoreSDKLoader(); const HardwareSDK = await this.getHardwareSDKInstance(); diff --git a/packages/engine/src/vaults/impl/algo/KeyringHardware.ts b/packages/engine/src/vaults/impl/algo/KeyringHardware.ts index e31a7dd085b..e61b097636f 100644 --- a/packages/engine/src/vaults/impl/algo/KeyringHardware.ts +++ b/packages/engine/src/vaults/impl/algo/KeyringHardware.ts @@ -14,6 +14,7 @@ import sdk from './sdkAlgo'; import type { DBSimpleAccount } from '../../../types/account'; import type { IGetAddressParams, + IHardwareGetAddressParams, IPrepareHardwareAccountsParams, } from '../../types'; import type { ISdkAlgoEncodedTransaction } from './sdkAlgo'; @@ -129,4 +130,27 @@ export class KeyringHardware extends KeyringHardwareBase { } throw convertDeviceError(response.payload); } + + override async batchGetAddress( + params: IHardwareGetAddressParams[], + ): Promise<{ path: string; address: string }[]> { + const HardwareSDK = await this.getHardwareSDKInstance(); + const { connectId, deviceId } = await this.getHardwareInfo(); + const passphraseState = await this.getWalletPassphraseState(); + const response = await HardwareSDK.algoGetAddress(connectId, deviceId, { + ...passphraseState, + bundle: params.map(({ path, showOnOneKey }) => ({ + path, + showOnOneKey: !!showOnOneKey, + })), + }); + + if (!response.success) { + throw convertDeviceError(response.payload); + } + return response.payload.map((item) => ({ + path: item.path ?? '', + address: item.address ?? '', + })); + } } diff --git a/packages/engine/src/vaults/impl/apt/KeyringHardware.ts b/packages/engine/src/vaults/impl/apt/KeyringHardware.ts index 33bd339cd07..845cc07ef0c 100644 --- a/packages/engine/src/vaults/impl/apt/KeyringHardware.ts +++ b/packages/engine/src/vaults/impl/apt/KeyringHardware.ts @@ -131,6 +131,29 @@ export class KeyringHardware extends KeyringHardwareBase { throw convertDeviceError(response.payload); } + override async batchGetAddress( + params: IHardwareGetAddressParams[], + ): Promise<{ path: string; address: string }[]> { + const HardwareSDK = await this.getHardwareSDKInstance(); + const { connectId, deviceId } = await this.getHardwareInfo(); + const passphraseState = await this.getWalletPassphraseState(); + const response = await HardwareSDK.aptosGetAddress(connectId, deviceId, { + ...passphraseState, + bundle: params.map(({ path, showOnOneKey }) => ({ + path, + showOnOneKey: !!showOnOneKey, + })), + }); + + if (!response.success) { + throw convertDeviceError(response.payload); + } + return response.payload.map((item) => ({ + path: item.path ?? '', + address: item.address ?? '', + })); + } + async signTransaction( unsignedTx: UnsignedTx, options: ISignCredentialOptions, diff --git a/packages/engine/src/vaults/impl/cfx/KeyringHardware.ts b/packages/engine/src/vaults/impl/cfx/KeyringHardware.ts index ce0ab8cf266..3979227b054 100644 --- a/packages/engine/src/vaults/impl/cfx/KeyringHardware.ts +++ b/packages/engine/src/vaults/impl/cfx/KeyringHardware.ts @@ -168,6 +168,31 @@ export class KeyringHardware extends KeyringHardwareBase { throw convertDeviceError(response.payload); } + override async batchGetAddress( + params: IGetAddressParams[], + ): Promise<{ path: string; address: string }[]> { + const HardwareSDK = await this.getHardwareSDKInstance(); + const { connectId, deviceId } = await this.getHardwareInfo(); + const passphraseState = await this.getWalletPassphraseState(); + const chainId = new BigNumber(await this.getNetworkChainId()).toNumber(); + const response = await HardwareSDK.aptosGetAddress(connectId, deviceId, { + ...passphraseState, + bundle: params.map(({ path, showOnOneKey }) => ({ + path, + showOnOneKey: !!showOnOneKey, + chainId, + })), + }); + + if (!response.success) { + throw convertDeviceError(response.payload); + } + return response.payload.map((item) => ({ + path: item.path ?? '', + address: item.address ?? '', + })); + } + async handleSignMessage(message: IUnsignedMessageCfx) { const HardwareSDK = await this.getHardwareSDKInstance(); const path = await this.getAccountPath(); diff --git a/packages/engine/src/vaults/impl/cosmos/KeyringHardware.ts b/packages/engine/src/vaults/impl/cosmos/KeyringHardware.ts index 63190159552..6c568ba0ffd 100644 --- a/packages/engine/src/vaults/impl/cosmos/KeyringHardware.ts +++ b/packages/engine/src/vaults/impl/cosmos/KeyringHardware.ts @@ -144,6 +144,38 @@ export class KeyringHardware extends KeyringHardwareBase { throw convertDeviceError(response.payload); } + override async batchGetAddress( + params: IHardwareGetAddressParams[], + ): Promise<{ path: string; address: string }[]> { + const HardwareSDK = await this.getHardwareSDKInstance(); + const { connectId, deviceId } = await this.getHardwareInfo(); + const passphraseState = await this.getWalletPassphraseState(); + const chainInfo = await this.getChainInfo(); + const curve = chainInfo?.implOptions?.curve ?? 'secp256k1'; + const addressPrefix = chainInfo?.implOptions?.addressPrefix; + + if (curve === 'ed25519') { + throw new HardwareError('ed25519 curve is not supported'); + } + + const response = await HardwareSDK.cosmosGetAddress(connectId, deviceId, { + ...passphraseState, + bundle: params.map(({ path, showOnOneKey }) => ({ + path, + hrp: addressPrefix, + showOnOneKey: !!showOnOneKey, + })), + }); + + if (!response.success) { + throw convertDeviceError(response.payload); + } + return response.payload.map((item) => ({ + path: item.path ?? '', + address: item.address ?? '', + })); + } + async signTransaction(unsignedTx: UnsignedTx): Promise { debugLogger.common.info('signTransaction', unsignedTx); const dbAccount = await this.getDbAccount(); diff --git a/packages/engine/src/vaults/impl/dot/KeyringHardware.ts b/packages/engine/src/vaults/impl/dot/KeyringHardware.ts index 5f41faae10d..a2d140525e2 100644 --- a/packages/engine/src/vaults/impl/dot/KeyringHardware.ts +++ b/packages/engine/src/vaults/impl/dot/KeyringHardware.ts @@ -128,6 +128,34 @@ export class KeyringHardware extends KeyringHardwareBase { throw convertDeviceError(response.payload); } + override async batchGetAddress( + params: IHardwareGetAddressParams[], + ): Promise<{ path: string; address: string }[]> { + const HardwareSDK = await this.getHardwareSDKInstance(); + const { connectId, deviceId } = await this.getHardwareInfo(); + const chainInfoImpl = await this.getChainInfoImplOptions(); + const chainId = await this.getNetworkChainId(); + const passphraseState = await this.getWalletPassphraseState(); + + const response = await HardwareSDK.polkadotGetAddress(connectId, deviceId, { + ...passphraseState, + bundle: params.map(({ path, showOnOneKey }) => ({ + path, + showOnOneKey: !!showOnOneKey, + prefix: chainInfoImpl.addressPrefix, + network: chainId, + })), + }); + + if (!response.success) { + throw convertDeviceError(response.payload); + } + return response.payload.map((item) => ({ + path: item.path ?? '', + address: item.address ?? '', + })); + } + async signTransaction( unsignedTx: UnsignedTx, // eslint-disable-next-line @typescript-eslint/no-unused-vars diff --git a/packages/engine/src/vaults/impl/evm/KeyringHardware.ts b/packages/engine/src/vaults/impl/evm/KeyringHardware.ts index bd34ebe1701..89f4ca601d3 100644 --- a/packages/engine/src/vaults/impl/evm/KeyringHardware.ts +++ b/packages/engine/src/vaults/impl/evm/KeyringHardware.ts @@ -209,4 +209,29 @@ export class KeyringHardware extends KeyringHardwareBase { return address; } + + override async batchGetAddress( + params: IGetAddressParams[], + ): Promise<{ path: string; address: string }[]> { + const HardwareSDK = await this.getHardwareSDKInstance(); + const chainId = await this.getNetworkChainId(); + const { connectId, deviceId } = await this.getHardwareInfo(); + const passphraseState = await this.getWalletPassphraseState(); + const response = await HardwareSDK.evmGetAddress(connectId, deviceId, { + ...passphraseState, + bundle: params.map(({ path, showOnOneKey }) => ({ + path, + showOnOneKey: !!showOnOneKey, + chainId: Number(chainId), + })), + }); + + if (!response.success) { + throw convertDeviceError(response.payload); + } + return response.payload.map((item) => ({ + path: item.path ?? '', + address: item.address ?? '', + })); + } } diff --git a/packages/engine/src/vaults/impl/fil/KeyringHardware.ts b/packages/engine/src/vaults/impl/fil/KeyringHardware.ts index a2549359c2b..86946552966 100644 --- a/packages/engine/src/vaults/impl/fil/KeyringHardware.ts +++ b/packages/engine/src/vaults/impl/fil/KeyringHardware.ts @@ -98,6 +98,31 @@ export class KeyringHardware extends KeyringHardwareBase { throw convertDeviceError(response.payload); } + override async batchGetAddress( + params: IHardwareGetAddressParams[], + ): Promise<{ path: string; address: string }[]> { + const network = await this.getNetwork(); + const HardwareSDK = await this.getHardwareSDKInstance(); + const { connectId, deviceId } = await this.getHardwareInfo(); + const passphraseState = await this.getWalletPassphraseState(); + const response = await HardwareSDK.filecoinGetAddress(connectId, deviceId, { + ...passphraseState, + bundle: params.map(({ path, showOnOneKey }) => ({ + path, + showOnOneKey: !!showOnOneKey, + isTestnet: network.isTestnet, + })), + }); + + if (!response.success) { + throw convertDeviceError(response.payload); + } + return response.payload.map((item) => ({ + path: item.path ?? '', + address: item.address ?? '', + })); + } + async signTransaction(unsignedTx: IUnsignedTxPro): Promise { const HardwareSDK = await this.getHardwareSDKInstance(); const network = await this.getNetwork(); diff --git a/packages/engine/src/vaults/impl/near/KeyringHardware.ts b/packages/engine/src/vaults/impl/near/KeyringHardware.ts index 051a9c6d675..19b14fc4210 100644 --- a/packages/engine/src/vaults/impl/near/KeyringHardware.ts +++ b/packages/engine/src/vaults/impl/near/KeyringHardware.ts @@ -140,4 +140,27 @@ export class KeyringHardware extends KeyringHardwareBase { } throw convertDeviceError(response.payload); } + + override async batchGetAddress( + params: IGetAddressParams[], + ): Promise<{ path: string; address: string }[]> { + const HardwareSDK = await this.getHardwareSDKInstance(); + const { connectId, deviceId } = await this.getHardwareInfo(); + const passphraseState = await this.getWalletPassphraseState(); + const response = await HardwareSDK.nearGetAddress(connectId, deviceId, { + ...passphraseState, + bundle: params.map(({ path, showOnOneKey }) => ({ + path, + showOnOneKey: !!showOnOneKey, + })), + }); + + if (!response.success) { + throw convertDeviceError(response.payload); + } + return response.payload.map((item) => ({ + path: item.path ?? '', + address: item.address ?? '', + })); + } } diff --git a/packages/engine/src/vaults/impl/sol/KeyringHardware.ts b/packages/engine/src/vaults/impl/sol/KeyringHardware.ts index 4a61d9a6ca5..d22f93efb30 100644 --- a/packages/engine/src/vaults/impl/sol/KeyringHardware.ts +++ b/packages/engine/src/vaults/impl/sol/KeyringHardware.ts @@ -126,4 +126,27 @@ export class KeyringHardware extends KeyringHardwareBase { } throw convertDeviceError(response.payload); } + + override async batchGetAddress( + params: IGetAddressParams[], + ): Promise<{ path: string; address: string }[]> { + const HardwareSDK = await this.getHardwareSDKInstance(); + const { connectId, deviceId } = await this.getHardwareInfo(); + const passphraseState = await this.getWalletPassphraseState(); + const response = await HardwareSDK.solGetAddress(connectId, deviceId, { + ...passphraseState, + bundle: params.map(({ path, showOnOneKey }) => ({ + path, + showOnOneKey: !!showOnOneKey, + })), + }); + + if (!response.success) { + throw convertDeviceError(response.payload); + } + return response.payload.map((item) => ({ + path: item.path ?? '', + address: item.address ?? '', + })); + } } diff --git a/packages/engine/src/vaults/impl/stc/KeyringHardware.ts b/packages/engine/src/vaults/impl/stc/KeyringHardware.ts index f56b14ba162..36ef0d30463 100644 --- a/packages/engine/src/vaults/impl/stc/KeyringHardware.ts +++ b/packages/engine/src/vaults/impl/stc/KeyringHardware.ts @@ -215,4 +215,27 @@ export class KeyringHardware extends KeyringHardwareBase { } throw convertDeviceError(response.payload); } + + override async batchGetAddress( + params: IGetAddressParams[], + ): Promise<{ path: string; address: string }[]> { + const HardwareSDK = await this.getHardwareSDKInstance(); + const { connectId, deviceId } = await this.getHardwareInfo(); + const passphraseState = await this.getWalletPassphraseState(); + const response = await HardwareSDK.starcoinGetAddress(connectId, deviceId, { + ...passphraseState, + bundle: params.map(({ path, showOnOneKey }) => ({ + path, + showOnOneKey: !!showOnOneKey, + })), + }); + + if (!response.success) { + throw convertDeviceError(response.payload); + } + return response.payload.map((item) => ({ + path: item.path ?? '', + address: item.address ?? '', + })); + } } diff --git a/packages/engine/src/vaults/impl/sui/KeyringHardware.ts b/packages/engine/src/vaults/impl/sui/KeyringHardware.ts index a16eea0410b..cd82d3021c8 100644 --- a/packages/engine/src/vaults/impl/sui/KeyringHardware.ts +++ b/packages/engine/src/vaults/impl/sui/KeyringHardware.ts @@ -136,6 +136,30 @@ export class KeyringHardware extends KeyringHardwareBase { throw convertDeviceError(response.payload); } + override async batchGetAddress( + params: IHardwareGetAddressParams[], + ): Promise<{ path: string; address: string }[]> { + const HardwareSDK = await this.getHardwareSDKInstance(); + const { connectId, deviceId } = await this.getHardwareInfo(); + const passphraseState = await this.getWalletPassphraseState(); + // @ts-expect-error + const response = await HardwareSDK.suiGetAddress(connectId, deviceId, { + ...passphraseState, + bundle: params.map(({ path, showOnOneKey }) => ({ + path, + showOnOneKey: !!showOnOneKey, + })), + }); + + if (!response.success) { + throw convertDeviceError(response.payload); + } + return response.payload.map((item) => ({ + path: item.path ?? '', + address: item.address ?? '', + })); + } + async signTransaction( unsignedTx: UnsignedTx, options: ISignCredentialOptions, diff --git a/packages/engine/src/vaults/impl/tron/KeyringHardware.ts b/packages/engine/src/vaults/impl/tron/KeyringHardware.ts index d7081117d3e..4bee8e87156 100644 --- a/packages/engine/src/vaults/impl/tron/KeyringHardware.ts +++ b/packages/engine/src/vaults/impl/tron/KeyringHardware.ts @@ -164,4 +164,27 @@ export class KeyringHardware extends KeyringHardwareBase { } throw convertDeviceError(response.payload); } + + override async batchGetAddress( + params: IGetAddressParams[], + ): Promise<{ path: string; address: string }[]> { + const HardwareSDK = await this.getHardwareSDKInstance(); + const { connectId, deviceId } = await this.getHardwareInfo(); + const passphraseState = await this.getWalletPassphraseState(); + const response = await HardwareSDK.tronGetAddress(connectId, deviceId, { + ...passphraseState, + bundle: params.map(({ path, showOnOneKey }) => ({ + path, + showOnOneKey: !!showOnOneKey, + })), + }); + + if (!response.success) { + throw convertDeviceError(response.payload); + } + return response.payload.map((item) => ({ + path: item.path ?? '', + address: item.address ?? '', + })); + } } diff --git a/packages/engine/src/vaults/impl/xrp/KeyringHardware.ts b/packages/engine/src/vaults/impl/xrp/KeyringHardware.ts index 06a002db72f..fe198f64227 100644 --- a/packages/engine/src/vaults/impl/xrp/KeyringHardware.ts +++ b/packages/engine/src/vaults/impl/xrp/KeyringHardware.ts @@ -82,6 +82,29 @@ export class KeyringHardware extends KeyringHardwareBase { throw convertDeviceError(response.payload); } + override async batchGetAddress( + params: IHardwareGetAddressParams[], + ): Promise<{ path: string; address: string }[]> { + const HardwareSDK = await this.getHardwareSDKInstance(); + const { connectId, deviceId } = await this.getHardwareInfo(); + const passphraseState = await this.getWalletPassphraseState(); + const response = await HardwareSDK.xrpGetAddress(connectId, deviceId, { + ...passphraseState, + bundle: params.map(({ path, showOnOneKey }) => ({ + path, + showOnOneKey: !!showOnOneKey, + })), + }); + + if (!response.success) { + throw convertDeviceError(response.payload); + } + return response.payload.map((item) => ({ + path: item.path ?? '', + address: item.address ?? '', + })); + } + override async signTransaction(unsignedTx: UnsignedTx): Promise { debugLogger.common.info('signTransaction', unsignedTx); const { payload } = unsignedTx; diff --git a/packages/engine/src/vaults/keyring/KeyringBase.ts b/packages/engine/src/vaults/keyring/KeyringBase.ts index 2f1c8346b22..406e07447ec 100644 --- a/packages/engine/src/vaults/keyring/KeyringBase.ts +++ b/packages/engine/src/vaults/keyring/KeyringBase.ts @@ -43,6 +43,10 @@ export abstract class KeyringBase extends VaultContext { abstract getAddress(params: IGetAddressParams): Promise; + abstract batchGetAddress( + params: IGetAddressParams[], + ): Promise<{ path: string; address: string }[]>; + override async addressFromBase(account: DBAccount) { return this.vault.addressFromBase(account); } diff --git a/packages/engine/src/vaults/keyring/KeyringHardwareBase.ts b/packages/engine/src/vaults/keyring/KeyringHardwareBase.ts index 9c33c7f3e17..b020561703e 100644 --- a/packages/engine/src/vaults/keyring/KeyringHardwareBase.ts +++ b/packages/engine/src/vaults/keyring/KeyringHardwareBase.ts @@ -5,7 +5,10 @@ import { isPassphraseWallet } from '@onekeyhq/shared/src/engine/engineUtils'; import { KeyringBase } from './KeyringBase'; import type { DBAccount } from '../../types/account'; -import type { IPrepareAccountByAddressIndexParams } from '../types'; +import type { + IHardwareGetAddressParams, + IPrepareAccountByAddressIndexParams, +} from '../types'; export type WalletPassphraseState = { passphraseState?: string; diff --git a/packages/engine/src/vaults/keyring/KeyringHdBase.ts b/packages/engine/src/vaults/keyring/KeyringHdBase.ts index e553df3140c..f8eed0ac6e7 100644 --- a/packages/engine/src/vaults/keyring/KeyringHdBase.ts +++ b/packages/engine/src/vaults/keyring/KeyringHdBase.ts @@ -47,6 +47,10 @@ export abstract class KeyringHdBase extends KeyringSoftwareBase { throw new Error('Method not implemented.'); } + override batchGetAddress(): Promise<{ path: string; address: string }[]> { + throw new Error('Method not implemented.'); + } + override prepareAccountByAddressIndex( // eslint-disable-next-line @typescript-eslint/no-unused-vars params: IPrepareAccountByAddressIndexParams, diff --git a/packages/engine/src/vaults/keyring/KeyringImportedBase.ts b/packages/engine/src/vaults/keyring/KeyringImportedBase.ts index 41647c2cf34..be7f1442609 100644 --- a/packages/engine/src/vaults/keyring/KeyringImportedBase.ts +++ b/packages/engine/src/vaults/keyring/KeyringImportedBase.ts @@ -31,6 +31,10 @@ export abstract class KeyringImportedBase extends KeyringSoftwareBase { throw new Error('Method not implemented.'); } + override batchGetAddress(): Promise<{ path: string; address: string }[]> { + throw new Error('Method not implemented.'); + } + override prepareAccountByAddressIndex(): Promise<[]> { throw new Error('Method not implemented.'); } diff --git a/packages/engine/src/vaults/keyring/KeyringSoftwareBase.ts b/packages/engine/src/vaults/keyring/KeyringSoftwareBase.ts index 93c5eff6655..ccc8172e413 100644 --- a/packages/engine/src/vaults/keyring/KeyringSoftwareBase.ts +++ b/packages/engine/src/vaults/keyring/KeyringSoftwareBase.ts @@ -81,6 +81,10 @@ export abstract class KeyringSoftwareBase extends KeyringBase { throw new Error('Method not implemented.'); } + override batchGetAddress(): Promise<{ path: string; address: string }[]> { + throw new Error('Method not implemented.'); + } + override prepareAccountByAddressIndex( // eslint-disable-next-line @typescript-eslint/no-unused-vars params: IPrepareAccountByAddressIndexParams, diff --git a/packages/engine/src/vaults/keyring/KeyringWatchingBase.ts b/packages/engine/src/vaults/keyring/KeyringWatchingBase.ts index fe6f2aa7468..3aa90cc438a 100644 --- a/packages/engine/src/vaults/keyring/KeyringWatchingBase.ts +++ b/packages/engine/src/vaults/keyring/KeyringWatchingBase.ts @@ -37,6 +37,10 @@ export abstract class KeyringWatchingBase extends KeyringBase { throw new Error('Method not implemented.'); } + override batchGetAddress(): Promise<{ path: string; address: string }[]> { + throw new Error('Method not implemented.'); + } + override prepareAccountByAddressIndex(): Promise<[]> { throw new Error('Method not implemented.'); } diff --git a/packages/engine/src/vaults/utils/btcForkChain/KeyringHardware.ts b/packages/engine/src/vaults/utils/btcForkChain/KeyringHardware.ts index 1688d8beeb4..402c5554f80 100644 --- a/packages/engine/src/vaults/utils/btcForkChain/KeyringHardware.ts +++ b/packages/engine/src/vaults/utils/btcForkChain/KeyringHardware.ts @@ -362,6 +362,30 @@ export class KeyringHardware extends KeyringHardwareBase { throw convertDeviceError(response.payload); } + override async batchGetAddress( + params: IGetAddressParams[], + ): Promise<{ path: string; address: string }[]> { + const coinName = (this.vault as unknown as BTCForkVault).getCoinName(); + const { connectId, deviceId } = await this.getHardwareInfo(); + const passphraseState = await this.getWalletPassphraseState(); + const response = await HardwareSDK.btcGetAddress(connectId, deviceId, { + ...passphraseState, + bundle: params.map(({ path, showOnOneKey }) => ({ + path, + showOnOneKey: !!showOnOneKey, + coin: coinName.toLowerCase(), + })), + }); + + if (!response.success) { + throw convertDeviceError(response.payload); + } + return response.payload.map((item) => ({ + path: item.path ?? '', + address: item.address ?? '', + })); + } + signMessage(): Promise { throw new NotImplemented(); } diff --git a/packages/kit-bg/src/services/ServiceDerivationPath.ts b/packages/kit-bg/src/services/ServiceDerivationPath.ts index 7efaa8341fa..b8b6378994d 100644 --- a/packages/kit-bg/src/services/ServiceDerivationPath.ts +++ b/packages/kit-bg/src/services/ServiceDerivationPath.ts @@ -10,6 +10,7 @@ import type { IAccount } from '@onekeyhq/engine/src/types'; import type { Account, DBUTXOAccount, + ImportableHDAccount, } from '@onekeyhq/engine/src/types/account'; import type VaultBtcFork from '@onekeyhq/engine/src/vaults/utils/btcForkChain/VaultBtcFork'; import { @@ -216,6 +217,78 @@ export default class ServiceDerivationPath extends ServiceBase { return vault.getAllUsedAddress(); } + @backgroundMethod() + async batchGetHWAddress({ + networkId, + walletId, + indexes, + confirmOnDevice, + template, + fullPaths, + }: { + networkId: string; + walletId: string; + indexes: number[]; + confirmOnDevice: boolean; + template: string; + fullPaths?: string[]; + }) { + const vault = await this.backgroundApi.engine.getWalletOnlyVault( + networkId, + walletId, + ); + const device = await this.backgroundApi.engine.getHWDeviceByWalletId( + walletId, + ); + if (!device) { + throw new OneKeyInternalError(`Device not found.`); + } + const bundle = fullPaths + ? fullPaths.map((path) => ({ path, showOnOneKey: confirmOnDevice })) + : indexes.map((index) => ({ + path: template.replace(INDEX_PLACEHOLDER, index.toString()), + showOnOneKey: confirmOnDevice, + })); + const response = await vault.keyring.batchGetAddress(bundle); + return Promise.all( + response.map(async (item, idx) => { + const importableAccount = + await this.convertPlainAddressItemToImportableHDAccount({ + networkId, + ...item, + }); + return { + ...importableAccount, + ...item, + index: indexes?.[idx], + }; + }), + ); + } + + @backgroundMethod() + async convertPlainAddressItemToImportableHDAccount({ + networkId, + address, + path, + }: { + networkId: string; + address: string; + path: string; + }): Promise { + const displayAddress = await this.backgroundApi.engine.getDisplayAddress( + networkId, + address, + ); + return { + displayAddress, + path, + index: -1, + defaultName: '', + mainBalance: '0', + }; + } + @backgroundMethod() async createAccountByCustomAddressIndex({ networkId, diff --git a/packages/kit-bg/src/services/ServiceHardware.ts b/packages/kit-bg/src/services/ServiceHardware.ts index 7afb41af61f..b3416877d43 100644 --- a/packages/kit-bg/src/services/ServiceHardware.ts +++ b/packages/kit-bg/src/services/ServiceHardware.ts @@ -8,6 +8,7 @@ import { addConnectedConnectId, removeConnectedConnectId, setHardwarePopup, + setPreviousAddress, setUpdateFirmwareStep, updateDevicePassphraseOpenedState, } from '@onekeyhq/kit/src/store/reducers/hardware'; @@ -89,6 +90,7 @@ class ServiceHardware extends ServiceBase { DEVICE, FIRMWARE, FIRMWARE_EVENT, + UI_REQUEST, supportInputPinOnSoftware, } = await CoreSDKLoader(); instance.on('UI_EVENT', (e) => { @@ -193,6 +195,9 @@ class ServiceHardware extends ServiceBase { ); } }); + instance.on(UI_REQUEST.PREVIOUS_ADDRESS_RESULT, (payload) => { + this.backgroundApi.dispatch(setPreviousAddress(payload)); + }); } return instance; }, diff --git a/packages/kit/src/store/reducers/hardware.ts b/packages/kit/src/store/reducers/hardware.ts index b171ad8b9db..c6feaa2793e 100644 --- a/packages/kit/src/store/reducers/hardware.ts +++ b/packages/kit/src/store/reducers/hardware.ts @@ -3,6 +3,7 @@ import { createSlice } from '@reduxjs/toolkit'; import platformEnv from '@onekeyhq/shared/src/platformEnv'; import type { IOneKeyDeviceType } from '@onekeyhq/shared/types'; +import type { KnownDevice } from '@onekeyfe/hd-core'; import type { PayloadAction } from '@reduxjs/toolkit'; export type HardwareUiEventPayload = { @@ -26,6 +27,10 @@ type InitialState = { lastCheckUpdateTime: Record; // connectId -> time updateFirmwareStep: string; pendingRememberWalletConnectId?: string; + previousAddress?: { + device: KnownDevice; + data: { path?: string; address?: string }; + }; }; const initialState: InitialState = { connected: [], @@ -33,6 +38,7 @@ const initialState: InitialState = { lastCheckUpdateTime: {}, updateFirmwareStep: '', pendingRememberWalletConnectId: undefined, + previousAddress: undefined, }; export const hardwareSlice = createSlice({ name: 'hardware', @@ -86,6 +92,15 @@ export const hardwareSlice = createSlice({ ) => { state.pendingRememberWalletConnectId = action.payload; }, + setPreviousAddress( + state, + action: PayloadAction, + ) { + state.previousAddress = action.payload; + }, + clearPreviousAddress(state) { + state.previousAddress = undefined; + }, }, }); @@ -97,6 +112,8 @@ export const { updateDevicePassphraseOpenedState, setUpdateFirmwareStep, setPendingRememberWalletConnectId, + setPreviousAddress, + clearPreviousAddress, } = hardwareSlice.actions; export default hardwareSlice.reducer; diff --git a/packages/kit/src/views/Account/BulkCopyAddress/FetchAddressModal.tsx b/packages/kit/src/views/Account/BulkCopyAddress/FetchAddressModal.tsx index 2f000a48133..b900bdb6a1f 100644 --- a/packages/kit/src/views/Account/BulkCopyAddress/FetchAddressModal.tsx +++ b/packages/kit/src/views/Account/BulkCopyAddress/FetchAddressModal.tsx @@ -1,5 +1,5 @@ import type { FC } from 'react'; -import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import { useCallback, useEffect, useMemo, useRef } from 'react'; import { useNavigation, useRoute } from '@react-navigation/core'; import { useIntl } from 'react-intl'; @@ -10,28 +10,16 @@ import { Modal, Progress, Text, - ToastManager, VStack, } from '@onekeyhq/components'; -import { OneKeyErrorClassNames } from '@onekeyhq/engine/src/errors'; -import { getDefaultAccountNameInfoByImpl } from '@onekeyhq/engine/src/managers/impl'; -import type { - Account, - ImportableHDAccount, -} from '@onekeyhq/engine/src/types/account'; -import { - IMPL_COSMOS, - INDEX_PLACEHOLDER, -} from '@onekeyhq/shared/src/engine/engineConsts'; -import debugLogger from '@onekeyhq/shared/src/logger/debugLogger'; -import platformEnv from '@onekeyhq/shared/src/platformEnv'; +import type { Account } from '@onekeyhq/engine/src/types/account'; import backgroundApiProxy from '../../../background/instance/backgroundApiProxy'; import { CreateAccountModalRoutes } from '../../../routes/routesEnum'; -import { deviceUtils } from '../../../utils/hardware'; -import { wait } from '../../../utils/helper'; import { formatDerivationLabel } from './helper'; +import { useFetchSetRangeAddress } from './useFetchSetRangeAddress'; +import { useFetchWalletAddress } from './useFetchWalletAddress'; import type { CreateAccountRoutesParams } from '../../../routes'; import type { ModalScreenProps } from '../../../routes/types'; @@ -54,392 +42,83 @@ type RouteProps = RouteProp< CreateAccountModalRoutes.FetchAddressModal >; -type IWalletAccounts = INetworkDerivationItem & { - accountData: (Account & { index: number })[]; +export type IWalletAccounts = INetworkDerivationItem & { + accountData: (Account & { + index: number; + fullPath?: string; + confirm?: boolean; + })[]; }; -const FROM_INDEX_MAX = 2 ** 31; - -function getAccountIndex(template: string, path: string) { - const templateParts = template.split(INDEX_PLACEHOLDER).filter(Boolean); - let currentPath = path; - for (const part of templateParts) { - currentPath = currentPath.split(part).filter(Boolean)?.[0]; - } - return currentPath.endsWith(`'`) ? currentPath.slice(0, -1) : currentPath; -} - const FetchAddressModal: FC = () => { const intl = useIntl(); const route = useRoute(); const { walletId, networkId, data, password } = route.params; const navigation = useNavigation(); + const { + progress: setRangeProgress, + progressText: setRangeProgressText, + previousAddress: setRangePreviousAddress, + generatedAccounts, + cancelFlagRef: setRangeCancelFlagRef, + } = useFetchSetRangeAddress({ + data, + walletId, + networkId, + password, + }); + + const { + progress: walletAccountsProgress, + progressText: walletAccountsProgressText, + previousAddress: walletAccountsPreviousAddress, + walletAccounts, + cancelFlagRef: walletAccountsCancelFlagRef, + } = useFetchWalletAddress({ + data, + walletId, + networkId, + password, + }); + const isHwWallet = walletId.startsWith('hw'); - const isHdWallet = walletId.startsWith('hd'); const cancelFlagRef = useRef(false); const handleExportDataRef = useRef(false); - const [progress, setProgress] = useState(0); - const [generatedAccounts, setGeneratedAccounts] = useState< - ImportableHDAccount[] - >([]); - const [previousAddress, setPreviousAddress] = useState(''); - const [walletAccounts, setWalletAccounts] = useState([]); + const isSetRangeMode = data.type === 'setRange'; - const updateSetRangeAccountProgress = useCallback( - (result: any[], forceFinish?: boolean) => { - if (data.type !== 'setRange') return; - const { generateCount } = data; - const value = forceFinish - ? 1 - : Math.floor((result.length / Number(generateCount)) * 100) / 100; - setGeneratedAccounts(result); - setProgress(value); - }, - [data], + const progress = useMemo( + () => (isSetRangeMode ? setRangeProgress : walletAccountsProgress), + [isSetRangeMode, setRangeProgress, walletAccountsProgress], ); - const generateHDAccounts = useCallback( - async ({ - start, - offset, - purpose, - template, - }: { - start: number; - offset: number; - purpose?: number; - template?: string; - }) => { - const accounts = await backgroundApiProxy.engine.searchHDAccounts( - walletId, - networkId, - password, - start, - offset, - purpose, - template, - ); - return accounts; - }, - [networkId, password, walletId], + const progressText = useMemo( + () => (isSetRangeMode ? setRangeProgressText : walletAccountsProgressText), + [isSetRangeMode, setRangeProgressText, walletAccountsProgressText], ); - // HD Wallet, fetch address for set range mode - useEffect(() => { - if (data.type !== 'setRange') return; - if (isHwWallet) return; - (async () => { - if (platformEnv.isNative) { - await wait(200); - } - const { fromIndex, generateCount, derivationOption } = data; - const template = derivationOption?.template; - const purpose = parseInt( - derivationOption?.category?.split("'/")?.[0] ?? '44', - ); - - const startIndex = Number(fromIndex) - 1; - let start = startIndex; - const pageSize = 5; - let finalLimit = Number(generateCount); - if (start + finalLimit > FROM_INDEX_MAX) { - finalLimit = FROM_INDEX_MAX - start; - } - - const result: ImportableHDAccount[] = []; - let totalGenerateCount = 0; - while (start < startIndex + finalLimit) { - let offset = pageSize; - if (start + pageSize > startIndex + finalLimit) { - offset = finalLimit - totalGenerateCount; - } - if (offset <= 0) { - break; - } - if (cancelFlagRef.current) { - break; - } - const accountsWithNormalizeAddress = await generateHDAccounts({ - start, - offset, - purpose, - template, - }); - const accounts = await Promise.all( - accountsWithNormalizeAddress.map(async (account) => ({ - ...account, - displayAddress: await backgroundApiProxy.engine.getDisplayAddress( - networkId, - account.displayAddress, - ), - })), - ); - result.push(...accounts); - start += pageSize; - totalGenerateCount += offset; - if (platformEnv.isNative) { - await wait(100); - } - if (accounts.length !== offset) { - updateSetRangeAccountProgress(result, true); - break; - } - updateSetRangeAccountProgress(result); - } - })(); - }, [ - data, - isHwWallet, - networkId, - password, - walletId, - generateHDAccounts, - updateSetRangeAccountProgress, - ]); - - // Fetch Hardware Address - useEffect(() => { - if (data.type !== 'setRange') return; - if (!isHwWallet) return; - (async () => { - const { fromIndex, generateCount, derivationOption } = data; - const template = derivationOption?.template; - if (!template) throw new Error('must be a template'); - const result = []; - let hasNotExistAccount = false; - // eslint-disable-next-line no-plusplus - for (let i = 0; i < Number(generateCount || 0); i++) { - if (cancelFlagRef.current) { - break; - } - const index = Number(fromIndex) - 1 + i; - try { - const addressInfo = - await backgroundApiProxy.serviceDerivationPath.getHWAddressByTemplate( - { - networkId, - walletId, - index, - template, - }, - ); - if (!addressInfo.accountExist) { - if (hasNotExistAccount) { - // If there is already no transaction record of the account, the result will be returned directly - updateSetRangeAccountProgress(result, true); - break; - } - hasNotExistAccount = true; - } - result.push(addressInfo); - setPreviousAddress(addressInfo.address); - updateSetRangeAccountProgress(result); - } catch (e: any) { - debugLogger.common.info('getHWAddressByTemplate error: ', e); - const { className } = e || {}; - if (className === OneKeyErrorClassNames.OneKeyHardwareError) { - deviceUtils.showErrorToast(e); - } else { - ToastManager.show({ - title: intl.formatMessage( - { - id: 'msg__cancelled_during_the_process', - }, - { type: 'error' }, - ), - }); - } - updateSetRangeAccountProgress(result, true); - break; - } - } - })(); - }, [ - data, - isHwWallet, - networkId, - walletId, - updateSetRangeAccountProgress, - intl, - ]); + const previousAddress = useMemo( + () => + isSetRangeMode ? setRangePreviousAddress : walletAccountsPreviousAddress, + [isSetRangeMode, setRangePreviousAddress, walletAccountsPreviousAddress], + ); - const updateWalletsAccountProgress = useCallback( - (result: IWalletAccounts[], forceFinish?: boolean) => { - if (data.type !== 'walletAccounts') return; - const { networkDerivations } = data; - const totalLength = networkDerivations.reduce( - (acc, cur) => acc + cur.accounts.length, - 0, - ); - const finishLength = result.reduce( - (acc, cur) => acc + cur.accountData.length, - 0, - ); - const value = forceFinish - ? 1 - : Math.floor((finishLength / Number(totalLength)) * 100) / 100; - setWalletAccounts(result); - setProgress(value); + const setCancelFlag = useCallback( + (flag: boolean) => { + cancelFlagRef.current = flag; + setRangeCancelFlagRef.current = flag; + walletAccountsCancelFlagRef.current = flag; }, - [data], + [setRangeCancelFlagRef, walletAccountsCancelFlagRef], ); - // Fetch Wallet Accounts - useEffect(() => { - if (data.type !== 'walletAccounts') return; - (async () => { - if (platformEnv.isNative) { - await wait(200); - } - let errorState = false; - const { networkDerivations } = data; - const result: IWalletAccounts[] = []; - const { impl } = await backgroundApiProxy.engine.getNetwork(networkId); - for (const networkDerivation of networkDerivations) { - const accounts = await backgroundApiProxy.engine.getAccounts( - networkDerivation.accounts, - networkId, - ); - const accountData = []; - for (const account of accounts) { - try { - if (cancelFlagRef.current || errorState) { - break; - } - if (isHdWallet) { - let { template } = account; - if (!template || impl === IMPL_COSMOS) { - template = getDefaultAccountNameInfoByImpl(impl).template; - } - const pathComponent = account.path.split('/'); - const purpose = Number( - pathComponent[1].endsWith(`'`) - ? pathComponent[1].slice(0, -1) - : pathComponent[1], - ); - const pathComponentAccountIndex = template - ?.split('/') - .findIndex((x: string) => x.startsWith(INDEX_PLACEHOLDER)); - if ( - !Number.isSafeInteger(pathComponentAccountIndex) || - Number(pathComponentAccountIndex) < 0 - ) { - debugLogger.common.error( - 'can not find account index: ', - account, - ); - throw new Error('can not find account index'); - } - const accountIndex = pathComponent[ - pathComponentAccountIndex ?? 0 - ].replace(/'$/, ''); - const hdAccount = - await backgroundApiProxy.engine.getAccountsByVault({ - walletId, - networkId, - password, - indexes: [parseInt(accountIndex, 10)], - purpose, - template, - }); - if ( - hdAccount.length === 1 && - account.address !== hdAccount?.[0].displayAddress - ) { - account.address = hdAccount[0].displayAddress; - } - } - if (isHwWallet) { - const address = await backgroundApiProxy.engine.getHWAddress( - account.id, - networkId, - walletId, - ); - if (address !== account.address) { - throw new Error('Not same address'); - } - setPreviousAddress(address); - } - const address = await backgroundApiProxy.engine.getDisplayAddress( - networkId, - account.address, - ); - accountData.push({ - ...account, - address, - index: getAccountIndex(networkDerivation.template, account.path), - }); - - const sortedAccountData = accountData.sort( - // @ts-expect-error - (a, b) => a.index - b.index, - ); - // replace or insert result data - const derivationIndex = result.findIndex( - (i) => i.template === networkDerivation.template, - ); - if (derivationIndex > -1) { - result.splice(derivationIndex, 1, { - ...networkDerivation, - accountData: sortedAccountData as unknown as (Account & { - index: number; - })[], - }); - } else { - result.push({ - ...networkDerivation, - accountData: sortedAccountData as unknown as (Account & { - index: number; - })[], - }); - } - updateWalletsAccountProgress(result); - if (platformEnv.isNative) { - await wait(0); - } - } catch (e: any) { - debugLogger.common.info('Fetch Wallet Accounts error: ', e); - const { className } = e || {}; - if (className === OneKeyErrorClassNames.OneKeyHardwareError) { - deviceUtils.showErrorToast(e); - } else { - ToastManager.show( - { - title: intl.formatMessage({ - id: 'msg__cancelled_during_the_process', - }), - }, - { type: 'error' }, - ); - } - updateWalletsAccountProgress(result, true); - errorState = true; - navigation.goBack(); - break; - } - } - } - })(); - }, [ - data, - isHwWallet, - isHdWallet, - updateWalletsAccountProgress, - networkId, - walletId, - intl, - password, - navigation, - ]); - useEffect(() => { if (handleExportDataRef.current) return; if (progress >= 1) { handleExportDataRef.current = true; let exportData: IExportAddressData[]; - if (data.type === 'setRange') { + if (isSetRangeMode) { exportData = [ { template: data.derivationOption?.template ?? '', @@ -481,6 +160,7 @@ const FetchAddressModal: FC = () => { } }, [ progress, + isSetRangeMode, data, generatedAccounts, walletAccounts, @@ -491,36 +171,6 @@ const FetchAddressModal: FC = () => { navigation, ]); - const progressText = useMemo(() => { - if (data.type === 'setRange') { - const total = data.generateCount || '0'; - return `${ - Number.isSafeInteger(generatedAccounts.length) - ? generatedAccounts.length - : 0 - }/${total}`; - } - if (data.type === 'walletAccounts') { - const total = data.networkDerivations.reduce( - (acc, cur) => acc + cur.accounts.length, - 0, - ); - const finish = walletAccounts.reduce( - (acc, cur) => acc + cur.accountData.length, - 0, - ); - return `${finish}/${total}`; - } - return ''; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [ - data, - generatedAccounts.length, - walletAccounts, - walletAccounts.length, - progress, - ]); - return ( { primaryActionProps={{ type: 'basic', }} - onPrimaryActionPress={() => { - cancelFlagRef.current = true; - // if (isHwWallet) { - // const device = - // await backgroundApiProxy.engine.getHWDeviceByWalletId( - // walletId, - // ); - // if (device) { - // backgroundApiProxy.serviceHardware.cancel(device.mac); - // } - // } + onPrimaryActionPress={async () => { + setCancelFlag(true); + if (isHwWallet) { + const device = await backgroundApiProxy.engine.getHWDeviceByWalletId( + walletId, + ); + if (device) { + backgroundApiProxy.serviceHardware.cancel(device.mac); + } + } navigation.goBack(); }} > diff --git a/packages/kit/src/views/Account/BulkCopyAddress/useFetchSetRangeAddress.ts b/packages/kit/src/views/Account/BulkCopyAddress/useFetchSetRangeAddress.ts new file mode 100644 index 00000000000..50ae6f0a021 --- /dev/null +++ b/packages/kit/src/views/Account/BulkCopyAddress/useFetchSetRangeAddress.ts @@ -0,0 +1,269 @@ +import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; + +import { useIntl } from 'react-intl'; + +import { ToastManager } from '@onekeyhq/components'; +import { OneKeyErrorClassNames } from '@onekeyhq/engine/src/errors'; +import type { ImportableHDAccount } from '@onekeyhq/engine/src/types/account'; +import { INDEX_PLACEHOLDER } from '@onekeyhq/shared/src/engine/engineConsts'; +import debugLogger from '@onekeyhq/shared/src/logger/debugLogger'; +import platformEnv from '@onekeyhq/shared/src/platformEnv'; + +import backgroundApiProxy from '../../../background/instance/backgroundApiProxy'; +import { useAppSelector } from '../../../hooks'; +import { clearPreviousAddress } from '../../../store/reducers/hardware'; +import { deviceUtils } from '../../../utils/hardware'; +import { wait } from '../../../utils/helper'; + +import type { IFetchAddressByRange, IFetchAddressByWallet } from '.'; + +const FROM_INDEX_MAX = 2 ** 31; + +export function useFetchSetRangeAddress({ + data, + walletId, + networkId, + password, +}: { + data: IFetchAddressByRange | IFetchAddressByWallet; + walletId: string; + networkId: string; + password: string; +}) { + const intl = useIntl(); + const isHwWallet = walletId.startsWith('hw'); + const isSetRangeMode = data.type === 'setRange'; + const cancelFlagRef = useRef(false); + const [progress, setProgress] = useState(0); + const [generatedAccounts, setGeneratedAccounts] = useState< + ImportableHDAccount[] + >([]); + const temporaryAccountsRef = useRef([]); + const checkAddressPathRef = useRef<{ address?: string; path: string }[]>([]); + const [previousAddress, setPreviousAddress] = useState(''); + const previousAddressPayload = useAppSelector( + (s) => s.hardware.previousAddress, + ); + + const updateSetRangeAccountProgress = useCallback( + (result: any[], forceFinish?: boolean) => { + if (data.type !== 'setRange') return; + const { generateCount } = data; + const value = forceFinish + ? 1 + : Math.floor((result.length / Number(generateCount)) * 100) / 100; + setGeneratedAccounts(result); + setProgress(value); + }, + [data], + ); + + useEffect(() => { + if (!isSetRangeMode) return; + const payloadData = previousAddressPayload?.data ?? {}; + if (!payloadData) return; + const { path, address } = payloadData; + const pathIndex = checkAddressPathRef.current.findIndex( + (i) => i.path === previousAddressPayload?.data.path, + ); + if (pathIndex < 0) { + return; + } + setPreviousAddress(address ?? ''); + backgroundApiProxy.serviceDerivationPath + .convertPlainAddressItemToImportableHDAccount({ + networkId, + path: path ?? '', + address: address ?? '', + }) + .then((account) => { + temporaryAccountsRef.current.push(account); + updateSetRangeAccountProgress(temporaryAccountsRef.current); + }); + }, [ + previousAddressPayload, + isSetRangeMode, + networkId, + updateSetRangeAccountProgress, + ]); + + useEffect(() => { + backgroundApiProxy.dispatch(clearPreviousAddress()); + return () => { + backgroundApiProxy.dispatch(clearPreviousAddress()); + }; + }, []); + + const generateHDAccounts = useCallback( + async ({ + start, + offset, + purpose, + template, + }: { + start: number; + offset: number; + purpose?: number; + template?: string; + }) => { + const accounts = await backgroundApiProxy.engine.searchHDAccounts( + walletId, + networkId, + password, + start, + offset, + purpose, + template, + ); + return accounts; + }, + [networkId, password, walletId], + ); + + // HD Wallet, fetch address for set range mode + useEffect(() => { + if (!isSetRangeMode) return; + if (isHwWallet) return; + (async () => { + if (platformEnv.isNative) { + await wait(200); + } + const { fromIndex, generateCount, derivationOption } = data; + const template = derivationOption?.template; + const purpose = parseInt( + derivationOption?.category?.split("'/")?.[0] ?? '44', + ); + + const startIndex = Number(fromIndex) - 1; + let start = startIndex; + const pageSize = 5; + let finalLimit = Number(generateCount); + if (start + finalLimit > FROM_INDEX_MAX) { + finalLimit = FROM_INDEX_MAX - start; + } + + const result: ImportableHDAccount[] = []; + let totalGenerateCount = 0; + while (start < startIndex + finalLimit) { + let offset = pageSize; + if (start + pageSize > startIndex + finalLimit) { + offset = finalLimit - totalGenerateCount; + } + if (offset <= 0) { + break; + } + if (cancelFlagRef.current) { + break; + } + const accountsWithNormalizeAddress = await generateHDAccounts({ + start, + offset, + purpose, + template, + }); + const accounts = await Promise.all( + accountsWithNormalizeAddress.map(async (account) => ({ + ...account, + displayAddress: await backgroundApiProxy.engine.getDisplayAddress( + networkId, + account.displayAddress, + ), + })), + ); + result.push(...accounts); + start += pageSize; + totalGenerateCount += offset; + if (platformEnv.isNative) { + await wait(100); + } + if (accounts.length !== offset) { + updateSetRangeAccountProgress(result, true); + break; + } + updateSetRangeAccountProgress(result); + } + })(); + }, [ + data, + isHwWallet, + isSetRangeMode, + networkId, + password, + walletId, + generateHDAccounts, + updateSetRangeAccountProgress, + ]); + + // Fetch Hardware Address + useEffect(() => { + if (!isSetRangeMode) return; + if (!isHwWallet) return; + (async () => { + const { fromIndex, generateCount, derivationOption } = data; + const template = derivationOption?.template; + if (!template) throw new Error('must be a template'); + const indexes = []; + // eslint-disable-next-line no-plusplus + for (let i = 0; i < Number(generateCount || 0); i++) { + const index = Number(fromIndex) - 1 + i; + indexes.push(index); + } + checkAddressPathRef.current = indexes.map((i) => ({ + path: template.replace(INDEX_PLACEHOLDER, i.toString()), + })); + try { + const addressInfos = + await backgroundApiProxy.serviceDerivationPath.batchGetHWAddress({ + networkId, + walletId, + indexes, + template, + confirmOnDevice: true, + }); + updateSetRangeAccountProgress(addressInfos); + } catch (e: any) { + debugLogger.common.info('getHWAddressByTemplate error: ', e); + const { className } = e || {}; + if (className === OneKeyErrorClassNames.OneKeyHardwareError) { + deviceUtils.showErrorToast(e); + } else { + ToastManager.show({ + title: intl.formatMessage( + { + id: 'msg__cancelled_during_the_process', + }, + { type: 'error' }, + ), + }); + } + updateSetRangeAccountProgress(temporaryAccountsRef.current, true); + } + })(); + }, [ + data, + isHwWallet, + isSetRangeMode, + networkId, + walletId, + updateSetRangeAccountProgress, + intl, + ]); + + const progressText = useMemo(() => { + if (!isSetRangeMode) return undefined; + const total = data.generateCount || '0'; + return `${ + Number.isSafeInteger(generatedAccounts.length) + ? generatedAccounts.length + : 0 + }/${total}`; + }, [data, isSetRangeMode, generatedAccounts.length]); + + return { + progress, + progressText, + generatedAccounts, + previousAddress, + cancelFlagRef, + }; +} diff --git a/packages/kit/src/views/Account/BulkCopyAddress/useFetchWalletAddress.ts b/packages/kit/src/views/Account/BulkCopyAddress/useFetchWalletAddress.ts new file mode 100644 index 00000000000..906b922aea3 --- /dev/null +++ b/packages/kit/src/views/Account/BulkCopyAddress/useFetchWalletAddress.ts @@ -0,0 +1,387 @@ +import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; + +import { useIntl } from 'react-intl'; + +import { ToastManager } from '@onekeyhq/components'; +import { OneKeyErrorClassNames } from '@onekeyhq/engine/src/errors'; +import { getDefaultAccountNameInfoByImpl } from '@onekeyhq/engine/src/managers/impl'; +import type { Account } from '@onekeyhq/engine/src/types/account'; +import { + IMPL_COSMOS, + INDEX_PLACEHOLDER, +} from '@onekeyhq/shared/src/engine/engineConsts'; +import debugLogger from '@onekeyhq/shared/src/logger/debugLogger'; +import platformEnv from '@onekeyhq/shared/src/platformEnv'; + +import backgroundApiProxy from '../../../background/instance/backgroundApiProxy'; +import { useAppSelector } from '../../../hooks'; +import useAppNavigation from '../../../hooks/useAppNavigation'; +import { deviceUtils } from '../../../utils/hardware'; +import { wait } from '../../../utils/helper'; + +import type { IFetchAddressByRange, IFetchAddressByWallet } from '.'; +import type { IWalletAccounts } from './FetchAddressModal'; + +function getAccountIndex(template: string, path: string) { + const templateParts = template.split(INDEX_PLACEHOLDER).filter(Boolean); + let currentPath = path; + for (const part of templateParts) { + currentPath = currentPath.split(part).filter(Boolean)?.[0]; + } + return currentPath.endsWith(`'`) ? currentPath.slice(0, -1) : currentPath; +} + +export function useFetchWalletAddress({ + data, + walletId, + networkId, + password, +}: { + data: IFetchAddressByRange | IFetchAddressByWallet; + walletId: string; + networkId: string; + password: string; +}) { + const intl = useIntl(); + const navigation = useAppNavigation(); + const isHwWallet = walletId.startsWith('hw'); + const isFetchWalletAccountsMode = data.type === 'walletAccounts'; + const cancelFlagRef = useRef(false); + const [progress, setProgress] = useState(0); + const [walletAccounts, setWalletAccounts] = useState([]); + const temporaryAccountsRef = useRef([]); + const currentTemplateRef = useRef(''); + + const [previousAddress, setPreviousAddress] = useState(''); + const previousAddressPayload = useAppSelector( + (s) => s.hardware.previousAddress, + ); + + const updateWalletsAccountProgress = useCallback( + (result: IWalletAccounts[], forceFinish?: boolean) => { + if (data.type !== 'walletAccounts') return; + const { networkDerivations } = data; + const totalLength = networkDerivations.reduce( + (acc, cur) => acc + cur.accounts.length, + 0, + ); + const finishLength = result.reduce((acc, cur) => { + const accountDataLength = isHwWallet + ? cur.accountData.filter((i) => i.confirm).length + : cur.accountData.length; + return acc + accountDataLength; + }, 0); + const value = forceFinish + ? 1 + : Math.floor((finishLength / Number(totalLength)) * 100) / 100; + setWalletAccounts(result); + setProgress(value); + }, + [data, isHwWallet], + ); + + useEffect(() => { + if (!isFetchWalletAccountsMode) return; + const payloadData = previousAddressPayload?.data ?? {}; + if (!payloadData) return; + const { path, address } = payloadData; + if (!currentTemplateRef.current) return; + temporaryAccountsRef.current.forEach((temporaryAccount) => { + if (temporaryAccount.template !== currentTemplateRef.current) { + return; + } + const { accountData } = temporaryAccount; + const matchIndex = accountData.findIndex( + (account) => account.fullPath === path, + ); + if (matchIndex !== -1) { + if ( + address && + accountData[matchIndex].address.toLowerCase() !== + address.toLowerCase() + ) { + throw new Error('not same address'); + } else if (address) { + backgroundApiProxy.serviceDerivationPath + .convertPlainAddressItemToImportableHDAccount({ + networkId, + path: path ?? '', + address: address ?? '', + }) + .then((account) => { + accountData[matchIndex].address = account.displayAddress; + accountData[matchIndex].confirm = true; + setPreviousAddress(account.displayAddress ?? ''); + updateWalletsAccountProgress(temporaryAccountsRef.current); + }); + } + } + }); + }, [ + previousAddressPayload, + isFetchWalletAccountsMode, + networkId, + updateWalletsAccountProgress, + ]); + + // Fetch HD Wallet Accounts + useEffect(() => { + if (!isFetchWalletAccountsMode) return; + if (isHwWallet) return; + + (async () => { + if (platformEnv.isNative) { + await wait(200); + } + let errorState = false; + const { networkDerivations } = data; + const result: IWalletAccounts[] = []; + const { impl } = await backgroundApiProxy.engine.getNetwork(networkId); + for (const networkDerivation of networkDerivations) { + const accounts = await backgroundApiProxy.engine.getAccounts( + networkDerivation.accounts, + networkId, + ); + const accountData = []; + for (const account of accounts) { + try { + if (cancelFlagRef.current || errorState) { + break; + } + let { template } = account; + if (!template || impl === IMPL_COSMOS) { + template = getDefaultAccountNameInfoByImpl(impl).template; + } + const pathComponent = account.path.split('/'); + const purpose = Number( + pathComponent[1].endsWith(`'`) + ? pathComponent[1].slice(0, -1) + : pathComponent[1], + ); + const pathComponentAccountIndex = template + ?.split('/') + .findIndex((x: string) => x.startsWith(INDEX_PLACEHOLDER)); + if ( + !Number.isSafeInteger(pathComponentAccountIndex) || + Number(pathComponentAccountIndex) < 0 + ) { + debugLogger.common.error('can not find account index: ', account); + throw new Error('can not find account index'); + } + const accountIndex = pathComponent[ + pathComponentAccountIndex ?? 0 + ].replace(/'$/, ''); + const hdAccount = + await backgroundApiProxy.engine.getAccountsByVault({ + walletId, + networkId, + password, + indexes: [parseInt(accountIndex, 10)], + purpose, + template, + }); + if ( + hdAccount.length === 1 && + account.address !== hdAccount?.[0].displayAddress + ) { + account.address = hdAccount[0].displayAddress; + } + const address = await backgroundApiProxy.engine.getDisplayAddress( + networkId, + account.address, + ); + accountData.push({ + ...account, + address, + index: getAccountIndex(networkDerivation.template, account.path), + }); + + const sortedAccountData = accountData.sort( + (a, b) => Number(a.index) - Number(b.index), + ); + // replace or insert result data + const derivationIndex = result.findIndex( + (i) => i.template === networkDerivation.template, + ); + if (derivationIndex > -1) { + result.splice(derivationIndex, 1, { + ...networkDerivation, + accountData: sortedAccountData as unknown as (Account & { + index: number; + })[], + }); + } else { + result.push({ + ...networkDerivation, + accountData: sortedAccountData as unknown as (Account & { + index: number; + })[], + }); + } + updateWalletsAccountProgress(result); + if (platformEnv.isNative) { + await wait(0); + } + } catch (e: any) { + debugLogger.common.info('Fetch Wallet Accounts error: ', e); + const { className } = e || {}; + if (className === OneKeyErrorClassNames.OneKeyHardwareError) { + deviceUtils.showErrorToast(e); + } else { + ToastManager.show( + { + title: intl.formatMessage({ + id: 'msg__cancelled_during_the_process', + }), + }, + { type: 'error' }, + ); + } + updateWalletsAccountProgress(result, true); + errorState = true; + navigation.goBack(); + break; + } + } + } + })(); + }, [ + data, + isHwWallet, + isFetchWalletAccountsMode, + updateWalletsAccountProgress, + networkId, + walletId, + intl, + password, + navigation, + ]); + + // Fetch Hardware Wallet Accounts + useEffect(() => { + if (!isFetchWalletAccountsMode) return; + if (!isHwWallet) return; + + (async () => { + if (platformEnv.isNative) { + await wait(200); + } + let errorState = false; + const { networkDerivations } = data; + const result: IWalletAccounts[] = []; + for (const networkDerivation of networkDerivations) { + try { + const accounts = await backgroundApiProxy.engine.getAccounts( + networkDerivation.accounts, + networkId, + ); + const accountData = accounts + .map((account) => { + const index = getAccountIndex( + networkDerivation.template, + account.path, + ); + return { + fullPath: networkDerivation.template.replace( + INDEX_PLACEHOLDER, + index.toString(), + ), + index: Number(index), + ...account, + }; + }) + .sort((a, b) => Number(a.index) - Number(b.index)); + + currentTemplateRef.current = networkDerivation.template; + temporaryAccountsRef.current.push({ + ...networkDerivation, + accountData: accountData.map((i) => ({ ...i, confirm: false })), + }); + + const hardwareAddressesResults = + await backgroundApiProxy.serviceDerivationPath.batchGetHWAddress({ + networkId, + walletId, + indexes: accountData.map((i) => Number(i.index)), + confirmOnDevice: true, + template: networkDerivation.template, + }); + hardwareAddressesResults.forEach((res) => { + const index = accountData.findIndex((i) => i.fullPath === res.path); + if (index > -1) { + accountData[index].displayAddress = res.displayAddress; + } + }); + result.push({ + ...networkDerivation, + accountData, + }); + updateWalletsAccountProgress(result); + if (cancelFlagRef.current || errorState) { + break; + } + if (platformEnv.isNative) { + await wait(0); + } + } catch (e: any) { + debugLogger.common.info('Fetch Wallet Accounts error: ', e); + const { className } = e || {}; + if (className === OneKeyErrorClassNames.OneKeyHardwareError) { + deviceUtils.showErrorToast(e); + } else { + ToastManager.show( + { + title: intl.formatMessage({ + id: 'msg__cancelled_during_the_process', + }), + }, + { type: 'error' }, + ); + } + updateWalletsAccountProgress(result, true); + errorState = true; + navigation.goBack(); + break; + } + } + })(); + }, [ + data, + isHwWallet, + isFetchWalletAccountsMode, + updateWalletsAccountProgress, + networkId, + walletId, + intl, + password, + navigation, + ]); + + const progressText = useMemo(() => { + if (!isFetchWalletAccountsMode) return undefined; + const total = data.networkDerivations.reduce( + (acc, cur) => acc + cur.accounts.length, + 0, + ); + const dataSource = isHwWallet + ? temporaryAccountsRef.current + : walletAccounts; + const finish = dataSource.reduce((acc, cur) => { + const accountDataLength = isHwWallet + ? cur.accountData.filter((i) => i.confirm).length + : cur.accountData.length; + return acc + accountDataLength; + }, 0); + return `${finish}/${total}`; + + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [data, isHwWallet, isFetchWalletAccountsMode, walletAccounts, progress]); + + return { + progress, + progressText, + previousAddress, + walletAccounts, + cancelFlagRef, + }; +} diff --git a/packages/shared/src/config/appConfig.ts b/packages/shared/src/config/appConfig.ts index af0a985d866..5c8865313d7 100644 --- a/packages/shared/src/config/appConfig.ts +++ b/packages/shared/src/config/appConfig.ts @@ -9,7 +9,7 @@ export const COVALENT_API_KEY = process.env.COVALENT_KEY!; export const JPUSH_KEY = process.env.JPUSH_KEY!; export const HARDWARE_SDK_IFRAME_SRC = - process.env.HARDWARE_SDK_CONNECT_SRC || 'https://jssdk.onekey.so/0.2.43/'; + process.env.HARDWARE_SDK_CONNECT_SRC || 'https://jssdk.onekey.so/0.2.44/'; export const HARDWARE_BRIDGE_DOWNLOAD_URL = 'https://onekey.so/download/?client=bridge'; diff --git a/yarn.lock b/yarn.lock index 205a975fd82..8ab63719d4f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5029,23 +5029,23 @@ __metadata: languageName: node linkType: hard -"@onekeyfe/hd-ble-sdk@npm:0.2.43": - version: 0.2.43 - resolution: "@onekeyfe/hd-ble-sdk@npm:0.2.43" +"@onekeyfe/hd-ble-sdk@npm:0.2.44": + version: 0.2.44 + resolution: "@onekeyfe/hd-ble-sdk@npm:0.2.44" dependencies: - "@onekeyfe/hd-core": ^0.2.43 - "@onekeyfe/hd-shared": ^0.2.43 - "@onekeyfe/hd-transport-react-native": ^0.2.43 - checksum: cc5cc996ba2ebd58271687233e3f80a445b4162c655f196cbce86389e1adb26ccd2b3452f5ccab9a7e2ca9537f41b58e75991cba734cd589b1a9816856143b44 + "@onekeyfe/hd-core": ^0.2.44 + "@onekeyfe/hd-shared": ^0.2.44 + "@onekeyfe/hd-transport-react-native": ^0.2.44 + checksum: fa424c16d112a52f1482bc535601fa49de2a815f548d8a3ed6d4dd390c15c60d64869daa149d968cf6327ddbe196a9b7d32a12d2d7cc5871a2664a51b4002ef5 languageName: node linkType: hard -"@onekeyfe/hd-core@npm:0.2.43, @onekeyfe/hd-core@npm:^0.2.43": - version: 0.2.43 - resolution: "@onekeyfe/hd-core@npm:0.2.43" +"@onekeyfe/hd-core@npm:0.2.44, @onekeyfe/hd-core@npm:^0.2.44": + version: 0.2.44 + resolution: "@onekeyfe/hd-core@npm:0.2.44" dependencies: - "@onekeyfe/hd-shared": ^0.2.43 - "@onekeyfe/hd-transport": ^0.2.43 + "@onekeyfe/hd-shared": ^0.2.44 + "@onekeyfe/hd-transport": ^0.2.44 axios: ^0.27.2 bignumber.js: ^9.0.2 bytebuffer: ^5.0.1 @@ -5055,71 +5055,71 @@ __metadata: peerDependencies: "@noble/hashes": ^1.1.3 ripple-keypairs: ^1.1.4 - checksum: 48c74e6561bc923bf7060904f6666753d6ee35c11b3d93208ace16c77da3d382277d89dbb39f7c1c1791485e3b634c9f1fbb8f0135a22639c6636b7391207ca5 + checksum: 7ce0d0a53d10ae511db026cb61f74a778c33571f2f93287df740999c2c8017e626aa2206948112e603471f794d9378631ae35658373921d44d0a01c8973a058b languageName: node linkType: hard -"@onekeyfe/hd-shared@npm:0.2.43, @onekeyfe/hd-shared@npm:^0.2.43": - version: 0.2.43 - resolution: "@onekeyfe/hd-shared@npm:0.2.43" - checksum: e9e291d5d557f2d72cfb3d6c6f2e75075e088a788d27e9cfbf5ffdfe063f2b97ec420e2dd118ee01f52a5d7c8a96f4007e19c51d26e0df1c62cf98332810b36a +"@onekeyfe/hd-shared@npm:0.2.44, @onekeyfe/hd-shared@npm:^0.2.44": + version: 0.2.44 + resolution: "@onekeyfe/hd-shared@npm:0.2.44" + checksum: f49895b0ef788a41a19912595183f4adda55e31a09d50c4aca96c667201668627019bd39655ff48a3ccae95c172f22721cbf4730e4dd4500c033ee0c753339d5 languageName: node linkType: hard -"@onekeyfe/hd-transport-http@npm:^0.2.43": - version: 0.2.43 - resolution: "@onekeyfe/hd-transport-http@npm:0.2.43" +"@onekeyfe/hd-transport-http@npm:^0.2.44": + version: 0.2.44 + resolution: "@onekeyfe/hd-transport-http@npm:0.2.44" dependencies: - "@onekeyfe/hd-shared": ^0.2.43 - "@onekeyfe/hd-transport": ^0.2.43 + "@onekeyfe/hd-shared": ^0.2.44 + "@onekeyfe/hd-transport": ^0.2.44 axios: ^0.27.2 - checksum: 3881e705ce979f0af31308710d810d4ba970f258f33a3b776ec2c165f74c055ea68d1f554b88d951a1228a9ff8d1c7037279c623ed7f08b931c3c32a6047c0af + checksum: bb14bc097a6fb306eda49fce1908d1fae19a162bb080602e40382730878d807106e439c4cba20a47f9797b99b2e293016346c7d6c58dcd8aff8025220c1ae4ae languageName: node linkType: hard -"@onekeyfe/hd-transport-react-native@npm:^0.2.43": - version: 0.2.43 - resolution: "@onekeyfe/hd-transport-react-native@npm:0.2.43" +"@onekeyfe/hd-transport-react-native@npm:^0.2.44": + version: 0.2.44 + resolution: "@onekeyfe/hd-transport-react-native@npm:0.2.44" dependencies: - "@onekeyfe/hd-shared": ^0.2.43 - "@onekeyfe/hd-transport": ^0.2.43 + "@onekeyfe/hd-shared": ^0.2.44 + "@onekeyfe/hd-transport": ^0.2.44 "@onekeyfe/react-native-ble-plx": 3.0.0 react-native-ble-manager: ^8.1.0 - checksum: 5f08f889c9773d3944dc2e321401aa77c9740c90e29be4f3c86a174f9144b14b06dc87fa794e7aa71c553ed85c602a1b9e689f4e60c943d92b67cb0aa73ffc63 + checksum: 94c757f2e700ecb61ed69238ba42c4857d3bc83e2a932f1a4a94670a172edbc18730e2e1307ee70ccbaea3bff5b02d522bf6ce811b57ecd2972196135724ad8e languageName: node linkType: hard -"@onekeyfe/hd-transport-webusb@npm:^0.2.43": - version: 0.2.43 - resolution: "@onekeyfe/hd-transport-webusb@npm:0.2.43" +"@onekeyfe/hd-transport-webusb@npm:^0.2.44": + version: 0.2.44 + resolution: "@onekeyfe/hd-transport-webusb@npm:0.2.44" dependencies: - "@onekeyfe/hd-shared": ^0.2.43 - "@onekeyfe/hd-transport": ^0.2.43 - checksum: d19f867081bc1feebfc73c9828a3bd251bfb42a2bd5c9323f3d8906904e317bcbf026b7bf886dd628665712d21fa3e33d51e62e949ae57a9d44f41c2cc0acbd9 + "@onekeyfe/hd-shared": ^0.2.44 + "@onekeyfe/hd-transport": ^0.2.44 + checksum: 12b298e668861a0a45413b1fca11d17b843b9583b7691f491d3a6aa94f05f6a8ed69dea100b8523c14b89fa3e57457a390b318e7e98168949b149b6b9cb98d1d languageName: node linkType: hard -"@onekeyfe/hd-transport@npm:0.2.43, @onekeyfe/hd-transport@npm:^0.2.43": - version: 0.2.43 - resolution: "@onekeyfe/hd-transport@npm:0.2.43" +"@onekeyfe/hd-transport@npm:0.2.44, @onekeyfe/hd-transport@npm:^0.2.44": + version: 0.2.44 + resolution: "@onekeyfe/hd-transport@npm:0.2.44" dependencies: bytebuffer: ^5.0.1 long: ^4.0.0 protobufjs: ^6.11.2 - checksum: 5bec307ee134d36e7e024ffc6ad0c2a432e211c092b789ba0acbf773f864d792fe4400c4ad438570267a05edb0752c5dc13399643a77cd8431ed72c675b5c92a + checksum: 1705ae999d24366ad8cf223cd19f2e46a61bae3cdb348a83012953eed449f80d3087cae4291a1722be580287d175c1f8386c723561b07ca4de1d3079be7a0dca languageName: node linkType: hard -"@onekeyfe/hd-web-sdk@npm:0.2.43": - version: 0.2.43 - resolution: "@onekeyfe/hd-web-sdk@npm:0.2.43" +"@onekeyfe/hd-web-sdk@npm:0.2.44": + version: 0.2.44 + resolution: "@onekeyfe/hd-web-sdk@npm:0.2.44" dependencies: "@onekeyfe/cross-inpage-provider-core": ^0.0.17 - "@onekeyfe/hd-core": ^0.2.43 - "@onekeyfe/hd-shared": ^0.2.43 - "@onekeyfe/hd-transport-http": ^0.2.43 - "@onekeyfe/hd-transport-webusb": ^0.2.43 - checksum: f10f5b1fcdaac1ca39391515385983a9559b20a076a2a138155cb01199472e9b66cc90215866f43a5dc2a57d7defea3a029497637dddb05550d9c4b9a302d59d + "@onekeyfe/hd-core": ^0.2.44 + "@onekeyfe/hd-shared": ^0.2.44 + "@onekeyfe/hd-transport-http": ^0.2.44 + "@onekeyfe/hd-transport-webusb": ^0.2.44 + checksum: f4b56b682c7b747c50ad149f9be45ba148b904e1811863afa3b948f7ff27b3238095b32d1a173d9352fa79c33d55ebfb71e55f995f7b19d12b3befba4b0bf4f6 languageName: node linkType: hard @@ -5368,11 +5368,11 @@ __metadata: "@onekeyfe/cross-inpage-provider-injected": 1.1.24 "@onekeyfe/cross-inpage-provider-types": 1.1.24 "@onekeyfe/extension-bridge-hosted": 1.1.24 - "@onekeyfe/hd-ble-sdk": 0.2.43 - "@onekeyfe/hd-core": 0.2.43 - "@onekeyfe/hd-shared": 0.2.43 - "@onekeyfe/hd-transport": 0.2.43 - "@onekeyfe/hd-web-sdk": 0.2.43 + "@onekeyfe/hd-ble-sdk": 0.2.44 + "@onekeyfe/hd-core": 0.2.44 + "@onekeyfe/hd-shared": 0.2.44 + "@onekeyfe/hd-transport": 0.2.44 + "@onekeyfe/hd-web-sdk": 0.2.44 "@onekeyfe/network-list": 1.6.54 "@onekeyfe/onekey-cross-webview": 1.1.24 "@open-wc/webpack-import-meta-loader": ^0.4.7