UNPKG

@daimo/pay

Version:

Seamless crypto payments. Onboard users from any chain, any coin into your app with one click.

160 lines (157 loc) 6.4 kB
import { jsxs, jsx } from 'react/jsx-runtime'; import { useState, useEffect } from 'react'; import { usePayContext } from '../../../hooks/usePayContext.js'; import { PageContent, ModalContent, ModalBody } from '../Modal/styles.js'; import { parseUnits } from 'viem'; import styled from '../../../styles/styled/index.js'; import { formatUsd, usdToRoundedTokenAmount, USD_DECIMALS, tokenAmountToRoundedUsd, roundUsd, roundTokenAmount, roundTokenAmountUnits } from '../../../utils/format.js'; import { isValidNumber, sanitizeNumber } from '../../../utils/validateInput.js'; import Button from '../Button/index.js'; import SwitchButton from '../SwitchButton/index.js'; import TokenLogoSpinner from '../../Spinners/TokenLogoSpinner/index.js'; import AmountInputField from './AmountInputField.js'; const MultiCurrencySelectAmount = ({ selectedTokenOption, setSelectedTokenOption, nextPage }) => { const { paymentState, setRoute, triggerResize } = usePayContext(); const maxUsdLimit = paymentState.getOrderUsdLimit(); const balanceToken = selectedTokenOption.balance.token; const minimumMessage = selectedTokenOption.minimumRequired.usd > 0 ? `Minimum ${formatUsd(selectedTokenOption.minimumRequired.usd, "up")}` : null; const [usdValue, setUsdValue] = useState(""); const [tokenValue, setTokenValue] = useState( usdToRoundedTokenAmount(0, balanceToken) ); const [isEditingUsd, setIsEditingUsd] = useState(true); const [message, setMessage] = useState(minimumMessage); const [continueDisabled, setContinueDisabled] = useState(true); useEffect(() => { triggerResize(); }, [message]); const updateValues = (newUsdValue, newTokenValue, newIsEditingUsd) => { const sanitizedUsdValue = sanitizeNumber(newUsdValue); const sanitizedTokenValue = sanitizeNumber(newTokenValue); setUsdValue( newIsEditingUsd ? newUsdValue : roundUsd(Number(sanitizedUsdValue)) ); setTokenValue( newIsEditingUsd ? roundTokenAmountUnits(Number(sanitizedTokenValue), balanceToken) : newTokenValue ); setIsEditingUsd(newIsEditingUsd); setContinueDisabled( Number(sanitizedUsdValue) <= 0 || Number(sanitizedUsdValue) < selectedTokenOption.minimumRequired.usd || Number(sanitizedUsdValue) > selectedTokenOption.balance.usd || Number(sanitizedUsdValue) > maxUsdLimit ); if (Number(sanitizedUsdValue) > selectedTokenOption.balance.usd) { setMessage( `Amount exceeds your balance: ${formatUsd(selectedTokenOption.balance.usd)}` ); } else if (Number(usdValue) > maxUsdLimit) { setMessage(`Maximum ${formatUsd(maxUsdLimit)}`); } else { setMessage(minimumMessage); } }; const handleAmountChange = (e) => { const value = e.target.value; const maxDecimals = isEditingUsd ? USD_DECIMALS : balanceToken.displayDecimals; if (value !== "" && !isValidNumber(value, maxDecimals)) return; const sanitizedValue = sanitizeNumber(value); const newUsdValue = isEditingUsd ? value : tokenAmountToRoundedUsd( parseUnits(sanitizedValue, balanceToken.decimals), balanceToken ); const newTokenValue = isEditingUsd ? usdToRoundedTokenAmount(Number(sanitizedValue), balanceToken) : value; updateValues(newUsdValue, newTokenValue, isEditingUsd); }; const handleMax = () => { const usdValue2 = roundUsd(Number(selectedTokenOption.balance.usd)); const tokenValue2 = roundTokenAmount( selectedTokenOption.balance.amount, balanceToken ); updateValues(usdValue2, tokenValue2, isEditingUsd); }; const handleKeyDown = (e) => { if (e.key === "Enter" && !continueDisabled) { handleContinue(); } }; const handleSwitchCurrency = () => { updateValues(usdValue, tokenValue, !isEditingUsd); }; const handleContinue = () => { const usd = Number(sanitizeNumber(usdValue)); const amountUnits = usd / balanceToken.usd; const amount = parseUnits(amountUnits.toString(), balanceToken.decimals); setSelectedTokenOption({ ...selectedTokenOption, required: { token: balanceToken, amount: amount.toString(), usd } }); paymentState.setChosenUsd(usd); setRoute(nextPage, { amountUsd: usd, amountUnits, tokenSymbol: balanceToken.symbol }); }; return /* @__PURE__ */ jsxs(PageContent, { children: [ /* @__PURE__ */ jsx(TokenLogoSpinner, { token: balanceToken }), /* @__PURE__ */ jsxs(ModalContent, { $preserveDisplay: true, children: [ /* @__PURE__ */ jsxs(AmountInputContainer, { children: [ /* @__PURE__ */ jsx(MaxButton, { style: { visibility: "hidden" }, children: "Max" }), /* @__PURE__ */ jsx( AmountInputField, { value: isEditingUsd ? usdValue : tokenValue, onChange: handleAmountChange, currency: isEditingUsd ? "$" : balanceToken.symbol, onKeyDown: handleKeyDown } ), /* @__PURE__ */ jsx(MaxButton, { onClick: handleMax, children: "Max" }) ] }), balanceToken.fiatISO !== "USD" && /* @__PURE__ */ jsx(SwitchContainer, { children: /* @__PURE__ */ jsx(SwitchButton, { onClick: handleSwitchCurrency, children: /* @__PURE__ */ jsx(SecondaryAmount, { children: isEditingUsd ? `${tokenValue} ${balanceToken.symbol}` : `$${usdValue}` }) }) }), message && /* @__PURE__ */ jsx(ModalBody, { children: message }), /* @__PURE__ */ jsx(Button, { onClick: handleContinue, disabled: continueDisabled, children: "Continue" }) ] }) ] }); }; const AmountInputContainer = styled.div` display: flex; align-items: center; justify-content: center; gap: 6px; `; const SecondaryAmount = styled.div` font-size: 16px; font-weight: 400; line-height: 21px; color: var(--ck-body-color-muted); strong { font-weight: 500; color: var(--ck-body-color); } `; const MaxButton = styled.button` display: inline-block; padding: 3px 8px; border-radius: var(--ck-primary-button-border-radius); font-size: 14px; font-weight: 400; background: var( --ck-secondary-button-background, var(--ck-body-background-secondary) ); color: var(--ck-body-color-secondary); cursor: pointer; `; const SwitchContainer = styled.div` display: flex; align-items: center; justify-content: center; `; export { MultiCurrencySelectAmount as default }; //# sourceMappingURL=index.js.map