import React, { useState, useMemo, useEffect, useContext } from 'react'; import { useTranslation } from 'react-i18next'; import { Dialog, DialogTitle, DialogContentText, DialogActions, DialogContent, Box, Button, Tooltip, Grid, TextField, useTheme, Typography, FormHelperText, } from '@mui/material'; import Countdown from 'react-countdown'; import currencies from '../../../static/assets/currencies.json'; import { type Order, type Info } from '../../models'; import { ConfirmationDialog } from '../Dialogs'; import { LoadingButton } from '@mui/lab'; import { computeSats } from '../../utils'; import { GarageContext, type UseGarageStoreType } from '../../contexts/GarageContext'; import { type UseFederationStoreType, FederationContext } from '../../contexts/FederationContext'; import { useNavigate } from 'react-router-dom'; interface TakeButtonProps { currentOrder: Order; info?: Info; onClickGenerateRobot?: () => void; } interface OpenDialogsProps { inactiveMaker: boolean; confirmation: boolean; } const closeAll = { inactiveMaker: false, confirmation: false }; const TakeButton = ({ currentOrder, info, onClickGenerateRobot = () => null, }: TakeButtonProps): JSX.Element => { const { t } = useTranslation(); const theme = useTheme(); const navigate = useNavigate(); const { garage, slotUpdatedAt } = useContext(GarageContext); const { federation } = useContext(FederationContext); const [takeAmount, setTakeAmount] = useState(''); const [badRequest, setBadRequest] = useState(''); const [loadingTake, setLoadingTake] = useState(false); const [open, setOpen] = useState(closeAll); const [satoshis, setSatoshis] = useState(''); const satoshisNow = (): string | undefined => { if (currentOrder === null) return; const tradeFee = info?.taker_fee ?? 0; const defaultRoutingBudget = 0.001; const btcNow = currentOrder.satoshis_now / 100000000; const rate = currentOrder.amount != null ? currentOrder.amount / btcNow : currentOrder.max_amount / btcNow; const amount = currentOrder.currency === 1000 ? Number(takeAmount) / 100000000 : Number(takeAmount); const satoshis = computeSats({ amount, routingBudget: currentOrder.is_buyer ? defaultRoutingBudget : 0, fee: tradeFee, rate, }); return satoshis; }; useEffect(() => { setSatoshis(satoshisNow() ?? ''); }, [slotUpdatedAt, takeAmount, info]); const currencyCode: string = currentOrder?.currency === 1000 ? 'Sats' : currencies[`${Number(currentOrder?.currency)}`]; const InactiveMakerDialog = function (): JSX.Element { return ( { setOpen({ ...open, inactiveMaker: false }); }} > {t('The maker is away')} {t( 'By taking this order you risk wasting your time. If the maker does not proceed in time, you will be compensated in satoshis for 50% of the maker bond.', )} ); }; interface countdownTakeOrderRendererProps { seconds: number; completed: boolean; } const countdownTakeOrderRenderer = function ({ seconds, completed, }: countdownTakeOrderRendererProps): JSX.Element { if (isNaN(seconds) || completed) { return takeOrderButton(); } else { return ( {t('Take Order')} ); } }; const handleTakeAmountChange = function (e: React.ChangeEvent): void { if (e.target.value !== '' && e.target.value != null) { setTakeAmount(`${parseFloat(e.target.value)}`); } else { setTakeAmount(e.target.value); } }; const amountHelperText = useMemo(() => { if (currentOrder === null) return; const amount = currentOrder.currency === 1000 ? Number(takeAmount) / 100000000 : Number(takeAmount); if (amount < Number(currentOrder.min_amount) && takeAmount !== '') { return t('Too low'); } else if (amount > Number(currentOrder.max_amount) && takeAmount !== '') { return t('Too high'); } else { return null; } }, [slotUpdatedAt, takeAmount]); const onTakeOrderClicked = function (): void { if (currentOrder?.maker_status === 'Inactive') { setOpen({ inactiveMaker: true, confirmation: false }); } else { setOpen({ inactiveMaker: false, confirmation: true }); } }; const invalidTakeAmount = useMemo(() => { const amount = currentOrder?.currency === 1000 ? Number(takeAmount) / 100000000 : Number(takeAmount); return ( amount < Number(currentOrder?.min_amount) || amount > Number(currentOrder?.max_amount) || takeAmount === '' || takeAmount == null ); }, [takeAmount, slotUpdatedAt]); const takeOrderButton = function (): JSX.Element { if (currentOrder?.has_range) { return (
{t('Take Order')}
{t('Take Order')}
{satoshis !== '0' && satoshis !== '' && !invalidTakeAmount ? ( {currentOrder?.type === 1 ? t('You will receive {{satoshis}} Sats (Approx)', { satoshis }) : t('You will send {{satoshis}} Sats (Approx)', { satoshis })} ) : null}
); } else { return ( {t('Take Order')} ); } }; const takeOrder = function (): void { const slot = garage.getSlot(); if (currentOrder === null || slot === null) return; setLoadingTake(true); currentOrder .submitAction(federation, slot, { action: 'take', amount: currentOrder?.currency === 1000 ? Number(takeAmount) / 100000000 : Number(takeAmount), }) .then((order) => { if (order?.bad_request !== undefined) { setBadRequest(order.bad_request); } else { setBadRequest(''); navigate(`/order/${order.shortAlias}/${order.id}`); } }) .catch(() => { setBadRequest('Request error'); }); }; return ( {badRequest !== '' ? ( {t(badRequest)} ) : ( <> )} { setOpen({ ...open, confirmation: false }); }} onClickDone={() => { takeOrder(); setLoadingTake(true); setOpen(closeAll); }} hasRobot={Boolean(garage.getSlot()?.hashId)} onClickGenerateRobot={onClickGenerateRobot} /> ); }; export default TakeButton;