diff --git a/packages/engine/src/proxy.ts b/packages/engine/src/proxy.ts index e20261a746d..b6eb1a47a77 100644 --- a/packages/engine/src/proxy.ts +++ b/packages/engine/src/proxy.ts @@ -341,6 +341,36 @@ class ProviderController extends BaseProviderController { prices: gasInfo.prices as EIP1559Fee[], }; } catch { + const result = await this.getClient(networkId).then((client) => + (client as Geth).rpc.batchCall<[string, { baseFeePerGas: string }]>([ + ['eth_maxPriorityFeePerGas', []], + ['eth_getBlockByNumber', ['pending', true]], + ]), + ); + // doc https://docs.alchemy.com/docs/maxpriorityfeepergas-vs-maxfeepergas#example-using-maxfeepergas-a-hreflets-see-them-in-action-idlets-see-them-in-actiona + if (result) { + const coefficients: string[] = ['1.13', '1.25', '1.3']; + const [maxPriorityFeePerGas, { baseFeePerGas }] = result; + const baseFee = new BigNumber(baseFeePerGas).shiftedBy(-9); + const maxPriorityFee = new BigNumber(maxPriorityFeePerGas).shiftedBy( + -9, + ); + + return { + prices: coefficients.map((coefficient) => { + const maxPriorityFeePerGasBN = maxPriorityFee.times(coefficient); + return { + baseFee: baseFee.toFixed(), + maxPriorityFeePerGas: maxPriorityFeePerGasBN.toFixed(), + maxFeePerGas: baseFee + .plus(maxPriorityFeePerGasBN) + // .minus(1) + .toFixed(), + }; + }), + }; + } + const { baseFeePerGas, reward, @@ -421,7 +451,7 @@ class ProviderController extends BaseProviderController { ...blockNativeGasInfo, }); } else { - reject(); + reject(new Error('failed to fetch gas info from API')); } } }); @@ -439,7 +469,7 @@ class ProviderController extends BaseProviderController { ...blockNativeGasInfo, }); } else { - reject(); + reject(new Error('failed to fetch gas info from API')); } } }); diff --git a/packages/kit/src/hooks/useShortcuts.ts b/packages/kit/src/hooks/useShortcuts.ts index 46d76763e10..243bbaac07f 100644 --- a/packages/kit/src/hooks/useShortcuts.ts +++ b/packages/kit/src/hooks/useShortcuts.ts @@ -45,7 +45,12 @@ export const useShortcuts = platformEnv.isDesktop ) { const { tabs } = getWebTabs(); if (tabs.length > 1) { - webTabsActions.closeWebTab(tabs[tabs.length - 1].id); + const curTab = tabs.find((tab) => tab.isCurrent); + if (curTab && curTab.id) { + webTabsActions.closeWebTab(curTab.id); + } else { + webTabsActions.closeWebTab(tabs[tabs.length - 1].id); + } } else { window.desktopApi.quitApp(); } diff --git a/packages/kit/src/views/Discover/Explorer/Desktop/TabBarDesktop.tsx b/packages/kit/src/views/Discover/Explorer/Desktop/TabBarDesktop.tsx index 6ab3280504a..ee54118a7cc 100644 --- a/packages/kit/src/views/Discover/Explorer/Desktop/TabBarDesktop.tsx +++ b/packages/kit/src/views/Discover/Explorer/Desktop/TabBarDesktop.tsx @@ -15,6 +15,7 @@ import { import { webTabsActions } from '../../../../store/observable/webTabs'; import { useWebTabs } from '../Controller/useWebTabs'; +import { dismissWebviewKeyboard } from '../explorerUtils'; import type { WebTab } from '../../../../store/observable/webTabs'; import type { LayoutChangeEvent } from 'react-native'; @@ -27,6 +28,10 @@ const Tab: FC< } > = ({ isCurrent, id, title, onLayout, favicon }) => { const setCurrentTab = useCallback(() => { + if (platformEnv.isNative) { + // hide the keyboard for active tab + dismissWebviewKeyboard(); + } webTabsActions.setCurrentWebTab(id); }, [id]); const closeTab = useCallback(() => { diff --git a/packages/kit/src/views/Discover/Explorer/explorerAnimation.ts b/packages/kit/src/views/Discover/Explorer/explorerAnimation.ts index 4a6f67c3bb7..5f65a4b6fe9 100644 --- a/packages/kit/src/views/Discover/Explorer/explorerAnimation.ts +++ b/packages/kit/src/views/Discover/Explorer/explorerAnimation.ts @@ -3,7 +3,11 @@ import { makeMutable, runOnJS, withTiming } from 'react-native-reanimated'; import { getCurrentTabId } from '../../../store/observable/webTabs'; import { getWebTabs } from './Controller/useWebTabs'; -import { pauseDappInteraction, resumeDappInteraction } from './explorerUtils'; +import { + dismissWebviewKeyboard, + pauseDappInteraction, + resumeDappInteraction, +} from './explorerUtils'; import type { View } from 'react-native'; // for mobile tab animations @@ -100,6 +104,7 @@ export const minimizeFloatingWindow = ({ after = () => {}, }: ExpandAnimationEvents) => { pauseDappInteraction(); + dismissWebviewKeyboard(); before?.(); setTimeout(() => { expandAnim.value = withTiming(MIN_OR_HIDE, { duration: 300 }, () => diff --git a/packages/kit/src/views/Discover/Explorer/explorerUtils.ts b/packages/kit/src/views/Discover/Explorer/explorerUtils.ts index bc21d9c9a9e..30f55bd9067 100644 --- a/packages/kit/src/views/Discover/Explorer/explorerUtils.ts +++ b/packages/kit/src/views/Discover/Explorer/explorerUtils.ts @@ -168,6 +168,42 @@ const injectToResumeWebsocket = ` })() `; +// for hide keyboard +const injectToDismissWebviewKeyboard = ` +(function(){ + document.activeElement && document.activeElement.blur() +})() +`; + +export function dismissWebviewKeyboard(id?: string) { + const ref = getWebviewWrapperRef(id); + if (ref) { + if (platformEnv.isNative) { + try { + (ref.innerRef as WebView)?.injectJavaScript( + injectToDismissWebviewKeyboard, + ); + } catch (error) { + // ipad mini orientation changed cause injectJavaScript ERROR, which crash app + console.error( + 'blurActiveElement webview.injectJavaScript() ERROR >>>>> ', + error, + ); + } + } + if (platformEnv.isDesktop) { + const deskTopRef = ref.innerRef as IElectronWebView; + if (deskTopRef) { + try { + deskTopRef.executeJavaScript(injectToDismissWebviewKeyboard); + } catch (e) { + // if not dom ready, no need to pause websocket + } + } + } + } +} + export function pauseDappInteraction(id?: string) { const ref = getWebviewWrapperRef(id); if (ref) { diff --git a/packages/kit/src/views/Discover/Home/DappRenderItem/index.tsx b/packages/kit/src/views/Discover/Home/DappRenderItem/index.tsx index eb32a313133..30e4a9a6cff 100644 --- a/packages/kit/src/views/Discover/Home/DappRenderItem/index.tsx +++ b/packages/kit/src/views/Discover/Home/DappRenderItem/index.tsx @@ -1,4 +1,4 @@ -import { type FC, type ReactElement, useCallback } from 'react'; +import { type FC, type ReactElement, cloneElement, useCallback } from 'react'; import { Box, Center, Typography } from '@onekeyhq/components'; import { NetworkIconGroup } from '@onekeyhq/kit/src/components/NetworkIconGroup'; @@ -109,21 +109,27 @@ export const DappItemPlain: FC = (props) => { justifyContent="space-between" alignItems="center" > - - - - - - - {title} - - - {description} - - - - - {rightElement} + {({ isPressed }) => ( + <> + + + + + + + {title} + + + {description} + + + + + + {rightElement ? cloneElement(rightElement, { isPressed }) : null} + + + )} ); diff --git a/packages/kit/src/views/Discover/Home/Desktop/index.tsx b/packages/kit/src/views/Discover/Home/Desktop/index.tsx index ebc4ce95891..02cfe57e58c 100644 --- a/packages/kit/src/views/Discover/Home/Desktop/index.tsx +++ b/packages/kit/src/views/Discover/Home/Desktop/index.tsx @@ -27,7 +27,7 @@ export const Desktop = () => { > } diff --git a/packages/kit/src/views/Discover/Home/TabFavorites/index.tsx b/packages/kit/src/views/Discover/Home/TabFavorites/index.tsx index cca66900500..56d25ba3e22 100644 --- a/packages/kit/src/views/Discover/Home/TabFavorites/index.tsx +++ b/packages/kit/src/views/Discover/Home/TabFavorites/index.tsx @@ -17,10 +17,18 @@ import { EmptySkeleton } from '../EmptySkeleton'; import type { MatchDAppItemType } from '../../Explorer/explorerUtils'; -const DappItemPlainFavMenu: FC<{ item: MatchDAppItemType }> = ({ item }) => ( +const DappItemPlainFavMenu: FC<{ + item: MatchDAppItemType; + isPressed?: boolean; +}> = ({ item, isPressed }) => ( - + ); diff --git a/packages/kit/src/views/Swap/components/Transaction/index.tsx b/packages/kit/src/views/Swap/components/Transaction/index.tsx index 368f935bf40..f9e5c8c1782 100644 --- a/packages/kit/src/views/Swap/components/Transaction/index.tsx +++ b/packages/kit/src/views/Swap/components/Transaction/index.tsx @@ -574,10 +574,10 @@ const Transaction: FC = ({ [intl], ); - const onPress = useCallback(() => { + const onPress = useCallback(async () => { if (from && to && fromNetwork && toNetwork) { - backgroundApiProxy.serviceSwap.setInputToken(from.token); - backgroundApiProxy.serviceSwap.setOutputToken(to.token); + await backgroundApiProxy.serviceSwap.setInputToken(from.token); + await backgroundApiProxy.serviceSwap.setOutputToken(to.token); const parent = navigation.getParent() ?? navigation; parent.goBack();