wip: WithdrawDialog migrated to Tauri IPC

This commit is contained in:
binarybaron 2024-08-09 19:46:58 +02:00
parent 47821cbe79
commit 3d16ff6d5c
No known key found for this signature in database
GPG key ID: 99B75D3E1476A26E
118 changed files with 1779 additions and 1868 deletions

View file

@ -1,18 +1,18 @@
import QRCode from 'react-qr-code';
import { Box } from '@material-ui/core';
import QRCode from "react-qr-code";
import { Box } from "@material-ui/core";
export default function BitcoinQrCode({ address }: { address: string }) {
return (
<Box
style={{
height: '100%',
margin: '0 auto',
height: "100%",
margin: "0 auto",
}}
>
<QRCode
value={`bitcoin:${address}`}
size={256}
style={{ height: 'auto', maxWidth: '100%', width: '100%' }}
style={{ height: "auto", maxWidth: "100%", width: "100%" }}
/* eslint-disable-next-line @typescript-eslint/ban-ts-comment */
/* @ts-ignore */
viewBox="0 0 256 256"

View file

@ -1,8 +1,8 @@
import { isTestnet } from 'store/config';
import { getBitcoinTxExplorerUrl } from 'utils/conversionUtils';
import BitcoinIcon from 'renderer/components/icons/BitcoinIcon';
import { ReactNode } from 'react';
import TransactionInfoBox from './TransactionInfoBox';
import { isTestnet } from "store/config";
import { getBitcoinTxExplorerUrl } from "utils/conversionUtils";
import BitcoinIcon from "renderer/components/icons/BitcoinIcon";
import { ReactNode } from "react";
import TransactionInfoBox from "./TransactionInfoBox";
type Props = {
title: string;

View file

@ -3,8 +3,8 @@ import {
CircularProgress,
makeStyles,
Typography,
} from '@material-ui/core';
import { ReactNode } from 'react';
} from "@material-ui/core";
import { ReactNode } from "react";
const useStyles = makeStyles((theme) => ({
subtitle: {

View file

@ -1,12 +1,12 @@
import { Button } from '@material-ui/core';
import { ButtonProps } from '@material-ui/core/Button/Button';
import { Button } from "@material-ui/core";
import { ButtonProps } from "@material-ui/core/Button/Button";
export default function ClipboardIconButton({
text,
...props
}: { text: string } & ButtonProps) {
function writeToClipboard() {
throw new Error('Not implemented');
throw new Error("Not implemented");
}
return (

View file

@ -1,9 +1,9 @@
import { ReactNode } from 'react';
import { Box, Typography } from '@material-ui/core';
import FileCopyOutlinedIcon from '@material-ui/icons/FileCopyOutlined';
import InfoBox from './InfoBox';
import ClipboardIconButton from './ClipbiardIconButton';
import BitcoinQrCode from './BitcoinQrCode';
import { ReactNode } from "react";
import { Box, Typography } from "@material-ui/core";
import FileCopyOutlinedIcon from "@material-ui/icons/FileCopyOutlined";
import InfoBox from "./InfoBox";
import ClipboardIconButton from "./ClipbiardIconButton";
import BitcoinQrCode from "./BitcoinQrCode";
type Props = {
title: string;
@ -34,10 +34,10 @@ export default function DepositAddressInfoBox({
/>
<Box
style={{
display: 'flex',
flexDirection: 'row',
gap: '0.5rem',
alignItems: 'center',
display: "flex",
flexDirection: "row",
gap: "0.5rem",
alignItems: "center",
}}
>
<Box>{additionalContent}</Box>

View file

@ -4,8 +4,8 @@ import {
makeStyles,
Paper,
Typography,
} from '@material-ui/core';
import { ReactNode } from 'react';
} from "@material-ui/core";
import { ReactNode } from "react";
type Props = {
title: ReactNode;
@ -18,14 +18,14 @@ type Props = {
const useStyles = makeStyles((theme) => ({
outer: {
padding: theme.spacing(1.5),
overflow: 'hidden',
display: 'flex',
flexDirection: 'column',
overflow: "hidden",
display: "flex",
flexDirection: "column",
gap: theme.spacing(1),
},
upperContent: {
display: 'flex',
alignItems: 'center',
display: "flex",
alignItems: "center",
gap: theme.spacing(0.5),
},
}));

View file

@ -1,8 +1,8 @@
import { isTestnet } from 'store/config';
import { getMoneroTxExplorerUrl } from 'utils/conversionUtils';
import MoneroIcon from 'renderer/components/icons/MoneroIcon';
import { ReactNode } from 'react';
import TransactionInfoBox from './TransactionInfoBox';
import { isTestnet } from "store/config";
import { getMoneroTxExplorerUrl } from "utils/conversionUtils";
import MoneroIcon from "renderer/components/icons/MoneroIcon";
import { ReactNode } from "react";
import TransactionInfoBox from "./TransactionInfoBox";
type Props = {
title: string;

View file

@ -1,25 +1,25 @@
import { useState } from 'react';
import { useState } from "react";
import {
Button,
Dialog,
DialogActions,
DialogContent,
makeStyles,
} from '@material-ui/core';
import { useAppDispatch, useAppSelector } from 'store/hooks';
import { swapReset } from 'store/features/swapSlice';
import SwapStatePage from './pages/SwapStatePage';
import SwapStateStepper from './SwapStateStepper';
import SwapSuspendAlert from '../SwapSuspendAlert';
import SwapDialogTitle from './SwapDialogTitle';
import DebugPage from './pages/DebugPage';
} from "@material-ui/core";
import { useAppDispatch, useAppSelector } from "store/hooks";
import { swapReset } from "store/features/swapSlice";
import SwapStatePage from "./pages/SwapStatePage";
import SwapStateStepper from "./SwapStateStepper";
import SwapSuspendAlert from "../SwapSuspendAlert";
import SwapDialogTitle from "./SwapDialogTitle";
import DebugPage from "./pages/DebugPage";
const useStyles = makeStyles({
content: {
minHeight: '25rem',
display: 'flex',
flexDirection: 'column',
justifyContent: 'space-between',
minHeight: "25rem",
display: "flex",
flexDirection: "column",
justifyContent: "space-between",
},
});

View file

@ -1,22 +1,17 @@
import {
Box,
DialogTitle,
makeStyles,
Typography,
} from '@material-ui/core';
import TorStatusBadge from './pages/TorStatusBadge';
import FeedbackSubmitBadge from './pages/FeedbackSubmitBadge';
import DebugPageSwitchBadge from './pages/DebugPageSwitchBadge';
import { Box, DialogTitle, makeStyles, Typography } from "@material-ui/core";
import TorStatusBadge from "./pages/TorStatusBadge";
import FeedbackSubmitBadge from "./pages/FeedbackSubmitBadge";
import DebugPageSwitchBadge from "./pages/DebugPageSwitchBadge";
const useStyles = makeStyles((theme) => ({
root: {
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
display: "flex",
justifyContent: "space-between",
alignItems: "center",
},
rightSide: {
display: 'flex',
alignItems: 'center',
display: "flex",
alignItems: "center",
gridGap: theme.spacing(1),
},
}));

View file

@ -5,165 +5,162 @@ import { useActiveSwapInfo, useAppSelector } from "store/hooks";
import { exhaustiveGuard } from "utils/typescriptUtils";
export enum PathType {
HAPPY_PATH = "happy path",
UNHAPPY_PATH = "unhappy path",
HAPPY_PATH = "happy path",
UNHAPPY_PATH = "unhappy path",
}
function getActiveStep(
stateName: SwapStateName | null,
processExited: boolean,
stateName: SwapStateName | null,
processExited: boolean,
): [PathType, number, boolean] {
switch (stateName) {
/// // Happy Path
// Step: 0 (Waiting for Bitcoin lock tx to be published)
case null:
return [PathType.HAPPY_PATH, 0, false];
case SwapStateName.Started:
case SwapStateName.SwapSetupCompleted:
return [PathType.HAPPY_PATH, 0, processExited];
switch (stateName) {
/// // Happy Path
// Step: 0 (Waiting for Bitcoin lock tx to be published)
case null:
return [PathType.HAPPY_PATH, 0, false];
case SwapStateName.Started:
case SwapStateName.SwapSetupCompleted:
return [PathType.HAPPY_PATH, 0, processExited];
// Step: 1 (Waiting for Bitcoin Lock confirmation and XMR Lock Publication)
// We have locked the Bitcoin and are waiting for the other party to lock their XMR
case SwapStateName.BtcLocked:
return [PathType.HAPPY_PATH, 1, processExited];
// Step: 1 (Waiting for Bitcoin Lock confirmation and XMR Lock Publication)
// We have locked the Bitcoin and are waiting for the other party to lock their XMR
case SwapStateName.BtcLocked:
return [PathType.HAPPY_PATH, 1, processExited];
// Step: 2 (Waiting for XMR Lock confirmation)
// We have locked the Bitcoin and the other party has locked their XMR
case SwapStateName.XmrLockProofReceived:
return [PathType.HAPPY_PATH, 1, processExited];
// Step: 2 (Waiting for XMR Lock confirmation)
// We have locked the Bitcoin and the other party has locked their XMR
case SwapStateName.XmrLockProofReceived:
return [PathType.HAPPY_PATH, 1, processExited];
// Step: 3 (Sending Encrypted Signature and waiting for Bitcoin Redemption)
// The XMR lock transaction has been confirmed
// We now need to send the encrypted signature to the other party and wait for them to redeem the Bitcoin
case SwapStateName.XmrLocked:
case SwapStateName.EncSigSent:
return [PathType.HAPPY_PATH, 2, processExited];
// Step: 3 (Sending Encrypted Signature and waiting for Bitcoin Redemption)
// The XMR lock transaction has been confirmed
// We now need to send the encrypted signature to the other party and wait for them to redeem the Bitcoin
case SwapStateName.XmrLocked:
case SwapStateName.EncSigSent:
return [PathType.HAPPY_PATH, 2, processExited];
// Step: 4 (Waiting for XMR Redemption)
case SwapStateName.BtcRedeemed:
return [PathType.HAPPY_PATH, 3, processExited];
// Step: 4 (Waiting for XMR Redemption)
case SwapStateName.BtcRedeemed:
return [PathType.HAPPY_PATH, 3, processExited];
// Step: 4 (Completed) (Swap completed, XMR redeemed)
case SwapStateName.XmrRedeemed:
return [PathType.HAPPY_PATH, 4, false];
// Step: 4 (Completed) (Swap completed, XMR redeemed)
case SwapStateName.XmrRedeemed:
return [PathType.HAPPY_PATH, 4, false];
// Edge Case of Happy Path where the swap is safely aborted. We "fail" at the first step.
case SwapStateName.SafelyAborted:
return [PathType.HAPPY_PATH, 0, true];
// Edge Case of Happy Path where the swap is safely aborted. We "fail" at the first step.
case SwapStateName.SafelyAborted:
return [PathType.HAPPY_PATH, 0, true];
// // Unhappy Path
// Step: 1 (Cancelling swap, checking if cancel transaction has been published already by the other party)
case SwapStateName.CancelTimelockExpired:
return [PathType.UNHAPPY_PATH, 0, processExited];
// // Unhappy Path
// Step: 1 (Cancelling swap, checking if cancel transaction has been published already by the other party)
case SwapStateName.CancelTimelockExpired:
return [PathType.UNHAPPY_PATH, 0, processExited];
// Step: 2 (Attempt to publish the Bitcoin refund transaction)
case SwapStateName.BtcCancelled:
return [PathType.UNHAPPY_PATH, 1, processExited];
// Step: 2 (Attempt to publish the Bitcoin refund transaction)
case SwapStateName.BtcCancelled:
return [PathType.UNHAPPY_PATH, 1, processExited];
// Step: 2 (Completed) (Bitcoin refunded)
case SwapStateName.BtcRefunded:
return [PathType.UNHAPPY_PATH, 2, false];
// Step: 2 (Completed) (Bitcoin refunded)
case SwapStateName.BtcRefunded:
return [PathType.UNHAPPY_PATH, 2, false];
// Step: 2 (We failed to publish the Bitcoin refund transaction)
// We failed to publish the Bitcoin refund transaction because the timelock has expired.
// We will be punished. Nothing we can do about it now.
case SwapStateName.BtcPunished:
return [PathType.UNHAPPY_PATH, 1, true];
default:
return exhaustiveGuard(stateName);
}
// Step: 2 (We failed to publish the Bitcoin refund transaction)
// We failed to publish the Bitcoin refund transaction because the timelock has expired.
// We will be punished. Nothing we can do about it now.
case SwapStateName.BtcPunished:
return [PathType.UNHAPPY_PATH, 1, true];
default:
return exhaustiveGuard(stateName);
}
}
function HappyPathStepper({
activeStep,
error,
activeStep,
error,
}: {
activeStep: number;
error: boolean;
activeStep: number;
error: boolean;
}) {
return (
<Stepper activeStep={activeStep}>
<Step key={0}>
<StepLabel
optional={<Typography variant="caption">~12min</Typography>}
error={error && activeStep === 0}
>
Locking your BTC
</StepLabel>
</Step>
<Step key={1}>
<StepLabel
optional={<Typography variant="caption">~18min</Typography>}
error={error && activeStep === 1}
>
They lock their XMR
</StepLabel>
</Step>
<Step key={2}>
<StepLabel
optional={<Typography variant="caption">~2min</Typography>}
error={error && activeStep === 2}
>
They redeem the BTC
</StepLabel>
</Step>
<Step key={3}>
<StepLabel
optional={<Typography variant="caption">~2min</Typography>}
error={error && activeStep === 3}
>
Redeeming your XMR
</StepLabel>
</Step>
</Stepper>
);
return (
<Stepper activeStep={activeStep}>
<Step key={0}>
<StepLabel
optional={<Typography variant="caption">~12min</Typography>}
error={error && activeStep === 0}
>
Locking your BTC
</StepLabel>
</Step>
<Step key={1}>
<StepLabel
optional={<Typography variant="caption">~18min</Typography>}
error={error && activeStep === 1}
>
They lock their XMR
</StepLabel>
</Step>
<Step key={2}>
<StepLabel
optional={<Typography variant="caption">~2min</Typography>}
error={error && activeStep === 2}
>
They redeem the BTC
</StepLabel>
</Step>
<Step key={3}>
<StepLabel
optional={<Typography variant="caption">~2min</Typography>}
error={error && activeStep === 3}
>
Redeeming your XMR
</StepLabel>
</Step>
</Stepper>
);
}
function UnhappyPathStepper({
activeStep,
error,
activeStep,
error,
}: {
activeStep: number;
error: boolean;
activeStep: number;
error: boolean;
}) {
return (
<Stepper activeStep={activeStep}>
<Step key={0}>
<StepLabel
optional={<Typography variant="caption">~20min</Typography>}
error={error && activeStep === 0}
>
Cancelling swap
</StepLabel>
</Step>
<Step key={1}>
<StepLabel
optional={<Typography variant="caption">~20min</Typography>}
error={error && activeStep === 1}
>
Refunding your BTC
</StepLabel>
</Step>
</Stepper>
);
return (
<Stepper activeStep={activeStep}>
<Step key={0}>
<StepLabel
optional={<Typography variant="caption">~20min</Typography>}
error={error && activeStep === 0}
>
Cancelling swap
</StepLabel>
</Step>
<Step key={1}>
<StepLabel
optional={<Typography variant="caption">~20min</Typography>}
error={error && activeStep === 1}
>
Refunding your BTC
</StepLabel>
</Step>
</Stepper>
);
}
export default function SwapStateStepper() {
const currentSwapSpawnType = useAppSelector((s) => s.swap.spawnType);
const stateName = useActiveSwapInfo()?.state_name ?? null;
const processExited = useAppSelector((s) => !s.swap.processRunning);
const [pathType, activeStep, error] = getActiveStep(
stateName,
processExited,
);
const currentSwapSpawnType = useAppSelector((s) => s.swap.spawnType);
const stateName = useActiveSwapInfo()?.state_name ?? null;
const processExited = useAppSelector((s) => !s.swap.processRunning);
const [pathType, activeStep, error] = getActiveStep(stateName, processExited);
// If the current swap is being manually cancelled and refund, we want to show the unhappy path even though the current state is not a "unhappy" state
if (currentSwapSpawnType === SwapSpawnType.CANCEL_REFUND) {
return <UnhappyPathStepper activeStep={0} error={error} />;
}
// If the current swap is being manually cancelled and refund, we want to show the unhappy path even though the current state is not a "unhappy" state
if (currentSwapSpawnType === SwapSpawnType.CANCEL_REFUND) {
return <UnhappyPathStepper activeStep={0} error={error} />;
}
if (pathType === PathType.HAPPY_PATH) {
return <HappyPathStepper activeStep={activeStep} error={error} />;
}
return <UnhappyPathStepper activeStep={activeStep} error={error} />;
if (pathType === PathType.HAPPY_PATH) {
return <HappyPathStepper activeStep={activeStep} error={error} />;
}
return <UnhappyPathStepper activeStep={activeStep} error={error} />;
}

View file

@ -1,6 +1,6 @@
import { Link, Typography } from '@material-ui/core';
import { ReactNode } from 'react';
import InfoBox from './InfoBox';
import { Link, Typography } from "@material-ui/core";
import { ReactNode } from "react";
import InfoBox from "./InfoBox";
type TransactionInfoBoxProps = {
title: string;

View file

@ -1,6 +1,6 @@
import { Tooltip } from '@material-ui/core';
import IconButton from '@material-ui/core/IconButton';
import DeveloperBoardIcon from '@material-ui/icons/DeveloperBoard';
import { Tooltip } from "@material-ui/core";
import IconButton from "@material-ui/core/IconButton";
import DeveloperBoardIcon from "@material-ui/icons/DeveloperBoard";
export default function DebugPageSwitchBadge({
enabled,
@ -14,10 +14,10 @@ export default function DebugPageSwitchBadge({
};
return (
<Tooltip title={enabled ? 'Hide debug view' : 'Show debug view'}>
<Tooltip title={enabled ? "Hide debug view" : "Show debug view"}>
<IconButton
onClick={handleToggle}
color={enabled ? 'primary' : 'default'}
color={enabled ? "primary" : "default"}
>
<DeveloperBoardIcon />
</IconButton>

View file

@ -1,7 +1,7 @@
import { IconButton } from '@material-ui/core';
import FeedbackIcon from '@material-ui/icons/Feedback';
import FeedbackDialog from '../../feedback/FeedbackDialog';
import { useState } from 'react';
import { IconButton } from "@material-ui/core";
import FeedbackIcon from "@material-ui/icons/Feedback";
import FeedbackDialog from "../../feedback/FeedbackDialog";
import { useState } from "react";
export default function FeedbackSubmitBadge() {
const [showFeedbackDialog, setShowFeedbackDialog] = useState(false);

View file

@ -1,5 +1,5 @@
import { Box } from '@material-ui/core';
import { useAppSelector } from 'store/hooks';
import { Box } from "@material-ui/core";
import { useAppSelector } from "store/hooks";
import {
isSwapStateBtcCancelled,
isSwapStateBtcLockInMempool,
@ -15,23 +15,23 @@ import {
isSwapStateXmrLockInMempool,
isSwapStateXmrRedeemInMempool,
SwapState,
} from '../../../../../models/storeModel';
import InitiatedPage from './init/InitiatedPage';
import WaitingForBitcoinDepositPage from './init/WaitingForBitcoinDepositPage';
import StartedPage from './in_progress/StartedPage';
import BitcoinLockTxInMempoolPage from './in_progress/BitcoinLockTxInMempoolPage';
import XmrLockTxInMempoolPage from './in_progress/XmrLockInMempoolPage';
} from "../../../../../models/storeModel";
import InitiatedPage from "./init/InitiatedPage";
import WaitingForBitcoinDepositPage from "./init/WaitingForBitcoinDepositPage";
import StartedPage from "./in_progress/StartedPage";
import BitcoinLockTxInMempoolPage from "./in_progress/BitcoinLockTxInMempoolPage";
import XmrLockTxInMempoolPage from "./in_progress/XmrLockInMempoolPage";
// eslint-disable-next-line import/no-cycle
import ProcessExitedPage from './exited/ProcessExitedPage';
import XmrRedeemInMempoolPage from './done/XmrRedeemInMempoolPage';
import ReceivedQuotePage from './in_progress/ReceivedQuotePage';
import BitcoinRedeemedPage from './in_progress/BitcoinRedeemedPage';
import InitPage from './init/InitPage';
import XmrLockedPage from './in_progress/XmrLockedPage';
import BitcoinCancelledPage from './in_progress/BitcoinCancelledPage';
import BitcoinRefundedPage from './done/BitcoinRefundedPage';
import BitcoinPunishedPage from './done/BitcoinPunishedPage';
import { SyncingMoneroWalletPage } from './in_progress/SyncingMoneroWalletPage';
import ProcessExitedPage from "./exited/ProcessExitedPage";
import XmrRedeemInMempoolPage from "./done/XmrRedeemInMempoolPage";
import ReceivedQuotePage from "./in_progress/ReceivedQuotePage";
import BitcoinRedeemedPage from "./in_progress/BitcoinRedeemedPage";
import InitPage from "./init/InitPage";
import XmrLockedPage from "./in_progress/XmrLockedPage";
import BitcoinCancelledPage from "./in_progress/BitcoinCancelledPage";
import BitcoinRefundedPage from "./done/BitcoinRefundedPage";
import BitcoinPunishedPage from "./done/BitcoinPunishedPage";
import { SyncingMoneroWalletPage } from "./in_progress/SyncingMoneroWalletPage";
export default function SwapStatePage({
swapState,

View file

@ -1,6 +1,6 @@
import { IconButton, Tooltip } from '@material-ui/core';
import { useAppSelector } from 'store/hooks';
import TorIcon from '../../../icons/TorIcon';
import { IconButton, Tooltip } from "@material-ui/core";
import { useAppSelector } from "store/hooks";
import TorIcon from "../../../icons/TorIcon";
export default function TorStatusBadge() {
const tor = useAppSelector((s) => s.tor);

View file

@ -1,5 +1,5 @@
import { Box, DialogContentText } from '@material-ui/core';
import FeedbackInfoBox from '../../../../pages/help/FeedbackInfoBox';
import { Box, DialogContentText } from "@material-ui/core";
import FeedbackInfoBox from "../../../../pages/help/FeedbackInfoBox";
export default function BitcoinPunishedPage() {
return (

View file

@ -5,40 +5,39 @@ import BitcoinTransactionInfoBox from "../../BitcoinTransactionInfoBox";
import FeedbackInfoBox from "../../../../pages/help/FeedbackInfoBox";
export default function BitcoinRefundedPage({
state,
state,
}: {
state: SwapStateBtcRefunded | null;
state: SwapStateBtcRefunded | null;
}) {
const swap = useActiveSwapInfo();
const additionalContent = swap
? `Refund address: ${swap.btc_refund_address}`
: null;
const swap = useActiveSwapInfo();
const additionalContent = swap
? `Refund address: ${swap.btc_refund_address}`
: null;
return (
<Box>
<DialogContentText>
Unfortunately, the swap was not successful. However, rest
assured that all your Bitcoin has been refunded to the specified
address. The swap process is now complete, and you are free to
exit the application.
</DialogContentText>
<Box
style={{
display: "flex",
flexDirection: "column",
gap: "0.5rem",
}}
>
{state && (
<BitcoinTransactionInfoBox
title="Bitcoin Refund Transaction"
txId={state.bobBtcRefundTxId}
loading={false}
additionalContent={additionalContent}
/>
)}
<FeedbackInfoBox />
</Box>
</Box>
);
return (
<Box>
<DialogContentText>
Unfortunately, the swap was not successful. However, rest assured that
all your Bitcoin has been refunded to the specified address. The swap
process is now complete, and you are free to exit the application.
</DialogContentText>
<Box
style={{
display: "flex",
flexDirection: "column",
gap: "0.5rem",
}}
>
{state && (
<BitcoinTransactionInfoBox
title="Bitcoin Refund Transaction"
txId={state.bobBtcRefundTxId}
loading={false}
additionalContent={additionalContent}
/>
)}
<FeedbackInfoBox />
</Box>
</Box>
);
}

View file

@ -1,9 +1,9 @@
import { Box, DialogContentText } from '@material-ui/core';
import { SwapStateXmrRedeemInMempool } from 'models/storeModel';
import { useActiveSwapInfo } from 'store/hooks';
import { getSwapXmrAmount } from 'models/rpcModel';
import MoneroTransactionInfoBox from '../../MoneroTransactionInfoBox';
import FeedbackInfoBox from '../../../../pages/help/FeedbackInfoBox';
import { Box, DialogContentText } from "@material-ui/core";
import { SwapStateXmrRedeemInMempool } from "models/storeModel";
import { useActiveSwapInfo } from "store/hooks";
import { getSwapXmrAmount } from "models/rpcModel";
import MoneroTransactionInfoBox from "../../MoneroTransactionInfoBox";
import FeedbackInfoBox from "../../../../pages/help/FeedbackInfoBox";
type XmrRedeemInMempoolPageProps = {
state: SwapStateXmrRedeemInMempool | null;
@ -27,9 +27,9 @@ export default function XmrRedeemInMempoolPage({
</DialogContentText>
<Box
style={{
display: 'flex',
flexDirection: 'column',
gap: '0.5rem',
display: "flex",
flexDirection: "column",
gap: "0.5rem",
}}
>
{state && (

View file

@ -5,67 +5,67 @@ import CliLogsBox from "../../../../other/RenderedCliLog";
import { SwapSpawnType } from "models/cliModel";
export default function ProcessExitedAndNotDonePage({
state,
state,
}: {
state: SwapStateProcessExited;
state: SwapStateProcessExited;
}) {
const swap = useActiveSwapInfo();
const logs = useAppSelector((s) => s.swap.logs);
const spawnType = useAppSelector((s) => s.swap.spawnType);
const swap = useActiveSwapInfo();
const logs = useAppSelector((s) => s.swap.logs);
const spawnType = useAppSelector((s) => s.swap.spawnType);
function getText() {
const isCancelRefund = spawnType === SwapSpawnType.CANCEL_REFUND;
const hasRpcError = state.rpcError != null;
const hasSwap = swap != null;
function getText() {
const isCancelRefund = spawnType === SwapSpawnType.CANCEL_REFUND;
const hasRpcError = state.rpcError != null;
const hasSwap = swap != null;
let messages = [];
let messages = [];
messages.push(
isCancelRefund
? "The manual cancel and refund was unsuccessful."
: "The swap exited unexpectedly without completing.",
);
messages.push(
isCancelRefund
? "The manual cancel and refund was unsuccessful."
: "The swap exited unexpectedly without completing.",
);
if (!hasSwap && !isCancelRefund) {
messages.push("No funds were locked.");
}
messages.push(
hasRpcError
? "Check the error and the logs below for more information."
: "Check the logs below for more information.",
);
if (hasSwap) {
messages.push(`The swap is in the "${swap.state_name}" state.`);
if (!isCancelRefund) {
messages.push(
"Try resuming the swap or attempt to initiate a manual cancel and refund.",
);
}
}
return messages.join(" ");
if (!hasSwap && !isCancelRefund) {
messages.push("No funds were locked.");
}
return (
<Box>
<DialogContentText>{getText()}</DialogContentText>
<Box
style={{
display: "flex",
flexDirection: "column",
gap: "0.5rem",
}}
>
{state.rpcError && (
<CliLogsBox
logs={[state.rpcError]}
label="Error returned by the Swap Daemon"
/>
)}
<CliLogsBox logs={logs} label="Logs relevant to the swap" />
</Box>
</Box>
messages.push(
hasRpcError
? "Check the error and the logs below for more information."
: "Check the logs below for more information.",
);
if (hasSwap) {
messages.push(`The swap is in the "${swap.state_name}" state.`);
if (!isCancelRefund) {
messages.push(
"Try resuming the swap or attempt to initiate a manual cancel and refund.",
);
}
}
return messages.join(" ");
}
return (
<Box>
<DialogContentText>{getText()}</DialogContentText>
<Box
style={{
display: "flex",
flexDirection: "column",
gap: "0.5rem",
}}
>
{state.rpcError && (
<CliLogsBox
logs={[state.rpcError]}
label="Error returned by the Swap Daemon"
/>
)}
<CliLogsBox logs={logs} label="Logs relevant to the swap" />
</Box>
</Box>
);
}

View file

@ -1,10 +1,10 @@
import { useActiveSwapInfo } from "store/hooks";
import { SwapStateName } from "models/rpcModel";
import {
isSwapStateBtcPunished,
isSwapStateBtcRefunded,
isSwapStateXmrRedeemInMempool,
SwapStateProcessExited,
isSwapStateBtcPunished,
isSwapStateBtcRefunded,
isSwapStateXmrRedeemInMempool,
SwapStateProcessExited,
} from "../../../../../../models/storeModel";
import XmrRedeemInMempoolPage from "../done/XmrRedeemInMempoolPage";
import BitcoinPunishedPage from "../done/BitcoinPunishedPage";
@ -14,34 +14,34 @@ import BitcoinRefundedPage from "../done/BitcoinRefundedPage";
import ProcessExitedAndNotDonePage from "./ProcessExitedAndNotDonePage";
type ProcessExitedPageProps = {
state: SwapStateProcessExited;
state: SwapStateProcessExited;
};
export default function ProcessExitedPage({ state }: ProcessExitedPageProps) {
const swap = useActiveSwapInfo();
const swap = useActiveSwapInfo();
// If we have a swap state, for a "done" state we should use it to display additional information that can't be extracted from the database
if (
isSwapStateXmrRedeemInMempool(state.prevState) ||
isSwapStateBtcRefunded(state.prevState) ||
isSwapStateBtcPunished(state.prevState)
) {
return <SwapStatePage swapState={state.prevState} />;
// If we have a swap state, for a "done" state we should use it to display additional information that can't be extracted from the database
if (
isSwapStateXmrRedeemInMempool(state.prevState) ||
isSwapStateBtcRefunded(state.prevState) ||
isSwapStateBtcPunished(state.prevState)
) {
return <SwapStatePage swapState={state.prevState} />;
}
// If we don't have a swap state for a "done" state, we should fall back to using the database to display as much information as we can
if (swap) {
if (swap.state_name === SwapStateName.XmrRedeemed) {
return <XmrRedeemInMempoolPage state={null} />;
}
// If we don't have a swap state for a "done" state, we should fall back to using the database to display as much information as we can
if (swap) {
if (swap.state_name === SwapStateName.XmrRedeemed) {
return <XmrRedeemInMempoolPage state={null} />;
}
if (swap.state_name === SwapStateName.BtcRefunded) {
return <BitcoinRefundedPage state={null} />;
}
if (swap.state_name === SwapStateName.BtcPunished) {
return <BitcoinPunishedPage />;
}
if (swap.state_name === SwapStateName.BtcRefunded) {
return <BitcoinRefundedPage state={null} />;
}
if (swap.state_name === SwapStateName.BtcPunished) {
return <BitcoinPunishedPage />;
}
}
// If the swap is not a "done" state (or we don't have a db state because the swap did complete the SwapSetup yet) we should tell the user and show logs
return <ProcessExitedAndNotDonePage state={state} />;
// If the swap is not a "done" state (or we don't have a db state because the swap did complete the SwapSetup yet) we should tell the user and show logs
return <ProcessExitedAndNotDonePage state={state} />;
}

View file

@ -1,4 +1,4 @@
import CircularProgressWithSubtitle from '../../CircularProgressWithSubtitle';
import CircularProgressWithSubtitle from "../../CircularProgressWithSubtitle";
export default function BitcoinCancelledPage() {
return <CircularProgressWithSubtitle description="Refunding your Bitcoin" />;

View file

@ -1,7 +1,7 @@
import { Box, DialogContentText } from '@material-ui/core';
import { SwapStateBtcLockInMempool } from 'models/storeModel';
import BitcoinTransactionInfoBox from '../../BitcoinTransactionInfoBox';
import SwapMightBeCancelledAlert from '../../../../alert/SwapMightBeCancelledAlert';
import { Box, DialogContentText } from "@material-ui/core";
import { SwapStateBtcLockInMempool } from "models/storeModel";
import BitcoinTransactionInfoBox from "../../BitcoinTransactionInfoBox";
import SwapMightBeCancelledAlert from "../../../../alert/SwapMightBeCancelledAlert";
type BitcoinLockTxInMempoolPageProps = {
state: SwapStateBtcLockInMempool;

View file

@ -1,4 +1,4 @@
import CircularProgressWithSubtitle from '../../CircularProgressWithSubtitle';
import CircularProgressWithSubtitle from "../../CircularProgressWithSubtitle";
export default function BitcoinRedeemedPage() {
return <CircularProgressWithSubtitle description="Redeeming your Monero" />;

View file

@ -1,4 +1,4 @@
import CircularProgressWithSubtitle from '../../CircularProgressWithSubtitle';
import CircularProgressWithSubtitle from "../../CircularProgressWithSubtitle";
export default function ReceivedQuotePage() {
return (

View file

@ -1,6 +1,6 @@
import { SwapStateStarted } from 'models/storeModel';
import { BitcoinAmount } from 'renderer/components/other/Units';
import CircularProgressWithSubtitle from '../../CircularProgressWithSubtitle';
import { SwapStateStarted } from "models/storeModel";
import { BitcoinAmount } from "renderer/components/other/Units";
import CircularProgressWithSubtitle from "../../CircularProgressWithSubtitle";
export default function StartedPage({ state }: { state: SwapStateStarted }) {
const description = state.txLockDetails ? (
@ -9,7 +9,7 @@ export default function StartedPage({ state }: { state: SwapStateStarted }) {
network fee of <BitcoinAmount amount={state.txLockDetails.fees} />
</>
) : (
'Locking Bitcoin'
"Locking Bitcoin"
);
return <CircularProgressWithSubtitle description={description} />;

View file

@ -1,4 +1,4 @@
import CircularProgressWithSubtitle from '../../CircularProgressWithSubtitle';
import CircularProgressWithSubtitle from "../../CircularProgressWithSubtitle";
export function SyncingMoneroWalletPage() {
return (

View file

@ -1,6 +1,6 @@
import { Box, DialogContentText } from '@material-ui/core';
import { SwapStateXmrLockInMempool } from 'models/storeModel';
import MoneroTransactionInfoBox from '../../MoneroTransactionInfoBox';
import { Box, DialogContentText } from "@material-ui/core";
import { SwapStateXmrLockInMempool } from "models/storeModel";
import MoneroTransactionInfoBox from "../../MoneroTransactionInfoBox";
type XmrLockTxInMempoolPageProps = {
state: SwapStateXmrLockInMempool;

View file

@ -1,4 +1,4 @@
import CircularProgressWithSubtitle from '../../CircularProgressWithSubtitle';
import CircularProgressWithSubtitle from "../../CircularProgressWithSubtitle";
export default function XmrLockedPage() {
return (

View file

@ -1,24 +1,24 @@
import { useState } from 'react';
import { Box, makeStyles, TextField, Typography } from '@material-ui/core';
import { SwapStateWaitingForBtcDeposit } from 'models/storeModel';
import { useAppSelector } from 'store/hooks';
import { satsToBtc } from 'utils/conversionUtils';
import { MoneroAmount } from '../../../../other/Units';
import { useState } from "react";
import { Box, makeStyles, TextField, Typography } from "@material-ui/core";
import { SwapStateWaitingForBtcDeposit } from "models/storeModel";
import { useAppSelector } from "store/hooks";
import { satsToBtc } from "utils/conversionUtils";
import { MoneroAmount } from "../../../../other/Units";
const MONERO_FEE = 0.000016;
const useStyles = makeStyles((theme) => ({
outer: {
display: 'flex',
alignItems: 'center',
display: "flex",
alignItems: "center",
gap: theme.spacing(1),
},
textField: {
'& input::-webkit-outer-spin-button, & input::-webkit-inner-spin-button': {
display: 'none',
"& input::-webkit-outer-spin-button, & input::-webkit-inner-spin-button": {
display: "none",
},
'& input[type=number]': {
MozAppearance: 'textfield',
"& input[type=number]": {
MozAppearance: "textfield",
},
maxWidth: theme.spacing(16),
},
@ -83,7 +83,7 @@ export default function DepositAmountHelper({
className={classes.textField}
/>
<Typography variant="subtitle2">
BTC will give you approximately{' '}
BTC will give you approximately{" "}
<MoneroAmount amount={calcXMRAmount()} />.
</Typography>
</Box>

View file

@ -1,5 +1,5 @@
import CircularProgressWithSubtitle from '../../CircularProgressWithSubtitle';
import { MoneroWalletRpcUpdateState } from '../../../../../../models/storeModel';
import CircularProgressWithSubtitle from "../../CircularProgressWithSubtitle";
import { MoneroWalletRpcUpdateState } from "../../../../../../models/storeModel";
export default function DownloadingMoneroWalletRpcPage({
updateState,

View file

@ -1,32 +1,28 @@
import { Box, DialogContentText, makeStyles } from '@material-ui/core';
import { useState } from 'react';
import BitcoinAddressTextField from 'renderer/components/inputs/BitcoinAddressTextField';
import MoneroAddressTextField from 'renderer/components/inputs/MoneroAddressTextField';
import { useAppSelector } from 'store/hooks';
import PlayArrowIcon from '@material-ui/icons/PlayArrow';
import { isTestnet } from 'store/config';
import RemainingFundsWillBeUsedAlert from '../../../../alert/RemainingFundsWillBeUsedAlert';
import IpcInvokeButton from '../../../../IpcInvokeButton';
import { Box, DialogContentText, makeStyles } from "@material-ui/core";
import { useState } from "react";
import BitcoinAddressTextField from "renderer/components/inputs/BitcoinAddressTextField";
import MoneroAddressTextField from "renderer/components/inputs/MoneroAddressTextField";
import { useAppSelector } from "store/hooks";
import PlayArrowIcon from "@material-ui/icons/PlayArrow";
import { isTestnet } from "store/config";
import RemainingFundsWillBeUsedAlert from "../../../../alert/RemainingFundsWillBeUsedAlert";
import IpcInvokeButton from "../../../../IpcInvokeButton";
const useStyles = makeStyles((theme) => ({
initButton: {
marginTop: theme.spacing(1),
},
fieldsOuter: {
display: 'flex',
flexDirection: 'column',
display: "flex",
flexDirection: "column",
gap: theme.spacing(2),
},
}));
export default function InitPage() {
const classes = useStyles();
const [redeemAddress, setRedeemAddress] = useState(
''
);
const [refundAddress, setRefundAddress] = useState(
''
);
const [redeemAddress, setRedeemAddress] = useState("");
const [refundAddress, setRefundAddress] = useState("");
const [redeemAddressValid, setRedeemAddressValid] = useState(false);
const [refundAddressValid, setRefundAddressValid] = useState(false);
const selectedProvider = useAppSelector(

View file

@ -1,19 +1,19 @@
import { useAppSelector } from 'store/hooks';
import { SwapSpawnType } from 'models/cliModel';
import CircularProgressWithSubtitle from '../../CircularProgressWithSubtitle';
import { useAppSelector } from "store/hooks";
import { SwapSpawnType } from "models/cliModel";
import CircularProgressWithSubtitle from "../../CircularProgressWithSubtitle";
export default function InitiatedPage() {
const description = useAppSelector((s) => {
switch (s.swap.spawnType) {
case SwapSpawnType.INIT:
return 'Requesting quote from provider...';
return "Requesting quote from provider...";
case SwapSpawnType.RESUME:
return 'Resuming swap...';
return "Resuming swap...";
case SwapSpawnType.CANCEL_REFUND:
return 'Attempting to cancel & refund swap...';
return "Attempting to cancel & refund swap...";
default:
// Should never be hit
return 'Initiating swap...';
return "Initiating swap...";
}
});

View file

@ -1,25 +1,25 @@
import { Box, makeStyles, Typography } from '@material-ui/core';
import { SwapStateWaitingForBtcDeposit } from 'models/storeModel';
import { useAppSelector } from 'store/hooks';
import DepositAddressInfoBox from '../../DepositAddressInfoBox';
import BitcoinIcon from '../../../../icons/BitcoinIcon';
import DepositAmountHelper from './DepositAmountHelper';
import { Box, makeStyles, Typography } from "@material-ui/core";
import { SwapStateWaitingForBtcDeposit } from "models/storeModel";
import { useAppSelector } from "store/hooks";
import DepositAddressInfoBox from "../../DepositAddressInfoBox";
import BitcoinIcon from "../../../../icons/BitcoinIcon";
import DepositAmountHelper from "./DepositAmountHelper";
import {
BitcoinAmount,
MoneroBitcoinExchangeRate,
SatsAmount,
} from '../../../../other/Units';
} from "../../../../other/Units";
const useStyles = makeStyles((theme) => ({
amountHelper: {
display: 'flex',
alignItems: 'center',
display: "flex",
alignItems: "center",
},
additionalContent: {
paddingTop: theme.spacing(1),
gap: theme.spacing(0.5),
display: 'flex',
flexDirection: 'column',
display: "flex",
flexDirection: "column",
},
}));
@ -45,13 +45,13 @@ export default function WaitingForBtcDepositPage({
<ul>
{bitcoinBalance > 0 ? (
<li>
You have already deposited{' '}
You have already deposited{" "}
<SatsAmount amount={bitcoinBalance} />
</li>
) : null}
<li>
Send any amount between{' '}
<BitcoinAmount amount={state.minDeposit} /> and{' '}
Send any amount between{" "}
<BitcoinAmount amount={state.minDeposit} /> and{" "}
<BitcoinAmount amount={state.maxDeposit} /> to the address
above
{bitcoinBalance > 0 && (
@ -60,11 +60,11 @@ export default function WaitingForBtcDepositPage({
</li>
<li>
All Bitcoin sent to this this address will converted into
Monero at an exchance rate of{' '}
Monero at an exchance rate of{" "}
<MoneroBitcoinExchangeRate rate={state.price} />
</li>
<li>
The network fee of{' '}
The network fee of{" "}
<BitcoinAmount amount={state.minBitcoinLockTxFee} /> will
automatically be deducted from the deposited coins
</li>
@ -74,9 +74,7 @@ export default function WaitingForBtcDepositPage({
</li>
</ul>
</Typography>
<DepositAmountHelper
state={state}
/>
<DepositAmountHelper state={state} />
</Box>
}
icon={<BitcoinIcon />}