From ed5aa10176df69b17a9db551899532569a77d144 Mon Sep 17 00:00:00 2001 From: morizon Date: Sat, 27 Sep 2025 09:46:19 +0800 Subject: [PATCH 1/3] fix(perp): improve account selection and UI for HyperLiquid MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add debug logging and error handling in perps account selection - Adjust loading timeout delay from 0ms to 300ms for better UX - Add auto-select perps account when ETH accounts are added to wallet - Hide deposit button when no perps account is selected - Replace debug button text with icon for cleaner UI - Remove unnecessary console logs in subscription service 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .../ServiceHyperLiquid/ServiceHyperliquid.ts | 21 +++-- .../ServiceHyperliquidSubscription.ts | 4 - .../Perp/components/PerpsGlobalEffects.tsx | 27 ++++++ .../components/PerpsHeaderRight.tsx | 93 ++++++++++--------- 4 files changed, 89 insertions(+), 56 deletions(-) diff --git a/packages/kit-bg/src/services/ServiceHyperLiquid/ServiceHyperliquid.ts b/packages/kit-bg/src/services/ServiceHyperLiquid/ServiceHyperliquid.ts index 7bb574be323..7ecb5624493 100644 --- a/packages/kit-bg/src/services/ServiceHyperLiquid/ServiceHyperliquid.ts +++ b/packages/kit-bg/src/services/ServiceHyperLiquid/ServiceHyperliquid.ts @@ -466,14 +466,18 @@ export default class ServiceHyperliquid extends ServiceBase { console.log('selectPerpsAccount______111', indexedAccountId, accountId); if (indexedAccountId || accountId) { const ethNetworkId = PERPS_NETWORK_ID; + const getNetworkAccountParams = { + indexedAccountId: indexedAccountId ?? undefined, + accountId: indexedAccountId ? undefined : accountId ?? undefined, + networkId: ethNetworkId, + deriveType: deriveType || 'default', + }; + console.log('selectPerpsAccount______222', getNetworkAccountParams); const account = - await this.backgroundApi.serviceAccount.getNetworkAccount({ - indexedAccountId: indexedAccountId ?? undefined, - accountId: indexedAccountId ? undefined : accountId ?? undefined, - networkId: ethNetworkId, - deriveType: deriveType || 'default', - }); - console.log('selectPerpsAccount______222', account); + await this.backgroundApi.serviceAccount.getNetworkAccount( + getNetworkAccountParams, + ); + console.log('selectPerpsAccount______333', account); perpsAccount.accountAddress = (account.address?.toLowerCase() as IHex) || null; if (perpsAccount.accountAddress) { @@ -485,6 +489,7 @@ export default class ServiceHyperliquid extends ServiceBase { }); } } catch (error) { + console.log('selectPerpsAccount______444_error', error); console.error(error); } finally { clearTimeout(this.hideSelectAccountLoadingTimer); @@ -495,7 +500,7 @@ export default class ServiceHyperliquid extends ServiceBase { selectAccountLoading: false, }), ); - }, 0); + }, 300); } await perpsActiveAccountAtom.set(perpsAccount); diff --git a/packages/kit-bg/src/services/ServiceHyperLiquid/ServiceHyperliquidSubscription.ts b/packages/kit-bg/src/services/ServiceHyperLiquid/ServiceHyperliquidSubscription.ts index dde9ec3da09..877acd99ed5 100644 --- a/packages/kit-bg/src/services/ServiceHyperLiquid/ServiceHyperliquidSubscription.ts +++ b/packages/kit-bg/src/services/ServiceHyperLiquid/ServiceHyperliquidSubscription.ts @@ -428,10 +428,6 @@ export default class ServiceHyperliquidSubscription extends ServiceBase { } if (subscriptionType === ESubscriptionType.ALL_MIDS) { - console.log( - '[ServiceHyperliquidSubscription.handleSubscriptionData] User fills data:', - data, - ); // TODO remove hyperLiquidCache.allMids = data as IWsAllMids; void this.backgroundApi.serviceHyperliquid.refreshCurrentMid(); diff --git a/packages/kit/src/views/Perp/components/PerpsGlobalEffects.tsx b/packages/kit/src/views/Perp/components/PerpsGlobalEffects.tsx index e1133454249..072ef6a84a8 100644 --- a/packages/kit/src/views/Perp/components/PerpsGlobalEffects.tsx +++ b/packages/kit/src/views/Perp/components/PerpsGlobalEffects.tsx @@ -1,5 +1,7 @@ import { useCallback, useEffect, useRef } from 'react'; +// eslint-disable-next-line @typescript-eslint/no-unused-vars +import { useFocusEffect } from '@react-navigation/native'; import { noop } from 'lodash'; import { useUpdateEffect } from '@onekeyhq/components'; @@ -13,6 +15,8 @@ import { usePerpsActiveAccountAtom, } from '@onekeyhq/kit-bg/src/states/jotai/atoms/perps'; import { PERPS_NETWORK_ID } from '@onekeyhq/shared/src/consts/perp'; +import { COINTYPE_ETH } from '@onekeyhq/shared/src/engine/engineConsts'; +import type { IAppEventBusPayload } from '@onekeyhq/shared/src/eventBus/appEventBus'; import { EAppEventBusNames, appEventBus, @@ -184,6 +188,8 @@ function useHyperliquidAccountSelect() { const isFocused = useRouteIsFocused(); const [indexedAccountAddressCreationState] = useIndexedAccountAddressCreationStateAtom(); + const perpsAccountAddressRef = useRef(currentPerpsAccount?.accountAddress); + perpsAccountAddressRef.current = currentPerpsAccount?.accountAddress; // const [perpsAccountStatus] = usePerpsSelectedAccountStatusAtom(); // const perpsAccountStatusRef = useRef(perpsAccountStatus); @@ -225,6 +231,10 @@ function useHyperliquidAccountSelect() { return; } noop(activeAccount.account?.address); + console.log( + 'selectPerpsAccount______555_address', + activeAccount.account?.address, + ); const _account = await backgroundApiProxy.serviceHyperliquid.selectPerpsAccount({ indexedAccountId: activeAccount?.indexedAccount?.id || null, @@ -247,6 +257,23 @@ function useHyperliquidAccountSelect() { void selectPerpsAccount(); }, [selectPerpsAccount]); + useEffect(() => { + const fn = async ( + payload: IAppEventBusPayload[EAppEventBusNames.AddDBAccountsToWallet], + ) => { + await timerUtils.wait(600); + if (!perpsAccountAddressRef.current) { + if (payload?.accounts?.find((item) => item.coinType === COINTYPE_ETH)) { + await selectPerpsAccountRef.current(); + } + } + }; + appEventBus.on(EAppEventBusNames.AddDBAccountsToWallet, fn); + return () => { + appEventBus.off(EAppEventBusNames.AddDBAccountsToWallet, fn); + }; + }, []); + useUpdateEffect(() => { if (!accountIsAutoCreating && !indexedAccountAddressCreationState) { void selectPerpsAccountRef.current(); diff --git a/packages/kit/src/views/Perp/components/TradingPanel/components/PerpsHeaderRight.tsx b/packages/kit/src/views/Perp/components/TradingPanel/components/PerpsHeaderRight.tsx index 95d3d1f5918..021401f9332 100644 --- a/packages/kit/src/views/Perp/components/TradingPanel/components/PerpsHeaderRight.tsx +++ b/packages/kit/src/views/Perp/components/TradingPanel/components/PerpsHeaderRight.tsx @@ -6,6 +6,7 @@ import { DebugRenderTracker, Divider, Icon, + IconButton, SizableText, XStack, useMedia, @@ -53,7 +54,10 @@ function DebugButton() { return ( - + /> ); } @@ -89,51 +91,54 @@ export function PerpsHeaderRight() { const { gtSm } = useMedia(); const accountValue = accountSummary?.accountValue; const intl = useIntl(); + const [activeAccount] = usePerpsActiveAccountAtom(); return ( {process.env.NODE_ENV !== 'production' ? : null} - - showDepositWithdrawModal({ - actionType: 'deposit', - withdrawable: accountSummary?.withdrawable || '0', - }) - } - alignItems="center" - justifyContent="center" - flexDirection="row" - gap="$2" - px="$3" - h={32} - hoverStyle={{ - bg: '$bgStrongHover', - }} - pressStyle={{ - bg: '$bgStrongActive', - }} - cursor="pointer" - > - + {activeAccount.accountAddress ? ( + + showDepositWithdrawModal({ + actionType: 'deposit', + withdrawable: accountSummary?.withdrawable || '0', + }) + } + alignItems="center" + justifyContent="center" + flexDirection="row" + gap="$2" + px="$3" + h={32} + hoverStyle={{ + bg: '$bgStrongHover', + }} + pressStyle={{ + bg: '$bgStrongActive', + }} + cursor="pointer" + > + - {gtSm ? ( - + ) : null} + - ) : null} - - - {intl.formatMessage({ id: ETranslations.perp_trade_deposit })} - - + + {intl.formatMessage({ id: ETranslations.perp_trade_deposit })} + + + ) : null} {platformEnv.isNative ? null : ( )} From f50fe49cb0e5253ad652b85d21915054e2ce5c0c Mon Sep 17 00:00:00 2001 From: morizon Date: Sat, 27 Sep 2025 10:26:27 +0800 Subject: [PATCH 2/3] fix(perp): improve error handling and account status management MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add @toastIfError decorator to enableTrading method for better error handling - Fix atom setter type consistency in disposeExchangeClients - Refactor invalid agent error handling to use service method instead of direct atom manipulation - Remove redundant error toast in DepositWithdrawModal to avoid duplicate error messages 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .../ServiceHyperLiquid/ServiceHyperliquid.ts | 22 ++++++++++--------- .../contexts/hyperliquid/utils/withToast.ts | 12 ++-------- .../modals/DepositWithdrawModal.tsx | 7 +----- 3 files changed, 15 insertions(+), 26 deletions(-) diff --git a/packages/kit-bg/src/services/ServiceHyperLiquid/ServiceHyperliquid.ts b/packages/kit-bg/src/services/ServiceHyperLiquid/ServiceHyperliquid.ts index 7ecb5624493..62899b074d2 100644 --- a/packages/kit-bg/src/services/ServiceHyperLiquid/ServiceHyperliquid.ts +++ b/packages/kit-bg/src/services/ServiceHyperLiquid/ServiceHyperliquid.ts @@ -513,6 +513,7 @@ export default class ServiceHyperliquid extends ServiceBase { } @backgroundMethod() + @toastIfError() async enableTrading() { await this.checkPerpsAccountStatus({ isEnableTradingTrigger: true, @@ -932,16 +933,17 @@ export default class ServiceHyperliquid extends ServiceBase { @backgroundMethod() async disposeExchangeClients() { await this.exchangeService.dispose(); - await perpsActiveAccountStatusInfoAtom.set({ - accountAddress: null, - canTrade: false, - details: { - activatedOk: false, - agentOk: false, - builderFeeOk: false, - referralCodeOk: false, - }, - }); + await perpsActiveAccountStatusInfoAtom.set( + (_prev): IPerpsActiveAccountStatusInfoAtom => ({ + accountAddress: null, + details: { + activatedOk: false, + agentOk: false, + builderFeeOk: false, + referralCodeOk: false, + }, + }), + ); } @backgroundMethod() diff --git a/packages/kit/src/states/jotai/contexts/hyperliquid/utils/withToast.ts b/packages/kit/src/states/jotai/contexts/hyperliquid/utils/withToast.ts index 2eb1d4fdd69..187ee62fc19 100644 --- a/packages/kit/src/states/jotai/contexts/hyperliquid/utils/withToast.ts +++ b/packages/kit/src/states/jotai/contexts/hyperliquid/utils/withToast.ts @@ -1,5 +1,5 @@ import { Toast } from '@onekeyhq/components'; -import { perpsActiveAccountStatusInfoAtom } from '@onekeyhq/kit-bg/src/states/jotai/atoms'; +import backgroundApiProxy from '@onekeyhq/kit/src/background/instance/backgroundApiProxy'; import { ERROR_MESSAGES, ERROR_PATTERNS, TOAST_CONFIGS } from './config'; import { EErrorType } from './types'; @@ -37,15 +37,7 @@ async function handleError(error: unknown): Promise { if (errorType) { switch (errorType) { case EErrorType.INVALID_AGENT: { - const accountStatus = await perpsActiveAccountStatusInfoAtom.get(); - void perpsActiveAccountStatusInfoAtom.set({ - ...accountStatus, - canTrade: false, - details: { - ...accountStatus.details, - agentOk: false, - }, - }); + void backgroundApiProxy.serviceHyperliquid.checkPerpsAccountStatus(); break; } default: diff --git a/packages/kit/src/views/Perp/components/TradingPanel/modals/DepositWithdrawModal.tsx b/packages/kit/src/views/Perp/components/TradingPanel/modals/DepositWithdrawModal.tsx index a48471eee20..dc3730d84a6 100644 --- a/packages/kit/src/views/Perp/components/TradingPanel/modals/DepositWithdrawModal.tsx +++ b/packages/kit/src/views/Perp/components/TradingPanel/modals/DepositWithdrawModal.tsx @@ -354,12 +354,7 @@ function DepositWithdrawContent({ } } catch (error) { console.error(`[DepositWithdrawModal.${selectedAction}] Failed:`, error); - Toast.error({ - title: `${ - selectedAction === 'deposit' ? 'Deposit' : 'Withdraw' - } Failed`, - message: error instanceof Error ? error.message : 'Transaction failed', - }); + throw error; } finally { setIsSubmitting(false); } From 955ba1f5116b95c1ca4d7ff587c1dfa39fcdc6ed Mon Sep 17 00:00:00 2001 From: morizon Date: Sat, 27 Sep 2025 15:38:41 +0800 Subject: [PATCH 3/3] fix(perp): improve HyperLiquid agent credential cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Refactor shouldDeleteCredential method to use object parameters for better readability - Add delay and logic to prevent wallet-level deletion when account-specific deletion is requested - Fix parameter passing in cleanupOrphanedHyperLiquidAgentCredentials calls - Remove unnecessary walletId parameter when deleting specific accounts 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .../services/ServiceAccount/ServiceAccount.ts | 35 +++++++++++++++---- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/packages/kit-bg/src/services/ServiceAccount/ServiceAccount.ts b/packages/kit-bg/src/services/ServiceAccount/ServiceAccount.ts index c25799c4640..4891a004570 100644 --- a/packages/kit-bg/src/services/ServiceAccount/ServiceAccount.ts +++ b/packages/kit-bg/src/services/ServiceAccount/ServiceAccount.ts @@ -1355,14 +1355,17 @@ class ServiceAccount extends ServiceBase { return parts[1]; // userAddress } - private async shouldDeleteCredential( - addressRecord: IDBAddress | null, + private async shouldDeleteCredential({ + addressRecord, + deletedInfo, + }: { + addressRecord: IDBAddress | null; deletedInfo: { walletId?: string; indexedAccountId?: string; accountId?: string; - }, - ): Promise { + }; + }): Promise { if (!addressRecord) { return false; } @@ -1389,12 +1392,26 @@ class ServiceAccount extends ServiceBase { } @backgroundMethod() - async cleanupOrphanedHyperLiquidAgentCredentials(deletedInfo: { + async cleanupOrphanedHyperLiquidAgentCredentials({ + walletId, + indexedAccountId, + accountId, + }: { walletId?: string; indexedAccountId?: string; accountId?: string; }): Promise { try { + await timerUtils.wait(1000); + if (indexedAccountId || accountId) { + // eslint-disable-next-line no-param-reassign + walletId = undefined; + } + const deletedInfo = { + walletId, + indexedAccountId, + accountId, + }; // Get all HyperLiquid agent credentials const allCredentials = await localDb.getAllHyperLiquidAgentCredentials(); @@ -1414,7 +1431,12 @@ class ServiceAccount extends ServiceBase { }); // Check if this credential should be deleted - if (await this.shouldDeleteCredential(addressRecord, deletedInfo)) { + if ( + await this.shouldDeleteCredential({ + addressRecord, + deletedInfo, + }) + ) { credentialsToDelete.push(credential); } } catch (error) { @@ -3159,7 +3181,6 @@ class ServiceAccount extends ServiceBase { // Cleanup orphaned HyperLiquid agent credentials void this.cleanupOrphanedHyperLiquidAgentCredentials({ - walletId, accountId: account?.id, indexedAccountId: indexedAccount?.id, });