Skip to content

Commit

Permalink
feat(gui): Display timelock status using a timeline (#153)
Browse files Browse the repository at this point in the history
  • Loading branch information
binarybaron authored Nov 14, 2024
1 parent 3e79bb3 commit 4cf5cf7
Show file tree
Hide file tree
Showing 22 changed files with 499 additions and 343 deletions.
2 changes: 1 addition & 1 deletion src-gui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"@material-ui/core": "^4.12.4",
"@material-ui/icons": "^4.11.3",
"@material-ui/lab": "^4.0.0-alpha.61",
"@reduxjs/toolkit": "^2.2.6",
"@reduxjs/toolkit": "^2.3.0",
"@tauri-apps/api": "^2.0.0",
"@tauri-apps/plugin-cli": "^2.0.0",
"@tauri-apps/plugin-clipboard-manager": "^2.0.0",
Expand Down
54 changes: 53 additions & 1 deletion src-gui/src/models/tauriModelExt.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { exhaustiveGuard } from "utils/typescriptUtils";
import {
ExpiredTimelocks,
GetSwapInfoResponse,
Expand Down Expand Up @@ -30,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;
Expand All @@ -39,6 +60,22 @@ export type TimelockNone = Extract<ExpiredTimelocks, { type: "None" }>;
export type TimelockCancel = Extract<ExpiredTimelocks, { type: "Cancel" }>;
export type TimelockPunish = Extract<ExpiredTimelocks, { type: "Punish" }>;

// This function returns the absolute block number of the timelock relative to the block the tx_lock was included in
export function getAbsoluteBlock(timelock: ExpiredTimelocks, cancelTimelock: number, punishTimelock: number): number {
if (timelock.type === "None") {
return cancelTimelock - timelock.content.blocks_left;
}
if (timelock.type === "Cancel") {
return cancelTimelock + punishTimelock - timelock.content.blocks_left;
}
if (timelock.type === "Punish") {
return cancelTimelock + punishTimelock;
}

// We match all cases
return exhaustiveGuard(timelock);
}

export type BobStateNameRunningSwap = Exclude<
BobStateName,
| BobStateName.Started
Expand All @@ -50,7 +87,11 @@ export type BobStateNameRunningSwap = Exclude<
>;

export type GetSwapInfoResponseExtRunningSwap = GetSwapInfoResponseExt & {
stateName: BobStateNameRunningSwap;
state_name: BobStateNameRunningSwap;
};

export type GetSwapInfoResponseExtWithTimelock = GetSwapInfoResponseExt & {
timelock: ExpiredTimelocks;
};

export function isBobStateNameRunningSwap(
Expand Down Expand Up @@ -157,3 +198,14 @@ export function isGetSwapInfoResponseRunningSwap(
): response is GetSwapInfoResponseExtRunningSwap {
return isBobStateNameRunningSwap(response.state_name);
}

/**
* Type guard for GetSwapInfoResponseExt to ensure timelock is not null
* @param response The swap info response to check
* @returns True if the timelock exists, false otherwise
*/
export function isGetSwapInfoResponseWithTimelock(
response: GetSwapInfoResponseExt
): response is GetSwapInfoResponseExtWithTimelock {
return response.timelock !== null;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,31 @@ import { SatsAmount } from "../other/Units";
import WalletRefreshButton from "../pages/wallet/WalletRefreshButton";

const useStyles = makeStyles((theme) => ({
outer: {
paddingBottom: theme.spacing(1),
},
outer: {
paddingBottom: theme.spacing(1),
},
}));

export default function RemainingFundsWillBeUsedAlert() {
const classes = useStyles();
const balance = useAppSelector((s) => s.rpc.state.balance);
const classes = useStyles();
const balance = useAppSelector((s) => s.rpc.state.balance);

if (balance == null || balance <= 0) {
return <></>;
}
if (balance == null || balance <= 0) {
return <></>;
}

return (
<Box className={classes.outer}>
<Alert
severity="warning"
action={<WalletRefreshButton />}
variant="filled"
>
The remaining funds of <SatsAmount amount={balance} /> in the wallet
will be used for the next swap. If the remaining funds exceed the
minimum swap amount of the provider, a swap will be initiated
instantaneously.
</Alert>
</Box>
);
return (
<Box className={classes.outer}>
<Alert
severity="warning"
action={<WalletRefreshButton />}
variant="filled"
>
The remaining funds of <SatsAmount amount={balance} /> in the wallet
will be used for the next swap. If the remaining funds exceed the
minimum swap amount of the provider, a swap will be initiated
instantaneously.
</Alert>
</Box>
);
}
100 changes: 0 additions & 100 deletions src-gui/src/renderer/components/alert/SwapMightBeCancelledAlert.tsx

This file was deleted.

Loading

0 comments on commit 4cf5cf7

Please sign in to comment.