import { useState, useRef, useMemo } from "react" import { Data, CustomFunction, TokenKey } from "./PoolActions" import Button from '../../atoms/Button' import Slider from '../../atoms/Slider' import Token from "./Token" import { formatAmount, maxDecimals } from "../../../utils/format" import { BigNumber } from "bignumber.js" import { faRepeat } from '@fortawesome/free-solid-svg-icons'; import { setInputValue, getOtherTokenKey } from "./helpers" import Icon from "../../atoms/Icon" export interface Props { data: Data, onInput?: CustomFunction, onConfirm?: CustomFunction, onSwitchTokens?: CustomFunction } const SummaryItem = ({ label, value, empty, className }: { label: string, value?: string, empty?: boolean, className?: string }): JSX.Element => (
{ label }
{ value }
) const Trade = ({ data, onInput, onConfirm, onSwitchTokens }: Props): JSX.Element => { const [values, setValues] = useState({ percentage: 0, firstToken: 0, secondToken: 0 }) const hasValue = useMemo(() => { return !!values.firstToken && !!values.secondToken && !!values.percentage }, [ values.firstToken, values.secondToken, values.percentage ]) const [fromTokenKey, setFromTokenKey] = useState("firstToken") const toTokenKey = useMemo((): TokenKey => { if (fromTokenKey === "firstToken") return "secondToken" return "firstToken" }, [ fromTokenKey, data.firstToken, data.secondToken ]) const switchTokens = () => { if (onSwitchTokens) { onSwitchTokens({ from: data[toTokenKey], to: data[fromTokenKey] }) } setFromTokenKey(toTokenKey) setValue({ percentage: 0 }) } const firstTokenInput = useRef(null) const secondTokenInput = useRef(null) const tokenInputs = { firstToken: firstTokenInput, secondToken: secondTokenInput } const getRates = useMemo(() => { const getRatio = (tokenKey: TokenKey) => { const _token = data[tokenKey] const otherTokenKey = getOtherTokenKey(tokenKey) const token = data[otherTokenKey] let amount = new BigNumber(_token.price).dividedBy(token.price).toNumber() amount = maxDecimals(amount, 4) const text = `1 ${_token.symbol} = ${amount ? formatAmount(amount) : '0.0'} ${token.symbol}` return { amount, text, _token, token } } const from = getRatio(fromTokenKey) const to = getRatio(toTokenKey) return { from, to } }, [ fromTokenKey, toTokenKey, data[fromTokenKey], data[toTokenKey] ]) const getFee = useMemo(() => { const token = data[fromTokenKey] const percentage = hasValue ? 0.3 : 0 let amount = new BigNumber(values[fromTokenKey]).times(new BigNumber(percentage).dividedBy(100).toNumber()).toNumber() amount = maxDecimals(amount, 4) let value = new BigNumber(amount).times(token.price).toNumber() value = maxDecimals(value, 2) const text = `$${value ? formatAmount(value) : "0.0"} (${amount ? formatAmount(amount).replaceAll(",", " ") : '0'} ${token.symbol})` return { percentage, amount, value, token, text} }, [ fromTokenKey, hasValue, values[fromTokenKey] ]) const getSlippage = useMemo(() => { const percentage = hasValue ? 2.5 : 0 const warn = percentage > 5 return { percentage, warn } }, [ values ]) const maxValues = useMemo(() => { const output = { firstToken: data.firstToken.available, secondToken: data.secondToken.available } const getFullValue = (token: TokenKey) => new BigNumber(data[token].available).times(data[token].price).toNumber() output[toTokenKey] = new BigNumber(getFullValue(fromTokenKey)).dividedBy(data[toTokenKey].price).toNumber() return output }, [ data.firstToken.available, data.secondToken.available, fromTokenKey, toTokenKey ]) const setValue = ({ percentage, tokenKey, value }: { percentage: number, tokenKey?: TokenKey, value?: number }) => { const tokenValues: { firstToken: number, secondToken: number } = { firstToken: 0, secondToken: 0 } const calcTokenValue = (key: TokenKey) => { const tokenValue = new BigNumber(percentage).times(maxValues[key]).dividedBy(100).toNumber() return maxDecimals(tokenValue, 4) } if (value && tokenKey) { tokenValues[tokenKey] = value const otherTokenKey = getOtherTokenKey(tokenKey) tokenValues[otherTokenKey] = calcTokenValue(otherTokenKey) } else { tokenValues.firstToken = calcTokenValue("firstToken") tokenValues.secondToken = calcTokenValue("secondToken") } setInputValue(firstTokenInput, tokenValues.firstToken) setInputValue(secondTokenInput, tokenValues.secondToken) const newValues = { percentage, firstToken: tokenValues.firstToken, secondToken: tokenValues.secondToken } setValues(newValues) return newValues } const getOutput = (value = values) => { return { from: { token: data[fromTokenKey], amount: value[fromTokenKey] }, to: { token: data[toTokenKey], amount: value[toTokenKey] }, percentage: value.percentage, rates: getRates, fee: getFee, slippage: getSlippage } } const handleInput = ( tokenKey: TokenKey, event: React.ChangeEvent ) => { const token = data[tokenKey] const max = maxValues[tokenKey] || 0 let value = new BigNumber(event.target.value.replace(/[^0-9.]+/gi, "")).toNumber() value = maxDecimals(value, 4, "floor") if (isNaN(value) || value < 0) value = 0 if (value > max) value = max const percentage = new BigNumber(value).times(100).dividedBy(max).toNumber() const newValues = setValue({ percentage, tokenKey, value }) if (onInput) onInput({ token, value: getOutput(newValues), event }) } const handleSlide = (percentage: number) => { const newValues = setValue({ percentage }) if (onInput) onInput({ token: undefined, value: getOutput(newValues), event: "slide" }) } const confirm = () => { if (onConfirm) onConfirm(getOutput()) } return ( <>
handleInput(fromTokenKey, e)} onBlur={() => setInputValue(tokenInputs[fromTokenKey], values[fromTokenKey])} inputRef={tokenInputs[fromTokenKey]} />
handleInput(toTokenKey, e)} onBlur={() => setInputValue(tokenInputs[toTokenKey], values[toTokenKey])} inputRef={tokenInputs[toTokenKey]} />