Skip to content
Merged
Show file tree
Hide file tree
Changes from 56 commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
df6e91d
feat(gui): Implement base structure for new swap ux
b-enedict Jun 10, 2025
9b8ad7c
feat(gui): Implement basic multi step modal
b-enedict Jun 10, 2025
40e6635
feat(gui): Add outline of add choose maker and offer step
b-enedict Jun 10, 2025
ab5bf62
feat(gui): Add receive address selector
b-enedict Jun 12, 2025
0dd7624
refactor(gui): format code
b-enedict Jun 12, 2025
d23ef41
feat(gui): Make Swap Overveiw interactive
b-enedict Jun 12, 2025
4b59c25
feat(gui): Add action to swap amount selector to quickly go to deposi…
b-enedict Jun 12, 2025
f90aa37
progress
binarybaron Jun 20, 2025
53afe30
feat(gui, cli): Request quotes concurrently at all sellers
binarybaron Jun 20, 2025
7e7abcf
refresh offers occasionally, display progress
binarybaron Jun 20, 2025
47dbd1f
progress
binarybaron Jun 20, 2025
d2a5115
feat(gui, cli): Request quotes concurrently at all sellers
binarybaron Jun 20, 2025
28fe1c0
refresh offers occasionally, display progress
binarybaron Jun 20, 2025
38f56da
Merge branch 'feat/concurrent-quotes-swap-init' of https://github.com…
binarybaron Jun 20, 2025
3005e2a
progress, works again
binarybaron Jun 22, 2025
6492849
allow closing dialog without warning if no funds have been locked
binarybaron Jun 22, 2025
bc10da2
progress
binarybaron Jun 22, 2025
a522840
Merge branch 'feat/concurrent-quotes-swap-init' into 385-get-bitcoin-…
b-enedict Jun 23, 2025
7fcae4b
feat(gui): Rewrite Swap Components to have flow directly on swap page
b-enedict Jun 23, 2025
e1e9d2f
Merge branch 'master' into feat/concurrent-quotes-swap-init
binarybaron Jun 23, 2025
54ec5e0
feat: log monero_rpc_pool only at >= INFO level
binarybaron Jun 23, 2025
882a589
Merge branch '385-get-bitcoin-step' into feat/concurrent-quotes-swap-…
b-enedict Jun 24, 2025
ca442a2
Merge branch 'feat/concurrent-quotes-swap-init' of github.com:Unstopp…
b-enedict Jun 24, 2025
f858814
remove full_url, add migration to change scheme of node.monerodevs.or…
binarybaron Jun 24, 2025
e54ee09
feat: send known_quotes with WaitingForBitcoinDeposit Tauri progress …
binarybaron Jun 24, 2025
7308cc8
lock swap lock later
binarybaron Jun 24, 2025
33aedc4
refactor(monero-rpc-pool): Pass around tuple of (scheme, host, port) …
binarybaron Jun 24, 2025
160cfd9
Merge branch 'master' into feat/concurrent-quotes-swap-init
binarybaron Jun 24, 2025
d40b5ac
refactor(gui): Remove modal for swap and adjust few pages for swap pr…
b-enedict Jun 24, 2025
cbf10d8
allow cancel before lock
binarybaron Jun 27, 2025
3b7af49
remove unused code
binarybaron Jun 27, 2025
8531bd0
dynamic layout, chips for amounts
binarybaron Jun 27, 2025
6bfa217
feat(gui): Add breakpoints
b-enedict Jun 27, 2025
3f76058
remove continue button, add select button on each maker box
binarybaron Jun 27, 2025
c753239
Merge branch 'feat/concurrent-quotes-swap-init' of github.com:Unstopp…
b-enedict Jun 27, 2025
4ad0f42
Merge branch 'feat/concurrent-quotes-swap-init' of github.com:Unstopp…
b-enedict Jun 27, 2025
14982b3
add GetCurrentSwapArgs tauri command to only suspend swap if one is a…
binarybaron Jun 27, 2025
d409e9d
feat(gui): Show all known quotes and disable the ones that aren't ava…
b-enedict Jun 27, 2025
4f4650d
Merge branch 'feat/concurrent-quotes-swap-init' of github.com:Unstopp…
b-enedict Jun 27, 2025
b68373b
fix get_current_swap, kill tasks when buy_xmr is cancelled
binarybaron Jun 27, 2025
be4731d
cleanup: remove CleanupGuard
binarybaron Jun 27, 2025
9b03ba5
feat(gui): Add cancel button on every page
b-enedict Jun 27, 2025
6f56fb9
Merge branch 'master' into feat/concurrent-quotes-swap-init
b-enedict Jun 30, 2025
412f87c
refactor(gui): Fix merge issues
b-enedict Jun 30, 2025
ce28e25
refactor(gui): Unify Cancel Button insertion by using a swap base page
b-enedict Jun 30, 2025
4d764a4
refactor(gui): Unify Cancel Button insertion by using a swap base page
b-enedict Jun 30, 2025
43170f8
refactor(gui): Remove deeply nested relative paths
b-enedict Jun 30, 2025
db77e7b
refactor(gui): Made BaseSwapPage obsolete by moving Cancel Button to …
b-enedict Jun 30, 2025
b0995fe
Merge branch 'feat/concurrent-quotes-swap-init' of github.com:Unstopp…
b-enedict Jun 30, 2025
7fbfeb4
refactor(gui): Adjust condition for showing SwapSuspendAlert
b-enedict Jun 30, 2025
5bb0e5b
fix(gui): Fetch previous monero redeem addresses repeatedly
b-enedict Jun 30, 2025
6231071
refactor(gui): Remove QR Code from deposit and choose maker page
b-enedict Jun 30, 2025
d72ebc3
refactor(gui): Don't display dialog on History page
binarybaron Jun 30, 2025
fa92f45
fix(gui): If no swap was running "suspend_current_swap" will still re…
binarybaron Jun 30, 2025
35d9fe6
get offer select working
binarybaron Jun 30, 2025
ecbdcd8
refactor: dont display cancel button on set redeem address page
binarybaron Jun 30, 2025
0072706
Merge branch 'master' into feat/concurrent-quotes-swap-init
binarybaron Jun 30, 2025
56a5983
feat: add pagination to offers
binarybaron Jun 30, 2025
7ace399
refactor
binarybaron Jun 30, 2025
80fd1b1
emit partial events for list_sellers
binarybaron Jun 30, 2025
eb7df62
refactor: remove torSlice
binarybaron Jun 30, 2025
ebc5ead
refactor: use sync (non tokio) mutex for approvals
binarybaron Jun 30, 2025
493346a
throttle getSwapInfo calls
binarybaron Jun 30, 2025
01e4e98
feat: add debug page back, add info in suspend dialog about what will…
binarybaron Jun 30, 2025
f759bf0
refactor: format files
b-enedict Jul 2, 2025
ed64194
refactor(gui): Remove sortMakers method and replace with method that …
b-enedict Jul 2, 2025
300eaf0
refactor(gui): Refactor swap page structure
b-enedict Jul 2, 2025
22f1bd0
fix(gui): Add breakpoints to swapSetupInflightPage
b-enedict Jul 2, 2025
e5090b9
feat(gui): Add flag for outdated makers
b-enedict Jul 2, 2025
6537727
refactor(gui): Reduce fetch rate for maker quotes
b-enedict Jul 2, 2025
e329af0
fix(gui): Debug Window size
b-enedict Jul 2, 2025
cad5cb1
Merge branch 'master' into feat/concurrent-quotes-swap-init
binarybaron Jul 2, 2025
6e178e0
no unwrap
binarybaron Jul 2, 2025
ab2f38d
Merge remote-tracking branch 'origin/feat/concurrent-quotes-swap-init…
binarybaron Jul 2, 2025
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
description:
globs:
alwaysApply: false
---
NEVER NEVER NEVER upgrade or changr the versions used in dependencies without explicitly asking for confirmation!!
12 changes: 2 additions & 10 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 1 addition & 30 deletions monero-rpc-pool/src/pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,47 +158,24 @@ impl NodePool {
&self,
limit: usize,
) -> Result<Vec<crate::database::MoneroNode>> {
debug!(
"Getting top reliable nodes for network {} (target: {})",
self.network, limit
);

// Step 1: Try primary fetch - get top nodes based on recent success (last 200 health checks)
let mut top_nodes = self
.db
.get_top_nodes_by_recent_success(&self.network, 200, limit as i64)
.await
.context("Failed to get top nodes by recent success")?;

debug!(
"Primary fetch returned {} nodes for network {} (target: {})",
top_nodes.len(),
self.network,
limit
);

// Step 2: If primary fetch didn't return enough nodes, fall back to any identified nodes with successful health checks
if top_nodes.len() < limit {
debug!("Primary fetch returned insufficient nodes, falling back to any identified nodes with successful health checks");
top_nodes = self
.db
.get_identified_nodes_with_success(&self.network)
.await?;

debug!(
"Fallback fetch returned {} nodes with successful health checks for network {}",
top_nodes.len(),
self.network
);
}

// Step 3: Check if we still don't have enough nodes
if top_nodes.len() < limit {
let needed = limit - top_nodes.len();
debug!(
"Pool needs {} more nodes to reach target of {} for network {}",
needed, limit, self.network
);

// Step 4: Collect exclusion IDs from nodes already selected
let exclude_ids: Vec<i64> = top_nodes.iter().filter_map(|node| node.id).collect();
Expand All @@ -209,18 +186,12 @@ impl NodePool {
.get_random_nodes(&self.network, needed as i64, &exclude_ids)
.await?;

debug!(
"Secondary fetch returned {} random nodes for network {}",
random_fillers.len(),
self.network
);

// Step 6: Combine lists
top_nodes.extend(random_fillers);
}

debug!(
"Final pool size: {} nodes for network {} (target: {})",
"Pool size: {} nodes for network {} (target was {} nodes)",
top_nodes.len(),
self.network,
limit
Expand Down
1 change: 1 addition & 0 deletions src-gui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"@tauri-apps/plugin-store": "^2.0.0",
"@tauri-apps/plugin-updater": "2.7.1",
"@types/react-redux": "^7.1.34",
"boring-avatars": "^1.11.2",
"humanize-duration": "^3.32.1",
"jdenticon": "^3.3.0",
"lodash": "^4.17.21",
Expand Down
43 changes: 43 additions & 0 deletions src-gui/src/models/tauriModelExt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -292,3 +292,46 @@ export function isBitcoinSyncProgress(
): progress is TauriBitcoinSyncProgress {
return progress.componentName === "SyncingBitcoinWallet";
}

export type PendingSelectMakerApprovalRequest = PendingApprovalRequest & {
content: {
details: { type: "SelectMaker" };
};
};

export function isPendingSelectMakerApprovalEvent(
event: ApprovalRequest,
): event is PendingSelectMakerApprovalRequest {
// Check if the request is pending
if (event.state !== "Pending") {
return false;
}

// Check if the request is a SelectMaker request
return event.content.details.type === "SelectMaker";
}

/**
* Checks if any funds have been locked yet based on the swap progress event
* Returns true for events where funds have been locked
* @param event The TauriSwapProgressEvent to check
* @returns True if funds have been locked, false otherwise
*/
export function haveFundsBeenLocked(
event: TauriSwapProgressEvent | null,
): boolean {
if (event === null) {
return false;
}

switch (event.type) {
case "RequestingQuote":
case "Resuming":
case "ReceivedQuote":
case "WaitingForBtcDeposit":
case "SwapSetupInflight":
return false;
}

return true;
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ export default function MoneroAddressTextField({
setAddresses(response.addresses);
};
fetchAddresses();

const interval = setInterval(fetchAddresses, 5000);
return () => clearInterval(interval);
}, []);

// Event handlers
Expand Down
22 changes: 0 additions & 22 deletions src-gui/src/renderer/components/modal/swap/BitcoinQrCode.tsx

This file was deleted.

47 changes: 6 additions & 41 deletions src-gui/src/renderer/components/modal/swap/SwapDialog.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,11 @@
import {
Box,
Button,
Dialog,
DialogActions,
DialogContent,
} from "@mui/material";
import { Box, Dialog, DialogActions, DialogContent } from "@mui/material";
import { useState } from "react";
import { swapReset } from "store/features/swapSlice";
import { useAppDispatch, useAppSelector, useIsSwapRunning } from "store/hooks";
import SwapSuspendAlert from "../SwapSuspendAlert";
import { useAppSelector } from "store/hooks";
import DebugPage from "./pages/DebugPage";
import SwapStatePage from "./pages/SwapStatePage";
import SwapStatePage from "renderer/components/pages/swap/swap/SwapStatePage";
import SwapDialogTitle from "./SwapDialogTitle";
import SwapStateStepper from "./SwapStateStepper";
import CancelButton from "renderer/components/pages/swap/swap/CancelButton";

export default function SwapDialog({
open,
Expand All @@ -22,26 +15,13 @@ export default function SwapDialog({
onClose: () => void;
}) {
const swap = useAppSelector((state) => state.swap);
const isSwapRunning = useIsSwapRunning();
const [debug, setDebug] = useState(false);
const [openSuspendAlert, setOpenSuspendAlert] = useState(false);

const dispatch = useAppDispatch();

function onCancel() {
if (isSwapRunning) {
setOpenSuspendAlert(true);
} else {
onClose();
dispatch(swapReset());
}
}

// This prevents an issue where the Dialog is shown for a split second without a present swap state
if (!open) return null;

return (
<Dialog open={open} onClose={onCancel} maxWidth="md" fullWidth>
<Dialog open={open} onClose={onClose} maxWidth="md" fullWidth>
<SwapDialogTitle
debug={debug}
setDebug={setDebug}
Expand Down Expand Up @@ -78,23 +58,8 @@ export default function SwapDialog({
</DialogContent>

<DialogActions>
<Button onClick={onCancel} variant="text">
Cancel
</Button>
<Button
color="primary"
variant="contained"
onClick={onCancel}
disabled={isSwapRunning || swap.state === null}
>
Done
</Button>
<CancelButton />
</DialogActions>

<SwapSuspendAlert
open={openSuspendAlert}
onClose={() => setOpenSuspendAlert(false)}
/>
</Dialog>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ function getActiveStep(state: SwapState | null): PathStep | null {
case "RequestingQuote":
case "ReceivedQuote":
case "WaitingForBtcDeposit":
return null; // No funds have been locked yet
case "SwapSetupInflight":
return [PathType.HAPPY_PATH, 0, isReleased];

Expand Down

This file was deleted.

Loading