import { ChangeEvent, useEffect, useState } from 'react';
import {
makeStyles,
Box,
Paper,
Typography,
TextField,
LinearProgress,
Fab,
} from '@material-ui/core';
import InputAdornment from '@material-ui/core/InputAdornment';
import ArrowDownwardIcon from '@material-ui/icons/ArrowDownward';
import SwapHorizIcon from '@material-ui/icons/SwapHoriz';
import { Alert } from '@material-ui/lab';
import { satsToBtc } from 'utils/conversionUtils';
import { useAppSelector } from 'store/hooks';
import { ExtendedProviderStatus } from 'models/apiModel';
import { isSwapState } from 'models/storeModel';
import SwapDialog from '../../modal/swap/SwapDialog';
import ProviderSelect from '../../modal/provider/ProviderSelect';
import {
ListSellersDialogOpenButton,
ProviderSubmitDialogOpenButton,
} from '../../modal/provider/ProviderListDialog';
// After RECONNECTION_ATTEMPTS_UNTIL_ASSUME_DOWN failed reconnection attempts we can assume the public registry is down
const RECONNECTION_ATTEMPTS_UNTIL_ASSUME_DOWN = 1;
function isRegistryDown(reconnectionAttempts: number): boolean {
return reconnectionAttempts > RECONNECTION_ATTEMPTS_UNTIL_ASSUME_DOWN;
}
const useStyles = makeStyles((theme) => ({
inner: {
width: 'min(480px, 100%)',
minHeight: '150px',
display: 'grid',
padding: theme.spacing(1),
gridGap: theme.spacing(1),
},
header: {
padding: 0,
},
headerText: {
padding: theme.spacing(1),
},
providerInfo: {
padding: theme.spacing(1),
},
swapIconOuter: {
display: 'flex',
justifyContent: 'center',
},
swapIcon: {
marginRight: theme.spacing(1),
},
noProvidersAlertOuter: {
display: 'flex',
flexDirection: 'column',
gap: theme.spacing(1),
},
noProvidersAlertButtonsOuter: {
display: 'flex',
gap: theme.spacing(1),
},
}));
function Title() {
const classes = useStyles();
return (
Swap
);
}
function HasProviderSwapWidget({
selectedProvider,
}: {
selectedProvider: ExtendedProviderStatus;
}) {
const classes = useStyles();
const forceShowDialog = useAppSelector((state) =>
isSwapState(state.swap.state),
);
const [showDialog, setShowDialog] = useState(false);
const [btcFieldValue, setBtcFieldValue] = useState(
satsToBtc(selectedProvider.minSwapAmount),
);
const [xmrFieldValue, setXmrFieldValue] = useState(1);
function onBtcAmountChange(event: ChangeEvent) {
setBtcFieldValue(event.target.value);
}
function updateXmrValue() {
const parsedBtcAmount = Number(btcFieldValue);
if (Number.isNaN(parsedBtcAmount)) {
setXmrFieldValue(0);
} else {
const convertedXmrAmount =
parsedBtcAmount / satsToBtc(selectedProvider.price);
setXmrFieldValue(convertedXmrAmount);
}
}
function getBtcFieldError(): string | null {
const parsedBtcAmount = Number(btcFieldValue);
if (Number.isNaN(parsedBtcAmount)) {
return 'This is not a valid number';
}
if (parsedBtcAmount < satsToBtc(selectedProvider.minSwapAmount)) {
return `The minimum swap amount is ${satsToBtc(
selectedProvider.minSwapAmount,
)} BTC. Switch to a different provider if you want to swap less.`;
}
if (parsedBtcAmount > satsToBtc(selectedProvider.maxSwapAmount)) {
return `The maximum swap amount is ${satsToBtc(
selectedProvider.maxSwapAmount,
)} BTC. Switch to a different provider if you want to swap more.`;
}
return null;
}
function handleGuideDialogOpen() {
setShowDialog(true);
}
useEffect(updateXmrValue, [btcFieldValue, selectedProvider]);
return (
// 'elevation' prop can't be passed down (type def issue)
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
BTC,
}}
/>
XMR,
}}
/>
Swap
setShowDialog(false)}
/>
);
}
function HasNoProvidersSwapWidget() {
const forceShowDialog = useAppSelector((state) =>
isSwapState(state.swap.state),
);
const isPublicRegistryDown = useAppSelector((state) =>
isRegistryDown(
state.providers.registry.failedReconnectAttemptsSinceLastSuccess,
),
);
const classes = useStyles();
const alertBox = isPublicRegistryDown ? (
Currently, the public registry of providers seems to be unreachable.
Here's what you can do:
-
Try discovering a provider by connecting to a rendezvous point
-
Try again later when the public registry may be reachable again
) : (
Currently, there are no providers (trading partners) available in the
official registry. Here's what you can do:
-
Try discovering a provider by connecting to a rendezvous point
- Add a new provider to the public registry
- Try again later when more providers may be available
);
return (
{alertBox}
{}} />
);
}
function ProviderLoadingSwapWidget() {
const classes = useStyles();
return (
// 'elevation' prop can't be passed down (type def issue)
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
);
}
export default function SwapWidget() {
const selectedProvider = useAppSelector(
(state) => state.providers.selectedProvider,
);
// If we fail more than RECONNECTION_ATTEMPTS_UNTIL_ASSUME_DOWN reconnect attempts, we'll show the "no providers" widget. We can assume the public registry is down.
const providerLoading = useAppSelector(
(state) =>
state.providers.registry.providers === null &&
!isRegistryDown(
state.providers.registry.failedReconnectAttemptsSinceLastSuccess,
),
);
if (providerLoading) {
return ;
}
if (selectedProvider) {
return ;
}
return ;
}