Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(gui): Display timelock status using a timeline #153

Merged
merged 23 commits into from
Nov 14, 2024
Merged
Changes from 1 commit
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
make state name human readable
  • Loading branch information
binarybaron committed Nov 14, 2024
commit 589be2d1921edbe386c4fa8bee94f132e8da771e
20 changes: 20 additions & 0 deletions src-gui/src/models/tauriModelExt.ts
Original file line number Diff line number Diff line change
@@ -31,6 +31,26 @@ export enum BobStateName {
SafelyAborted = "safely aborted",
}

export function bobStateNameToHumanReadable(stateName: BobStateName): string {
switch (stateName) {
case BobStateName.Started: return "Started";
case BobStateName.SwapSetupCompleted: return "Setup completed";
case BobStateName.BtcLocked: return "Bitcoin locked";
case BobStateName.XmrLockProofReceived: return "Monero locked";
case BobStateName.XmrLocked: return "Monero locked and fully confirmed";
case BobStateName.EncSigSent: return "Encrypted signature sent";
case BobStateName.BtcRedeemed: return "Bitcoin redeemed";
case BobStateName.CancelTimelockExpired: return "Cancel timelock expired";
case BobStateName.BtcCancelled: return "Bitcoin cancelled";
case BobStateName.BtcRefunded: return "Bitcoin refunded";
case BobStateName.XmrRedeemed: return "Monero redeemed";
case BobStateName.BtcPunished: return "Bitcoin punished";
case BobStateName.SafelyAborted: return "Safely aborted";
default:
return exhaustiveGuard(stateName);
}
}

// TODO: This is a temporary solution until we have a typeshare definition for BobStateName
export type GetSwapInfoResponseExt = GetSwapInfoResponse & {
state_name: BobStateName;
29 changes: 13 additions & 16 deletions src-gui/src/renderer/components/alert/SwapMightBeCancelledAlert.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Box, makeStyles } from "@material-ui/core";
import { Alert, AlertTitle } from "@material-ui/lab";
import { useActiveSwapInfo } from "store/hooks";
import { StateAlert } from "./SwapStatusAlert/SwapStatusAlert";
import SwapStatusAlert, { StateAlert } from "./SwapStatusAlert/SwapStatusAlert";
import { TimelockTimeline } from "./SwapStatusAlert/TimelockTimeline";
import { isGetSwapInfoResponseRunningSwap, isGetSwapInfoResponseWithTimelock } from "models/tauriModelExt";
import { getAbsoluteBlock, isGetSwapInfoResponseRunningSwap, isGetSwapInfoResponseWithTimelock } from "models/tauriModelExt";

const useStyles = makeStyles((theme) => ({
outer: {
@@ -22,29 +22,26 @@ const useStyles = makeStyles((theme) => ({
},
}));

// This is the number of blocks after which we consider the swap to be at risk of being unsuccessful
const BITCOIN_CONFIRMATIONS_WARNING_THRESHOLD = 5;

export default function SwapMightBeCancelledAlert() {
const classes = useStyles();
const swapInfo = useActiveSwapInfo();

// If the swap does not have a timelock, we cannot display the alert
if (!isGetSwapInfoResponseWithTimelock(swapInfo)) {
return <></>;
return null;
}

if(!isGetSwapInfoResponseRunningSwap(swapInfo)) {
return <></>;
// If the swap has not been running for long enough, we do not need to display the alert
// The swap is probably gonna be successful
// No need to spook the user for no reason
if(getAbsoluteBlock(swapInfo.timelock, swapInfo.cancel_timelock, swapInfo.punish_timelock) < BITCOIN_CONFIRMATIONS_WARNING_THRESHOLD) {
return null;
}

return (
<Alert severity="warning" variant="filled" classes={{
message: classes.message,
}}>
<AlertTitle>
The swap has been running for a while
</AlertTitle>
<Box className={classes.box}>
<StateAlert swap={swapInfo} />
<TimelockTimeline swap={swapInfo} />
</Box>
</Alert>
<SwapStatusAlert swap={swapInfo} />
);
}
Original file line number Diff line number Diff line change
@@ -35,7 +35,7 @@ interface TimelineSegment {
alignItems: 'center',
justifyContent: 'center',
bgcolor: segment.bgcolor,
width: `${durationOfSegment ? ((durationOfSegment / totalBlocks) * 90) : 10}%`,
width: `${durationOfSegment ? ((durationOfSegment / totalBlocks) * 85) : 15}%`,
position: 'relative',
}} style={{
opacity: isActive ? 1 : 0.3
@@ -46,7 +46,7 @@ interface TimelineSegment {
top: 0,
left: 0,
height: '100%',
width: `${Math.max(2.5, ((absoluteBlock - segment.startBlock) / durationOfSegment) * 100)}%`,
width: `${Math.max(5, ((absoluteBlock - segment.startBlock) / durationOfSegment) * 100)}%`,
zIndex: 1,
}}>
<LinearProgress
Original file line number Diff line number Diff line change
@@ -8,30 +8,32 @@ export default function BitcoinLockTxInMempoolPage({
btc_lock_txid,
}: TauriSwapProgressEventContent<"BtcLockTxInMempool">) {
return (
<Box style={{
display: "flex",
flexDirection: "column",
gap: "1rem",
}}>
<Box>
<DialogContentText>
The Bitcoin lock transaction has been published. The swap will proceed
once the transaction is confirmed and the swap provider locks their
Monero.
</DialogContentText>
<SwapMightBeCancelledAlert />
<BitcoinTransactionInfoBox
title="Bitcoin Lock Transaction"
txId={btc_lock_txid}
loading
additionalContent={
<>
Most swap providers require one confirmation before locking their
Monero
<br />
Confirmations: {btc_lock_confirmations}
</>
}
/>
<Box style={{
display: "flex",
flexDirection: "column",
gap: "1rem",
}}>
<SwapMightBeCancelledAlert />
<BitcoinTransactionInfoBox
title="Bitcoin Lock Transaction"
txId={btc_lock_txid}
loading
additionalContent={
<>
Most swap providers require one confirmation before locking their
Monero
<br />
Confirmations: {btc_lock_confirmations}
</>
}
/>
</Box>
</Box>
);
}
Original file line number Diff line number Diff line change
@@ -15,6 +15,7 @@ import TruncatedText from "renderer/components/other/TruncatedText";
import { PiconeroAmount, SatsAmount } from "../../../other/Units";
import HistoryRowActions from "./HistoryRowActions";
import HistoryRowExpanded from "./HistoryRowExpanded";
import { bobStateNameToHumanReadable, GetSwapInfoResponseExt } from "models/tauriModelExt";

const useStyles = makeStyles((theme) => ({
amountTransferContainer: {
@@ -42,7 +43,7 @@ function AmountTransfer({
);
}

export default function HistoryRow(swap: GetSwapInfoResponse) {
export default function HistoryRow(swap: GetSwapInfoResponseExt) {
const [expanded, setExpanded] = useState(false);

return (
@@ -62,7 +63,7 @@ export default function HistoryRow(swap: GetSwapInfoResponse) {
btcAmount={swap.btc_amount}
/>
</TableCell>
<TableCell>{swap.state_name.toString()}</TableCell>
<TableCell>{bobStateNameToHumanReadable(swap.state_name)}</TableCell>
<TableCell>
<HistoryRowActions {...swap} />
</TableCell>
Original file line number Diff line number Diff line change
@@ -27,6 +27,11 @@ const useStyles = makeStyles((theme) => ({
padding: theme.spacing(1),
gap: theme.spacing(1),
},
outerAddressBox: {
display: "flex",
flexDirection: "column",
gap: theme.spacing(1),
},
actionsOuter: {
display: "flex",
flexDirection: "row",
@@ -88,7 +93,7 @@ export default function HistoryRowExpanded({
<TableRow>
<TableCell>Provider Address</TableCell>
<TableCell>
<Box>
<Box className={classes.outerAddressBox}>
{swap.seller.addresses.map((addr) => (
<ActionableMonospaceTextBox
key={addr}
@@ -122,16 +127,6 @@ export default function HistoryRowExpanded({
variant="outlined"
size="small"
/>
{/*
// TOOD: reimplement these buttons using Tauri

<SwapCancelRefundButton swap={swap} variant="contained" size="small" />
<SwapMoneroRecoveryButton
swap={swap}
variant="contained"
size="small"
/>
*/}
</Box>
</Box>
);