import { Box, Typography } from '@material-ui/core' import BigNumber from 'bignumber.js' import { useSnackbar } from 'notistack' import { ReactElement, useContext, useState } from 'react' import { useNavigate } from 'react-router' import ArrowDown from 'remixicon-react/ArrowDownCircleLineIcon' import Check from 'remixicon-react/CheckLineIcon' import ExpandableListItem from '../../components/ExpandableListItem' import ExpandableListItemActions from '../../components/ExpandableListItemActions' import ExpandableListItemKey from '../../components/ExpandableListItemKey' import { HistoryHeader } from '../../components/HistoryHeader' import { Loading } from '../../components/Loading' import { SwarmButton } from '../../components/SwarmButton' import { SwarmDivider } from '../../components/SwarmDivider' import { SwarmTextInput } from '../../components/SwarmTextInput' import { BzzToken } from '../../models/BzzToken' import { DaiToken } from '../../models/DaiToken' import { Context as BeeContext } from '../../providers/Bee' import { Context as TopUpContext } from '../../providers/TopUp' import { ROUTES } from '../../routes' import { sleepMs } from '../../utils' import { performSwap, restartBeeNode, upgradeToLightNode } from '../../utils/desktop' import { TopUpProgressIndicator } from './TopUpProgressIndicator' const MINIMUM_XDAI = '0.1' const MINIMUM_XBZZ = '0.1' interface Props { header: string } export function Swap({ header }: Props): ReactElement { const [loading, setLoading] = useState(false) const [hasSwapped, setSwapped] = useState(false) const [userInputSwap, setUserInputSwap] = useState(null) const [price] = useState(DaiToken.fromDecimal('0.6', 18)) const { providerUrl } = useContext(TopUpContext) const { balance, nodeAddresses } = useContext(BeeContext) const navigate = useNavigate() const { enqueueSnackbar } = useSnackbar() if (!balance || !nodeAddresses) { return } const optimalSwap = balance.dai.minusBaseUnits('1') const lowAmountSwap = new DaiToken(balance.dai.toBigNumber.dividedToIntegerBy(2)) let daiToSwap: DaiToken function isPositiveDecimal(value: string): boolean { try { return new BigNumber(value).isPositive() } catch { return false } } if (userInputSwap && isPositiveDecimal(userInputSwap)) { daiToSwap = DaiToken.fromDecimal(userInputSwap, 18) } else { daiToSwap = lowAmountSwap.toBigNumber.gt(optimalSwap.toBigNumber) ? lowAmountSwap : optimalSwap } const daiAfterSwap = new DaiToken(balance.dai.toBigNumber.minus(daiToSwap.toBigNumber)) const bzzAfterSwap = new BzzToken(daiToSwap.toBigNumber.dividedBy(100).dividedToIntegerBy(price.toDecimal)) async function onSwap() { if (hasSwapped || !providerUrl) { return } setLoading(true) setSwapped(true) try { await performSwap(daiToSwap.toString) enqueueSnackbar('Successfully swapped, restarting...', { variant: 'success' }) await sleepMs(5_000) await upgradeToLightNode(providerUrl) await restartBeeNode() navigate(ROUTES.RESTART_LIGHT) enqueueSnackbar('Upgraded to light node', { variant: 'success' }) } catch (error) { enqueueSnackbar(`Failed to swap: ${error}`, { variant: 'error' }) } finally { setLoading(false) } } return ( <> {header} Swap some xDAI to xBZZ You need to swap xDAI to xBZZ in order to use Swarm. Make sure to keep at least {MINIMUM_XDAI} xDAI in order to pay for transaction costs on the network. Your current balance is {balance.dai.toSignificantDigits(4)} xDAI and {balance.bzz.toSignificantDigits(4)}{' '} xBZZ. setUserInputSwap(event.target.value)} /> {daiAfterSwap.toDecimal.lt(MINIMUM_XDAI) ? ( Must keep at least {MINIMUM_XDAI} xDAI after swap! ) : null} {bzzAfterSwap.toDecimal.lt(MINIMUM_XBZZ) ? ( Must have at least {MINIMUM_XBZZ} xBZZ after swap! ) : null} Swap Now ) }