UNPKG

@reservoir0x/relay-kit-ui

Version:

Relay is the Fastest and Cheapest Way to Bridge and Transact Across Chains.

245 lines 11.4 kB
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime"; import { useMemo, useState, useEffect, useContext } from 'react'; import { parseUnits } from 'viem'; import {} from '@reservoir0x/relay-sdk'; import { calculateFillTime, extractDepositRequestId } from '../../../utils/relayTransaction.js'; import { useQuote, useRequests, useExecutionStatus } from '@reservoir0x/relay-kit-hooks'; import { useRelayClient } from '../../../hooks/index.js'; import { EventNames } from '../../../constants/events.js'; import { ProviderOptionsContext } from '../../../providers/RelayKitProvider.js'; import { useAccount } from 'wagmi'; import { calculatePriceTimeEstimate, extractDepositAddress, extractQuoteId } from '../../../utils/quote.js'; import { getDeadAddress } from '@reservoir0x/relay-sdk'; import { useQueryClient } from '@tanstack/react-query'; import { bitcoin } from '../../../utils/bitcoin.js'; import { errorToJSON } from '../../../utils/errors.js'; import { sha256 } from '../../../utils/hashing.js'; import { get15MinuteInterval } from '../../../utils/time.js'; export var TransactionProgressStep; (function (TransactionProgressStep) { TransactionProgressStep[TransactionProgressStep["WaitingForDeposit"] = 0] = "WaitingForDeposit"; TransactionProgressStep[TransactionProgressStep["Validating"] = 1] = "Validating"; TransactionProgressStep[TransactionProgressStep["Success"] = 2] = "Success"; TransactionProgressStep[TransactionProgressStep["Error"] = 3] = "Error"; })(TransactionProgressStep || (TransactionProgressStep = {})); export const DepositAddressModalRenderer = ({ open, address, fromChain, fromToken, toToken, debouncedInputAmountValue, debouncedOutputAmountValue, recipient, invalidateBalanceQueries, children, onSuccess, onAnalyticEvent, onSwapError }) => { const queryClient = useQueryClient(); const [progressStep, setProgressStep] = useState(TransactionProgressStep.WaitingForDeposit); const [swapError, setSwapError] = useState(null); const relayClient = useRelayClient(); const providerOptionsContext = useContext(ProviderOptionsContext); const { connector } = useAccount(); const deadAddress = getDeadAddress(fromChain?.vmType, fromChain?.id); const quoteParameters = fromToken && toToken ? { user: deadAddress, originChainId: fromToken.chainId, destinationChainId: toToken.chainId, originCurrency: fromToken.address, destinationCurrency: toToken.address, recipient: recipient, tradeType: 'EXACT_INPUT', appFees: providerOptionsContext.appFees, amount: parseUnits(debouncedInputAmountValue, fromToken.decimals).toString(), referrer: relayClient?.source ?? undefined, useDepositAddress: true } : undefined; const { data: quoteData, isLoading: isFetchingQuote, isRefetching, error: quoteError, queryKey } = useQuote(relayClient ? relayClient : undefined, undefined, quoteParameters, (options, config) => { const interval = get15MinuteInterval(); const quoteRequestId = sha256({ ...options, interval }); onAnalyticEvent?.(EventNames.QUOTE_REQUESTED, { parameters: options, httpConfig: config, quote_request_id: quoteRequestId, chain_id_in: options?.originChainId, chain_id_out: options?.destinationChainId }); }, ({ steps, details }, options) => { const interval = get15MinuteInterval(); const quoteRequestId = sha256({ ...options, interval }); onAnalyticEvent?.(EventNames.QUOTE_RECEIVED, { parameters: options, wallet_connector: connector?.name, quote_id: steps ? extractQuoteId(steps) : undefined, quote_request_id: quoteRequestId, 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 }); }, { enabled: Boolean(open && progressStep === TransactionProgressStep.WaitingForDeposit && relayClient && debouncedInputAmountValue && debouncedInputAmountValue.length > 0 && Number(debouncedInputAmountValue) !== 0 && fromToken !== undefined && toToken !== undefined), refetchOnWindowFocus: false, refetchOnReconnect: false, refetchInterval: false, refetchOnMount: false, retryOnMount: false, staleTime: Infinity }, (e) => { const errorMessage = errorToJSON(e?.response?.data?.message ? new Error(e?.response?.data?.message) : e); const interval = get15MinuteInterval(); const quoteRequestId = sha256({ ...quoteParameters, interval }); onAnalyticEvent?.(EventNames.QUOTE_ERROR, { wallet_connector: connector?.name, error_message: errorMessage, parameters: quoteParameters, quote_request_id: quoteRequestId }); }); const quote = isFetchingQuote || isRefetching ? undefined : quoteData; const requestId = useMemo(() => extractDepositRequestId(quote?.steps), [quote]); const depositAddress = useMemo(() => extractDepositAddress(quote?.steps), [quote]); useEffect(() => { if (!open) { if (quote) { onAnalyticEvent?.(EventNames.DEPOSIT_ADDRESS_MODAL_CLOSED); } setSwapError(null); queryClient.invalidateQueries({ queryKey }); } else { setProgressStep(TransactionProgressStep.WaitingForDeposit); onAnalyticEvent?.(EventNames.DEPOSIT_ADDRESS_MODAL_OPEN); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [open]); const { data: executionStatus } = useExecutionStatus(relayClient ? relayClient : undefined, { requestId: requestId ?? undefined, referrer: relayClient?.source }, undefined, undefined, { enabled: requestId !== null && open, refetchInterval(query) { const observableStates = ['waiting', 'pending', 'delayed']; if (!query.state.data?.status || (requestId && observableStates.includes(query.state.data?.status))) { return 1000; } return 0; } }); useEffect(() => { if (executionStatus?.status === 'failure' || executionStatus?.status === 'refund' || quoteError) { const swapError = new Error(executionStatus?.details ?? 'Oops! Something went wrong while processing your transaction.'); if (progressStep !== TransactionProgressStep.Error) { onSwapError?.(swapError.message, quote); } setProgressStep(TransactionProgressStep.Error); onAnalyticEvent?.(EventNames.DEPOSIT_ADDRESS_SWAP_ERROR, { error_message: errorToJSON(executionStatus?.details ?? quoteError), wallet_connector: connector?.name, quote_id: requestId, amount_in: parseFloat(`${debouncedInputAmountValue}`), currency_in: fromToken?.symbol, chain_id_in: fromToken?.chainId, amount_out: parseFloat(`${debouncedOutputAmountValue}`), currency_out: toToken?.symbol, chain_id_out: toToken?.chainId, txHashes: executionStatus?.txHashes ?? [] }); setSwapError(swapError); invalidateBalanceQueries(); } else if (executionStatus?.status === 'success') { if (progressStep !== TransactionProgressStep.Success) { onSuccess?.(quote, executionStatus); } setProgressStep(TransactionProgressStep.Success); invalidateBalanceQueries(); } else if (executionStatus?.status === 'pending') { const timeEstimateMs = ((quote?.details?.timeEstimate ?? 0) + (fromChain && fromChain.id === bitcoin.id ? 600 : 0)) * 1000; const isDelayedTx = timeEstimateMs > (relayClient?.maxPollingAttemptsBeforeTimeout ?? 30) * (relayClient?.pollingInterval ?? 5000); if (isDelayedTx) { setProgressStep(TransactionProgressStep.Success); } else { setProgressStep(TransactionProgressStep.Validating); } } }, [executionStatus?.status, quoteError]); const allTxHashes = useMemo(() => { const isRefund = executionStatus?.status === 'refund'; const _allTxHashes = []; executionStatus?.txHashes?.forEach((txHash) => { _allTxHashes.push({ txHash, chainId: isRefund ? fromToken?.chainId : toToken?.chainId }); }); executionStatus?.inTxHashes?.forEach((txHash) => { _allTxHashes.push({ txHash, chainId: fromToken?.chainId }); }); return _allTxHashes; }, [executionStatus?.txHashes, executionStatus?.inTxHashes]); const { data: transactions, isLoading: isLoadingTransaction } = useRequests((progressStep === TransactionProgressStep.Success || progressStep === TransactionProgressStep.Error) && allTxHashes[0] ? { user: address, hash: allTxHashes[0]?.txHash } : undefined, relayClient?.baseApiUrl, { enabled: (progressStep === TransactionProgressStep.Success || progressStep === TransactionProgressStep.Error) && allTxHashes[0] ? true : false, refetchOnWindowFocus: false, refetchOnReconnect: false, refetchInterval: false, retryOnMount: false }); const transaction = transactions[0]; const { fillTime, seconds } = calculateFillTime(transaction); const timeEstimate = calculatePriceTimeEstimate(quote?.details); const toChain = toToken?.chainId ? relayClient?.chains.find((chain) => chain.id === toToken?.chainId) : null; return (_jsx(_Fragment, { children: children({ progressStep, setProgressStep, quote, isFetchingQuote: isFetchingQuote || isRefetching, quoteError, swapError, setSwapError, allTxHashes, transaction, fillTime, seconds, requestId, depositAddress, executionStatus, isLoadingTransaction, toChain, timeEstimate }) })); }; //# sourceMappingURL=DepositAddressModalRenderer.js.map