mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2025-11-24 18:03:08 -05:00
feat(protocol, wallet): Reveal enc sig fast (#357)
* feat(asb, cli): Add safety margin to chosen Bitcoin fee for pre-signed transactions * feat(gui): Add Context init overlay * feat(protocol): Reveal enc sig fast (before full 10 confirmations) * feat(wallet): Use mempool.space as a secondary fee estimation source * log libp2p crates * revert useless stuff * remove unused elements in state machine * remove redundant diff * minimize diff * dont make xmr_lock_tx_target_confirmations optional * pass target conf in listener callback for monero txs * refactor * refactor * nitpicks * feat: add migration file for xmr field in state3, state4, state5 and state6 * revert .gitignore * add monero_double_spend_safe_confirmations to env.rs * change durations in SwapStateStepper.tsx * remove unused helper functions * use env_config.monero_double_spend_safe_confirmations in state machine * refactor * Update src-gui/src/renderer/components/modal/swap/pages/in_progress/WaitingForXmrConfirmationsBeforeRedeemPage.tsx Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * fix label for retry op --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
This commit is contained in:
parent
cc4069ebad
commit
9a04bd5682
22 changed files with 427 additions and 63 deletions
|
|
@ -239,7 +239,7 @@ export default function SwapStatusAlert({
|
|||
swap: GetSwapInfoResponseExt;
|
||||
isRunning: boolean;
|
||||
onlyShowIfUnusualAmountOfTimeHasPassed?: boolean;
|
||||
}): JSX.Element | null {
|
||||
}) {
|
||||
// If the swap is completed, we do not need to display anything
|
||||
if (!isGetSwapInfoResponseRunningSwap(swap)) {
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -83,7 +83,8 @@ function getActiveStep(state: SwapState | null): PathStep | null {
|
|||
|
||||
// Step 3: Waiting for XMR redemption
|
||||
// Bitcoin has been redeemed by Alice, now waiting for us to redeem Monero
|
||||
case "BtcRedeemed":
|
||||
case "WaitingForXmrConfirmationsBeforeRedeem":
|
||||
case "RedeemingMonero":
|
||||
return [PathType.HAPPY_PATH, 3, isReleased];
|
||||
|
||||
// Step 4: Swap completed successfully
|
||||
|
|
@ -162,9 +163,9 @@ function SwapStepper({
|
|||
|
||||
const HAPPY_PATH_STEP_LABELS = [
|
||||
{ label: "Locking your BTC", duration: "~12min" },
|
||||
{ label: "They lock their XMR", duration: "~18min" },
|
||||
{ label: "They lock their XMR", duration: "~10min" },
|
||||
{ label: "They redeem the BTC", duration: "~2min" },
|
||||
{ label: "Redeeming your XMR", duration: "~2min" },
|
||||
{ label: "Redeeming your XMR", duration: "~10min" },
|
||||
];
|
||||
|
||||
const UNHAPPY_PATH_STEP_LABELS = [
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ export type TransactionInfoBoxProps = {
|
|||
explorerUrlCreator: ((txId: string) => string) | null;
|
||||
additionalContent: ReactNode;
|
||||
loading: boolean;
|
||||
icon: JSX.Element;
|
||||
icon: ReactNode;
|
||||
};
|
||||
|
||||
export default function TransactionInfoBox({
|
||||
|
|
|
|||
|
|
@ -12,11 +12,12 @@ import XmrRedeemInMempoolPage from "./done/XmrRedeemInMempoolPage";
|
|||
import ProcessExitedPage from "./exited/ProcessExitedPage";
|
||||
import BitcoinCancelledPage from "./in_progress/BitcoinCancelledPage";
|
||||
import BitcoinLockTxInMempoolPage from "./in_progress/BitcoinLockTxInMempoolPage";
|
||||
import BitcoinRedeemedPage from "./in_progress/BitcoinRedeemedPage";
|
||||
import RedeemingMoneroPage from "./in_progress/RedeemingMoneroPage";
|
||||
import CancelTimelockExpiredPage from "./in_progress/CancelTimelockExpiredPage";
|
||||
import EncryptedSignatureSentPage from "./in_progress/EncryptedSignatureSentPage";
|
||||
import ReceivedQuotePage from "./in_progress/ReceivedQuotePage";
|
||||
import SwapSetupInflightPage from "./in_progress/SwapSetupInflightPage";
|
||||
import WaitingForXmrConfirmationsBeforeRedeemPage from "./in_progress/WaitingForXmrConfirmationsBeforeRedeemPage";
|
||||
import XmrLockedPage from "./in_progress/XmrLockedPage";
|
||||
import XmrLockTxInMempoolPage from "./in_progress/XmrLockInMempoolPage";
|
||||
import InitPage from "./init/InitPage";
|
||||
|
|
@ -62,8 +63,15 @@ export default function SwapStatePage({ state }: { state: SwapState | null }) {
|
|||
return <XmrLockedPage />;
|
||||
case "EncryptedSignatureSent":
|
||||
return <EncryptedSignatureSentPage />;
|
||||
case "BtcRedeemed":
|
||||
return <BitcoinRedeemedPage />;
|
||||
case "RedeemingMonero":
|
||||
return <RedeemingMoneroPage />;
|
||||
case "WaitingForXmrConfirmationsBeforeRedeem":
|
||||
if (state.curr.type === "WaitingForXmrConfirmationsBeforeRedeem") {
|
||||
return (
|
||||
<WaitingForXmrConfirmationsBeforeRedeemPage {...state.curr.content} />
|
||||
);
|
||||
}
|
||||
break;
|
||||
case "XmrRedeemInMempool":
|
||||
if (state.curr.type === "XmrRedeemInMempool") {
|
||||
return <XmrRedeemInMempoolPage {...state.curr.content} />;
|
||||
|
|
|
|||
|
|
@ -1,5 +0,0 @@
|
|||
import CircularProgressWithSubtitle from "../../CircularProgressWithSubtitle";
|
||||
|
||||
export default function BitcoinRedeemedPage() {
|
||||
return <CircularProgressWithSubtitle description="Redeeming your Monero" />;
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
import CircularProgressWithSubtitle from "../../CircularProgressWithSubtitle";
|
||||
|
||||
export default function RedeemingMoneroPage() {
|
||||
return (
|
||||
<CircularProgressWithSubtitle description="Preparing to redeem your Monero" />
|
||||
);
|
||||
}
|
||||
|
|
@ -481,7 +481,8 @@ const MoneroSecondaryContent = ({
|
|||
// Arrow animation styling extracted for reuse
|
||||
const arrowSx = {
|
||||
fontSize: "3rem",
|
||||
color: (theme: any) => theme.palette.primary.main,
|
||||
color: (theme: { palette: { primary: { main: string } } }) =>
|
||||
theme.palette.primary.main,
|
||||
animation: "slideArrow 2s infinite",
|
||||
"@keyframes slideArrow": {
|
||||
"0%": {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
import { Box, DialogContentText } from "@mui/material";
|
||||
import { TauriSwapProgressEventContent } from "models/tauriModelExt";
|
||||
import MoneroTransactionInfoBox from "../../MoneroTransactionInfoBox";
|
||||
|
||||
export default function WaitingForXmrConfirmationsBeforeRedeemPage({
|
||||
xmr_lock_txid,
|
||||
xmr_lock_tx_confirmations,
|
||||
xmr_lock_tx_target_confirmations,
|
||||
}: TauriSwapProgressEventContent<"WaitingForXmrConfirmationsBeforeRedeem">) {
|
||||
return (
|
||||
<Box>
|
||||
<DialogContentText>
|
||||
We are waiting for the Monero lock transaction to receive enough
|
||||
confirmations before we can sweep them to your address.
|
||||
</DialogContentText>
|
||||
|
||||
<MoneroTransactionInfoBox
|
||||
title="Monero Lock Transaction"
|
||||
txId={xmr_lock_txid}
|
||||
additionalContent={
|
||||
additionalContent={
|
||||
`Confirmations: ${xmr_lock_tx_confirmations}/${xmr_lock_tx_target_confirmations}`
|
||||
}
|
||||
}
|
||||
loading
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
|
@ -6,8 +6,9 @@ import MoneroTransactionInfoBox from "../../MoneroTransactionInfoBox";
|
|||
export default function XmrLockTxInMempoolPage({
|
||||
xmr_lock_tx_confirmations,
|
||||
xmr_lock_txid,
|
||||
xmr_lock_tx_target_confirmations,
|
||||
}: TauriSwapProgressEventContent<"XmrLockTxInMempool">) {
|
||||
const additionalContent = `Confirmations: ${formatConfirmations(xmr_lock_tx_confirmations, 10)}`;
|
||||
const additionalContent = `Confirmations: ${formatConfirmations(xmr_lock_tx_confirmations, xmr_lock_tx_target_confirmations)}`;
|
||||
|
||||
return (
|
||||
<Box>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
import React from "react";
|
||||
import { Badge } from "@mui/material";
|
||||
import { useResumeableSwapsCountExcludingPunished } from "store/hooks";
|
||||
|
||||
export default function UnfinishedSwapsBadge({
|
||||
children,
|
||||
}: {
|
||||
children: JSX.Element;
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
const resumableSwapsCount = useResumeableSwapsCountExcludingPunished();
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ function RenderedCliLog({ log }: { log: CliLog }) {
|
|||
};
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Box sx={{ display: "flex", flexDirection: "column" }}>
|
||||
<Box
|
||||
style={{
|
||||
display: "flex",
|
||||
|
|
@ -33,7 +33,6 @@ function RenderedCliLog({ log }: { log: CliLog }) {
|
|||
<Chip label={target.split("::")[0]} size="small" variant="outlined" />
|
||||
)}
|
||||
<Chip label={timestamp} size="small" variant="outlined" />
|
||||
<Typography variant="subtitle2">{fields.message}</Typography>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
|
|
@ -43,6 +42,7 @@ function RenderedCliLog({ log }: { log: CliLog }) {
|
|||
flexDirection: "column",
|
||||
}}
|
||||
>
|
||||
<Typography variant="subtitle2">{fields.message}</Typography>
|
||||
{Object.entries(fields).map(([key, value]) => {
|
||||
if (key !== "message") {
|
||||
return (
|
||||
|
|
@ -62,10 +62,12 @@ export default function CliLogsBox({
|
|||
label,
|
||||
logs,
|
||||
topRightButton = null,
|
||||
autoScroll = false,
|
||||
}: {
|
||||
label: string;
|
||||
logs: (CliLog | string)[];
|
||||
topRightButton?: ReactNode;
|
||||
autoScroll?: boolean;
|
||||
}) {
|
||||
const [searchQuery, setSearchQuery] = useState<string>("");
|
||||
|
||||
|
|
@ -85,6 +87,7 @@ export default function CliLogsBox({
|
|||
searchQuery={searchQuery}
|
||||
setSearchQuery={setSearchQuery}
|
||||
topRightButton={topRightButton}
|
||||
autoScroll={autoScroll}
|
||||
rows={memoizedLogs.map((log) =>
|
||||
typeof log === "string" ? (
|
||||
<Typography key={log} component="pre">
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ export default function ScrollablePaperTextBox({
|
|||
setSearchQuery = null,
|
||||
topRightButton = null,
|
||||
minHeight = MIN_HEIGHT,
|
||||
autoScroll = false,
|
||||
}: {
|
||||
rows: ReactNode[];
|
||||
title: string;
|
||||
|
|
@ -24,6 +25,7 @@ export default function ScrollablePaperTextBox({
|
|||
setSearchQuery?: ((query: string) => void) | null;
|
||||
minHeight?: string;
|
||||
topRightButton?: ReactNode | null;
|
||||
autoScroll?: boolean;
|
||||
}) {
|
||||
const virtuaEl = useRef<VListHandle | null>(null);
|
||||
|
||||
|
|
@ -39,6 +41,12 @@ export default function ScrollablePaperTextBox({
|
|||
virtuaEl.current?.scrollToIndex(0);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (autoScroll) {
|
||||
scrollToBottom();
|
||||
}
|
||||
}, [rows.length, autoScroll]);
|
||||
|
||||
return (
|
||||
<Paper
|
||||
variant="outlined"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue