mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2025-05-02 06:46:06 -04:00
feat(gui): Refund swap in the background (#154)
Swaps will now be refunded as soon as the cancel timelock expires if the GUI is running but the swap dialog is not open.
This commit is contained in:
parent
4cf5cf719a
commit
e46be4a9ff
12 changed files with 210 additions and 27 deletions
|
@ -26,6 +26,7 @@
|
|||
"@tauri-apps/plugin-shell": "^2.0.0",
|
||||
"@tauri-apps/plugin-store": "^2.1.0",
|
||||
"@tauri-apps/plugin-updater": "^2.0.0",
|
||||
"@types/react-redux": "^7.1.34",
|
||||
"humanize-duration": "^3.32.1",
|
||||
"lodash": "^4.17.21",
|
||||
"multiaddr": "^10.0.1",
|
||||
|
@ -36,7 +37,7 @@
|
|||
"react-dom": "^18.2.0",
|
||||
"react-qr-code": "^2.0.15",
|
||||
"react-redux": "^9.1.2",
|
||||
"react-router-dom": "^6.24.1",
|
||||
"react-router-dom": "^6.28.0",
|
||||
"redux-persist": "^6.0.0",
|
||||
"semver": "^7.6.2",
|
||||
"virtua": "^0.33.2"
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
import { BackgroundRefundState } from "models/tauriModel";
|
||||
import { useAppSelector } from "store/hooks";
|
||||
import { LoadingSpinnerAlert } from "./LoadingSpinnerAlert";
|
||||
import { AlertTitle } from "@material-ui/lab";
|
||||
import TruncatedText from "../other/TruncatedText";
|
||||
import { useSnackbar } from "notistack";
|
||||
import { useEffect } from "react";
|
||||
|
||||
export default function BackgroundRefundAlert() {
|
||||
const backgroundRefund = useAppSelector(state => state.rpc.state.backgroundRefund);
|
||||
const notistack = useSnackbar();
|
||||
|
||||
useEffect(() => {
|
||||
// If we failed to refund, show a notification
|
||||
if (backgroundRefund?.state.type === "Failed") {
|
||||
notistack.enqueueSnackbar(
|
||||
<>
|
||||
Our attempt to refund {backgroundRefund.swapId} in the background failed.
|
||||
<br />
|
||||
Error: {backgroundRefund.state.content.error}
|
||||
</>,
|
||||
{ variant: "error", autoHideDuration: 60 * 1000 }
|
||||
);
|
||||
}
|
||||
|
||||
// If we successfully refunded, show a notification as well
|
||||
if (backgroundRefund?.state.type === "Completed") {
|
||||
notistack.enqueueSnackbar(`The swap ${backgroundRefund.swapId} has been refunded in the background.`, { variant: "success", persist: true });
|
||||
}
|
||||
}, [backgroundRefund]);
|
||||
|
||||
if (backgroundRefund?.state.type === "Started") {
|
||||
return <LoadingSpinnerAlert>
|
||||
<AlertTitle>
|
||||
Refund in progress
|
||||
</AlertTitle>
|
||||
The swap <TruncatedText>{backgroundRefund.swapId}</TruncatedText> is being refunded in the background.
|
||||
</LoadingSpinnerAlert>
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
|
@ -1,13 +1,10 @@
|
|||
import { Button, CircularProgress } from "@material-ui/core";
|
||||
import { Alert, AlertProps } from "@material-ui/lab";
|
||||
import { Button } from "@material-ui/core";
|
||||
import { Alert } from "@material-ui/lab";
|
||||
import { TauriContextInitializationProgress } from "models/tauriModel";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useAppSelector } from "store/hooks";
|
||||
import { exhaustiveGuard } from "utils/typescriptUtils";
|
||||
|
||||
function LoadingSpinnerAlert({ ...rest }: AlertProps) {
|
||||
return <Alert icon={<CircularProgress size={22} />} {...rest} />;
|
||||
}
|
||||
import { LoadingSpinnerAlert } from "./LoadingSpinnerAlert";
|
||||
|
||||
export default function DaemonStatusAlert() {
|
||||
const contextStatus = useAppSelector((s) => s.rpc.status);
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
import { CircularProgress } from "@material-ui/core";
|
||||
import { AlertProps, Alert } from "@material-ui/lab";
|
||||
|
||||
export function LoadingSpinnerAlert({ ...rest }: AlertProps) {
|
||||
return <Alert icon={<CircularProgress size={22} />} {...rest} />;
|
||||
}
|
|
@ -8,6 +8,7 @@ import UnfinishedSwapsAlert from "../alert/UnfinishedSwapsAlert";
|
|||
import DiscordIcon from "../icons/DiscordIcon";
|
||||
import LinkIconButton from "../icons/LinkIconButton";
|
||||
import { DISCORD_URL } from "../pages/help/ContactInfoBox";
|
||||
import BackgroundRefundAlert from "../alert/BackgroundRefundAlert";
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
outer: {
|
||||
|
@ -29,6 +30,7 @@ export default function NavigationFooter() {
|
|||
<Box className={classes.outer}>
|
||||
<FundsLeftInWalletAlert />
|
||||
<UnfinishedSwapsAlert />
|
||||
<BackgroundRefundAlert />
|
||||
<DaemonStatusAlert />
|
||||
<MoneroWalletRpcUpdatingAlert />
|
||||
<Box className={classes.linksOuter}>
|
||||
|
|
|
@ -28,10 +28,12 @@ import {
|
|||
CheckElectrumNodeArgs,
|
||||
CheckElectrumNodeResponse,
|
||||
GetMoneroAddressesResponse,
|
||||
TauriBackgroundRefundEvent,
|
||||
} from "models/tauriModel";
|
||||
import {
|
||||
contextStatusEventReceived,
|
||||
receivedCliLog,
|
||||
rpcSetBackgroundRefundState,
|
||||
rpcSetBalance,
|
||||
rpcSetSwapInfo,
|
||||
timelockChangeEventReceived,
|
||||
|
@ -100,6 +102,11 @@ export async function initEventListeners() {
|
|||
console.log('Received timelock change event', event.payload);
|
||||
store.dispatch(timelockChangeEventReceived(event.payload));
|
||||
})
|
||||
|
||||
listen<TauriBackgroundRefundEvent>('background-refund', (event) => {
|
||||
console.log('Received background refund event', event.payload);
|
||||
store.dispatch(rpcSetBackgroundRefundState(event.payload));
|
||||
})
|
||||
}
|
||||
|
||||
async function invoke<ARGS, RESPONSE>(
|
||||
|
|
|
@ -5,6 +5,7 @@ import {
|
|||
GetSwapInfoResponse,
|
||||
TauriContextStatusEvent,
|
||||
TauriTimelockChangeEvent,
|
||||
BackgroundRefundState,
|
||||
} from "models/tauriModel";
|
||||
import { MoneroRecoveryResponse } from "../../models/rpcModel";
|
||||
import { GetSwapInfoResponseExt } from "models/tauriModelExt";
|
||||
|
@ -27,6 +28,10 @@ interface State {
|
|||
// TODO: Reimplement this using Tauri
|
||||
updateState: false;
|
||||
};
|
||||
backgroundRefund: {
|
||||
swapId: string;
|
||||
state: BackgroundRefundState;
|
||||
} | null;
|
||||
}
|
||||
|
||||
export interface RPCSlice {
|
||||
|
@ -46,6 +51,7 @@ const initialState: RPCSlice = {
|
|||
moneroWalletRpc: {
|
||||
updateState: false,
|
||||
},
|
||||
backgroundRefund: null,
|
||||
},
|
||||
logs: [],
|
||||
};
|
||||
|
@ -109,6 +115,12 @@ export const rpcSlice = createSlice({
|
|||
rpcResetMoneroRecoveryKeys(slice) {
|
||||
slice.state.moneroRecovery = null;
|
||||
},
|
||||
rpcSetBackgroundRefundState(slice, action: PayloadAction<{ swap_id: string, state: BackgroundRefundState }>) {
|
||||
slice.state.backgroundRefund = {
|
||||
swapId: action.payload.swap_id,
|
||||
state: action.payload.state,
|
||||
};
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -122,6 +134,7 @@ export const {
|
|||
rpcSetSwapInfo,
|
||||
rpcSetMoneroRecoveryKeys,
|
||||
rpcResetMoneroRecoveryKeys,
|
||||
rpcSetBackgroundRefundState,
|
||||
timelockChangeEventReceived
|
||||
} = rpcSlice.actions;
|
||||
|
||||
|
|
|
@ -192,6 +192,13 @@
|
|||
dependencies:
|
||||
regenerator-runtime "^0.14.0"
|
||||
|
||||
"@babel/runtime@^7.9.2":
|
||||
version "7.26.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.0.tgz#8600c2f595f277c60815256418b85356a65173c1"
|
||||
integrity sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.14.0"
|
||||
|
||||
"@babel/template@^7.24.7":
|
||||
version "7.24.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.7.tgz#02efcee317d0609d2c07117cb70ef8fb17ab7315"
|
||||
|
@ -552,10 +559,10 @@
|
|||
redux-thunk "^3.1.0"
|
||||
reselect "^5.1.0"
|
||||
|
||||
"@remix-run/router@1.17.1":
|
||||
version "1.17.1"
|
||||
resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.17.1.tgz#bf93997beb81863fde042ebd05013a2618471362"
|
||||
integrity sha512-mCOMec4BKd6BRGBZeSnGiIgwsbLGp3yhVqAD8H+PxiRNEHgDpZb8J1TnrSDlg97t0ySKMQJTHCWBCmBpSmkF6Q==
|
||||
"@remix-run/router@1.21.0":
|
||||
version "1.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.21.0.tgz#c65ae4262bdcfe415dbd4f64ec87676e4a56e2b5"
|
||||
integrity sha512-xfSkCAchbdG5PnbrKqFWwia4Bi61nH+wm8wLEqfHDyp7Y3dZzgqS2itV8i4gAq9pC2HsTpwyBC6Ds8VHZ96JlA==
|
||||
|
||||
"@rollup/plugin-virtual@^3.0.2":
|
||||
version "3.0.2"
|
||||
|
@ -971,6 +978,14 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50"
|
||||
integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==
|
||||
|
||||
"@types/hoist-non-react-statics@^3.3.0":
|
||||
version "3.3.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.5.tgz#dab7867ef789d87e2b4b0003c9d65c49cc44a494"
|
||||
integrity sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg==
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
hoist-non-react-statics "^3.3.0"
|
||||
|
||||
"@types/humanize-duration@^3.27.4":
|
||||
version "3.27.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/humanize-duration/-/humanize-duration-3.27.4.tgz#51d6d278213374735440bc3749de920935e9127e"
|
||||
|
@ -1000,6 +1015,16 @@
|
|||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react-redux@^7.1.34":
|
||||
version "7.1.34"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.34.tgz#83613e1957c481521e6776beeac4fd506d11bd0e"
|
||||
integrity sha512-GdFaVjEbYv4Fthm2ZLvj1VSCedV7TqE5y1kNwnjSdBOTXuRSgowux6J8TAct15T3CKBr63UMk+2CO7ilRhyrAQ==
|
||||
dependencies:
|
||||
"@types/hoist-non-react-statics" "^3.3.0"
|
||||
"@types/react" "*"
|
||||
hoist-non-react-statics "^3.3.0"
|
||||
redux "^4.0.0"
|
||||
|
||||
"@types/react-transition-group@^4.2.0":
|
||||
version "4.4.10"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.10.tgz#6ee71127bdab1f18f11ad8fb3322c6da27c327ac"
|
||||
|
@ -2221,7 +2246,7 @@ help-me@^5.0.0:
|
|||
resolved "https://registry.yarnpkg.com/help-me/-/help-me-5.0.0.tgz#b1ebe63b967b74060027c2ac61f9be12d354a6f6"
|
||||
integrity sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==
|
||||
|
||||
hoist-non-react-statics@^3.3.2:
|
||||
hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2:
|
||||
version "3.3.2"
|
||||
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
|
||||
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
|
||||
|
@ -3139,20 +3164,20 @@ react-refresh@^0.14.2:
|
|||
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.2.tgz#3833da01ce32da470f1f936b9d477da5c7028bf9"
|
||||
integrity sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==
|
||||
|
||||
react-router-dom@^6.24.1:
|
||||
version "6.24.1"
|
||||
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.24.1.tgz#b1a22f7d6c5a1bfce30732bd370713f991ab4de4"
|
||||
integrity sha512-U19KtXqooqw967Vw0Qcn5cOvrX5Ejo9ORmOtJMzYWtCT4/WOfFLIZGGsVLxcd9UkBO0mSTZtXqhZBsWlHr7+Sg==
|
||||
react-router-dom@^6.28.0:
|
||||
version "6.28.0"
|
||||
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.28.0.tgz#f73ebb3490e59ac9f299377062ad1d10a9f579e6"
|
||||
integrity sha512-kQ7Unsl5YdyOltsPGl31zOjLrDv+m2VcIEcIHqYYD3Lp0UppLjrzcfJqDJwXxFw3TH/yvapbnUvPlAj7Kx5nbg==
|
||||
dependencies:
|
||||
"@remix-run/router" "1.17.1"
|
||||
react-router "6.24.1"
|
||||
"@remix-run/router" "1.21.0"
|
||||
react-router "6.28.0"
|
||||
|
||||
react-router@6.24.1:
|
||||
version "6.24.1"
|
||||
resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.24.1.tgz#5a3bbba0000afba68d42915456ca4c806f37a7de"
|
||||
integrity sha512-PTXFXGK2pyXpHzVo3rR9H7ip4lSPZZc0bHG5CARmj65fTT6qG7sTngmb6lcYu1gf3y/8KxORoy9yn59pGpCnpg==
|
||||
react-router@6.28.0:
|
||||
version "6.28.0"
|
||||
resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.28.0.tgz#29247c86d7ba901d7e5a13aa79a96723c3e59d0d"
|
||||
integrity sha512-HrYdIFqdrnhDw0PqG/AKjAqEqM7AvxCz0DQ4h2W8k6nqmc5uRBYDag0SBxx9iYz5G8gnuNVLzUe13wl9eAsXXg==
|
||||
dependencies:
|
||||
"@remix-run/router" "1.17.1"
|
||||
"@remix-run/router" "1.21.0"
|
||||
|
||||
react-transition-group@^4.4.0:
|
||||
version "4.4.5"
|
||||
|
@ -3204,6 +3229,13 @@ redux-thunk@^3.1.0:
|
|||
resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-3.1.0.tgz#94aa6e04977c30e14e892eae84978c1af6058ff3"
|
||||
integrity sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==
|
||||
|
||||
redux@^4.0.0:
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/redux/-/redux-4.2.1.tgz#c08f4306826c49b5e9dc901dee0452ea8fce6197"
|
||||
integrity sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.9.2"
|
||||
|
||||
redux@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/redux/-/redux-5.0.1.tgz#97fa26881ce5746500125585d5642c77b6e9447b"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue