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

@ -24,5 +24,5 @@ export interface Alert {
id: number;
title: string;
body: string;
severity: 'info' | 'warning' | 'error';
severity: "info" | "warning" | "error";
}

View file

@ -1,14 +1,14 @@
export enum SwapSpawnType {
INIT = 'init',
RESUME = 'resume',
CANCEL_REFUND = 'cancel-refund',
INIT = "init",
RESUME = "resume",
CANCEL_REFUND = "cancel-refund",
}
export type CliLogSpanType = string | 'BitcoinWalletSubscription';
export type CliLogSpanType = string | "BitcoinWalletSubscription";
export interface CliLog {
timestamp: string;
level: 'DEBUG' | 'INFO' | 'WARN' | 'ERROR' | 'TRACE';
level: "DEBUG" | "INFO" | "WARN" | "ERROR" | "TRACE";
fields: {
message: string;
[index: string]: unknown;
@ -20,12 +20,12 @@ export interface CliLog {
}
export function isCliLog(log: unknown): log is CliLog {
if (log && typeof log === 'object') {
if (log && typeof log === "object") {
return (
'timestamp' in (log as CliLog) &&
'level' in (log as CliLog) &&
'fields' in (log as CliLog) &&
typeof (log as CliLog).fields?.message === 'string'
"timestamp" in (log as CliLog) &&
"level" in (log as CliLog) &&
"fields" in (log as CliLog) &&
typeof (log as CliLog).fields?.message === "string"
);
}
return false;
@ -33,7 +33,7 @@ export function isCliLog(log: unknown): log is CliLog {
export interface CliLogStartedRpcServer extends CliLog {
fields: {
message: 'Started RPC server';
message: "Started RPC server";
addr: string;
};
}
@ -41,12 +41,12 @@ export interface CliLogStartedRpcServer extends CliLog {
export function isCliLogStartedRpcServer(
log: CliLog,
): log is CliLogStartedRpcServer {
return log.fields.message === 'Started RPC server';
return log.fields.message === "Started RPC server";
}
export interface CliLogReleasingSwapLockLog extends CliLog {
fields: {
message: 'Releasing swap lock';
message: "Releasing swap lock";
swap_id: string;
};
}
@ -54,23 +54,23 @@ export interface CliLogReleasingSwapLockLog extends CliLog {
export function isCliLogReleasingSwapLockLog(
log: CliLog,
): log is CliLogReleasingSwapLockLog {
return log.fields.message === 'Releasing swap lock';
return log.fields.message === "Releasing swap lock";
}
export interface CliLogApiCallError extends CliLog {
fields: {
message: 'API call resulted in an error';
message: "API call resulted in an error";
err: string;
};
}
export function isCliLogApiCallError(log: CliLog): log is CliLogApiCallError {
return log.fields.message === 'API call resulted in an error';
return log.fields.message === "API call resulted in an error";
}
export interface CliLogAcquiringSwapLockLog extends CliLog {
fields: {
message: 'Acquiring swap lock';
message: "Acquiring swap lock";
swap_id: string;
};
}
@ -78,12 +78,12 @@ export interface CliLogAcquiringSwapLockLog extends CliLog {
export function isCliLogAcquiringSwapLockLog(
log: CliLog,
): log is CliLogAcquiringSwapLockLog {
return log.fields.message === 'Acquiring swap lock';
return log.fields.message === "Acquiring swap lock";
}
export interface CliLogReceivedQuote extends CliLog {
fields: {
message: 'Received quote';
message: "Received quote";
price: string;
minimum_amount: string;
maximum_amount: string;
@ -91,12 +91,12 @@ export interface CliLogReceivedQuote extends CliLog {
}
export function isCliLogReceivedQuote(log: CliLog): log is CliLogReceivedQuote {
return log.fields.message === 'Received quote';
return log.fields.message === "Received quote";
}
export interface CliLogWaitingForBtcDeposit extends CliLog {
fields: {
message: 'Waiting for Bitcoin deposit';
message: "Waiting for Bitcoin deposit";
deposit_address: string;
min_deposit_until_swap_will_start: string;
max_deposit_until_maximum_amount_is_reached: string;
@ -111,24 +111,24 @@ export interface CliLogWaitingForBtcDeposit extends CliLog {
export function isCliLogWaitingForBtcDeposit(
log: CliLog,
): log is CliLogWaitingForBtcDeposit {
return log.fields.message === 'Waiting for Bitcoin deposit';
return log.fields.message === "Waiting for Bitcoin deposit";
}
export interface CliLogReceivedBtc extends CliLog {
fields: {
message: 'Received Bitcoin';
message: "Received Bitcoin";
max_giveable: string;
new_balance: string;
};
}
export function isCliLogReceivedBtc(log: CliLog): log is CliLogReceivedBtc {
return log.fields.message === 'Received Bitcoin';
return log.fields.message === "Received Bitcoin";
}
export interface CliLogDeterminedSwapAmount extends CliLog {
fields: {
message: 'Determined swap amount';
message: "Determined swap amount";
amount: string;
fees: string;
};
@ -137,49 +137,49 @@ export interface CliLogDeterminedSwapAmount extends CliLog {
export function isCliLogDeterminedSwapAmount(
log: CliLog,
): log is CliLogDeterminedSwapAmount {
return log.fields.message === 'Determined swap amount';
return log.fields.message === "Determined swap amount";
}
export interface CliLogStartedSwap extends CliLog {
fields: {
message: 'Starting new swap';
message: "Starting new swap";
swap_id: string;
};
}
export function isCliLogStartedSwap(log: CliLog): log is CliLogStartedSwap {
return log.fields.message === 'Starting new swap';
return log.fields.message === "Starting new swap";
}
export interface CliLogPublishedBtcTx extends CliLog {
fields: {
message: 'Published Bitcoin transaction';
message: "Published Bitcoin transaction";
txid: string;
kind: 'lock' | 'cancel' | 'withdraw' | 'refund';
kind: "lock" | "cancel" | "withdraw" | "refund";
};
}
export function isCliLogPublishedBtcTx(
log: CliLog,
): log is CliLogPublishedBtcTx {
return log.fields.message === 'Published Bitcoin transaction';
return log.fields.message === "Published Bitcoin transaction";
}
export interface CliLogBtcTxFound extends CliLog {
fields: {
message: 'Found relevant Bitcoin transaction';
message: "Found relevant Bitcoin transaction";
txid: string;
status: string;
};
}
export function isCliLogBtcTxFound(log: CliLog): log is CliLogBtcTxFound {
return log.fields.message === 'Found relevant Bitcoin transaction';
return log.fields.message === "Found relevant Bitcoin transaction";
}
export interface CliLogBtcTxStatusChanged extends CliLog {
fields: {
message: 'Bitcoin transaction status changed';
message: "Bitcoin transaction status changed";
txid: string;
new_status: string;
};
@ -188,12 +188,12 @@ export interface CliLogBtcTxStatusChanged extends CliLog {
export function isCliLogBtcTxStatusChanged(
log: CliLog,
): log is CliLogBtcTxStatusChanged {
return log.fields.message === 'Bitcoin transaction status changed';
return log.fields.message === "Bitcoin transaction status changed";
}
export interface CliLogAliceLockedXmr extends CliLog {
fields: {
message: 'Alice locked Monero';
message: "Alice locked Monero";
txid: string;
};
}
@ -201,12 +201,12 @@ export interface CliLogAliceLockedXmr extends CliLog {
export function isCliLogAliceLockedXmr(
log: CliLog,
): log is CliLogAliceLockedXmr {
return log.fields.message === 'Alice locked Monero';
return log.fields.message === "Alice locked Monero";
}
export interface CliLogReceivedXmrLockTxConfirmation extends CliLog {
fields: {
message: 'Received new confirmation for Monero lock tx';
message: "Received new confirmation for Monero lock tx";
txid: string;
seen_confirmations: string;
needed_confirmations: string;
@ -216,50 +216,50 @@ export interface CliLogReceivedXmrLockTxConfirmation extends CliLog {
export function isCliLogReceivedXmrLockTxConfirmation(
log: CliLog,
): log is CliLogReceivedXmrLockTxConfirmation {
return log.fields.message === 'Received new confirmation for Monero lock tx';
return log.fields.message === "Received new confirmation for Monero lock tx";
}
export interface CliLogAdvancingState extends CliLog {
fields: {
message: 'Advancing state';
message: "Advancing state";
state:
| 'quote has been requested'
| 'execution setup done'
| 'btc is locked'
| 'XMR lock transaction transfer proof received'
| 'xmr is locked'
| 'encrypted signature is sent'
| 'btc is redeemed'
| 'cancel timelock is expired'
| 'btc is cancelled'
| 'btc is refunded'
| 'xmr is redeemed'
| 'btc is punished'
| 'safely aborted';
| "quote has been requested"
| "execution setup done"
| "btc is locked"
| "XMR lock transaction transfer proof received"
| "xmr is locked"
| "encrypted signature is sent"
| "btc is redeemed"
| "cancel timelock is expired"
| "btc is cancelled"
| "btc is refunded"
| "xmr is redeemed"
| "btc is punished"
| "safely aborted";
};
}
export function isCliLogAdvancingState(
log: CliLog,
): log is CliLogAdvancingState {
return log.fields.message === 'Advancing state';
return log.fields.message === "Advancing state";
}
export interface CliLogRedeemedXmr extends CliLog {
fields: {
message: 'Successfully transferred XMR to wallet';
message: "Successfully transferred XMR to wallet";
monero_receive_address: string;
txid: string;
};
}
export function isCliLogRedeemedXmr(log: CliLog): log is CliLogRedeemedXmr {
return log.fields.message === 'Successfully transferred XMR to wallet';
return log.fields.message === "Successfully transferred XMR to wallet";
}
export interface YouHaveBeenPunishedCliLog extends CliLog {
fields: {
message: 'You have been punished for not refunding in time';
message: "You have been punished for not refunding in time";
};
}
@ -267,7 +267,7 @@ export function isYouHaveBeenPunishedCliLog(
log: CliLog,
): log is YouHaveBeenPunishedCliLog {
return (
log.fields.message === 'You have been punished for not refunding in time'
log.fields.message === "You have been punished for not refunding in time"
);
}
@ -280,14 +280,14 @@ function getCliLogSpanAttribute<T>(log: CliLog, key: string): T | null {
}
export function getCliLogSpanSwapId(log: CliLog): string | null {
return getCliLogSpanAttribute<string>(log, 'swap_id');
return getCliLogSpanAttribute<string>(log, "swap_id");
}
export function getCliLogSpanLogReferenceId(log: CliLog): string | null {
return (
getCliLogSpanAttribute<string>(log, 'log_reference_id')?.replace(
getCliLogSpanAttribute<string>(log, "log_reference_id")?.replace(
/"/g,
'',
"",
) || null
);
}
@ -301,7 +301,7 @@ export function hasCliLogOneOfMultipleSpans(
export interface CliLogStartedSyncingMoneroWallet extends CliLog {
fields: {
message: 'Syncing Monero wallet';
message: "Syncing Monero wallet";
current_sync_height?: boolean;
};
}
@ -309,18 +309,18 @@ export interface CliLogStartedSyncingMoneroWallet extends CliLog {
export function isCliLogStartedSyncingMoneroWallet(
log: CliLog,
): log is CliLogStartedSyncingMoneroWallet {
return log.fields.message === 'Syncing Monero wallet';
return log.fields.message === "Syncing Monero wallet";
}
export interface CliLogFinishedSyncingMoneroWallet extends CliLog {
fields: {
message: 'Synced Monero wallet';
message: "Synced Monero wallet";
};
}
export interface CliLogFailedToSyncMoneroWallet extends CliLog {
fields: {
message: 'Failed to sync Monero wallet';
message: "Failed to sync Monero wallet";
error: string;
};
}
@ -328,18 +328,18 @@ export interface CliLogFailedToSyncMoneroWallet extends CliLog {
export function isCliLogFailedToSyncMoneroWallet(
log: CliLog,
): log is CliLogFailedToSyncMoneroWallet {
return log.fields.message === 'Failed to sync Monero wallet';
return log.fields.message === "Failed to sync Monero wallet";
}
export function isCliLogFinishedSyncingMoneroWallet(
log: CliLog,
): log is CliLogFinishedSyncingMoneroWallet {
return log.fields.message === 'Monero wallet synced';
return log.fields.message === "Monero wallet synced";
}
export interface CliLogDownloadingMoneroWalletRpc extends CliLog {
fields: {
message: 'Downloading monero-wallet-rpc';
message: "Downloading monero-wallet-rpc";
progress: string;
size: string;
download_url: string;
@ -349,19 +349,19 @@ export interface CliLogDownloadingMoneroWalletRpc extends CliLog {
export function isCliLogDownloadingMoneroWalletRpc(
log: CliLog,
): log is CliLogDownloadingMoneroWalletRpc {
return log.fields.message === 'Downloading monero-wallet-rpc';
return log.fields.message === "Downloading monero-wallet-rpc";
}
export interface CliLogStartedSyncingMoneroWallet extends CliLog {
fields: {
message: 'Syncing Monero wallet';
message: "Syncing Monero wallet";
current_sync_height?: boolean;
};
}
export interface CliLogDownloadingMoneroWalletRpc extends CliLog {
fields: {
message: 'Downloading monero-wallet-rpc';
message: "Downloading monero-wallet-rpc";
progress: string;
size: string;
download_url: string;
@ -370,7 +370,7 @@ export interface CliLogDownloadingMoneroWalletRpc extends CliLog {
export interface CliLogGotNotificationForNewBlock extends CliLog {
fields: {
message: 'Got notification for new block';
message: "Got notification for new block";
block_height: string;
};
}
@ -378,29 +378,36 @@ export interface CliLogGotNotificationForNewBlock extends CliLog {
export function isCliLogGotNotificationForNewBlock(
log: CliLog,
): log is CliLogGotNotificationForNewBlock {
return log.fields.message === 'Got notification for new block';
return log.fields.message === "Got notification for new block";
}
export interface CliLogAttemptingToCooperativelyRedeemXmr extends CliLog {
fields: {
message: 'Attempting to cooperatively redeem XMR after being punished';
message: "Attempting to cooperatively redeem XMR after being punished";
};
}
export function isCliLogAttemptingToCooperativelyRedeemXmr(
log: CliLog,
): log is CliLogAttemptingToCooperativelyRedeemXmr {
return log.fields.message === 'Attempting to cooperatively redeem XMR after being punished';
return (
log.fields.message ===
"Attempting to cooperatively redeem XMR after being punished"
);
}
export interface CliLogAliceHasAcceptedOurRequestToCooperativelyRedeemTheXmr extends CliLog {
export interface CliLogAliceHasAcceptedOurRequestToCooperativelyRedeemTheXmr
extends CliLog {
fields: {
message: 'Alice has accepted our request to cooperatively redeem the XMR';
message: "Alice has accepted our request to cooperatively redeem the XMR";
};
}
export function isCliLogAliceHasAcceptedOurRequestToCooperativelyRedeemTheXmr(
log: CliLog,
): log is CliLogAliceHasAcceptedOurRequestToCooperativelyRedeemTheXmr {
return log.fields.message === 'Alice has accepted our request to cooperatively redeem the XMR';
return (
log.fields.message ===
"Alice has accepted our request to cooperatively redeem the XMR"
);
}

View file

@ -1,5 +1,5 @@
import { CliLog, SwapSpawnType } from './cliModel';
import { Provider } from './apiModel';
import { CliLog, SwapSpawnType } from "./cliModel";
import { Provider } from "./apiModel";
export interface SwapSlice {
state: SwapState | null;
@ -20,21 +20,21 @@ export interface SwapState {
}
export enum SwapStateType {
INITIATED = 'initiated',
RECEIVED_QUOTE = 'received quote',
WAITING_FOR_BTC_DEPOSIT = 'waiting for btc deposit',
STARTED = 'started',
BTC_LOCK_TX_IN_MEMPOOL = 'btc lock tx is in mempool',
XMR_LOCK_TX_IN_MEMPOOL = 'xmr lock tx is in mempool',
XMR_LOCKED = 'xmr is locked',
BTC_REDEEMED = 'btc redeemed',
XMR_REDEEM_IN_MEMPOOL = 'xmr redeem tx is in mempool',
PROCESS_EXITED = 'process exited',
BTC_CANCELLED = 'btc cancelled',
BTC_REFUNDED = 'btc refunded',
BTC_PUNISHED = 'btc punished',
ATTEMPTING_COOPERATIVE_REDEEM = 'attempting cooperative redeem',
COOPERATIVE_REDEEM_REJECTED = 'cooperative redeem rejected',
INITIATED = "initiated",
RECEIVED_QUOTE = "received quote",
WAITING_FOR_BTC_DEPOSIT = "waiting for btc deposit",
STARTED = "started",
BTC_LOCK_TX_IN_MEMPOOL = "btc lock tx is in mempool",
XMR_LOCK_TX_IN_MEMPOOL = "xmr lock tx is in mempool",
XMR_LOCKED = "xmr is locked",
BTC_REDEEMED = "btc redeemed",
XMR_REDEEM_IN_MEMPOOL = "xmr redeem tx is in mempool",
PROCESS_EXITED = "process exited",
BTC_CANCELLED = "btc cancelled",
BTC_REFUNDED = "btc refunded",
BTC_PUNISHED = "btc punished",
ATTEMPTING_COOPERATIVE_REDEEM = "attempting cooperative redeem",
COOPERATIVE_REDEEM_REJECTED = "cooperative redeem rejected",
}
export function isSwapState(state?: SwapState | null): state is SwapState {

View file

@ -1,6 +1,6 @@
import { Alert, ExtendedProviderStatus } from 'models/apiModel';
import { Alert, ExtendedProviderStatus } from "models/apiModel";
const API_BASE_URL = 'https://api.unstoppableswap.net';
const API_BASE_URL = "https://api.unstoppableswap.net";
export async function fetchProvidersViaHttp(): Promise<
ExtendedProviderStatus[]
@ -23,9 +23,9 @@ export async function submitFeedbackViaHttp(
};
const response = await fetch(`${API_BASE_URL}/api/submit-feedback`, {
method: 'POST',
method: "POST",
headers: {
'Content-Type': 'application/json',
"Content-Type": "application/json",
},
body: JSON.stringify({ body, attachedData }),
});
@ -53,9 +53,9 @@ async function fetchCurrencyUsdPrice(currency: string): Promise<number> {
}
export async function fetchBtcPrice(): Promise<number> {
return fetchCurrencyUsdPrice('bitcoin');
return fetchCurrencyUsdPrice("bitcoin");
}
export async function fetchXmrPrice(): Promise<number> {
return fetchCurrencyUsdPrice('monero');
return fetchCurrencyUsdPrice("monero");
}

View file

@ -1,13 +1,13 @@
import { Box, makeStyles, CssBaseline } from '@material-ui/core';
import { createTheme, ThemeProvider } from '@material-ui/core/styles';
import { indigo } from '@material-ui/core/colors';
import { MemoryRouter as Router, Routes, Route } from 'react-router-dom';
import Navigation, { drawerWidth } from './navigation/Navigation';
import HistoryPage from './pages/history/HistoryPage';
import SwapPage from './pages/swap/SwapPage';
import WalletPage from './pages/wallet/WalletPage';
import HelpPage from './pages/help/HelpPage';
import GlobalSnackbarProvider from './snackbar/GlobalSnackbarProvider';
import { Box, makeStyles, CssBaseline } from "@material-ui/core";
import { createTheme, ThemeProvider } from "@material-ui/core/styles";
import { indigo } from "@material-ui/core/colors";
import { MemoryRouter as Router, Routes, Route } from "react-router-dom";
import Navigation, { drawerWidth } from "./navigation/Navigation";
import HistoryPage from "./pages/history/HistoryPage";
import SwapPage from "./pages/swap/SwapPage";
import WalletPage from "./pages/wallet/WalletPage";
import HelpPage from "./pages/help/HelpPage";
import GlobalSnackbarProvider from "./snackbar/GlobalSnackbarProvider";
const useStyles = makeStyles((theme) => ({
innerContent: {
@ -20,14 +20,14 @@ const useStyles = makeStyles((theme) => ({
const theme = createTheme({
palette: {
type: 'dark',
type: "dark",
primary: {
main: '#f4511e',
main: "#f4511e",
},
secondary: indigo,
},
transitions: {
create: () => 'none',
create: () => "none",
},
props: {
MuiButtonBase: {

View file

@ -4,12 +4,12 @@ import {
CircularProgress,
IconButton,
Tooltip,
} from '@material-ui/core';
import { ReactElement, ReactNode, useEffect, useState } from 'react';
import { useSnackbar } from 'notistack';
import { useAppSelector } from 'store/hooks';
import { RpcProcessStateType } from 'models/rpcModel';
import { isExternalRpc } from 'store/config';
} from "@material-ui/core";
import { ReactElement, ReactNode, useEffect, useState } from "react";
import { useSnackbar } from "notistack";
import { useAppSelector } from "store/hooks";
import { RpcProcessStateType } from "models/rpcModel";
import { isExternalRpc } from "store/config";
function IpcButtonTooltip({
requiresRpcAndNotReady,
@ -27,19 +27,19 @@ function IpcButtonTooltip({
}
const getMessage = () => {
if (!requiresRpcAndNotReady) return '';
if (!requiresRpcAndNotReady) return "";
switch (processType) {
case RpcProcessStateType.LISTENING_FOR_CONNECTIONS:
return '';
return "";
case RpcProcessStateType.STARTED:
return 'Cannot execute this action because the Swap Daemon is still starting and not yet ready to accept connections. Please wait a moment and try again';
return "Cannot execute this action because the Swap Daemon is still starting and not yet ready to accept connections. Please wait a moment and try again";
case RpcProcessStateType.EXITED:
return 'Cannot execute this action because the Swap Daemon has been stopped. Please start the Swap Daemon again to continue';
return "Cannot execute this action because the Swap Daemon has been stopped. Please start the Swap Daemon again to continue";
case RpcProcessStateType.NOT_STARTED:
return 'Cannot execute this action because the Swap Daemon has not been started yet. Please start the Swap Daemon first';
return "Cannot execute this action because the Swap Daemon has not been started yet. Please start the Swap Daemon first";
default:
return '';
return "";
}
};
@ -108,13 +108,13 @@ export default function IpcInvokeButton<T>({
setIsPending(true);
try {
// const result = await ipcRenderer.invoke(ipcChannel, ...ipcArgs);
throw new Error('Not implemented');
throw new Error("Not implemented");
// onSuccess?.(result);
} catch (e: unknown) {
if (displayErrorSnackbar) {
enqueueSnackbar((e as Error).message, {
autoHideDuration: 60 * 1000,
variant: 'error',
variant: "error",
});
}
} finally {

View file

@ -6,7 +6,7 @@ import { ReactNode, useEffect, useState } from "react";
interface IpcInvokeButtonProps<T> {
onSuccess?: (data: T) => void;
onClick: () => Promise<T>;
onPendingChange?: (bool) => void;
onPendingChange?: (isPending: boolean) => void;
isLoadingOverride?: boolean;
isIconButton?: boolean;
loadIcon?: ReactNode;
@ -46,7 +46,7 @@ export default function PromiseInvokeButton<T>({
onSuccess?.(result);
} catch (e: unknown) {
if (displayErrorSnackbar) {
enqueueSnackbar((e as Error).message, {
enqueueSnackbar(e as String, {
autoHideDuration: 60 * 1000,
variant: "error",
});

View file

@ -1,7 +1,7 @@
import { Button } from '@material-ui/core';
import Alert from '@material-ui/lab/Alert';
import { useNavigate } from 'react-router-dom';
import { useAppSelector } from 'store/hooks';
import { Button } from "@material-ui/core";
import Alert from "@material-ui/lab/Alert";
import { useNavigate } from "react-router-dom";
import { useAppSelector } from "store/hooks";
export default function FundsLeftInWalletAlert() {
const fundsLeft = useAppSelector((state) => state.rpc.state.balance);
@ -16,7 +16,7 @@ export default function FundsLeftInWalletAlert() {
<Button
color="inherit"
size="small"
onClick={() => navigate('/wallet')}
onClick={() => navigate("/wallet")}
>
View
</Button>

View file

@ -1,6 +1,6 @@
import { Alert } from '@material-ui/lab';
import { Box, LinearProgress } from '@material-ui/core';
import { useAppSelector } from 'store/hooks';
import { Alert } from "@material-ui/lab";
import { Box, LinearProgress } from "@material-ui/core";
import { useAppSelector } from "store/hooks";
export default function MoneroWalletRpcUpdatingAlert() {
const updateState = useAppSelector(
@ -17,7 +17,7 @@ export default function MoneroWalletRpcUpdatingAlert() {
return (
<Alert severity="info">
<Box style={{ display: 'flex', flexDirection: 'column', gap: '0.5rem' }}>
<Box style={{ display: "flex", flexDirection: "column", gap: "0.5rem" }}>
<span>The Monero wallet is updating. This may take a few moments</span>
<LinearProgress
variant="determinate"

View file

@ -1,8 +1,8 @@
import { Alert } from '@material-ui/lab';
import { Box, makeStyles } from '@material-ui/core';
import { useAppSelector } from 'store/hooks';
import WalletRefreshButton from '../pages/wallet/WalletRefreshButton';
import { SatsAmount } from '../other/Units';
import { Alert } from "@material-ui/lab";
import { Box, makeStyles } from "@material-ui/core";
import { useAppSelector } from "store/hooks";
import WalletRefreshButton from "../pages/wallet/WalletRefreshButton";
import { SatsAmount } from "../other/Units";
const useStyles = makeStyles((theme) => ({
outer: {

View file

@ -1,7 +1,7 @@
import { Alert } from '@material-ui/lab';
import { CircularProgress } from '@material-ui/core';
import { useAppSelector } from 'store/hooks';
import { RpcProcessStateType } from 'models/rpcModel';
import { Alert } from "@material-ui/lab";
import { CircularProgress } from "@material-ui/core";
import { useAppSelector } from "store/hooks";
import { RpcProcessStateType } from "models/rpcModel";
export default function RpcStatusAlert() {
const rpcProcess = useAppSelector((s) => s.rpc.process);

View file

@ -38,21 +38,20 @@ export default function SwapMightBeCancelledAlert({
return (
<Alert severity="warning" className={classes.outer} variant="filled">
<AlertTitle>Be careful!</AlertTitle>
The swap provider has taken a long time to lock their Monero. This
might mean that:
The swap provider has taken a long time to lock their Monero. This might
mean that:
<ul className={classes.list}>
<li>
There is a technical issue that prevents them from locking
their funds
There is a technical issue that prevents them from locking their funds
</li>
<li>They are a malicious actor (unlikely)</li>
</ul>
<br />
There is still hope for the swap to be successful but you have to be
extra careful. Regardless of why it has taken them so long, it is
important that you refund the swap within the required time period
if the swap is not completed. If you fail to to do so, you will be
punished and lose your money.
There is still hope for the swap to be successful but you have to be extra
careful. Regardless of why it has taken them so long, it is important that
you refund the swap within the required time period if the swap is not
completed. If you fail to to do so, you will be punished and lose your
money.
<ul className={classes.list}>
{isSwapTimelockInfoNone(timelock) && (
<>
@ -67,13 +66,9 @@ export default function SwapMightBeCancelledAlert({
<li>
<strong>
If you have not refunded or completed the swap
in about{" "}
If you have not refunded or completed the swap in about{" "}
<HumanizedBitcoinBlockDuration
blocks={
timelock.None.blocks_left +
punishTimelockOffset
}
blocks={timelock.None.blocks_left + punishTimelockOffset}
/>
, you will lose your funds.
</strong>
@ -83,8 +78,7 @@ export default function SwapMightBeCancelledAlert({
{isSwapTimelockInfoCancelled(timelock) && (
<li>
<strong>
If you have not refunded or completed the swap in
about{" "}
If you have not refunded or completed the swap in about{" "}
<HumanizedBitcoinBlockDuration
blocks={timelock.Cancel.blocks_left}
/>
@ -94,8 +88,8 @@ export default function SwapMightBeCancelledAlert({
)}
<li>
As long as you see this screen, the swap will be refunded
automatically when the time comes. If this fails, you have
to manually refund by navigating to the History page.
automatically when the time comes. If this fails, you have to manually
refund by navigating to the History page.
</li>
</ul>
</Alert>

View file

@ -66,11 +66,7 @@ const BitcoinRedeemedStateAlert = ({ swap }: { swap: GetSwapInfoResponse }) => {
"If this step fails, you can manually redeem the funds",
]}
/>
<SwapMoneroRecoveryButton
swap={swap}
size="small"
variant="contained"
/>
<SwapMoneroRecoveryButton swap={swap} size="small" variant="contained" />
</Box>
);
};
@ -91,16 +87,13 @@ const BitcoinLockedNoTimelockExpiredStateAlert = ({
<MessageList
messages={[
<>
Your Bitcoin is locked. If the swap is not completed in
approximately{" "}
<HumanizedBitcoinBlockDuration
blocks={timelock.None.blocks_left}
/>
, you need to refund
Your Bitcoin is locked. If the swap is not completed in approximately{" "}
<HumanizedBitcoinBlockDuration blocks={timelock.None.blocks_left} />,
you need to refund
</>,
<>
You will lose your funds if you do not refund or complete the
swap within{" "}
You will lose your funds if you do not refund or complete the swap
within{" "}
<HumanizedBitcoinBlockDuration
blocks={timelock.None.blocks_left + punishTimelockOffset}
/>
@ -138,11 +131,7 @@ const BitcoinPossiblyCancelledAlert = ({
</>,
]}
/>
<SwapCancelRefundButton
swap={swap}
size="small"
variant="contained"
/>
<SwapCancelRefundButton swap={swap} size="small" variant="contained" />
</Box>
);
};

View file

@ -1,7 +1,7 @@
import { Button } from '@material-ui/core';
import Alert from '@material-ui/lab/Alert';
import { useNavigate } from 'react-router-dom';
import { useResumeableSwapsCount } from 'store/hooks';
import { Button } from "@material-ui/core";
import Alert from "@material-ui/lab/Alert";
import { useNavigate } from "react-router-dom";
import { useResumeableSwapsCount } from "store/hooks";
export default function UnfinishedSwapsAlert() {
const resumableSwapsCount = useResumeableSwapsCount();
@ -16,16 +16,16 @@ export default function UnfinishedSwapsAlert() {
<Button
color="inherit"
size="small"
onClick={() => navigate('/history')}
onClick={() => navigate("/history")}
>
VIEW
</Button>
}
>
You have{' '}
You have{" "}
{resumableSwapsCount > 1
? `${resumableSwapsCount} unfinished swaps`
: 'one unfinished swap'}
: "one unfinished swap"}
</Alert>
);
}

View file

@ -1,5 +1,5 @@
import { SvgIcon } from '@material-ui/core';
import { SvgIconProps } from '@material-ui/core/SvgIcon/SvgIcon';
import { SvgIcon } from "@material-ui/core";
import { SvgIconProps } from "@material-ui/core/SvgIcon/SvgIcon";
export default function BitcoinIcon(props: SvgIconProps) {
return (

View file

@ -1,5 +1,5 @@
import { SvgIconProps } from '@material-ui/core/SvgIcon/SvgIcon';
import { SvgIcon } from '@material-ui/core';
import { SvgIconProps } from "@material-ui/core/SvgIcon/SvgIcon";
import { SvgIcon } from "@material-ui/core";
export default function DiscordIcon(props: SvgIconProps) {
return (

View file

@ -1,5 +1,5 @@
import { ReactNode } from 'react';
import { IconButton } from '@material-ui/core';
import { ReactNode } from "react";
import { IconButton } from "@material-ui/core";
export default function LinkIconButton({
url,
@ -9,7 +9,7 @@ export default function LinkIconButton({
children: ReactNode;
}) {
return (
<IconButton component="span" onClick={() => window.open(url, '_blank')}>
<IconButton component="span" onClick={() => window.open(url, "_blank")}>
{children}
</IconButton>
);

View file

@ -1,5 +1,5 @@
import { SvgIcon } from '@material-ui/core';
import { SvgIconProps } from '@material-ui/core/SvgIcon/SvgIcon';
import { SvgIcon } from "@material-ui/core";
import { SvgIconProps } from "@material-ui/core/SvgIcon/SvgIcon";
export default function MoneroIcon(props: SvgIconProps) {
return (

View file

@ -1,5 +1,5 @@
import { SvgIcon } from '@material-ui/core';
import { SvgIconProps } from '@material-ui/core/SvgIcon/SvgIcon';
import { SvgIcon } from "@material-ui/core";
import { SvgIconProps } from "@material-ui/core/SvgIcon/SvgIcon";
export default function TorIcon(props: SvgIconProps) {
return (

View file

@ -1,8 +1,8 @@
import { useEffect } from 'react';
import { TextField } from '@material-ui/core';
import { TextFieldProps } from '@material-ui/core/TextField/TextField';
import { isBtcAddressValid } from 'utils/conversionUtils';
import { isTestnet } from 'store/config';
import { useEffect } from "react";
import { TextField } from "@material-ui/core";
import { TextFieldProps } from "@material-ui/core/TextField/TextField";
import { isBtcAddressValid } from "utils/conversionUtils";
import { isTestnet } from "store/config";
export default function BitcoinAddressTextField({
address,
@ -16,11 +16,11 @@ export default function BitcoinAddressTextField({
onAddressValidityChange: (valid: boolean) => void;
helperText: string;
} & TextFieldProps) {
const placeholder = isTestnet() ? 'tb1q4aelwalu...' : 'bc18ociqZ9mZ...';
const placeholder = isTestnet() ? "tb1q4aelwalu..." : "bc18ociqZ9mZ...";
const errorText = isBtcAddressValid(address, isTestnet())
? null
: `Only bech32 addresses are supported. They begin with "${
isTestnet() ? 'tb1' : 'bc1'
isTestnet() ? "tb1" : "bc1"
}"`;
useEffect(() => {

View file

@ -1,8 +1,8 @@
import { useEffect } from 'react';
import { TextField } from '@material-ui/core';
import { TextFieldProps } from '@material-ui/core/TextField/TextField';
import { isXmrAddressValid } from 'utils/conversionUtils';
import { isTestnet } from 'store/config';
import { useEffect } from "react";
import { TextField } from "@material-ui/core";
import { TextFieldProps } from "@material-ui/core/TextField/TextField";
import { isXmrAddressValid } from "utils/conversionUtils";
import { isTestnet } from "store/config";
export default function MoneroAddressTextField({
address,
@ -16,10 +16,10 @@ export default function MoneroAddressTextField({
onAddressValidityChange: (valid: boolean) => void;
helperText: string;
} & TextFieldProps) {
const placeholder = isTestnet() ? '59McWTPGc745...' : '888tNkZrPN6J...';
const placeholder = isTestnet() ? "59McWTPGc745..." : "888tNkZrPN6J...";
const errorText = isXmrAddressValid(address, isTestnet())
? null
: 'Not a valid Monero address';
: "Not a valid Monero address";
useEffect(() => {
onAddressValidityChange(!errorText);

View file

@ -1,9 +1,9 @@
import { DialogTitle, makeStyles, Typography } from '@material-ui/core';
import { DialogTitle, makeStyles, Typography } from "@material-ui/core";
const useStyles = makeStyles({
root: {
display: 'flex',
justifyContent: 'space-between',
display: "flex",
justifyContent: "space-between",
},
});

View file

@ -1,12 +1,12 @@
import { Button, makeStyles, Paper, Typography } from '@material-ui/core';
import { Button, makeStyles, Paper, Typography } from "@material-ui/core";
const useStyles = makeStyles((theme) => ({
logsOuter: {
overflow: 'auto',
overflow: "auto",
padding: theme.spacing(1),
marginTop: theme.spacing(1),
marginBottom: theme.spacing(1),
maxHeight: '10rem',
maxHeight: "10rem",
},
copyButton: {
marginTop: theme.spacing(1),
@ -17,7 +17,7 @@ export default function PaperTextBox({ stdOut }: { stdOut: string }) {
const classes = useStyles();
function handleCopyLogs() {
throw new Error('Not implemented');
throw new Error("Not implemented");
}
return (

View file

@ -5,8 +5,8 @@ import {
DialogContent,
DialogContentText,
DialogTitle,
} from '@material-ui/core';
import IpcInvokeButton from '../IpcInvokeButton';
} from "@material-ui/core";
import IpcInvokeButton from "../IpcInvokeButton";
type SwapCancelAlertProps = {
open: boolean;

View file

@ -69,8 +69,7 @@ function SwapSelectDropDown({
{swaps.map((swap) => (
<MenuItem value={swap.swap_id}>
Swap {swap.swap_id.substring(0, 5)}... from{" "}
{new Date(parseDateString(swap.start_date)).toDateString()}{" "}
(
{new Date(parseDateString(swap.start_date)).toDateString()} (
<PiconeroAmount amount={swap.xmr_amount} />)
</MenuItem>
))}
@ -104,11 +103,11 @@ export default function FeedbackDialog({
<DialogTitle>Submit Feedback</DialogTitle>
<DialogContent>
<DialogContentText>
Got something to say? Drop us a message below. If you had an
issue with a specific swap, select it from the dropdown to
attach the logs. It will help us figure out what went wrong.
Hit that submit button when you are ready. We appreciate you
taking the time to share your thoughts!
Got something to say? Drop us a message below. If you had an issue
with a specific swap, select it from the dropdown to attach the logs.
It will help us figure out what went wrong. Hit that submit button
when you are ready. We appreciate you taking the time to share your
thoughts!
</DialogContentText>
<Box
style={{
@ -150,24 +149,15 @@ export default function FeedbackDialog({
try {
setPending(true);
await submitFeedback(
bodyText,
selectedAttachedSwap,
);
enqueueSnackbar(
"Feedback submitted successfully!",
{
await submitFeedback(bodyText, selectedAttachedSwap);
enqueueSnackbar("Feedback submitted successfully!", {
variant: "success",
},
);
});
} catch (e) {
console.error(`Failed to submit feedback: ${e}`);
enqueueSnackbar(
`Failed to submit feedback (${e})`,
{
enqueueSnackbar(`Failed to submit feedback (${e})`, {
variant: "error",
},
);
});
} finally {
setPending(false);
}

View file

@ -1,4 +1,4 @@
import { ChangeEvent, useState } from 'react';
import { ChangeEvent, useState } from "react";
import {
DialogTitle,
Dialog,
@ -11,20 +11,20 @@ import {
Chip,
makeStyles,
Theme,
} from '@material-ui/core';
import { Multiaddr } from 'multiaddr';
import { useSnackbar } from 'notistack';
import IpcInvokeButton from '../../IpcInvokeButton';
} from "@material-ui/core";
import { Multiaddr } from "multiaddr";
import { useSnackbar } from "notistack";
import IpcInvokeButton from "../../IpcInvokeButton";
const PRESET_RENDEZVOUS_POINTS = [
'/dns4/discover.unstoppableswap.net/tcp/8888/p2p/12D3KooWA6cnqJpVnreBVnoro8midDL9Lpzmg8oJPoAGi7YYaamE',
'/dns4/eratosthen.es/tcp/7798/p2p/12D3KooWAh7EXXa2ZyegzLGdjvj1W4G3EXrTGrf6trraoT1MEobs',
"/dns4/discover.unstoppableswap.net/tcp/8888/p2p/12D3KooWA6cnqJpVnreBVnoro8midDL9Lpzmg8oJPoAGi7YYaamE",
"/dns4/eratosthen.es/tcp/7798/p2p/12D3KooWAh7EXXa2ZyegzLGdjvj1W4G3EXrTGrf6trraoT1MEobs",
];
const useStyles = makeStyles((theme: Theme) => ({
chipOuter: {
display: 'flex',
flexWrap: 'wrap',
display: "flex",
flexWrap: "wrap",
gap: theme.spacing(1),
},
}));
@ -39,7 +39,7 @@ export default function ListSellersDialog({
onClose,
}: ListSellersDialogProps) {
const classes = useStyles();
const [rendezvousAddress, setRendezvousAddress] = useState('');
const [rendezvousAddress, setRendezvousAddress] = useState("");
const { enqueueSnackbar } = useSnackbar();
function handleMultiAddrChange(event: ChangeEvent<HTMLInputElement>) {
@ -49,12 +49,12 @@ export default function ListSellersDialog({
function getMultiAddressError(): string | null {
try {
const multiAddress = new Multiaddr(rendezvousAddress);
if (!multiAddress.protoNames().includes('p2p')) {
return 'The multi address must contain the peer id (/p2p/)';
if (!multiAddress.protoNames().includes("p2p")) {
return "The multi address must contain the peer id (/p2p/)";
}
return null;
} catch (e) {
return 'Not a valid multi address';
return "Not a valid multi address";
}
}
@ -73,7 +73,7 @@ export default function ListSellersDialog({
}
enqueueSnackbar(message, {
variant: 'success',
variant: "success",
autoHideDuration: 5000,
});
@ -96,7 +96,7 @@ export default function ListSellersDialog({
label="Rendezvous point"
fullWidth
helperText={
getMultiAddressError() || 'Multiaddress of the rendezvous point'
getMultiAddressError() || "Multiaddress of the rendezvous point"
}
value={rendezvousAddress}
onChange={handleMultiAddrChange}

View file

@ -1,24 +1,24 @@
import { makeStyles, Box, Typography, Chip, Tooltip } from '@material-ui/core';
import { VerifiedUser } from '@material-ui/icons';
import { satsToBtc, secondsToDays } from 'utils/conversionUtils';
import { ExtendedProviderStatus } from 'models/apiModel';
import { makeStyles, Box, Typography, Chip, Tooltip } from "@material-ui/core";
import { VerifiedUser } from "@material-ui/icons";
import { satsToBtc, secondsToDays } from "utils/conversionUtils";
import { ExtendedProviderStatus } from "models/apiModel";
import {
MoneroBitcoinExchangeRate,
SatsAmount,
} from 'renderer/components/other/Units';
} from "renderer/components/other/Units";
const useStyles = makeStyles((theme) => ({
content: {
flex: 1,
'& *': {
lineBreak: 'anywhere',
"& *": {
lineBreak: "anywhere",
},
},
chipsOuter: {
display: 'flex',
display: "flex",
marginTop: theme.spacing(1),
gap: theme.spacing(0.5),
flexWrap: 'wrap',
flexWrap: "wrap",
},
}));
@ -41,7 +41,7 @@ export default function ProviderInfo({
{provider.peerId.substring(0, 8)}...{provider.peerId.slice(-8)}
</Typography>
<Typography variant="caption">
Exchange rate:{' '}
Exchange rate:{" "}
<MoneroBitcoinExchangeRate rate={satsToBtc(provider.price)} />
<br />
Minimum swap amount: <SatsAmount amount={provider.minSwapAmount} />
@ -49,7 +49,7 @@ export default function ProviderInfo({
Maximum swap amount: <SatsAmount amount={provider.maxSwapAmount} />
</Typography>
<Box className={classes.chipsOuter}>
<Chip label={provider.testnet ? 'Testnet' : 'Mainnet'} />
<Chip label={provider.testnet ? "Testnet" : "Mainnet"} />
{provider.uptime && (
<Tooltip title="A high uptime indicates reliability. Providers with low uptime may be unreliable and cause swaps to take longer to complete or fail entirely.">
<Chip label={`${Math.round(provider.uptime * 100)} % uptime`} />
@ -58,7 +58,7 @@ export default function ProviderInfo({
{provider.age ? (
<Chip
label={`Went online ${Math.round(secondsToDays(provider.age))} ${
provider.age === 1 ? 'day' : 'days'
provider.age === 1 ? "day" : "days"
} ago`}
/>
) : (

View file

@ -11,21 +11,21 @@ import {
DialogContent,
makeStyles,
CircularProgress,
} from '@material-ui/core';
import AddIcon from '@material-ui/icons/Add';
import { useState } from 'react';
import SearchIcon from '@material-ui/icons/Search';
import { ExtendedProviderStatus } from 'models/apiModel';
} from "@material-ui/core";
import AddIcon from "@material-ui/icons/Add";
import { useState } from "react";
import SearchIcon from "@material-ui/icons/Search";
import { ExtendedProviderStatus } from "models/apiModel";
import {
useAllProviders,
useAppDispatch,
useIsRpcEndpointBusy,
} from 'store/hooks';
import { setSelectedProvider } from 'store/features/providersSlice';
import { RpcMethod } from 'models/rpcModel';
import ProviderSubmitDialog from './ProviderSubmitDialog';
import ListSellersDialog from '../listSellers/ListSellersDialog';
import ProviderInfo from './ProviderInfo';
} from "store/hooks";
import { setSelectedProvider } from "store/features/providersSlice";
import { RpcMethod } from "models/rpcModel";
import ProviderSubmitDialog from "./ProviderSubmitDialog";
import ListSellersDialog from "../listSellers/ListSellersDialog";
import ProviderInfo from "./ProviderInfo";
const useStyles = makeStyles({
dialogContent: {

View file

@ -4,25 +4,25 @@ import {
CardContent,
Box,
IconButton,
} from '@material-ui/core';
import ArrowForwardIosIcon from '@material-ui/icons/ArrowForwardIos';
import { useState } from 'react';
import { useAppSelector } from 'store/hooks';
import ProviderInfo from './ProviderInfo';
import ProviderListDialog from './ProviderListDialog';
} from "@material-ui/core";
import ArrowForwardIosIcon from "@material-ui/icons/ArrowForwardIos";
import { useState } from "react";
import { useAppSelector } from "store/hooks";
import ProviderInfo from "./ProviderInfo";
import ProviderListDialog from "./ProviderListDialog";
const useStyles = makeStyles({
inner: {
textAlign: 'left',
width: '100%',
height: '100%',
textAlign: "left",
width: "100%",
height: "100%",
},
providerCard: {
width: '100%',
width: "100%",
},
providerCardContent: {
display: 'flex',
alignItems: 'center',
display: "flex",
alignItems: "center",
},
});

View file

@ -1,4 +1,4 @@
import { ChangeEvent, useState } from 'react';
import { ChangeEvent, useState } from "react";
import {
DialogTitle,
Dialog,
@ -7,8 +7,8 @@ import {
TextField,
DialogActions,
Button,
} from '@material-ui/core';
import { Multiaddr } from 'multiaddr';
} from "@material-ui/core";
import { Multiaddr } from "multiaddr";
type ProviderSubmitDialogProps = {
open: boolean;
@ -19,23 +19,23 @@ export default function ProviderSubmitDialog({
open,
onClose,
}: ProviderSubmitDialogProps) {
const [multiAddr, setMultiAddr] = useState('');
const [peerId, setPeerId] = useState('');
const [multiAddr, setMultiAddr] = useState("");
const [peerId, setPeerId] = useState("");
async function handleProviderSubmit() {
if (multiAddr && peerId) {
await fetch('https://api.unstoppableswap.net/api/submit-provider', {
method: 'post',
await fetch("https://api.unstoppableswap.net/api/submit-provider", {
method: "post",
headers: {
'Content-Type': 'application/json',
"Content-Type": "application/json",
},
body: JSON.stringify({
multiAddr,
peerId,
}),
});
setMultiAddr('');
setPeerId('');
setMultiAddr("");
setPeerId("");
onClose();
}
}
@ -51,15 +51,15 @@ export default function ProviderSubmitDialog({
function getMultiAddressError(): string | null {
try {
const multiAddress = new Multiaddr(multiAddr);
if (multiAddress.protoNames().includes('p2p')) {
return 'The multi address should not contain the peer id (/p2p/)';
if (multiAddress.protoNames().includes("p2p")) {
return "The multi address should not contain the peer id (/p2p/)";
}
if (multiAddress.protoNames().find((name) => name.includes('onion'))) {
return 'It is currently not possible to add a provider that is only reachable via Tor';
if (multiAddress.protoNames().find((name) => name.includes("onion"))) {
return "It is currently not possible to add a provider that is only reachable via Tor";
}
return null;
} catch (e) {
return 'Not a valid multi address';
return "Not a valid multi address";
}
}
@ -78,7 +78,7 @@ export default function ProviderSubmitDialog({
fullWidth
helperText={
getMultiAddressError() ||
'Tells the swap client where the provider can be reached'
"Tells the swap client where the provider can be reached"
}
value={multiAddr}
onChange={handleMultiAddrChange}

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

@ -152,10 +152,7 @@ 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 [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) {

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

@ -17,10 +17,9 @@ export default function BitcoinRefundedPage({
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.
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={{

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

@ -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 />}

View file

@ -9,6 +9,7 @@ import { useState } from "react";
import { withdrawBtc } from "renderer/rpc";
import BtcTxInMempoolPageContent from "./pages/BitcoinWithdrawTxInMempoolPage";
import AddressInputPage from "./pages/AddressInputPage";
import WithdrawDialogContent from "./WithdrawDialogContent";
export default function WithdrawDialog({
open,
@ -30,12 +31,10 @@ export default function WithdrawDialog({
}
}
// This prevents an issue where the Dialog is shown for a split second without a present withdraw state
if (!open) return null;
return (
<Dialog open onClose={onCancel} maxWidth="sm" fullWidth>
<Dialog open={open} onClose={onCancel} maxWidth="sm" fullWidth>
<DialogHeader title="Withdraw Bitcoin" />
<WithdrawDialogContent isPending={pending} withdrawTxId={withdrawTxId}>
{withdrawTxId === null ? (
<AddressInputPage
setWithdrawAddress={setWithdrawAddress}
@ -48,9 +47,14 @@ export default function WithdrawDialog({
onCancel={onCancel}
/>
)}
</WithdrawDialogContent>
<DialogActions>
{withdrawTxId === null ? (
<Button onClick={onCancel} color="primary" disabled={pending}>
{withdrawTxId === null ? "Cancel" : "Done"}
</Button>
{withdrawTxId === null && (
<PromiseInvokeButton
displayErrorSnackbar
variant="contained"
color="primary"
disabled={!withdrawAddressValid}
@ -65,10 +69,6 @@ export default function WithdrawDialog({
>
Withdraw
</PromiseInvokeButton>
) : (
<Button onClick={onCancel} color="primary" disabled={pending}>
Close
</Button>
)}
</DialogActions>
</Dialog>

View file

@ -1,27 +1,31 @@
import { ReactNode } from 'react';
import { Box, DialogContent, makeStyles } from '@material-ui/core';
import WithdrawStepper from './WithdrawStepper';
import { ReactNode } from "react";
import { Box, DialogContent, makeStyles } from "@material-ui/core";
import WithdrawStepper from "./WithdrawStepper";
const useStyles = makeStyles({
outer: {
minHeight: '15rem',
display: 'flex',
flexDirection: 'column',
justifyContent: 'space-between',
minHeight: "15rem",
display: "flex",
flexDirection: "column",
justifyContent: "space-between",
},
});
export default function WithdrawDialogContent({
children,
isPending,
withdrawTxId,
}: {
children: ReactNode;
isPending: boolean;
withdrawTxId: string | null;
}) {
const classes = useStyles();
return (
<DialogContent dividers className={classes.outer}>
<Box>{children}</Box>
<WithdrawStepper />
<WithdrawStepper isPending={isPending} withdrawTxId={withdrawTxId} />
</DialogContent>
);
}

View file

@ -1,27 +0,0 @@
import { useAppSelector, useIsRpcEndpointBusy } from 'store/hooks';
import { RpcMethod } from 'models/rpcModel';
import AddressInputPage from './pages/AddressInputPage';
import InitiatedPage from './pages/InitiatedPage';
import BtcTxInMempoolPageContent from './pages/BitcoinWithdrawTxInMempoolPage';
export default function WithdrawStatePage({
onCancel,
}: {
onCancel: () => void;
}) {
const isRpcEndpointBusy = useIsRpcEndpointBusy(RpcMethod.WITHDRAW_BTC);
const withdrawTxId = useAppSelector((state) => state.rpc.state.withdrawTxId);
if (withdrawTxId !== null) {
return (
<BtcTxInMempoolPageContent
withdrawTxId={withdrawTxId}
onCancel={onCancel}
/>
);
}
if (isRpcEndpointBusy) {
return <InitiatedPage onCancel={onCancel} />;
}
return <AddressInputPage onCancel={onCancel} />;
}

View file

@ -1,12 +1,8 @@
import { Step, StepLabel, Stepper } from '@material-ui/core';
import { useAppSelector, useIsRpcEndpointBusy } from 'store/hooks';
import { RpcMethod } from 'models/rpcModel';
import { Step, StepLabel, Stepper } from "@material-ui/core";
import { useAppSelector, useIsRpcEndpointBusy } from "store/hooks";
function getActiveStep(
isWithdrawInProgress: boolean,
withdrawTxId: string | null,
) {
if (isWithdrawInProgress) {
function getActiveStep(isPending: boolean, withdrawTxId: string | null) {
if (isPending) {
return 1;
}
if (withdrawTxId !== null) {
@ -15,12 +11,15 @@ function getActiveStep(
return 0;
}
export default function WithdrawStepper() {
const isWithdrawInProgress = useIsRpcEndpointBusy(RpcMethod.WITHDRAW_BTC);
const withdrawTxId = useAppSelector((s) => s.rpc.state.withdrawTxId);
export default function WithdrawStepper({
isPending,
withdrawTxId,
}: {
isPending: boolean;
withdrawTxId: string | null;
}) {
return (
<Stepper activeStep={getActiveStep(isWithdrawInProgress, withdrawTxId)}>
<Stepper activeStep={getActiveStep(isPending, withdrawTxId)}>
<Step key={0}>
<StepLabel>Enter withdraw address</StepLabel>
</Step>

View file

@ -15,10 +15,9 @@ export default function AddressInputPage({
}) {
return (
<>
<WithdrawDialogContent>
<DialogContentText>
To withdraw the BTC of the internal wallet, please enter an address.
All funds will be sent to that address.
To withdraw the Bitcoin inside the internal wallet, please enter an
address. All funds will be sent to that address.
</DialogContentText>
<BitcoinAddressTextField
@ -28,7 +27,6 @@ export default function AddressInputPage({
helperText="All Bitcoin of the internal wallet will be transferred to this address"
fullWidth
/>
</WithdrawDialogContent>
</>
);
}

View file

@ -11,7 +11,6 @@ export default function BtcTxInMempoolPageContent({
}) {
return (
<>
<WithdrawDialogContent>
<DialogContentText>
All funds of the internal Bitcoin wallet have been transferred to your
withdraw address.
@ -22,7 +21,6 @@ export default function BtcTxInMempoolPageContent({
title="Bitcoin Withdraw Transaction"
additionalContent={null}
/>
</WithdrawDialogContent>
</>
);
}

View file

@ -1,6 +1,6 @@
import { Drawer, makeStyles, Box } from '@material-ui/core';
import NavigationHeader from './NavigationHeader';
import NavigationFooter from './NavigationFooter';
import { Drawer, makeStyles, Box } from "@material-ui/core";
import NavigationHeader from "./NavigationHeader";
import NavigationFooter from "./NavigationFooter";
export const drawerWidth = 240;
@ -13,11 +13,11 @@ const useStyles = makeStyles({
width: drawerWidth,
},
drawerContainer: {
overflow: 'auto',
display: 'flex',
flexDirection: 'column',
justifyContent: 'space-between',
height: '100%',
overflow: "auto",
display: "flex",
flexDirection: "column",
justifyContent: "space-between",
height: "100%",
},
});

View file

@ -1,24 +1,24 @@
import RedditIcon from '@material-ui/icons/Reddit';
import GitHubIcon from '@material-ui/icons/GitHub';
import { Box, makeStyles } from '@material-ui/core';
import LinkIconButton from '../icons/LinkIconButton';
import UnfinishedSwapsAlert from '../alert/UnfinishedSwapsAlert';
import FundsLeftInWalletAlert from '../alert/FundsLeftInWalletAlert';
import RpcStatusAlert from '../alert/RpcStatusAlert';
import DiscordIcon from '../icons/DiscordIcon';
import { DISCORD_URL } from '../pages/help/ContactInfoBox';
import MoneroWalletRpcUpdatingAlert from '../alert/MoneroWalletRpcUpdatingAlert';
import RedditIcon from "@material-ui/icons/Reddit";
import GitHubIcon from "@material-ui/icons/GitHub";
import { Box, makeStyles } from "@material-ui/core";
import LinkIconButton from "../icons/LinkIconButton";
import UnfinishedSwapsAlert from "../alert/UnfinishedSwapsAlert";
import FundsLeftInWalletAlert from "../alert/FundsLeftInWalletAlert";
import RpcStatusAlert from "../alert/RpcStatusAlert";
import DiscordIcon from "../icons/DiscordIcon";
import { DISCORD_URL } from "../pages/help/ContactInfoBox";
import MoneroWalletRpcUpdatingAlert from "../alert/MoneroWalletRpcUpdatingAlert";
const useStyles = makeStyles((theme) => ({
outer: {
display: 'flex',
flexDirection: 'column',
display: "flex",
flexDirection: "column",
padding: theme.spacing(1),
gap: theme.spacing(1),
},
linksOuter: {
display: 'flex',
justifyContent: 'space-evenly',
display: "flex",
justifyContent: "space-evenly",
},
}));

View file

@ -1,10 +1,10 @@
import { Box, List } from '@material-ui/core';
import SwapHorizOutlinedIcon from '@material-ui/icons/SwapHorizOutlined';
import HistoryOutlinedIcon from '@material-ui/icons/HistoryOutlined';
import AccountBalanceWalletIcon from '@material-ui/icons/AccountBalanceWallet';
import HelpOutlineIcon from '@material-ui/icons/HelpOutline';
import RouteListItemIconButton from './RouteListItemIconButton';
import UnfinishedSwapsBadge from './UnfinishedSwapsCountBadge';
import { Box, List } from "@material-ui/core";
import SwapHorizOutlinedIcon from "@material-ui/icons/SwapHorizOutlined";
import HistoryOutlinedIcon from "@material-ui/icons/HistoryOutlined";
import AccountBalanceWalletIcon from "@material-ui/icons/AccountBalanceWallet";
import HelpOutlineIcon from "@material-ui/icons/HelpOutline";
import RouteListItemIconButton from "./RouteListItemIconButton";
import UnfinishedSwapsBadge from "./UnfinishedSwapsCountBadge";
export default function NavigationHeader() {
return (

View file

@ -1,6 +1,6 @@
import { ReactNode } from 'react';
import { useNavigate } from 'react-router-dom';
import { ListItem, ListItemIcon, ListItemText } from '@material-ui/core';
import { ReactNode } from "react";
import { useNavigate } from "react-router-dom";
import { ListItem, ListItemIcon, ListItemText } from "@material-ui/core";
export default function RouteListItemIconButton({
name,

View file

@ -1,5 +1,5 @@
import { Badge } from '@material-ui/core';
import { useResumeableSwapsCount } from 'store/hooks';
import { Badge } from "@material-ui/core";
import { useResumeableSwapsCount } from "store/hooks";
export default function UnfinishedSwapsBadge({
children,

View file

@ -1,7 +1,7 @@
import { useState } from 'react';
import { Box, IconButton, TextField } from '@material-ui/core';
import SearchIcon from '@material-ui/icons/Search';
import CloseIcon from '@material-ui/icons/Close';
import { useState } from "react";
import { Box, IconButton, TextField } from "@material-ui/core";
import SearchIcon from "@material-ui/icons/Search";
import CloseIcon from "@material-ui/icons/Close";
export function ExpandableSearchBox({
query,
@ -13,8 +13,8 @@ export function ExpandableSearchBox({
const [expanded, setExpanded] = useState(false);
return (
<Box style={{ display: 'flex', justifyContent: 'center' }}>
<Box style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
<Box style={{ display: "flex", justifyContent: "center" }}>
<Box style={{ display: "flex", alignItems: "center", gap: "0.5rem" }}>
{expanded ? (
<>
<TextField
@ -26,7 +26,7 @@ export function ExpandableSearchBox({
<IconButton
onClick={() => {
setExpanded(false);
setQuery('');
setQuery("");
}}
size="small"
>

View file

@ -1,4 +1,4 @@
import humanizeDuration from 'humanize-duration';
import humanizeDuration from "humanize-duration";
const AVG_BLOCK_TIME_MS = 10 * 60 * 1000;
@ -10,7 +10,7 @@ export default function HumanizedBitcoinBlockDuration({
return (
<>
{`${humanizeDuration(blocks * AVG_BLOCK_TIME_MS, {
conjunction: ' and ',
conjunction: " and ",
})} (${blocks} blocks)`}
</>
);

View file

@ -1,8 +1,8 @@
import TreeView from '@material-ui/lab/TreeView';
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
import ChevronRightIcon from '@material-ui/icons/ChevronRight';
import TreeItem from '@material-ui/lab/TreeItem';
import ScrollablePaperTextBox from './ScrollablePaperTextBox';
import TreeView from "@material-ui/lab/TreeView";
import ExpandMoreIcon from "@material-ui/icons/ExpandMore";
import ChevronRightIcon from "@material-ui/icons/ChevronRight";
import TreeItem from "@material-ui/lab/TreeItem";
import ScrollablePaperTextBox from "./ScrollablePaperTextBox";
interface JsonTreeViewProps {
data: any;
@ -13,7 +13,7 @@ export default function JsonTreeView({ data, label }: JsonTreeViewProps) {
const renderTree = (nodes: any, parentId: string) => {
return Object.keys(nodes).map((key, _) => {
const nodeId = `${parentId}.${key}`;
if (typeof nodes[key] === 'object' && nodes[key] !== null) {
if (typeof nodes[key] === "object" && nodes[key] !== null) {
return (
<TreeItem nodeId={nodeId} label={key} key={nodeId}>
{renderTree(nodes[key], nodeId)}
@ -38,10 +38,10 @@ export default function JsonTreeView({ data, label }: JsonTreeViewProps) {
<TreeView
defaultCollapseIcon={<ExpandMoreIcon />}
defaultExpandIcon={<ChevronRightIcon />}
defaultExpanded={['root']}
defaultExpanded={["root"]}
>
<TreeItem nodeId="root" label={label}>
{renderTree(data ?? {}, 'root')}
{renderTree(data ?? {}, "root")}
</TreeItem>
</TreeView>,
]}

View file

@ -1,6 +1,6 @@
import React from 'react';
import Button, { ButtonProps } from '@material-ui/core/Button';
import CircularProgress from '@material-ui/core/CircularProgress';
import React from "react";
import Button, { ButtonProps } from "@material-ui/core/Button";
import CircularProgress from "@material-ui/core/CircularProgress";
interface LoadingButtonProps extends ButtonProps {
loading: boolean;

View file

@ -1,47 +1,47 @@
import { Box, Chip, Typography } from '@material-ui/core';
import { useMemo, useState } from 'react';
import { CliLog } from 'models/cliModel';
import { logsToRawString } from 'utils/parseUtils';
import ScrollablePaperTextBox from './ScrollablePaperTextBox';
import { Box, Chip, Typography } from "@material-ui/core";
import { useMemo, useState } from "react";
import { CliLog } from "models/cliModel";
import { logsToRawString } from "utils/parseUtils";
import ScrollablePaperTextBox from "./ScrollablePaperTextBox";
function RenderedCliLog({ log }: { log: CliLog }) {
const { timestamp, level, fields } = log;
const levelColorMap = {
DEBUG: '#1976d2', // Blue
INFO: '#388e3c', // Green
WARN: '#fbc02d', // Yellow
ERROR: '#d32f2f', // Red
TRACE: '#8e24aa', // Purple
DEBUG: "#1976d2", // Blue
INFO: "#388e3c", // Green
WARN: "#fbc02d", // Yellow
ERROR: "#d32f2f", // Red
TRACE: "#8e24aa", // Purple
};
return (
<Box>
<Box
style={{
display: 'flex',
gap: '0.3rem',
alignItems: 'center',
display: "flex",
gap: "0.3rem",
alignItems: "center",
}}
>
<Chip
label={level}
size="small"
style={{ backgroundColor: levelColorMap[level], color: 'white' }}
style={{ backgroundColor: levelColorMap[level], color: "white" }}
/>
<Chip label={timestamp} size="small" variant="outlined" />
<Typography variant="subtitle2">{fields.message}</Typography>
</Box>
<Box
sx={{
paddingLeft: '1rem',
paddingTop: '0.2rem',
display: 'flex',
flexDirection: 'column',
paddingLeft: "1rem",
paddingTop: "0.2rem",
display: "flex",
flexDirection: "column",
}}
>
{Object.entries(fields).map(([key, value]) => {
if (key !== 'message') {
if (key !== "message") {
return (
<Typography variant="caption" key={key}>
{key}: {JSON.stringify(value)}
@ -62,7 +62,7 @@ export default function CliLogsBox({
label: string;
logs: (CliLog | string)[];
}) {
const [searchQuery, setSearchQuery] = useState<string>('');
const [searchQuery, setSearchQuery] = useState<string>("");
const memoizedLogs = useMemo(() => {
if (searchQuery.length === 0) {
@ -80,7 +80,7 @@ export default function CliLogsBox({
searchQuery={searchQuery}
setSearchQuery={setSearchQuery}
rows={memoizedLogs.map((log) =>
typeof log === 'string' ? (
typeof log === "string" ? (
<Typography component="pre">{log}</Typography>
) : (
<RenderedCliLog log={log} key={JSON.stringify(log)} />

View file

@ -1,12 +1,12 @@
import { Box, Divider, IconButton, Paper, Typography } from '@material-ui/core';
import { ReactNode, useRef } from 'react';
import KeyboardArrowDownIcon from '@material-ui/icons/KeyboardArrowDown';
import KeyboardArrowUpIcon from '@material-ui/icons/KeyboardArrowUp';
import { VList, VListHandle } from 'virtua';
import FileCopyOutlinedIcon from '@material-ui/icons/FileCopyOutlined';
import { ExpandableSearchBox } from './ExpandableSearchBox';
import { Box, Divider, IconButton, Paper, Typography } from "@material-ui/core";
import { ReactNode, useRef } from "react";
import KeyboardArrowDownIcon from "@material-ui/icons/KeyboardArrowDown";
import KeyboardArrowUpIcon from "@material-ui/icons/KeyboardArrowUp";
import { VList, VListHandle } from "virtua";
import FileCopyOutlinedIcon from "@material-ui/icons/FileCopyOutlined";
import { ExpandableSearchBox } from "./ExpandableSearchBox";
const MIN_HEIGHT = '10rem';
const MIN_HEIGHT = "10rem";
export default function ScrollablePaperTextBox({
rows,
@ -41,31 +41,31 @@ export default function ScrollablePaperTextBox({
<Paper
variant="outlined"
style={{
display: 'flex',
flexDirection: 'column',
gap: '0.5rem',
padding: '0.5rem',
width: '100%',
display: "flex",
flexDirection: "column",
gap: "0.5rem",
padding: "0.5rem",
width: "100%",
}}
>
<Typography>{title}</Typography>
<Divider />
<Box
style={{
overflow: 'auto',
whiteSpace: 'nowrap',
overflow: "auto",
whiteSpace: "nowrap",
maxHeight: minHeight,
minHeight,
display: 'flex',
flexDirection: 'column',
gap: '0.5rem',
display: "flex",
flexDirection: "column",
gap: "0.5rem",
}}
>
<VList ref={virtuaEl} style={{ height: MIN_HEIGHT, width: '100%' }}>
<VList ref={virtuaEl} style={{ height: MIN_HEIGHT, width: "100%" }}>
{rows}
</VList>
</Box>
<Box style={{ display: 'flex', gap: '0.5rem' }}>
<Box style={{ display: "flex", gap: "0.5rem" }}>
<IconButton onClick={onCopy} size="small">
<FileCopyOutlinedIcon />
</IconButton>

View file

@ -1,17 +1,17 @@
import { Box, Button, makeStyles, Typography } from '@material-ui/core';
import InfoBox from '../../modal/swap/InfoBox';
import { Box, Button, makeStyles, Typography } from "@material-ui/core";
import InfoBox from "../../modal/swap/InfoBox";
const useStyles = makeStyles((theme) => ({
spacedBox: {
display: 'flex',
display: "flex",
gap: theme.spacing(1),
},
}));
const GITHUB_ISSUE_URL =
'https://github.com/UnstoppableSwap/unstoppableswap-gui/issues/new/choose';
const MATRIX_ROOM_URL = 'https://matrix.to/#/#unstoppableswap:matrix.org';
export const DISCORD_URL = 'https://discord.gg/APJ6rJmq';
"https://github.com/UnstoppableSwap/unstoppableswap-gui/issues/new/choose";
const MATRIX_ROOM_URL = "https://matrix.to/#/#unstoppableswap:matrix.org";
export const DISCORD_URL = "https://discord.gg/APJ6rJmq";
export default function ContactInfoBox() {
const classes = useStyles();

View file

@ -1,9 +1,9 @@
import { Typography } from '@material-ui/core';
import DepositAddressInfoBox from '../../modal/swap/DepositAddressInfoBox';
import MoneroIcon from '../../icons/MoneroIcon';
import { Typography } from "@material-ui/core";
import DepositAddressInfoBox from "../../modal/swap/DepositAddressInfoBox";
import MoneroIcon from "../../icons/MoneroIcon";
const XMR_DONATE_ADDRESS =
'87jS4C7ngk9EHdqFFuxGFgg8AyH63dRUoULshWDybFJaP75UA89qsutG5B1L1QTc4w228nsqsv8EjhL7bz8fB3611Mh98mg';
"87jS4C7ngk9EHdqFFuxGFgg8AyH63dRUoULshWDybFJaP75UA89qsutG5B1L1QTc4w228nsqsv8EjhL7bz8fB3611Mh98mg";
export default function DonateInfoBox() {
return (

View file

@ -1,7 +1,7 @@
import { Button, Typography } from '@material-ui/core';
import { useState } from 'react';
import InfoBox from '../../modal/swap/InfoBox';
import FeedbackDialog from '../../modal/feedback/FeedbackDialog';
import { Button, Typography } from "@material-ui/core";
import { useState } from "react";
import InfoBox from "../../modal/swap/InfoBox";
import FeedbackDialog from "../../modal/feedback/FeedbackDialog";
export default function FeedbackInfoBox() {
const [showDialog, setShowDialog] = useState(false);

View file

@ -1,15 +1,15 @@
import { Box, makeStyles } from '@material-ui/core';
import ContactInfoBox from './ContactInfoBox';
import FeedbackInfoBox from './FeedbackInfoBox';
import DonateInfoBox from './DonateInfoBox';
import TorInfoBox from './TorInfoBox';
import RpcControlBox from './RpcControlBox';
import { Box, makeStyles } from "@material-ui/core";
import ContactInfoBox from "./ContactInfoBox";
import FeedbackInfoBox from "./FeedbackInfoBox";
import DonateInfoBox from "./DonateInfoBox";
import TorInfoBox from "./TorInfoBox";
import RpcControlBox from "./RpcControlBox";
const useStyles = makeStyles((theme) => ({
outer: {
display: 'flex',
display: "flex",
gap: theme.spacing(2),
flexDirection: 'column',
flexDirection: "column",
},
}));

View file

@ -1,18 +1,18 @@
import { Box, makeStyles } from '@material-ui/core';
import IpcInvokeButton from 'renderer/components/IpcInvokeButton';
import { useAppSelector } from 'store/hooks';
import StopIcon from '@material-ui/icons/Stop';
import PlayArrowIcon from '@material-ui/icons/PlayArrow';
import { RpcProcessStateType } from 'models/rpcModel';
import InfoBox from '../../modal/swap/InfoBox';
import CliLogsBox from '../../other/RenderedCliLog';
import FolderOpenIcon from '@material-ui/icons/FolderOpen';
import { Box, makeStyles } from "@material-ui/core";
import IpcInvokeButton from "renderer/components/IpcInvokeButton";
import { useAppSelector } from "store/hooks";
import StopIcon from "@material-ui/icons/Stop";
import PlayArrowIcon from "@material-ui/icons/PlayArrow";
import { RpcProcessStateType } from "models/rpcModel";
import InfoBox from "../../modal/swap/InfoBox";
import CliLogsBox from "../../other/RenderedCliLog";
import FolderOpenIcon from "@material-ui/icons/FolderOpen";
const useStyles = makeStyles((theme) => ({
actionsOuter: {
display: 'flex',
display: "flex",
gap: theme.spacing(1),
alignItems: 'center',
alignItems: "center",
},
}));

View file

@ -1,14 +1,14 @@
import { Box, makeStyles, Typography } from '@material-ui/core';
import IpcInvokeButton from 'renderer/components/IpcInvokeButton';
import { useAppSelector } from 'store/hooks';
import StopIcon from '@material-ui/icons/Stop';
import PlayArrowIcon from '@material-ui/icons/PlayArrow';
import InfoBox from '../../modal/swap/InfoBox';
import CliLogsBox from '../../other/RenderedCliLog';
import { Box, makeStyles, Typography } from "@material-ui/core";
import IpcInvokeButton from "renderer/components/IpcInvokeButton";
import { useAppSelector } from "store/hooks";
import StopIcon from "@material-ui/icons/Stop";
import PlayArrowIcon from "@material-ui/icons/PlayArrow";
import InfoBox from "../../modal/swap/InfoBox";
import CliLogsBox from "../../other/RenderedCliLog";
const useStyles = makeStyles((theme) => ({
actionsOuter: {
display: 'flex',
display: "flex",
gap: theme.spacing(1),
},
}));
@ -24,10 +24,10 @@ export default function TorInfoBox() {
mainContent={
<Box
style={{
width: '100%',
display: 'flex',
flexDirection: 'column',
gap: '8px',
width: "100%",
display: "flex",
flexDirection: "column",
gap: "8px",
}}
>
<Typography variant="subtitle2">
@ -37,7 +37,7 @@ export default function TorInfoBox() {
below. If Tor is running, all traffic will be routed through it and
the swap provider will not be able to see your IP address.
</Typography>
<CliLogsBox label="Tor Daemon Logs" logs={torStdOut.split('\n')} />
<CliLogsBox label="Tor Daemon Logs" logs={torStdOut.split("\n")} />
</Box>
}
additionalContent={

View file

@ -1,8 +1,8 @@
import { Typography } from '@material-ui/core';
import { useIsSwapRunning } from 'store/hooks';
import HistoryTable from './table/HistoryTable';
import SwapDialog from '../../modal/swap/SwapDialog';
import SwapTxLockAlertsBox from '../../alert/SwapTxLockAlertsBox';
import { Typography } from "@material-ui/core";
import { useIsSwapRunning } from "store/hooks";
import HistoryTable from "./table/HistoryTable";
import SwapDialog from "../../modal/swap/SwapDialog";
import SwapTxLockAlertsBox from "../../alert/SwapTxLockAlertsBox";
export default function HistoryPage() {
const showDialog = useIsSwapRunning();

View file

@ -60,27 +60,15 @@ export default function HistoryRow({ swap }: HistoryRowProps) {
<>
<TableRow>
<TableCell>
<IconButton
size="small"
onClick={() => setExpanded(!expanded)}
>
{expanded ? (
<KeyboardArrowUpIcon />
) : (
<KeyboardArrowDownIcon />
)}
<IconButton size="small" onClick={() => setExpanded(!expanded)}>
{expanded ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />}
</IconButton>
</TableCell>
<TableCell>{swap.swap_id.substring(0, 5)}...</TableCell>
<TableCell>
<AmountTransfer
xmrAmount={xmrAmount}
btcAmount={btcAmount}
/>
</TableCell>
<TableCell>
{getHumanReadableDbStateType(swap.state_name)}
<AmountTransfer xmrAmount={xmrAmount} btcAmount={btcAmount} />
</TableCell>
<TableCell>{getHumanReadableDbStateType(swap.state_name)}</TableCell>
<TableCell>
<HistoryRowActions swap={swap} />
</TableCell>

View file

@ -87,9 +87,7 @@ export default function HistoryRowExpanded({
<TableRow>
<TableCell>Exchange Rate</TableCell>
<TableCell>
<MoneroBitcoinExchangeRate
rate={exchangeRate}
/>
<MoneroBitcoinExchangeRate rate={exchangeRate} />
</TableCell>
</TableRow>
<TableRow>
@ -108,10 +106,7 @@ export default function HistoryRowExpanded({
<TableCell>Bitcoin lock transaction</TableCell>
<TableCell>
<Link
href={getBitcoinTxExplorerUrl(
swap.tx_lock_id,
isTestnet(),
)}
href={getBitcoinTxExplorerUrl(swap.tx_lock_id, isTestnet())}
target="_blank"
>
{swap.tx_lock_id}
@ -127,11 +122,7 @@ export default function HistoryRowExpanded({
variant="outlined"
size="small"
/>
<SwapCancelRefundButton
swap={swap}
variant="contained"
size="small"
/>
<SwapCancelRefundButton swap={swap} variant="contained" size="small" />
<SwapMoneroRecoveryButton
swap={swap}
variant="contained"

View file

@ -1,15 +1,15 @@
import { ButtonProps } from '@material-ui/core/Button/Button';
import { ButtonProps } from "@material-ui/core/Button/Button";
import {
Button,
Dialog,
DialogActions,
DialogContent,
DialogTitle,
} from '@material-ui/core';
import { useState } from 'react';
import { CliLog } from 'models/cliModel';
import IpcInvokeButton from '../../../IpcInvokeButton';
import CliLogsBox from '../../../other/RenderedCliLog';
} from "@material-ui/core";
import { useState } from "react";
import { CliLog } from "models/cliModel";
import IpcInvokeButton from "../../../IpcInvokeButton";
import CliLogsBox from "../../../other/RenderedCliLog";
export default function SwapLogFileOpenButton({
swapId,

View file

@ -37,17 +37,16 @@ function MoneroRecoveryKeysDialog({ swap }: { swap: GetSwapInfoResponse }) {
/>
<DialogContent>
<DialogContentText>
You can use the keys below to manually redeem the Monero
funds from the multi-signature wallet.
You can use the keys below to manually redeem the Monero funds from
the multi-signature wallet.
<ul>
<li>
This is useful if the swap daemon fails to redeem
the funds itself
This is useful if the swap daemon fails to redeem the funds itself
</li>
<li>
If you have come this far, there is no risk of
losing funds. You are the only one with access to
these keys and can use them to access your funds
If you have come this far, there is no risk of losing funds. You
are the only one with access to these keys and can use them to
access your funds
</li>
<li>
View{" "}
@ -58,8 +57,8 @@ function MoneroRecoveryKeysDialog({ swap }: { swap: GetSwapInfoResponse }) {
>
this guide
</Link>{" "}
for a detailed description on how to import the keys
and spend the funds.
for a detailed description on how to import the keys and spend the
funds.
</li>
</ul>
</DialogContentText>

View file

@ -1,7 +1,7 @@
import { Box } from '@material-ui/core';
import { Alert, AlertTitle } from '@material-ui/lab';
import { removeAlert } from 'store/features/alertsSlice';
import { useAppDispatch, useAppSelector } from 'store/hooks';
import { Box } from "@material-ui/core";
import { Alert, AlertTitle } from "@material-ui/lab";
import { removeAlert } from "store/features/alertsSlice";
import { useAppDispatch, useAppSelector } from "store/hooks";
export default function ApiAlertsBox() {
const alerts = useAppSelector((state) => state.alerts.alerts);
@ -14,7 +14,7 @@ export default function ApiAlertsBox() {
if (alerts.length === 0) return null;
return (
<Box style={{ display: 'flex', justifyContent: 'center', gap: '1rem' }}>
<Box style={{ display: "flex", justifyContent: "center", gap: "1rem" }}>
{alerts.map((alert) => (
<Alert
variant="filled"

View file

@ -1,13 +1,13 @@
import { Box, makeStyles } from '@material-ui/core';
import SwapWidget from './SwapWidget';
import ApiAlertsBox from './ApiAlertsBox';
import { Box, makeStyles } from "@material-ui/core";
import SwapWidget from "./SwapWidget";
import ApiAlertsBox from "./ApiAlertsBox";
const useStyles = makeStyles((theme) => ({
outer: {
display: 'flex',
width: '100%',
flexDirection: 'column',
alignItems: 'center',
display: "flex",
width: "100%",
flexDirection: "column",
alignItems: "center",
paddingBottom: theme.spacing(1),
gap: theme.spacing(1),
},

View file

@ -1,4 +1,4 @@
import { ChangeEvent, useEffect, useState } from 'react';
import { ChangeEvent, useEffect, useState } from "react";
import {
makeStyles,
Box,
@ -7,21 +7,21 @@ import {
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';
} 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';
} 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;
@ -32,9 +32,9 @@ function isRegistryDown(reconnectionAttempts: number): boolean {
const useStyles = makeStyles((theme) => ({
inner: {
width: 'min(480px, 100%)',
minHeight: '150px',
display: 'grid',
width: "min(480px, 100%)",
minHeight: "150px",
display: "grid",
padding: theme.spacing(1),
gridGap: theme.spacing(1),
},
@ -48,19 +48,19 @@ const useStyles = makeStyles((theme) => ({
padding: theme.spacing(1),
},
swapIconOuter: {
display: 'flex',
justifyContent: 'center',
display: "flex",
justifyContent: "center",
},
swapIcon: {
marginRight: theme.spacing(1),
},
noProvidersAlertOuter: {
display: 'flex',
flexDirection: 'column',
display: "flex",
flexDirection: "column",
gap: theme.spacing(1),
},
noProvidersAlertButtonsOuter: {
display: 'flex',
display: "flex",
gap: theme.spacing(1),
},
}));
@ -111,7 +111,7 @@ function HasProviderSwapWidget({
function getBtcFieldError(): string | null {
const parsedBtcAmount = Number(btcFieldValue);
if (Number.isNaN(parsedBtcAmount)) {
return 'This is not a valid number';
return "This is not a valid number";
}
if (parsedBtcAmount < satsToBtc(selectedProvider.minSwapAmount)) {
return `The minimum swap amount is ${satsToBtc(

View file

@ -1,11 +1,11 @@
import { Box, makeStyles, Typography } from '@material-ui/core';
import { Alert } from '@material-ui/lab';
import WithdrawWidget from './WithdrawWidget';
import { Box, makeStyles, Typography } from "@material-ui/core";
import { Alert } from "@material-ui/lab";
import WithdrawWidget from "./WithdrawWidget";
const useStyles = makeStyles((theme) => ({
outer: {
display: 'flex',
flexDirection: 'column',
display: "flex",
flexDirection: "column",
gridGap: theme.spacing(0.5),
},
}));

View file

@ -1,18 +1,18 @@
import { Box, Button, makeStyles, Typography } from '@material-ui/core';
import { useState } from 'react';
import SendIcon from '@material-ui/icons/Send';
import { useAppSelector, useIsRpcEndpointBusy } from 'store/hooks';
import { RpcMethod } from 'models/rpcModel';
import BitcoinIcon from '../../icons/BitcoinIcon';
import WithdrawDialog from '../../modal/wallet/WithdrawDialog';
import WalletRefreshButton from './WalletRefreshButton';
import InfoBox from '../../modal/swap/InfoBox';
import { SatsAmount } from 'renderer/components/other/Units';
import { Box, Button, makeStyles, Typography } from "@material-ui/core";
import { useState } from "react";
import SendIcon from "@material-ui/icons/Send";
import { useAppSelector, useIsRpcEndpointBusy } from "store/hooks";
import { RpcMethod } from "models/rpcModel";
import BitcoinIcon from "../../icons/BitcoinIcon";
import WithdrawDialog from "../../modal/wallet/WithdrawDialog";
import WalletRefreshButton from "./WalletRefreshButton";
import InfoBox from "../../modal/swap/InfoBox";
import { SatsAmount } from "renderer/components/other/Units";
const useStyles = makeStyles((theme) => ({
title: {
alignItems: 'center',
display: 'flex',
alignItems: "center",
display: "flex",
gap: theme.spacing(0.5),
},
}));

View file

@ -3,14 +3,14 @@ import {
SnackbarKey,
SnackbarProvider,
useSnackbar,
} from 'notistack';
import { IconButton, styled } from '@material-ui/core';
import { Close } from '@material-ui/icons';
import { ReactNode } from 'react';
} from "notistack";
import { IconButton, styled } from "@material-ui/core";
import { Close } from "@material-ui/icons";
import { ReactNode } from "react";
const StyledMaterialDesignContent = styled(MaterialDesignContent)(() => ({
'&.notistack-MuiContent': {
maxWidth: '50vw',
"&.notistack-MuiContent": {
maxWidth: "50vw",
},
}));

View file

@ -1,18 +1,18 @@
import { render } from 'react-dom';
import { Provider } from 'react-redux';
import { store } from './store/storeRenderer';
import { setRegistryProviders } from 'store/features/providersSlice';
import { setAlerts } from 'store/features/alertsSlice';
import { setXmrPrice, setBtcPrice } from 'store/features/ratesSlice';
import { render } from "react-dom";
import { Provider } from "react-redux";
import { store } from "./store/storeRenderer";
import { setRegistryProviders } from "store/features/providersSlice";
import { setAlerts } from "store/features/alertsSlice";
import { setXmrPrice, setBtcPrice } from "store/features/ratesSlice";
import {
fetchAlertsViaHttp,
fetchBtcPrice,
fetchProvidersViaHttp,
fetchXmrPrice,
} from './api';
import logger from '../utils/logger';
import App from './components/App';
import { checkBitcoinBalance, getRawSwapInfos } from './rpc';
} from "./api";
import logger from "../utils/logger";
import App from "./components/App";
import { checkBitcoinBalance, getRawSwapInfos } from "./rpc";
setTimeout(() => {
checkBitcoinBalance();
@ -23,7 +23,7 @@ render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root'),
document.getElementById("root"),
);
async function fetchInitialData() {
@ -33,30 +33,30 @@ async function fetchInitialData() {
logger.info(
{ providerList },
'Fetched providers via UnstoppableSwap HTTP API',
"Fetched providers via UnstoppableSwap HTTP API",
);
} catch (e) {
logger.error(e, 'Failed to fetch providers via UnstoppableSwap HTTP API');
logger.error(e, "Failed to fetch providers via UnstoppableSwap HTTP API");
}
try {
const alerts = await fetchAlertsViaHttp();
store.dispatch(setAlerts(alerts));
logger.info({ alerts }, 'Fetched alerts via UnstoppableSwap HTTP API');
logger.info({ alerts }, "Fetched alerts via UnstoppableSwap HTTP API");
} catch (e) {
logger.error(e, 'Failed to fetch alerts via UnstoppableSwap HTTP API');
logger.error(e, "Failed to fetch alerts via UnstoppableSwap HTTP API");
}
try {
const xmrPrice = await fetchXmrPrice();
store.dispatch(setXmrPrice(xmrPrice));
logger.info({ xmrPrice }, 'Fetched XMR price');
logger.info({ xmrPrice }, "Fetched XMR price");
const btcPrice = await fetchBtcPrice();
store.dispatch(setBtcPrice(btcPrice));
logger.info({ btcPrice }, 'Fetched BTC price');
logger.info({ btcPrice }, "Fetched BTC price");
} catch (e) {
logger.error(e, 'Error retrieving fiat prices');
logger.error(e, "Error retrieving fiat prices");
}
}

View file

@ -1,5 +1,5 @@
import { configureStore } from '@reduxjs/toolkit';
import { reducers } from 'store/combinedReducer';
import { configureStore } from "@reduxjs/toolkit";
import { reducers } from "store/combinedReducer";
export const store = configureStore({
reducer: reducers,

View file

@ -1,9 +1,9 @@
import swapReducer from './features/swapSlice';
import providersSlice from './features/providersSlice';
import torSlice from './features/torSlice';
import rpcSlice from './features/rpcSlice';
import alertsSlice from './features/alertsSlice';
import ratesSlice from './features/ratesSlice';
import swapReducer from "./features/swapSlice";
import providersSlice from "./features/providersSlice";
import torSlice from "./features/torSlice";
import rpcSlice from "./features/rpcSlice";
import alertsSlice from "./features/alertsSlice";
import ratesSlice from "./features/ratesSlice";
export const reducers = {
swap: swapReducer,

View file

@ -1,5 +1,5 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import { Alert } from 'models/apiModel';
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { Alert } from "models/apiModel";
export interface AlertsSlice {
alerts: Alert[];
@ -10,7 +10,7 @@ const initialState: AlertsSlice = {
};
const alertsSlice = createSlice({
name: 'alerts',
name: "alerts",
initialState,
reducers: {
setAlerts(slice, action: PayloadAction<Alert[]>) {

View file

@ -1,8 +1,8 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import { ExtendedProviderStatus, ProviderStatus } from 'models/apiModel';
import { sortProviderList } from 'utils/sortUtils';
import { isProviderCompatible } from 'utils/multiAddrUtils';
import { getStubTestnetProvider } from 'store/config';
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { ExtendedProviderStatus, ProviderStatus } from "models/apiModel";
import { sortProviderList } from "utils/sortUtils";
import { isProviderCompatible } from "utils/multiAddrUtils";
import { getStubTestnetProvider } from "store/config";
const stubTestnetProvider = getStubTestnetProvider();
@ -44,7 +44,7 @@ function selectNewSelectedProvider(
}
export const providersSlice = createSlice({
name: 'providers',
name: "providers",
initialState,
reducers: {
discoveredProvidersByRendezvous(

Some files were not shown because too many files have changed in this diff Show more