Skip to content

Commit

Permalink
aaaaaa
Browse files Browse the repository at this point in the history
  • Loading branch information
greg-schrammel committed May 24, 2024
1 parent 81b8f09 commit 968236d
Show file tree
Hide file tree
Showing 9 changed files with 85 additions and 98 deletions.
6 changes: 3 additions & 3 deletions src/__swaps__/screens/Swap/components/GasButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<Inline alignVertical="center" space="4px">
Expand Down Expand Up @@ -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`;
Expand Down
121 changes: 56 additions & 65 deletions src/__swaps__/screens/Swap/components/GasPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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';
Expand Down Expand Up @@ -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;
}) {
Expand Down Expand Up @@ -161,8 +161,27 @@ function CurrentBaseFee() {
);
}

type GasPanelState = { gasPrice?: string; maxBaseFee?: string; maxPriorityFee?: string };
const useGasPanelStore = createRainbowStore<GasPanelState | undefined>(() => undefined);

function useGasPanelState<Selected>(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<GasPanelState>) => useGasPanelStore.setState(update);

function EditMaxBaseFee() {
const maxBaseFee = useUnsavedCustomGasStore(s => s?.maxBaseFee);
const maxBaseFee = useGasPanelState(s => s?.maxBaseFee);
const { navigate } = useNavigation();

return (
Expand All @@ -171,14 +190,14 @@ function EditMaxBaseFee() {
<PressableLabel onPress={() => navigate(Routes.EXPLAIN_SHEET, { type: MAX_BASE_FEE_TYPE })}>
{i18n.t(i18n.l.gas.max_base_fee)}
</PressableLabel>
<GasSettingInput value={maxBaseFee} onChange={maxBaseFee => setUnsavedCustomGasStore({ maxBaseFee })} />
<GasSettingInput value={maxBaseFee} onDebouncedChange={maxBaseFee => setGasPanelState({ maxBaseFee })} />
</Inline>
);
}

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);
Expand All @@ -191,31 +210,36 @@ function EditPriorityFee() {
<PressableLabel onPress={() => navigate(Routes.EXPLAIN_SHEET, { type: MINER_TIP_TYPE })}>
{i18n.t(i18n.l.gas.miner_tip)}
</PressableLabel>
<GasSettingInput value={maxPriorityFee} onChange={maxPriorityFee => setUnsavedCustomGasStore({ maxPriorityFee })} min={min} />
<GasSettingInput value={maxPriorityFee} onDebouncedChange={maxPriorityFee => setGasPanelState({ maxPriorityFee })} min={min} />
</Inline>
);
}

// function EditGasPrice() {
// const gasPrice = useUnsavedCustomGasStore(s => s?.gasPrice || '0');
// const { navigate } = useNavigation();

// return (
// <Inline horizontalSpace="10px" alignVertical="center" alignHorizontal="justify">
// {/* TODO: Add error and warning values here */}
// <PressableLabel onPress={() => navigate(Routes.EXPLAIN_SHEET, { type: MAX_BASE_FEE_TYPE })}>
// {i18n.t(i18n.l.gas.max_base_fee)}
// </PressableLabel>
// <GasSettingInput value={gasPrice} onChange={gasPrice => setUnsavedCustomGasStore({ gasPrice })} />
// </Inline>
// );
// }
function EditGasPrice() {
const gasPrice = useGasPanelState(s => s?.gasPrice);
const { navigate } = useNavigation();

return (
<Inline horizontalSpace="10px" alignVertical="center" alignHorizontal="justify">
{/* TODO: Add error and warning values here */}
<PressableLabel onPress={() => navigate(Routes.EXPLAIN_SHEET, { type: MAX_BASE_FEE_TYPE })}>
{i18n.t(i18n.l.gas.max_base_fee)}
</PressableLabel>
<GasSettingInput value={gasPrice} onDebouncedChange={gasPrice => setGasPanelState({ gasPrice })} />
</Inline>
);
}

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 (
<Inline horizontalSpace="10px" alignVertical="center" alignHorizontal="justify">
Expand All @@ -239,19 +263,9 @@ function MaxTransactionFee() {
);
}

type UnsavedSetting = { type: 'suggestion' | 'user inputed' } & GasSettings;
const useUnsavedCustomGasStore = createRainbowStore<UnsavedSetting | undefined>(() => undefined);
const setUnsavedCustomGasStore = (settings: Partial<UnsavedSetting>) => {
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 <EditGasPrice />;
// const isEIP1559 = use;
// if (!isEIP1559) return <EditGasPrice />;
return (
<>
<EditMaxBaseFee />
Expand All @@ -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() {
Expand Down
2 changes: 1 addition & 1 deletion src/__swaps__/screens/Swap/components/ReviewPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<Text align="left" color={'label'} size="15pt" weight="heavy">
Expand Down
31 changes: 18 additions & 13 deletions src/__swaps__/screens/Swap/hooks/useCustomGas.ts
Original file line number Diff line number Diff line change
@@ -1,39 +1,44 @@
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<CustomGasStoreState>(() => ({}));

export const useCustomGasSettings = (chainId: ChainId) => useCustomGasStore(s => s[chainId]);
export const getCustomGasSettings = (chainId: ChainId) => useCustomGasStore.getState()[chainId];

const setCustomGasSettings = (chainId: ChainId, update: Partial<EIP1159GasSettings>) =>
const setCustomEIP1559GasSettings = (chainId: ChainId, update: Partial<EIP1159GasSettings>) =>
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<LegacyGasSettings>) =>
// 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<LegacyGasSettings>) =>
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<GasSettings>) => {
if ('gasPrice' in update && !!update.gasPrice) return setCustomLegacyGasSettings(chainId, update as Partial<LegacyGasSettings>);
return setCustomEIP1559GasSettings(chainId, update as Partial<EIP1159GasSettings>);
};

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 });
4 changes: 2 additions & 2 deletions src/__swaps__/screens/Swap/hooks/useEstimatedGasFee.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
})
Expand Down
4 changes: 1 addition & 3 deletions src/__swaps__/screens/Swap/hooks/useSwapNavigation.ts
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down Expand Up @@ -44,8 +44,6 @@ export function useSwapNavigation({
({ backToReview = false }: { backToReview?: boolean }) => {
'worklet';

runOnJS(onOpenGasPanel)();

if (backToReview) {
navigateBackToReview.value = true;
}
Expand Down
11 changes: 2 additions & 9 deletions src/__swaps__/types/gas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion src/__swaps__/utils/meteorology.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)}`;
},
Expand Down

0 comments on commit 968236d

Please sign in to comment.