Skip to content

Commit

Permalink
Improve nonce management logic for private mempool handling (#6277)
Browse files Browse the repository at this point in the history
* Add support for default private mempool timeout of 2 minutes

* fix: rename chainsPrivateMempoolTimout

* Use existing timestamp to update tx timestamp for new pending txns or updating pending txns

* Update nonce management logic

* Wrap latest and pending tx count calls in Promise.all

* Add support for batched provider

* Use batched provider in nonce manager logic

* Update getNextNonce forloop exit

* Fix: handle when localNonce not set yet

* Remove nonce logic for flashbots from pending txn watcher

* Remove flashbots toggle from swap review panel

* Remove flashbots from swap-provider

* Remove flashbots logic from swap gas panel

* Remove flashbots from swap settings and meteorology

* Remove flashbots enabled from redux and global settings

* Remove flashbots from speedup and cancel sheet and redux gas

* Remove flashbots from explain sheet

* Remove flashbots from raps

* Remove getFlashbotsProvider

* Remove flashbots from remote config defaults

* Remove flashbots from txns parser

* Remove flashbots row from swap settings panel

* Remove flashbots from animated swap styles

* Remove supported flashbots chain ids list

* Remove flashbots in analytics and experimental config

* Remove flashbots from GasSpeedButton and FeesPanel

* Remove flashbots min tip constant

* Remove en_US flashbots copy

* Adding new txn to behave similar to updating txns in order to handle new txns that are using a gapped nonce

* Fix addPendingTxn to ensure pending txns are ordered by nonce

* Simplify updateTransaction which matches addNewTransaction

* Support pendingTransactions function for returning txns in recent first order

* Cleanup sort function

* Fix: setNonce only when nonce is greater than currentNonce now that addNewtx and updateTxn have been consolidated and a gapped nonce can be picked up

* Set up HARDHAT_RPC_URL constant

* Fix: array sort sorts in place

* Remove flashbots from latest changes for navigateToSwaps

* Add a comment for getNextNonce logic

* Remove unnecessary updating of nonces from pending txn watcher as it clobbers over data during for loop

* Fix: off by one error when comparing local nonce with pending txn count

* Remove flashbots reference
  • Loading branch information
jinchung authored Dec 10, 2024
1 parent 7b33b8d commit 044daae
Show file tree
Hide file tree
Showing 44 changed files with 167 additions and 566 deletions.
8 changes: 2 additions & 6 deletions src/__swaps__/screens/Swap/components/GasPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as i18n from '@/languages';
import React, { PropsWithChildren, ReactNode, useMemo } from 'react';
import Animated, { runOnJS, useAnimatedReaction, useAnimatedStyle, withDelay, withSpring } from 'react-native-reanimated';

import { MIN_FLASHBOTS_PRIORITY_FEE, THICK_BORDER_WIDTH } from '@/__swaps__/screens/Swap/constants';
import { THICK_BORDER_WIDTH } from '@/__swaps__/screens/Swap/constants';
import { NavigationSteps, useSwapContext } from '@/__swaps__/screens/Swap/providers/swap-provider';
import { ChainId } from '@/chains/types';
import { GasSpeed } from '@/__swaps__/types/gas';
Expand Down Expand Up @@ -318,18 +318,14 @@ function EditMaxBaseFee() {

function EditPriorityFee() {
const { navigate } = useNavigation();

const isFlashbotsEnabled = useSwapsStore(s => s.flashbots);
const min = isFlashbotsEnabled ? MIN_FLASHBOTS_PRIORITY_FEE : '0';

const maxPriorityFee = useGasPanelState('maxPriorityFee');

return (
<Inline horizontalSpace="10px" alignVertical="center" alignHorizontal="justify">
<PressableLabel onPress={() => navigate(Routes.EXPLAIN_SHEET, { type: MINER_TIP_TYPE })}>
{i18n.t(i18n.l.gas.miner_tip)}
</PressableLabel>
<GasSettingInput value={maxPriorityFee} onChange={maxPriorityFee => setGasPanelState({ maxPriorityFee })} min={min} />
<GasSettingInput value={maxPriorityFee} onChange={maxPriorityFee => setGasPanelState({ maxPriorityFee })} min={'0'} />
</Inline>
);
}
Expand Down
69 changes: 0 additions & 69 deletions src/__swaps__/screens/Swap/components/ReviewPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ import Animated, {
import { REVIEW_SHEET_ROW_HEIGHT, THICK_BORDER_WIDTH } from '../constants';
import { useSelectedGasSpeed } from '../hooks/useSelectedGas';
import { NavigationSteps, useSwapContext } from '../providers/swap-provider';
import { AnimatedSwitch } from './AnimatedSwitch';
import { EstimatedSwapGasFee, EstimatedSwapGasFeeSlot } from './EstimatedSwapGasFee';
import { UnmountOnAnimatedReaction } from './UnmountOnAnimatedReaction';
import { chainsLabel, chainsNativeAsset } from '@/chains';
Expand All @@ -51,7 +50,6 @@ const NETWORK_LABEL = i18n.t(i18n.l.settings.network);
const MINIMUM_RECEIVED_LABEL = i18n.t(i18n.l.expanded_state.swap_details_v2.minimum_received);
const MAXIMUM_SOLD_LABEL = i18n.t(i18n.l.expanded_state.swap_details_v2.maximum_sold);
const RAINBOW_FEE_LABEL = i18n.t(i18n.l.expanded_state.swap_details_v2.rainbow_fee);
const FLASHBOTS_PROTECTION_LABEL = i18n.t(i18n.l.swap.flashbots_protection);
const MAX_SLIPPAGE_LABEL = i18n.t(i18n.l.exchange.slippage_tolerance);
const ESTIMATED_NETWORK_FEE_LABEL = i18n.t(i18n.l.gas.network_fee);

Expand Down Expand Up @@ -126,71 +124,6 @@ function EstimatedArrivalTime() {
);
}

function FlashbotsToggle() {
const { SwapSettings } = useSwapContext();

return (
<AnimatedSwitch
onToggle={SwapSettings.onToggleFlashbots}
value={SwapSettings.flashbots}
activeLabel={i18n.t(i18n.l.expanded_state.swap.on)}
inactiveLabel={i18n.t(i18n.l.expanded_state.swap.off)}
/>
);
}

export const FlashbotsRow = () => {
const { navigate } = useNavigation();
const { internalSelectedInputAsset } = useSwapContext();

const labelTertiary = useForegroundColor('labelTertiary');

const flashbotsVisibilityStyle = useAnimatedStyle(() => {
const shouldDisplay = (internalSelectedInputAsset.value?.chainId ?? ChainId.mainnet) === ChainId.mainnet;
return {
display: shouldDisplay ? 'flex' : 'none',
};
});

const openFlashbotsExplainer = useCallback(() => {
navigate(Routes.EXPLAIN_SHEET, {
type: 'flashbots',
});
}, [navigate]);

return (
<Animated.View style={[flashbotsVisibilityStyle, { height: REVIEW_SHEET_ROW_HEIGHT, justifyContent: 'center' }]}>
<Inline wrap={false} horizontalSpace="10px" alignVertical="center" alignHorizontal="justify">
<Inline wrap={false} horizontalSpace="12px">
<TextIcon color="labelTertiary" height={9} size="icon 13px" weight="bold" width={16}>
􀋦
</TextIcon>
<Inline wrap={false} horizontalSpace="4px">
<Text color="labelTertiary" weight="semibold" size="15pt">
{FLASHBOTS_PROTECTION_LABEL}
</Text>
<Bleed space="12px">
<ButtonPressAnimation onPress={openFlashbotsExplainer} scaleTo={0.8}>
<Text
align="center"
color={{ custom: opacity(labelTertiary, 0.24) }}
size="icon 13px"
style={{ padding: 12, top: 0.5 }}
weight="semibold"
>
􀅴
</Text>
</ButtonPressAnimation>
</Bleed>
</Inline>
</Inline>

<FlashbotsToggle />
</Inline>
</Animated.View>
);
};

export const SlippageRow = () => {
const { navigate } = useNavigation();
const { SwapSettings } = useSwapContext();
Expand Down Expand Up @@ -439,8 +372,6 @@ export function ReviewPanel() {

<Separator color={{ custom: opacity(separator, 0.03) }} thickness={THICK_BORDER_WIDTH} />

<FlashbotsRow />

<SlippageRow />

<Separator color={{ custom: opacity(separator, 0.03) }} thickness={THICK_BORDER_WIDTH} />
Expand Down
3 changes: 1 addition & 2 deletions src/__swaps__/screens/Swap/components/SettingsPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { THICK_BORDER_WIDTH } from '../constants';
import { NavigationSteps, useSwapContext } from '../providers/swap-provider';
import { AnimatedSwitch } from './AnimatedSwitch';
import { GestureHandlerButton } from './GestureHandlerButton';
import { FlashbotsRow, SlippageRow } from './ReviewPanel';
import { SlippageRow } from './ReviewPanel';

const PreferredNetworkMenu = () => {
const preferredNetwork = useSwapsStore(state => state.preferredNetwork);
Expand Down Expand Up @@ -98,7 +98,6 @@ export function SettingsPanel() {

<Box gap={28} paddingHorizontal="12px" width="full">
<Animated.View style={[degenSettingsVisibilityStyle, { gap: 28 }]}>
<FlashbotsRow />
<SlippageRow />
<Separator color={{ custom: opacity(separator, 0.03) }} thickness={THICK_BORDER_WIDTH} />
</Animated.View>
Expand Down
3 changes: 0 additions & 3 deletions src/__swaps__/screens/Swap/constants.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { gweiToWei } from '@/parsers';
import { getDefaultKeyboardHeight } from '@/redux/keyboardHeight';
import { deviceUtils, safeAreaInsetValues } from '@/utils';
import { Easing, WithSpringConfig, WithTimingConfig } from 'react-native-reanimated';
Expand Down Expand Up @@ -85,5 +84,3 @@ export const highPriceImpactThreshold = 0.05;
export const severePriceImpactThreshold = 0.1;

export const slippageStep = 0.5;

export const MIN_FLASHBOTS_PRIORITY_FEE = gweiToWei('6');
7 changes: 1 addition & 6 deletions src/__swaps__/screens/Swap/hooks/useAnimatedSwapStyles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import { safeAreaInsetValues } from '@/utils';
import { getSoftMenuBarHeight } from 'react-native-extra-dimensions-android';
import { DerivedValue, SharedValue, interpolate, useAnimatedStyle, useDerivedValue, withSpring, withTiming } from 'react-native-reanimated';
import { NavigationSteps } from './useSwapNavigation';
import { ChainId } from '@/chains/types';
import { SPRING_CONFIGS, TIMING_CONFIGS } from '@/components/animations/animationConfigs';

const INSET_BOTTOM = IS_ANDROID ? getSoftMenuBarHeight() - 24 : safeAreaInsetValues.bottom + 16;
Expand Down Expand Up @@ -169,15 +168,11 @@ export function useAnimatedSwapStyles({
const isSettingsOpen = configProgress.value === NavigationSteps.SHOW_SETTINGS;
const isBottomSheetOpen = isReviewing || isSettingsOpen || configProgress.value === NavigationSteps.SHOW_GAS;

const shouldHideFlashbotsRow = (internalSelectedInputAsset.value?.chainId ?? ChainId.mainnet) !== ChainId.mainnet;

let heightForCurrentSheet = HEIGHT_FOR_PANEL[configProgress.value];
if (isReviewing && shouldHideFlashbotsRow) {
// Remove height when the Flashbots row in the review sheet is hidden
if (isReviewing) {
heightForCurrentSheet -= REVIEW_SHEET_ROW_HEIGHT + REVIEW_SHEET_ROW_GAP;
} else if (degenMode.value && isSettingsOpen && swapInfo.value.areBothAssetsSet) {
heightForCurrentSheet += REVIEW_SHEET_ROW_HEIGHT + SETTINGS_SHEET_ROW_GAP * 2 + THICK_BORDER_WIDTH;
if (!shouldHideFlashbotsRow) heightForCurrentSheet += REVIEW_SHEET_ROW_HEIGHT + SETTINGS_SHEET_ROW_GAP;
}

return {
Expand Down
13 changes: 0 additions & 13 deletions src/__swaps__/screens/Swap/hooks/useSwapSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,15 @@ import { swapsStore } from '@/state/swaps/swapsStore';
import { runOnJS, SharedValue, useSharedValue } from 'react-native-reanimated';

export const useSwapSettings = ({ debouncedFetchQuote, slippage }: { debouncedFetchQuote: () => void; slippage: SharedValue<string> }) => {
const flashbots = useSharedValue(swapsStore.getState().flashbots);
const degenMode = useSharedValue(swapsStore.getState().degenMode);

const setSlippage = swapsStore(state => state.setSlippage);
const setFlashbots = swapsStore(state => state.setFlashbots);

const setDegenMode = (value: boolean) => {
swapsStore.getState().setDegenMode(value);
analyticsV2.track(analyticsV2.event.swapsToggledDegenMode, { enabled: value });
};

const onToggleFlashbots = () => {
'worklet';

const current = flashbots.value;
flashbots.value = !current;
runOnJS(setFlashbots)(!current);
};

const onUpdateSlippage = (operation: 'plus' | 'minus') => {
'worklet';

Expand Down Expand Up @@ -51,11 +41,8 @@ export const useSwapSettings = ({ debouncedFetchQuote, slippage }: { debouncedFe
};

return {
flashbots,
slippage,
degenMode,

onToggleFlashbots,
onUpdateSlippage,
onToggleDegenMode,
};
Expand Down
2 changes: 1 addition & 1 deletion src/__swaps__/screens/Swap/navigateToSwaps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { watchingAlert } from '@/utils';
import Routes from '@/navigation/routesNames';

export type SwapsParams = Partial<
Pick<SwapsState, 'inputAsset' | 'outputAsset' | 'percentageToSell' | 'flashbots' | 'slippage'> & {
Pick<SwapsState, 'inputAsset' | 'outputAsset' | 'percentageToSell' | 'slippage'> & {
inputAmount: string;
outputAmount: string;
gasSpeed: GasSpeed;
Expand Down
16 changes: 3 additions & 13 deletions src/__swaps__/screens/Swap/providers/swap-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import { SwapAssetType, inputKeys } from '@/__swaps__/types/swap';
import { clamp, getDefaultSlippageWorklet, parseAssetAndExtend } from '@/__swaps__/utils/swaps';
import { analyticsV2 } from '@/analytics';
import { LegacyTransactionGasParamAmounts, TransactionGasParamAmounts } from '@/entities';
import { getFlashbotsProvider, getProvider } from '@/handlers/web3';
import { getProvider } from '@/handlers/web3';
import { WrappedAlert as Alert } from '@/helpers/alert';
import { useAccountSettings } from '@/hooks';
import { useAnimatedInterval } from '@/hooks/reanimated/useAnimatedInterval';
Expand Down Expand Up @@ -58,11 +58,9 @@ import { SyncGasStateToSharedValues, SyncQuoteSharedValuesToState } from './Sync
import { performanceTracking, Screens, TimeToSignOperation } from '@/state/performance/performance';
import { getRemoteConfig } from '@/model/remoteConfig';
import { useConnectedToHardhatStore } from '@/state/connectedToHardhat';
import { chainsNativeAsset, supportedFlashbotsChainIds } from '@/chains';
import { chainsNativeAsset } from '@/chains';
import { getSwapsNavigationParams } from '../navigateToSwaps';
import { LedgerSigner } from '@/handlers/LedgerSigner';
import { EventProperties } from '@/analytics/event';
import { isEqual } from 'lodash';

const swapping = i18n.t(i18n.l.swap.actions.swapping);
const holdToSwap = i18n.t(i18n.l.swap.actions.hold_to_swap);
Expand Down Expand Up @@ -227,10 +225,7 @@ export const SwapProvider = ({ children }: SwapProviderProps) => {
const NotificationManager = IS_IOS ? NativeModules.NotificationManager : null;
NotificationManager?.postNotification('rapInProgress');

const provider =
parameters.flashbots && supportedFlashbotsChainIds.includes(parameters.chainId)
? getFlashbotsProvider()
: getProvider({ chainId: parameters.chainId });
const provider = getProvider({ chainId: parameters.chainId });
const connectedToHardhat = useConnectedToHardhatStore.getState().connectedToHardhat;

const isBridge = swapsStore.getState().inputAsset?.mainnetAddress === swapsStore.getState().outputAsset?.mainnetAddress;
Expand Down Expand Up @@ -327,7 +322,6 @@ export const SwapProvider = ({ children }: SwapProviderProps) => {
mainnetAddress: (parameters.assetToBuy.chainId === ChainId.mainnet
? parameters.assetToBuy.address
: parameters.assetToSell.mainnetAddress) as AddressOrEth,
flashbots: parameters.flashbots ?? false,
tradeAmountUSD: parameters.quote.tradeAmountUSD,
degenMode: isDegenModeEnabled,
isSwappingToPopularAsset,
Expand Down Expand Up @@ -399,7 +393,6 @@ export const SwapProvider = ({ children }: SwapProviderProps) => {
mainnetAddress: (parameters.assetToBuy.chainId === ChainId.mainnet
? parameters.assetToBuy.address
: parameters.assetToSell.mainnetAddress) as AddressOrEth,
flashbots: parameters.flashbots ?? false,
tradeAmountUSD: parameters.quote.tradeAmountUSD,
degenMode: isDegenModeEnabled,
isSwappingToPopularAsset,
Expand Down Expand Up @@ -441,8 +434,6 @@ export const SwapProvider = ({ children }: SwapProviderProps) => {

const type = inputAsset.chainId !== outputAsset.chainId ? 'crosschainSwap' : 'swap';
const quoteData = q as QuoteTypeMap[typeof type];
const flashbots = (SwapSettings.flashbots.value && !!supportedFlashbotsChainIds.includes(inputAsset.chainId)) ?? false;

const isNativeWrapOrUnwrap = quoteData.swapType === SwapType.wrap || quoteData.swapType === SwapType.unwrap;

const parameters: Omit<RapSwapActionParameters<typeof type>, 'gasParams' | 'gasFeeParamsBySpeed' | 'selectedGasFee'> = {
Expand All @@ -457,7 +448,6 @@ export const SwapProvider = ({ children }: SwapProviderProps) => {
sellAmountDisplay: isNativeWrapOrUnwrap ? quoteData.sellAmount : quoteData.sellAmountDisplay,
feeInEth: isNativeWrapOrUnwrap ? '0' : quoteData.feeInEth,
},
flashbots,
};

runOnJS(getNonceAndPerformSwap)({
Expand Down
2 changes: 1 addition & 1 deletion src/__swaps__/types/swap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export type inputKeys = 'inputAmount' | 'inputNativeValue' | 'outputAmount' | 'o
export type inputMethods = inputKeys | 'slider';
export type inputValuesType = { [key in inputKeys]: number | string };

export type settingsKeys = 'swapFee' | 'slippage' | 'flashbots';
export type settingsKeys = 'swapFee' | 'slippage';

export enum SortMethod {
token = 'token',
Expand Down
14 changes: 0 additions & 14 deletions src/__swaps__/utils/gasUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ import { addHexPrefix, toHex } from '@/handlers/web3';
import { MeteorologyLegacyResponse, MeteorologyResponse } from '@/entities/gas';
import { getMinimalTimeUnitStringForMs } from '@/helpers/time';

export const FLASHBOTS_MIN_TIP = 6;

export const parseGasDataConfirmationTime = ({
maxBaseFee,
maxPriorityFee,
Expand Down Expand Up @@ -463,7 +461,6 @@ export const parseGasFeeParamsBySpeed = ({
nativeAsset,
currency,
optimismL1SecurityFee,
flashbotsEnabled,
additionalTime = 0,
}: {
chainId: ChainId;
Expand All @@ -472,7 +469,6 @@ export const parseGasFeeParamsBySpeed = ({
nativeAsset?: ParsedAsset;
currency: SupportedCurrencyKey;
optimismL1SecurityFee?: string | null;
flashbotsEnabled?: boolean;
additionalTime?: number;
}) => {
if (meteorologySupportsType2ForChain(chainId)) {
Expand All @@ -486,16 +482,6 @@ export const parseGasFeeParamsBySpeed = ({
byPriorityFee: response.data.blocksToConfirmationByPriorityFee,
};

if (flashbotsEnabled) {
for (const speed in maxPriorityFeeSuggestions) {
type gasSpeed = 'fast' | 'normal' | 'urgent';
maxPriorityFeeSuggestions[speed as gasSpeed] = Math.max(
Number(gweiToWei(FLASHBOTS_MIN_TIP.toString())),
Number(maxPriorityFeeSuggestions[speed as gasSpeed])
).toString();
}
}

const parseGasFeeParamsSpeed = ({ speed }: { speed: GasSpeed }) =>
parseGasFeeParams({
currentBaseFee,
Expand Down
Loading

0 comments on commit 044daae

Please sign in to comment.