From 968236d9120077f2cbc266493ac6890e42091866 Mon Sep 17 00:00:00 2001 From: gregs Date: Fri, 24 May 2024 12:57:15 -0300 Subject: [PATCH] aaaaaa --- .../screens/Swap/components/GasButton.tsx | 6 +- .../screens/Swap/components/GasPanel.tsx | 121 ++++++++---------- .../screens/Swap/components/ReviewPanel.tsx | 2 +- .../screens/Swap/hooks/useCustomGas.ts | 31 +++-- .../screens/Swap/hooks/useEstimatedGasFee.ts | 4 +- .../Swap/hooks/useSwapEstimatedGasLimit.ts | 2 +- .../screens/Swap/hooks/useSwapNavigation.ts | 4 +- src/__swaps__/types/gas.ts | 11 +- src/__swaps__/utils/meteorology.ts | 2 +- 9 files changed, 85 insertions(+), 98 deletions(-) diff --git a/src/__swaps__/screens/Swap/components/GasButton.tsx b/src/__swaps__/screens/Swap/components/GasButton.tsx index 5e1562a5a9b..933b9d4c0c1 100644 --- a/src/__swaps__/screens/Swap/components/GasButton.tsx +++ b/src/__swaps__/screens/Swap/components/GasButton.tsx @@ -21,12 +21,12 @@ import { useSwapEstimatedGasFee } from '../hooks/useEstimatedGasFee'; import { GasSpeed, setSelectedGasSpeed, useSelectedGas, useSelectedGasSpeed } from '../hooks/useSelectedGas'; import { useSwapContext } from '../providers/swap-provider'; -const { CUSTOM, GAS_ICONS } = gasUtils; +const { GAS_ICONS } = gasUtils; function EstimatedGasFee() { const chainId = useSwapsStore(s => s.inputAsset?.chainId || ChainId.mainnet); const gasSettings = useSelectedGas(chainId); - const estimatedGasFee = useSwapEstimatedGasFee({ gasSettings }); + const estimatedGasFee = useSwapEstimatedGasFee(gasSettings); return ( @@ -68,7 +68,7 @@ const GasSpeedPagerCentered = styled(Centered).attrs(() => ({ function getEstimatedFeeRangeInGwei(gasSettings: GasSettings | undefined, currentBaseFee?: string | undefined) { if (!gasSettings) return undefined; - // if (!gasSettings.isEIP1559) return `${formatNumber(weiToGwei(gasSettings.gasPrice))} Gwei`; + if (!gasSettings.isEIP1559) return `${formatNumber(weiToGwei(gasSettings.gasPrice))} Gwei`; const { maxBaseFee, maxPriorityFee } = gasSettings; return `${formatNumber(weiToGwei(add(maxBaseFee, maxPriorityFee)))} Gwei`; diff --git a/src/__swaps__/screens/Swap/components/GasPanel.tsx b/src/__swaps__/screens/Swap/components/GasPanel.tsx index afc447191d4..9b37a49f532 100644 --- a/src/__swaps__/screens/Swap/components/GasPanel.tsx +++ b/src/__swaps__/screens/Swap/components/GasPanel.tsx @@ -6,7 +6,7 @@ import { fadeConfig } from '@/__swaps__/screens/Swap/constants'; import { NavigationSteps, useSwapContext } from '@/__swaps__/screens/Swap/providers/swap-provider'; import { ChainId } from '@/__swaps__/types/chains'; import { gweiToWei, weiToGwei } from '@/__swaps__/utils/ethereum'; -import { getCachedGasSuggestions, useBaseFee, useGasTrend } from '@/__swaps__/utils/meteorology'; +import { useBaseFee, useGasTrend, useMeteorologySuggestions } from '@/__swaps__/utils/meteorology'; import { add, subtract } from '@/__swaps__/utils/numbers'; import { ButtonPressAnimation } from '@/components/animations'; import { Box, Inline, Separator, Stack, Text, globalColors, useColorMode } from '@/design-system'; @@ -18,9 +18,9 @@ import { createRainbowStore } from '@/state/internal/createRainbowStore'; import { useSwapsStore } from '@/state/swaps/swapsStore'; import { upperFirst } from 'lodash'; import { formatNumber } from '../hooks/formatNumber'; -import { GasSettings, getCustomGasSettings, useCustomGasStore } from '../hooks/useCustomGas'; +import { GasSettings, setCustomGasSettings } from '../hooks/useCustomGas'; import { useSwapEstimatedGasFee } from '../hooks/useEstimatedGasFee'; -import { getSelectedGasSpeed, setSelectedGasSpeed } from '../hooks/useSelectedGas'; +import { setSelectedGasSpeed, useSelectedGasSpeed } from '../hooks/useSelectedGas'; const MINER_TIP_TYPE = 'minerTip'; const MAX_BASE_FEE_TYPE = 'maxBaseFee'; @@ -85,11 +85,11 @@ function NumericInputButton({ children, onPress }: PropsWithChildren<{ onPress: const INPUT_STEP = gweiToWei('0.1'); function GasSettingInput({ - onChange, + onDebouncedChange: onChange, min = '0', value = min || '0', }: { - onChange: (v: string) => void; + onDebouncedChange: (v: string) => void; value: string | undefined; min?: string; }) { @@ -161,8 +161,27 @@ function CurrentBaseFee() { ); } +type GasPanelState = { gasPrice?: string; maxBaseFee?: string; maxPriorityFee?: string }; +const useGasPanelStore = createRainbowStore(() => undefined); + +function useGasPanelState(selector: (s: GasPanelState | undefined) => Selected = s => s as Selected) { + const state = useGasPanelStore(selector); + + const chainId = useSwapsStore(s => s.inputAsset?.chainId || ChainId.mainnet); + const selectedSpeed = useSelectedGasSpeed(chainId); + const { data: placeholder } = useMeteorologySuggestions({ + chainId, + select: d => selector(selectedSpeed === 'custom' ? undefined : d[selectedSpeed]), + enabled: !state && selectedSpeed !== 'custom', + }); + + return state ?? placeholder; +} + +const setGasPanelState = (update: Partial) => useGasPanelStore.setState(update); + function EditMaxBaseFee() { - const maxBaseFee = useUnsavedCustomGasStore(s => s?.maxBaseFee); + const maxBaseFee = useGasPanelState(s => s?.maxBaseFee); const { navigate } = useNavigation(); return ( @@ -171,14 +190,14 @@ function EditMaxBaseFee() { navigate(Routes.EXPLAIN_SHEET, { type: MAX_BASE_FEE_TYPE })}> {i18n.t(i18n.l.gas.max_base_fee)} - setUnsavedCustomGasStore({ maxBaseFee })} /> + setGasPanelState({ maxBaseFee })} /> ); } const MIN_FLASHBOTS_PRIORITY_FEE = gweiToWei('6'); function EditPriorityFee() { - const maxPriorityFee = useUnsavedCustomGasStore(s => s?.maxPriorityFee); + const maxPriorityFee = useGasPanelState(s => s?.maxPriorityFee); const { navigate } = useNavigation(); const isFlashbotsEnabled = useSwapsStore(s => s.flashbots); @@ -191,31 +210,36 @@ function EditPriorityFee() { navigate(Routes.EXPLAIN_SHEET, { type: MINER_TIP_TYPE })}> {i18n.t(i18n.l.gas.miner_tip)} - setUnsavedCustomGasStore({ maxPriorityFee })} min={min} /> + setGasPanelState({ maxPriorityFee })} min={min} /> ); } -// function EditGasPrice() { -// const gasPrice = useUnsavedCustomGasStore(s => s?.gasPrice || '0'); -// const { navigate } = useNavigation(); - -// return ( -// -// {/* TODO: Add error and warning values here */} -// navigate(Routes.EXPLAIN_SHEET, { type: MAX_BASE_FEE_TYPE })}> -// {i18n.t(i18n.l.gas.max_base_fee)} -// -// setUnsavedCustomGasStore({ gasPrice })} /> -// -// ); -// } +function EditGasPrice() { + const gasPrice = useGasPanelState(s => s?.gasPrice); + const { navigate } = useNavigation(); + + return ( + + {/* TODO: Add error and warning values here */} + navigate(Routes.EXPLAIN_SHEET, { type: MAX_BASE_FEE_TYPE })}> + {i18n.t(i18n.l.gas.max_base_fee)} + + setGasPanelState({ gasPrice })} /> + + ); +} +const stateToGasSettings = (s: GasPanelState | undefined): GasSettings | undefined => { + if (!s) return; + if (s.gasPrice) return { isEIP1559: false, gasPrice: s.gasPrice || '0' }; + return { isEIP1559: true, maxBaseFee: s.maxBaseFee || '0', maxPriorityFee: s.maxPriorityFee || '0' }; +}; function MaxTransactionFee() { const { isDarkMode } = useColorMode(); - const gasSettings = useUnsavedCustomGasStore(); - const maxTransactionFee = useSwapEstimatedGasFee({ gasSettings }); + const gasSettings = useGasPanelStore(stateToGasSettings); + const maxTransactionFee = useSwapEstimatedGasFee(gasSettings); return ( @@ -239,19 +263,9 @@ function MaxTransactionFee() { ); } -type UnsavedSetting = { type: 'suggestion' | 'user inputed' } & GasSettings; -const useUnsavedCustomGasStore = createRainbowStore(() => undefined); -const setUnsavedCustomGasStore = (settings: Partial) => { - useUnsavedCustomGasStore.setState(s => ({ - isEIP1559: true, - type: 'user inputed', - maxBaseFee: settings.maxBaseFee || s?.maxBaseFee || '0', - maxPriorityFee: settings.maxPriorityFee || s?.maxPriorityFee || '0', - })); -}; - function EditableGasSettings() { - // if (settings && !settings.isEIP1559) return ; + // const isEIP1559 = use; + // if (!isEIP1559) return ; return ( <> @@ -260,39 +274,16 @@ function EditableGasSettings() { ); } -export function onOpenGasPanel() { - /* - when opening the gas panel, and the previously selected speed was NOT custom, - we prefill the custom gas settings with the selected suggestion - when closing this panel, if the user didn't modify the settings, we keep the selected gas speed the same as before - - ex: was on fast, taps custom, don't change anything and closes, we keep the selected speed as fast - */ - const chainId = useSwapsStore.getState().inputAsset?.chainId || ChainId.mainnet; - const selectedSpeed = getSelectedGasSpeed(chainId); - const suggestions = getCachedGasSuggestions(chainId); - - const customGasSettings = getCustomGasSettings(chainId); - if (selectedSpeed === 'custom' && customGasSettings) { - useUnsavedCustomGasStore.setState({ ...customGasSettings, type: 'user inputed' }); - return; - } - - const suggestion = suggestions?.[selectedSpeed === 'custom' ? 'fast' : selectedSpeed]; - if (!suggestion || !suggestion.isEIP1559) return; - - useUnsavedCustomGasStore.setState({ ...suggestion, type: 'suggestion' }); -} - function saveCustomGasSettings() { - const unsaved = useUnsavedCustomGasStore.getState(); - console.log({ unsaved }); - if (!unsaved || unsaved.type === 'suggestion') return; + const unsaved = useGasPanelStore.getState(); + // input is debounced if the time between editing and closing the panel is less than the debounce time (500ms) it's gonna be outdated + if (!unsaved) return; const { inputAsset } = useSwapsStore.getState(); const chainId = inputAsset?.chainId || ChainId.mainnet; - useCustomGasStore.setState({ [chainId]: unsaved }); + setCustomGasSettings(chainId, unsaved); setSelectedGasSpeed(chainId, 'custom'); + useGasPanelStore.setState(undefined); } export function onCloseGasPanel() { diff --git a/src/__swaps__/screens/Swap/components/ReviewPanel.tsx b/src/__swaps__/screens/Swap/components/ReviewPanel.tsx index 3fe201952bf..392c632d1f0 100644 --- a/src/__swaps__/screens/Swap/components/ReviewPanel.tsx +++ b/src/__swaps__/screens/Swap/components/ReviewPanel.tsx @@ -89,7 +89,7 @@ const RainbowFee = () => { function EstimatedGasFee() { const chainId = useSwapsStore(s => s.inputAsset?.chainId || ChainId.mainnet); const gasSettings = useSelectedGas(chainId); - const estimatedGasFee = useSwapEstimatedGasFee({ gasSettings }); + const estimatedGasFee = useSwapEstimatedGasFee(gasSettings); return ( diff --git a/src/__swaps__/screens/Swap/hooks/useCustomGas.ts b/src/__swaps__/screens/Swap/hooks/useCustomGas.ts index 61d811c55a8..c386cc65b12 100644 --- a/src/__swaps__/screens/Swap/hooks/useCustomGas.ts +++ b/src/__swaps__/screens/Swap/hooks/useCustomGas.ts @@ -1,18 +1,18 @@ import { ChainId } from '@/__swaps__/types/chains'; import { createRainbowStore } from '@/state/internal/createRainbowStore'; -type EIP1159GasSettings = { +export type EIP1159GasSettings = { isEIP1559: true; maxBaseFee: string; maxPriorityFee: string; }; -type LegacyGasSettings = { +export type LegacyGasSettings = { isEIP1559: false; gasPrice: string; }; -export type GasSettings = EIP1159GasSettings; // | LegacyGasSettings; +export type GasSettings = EIP1159GasSettings | LegacyGasSettings; export type CustomGasStoreState = { [c in ChainId]?: GasSettings }; export const useCustomGasStore = createRainbowStore(() => ({})); @@ -20,20 +20,25 @@ export const useCustomGasStore = createRainbowStore(() => ( export const useCustomGasSettings = (chainId: ChainId) => useCustomGasStore(s => s[chainId]); export const getCustomGasSettings = (chainId: ChainId) => useCustomGasStore.getState()[chainId]; -const setCustomGasSettings = (chainId: ChainId, update: Partial) => +const setCustomEIP1559GasSettings = (chainId: ChainId, update: Partial) => useCustomGasStore.setState(s => { const state = s[chainId] || { isEIP1559: true, maxBaseFee: '0', maxPriorityFee: '0' }; if (!state.isEIP1559) return s; return { [chainId]: { ...state, ...update } }; }); -// const setCustomLegacyGasSettings = (chainId: ChainId, update: Partial) => -// useCustomGasStore.setState(s => { -// const state = s[chainId] || { isEIP1559: false, gasPrice: '0' }; -// if (state.isEIP1559) return s; -// return { [chainId]: { ...state, ...update } }; -// }); +const setCustomLegacyGasSettings = (chainId: ChainId, update: Partial) => + useCustomGasStore.setState(s => { + const state = s[chainId] || { isEIP1559: false, gasPrice: '0' }; + if (state.isEIP1559) return s; + return { [chainId]: { ...state, ...update } }; + }); + +export const setCustomGasSettings = (chainId: ChainId, update: Partial) => { + if ('gasPrice' in update && !!update.gasPrice) return setCustomLegacyGasSettings(chainId, update as Partial); + return setCustomEIP1559GasSettings(chainId, update as Partial); +}; -export const setCustomMaxBaseFee = (chainId: ChainId, maxBaseFee = '0') => setCustomGasSettings(chainId, { maxBaseFee }); -export const setCustomMaxPriorityFee = (chainId: ChainId, maxPriorityFee = '0') => setCustomGasSettings(chainId, { maxPriorityFee }); -// export const setCustomGasPrice = (chainId: ChainId, gasPrice = '0') => setCustomLegacyGasSettings(chainId, { gasPrice }); +export const setCustomMaxBaseFee = (chainId: ChainId, maxBaseFee = '0') => setCustomEIP1559GasSettings(chainId, { maxBaseFee }); +export const setCustomMaxPriorityFee = (chainId: ChainId, maxPriorityFee = '0') => setCustomEIP1559GasSettings(chainId, { maxPriorityFee }); +export const setCustomGasPrice = (chainId: ChainId, gasPrice = '0') => setCustomLegacyGasSettings(chainId, { gasPrice }); diff --git a/src/__swaps__/screens/Swap/hooks/useEstimatedGasFee.ts b/src/__swaps__/screens/Swap/hooks/useEstimatedGasFee.ts index 7ecb2159c03..6e01456917b 100644 --- a/src/__swaps__/screens/Swap/hooks/useEstimatedGasFee.ts +++ b/src/__swaps__/screens/Swap/hooks/useEstimatedGasFee.ts @@ -22,7 +22,7 @@ export function useEstimatedGasFee({ if (!gasLimit || !gasSettings || !nativeNetworkAsset) return 'Loading...'; // TODO: loading state - const amount = gasSettings.isEIP1559 ? add(gasSettings.maxBaseFee, gasSettings.maxPriorityFee) : '0'; // gasSettings.gasPrice; + const amount = gasSettings.isEIP1559 ? add(gasSettings.maxBaseFee, gasSettings.maxPriorityFee) : gasSettings.gasPrice; const totalWei = multiply(gasLimit, amount); const nativePrice = nativeNetworkAsset.price.value?.toString(); @@ -35,7 +35,7 @@ export function useEstimatedGasFee({ return formatCurrency(feeInUserCurrency); } -export function useSwapEstimatedGasFee({ gasSettings }: { gasSettings: GasSettings | undefined }) { +export function useSwapEstimatedGasFee(gasSettings: GasSettings | undefined) { const chainId = useSwapsStore(s => s.inputAsset?.chainId || ChainId.mainnet); const assetToSell = useSwapsStore(s => s.inputAsset); diff --git a/src/__swaps__/screens/Swap/hooks/useSwapEstimatedGasLimit.ts b/src/__swaps__/screens/Swap/hooks/useSwapEstimatedGasLimit.ts index 253c3a2384b..905a2ae1c58 100644 --- a/src/__swaps__/screens/Swap/hooks/useSwapEstimatedGasLimit.ts +++ b/src/__swaps__/screens/Swap/hooks/useSwapEstimatedGasLimit.ts @@ -42,7 +42,7 @@ async function estimateSwapGasLimitQueryFunction({ const gasLimit = await (quote.swapType === SwapType.crossChain ? estimateUnlockAndCrosschainSwap({ chainId, - quote, + quote: quote as CrosschainQuote, sellAmount: quote.sellAmount.toString(), assetToSell, }) diff --git a/src/__swaps__/screens/Swap/hooks/useSwapNavigation.ts b/src/__swaps__/screens/Swap/hooks/useSwapNavigation.ts index b3cac3724a0..567f71737ad 100644 --- a/src/__swaps__/screens/Swap/hooks/useSwapNavigation.ts +++ b/src/__swaps__/screens/Swap/hooks/useSwapNavigation.ts @@ -1,6 +1,6 @@ import { useCallback } from 'react'; import { SharedValue, runOnJS, useSharedValue } from 'react-native-reanimated'; -import { onCloseGasPanel, onOpenGasPanel } from '../components/GasPanel'; +import { onCloseGasPanel } from '../components/GasPanel'; import { useSwapInputsController } from './useSwapInputsController'; export const enum NavigationSteps { @@ -44,8 +44,6 @@ export function useSwapNavigation({ ({ backToReview = false }: { backToReview?: boolean }) => { 'worklet'; - runOnJS(onOpenGasPanel)(); - if (backToReview) { navigateBackToReview.value = true; } diff --git a/src/__swaps__/types/gas.ts b/src/__swaps__/types/gas.ts index b9d9d9fb964..dbbe7584285 100644 --- a/src/__swaps__/types/gas.ts +++ b/src/__swaps__/types/gas.ts @@ -48,18 +48,11 @@ export type GasFeeParamsBySpeed = { }; export interface BlocksToConfirmationByPriorityFee { - 1: string; - 2: string; - 3: string; - 4: string; + [priorityFee: string]: string; } export interface BlocksToConfirmationByBaseFee { - 4: string; - 8: string; - 40: string; - 120: string; - 240: string; + [baseFee: string]: string; } export interface BlocksToConfirmation { diff --git a/src/__swaps__/utils/meteorology.ts b/src/__swaps__/utils/meteorology.ts index c719e129c45..e31392fc103 100644 --- a/src/__swaps__/utils/meteorology.ts +++ b/src/__swaps__/utils/meteorology.ts @@ -195,7 +195,7 @@ export function useEstimatedTime({ chainId, speed }: { chainId: ChainId; speed: const gasSettings = getGasSettings(speed, chainId); if (!gasSettings?.isEIP1559) return undefined; const value = findClosestValue(gasSettings.maxPriorityFee, Object.values(data.confirmationTimeByPriorityFee)); - const [time] = Object.entries(data.confirmationTimeByPriorityFee).find(([ms, v]) => v === value) || []; + const [time] = Object.entries(data.confirmationTimeByPriorityFee).find(([, v]) => v === value) || []; if (!time) return undefined; return `${+time >= 3600 ? '>' : '~'} ${getMinimalTimeUnitStringForMs(+time * 1000)}`; },