Skip to content

Commit

Permalink
Merge branch 'develop' of https://github.com/rainbow-me/rainbow into …
Browse files Browse the repository at this point in the history
…@benisgold/crosschain-swaps-rap
  • Loading branch information
benisgold committed Nov 15, 2024
2 parents 7dbe664 + 6db854e commit 4f91665
Show file tree
Hide file tree
Showing 10 changed files with 168 additions and 244 deletions.
4 changes: 2 additions & 2 deletions src/__swaps__/screens/Swap/hooks/useSwapEstimatedGasLimit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { useQuery } from '@tanstack/react-query';

import { ParsedSearchAsset } from '@/__swaps__/types/assets';
import { ChainId } from '@/chains/types';
import { estimateUnlockAndCrosschainSwap } from '@/raps/unlockAndCrosschainSwap';
import { estimateUnlockAndSwap } from '@/raps/unlockAndSwap';
import { estimateUnlockAndCrosschainSwap } from '@/raps/actions/crosschainSwap';
import { estimateUnlockAndSwap } from '@/raps/actions/swap';
import { QueryConfigWithSelect, QueryFunctionArgs, QueryFunctionResult, createQueryKey } from '@/react-query';
import { gasUnits } from '@/references/gasUnits';

Expand Down
7 changes: 6 additions & 1 deletion src/__swaps__/screens/Swap/providers/swap-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ import { queryClient } from '@/react-query';
import { userAssetsQueryKey } from '@/resources/assets/UserAssetsQuery';
import { userAssetsStore } from '@/state/assets/userAssets';
import { swapsStore } from '@/state/swaps/swapsStore';
import { getNextNonce } from '@/state/nonces';

import { haptics } from '@/utils';
import { CrosschainQuote, Quote, QuoteError, SwapType } from '@rainbow-me/swaps';

Expand Down Expand Up @@ -202,7 +204,7 @@ export const SwapProvider = ({ children }: SwapProviderProps) => {

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

Expand Down Expand Up @@ -261,6 +263,8 @@ export const SwapProvider = ({ children }: SwapProviderProps) => {
}

const chainId = connectedToHardhat ? ChainId.hardhat : parameters.chainId;
const nonce = await getNextNonce({ address: parameters.quote.from, chainId });

const { errorMessage } = await performanceTracking.getState().executeFn({
fn: walletExecuteRap,
screen: Screens.SWAPS,
Expand All @@ -270,6 +274,7 @@ export const SwapProvider = ({ children }: SwapProviderProps) => {
},
})(wallet, type, {
...parameters,
nonce,
chainId,
gasParams,
// @ts-expect-error - collision between old gas types and new
Expand Down
77 changes: 1 addition & 76 deletions src/handlers/swap.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
import { BigNumberish } from '@ethersproject/bignumber';
import { Block, StaticJsonRpcProvider } from '@ethersproject/providers';
import {
CrosschainQuote,
getQuoteExecutionDetails,
getRainbowRouterContractAddress,
getWrappedAssetMethod,
PermitSupportedTokenList,
Quote,
SwapType,
} from '@rainbow-me/swaps';
import { CrosschainQuote, getQuoteExecutionDetails, getRainbowRouterContractAddress, Quote } from '@rainbow-me/swaps';
import { Contract } from '@ethersproject/contracts';
import { MaxUint256 } from '@ethersproject/constants';
import { IS_TESTING } from 'react-native-dotenv';
Expand Down Expand Up @@ -184,73 +176,6 @@ export const getSwapGasLimitWithFakeApproval = async (
return getDefaultGasLimitForTrade(tradeDetails, chainId);
};

export const estimateSwapGasLimit = async ({
chainId,
requiresApprove,
tradeDetails,
}: {
chainId: ChainId;
requiresApprove?: boolean;
tradeDetails: Quote | null;
}): Promise<string | number> => {
const provider = getProvider({ chainId });
if (!provider || !tradeDetails) {
return ethereumUtils.getBasicSwapGasLimit(Number(chainId));
}
const isWrapNativeAsset = tradeDetails.swapType === SwapType.wrap;
const isUnwrapNativeAsset = tradeDetails.swapType === SwapType.unwrap;

// Wrap / Unwrap Eth
if (isWrapNativeAsset || isUnwrapNativeAsset) {
const default_estimate = isWrapNativeAsset ? ethUnits.weth_wrap : ethUnits.weth_unwrap;
try {
const gasLimit = await estimateGasWithPadding(
{
from: tradeDetails.from,
value: isWrapNativeAsset ? tradeDetails.buyAmount : '0',
},
getWrappedAssetMethod(isWrapNativeAsset ? 'deposit' : 'withdraw', provider, chainId as number),
// @ts-ignore
isUnwrapNativeAsset ? [tradeDetails.buyAmount] : null,
provider,
1.002
);

return gasLimit || tradeDetails?.defaultGasLimit || default_estimate;
} catch (e) {
return tradeDetails?.defaultGasLimit || default_estimate;
}
// Swap
} else {
try {
const { params, method, methodArgs } = getQuoteExecutionDetails(tradeDetails, { from: tradeDetails.from }, provider);

if (requiresApprove) {
if (CHAIN_IDS_WITH_TRACE_SUPPORT.includes(chainId) && IS_TESTING !== 'true') {
try {
const gasLimitWithFakeApproval = await getSwapGasLimitWithFakeApproval(chainId, provider, tradeDetails);
logger.debug('[swap]: Got gasLimitWithFakeApproval!', {
gasLimitWithFakeApproval,
});
return gasLimitWithFakeApproval;
} catch (e) {
logger.error(new RainbowError('[swap]: Error estimating swap gas limit with approval'), {
error: e,
});
}
}

return getDefaultGasLimitForTrade(tradeDetails, chainId);
}

const gasLimit = await estimateGasWithPadding(params, method, methodArgs as any, provider, SWAP_GAS_PADDING);
return gasLimit || getDefaultGasLimitForTrade(tradeDetails, chainId);
} catch (error) {
return getDefaultGasLimitForTrade(tradeDetails, chainId);
}
}
};

export const estimateCrosschainSwapGasLimit = async ({
chainId,
requiresApprove,
Expand Down
4 changes: 2 additions & 2 deletions src/handlers/web3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@ export const isTestnetChain = ({ chainId = ChainId.mainnet }: { chainId?: ChainI
return !!defaultChains[chainId].testnet;
};

// shoudl figure out better way to include this in networks
export const getFlashbotsProvider = async () => {
// TODO: should figure out better way to include this in networks
export const getFlashbotsProvider = () => {
return new StaticJsonRpcProvider(
proxyCustomRpcEndpoint(
ChainId.mainnet,
Expand Down
77 changes: 70 additions & 7 deletions src/raps/actions/crosschainSwap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { Signer } from '@ethersproject/abstract-signer';
import { CrosschainQuote, fillCrosschainQuote } from '@rainbow-me/swaps';
import { Address } from 'viem';
import { estimateGasWithPadding, getProvider, toHex } from '@/handlers/web3';
import { add } from '@/helpers/utilities';
import { assetNeedsUnlocking, estimateApprove } from './unlock';

import { REFERRER, gasUnits, ReferrerType } from '@/references';
import { ChainId } from '@/chains/types';
Expand All @@ -10,7 +12,8 @@ import { addNewTransaction } from '@/state/pendingTransactions';
import { RainbowError, logger } from '@/logger';

import { TransactionGasParams, TransactionLegacyGasParams } from '@/__swaps__/types/gas';
import { ActionProps, RapActionResult } from '../references';
import { ActionProps, RapActionResult, RapSwapActionParameters } from '../references';

import {
CHAIN_IDS_WITH_TRACE_SUPPORT,
SWAP_GAS_PADDING,
Expand All @@ -27,6 +30,65 @@ import { chainsName } from '@/chains';

const getCrosschainSwapDefaultGasLimit = (quote: CrosschainQuote) => quote?.routes?.[0]?.userTxs?.[0]?.gasFees?.gasLimit;

export const estimateUnlockAndCrosschainSwap = async ({
sellAmount,
quote,
chainId,
assetToSell,
}: Pick<RapSwapActionParameters<'crosschainSwap'>, 'sellAmount' | 'quote' | 'chainId' | 'assetToSell'>) => {
const {
from: accountAddress,
sellTokenAddress,
allowanceTarget,
allowanceNeeded,
} = quote as {
from: Address;
sellTokenAddress: Address;
allowanceTarget: Address;
allowanceNeeded: boolean;
};

let gasLimits: (string | number)[] = [];
let swapAssetNeedsUnlocking = false;

if (allowanceNeeded) {
swapAssetNeedsUnlocking = await assetNeedsUnlocking({
owner: accountAddress,
amount: sellAmount,
assetToUnlock: assetToSell,
spender: allowanceTarget,
chainId,
});
}

if (swapAssetNeedsUnlocking) {
const unlockGasLimit = await estimateApprove({
owner: accountAddress,
tokenAddress: sellTokenAddress,
spender: allowanceTarget,
chainId,
});
gasLimits = gasLimits.concat(unlockGasLimit);
}

const swapGasLimit = await estimateCrosschainSwapGasLimit({
chainId,
requiresApprove: swapAssetNeedsUnlocking,
quote,
});

if (swapGasLimit === null || swapGasLimit === undefined || isNaN(Number(swapGasLimit))) {
return getCrosschainSwapDefaultGasLimit(quote) || getDefaultGasLimitForTrade(quote, chainId);
}

const gasLimit = gasLimits.concat(swapGasLimit).reduce((acc, limit) => add(acc, limit), '0');
if (isNaN(Number(gasLimit))) {
return getCrosschainSwapDefaultGasLimit(quote) || getDefaultGasLimitForTrade(quote, chainId);
}

return gasLimit.toString();
};

export const estimateCrosschainSwapGasLimit = async ({
chainId,
requiresApprove,
Expand Down Expand Up @@ -112,7 +174,7 @@ export const crosschainSwap = async ({
gasParams,
gasFeeParamsBySpeed,
}: ActionProps<'crosschainSwap'>): Promise<RapActionResult> => {
const { quote, chainId, requiresApprove } = parameters;
const { assetToSell, sellAmount, quote, chainId } = parameters;

let gasParamsToUse = gasParams;
if (currentRap.actions.length - 1 > index) {
Expand All @@ -125,10 +187,11 @@ export const crosschainSwap = async ({

let gasLimit;
try {
gasLimit = await estimateCrosschainSwapGasLimit({
chainId,
requiresApprove,
gasLimit = await estimateUnlockAndCrosschainSwap({
sellAmount,
quote,
chainId,
assetToSell,
});
} catch (e) {
logger.error(new RainbowError('[raps/crosschainSwap]: error estimateCrosschainSwapGasLimit'), {
Expand Down Expand Up @@ -187,7 +250,7 @@ export const crosschainSwap = async ({
price: nativePriceForAssetToBuy,
} satisfies ParsedAsset;

const assetToSell = {
const updatedAssetToSell = {
...parameters.assetToSell,
network: chainsName[parameters.assetToSell.chainId],
networks: parameters.assetToSell.networks as Record<string, AddysNetworkDetails>,
Expand All @@ -206,7 +269,7 @@ export const crosschainSwap = async ({
{
direction: TransactionDirection.OUT,
asset: {
...assetToSell,
...updatedAssetToSell,
native: undefined,
},
value: quote.sellAmount.toString(),
Expand Down
Loading

0 comments on commit 4f91665

Please sign in to comment.