UNPKG

@reservoir0x/relay-kit-ui

Version:

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

332 lines 24.8 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import OnrampWidgetRenderer from './OnrampWidgetRenderer.js'; import { Box, Button, Flex, Text } from '../../../primitives/index.js'; import AmountInput from '../../../common/AmountInput.js'; import { useCallback, useContext, useEffect, useState } from 'react'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faArrowDownLong, faArrowUpLong, faClipboard, faCreditCard } from '@fortawesome/free-solid-svg-icons'; import TokenSelector from '../../../common/TokenSelector/TokenSelector.js'; import { EventNames } from '../../../../constants/events.js'; import { TokenTrigger } from '../../../common/TokenSelector/triggers/TokenTrigger.js'; import { MultiWalletDropdown } from '../../../common/MultiWalletDropdown.js'; import { CustomAddressModal } from '../../../common/CustomAddressModal.js'; import { useAccount } from 'wagmi'; import { OnrampModal } from '../modals/OnrampModal.js'; import { formatBN } from '../../../../utils/numbers.js'; import { findSupportedWallet } from '../../../../utils/address.js'; import { ProviderOptionsContext } from '../../../../providers/RelayKitProvider.js'; const OnrampWidget = ({ defaultWalletAddress, moonPayApiKey, moonpayOnUrlSignatureRequested, linkedWallets, multiWalletSupportEnabled, supportedWalletVMs, moonPayThemeId, moonPayThemeMode, token, setToken, disablePasteWalletAddressOption, onTokenChange, onConnectWallet, onLinkNewWallet, onSetPrimaryWallet, onAnalyticEvent: _onAnalyticEvent, onSuccess }) => { const onAnalyticEvent = useCallback((eventName, data) => { try { _onAnalyticEvent?.(eventName, data); } catch (e) { console.error('Error in onAnalyticEvent', eventName, data, e); } }, [_onAnalyticEvent]); const [addressModalOpen, setAddressModalOpen] = useState(false); const [onrampModalOpen, setOnrampModalOpen] = useState(false); const { isConnected } = useAccount(); const providerOptionsContext = useContext(ProviderOptionsContext); const connectorKeyOverrides = providerOptionsContext.vmConnectorKeyOverrides; return (_jsx(OnrampWidgetRenderer, { defaultWalletAddress: defaultWalletAddress, supportedWalletVMs: supportedWalletVMs, linkedWallets: linkedWallets, multiWalletSupportEnabled: multiWalletSupportEnabled, moonPayApiKey: moonPayApiKey, token: token, setToken: setToken, children: ({ displayCurrency, setDisplayCurrency, recipient, setRecipient, isRecipientLinked, isValidRecipient, amount, amountToToken, setInputValue, amountToTokenFormatted, token, fromToken, setToken, toChain, fromChain, toDisplayName, toChainWalletVMSupported, fiatCurrency, setFiatCurrency, minAmountCurrency, notEnoughFiat, ctaCopy, moonPayCurrencyCode, isPassthrough, usdRate }) => { //Reset recipient if no longer valid useEffect(() => { if (multiWalletSupportEnabled && fromChain && recipient && linkedWallets && !isValidRecipient) { const supportedAddress = findSupportedWallet(fromChain, recipient, linkedWallets, connectorKeyOverrides); if (supportedAddress) { onSetPrimaryWallet?.(supportedAddress); } } if (multiWalletSupportEnabled && toChain && recipient && linkedWallets && !isValidRecipient) { setRecipient(undefined); } }, [ multiWalletSupportEnabled, fromChain?.id, toChain?.id, linkedWallets, onSetPrimaryWallet, isValidRecipient, connectorKeyOverrides ]); const formattedAmount = amount === '' ? '' : amount.endsWith('.') ? new Intl.NumberFormat(undefined, { style: 'currency', currency: 'USD', currencyDisplay: 'narrowSymbol', minimumFractionDigits: 0, maximumFractionDigits: 0 }).format(+amount) + '.' : new Intl.NumberFormat(undefined, { style: 'currency', currency: 'USD', currencyDisplay: 'narrowSymbol', minimumFractionDigits: amount.includes('.0') ? 1 : amount.endsWith('0') && amount.includes('.') ? 2 : 0, maximumFractionDigits: amount.includes('.') ? 2 : 0, minimumSignificantDigits: 1, maximumSignificantDigits: amount.length }).format(+amount); return (_jsxs("div", { className: "relay-kit-reset", style: { maxWidth: 408, minWidth: 308, width: '100%' }, children: [_jsx(Flex, { direction: "column", css: { gap: '2', border: 'widget-border', width: '100%' }, children: _jsxs(Flex, { direction: "column", css: { width: '100%', overflow: 'hidden', borderRadius: 'widget-card-border-radius', backgroundColor: 'widget-background', border: 'widget-card-border', mb: 'widget-card-section-gutter', px: '4', pt: '40px', pb: '24px' }, children: [_jsx(Text, { style: "subtitle2", color: "subtle", css: { textAlign: 'center' }, children: "Enter an amount" }), _jsx(AmountInput, { value: displayCurrency ? amountToToken !== '' ? `${amountToToken} ${token.symbol}` : '' : formattedAmount, setValue: (e) => { //unused }, placeholder: ` 0`, onChange: (e) => { const input = e.target; setInputValue(input.value); if (displayCurrency) { setTimeout(() => { const numericValue = input.value.match(/[\d.]+/g); const numericValueLength = numericValue !== null ? numericValue.join('').length : 0; input.setSelectionRange(numericValueLength, numericValueLength); }, 0); } }, onKeyDown: (e) => { const input = e.target; const cursorPosition = input.selectionStart; // Prevent multiple decimals if (e.key === '.' && (input.value.match(/\./g) || []).length > 0) { e.preventDefault(); // Prevent the key press if there's already a decimal return; } if (e.key === 'ArrowLeft' && cursorPosition !== null) { const valueBeforeCursor = input.value.substring(0, cursorPosition); const charBeforeCursor = valueBeforeCursor.charAt(cursorPosition - 1); if (charBeforeCursor === '$') { e.preventDefault(); } } if (e.key === 'ArrowRight' && cursorPosition !== null) { const valueAfterCursor = input.value.substring(0, cursorPosition + 1); const charAfterCursor = valueAfterCursor.charAt(cursorPosition); if (charAfterCursor === ' ') { e.preventDefault(); } } }, onMouseDown: (e) => { const input = e.target; input.style.caretColor = 'transparent'; }, onMouseUp: (e) => { const input = e.target; const cursorPosition = input.selectionStart; // Get the current cursor position if (cursorPosition !== null) { const valueAfterCursor = input.value.substring(0, cursorPosition + 1); const charAfterCursor = valueAfterCursor.charAt(cursorPosition); const valueBeforeCursor = input.value.substring(0, cursorPosition); const charBeforeCursor = valueBeforeCursor.charAt(cursorPosition - 1); const specialCharacterRegex = /[ a-zA-Z]/; const alphaRegex = /[a-zA-Z]/; if (charAfterCursor === '$' || alphaRegex.test(charAfterCursor) || specialCharacterRegex.test(charBeforeCursor)) { e.preventDefault(); e.stopPropagation(); input.setSelectionRange(1, 1); } } input.style.caretColor = 'initial'; }, css: { fontWeight: '700', fontSize: 48, lineHeight: '58px', textAlign: 'center', textIndent: amount === '' || amountToToken === '' ? '-36px' : undefined, whiteSpace: 'pre', _placeholder: { color: 'text-subtle' } }, containerCss: { mb: '2', width: '100%' } }), notEnoughFiat ? (_jsxs(Text, { color: "red", css: { mb: 24, textAlign: 'center' }, children: ["Minimum amount is", ' ', displayCurrency && minAmountCurrency ? `${minAmountCurrency} ${token.symbol}` : '$20'] })) : undefined, _jsxs("button", { style: { gap: '8px', cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', marginBottom: '16px', alignSelf: 'center' }, onClick: () => { const _displayCurrency = !displayCurrency; setDisplayCurrency(_displayCurrency); if (_displayCurrency) { let _amountToToken = 21 / usdRate; if (+amountToToken > _amountToToken) { _amountToToken = +amountToToken; } setInputValue(formatBN(_amountToToken, 5, token.decimals, false), _displayCurrency); } }, children: [_jsx(Text, { style: "body2", color: "subtle", children: displayCurrency ? formattedAmount : `${amountToTokenFormatted} ${token.symbol}` }), _jsxs(Flex, { css: { color: 'gray8' }, children: [_jsx(FontAwesomeIcon, { style: { height: 14 }, icon: faArrowUpLong }), _jsx(FontAwesomeIcon, { style: { height: 14 }, icon: faArrowDownLong })] })] }), _jsx(TokenSelector, { address: recipient, isValidAddress: isValidRecipient, token: token, onAnalyticEvent: onAnalyticEvent, fromChainWalletVMSupported: false, supportedWalletVMs: [], setToken: (token) => { setToken(token); onTokenChange?.(token); }, context: "to", trigger: _jsx("div", { style: { width: 'max-content', margin: '0 auto', marginBottom: '16px' }, children: _jsx(TokenTrigger, { isSingleChainLocked: true, token: token }) }) }), _jsxs(Flex, { css: { gap: '2', margin: '0 auto' }, children: [_jsx(Button, { color: "white", corners: "pill", css: { minHeight: 28, px: 3, py: 1, _light: { filter: amount === '100' && !displayCurrency ? 'brightness(97%)' : undefined }, _dark: { filter: amount === '100' && !displayCurrency ? 'brightness(130%)' : undefined } }, onClick: () => { setDisplayCurrency(false); setInputValue('100', false); }, children: _jsx(Text, { style: "subtitle2", children: "$100" }) }), _jsx(Button, { color: "white", corners: "pill", css: { minHeight: 28, px: 3, py: 1, _light: { filter: amount === '300' && !displayCurrency ? 'brightness(97%)' : undefined }, _dark: { filter: amount === '300' && !displayCurrency ? 'brightness(130%)' : undefined } }, onClick: () => { setDisplayCurrency(false); setInputValue('300', false); }, children: _jsx(Text, { style: "subtitle2", children: "$300" }) }), _jsx(Button, { color: "white", corners: "pill", css: { minHeight: 28, px: 3, py: 1, _light: { filter: amount === '1000' && !displayCurrency ? 'brightness(97%)' : undefined }, _dark: { filter: amount === '1000' && !displayCurrency ? 'brightness(130%)' : undefined } }, onClick: () => { setDisplayCurrency(false); setInputValue('1000', false); }, children: _jsx(Text, { style: "subtitle2", children: "$1,000" }) })] })] }) }), _jsxs(Flex, { direction: "column", css: { width: '100%', overflow: 'hidden', borderRadius: 'widget-card-border-radius', backgroundColor: 'widget-background', border: 'widget-card-border', mb: 'widget-card-section-gutter', p: '4' }, children: [_jsxs(Flex, { justify: "between", align: "center", css: { mb: '2' }, children: [_jsx(Text, { color: "subtle", style: "subtitle2", children: "Recipient" }), multiWalletSupportEnabled === true && toChainWalletVMSupported ? (_jsx(MultiWalletDropdown, { context: "destination", selectedWalletAddress: recipient, onSelect: (wallet) => setRecipient(wallet.address), chain: toChain, onLinkNewWallet: () => { if ((!linkedWallets || linkedWallets.length === 0) && toChainWalletVMSupported) { onConnectWallet?.(); } else { onLinkNewWallet?.({ chain: toChain, direction: 'to' })?.then((wallet) => { onSetPrimaryWallet?.(wallet.address); }); } }, setAddressModalOpen: setAddressModalOpen, wallets: linkedWallets, onAnalyticEvent: onAnalyticEvent, disablePasteWalletAddressOption: disablePasteWalletAddressOption })) : null, !multiWalletSupportEnabled || !toChainWalletVMSupported ? (_jsxs(Button, { color: isValidRecipient && !isRecipientLinked ? 'warning' : 'secondary', corners: "pill", size: "none", css: { display: 'flex', alignItems: 'center', px: '2', py: '1' }, onClick: () => { setAddressModalOpen(true); onAnalyticEvent?.(EventNames.SWAP_ADDRESS_MODAL_CLICKED); }, children: [isValidRecipient && !isRecipientLinked ? (_jsx(Box, { css: { color: 'amber11' }, children: _jsx(FontAwesomeIcon, { icon: faClipboard, width: 16, height: 16 }) })) : null, _jsx(Text, { style: "subtitle2", css: { color: isValidRecipient && !isRecipientLinked ? 'amber11' : 'anchor-color' }, children: !isValidRecipient ? `Enter Address` : toDisplayName })] })) : null] }), _jsxs(Flex, { justify: "between", align: "center", children: [_jsx(Text, { color: "subtle", style: "subtitle2", children: "Paying with" }), _jsxs(Flex, { css: { alignItems: 'center', gap: '2', ml: 'auto', mr: '2', color: 'gray9' }, children: [_jsx(FontAwesomeIcon, { style: { width: 16 }, icon: faCreditCard }), _jsx(Text, { style: "subtitle2", children: "Card" })] })] })] }), _jsx(Button, { css: { width: '100%', justifyContent: 'center' }, disabled: notEnoughFiat, onClick: () => { if (!recipient && toChainWalletVMSupported) { if (!linkedWallets || linkedWallets.length === 0) { onConnectWallet?.(); } else { onLinkNewWallet?.({ chain: toChain, direction: 'to' })?.then((wallet) => { onSetPrimaryWallet?.(wallet.address); }); } } else if (!recipient) { setAddressModalOpen(true); } else { setOnrampModalOpen(true); } }, children: ctaCopy }), _jsx(CustomAddressModal, { open: addressModalOpen, toAddress: recipient, toChain: toChain, isConnected: (linkedWallets && linkedWallets.length > 0) || isConnected ? true : false, linkedWallets: linkedWallets ?? [], multiWalletSupportEnabled: multiWalletSupportEnabled, onAnalyticEvent: onAnalyticEvent, onOpenChange: (open) => { setAddressModalOpen(open); }, onConfirmed: (address) => { setRecipient(address); }, onClear: () => { setRecipient(undefined); } }), _jsx(OnrampModal, { open: onrampModalOpen, onOpenChange: setOnrampModalOpen, onAnalyticEvent: onAnalyticEvent, moonpayOnUrlSignatureRequested: moonpayOnUrlSignatureRequested, fromToken: fromToken, toToken: token, fromChain: fromChain, toChain: toChain, amount: amount, amountFormatted: formattedAmount, amountToTokenFormatted: amountToTokenFormatted, fiatCurrency: fiatCurrency, recipient: recipient, onSuccess: onSuccess, moonPayCurrencyCode: moonPayCurrencyCode, isPassthrough: isPassthrough, usdRate: usdRate, moonPayThemeId: moonPayThemeId, moonPayThemeMode: moonPayThemeMode, moonPayApiKey: moonPayApiKey })] })); } })); }; export default OnrampWidget; //# sourceMappingURL=index.js.map