import { Currency, CurrencyAmount, Percent, Price, Token, } from "@uniswap/sdk-core"; import React, { useState, useCallback, Fragment, useMemo } from "react"; import styled from "styled-components/macro"; import { darken, lighten } from "polished"; import { useCurrencyBalance } from "../../hooks/Balances"; import CurrencySearchModal from "../SearchModal/CurrencySearchModal"; import CurrencyLogo from "../CurrencyLogo"; import DoubleCurrencyLogo from "../DoubleLogo"; import { ButtonGray } from "../Button"; import { RowBetween, RowFixed } from "../Row"; import { TYPE } from "../../theme"; import { Input as NumericalInput } from "../NumericalInput"; import { useWeb3 } from "../../web3"; import useTheme from "../../hooks/useTheme"; import { Lock } from "react-feather"; import { AutoColumn } from "../Column"; import { FiatValue } from "./FiatValue"; import { formatTokenAmount } from "../../utils/formatTokenAmount"; import { MouseoverTooltip } from "../Tooltip"; import DropDown from "../../assets/images/dropdown.svg"; import { isRangeOrderSupportedChain } from "@gelatonetwork/range-orders-lib/dist/utils"; import { Pair } from "../../entities/pair"; import { RatePercentage } from "./RatePercentage"; import { Rate } from "../../state/gorder/actions"; const InputPanel = styled.div<{ hideInput?: boolean }>` ${({ theme }) => theme.flexColumnNoWrap} position: relative; border-radius: ${({ hideInput }) => (hideInput ? "16px" : "20px")}; background-color: ${({ theme, hideInput }) => hideInput ? "transparent" : theme.bg2}; z-index: 1; width: ${({ hideInput }) => (hideInput ? "100%" : "initial")}; `; const FixedContainer = styled.div` width: 100%; height: 100%; position: absolute; border-radius: 20px; background-color: ${({ theme }) => theme.bg1}; opacity: 0.95; display: flex; align-items: center; justify-content: center; z-index: 2; `; const Container = styled.div<{ hideInput: boolean }>` border-radius: ${({ hideInput }) => (hideInput ? "16px" : "20px")}; border: 1px solid ${({ theme, hideInput }) => (hideInput ? " transparent" : theme.bg2)}; background-color: ${({ theme }) => theme.bg1}; width: ${({ hideInput }) => (hideInput ? "100%" : "initial")}; :focus, :hover { border: 1px solid ${({ theme, hideInput }) => (hideInput ? " transparent" : theme.bg3)}; } `; const CurrencySelect = styled(ButtonGray)<{ selected: boolean; hideInput?: boolean; }>` align-items: center; font-size: 24px; font-weight: 500; background-color: ${({ selected, theme }) => selected ? theme.bg0 : theme.primary1}; color: ${({ selected, theme }) => (selected ? theme.text1 : theme.white)}; border-radius: 16px; box-shadow: ${({ selected }) => selected ? "none" : "0px 6px 10px rgba(0, 0, 0, 0.075)"}; box-shadow: 0px 6px 10px rgba(0, 0, 0, 0.075); outline: none; cursor: pointer; user-select: none; border: none; height: ${({ hideInput }) => (hideInput ? "2.8rem" : "2.4rem")}; width: ${({ hideInput }) => (hideInput ? "100%" : "initial")}; padding: 0 8px; justify-content: space-between; margin-right: ${({ hideInput }) => (hideInput ? "0" : "12px")}; :focus, :hover { background-color: ${({ selected, theme }) => selected ? theme.bg2 : darken(0.05, theme.primary1)}; } `; const PriceSelect = styled(ButtonGray)<{ selected: boolean; hideInput?: boolean; }>` align-items: center; font-size: 24px; font-weight: 500; background-color: ${({ theme, selected }) => selected ? theme.bg0 : theme.bg1}; color: ${({ theme }) => theme.text1}; border-radius: 8px; box-shadow: 0px 6px 10px rgba(0, 0, 0, 0.075); outline: none; cursor: pointer; user-select: none; border: 1px solid ${({ theme }) => lighten(0.05, theme.bg3)}; height: ${({ hideInput }) => (hideInput ? "2.8rem" : "2.4rem")}; width: ${({ hideInput }) => (hideInput ? "100%" : "50%")}; padding: 0 8px; justify-content: space-between; margin-right: ${({ hideInput }) => (hideInput ? "0" : "12px")}; :focus, :hover { background-color: ${({ theme }) => theme.bg0}; border: ${({ selected }) => (selected ? "1px solid" : "none")}; border-color: ${({ selected, theme }) => selected ? theme.primary1 : "none"}; } `; const InputRow = styled.div<{ selected: boolean }>` ${({ theme }) => theme.flexRowNoWrap} align-items: center; padding: ${({ selected }) => selected ? " 1rem 1rem 0.75rem 1rem" : "1rem 1rem 0.75rem 1rem"}; `; const LabelRow = styled.div` ${({ theme }) => theme.flexRowNoWrap} align-items: center; color: ${({ theme }) => theme.text1}; font-size: 0.75rem; line-height: 1rem; padding: 0 1rem 1rem; span:hover { cursor: pointer; color: ${({ theme }) => darken(0.2, theme.text2)}; } `; const FiatRow = styled(LabelRow)` justify-content: flex-end; `; const PriceRow = styled(LabelRow)` justify-content: space-between; `; const ErrorRow = styled(LabelRow)` justify-content: space-between; `; const Aligner = styled.span` display: flex; align-items: center; justify-content: space-between; width: 100%; `; const PriceAligner = styled.span` display: flex; align-items: center; justify-content: center; width: 100%; `; const StyledDropDown = styled(DropDown)<{ selected: boolean }>` margin: 0 0.25rem 0 0.35rem; height: 35%; path { stroke: ${({ selected, theme }) => (selected ? theme.text1 : theme.white)}; stroke-width: 1.5px; } `; const StyledTokenName = styled.span<{ active?: boolean }>` ${({ active }) => active ? " margin: 0 0.25rem 0 0.25rem;" : " margin: 0 0.25rem 0 0.25rem;"} font-size: ${({ active }) => (active ? "18px" : "18px")}; `; const StyledBalanceMax = styled.button<{ disabled?: boolean }>` background-color: transparent; border: none; border-radius: 12px; font-size: 14px; font-weight: 500; cursor: pointer; padding: 0; color: ${({ theme }) => theme.primary1}; opacity: ${({ disabled }) => (!disabled ? 1 : 0.4)}; pointer-events: ${({ disabled }) => (!disabled ? "initial" : "none")}; margin-left: 0.25rem; :focus { outline: none; } ${({ theme }) => theme.mediaWidth.upToExtraSmall` margin-right: 0.5rem; `}; `; interface CurrencyInputPanelProps { value: string; onUserInput: (value: string) => void; onMax?: () => void; showMaxButton: boolean; label?: string; onCurrencySelect?: (currency: Currency) => void; currency?: Currency | null; hideBalance?: boolean; pair?: Pair | null; hideInput?: boolean; otherCurrency?: Currency | null; fiatValue?: CurrencyAmount | null; priceImpact?: Percent; id: string; showCommonBases?: boolean; customBalanceText?: string; locked?: boolean; showCurrencySelector?: boolean; showRate?: boolean; showRange?: boolean; rangePriceLower?: string; rangeLowerEnabled?: boolean; lowerTick?: number; rangePriceUpper?: string; rangeUpperEnabled?: boolean; upperTick?: number; isInvertedRate?: boolean; realExecutionPrice?: Price | undefined; realExecutionPriceAsString?: string | undefined; gasPrice?: number; rateType?: Rate; onPriceSelect?: (price: any) => void; inputError?: string; } export default function CurrencyInputPanel({ value, onUserInput, onMax, showMaxButton, onCurrencySelect, currency, otherCurrency, id, showCommonBases, customBalanceText, fiatValue, priceImpact, hideBalance = false, pair = null, // used for double token logo hideInput = false, locked = false, showCurrencySelector = true, showRate = false, showRange = false, rangePriceLower, rangeLowerEnabled, lowerTick, rangePriceUpper, rangeUpperEnabled, upperTick, inputError, isInvertedRate = false, realExecutionPriceAsString, rateType, onPriceSelect, ...rest }: CurrencyInputPanelProps) { const [modalOpen, setModalOpen] = useState(false); const [selectPriceA, setSelectPriceA] = useState(false); const [selectPriceB, setSelectPriceB] = useState(false); const { account, chainId } = useWeb3(); const selectedCurrencyBalance = useCurrencyBalance( account ?? undefined, currency ?? undefined ); const theme = useTheme(); const handleDismissSearch = useCallback(() => { setModalOpen(false); }, [setModalOpen]); const isSupportedChain = chainId && isRangeOrderSupportedChain(chainId); const rate = useMemo( () => currency && otherCurrency && value ? `1 ${ isInvertedRate ? otherCurrency?.symbol : currency?.symbol } = ${value} ${ isInvertedRate ? currency?.symbol : otherCurrency?.symbol }` : undefined, [currency, isInvertedRate, otherCurrency, value] ); const realExecutionRateExplainer = useMemo( () => currency && otherCurrency && realExecutionPriceAsString ? realExecutionPriceAsString === "never executes" ? realExecutionPriceAsString : `1 ${ isInvertedRate ? otherCurrency?.symbol : currency?.symbol } = ${realExecutionPriceAsString} ${ isInvertedRate ? currency?.symbol : otherCurrency?.symbol }` : undefined, [currency, isInvertedRate, otherCurrency, realExecutionPriceAsString] ); return ( {locked && ( The market price is outside your specified price range. Single-asset deposit only. )} {showCurrencySelector ? ( { if (onCurrencySelect) { setModalOpen(true); } }} > {pair ? ( ) : currency ? ( ) : null} {pair ? ( {pair?.token0.symbol}:{pair?.token1.symbol} ) : ( {(currency && currency.symbol && currency.symbol.length > 20 ? currency.symbol.slice(0, 4) + "..." + currency.symbol.slice( currency.symbol.length - 5, currency.symbol.length ) : currency?.symbol) || "Select a token"} )} {onCurrencySelect && } ) : null} {showRange && ( {"Enter a price"} )} {!hideInput && ( { onUserInput(val); }} /> )} {showRange && ( {otherCurrency?.symbol} )} {!hideInput && !hideBalance && !showRate && ( {account ? ( {!hideBalance && !!currency && selectedCurrencyBalance ? (customBalanceText ?? "Balance: ") + formatTokenAmount(selectedCurrencyBalance, 4) + " " + currency.symbol : "-"} {showMaxButton && selectedCurrencyBalance ? ( (Max) ) : null} ) : ( "-" )} {!rateType ? ( ) : ( // Only show on output panel )} )} {/* Range Order Inputs */} {value && currency && otherCurrency && isSupportedChain && showRange && onPriceSelect && ( Select Range order price { setSelectPriceA(true); setSelectPriceB(false); onPriceSelect({ tick: lowerTick, price: rangePriceLower }); }} disabled={!rangeLowerEnabled} > {rangePriceLower} { setSelectPriceA(false); setSelectPriceB(true); onPriceSelect({ tick: upperTick, price: rangePriceUpper }); }} disabled={!rangeUpperEnabled} > {rangePriceUpper} {inputError && ( {inputError} )} )} {onCurrencySelect && ( )} ); }