@reservoir0x/relay-kit-ui
Version:
Relay is the Fastest and Cheapest Way to Bridge and Transact Across Chains.
286 lines • 15.8 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.OnrampModal = exports.OnrampProcessingStep = exports.OnrampStep = void 0;
const tslib_1 = require("tslib");
const jsx_runtime_1 = require("react/jsx-runtime");
const relay_sdk_1 = require("@reservoir0x/relay-sdk");
const react_1 = require("react");
const Modal_js_1 = require("../../../common/Modal.js");
const useRelayClient_js_1 = tslib_1.__importDefault(require("../../../../hooks/useRelayClient.js"));
const events_js_1 = require("../../../../constants/events.js");
const relay_kit_hooks_1 = require("@reservoir0x/relay-kit-hooks");
const relayTransaction_js_1 = require("../../../../utils/relayTransaction.js");
const viem_1 = require("viem");
const quote_js_1 = require("../../../../utils/quote.js");
const getTxBlockExplorerUrl_js_1 = require("../../../../utils/getTxBlockExplorerUrl.js");
const OnrampConfirmingStep_js_1 = require("./steps/OnrampConfirmingStep.js");
const OnrampProcessingStepUI_js_1 = require("./steps/OnrampProcessingStepUI.js");
const OnrampProcessingPassthroughStep_js_1 = require("./steps/OnrampProcessingPassthroughStep.js");
const OnrampSuccessStep_js_1 = require("./steps/OnrampSuccessStep.js");
const OnrampMoonPayStep_js_1 = require("./steps/OnrampMoonPayStep.js");
const numbers_js_1 = require("../../../../utils/numbers.js");
const ErrorStep_js_1 = require("../../../common/TransactionModal/steps/ErrorStep.js");
const errors_js_1 = require("../../../../utils/errors.js");
const wagmi_1 = require("wagmi");
const chains_1 = require("viem/chains");
var OnrampStep;
(function (OnrampStep) {
OnrampStep[OnrampStep["Confirming"] = 0] = "Confirming";
OnrampStep[OnrampStep["Moonpay"] = 1] = "Moonpay";
OnrampStep[OnrampStep["Processing"] = 2] = "Processing";
OnrampStep[OnrampStep["ProcessingPassthrough"] = 3] = "ProcessingPassthrough";
OnrampStep[OnrampStep["Success"] = 4] = "Success";
OnrampStep[OnrampStep["Error"] = 5] = "Error";
})(OnrampStep || (exports.OnrampStep = OnrampStep = {}));
var OnrampProcessingStep;
(function (OnrampProcessingStep) {
OnrampProcessingStep[OnrampProcessingStep["Finalizing"] = 0] = "Finalizing";
OnrampProcessingStep[OnrampProcessingStep["Relaying"] = 1] = "Relaying";
})(OnrampProcessingStep || (exports.OnrampProcessingStep = OnrampProcessingStep = {}));
const OnrampModal = ({ open, amount, amountFormatted, recipient, fromToken, toToken, toChain, fromChain, fiatCurrency, isPassthrough, amountToTokenFormatted, moonPayCurrencyCode, usdRate, moonPayThemeId, moonPayThemeMode, moonPayApiKey, moonpayOnUrlSignatureRequested, onAnalyticEvent, onSuccess, onError, onOpenChange }) => {
const [swapError, setSwapError] = (0, react_1.useState)(null);
const [step, setStep] = (0, react_1.useState)(OnrampStep.Confirming);
const [processingStep, setProcessingStep] = (0, react_1.useState)();
const [moonPayRequestId, setMoonPayRequestId] = (0, react_1.useState)();
const client = (0, useRelayClient_js_1.default)();
const { connector } = (0, wagmi_1.useAccount)();
const [moonPayIdAppended, setMoonPayIdAppended] = (0, react_1.useState)(false);
const { data: ethTokenPriceResponse } = (0, relay_kit_hooks_1.useTokenPrice)(client?.baseApiUrl, {
address: viem_1.zeroAddress,
chainId: chains_1.mainnet.id,
referrer: client?.source
}, {
refetchInterval: 60000 * 5,
refetchOnWindowFocus: false
});
const [passthroughExternalId, setPassthroughExternalId] = (0, react_1.useState)();
(0, react_1.useEffect)(() => {
if (!open) {
setStep(OnrampStep.Confirming);
setProcessingStep(undefined);
setMoonPayRequestId(undefined);
setMoonPayIdAppended(false);
setSwapError(null);
setPassthroughExternalId(undefined);
}
else {
if (isPassthrough) {
setStep(OnrampStep.Moonpay);
setPassthroughExternalId(`${recipient ? recipient.slice(recipient.length - 5) : ''}${Date.now()}`);
}
onAnalyticEvent?.(events_js_1.EventNames.ONRAMP_MODAL_OPEN, {
isPassthrough
});
}
}, [open]);
const ethAmount = ethTokenPriceResponse && ethTokenPriceResponse.price
? +(amount ?? '0') / ethTokenPriceResponse.price
: 0;
const { data: quote, error: quoteError, isFetching: isFetchingQuote } = (0, relay_kit_hooks_1.useQuote)(client ?? undefined, undefined, {
originChainId: fromToken.chainId,
originCurrency: fromToken.address,
destinationChainId: toToken.chainId,
destinationCurrency: toToken.address,
useDepositAddress: true,
tradeType: 'EXACT_INPUT',
amount: fromToken.symbol === 'USDC'
? (0, viem_1.parseUnits)(`${amount}`, 6).toString()
: (0, viem_1.parseUnits)(`${ethAmount}`, fromToken.decimals).toString(),
user: (0, relay_sdk_1.getDeadAddress)(),
recipient
}, undefined, undefined, {
refetchOnMount: false,
refetchOnWindowFocus: false,
refetchOnReconnect: false,
enabled: Boolean(amount &&
amount.length > 0 &&
toToken &&
fromToken &&
!isPassthrough &&
recipient !== undefined &&
open)
});
const totalAmount = quote?.fees && amount && !isPassthrough
? `${Math.floor((Number(quote.fees.relayer?.amountUsd ?? 0) +
Number(quote.fees.gas?.amountUsd ?? 0) +
Number(quote.fees.app?.amountUsd ?? 0) +
+amount) *
100) / 100}`
: amount;
const ethTotalAmount = (0, numbers_js_1.formatBN)(totalAmount ? +totalAmount / (ethTokenPriceResponse?.price ?? 0) : 0, 5, 18);
const toTokenTotalAmount = (0, numbers_js_1.formatBN)(+(totalAmount ?? '0') / (usdRate ?? 0), 5, toToken.decimals);
const depositAddress = (0, react_1.useMemo)(() => (0, quote_js_1.extractDepositAddress)(quote?.steps), [quote]);
const baseTransactionUrl = client?.baseApiUrl.includes('testnets')
? 'https://testnets.relay.link'
: 'https://relay.link';
const requestId = (0, react_1.useMemo)(() => (0, relayTransaction_js_1.extractDepositRequestId)(quote?.steps), [quote]);
const { data: executionStatus } = (0, relay_kit_hooks_1.useExecutionStatus)(client ? client : undefined, {
requestId: requestId ?? undefined,
referrer: client?.source
}, undefined, undefined, {
enabled: requestId !== null && step === OnrampStep.Processing && open,
refetchInterval(query) {
const observableStates = ['waiting', 'pending', 'delayed'];
if (!query.state.data?.status ||
(requestId && observableStates.includes(query.state.data?.status))) {
return 1000;
}
return 0;
}
});
const fillTxHash = (0, react_1.useMemo)(() => {
if (executionStatus?.txHashes && executionStatus?.txHashes[0]) {
return executionStatus?.txHashes[0];
}
}, [executionStatus]);
const { data: transactions, isLoading: isLoadingTransaction } = (0, relay_kit_hooks_1.useRequests)(step === OnrampStep.Success && fillTxHash
? {
user: recipient,
hash: fillTxHash
}
: undefined, client?.baseApiUrl, {
enabled: Boolean(step === OnrampStep.Success && fillTxHash),
refetchOnWindowFocus: false,
refetchOnReconnect: false,
refetchInterval: false,
retryOnMount: false
});
const transaction = transactions && transactions[0] ? transactions[0] : null;
const toAmountFormatted = transaction?.data?.metadata?.currencyOut
?.amountFormatted
? ((0, numbers_js_1.formatBN)(+transaction.data.metadata.currencyOut.amountFormatted, 5, transaction?.data?.metadata?.currencyOut?.currency?.decimals ?? 18) ?? undefined)
: amountToTokenFormatted;
const fillTxUrl = fillTxHash
? (0, getTxBlockExplorerUrl_js_1.getTxBlockExplorerUrl)(toToken.chainId, client?.chains, fillTxHash)
: undefined;
const moonpayTxUrl = moonPayRequestId
? `https://buy.moonpay.com/transaction_receipt?transactionId=${moonPayRequestId}`
: null;
(0, react_1.useEffect)(() => {
if (executionStatus?.status === 'pending' &&
(step !== OnrampStep.Processing ||
processingStep !== OnrampProcessingStep.Relaying)) {
setStep(OnrampStep.Processing);
setProcessingStep(OnrampProcessingStep.Relaying);
}
if (executionStatus?.status === 'success') {
setStep(OnrampStep.Success);
onAnalyticEvent?.(events_js_1.EventNames.ONRAMP_SUCCESS, {
chain_id_in: fromToken?.chainId,
currency_in: fromToken?.symbol,
chain_id_out: toToken?.chainId,
currency_out: toToken?.symbol,
quote_id: requestId,
txHashes: executionStatus.txHashes,
amount,
totalAmount,
ethTotalAmount,
moonPayRequestId,
isPassthrough
});
onSuccess?.(quote, moonPayRequestId);
setProcessingStep(undefined);
}
if (executionStatus?.status === 'failure' ||
executionStatus?.status === 'refund' ||
quoteError) {
const swapError = new Error(executionStatus?.details ??
'Oops! Something went wrong while processing your transaction.');
onOnrampError((0, errors_js_1.errorToJSON)(executionStatus?.details ?? quoteError), swapError);
}
}, [executionStatus, quoteError]);
(0, react_1.useEffect)(() => {
if (moonPayRequestId &&
quote &&
executionStatus?.inTxHashes &&
executionStatus?.inTxHashes[0] &&
!moonPayIdAppended) {
setMoonPayIdAppended(true);
(0, quote_js_1.appendMetadataToRequest)(client?.baseApiUrl, `${requestId}`, {
moonPayId: moonPayRequestId
}, client?.source)
?.then(() => {
client?.log(['Posting MoonPay request id', moonPayRequestId, requestId], relay_sdk_1.LogLevel.Verbose);
})
.catch((e) => {
setMoonPayIdAppended(false);
throw e;
});
}
}, [moonPayRequestId, executionStatus]);
const allTxHashes = (0, react_1.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 onOnrampError = (0, react_1.useCallback)((errorMsg, error) => {
if (step !== OnrampStep.Error) {
onError?.(error.message, quote, moonPayRequestId);
}
setStep(OnrampStep.Error);
onAnalyticEvent?.(events_js_1.EventNames.ONRAMP_ERROR, {
error_message: errorMsg,
wallet_connector: connector?.name,
quote_id: requestId,
amount_in: amount,
currency_in: fromToken?.symbol,
chain_id_in: fromToken?.chainId,
amount_out: quote?.details?.currencyOut?.amountFormatted,
currency_out: toToken?.symbol,
chain_id_out: toToken?.chainId,
txHashes: executionStatus?.txHashes ?? []
});
setSwapError(error);
}, [
executionStatus,
connector,
requestId,
quote,
toToken,
fromToken,
amount,
swapError,
moonPayRequestId,
step
]);
return ((0, jsx_runtime_1.jsxs)(Modal_js_1.Modal, { trigger: null, open: open, onOpenChange: (open) => {
if (!open) {
onAnalyticEvent?.(events_js_1.EventNames.ONRAMP_MODAL_CLOSE);
}
onOpenChange(open);
}, css: {
overflow: 'hidden',
p: '4',
maxWidth: '412px !important'
}, children: [step === OnrampStep.Confirming ? ((0, jsx_runtime_1.jsx)(OnrampConfirmingStep_js_1.OnrampConfirmingStep, { toToken: toToken, fromToken: fromToken, fromChain: fromChain, toChain: toChain, requestId: requestId ?? undefined, depositAddress: depositAddress, recipient: recipient, amount: amount, totalAmount: totalAmount ?? undefined, ethTotalAmount: ethTotalAmount, isFetchingQuote: isFetchingQuote, onAnalyticEvent: onAnalyticEvent, setStep: setStep })) : null, (0, jsx_runtime_1.jsx)(OnrampMoonPayStep_js_1.OnrampMoonPayStep, { step: step, processingStep: processingStep, toToken: toToken, fromToken: fromToken, fromChain: fromChain, toChain: toChain, recipient: recipient, depositAddress: depositAddress, totalAmount: isPassthrough
? toTokenTotalAmount
: fromToken.symbol === 'ETH'
? ethTotalAmount
: (totalAmount ?? undefined), fiatCurrency: fiatCurrency, isPassthrough: isPassthrough, moonPayCurrencyCode: moonPayCurrencyCode, onAnalyticEvent: onAnalyticEvent, setStep: setStep, setProcessingStep: setProcessingStep, setMoonPayRequestId: setMoonPayRequestId, moonpayOnUrlSignatureRequested: moonpayOnUrlSignatureRequested, onPassthroughSuccess: () => {
setStep(OnrampStep.Success);
onAnalyticEvent?.(events_js_1.EventNames.ONRAMP_PASSTHROUGH_SUCCESS, {
moonPayRequestId,
amount,
totalAmount,
ethTotalAmount
});
}, moonPayThemeId: moonPayThemeId, moonPayThemeMode: moonPayThemeMode, moonPayApiKey: moonPayApiKey, quoteRequestId: requestId, passthroughExternalId: passthroughExternalId, onError: (error) => {
onOnrampError(error.message, error);
} }), step === OnrampStep.ProcessingPassthrough ? ((0, jsx_runtime_1.jsx)(OnrampProcessingPassthroughStep_js_1.OnrampProcessingPassthroughStep, { toToken: toToken, amountToTokenFormatted: amountToTokenFormatted, moonpayTxUrl: moonpayTxUrl ?? undefined, amount: amountFormatted })) : null, step === OnrampStep.Processing ? ((0, jsx_runtime_1.jsx)(OnrampProcessingStepUI_js_1.OnrampProcessingStepUI, { toToken: toToken, fromToken: fromToken, fromChain: fromChain, toChain: toChain, moonpayTxUrl: moonpayTxUrl ?? undefined, fillTxUrl: fillTxUrl, fillTxHash: fillTxHash, processingStep: processingStep, baseTransactionUrl: baseTransactionUrl, requestId: requestId ?? undefined })) : null, step === OnrampStep.Success ? ((0, jsx_runtime_1.jsx)(OnrampSuccessStep_js_1.OnrampSuccessStep, { toToken: toToken, isLoadingTransaction: isLoadingTransaction, fillTxHash: fillTxHash, fillTxUrl: fillTxUrl, moonpayTxUrl: moonpayTxUrl ?? undefined, toAmountFormatted: toAmountFormatted, baseTransactionUrl: baseTransactionUrl, onOpenChange: onOpenChange })) : null, step === OnrampStep.Error ? ((0, jsx_runtime_1.jsx)(ErrorStep_js_1.ErrorStep, { error: quoteError || swapError, allTxHashes: allTxHashes, address: recipient, onOpenChange: onOpenChange, transaction: transaction ?? undefined, fromChain: fromChain, toChain: toChain })) : null] }));
};
exports.OnrampModal = OnrampModal;
//# sourceMappingURL=OnrampModal.js.map