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 => (
)
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]}
/>
>
)
}
export default Trade