@reservoir0x/relay-kit-ui
Version:
Relay is the Fastest and Cheapest Way to Bridge and Transact Across Chains.
735 lines • 36.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const index_js_1 = require("../../hooks/index.js");
const viem_1 = require("viem");
const wagmi_1 = require("wagmi");
const experimental_1 = require("wagmi/experimental");
const react_query_1 = require("@tanstack/react-query");
const quote_js_1 = require("../../utils/quote.js");
const relay_kit_hooks_1 = require("@reservoir0x/relay-kit-hooks");
const events_js_1 = require("../../constants/events.js");
const RelayKitProvider_js_1 = require("../../providers/RelayKitProvider.js");
const address_js_1 = require("../../utils/address.js");
const relay_sdk_1 = require("@reservoir0x/relay-sdk");
const errors_js_1 = require("../../utils/errors.js");
const useSwapButtonCta_js_1 = require("../../hooks/widget/useSwapButtonCta.js");
const hashing_js_1 = require("../../utils/hashing.js");
const time_js_1 = require("../../utils/time.js");
const tokenPriceQueryOptions = {
staleTime: 60 * 1000,
refetchInterval: 30 * 1000,
refetchOnWindowFocus: false
};
const SwapWidgetRenderer = ({ transactionModalOpen, setTransactionModalOpen, depositAddressModalOpen, fromToken: _fromToken, setFromToken: _setFromToken, toToken: _toToken, setToToken: _setToToken, defaultToAddress, defaultAmount, defaultTradeType, slippageTolerance, context, wallet, multiWalletSupportEnabled = false, linkedWallets, supportedWalletVMs, children, onAnalyticEvent, onSwapError }) => {
const [fromToken, setFromToken] = (0, index_js_1.useFallbackState)(_setFromToken ? _fromToken : undefined, _setFromToken
? [
_fromToken,
_setFromToken
]
: undefined);
const [toToken, setToToken] = (0, index_js_1.useFallbackState)(_setToToken ? _toToken : undefined, _setToToken
? [_toToken, _setToToken]
: undefined);
const providerOptionsContext = (0, react_1.useContext)(RelayKitProvider_js_1.ProviderOptionsContext);
const connectorKeyOverrides = providerOptionsContext.vmConnectorKeyOverrides;
const relayClient = (0, index_js_1.useRelayClient)();
const { connector } = (0, wagmi_1.useAccount)();
const walletClient = (0, wagmi_1.useWalletClient)();
const [customToAddress, setCustomToAddress] = (0, react_1.useState)(defaultToAddress);
const [useExternalLiquidity, setUseExternalLiquidity] = (0, react_1.useState)(false);
const address = (0, index_js_1.useWalletAddress)(wallet, linkedWallets);
const [tradeType, setTradeType] = (0, react_1.useState)(defaultTradeType ?? 'EXACT_INPUT');
const queryClient = (0, react_query_1.useQueryClient)();
const [steps, setSteps] = (0, react_1.useState)(null);
const [quoteInProgress, setQuoteInProgress] = (0, react_1.useState)(null);
const [waitingForSteps, setWaitingForSteps] = (0, react_1.useState)(false);
const [details, setDetails] = (0, react_1.useState)(null);
const [gasTopUpEnabled, setGasTopUpEnabled] = (0, react_1.useState)(false);
const [abortController, setAbortController] = (0, react_1.useState)(null);
const { value: amountInputValue, debouncedValue: debouncedInputAmountValue, setValue: setAmountInputValue, debouncedControls: debouncedAmountInputControls } = (0, index_js_1.useDebounceState)(!defaultTradeType || defaultTradeType === 'EXACT_INPUT'
? (defaultAmount ?? '')
: '', 500);
const { value: amountOutputValue, debouncedValue: debouncedOutputAmountValue, setValue: setAmountOutputValue, debouncedControls: debouncedAmountOutputControls } = (0, index_js_1.useDebounceState)(defaultTradeType === 'EXPECTED_OUTPUT' ? (defaultAmount ?? '') : '', 500);
const [swapError, setSwapError] = (0, react_1.useState)(null);
const tokenPairIsCanonical = fromToken?.chainId !== undefined &&
toToken?.chainId !== undefined &&
fromToken.symbol === toToken.symbol;
const toChain = relayClient?.chains.find((chain) => chain.id === toToken?.chainId);
const fromChain = relayClient?.chains?.find((chain) => chain.id === fromToken?.chainId);
const fromChainWalletVMSupported = !fromChain?.vmType ||
supportedWalletVMs.includes(fromChain?.vmType) ||
fromChain?.id === 1337;
const toChainWalletVMSupported = !toChain?.vmType || supportedWalletVMs.includes(toChain?.vmType);
const defaultRecipient = (0, react_1.useMemo)(() => {
const _linkedWallet = linkedWallets?.find((linkedWallet) => address ===
(linkedWallet.vmType === 'evm'
? linkedWallet.address.toLowerCase()
: linkedWallet.address));
const _isValidToAddress = (0, address_js_1.isValidAddress)(toChain?.vmType, customToAddress ?? '', toChain?.id, !customToAddress && _linkedWallet?.address === address
? _linkedWallet?.connector
: undefined, connectorKeyOverrides);
if (multiWalletSupportEnabled &&
toChain &&
linkedWallets &&
!_isValidToAddress) {
const supportedAddress = (0, address_js_1.findSupportedWallet)(toChain, customToAddress, linkedWallets, connectorKeyOverrides);
return supportedAddress;
}
}, [
multiWalletSupportEnabled,
toChain,
customToAddress,
address,
linkedWallets,
setCustomToAddress
]);
const recipient = customToAddress ?? defaultRecipient ?? address;
const { value: fromBalance, queryKey: fromBalanceQueryKey, isLoading: isLoadingFromBalance, isError: fromBalanceErrorFetching, isDuneBalance: fromBalanceIsDune, hasPendingBalance: fromBalancePending } = (0, index_js_1.useCurrencyBalance)({
chain: fromChain,
address: address,
currency: fromToken?.address ? fromToken.address : undefined,
enabled: fromToken !== undefined,
refreshInterval: undefined,
wallet
});
const { value: toBalance, queryKey: toBalanceQueryKey, isLoading: isLoadingToBalance, isDuneBalance: toBalanceIsDune, hasPendingBalance: toBalancePending } = (0, index_js_1.useCurrencyBalance)({
chain: toChain,
address: recipient,
currency: toToken?.address ? toToken.address : undefined,
enabled: toToken !== undefined,
refreshInterval: undefined,
wallet
});
const invalidateBalanceQueries = (0, react_1.useCallback)(() => {
const invalidatePeriodically = (invalidateFn) => {
let maxRefreshes = 4;
let refreshCount = 0;
const timer = setInterval(() => {
if (maxRefreshes === refreshCount) {
clearInterval(timer);
return;
}
refreshCount++;
invalidateFn();
}, 3000);
};
queryClient.invalidateQueries({ queryKey: ['useDuneBalances'] });
if (fromBalanceIsDune) {
invalidatePeriodically(() => {
queryClient.invalidateQueries({ queryKey: fromBalanceQueryKey });
});
}
else {
queryClient.invalidateQueries({ queryKey: fromBalanceQueryKey });
}
if (toBalanceIsDune) {
invalidatePeriodically(() => {
queryClient.invalidateQueries({ queryKey: toBalanceQueryKey });
});
}
else {
queryClient.invalidateQueries({ queryKey: toBalanceQueryKey });
}
}, [
queryClient,
fromBalanceQueryKey,
toBalanceQueryKey,
toBalanceIsDune,
fromBalanceIsDune,
address
]);
const { data: capabilities } = (0, experimental_1.useCapabilities)({
query: {
enabled: connector &&
(connector.id === 'coinbaseWalletSDK' || connector.id === 'coinbase')
}
});
const hasAuxiliaryFundsSupport = Boolean(fromToken?.chainId
? capabilities?.[fromToken?.chainId]?.auxiliaryFunds?.supported
: false);
const isSvmSwap = fromChain?.vmType === 'svm' || toChain?.vmType === 'svm';
const isBvmSwap = fromChain?.vmType === 'bvm' || toChain?.vmType === 'bvm';
const linkedWallet = linkedWallets?.find((linkedWallet) => address ===
(linkedWallet.vmType === 'evm'
? linkedWallet.address.toLowerCase()
: linkedWallet.address) || linkedWallet.address === address);
const isRecipientLinked = (recipient
? linkedWallets?.find((wallet) => wallet.address === recipient)
: undefined) !== undefined;
const isValidFromAddress = (0, address_js_1.isValidAddress)(fromChain?.vmType, address ?? '', fromChain?.id, linkedWallet?.connector, connectorKeyOverrides);
const fromAddressWithFallback = (0, address_js_1.addressWithFallback)(fromChain?.vmType, address, fromChain?.id, linkedWallet?.connector, connectorKeyOverrides);
const isValidToAddress = (0, address_js_1.isValidAddress)(toChain?.vmType, recipient ?? '', toChain?.id);
const toAddressWithFallback = (0, address_js_1.addressWithFallback)(toChain?.vmType, recipient, toChain?.id);
const externalLiquiditySupport = (0, relay_kit_hooks_1.useQuote)(relayClient ? relayClient : undefined, wallet, fromToken && toToken
? {
user: (0, relay_sdk_1.getDeadAddress)(fromChain?.vmType, fromChain?.id),
originChainId: fromToken.chainId,
destinationChainId: toToken.chainId,
originCurrency: fromToken.address,
destinationCurrency: toToken.address,
recipient: (0, relay_sdk_1.getDeadAddress)(toChain?.vmType, toChain?.id),
tradeType,
appFees: providerOptionsContext.appFees,
amount: '10000000000000000000000',
referrer: relayClient?.source ?? undefined,
useExternalLiquidity: true
}
: undefined, undefined, undefined, {
refetchOnWindowFocus: false,
enabled: fromToken !== undefined &&
toToken !== undefined &&
fromChain &&
toChain &&
(fromChain.id === toChain.baseChainId ||
toChain.id === fromChain.baseChainId)
});
const supportsExternalLiquidity = tokenPairIsCanonical &&
externalLiquiditySupport.status === 'success' &&
fromChainWalletVMSupported
? true
: false;
const { displayName: toDisplayName } = (0, index_js_1.useENSResolver)(recipient, {
enabled: toChain?.vmType === 'evm' && isValidToAddress
});
const [currentSlippageTolerance, setCurrentSlippageTolerance] = (0, react_1.useState)(slippageTolerance);
(0, react_1.useEffect)(() => {
setCurrentSlippageTolerance(slippageTolerance);
}, [slippageTolerance]);
const { required: gasTopUpRequired, amount: _gasTopUpAmount, amountUsd: _gasTopUpAmountUsd } = (0, index_js_1.useGasTopUpRequired)(toChain, fromChain, toToken, recipient);
const { data: fromTokenPriceData, isLoading: isLoadingFromTokenPrice } = (0, relay_kit_hooks_1.useTokenPrice)(relayClient?.baseApiUrl, {
address: fromToken?.address ?? '',
chainId: fromToken?.chainId ?? 0,
referrer: relayClient?.source
}, {
enabled: !!(fromToken?.address && fromToken.chainId),
...tokenPriceQueryOptions
});
const { data: toTokenPriceData, isLoading: isLoadingToTokenPrice } = (0, relay_kit_hooks_1.useTokenPrice)(relayClient?.baseApiUrl, {
address: toToken?.address ?? '',
chainId: toToken?.chainId ?? 0,
referrer: relayClient?.source
}, {
enabled: !!(toToken?.address && toToken.chainId),
...tokenPriceQueryOptions
});
const originChainSupportsProtocolv2 = fromChain?.protocol?.v2?.depository !== undefined;
const quoteProtocol = (0, react_1.useMemo)(() => {
if (fromChain?.id && originChainSupportsProtocolv2) {
if (!fromToken && !fromTokenPriceData) {
return undefined;
}
const relevantPrice = fromTokenPriceData?.price && !isLoadingFromTokenPrice
? fromTokenPriceData.price
: undefined;
const amount = tradeType === 'EXACT_INPUT'
? debouncedInputAmountValue
: debouncedOutputAmountValue;
if (!amount) {
return undefined;
}
const usdAmount = relevantPrice
? (0, quote_js_1.calculateUsdValue)(relevantPrice, amount)
: undefined;
return usdAmount !== undefined && usdAmount <= 100
? 'preferV2'
: undefined;
}
else {
return undefined;
}
}, [
fromTokenPriceData,
isLoadingFromTokenPrice,
debouncedInputAmountValue,
tradeType,
originChainSupportsProtocolv2
]);
const loadingProtocolVersion = fromChain?.id && originChainSupportsProtocolv2 && isLoadingFromTokenPrice;
const quoteParameters = fromToken && toToken
? {
user: fromAddressWithFallback,
originChainId: fromToken.chainId,
destinationChainId: toToken.chainId,
originCurrency: fromToken.address,
destinationCurrency: toToken.address,
recipient: toAddressWithFallback,
tradeType,
appFees: providerOptionsContext.appFees,
amount: tradeType === 'EXACT_INPUT'
? (0, viem_1.parseUnits)(debouncedInputAmountValue, fromToken.decimals).toString()
: (0, viem_1.parseUnits)(debouncedOutputAmountValue, toToken.decimals).toString(),
referrer: relayClient?.source ?? undefined,
useExternalLiquidity,
useDepositAddress: !fromChainWalletVMSupported || fromToken?.chainId === 1337,
refundTo: fromToken?.chainId === 1337 ? address : undefined,
slippageTolerance: slippageTolerance,
topupGas: gasTopUpEnabled && gasTopUpRequired,
protocolVersion: quoteProtocol
}
: undefined;
const onQuoteRequested = (options, config) => {
const interval = (0, time_js_1.get15MinuteInterval)();
const quoteRequestId = (0, hashing_js_1.sha256)({ ...options, interval });
onAnalyticEvent?.(events_js_1.EventNames.QUOTE_REQUESTED, {
parameters: options,
wallet_connector: linkedWallet?.connector,
chain_id_in: options?.originChainId,
chain_id_out: options?.destinationChainId,
http_config: config,
quote_request_id: quoteRequestId
});
};
const onQuoteReceived = ({ details, steps }, options) => {
const interval = (0, time_js_1.get15MinuteInterval)();
const quoteRequestId = (0, hashing_js_1.sha256)({ ...options, interval });
onAnalyticEvent?.(events_js_1.EventNames.QUOTE_RECEIVED, {
parameters: options,
wallet_connector: linkedWallet?.connector,
amount_in: details?.currencyIn?.amountFormatted,
amount_in_raw: details?.currencyIn?.amount,
currency_in: details?.currencyIn?.currency?.symbol,
chain_id_in: details?.currencyIn?.currency?.chainId,
amount_out: details?.currencyOut?.amountFormatted,
amount_out_raw: details?.currencyOut?.amount,
currency_out: details?.currencyOut?.currency?.symbol,
chain_id_out: details?.currencyOut?.currency?.chainId,
slippage_tolerance_destination_percentage: details?.slippageTolerance?.destination?.percent,
slippage_tolerance_origin_percentage: details?.slippageTolerance?.origin?.percent,
steps,
quote_request_id: quoteRequestId,
quote_id: steps ? (0, quote_js_1.extractQuoteId)(steps) : undefined
});
};
const quoteFetchingEnabled = Boolean(relayClient &&
((tradeType === 'EXACT_INPUT' &&
debouncedInputAmountValue &&
debouncedInputAmountValue.length > 0 &&
Number(debouncedInputAmountValue) !== 0) ||
(tradeType === 'EXPECTED_OUTPUT' &&
debouncedOutputAmountValue &&
debouncedOutputAmountValue.length > 0 &&
Number(debouncedOutputAmountValue) !== 0)) &&
fromToken !== undefined &&
toToken !== undefined &&
!transactionModalOpen &&
!depositAddressModalOpen &&
!loadingProtocolVersion);
const { data: _quoteData, error: quoteError, isFetching: isFetchingQuote, executeQuote: executeSwap, queryKey: quoteQueryKey } = (0, relay_kit_hooks_1.useQuote)(relayClient ? relayClient : undefined, wallet, quoteParameters, onQuoteRequested, onQuoteReceived, {
refetchOnWindowFocus: false,
enabled: quoteFetchingEnabled,
refetchInterval: !transactionModalOpen &&
!depositAddressModalOpen &&
debouncedInputAmountValue === amountInputValue &&
debouncedOutputAmountValue === amountOutputValue
? 12000
: undefined
}, (e) => {
const errorMessage = (0, errors_js_1.errorToJSON)(e?.response?.data?.message ? new Error(e?.response?.data?.message) : e);
const interval = (0, time_js_1.get15MinuteInterval)();
const quoteRequestId = (0, hashing_js_1.sha256)({ ...quoteParameters, interval });
onAnalyticEvent?.(events_js_1.EventNames.QUOTE_ERROR, {
wallet_connector: linkedWallet?.connector,
error_message: errorMessage,
parameters: quoteParameters,
quote_request_id: quoteRequestId,
status_code: e.response.status ?? e.status ?? ''
});
});
const invalidateQuoteQuery = (0, react_1.useCallback)(() => {
queryClient.invalidateQueries({ queryKey: quoteQueryKey });
}, [queryClient, quoteQueryKey]);
let error = _quoteData || (isFetchingQuote && quoteFetchingEnabled) ? null : quoteError;
let quote = error ? undefined : _quoteData;
const gasTopUpAmount = quote?.details?.currencyGasTopup?.amount
? BigInt(quote?.details?.currencyGasTopup?.amount)
: _gasTopUpAmount;
const gasTopUpAmountUsd = quote?.details?.currencyGasTopup?.amountUsd ?? _gasTopUpAmountUsd;
(0, index_js_1.useDisconnected)(address, () => {
setCustomToAddress(undefined);
});
(0, react_1.useEffect)(() => {
if (tradeType === 'EXACT_INPUT') {
const amountOut = quote?.details?.currencyOut?.amount ?? '';
setAmountOutputValue(amountOut !== ''
? (0, viem_1.formatUnits)(BigInt(amountOut), Number(quote?.details?.currencyOut?.currency?.decimals ?? 18))
: '');
}
else if (tradeType === 'EXPECTED_OUTPUT') {
const amountIn = quote?.details?.currencyIn?.amount ?? '';
setAmountInputValue(amountIn !== ''
? (0, viem_1.formatUnits)(BigInt(amountIn), Number(quote?.details?.currencyIn?.currency?.decimals ?? 18))
: '');
}
debouncedAmountInputControls.flush();
debouncedAmountOutputControls.flush();
}, [quote, tradeType]);
(0, react_1.useEffect)(() => {
if (useExternalLiquidity &&
!externalLiquiditySupport.isFetching &&
!supportsExternalLiquidity) {
setUseExternalLiquidity(false);
}
}, [
supportsExternalLiquidity,
useExternalLiquidity,
externalLiquiditySupport.isFetching
]);
const feeBreakdown = (0, react_1.useMemo)(() => {
const chains = relayClient?.chains;
const fromChain = chains?.find((chain) => chain.id === fromToken?.chainId);
const toChain = chains?.find((chain) => chain.id === toToken?.chainId);
return fromToken && toToken && fromChain && toChain && quote
? (0, quote_js_1.parseFees)(toChain, fromChain, quote)
: null;
}, [quote, fromToken, toToken, relayClient]);
const totalAmount = BigInt(quote?.details?.currencyIn?.amount ?? 0n);
const hasInsufficientBalance = Boolean(!fromBalanceErrorFetching &&
totalAmount &&
address &&
(fromBalance ?? 0n) < totalAmount &&
!hasAuxiliaryFundsSupport &&
fromChainWalletVMSupported);
const fetchQuoteErrorMessage = error
? error?.message
? error?.message
: 'Unknown Error'
: null;
const fetchQuoteDataErrorMessage = error
? error?.response?.data?.message
? error?.response?.data.message
: 'Unknown Error'
: null;
const isInsufficientLiquidityError = Boolean(fetchQuoteErrorMessage?.includes('No quotes available'));
const isCapacityExceededError = fetchQuoteDataErrorMessage?.includes('Amount is higher than the available liquidity') || fetchQuoteDataErrorMessage?.includes('Insufficient relayer liquidity');
const isCouldNotExecuteError = fetchQuoteDataErrorMessage?.includes('Could not execute');
const highRelayerServiceFee = (0, quote_js_1.isHighRelayerServiceFeeUsd)(quote);
const relayerFeeProportion = (0, quote_js_1.calculateRelayerFeeProportionUsd)(quote);
const timeEstimate = (0, quote_js_1.calculatePriceTimeEstimate)(quote?.details);
const canonicalTimeEstimate = (0, quote_js_1.calculatePriceTimeEstimate)(externalLiquiditySupport.data?.details);
const recipientWalletSupportsChain = (0, index_js_1.useIsWalletCompatible)(toChain?.id, recipient, linkedWallets, onAnalyticEvent);
const isFromNative = fromToken?.address === fromChain?.currency?.address;
const isSameCurrencySameRecipientSwap = fromToken?.address === toToken?.address &&
fromToken?.chainId === toToken?.chainId &&
address === recipient;
const ctaCopy = (0, useSwapButtonCta_js_1.useSwapButtonCta)({
fromToken,
toToken,
multiWalletSupportEnabled,
isValidFromAddress,
fromChainWalletVMSupported,
isValidToAddress,
toChainWalletVMSupported,
fromChain,
toChain,
isSameCurrencySameRecipientSwap,
debouncedInputAmountValue,
debouncedOutputAmountValue,
hasInsufficientBalance,
isInsufficientLiquidityError,
quote,
operation: quote?.details?.operation
});
(0, index_js_1.usePreviousValueChange)(isCapacityExceededError && supportsExternalLiquidity, !isFetchingQuote && !externalLiquiditySupport.isFetching, (capacityExceeded) => {
if (capacityExceeded) {
onAnalyticEvent?.(events_js_1.EventNames.CTA_MAX_CAPACITY_PROMPTED, {
inputAmount: debouncedInputAmountValue,
outputAmount: debouncedOutputAmountValue
});
}
});
const swap = (0, react_1.useCallback)(async () => {
let submittedEvents = [];
const swapErrorHandler = (error, currentSteps) => {
const errorMessage = (0, errors_js_1.errorToJSON)(error?.response?.data?.message
? new Error(error?.response?.data?.message)
: error);
if (error &&
((typeof error.message === 'string' &&
error.message.includes('rejected')) ||
(typeof error === 'string' && error.includes('rejected')) ||
(typeof error === 'string' && error.includes('Approval Denied')) ||
(typeof error === 'string' && error.includes('denied transaction')) ||
(typeof error.message === 'string' &&
error.message.includes('Approval Denied')) ||
(typeof error.message === 'string' &&
error.message.includes('Plugin Closed')) ||
(typeof error.message === 'string' &&
error.message.includes('denied transaction')) ||
(typeof error.message === 'string' &&
error.message.includes('Failed to initialize request') &&
fromChain?.id === 2741))) {
setTransactionModalOpen(false);
onAnalyticEvent?.(events_js_1.EventNames.USER_REJECTED_WALLET, {
error_message: errorMessage
});
return;
}
const { step, stepItem } = (0, quote_js_1.getCurrentStep)(currentSteps);
const swapEventData = {
...(0, quote_js_1.getSwapEventData)(quote?.details, currentSteps ?? null, linkedWallet?.connector, quoteParameters),
error_message: errorMessage
};
const isApproval = step?.id === 'approve';
const errorEvent = isApproval
? events_js_1.EventNames.APPROVAL_ERROR
: events_js_1.EventNames.DEPOSIT_ERROR;
const isTransactionConfirmationError = (error &&
typeof error.message === 'string' &&
error.message.includes('TransactionConfirmationError')) ||
(error.name && error.name.includes('TransactionConfirmationError'));
if (stepItem?.receipt &&
stepItem.check &&
!isTransactionConfirmationError &&
(typeof stepItem.receipt === 'object' && 'status' in stepItem.receipt
? stepItem.receipt.status !== 'reverted'
: true) &&
(!stepItem.checkStatus || stepItem.checkStatus !== 'unknown')) {
const successEvent = isApproval
? events_js_1.EventNames.APPROVAL_SUCCESS
: events_js_1.EventNames.DEPOSIT_SUCCESS;
if (!submittedEvents.includes(successEvent)) {
onAnalyticEvent?.(successEvent, swapEventData);
submittedEvents.push(successEvent);
setTimeout(() => {
onAnalyticEvent?.(events_js_1.EventNames.FILL_ERROR, swapEventData);
}, 20);
}
else {
onAnalyticEvent?.(events_js_1.EventNames.FILL_ERROR, swapEventData);
}
}
else if (!stepItem?.receipt ||
(typeof stepItem.receipt === 'object' &&
'status' in stepItem.receipt &&
stepItem.receipt.status === 'reverted')) {
onAnalyticEvent?.(errorEvent, swapEventData);
}
else {
onAnalyticEvent?.(events_js_1.EventNames.SWAP_ERROR, swapEventData);
}
setSwapError(errorMessage);
onSwapError?.(errorMessage, { ...quote, steps: currentSteps });
};
try {
const swapEventData = (0, quote_js_1.getSwapEventData)(quote?.details, quote?.steps ? quote?.steps : null, linkedWallet?.connector, quoteParameters);
onAnalyticEvent?.(events_js_1.EventNames.SWAP_CTA_CLICKED, swapEventData);
setWaitingForSteps(true);
if (!executeSwap) {
throw 'Missing a quote';
}
if (!wallet && !walletClient.data) {
throw 'Missing a wallet';
}
setSteps(quote?.steps);
setQuoteInProgress(quote);
setTransactionModalOpen(true);
const _wallet = wallet ?? (0, relay_sdk_1.adaptViemWallet)(walletClient.data);
const activeWalletChainId = await _wallet?.getChainId();
const activeWalletChain = relayClient?.chains?.find((chain) => chain.id === activeWalletChainId);
let targetChainId = fromToken?.chainId;
if (fromToken?.chainId === 1337) {
targetChainId =
activeWalletChain?.vmType !== 'evm' ? 1 : activeWalletChainId;
}
if (fromToken && targetChainId && targetChainId !== activeWalletChainId) {
onAnalyticEvent?.(events_js_1.EventNames.SWAP_SWITCH_NETWORK, {
activeWalletChainId,
...swapEventData
});
await _wallet?.switchChain(targetChainId);
}
let _currentSteps = undefined;
const execPromise = executeSwap(({ steps: currentSteps }) => {
setSteps(currentSteps);
_currentSteps = currentSteps;
const { step, stepItem } = (0, quote_js_1.getCurrentStep)(currentSteps);
const swapEventData = (0, quote_js_1.getSwapEventData)(quote?.details, currentSteps, linkedWallet?.connector, quoteParameters);
if (step && stepItem) {
const isApproval = step.id === 'approve' || step.id === 'approval';
let submittedEvent = isApproval
? events_js_1.EventNames.APPROVAL_SUBMITTED
: events_js_1.EventNames.DEPOSIT_SUBMITTED;
const successEvent = isApproval
? events_js_1.EventNames.APPROVAL_SUCCESS
: events_js_1.EventNames.DEPOSIT_SUCCESS;
const isBatchTransaction = Boolean(Array.isArray(step.items) &&
step.items.length > 1 &&
wallet?.handleBatchTransactionStep);
if (!isApproval && isBatchTransaction) {
submittedEvent = events_js_1.EventNames.BATCH_TX_SUBMITTED;
}
if (!submittedEvents.includes(submittedEvent) &&
!stepItem.receipt &&
stepItem?.txHashes &&
stepItem?.txHashes?.length > 0) {
submittedEvents.push(submittedEvent);
onAnalyticEvent?.(submittedEvent, swapEventData);
}
else if ((!submittedEvents.includes(successEvent) &&
stepItem.receipt &&
!(typeof stepItem.receipt === 'object' &&
'status' in stepItem.receipt &&
stepItem.receipt.status === 'reverted')) ||
stepItem.checkStatus === 'pending') {
onAnalyticEvent?.(successEvent, swapEventData);
submittedEvents.push(successEvent);
}
if (stepItem.status === 'complete' &&
stepItem.check &&
!submittedEvents.includes(events_js_1.EventNames.FILL_SUCCESS)) {
if (!submittedEvents.includes(events_js_1.EventNames.DEPOSIT_SUCCESS) &&
!isBatchTransaction) {
onAnalyticEvent?.(events_js_1.EventNames.DEPOSIT_SUCCESS, swapEventData);
submittedEvents.push(events_js_1.EventNames.DEPOSIT_SUCCESS);
setTimeout(() => {
onAnalyticEvent?.(events_js_1.EventNames.FILL_SUCCESS, swapEventData);
}, 20);
}
else {
onAnalyticEvent?.(events_js_1.EventNames.FILL_SUCCESS, swapEventData);
}
submittedEvents.push(events_js_1.EventNames.FILL_SUCCESS);
}
}
else if (currentSteps?.every((step) => step.items?.every((item) => item.status === 'complete')) &&
!submittedEvents.includes(events_js_1.EventNames.FILL_SUCCESS)) {
if (!submittedEvents.includes(events_js_1.EventNames.DEPOSIT_SUCCESS) &&
!submittedEvents.includes(events_js_1.EventNames.BATCH_TX_SUBMITTED)) {
onAnalyticEvent?.(events_js_1.EventNames.DEPOSIT_SUCCESS, swapEventData);
submittedEvents.push(events_js_1.EventNames.DEPOSIT_SUCCESS);
setTimeout(() => {
onAnalyticEvent?.(events_js_1.EventNames.FILL_SUCCESS, swapEventData);
}, 20);
}
else {
onAnalyticEvent?.(events_js_1.EventNames.FILL_SUCCESS, swapEventData);
}
submittedEvents.push(events_js_1.EventNames.FILL_SUCCESS);
}
});
if (execPromise &&
typeof execPromise === 'object' &&
'abortController' in execPromise) {
setAbortController(execPromise.abortController);
}
execPromise
?.catch((error) => {
swapErrorHandler(error, _currentSteps);
})
.finally(() => {
setWaitingForSteps(false);
setAbortController(null);
invalidateBalanceQueries();
});
}
catch (error) {
swapErrorHandler(error);
setWaitingForSteps(false);
}
}, [
relayClient,
address,
connector,
wallet,
walletClient,
fromToken,
toToken,
customToAddress,
recipient,
debouncedInputAmountValue,
debouncedOutputAmountValue,
tradeType,
useExternalLiquidity,
waitingForSteps,
executeSwap,
setSteps,
setQuoteInProgress,
invalidateBalanceQueries,
linkedWallet,
abortController
]);
return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: children({
quote,
steps,
setSteps,
swap,
transactionModalOpen,
feeBreakdown,
fromToken,
setFromToken,
toToken,
setToToken,
swapError,
error,
toDisplayName,
address,
recipient,
customToAddress,
setCustomToAddress,
tradeType,
setTradeType,
details,
isSameCurrencySameRecipientSwap,
debouncedInputAmountValue,
debouncedAmountInputControls,
setAmountInputValue,
amountInputValue,
amountOutputValue,
debouncedOutputAmountValue,
debouncedAmountOutputControls,
setAmountOutputValue,
toBalance,
toBalancePending,
isLoadingToBalance,
isFetchingQuote,
isLoadingFromBalance,
fromBalance,
fromBalancePending,
highRelayerServiceFee,
relayerFeeProportion,
hasInsufficientBalance,
isInsufficientLiquidityError,
isCapacityExceededError,
isCouldNotExecuteError,
ctaCopy,
isFromNative,
useExternalLiquidity,
slippageTolerance: currentSlippageTolerance,
supportsExternalLiquidity,
timeEstimate,
canonicalTimeEstimate,
fetchingExternalLiquiditySupport: externalLiquiditySupport.isFetching,
isSvmSwap,
isBvmSwap,
isValidFromAddress,
isValidToAddress,
supportedWalletVMs,
fromChainWalletVMSupported,
toChainWalletVMSupported,
isRecipientLinked,
recipientWalletSupportsChain,
gasTopUpEnabled,
setGasTopUpEnabled,
gasTopUpRequired,
gasTopUpAmount,
gasTopUpAmountUsd,
invalidateBalanceQueries,
invalidateQuoteQuery,
setUseExternalLiquidity,
setDetails,
setSwapError,
quoteInProgress,
setQuoteInProgress,
linkedWallet,
quoteParameters,
abortController,
fromTokenPriceData,
toTokenPriceData,
isLoadingFromTokenPrice,
isLoadingToTokenPrice
}) }));
};
exports.default = SwapWidgetRenderer;
//# sourceMappingURL=SwapWidgetRenderer.js.map