From 83f831ccac76e4e9267e5e570d983221e2ac594b Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Thu, 10 Oct 2024 18:51:56 +0600 Subject: [PATCH] feat(gui, tauri): Accept --testnet flag, default to mainnet (#106) This PR tackles #92 - Add the `tauri-plugin-cli` (only on desktop) - Check in the frontend if the `--testnet` flag is set. If it's set we pass `testnet=true` to the `initialize_context` command on invokation - We add the `vite-plugin-top-level-await` to allow top level await in all browsers - Remove the `bitcoin_confirmation_target` from settings for simplicity --- .gitignore | 2 +- Cargo.lock | 112 +++++++++++++++++- dprint.json | 2 +- src-gui/README.md | 2 +- src-gui/index.html | 2 - src-gui/package.json | 2 + .../modal/feedback/FeedbackDialog.tsx | 12 +- .../components/modal/swap/SwapDialog.tsx | 3 +- .../components/pages/help/SettingsBox.tsx | 9 +- src-gui/src/renderer/index.tsx | 2 + src-gui/src/renderer/rpc.ts | 4 + src-gui/src/store/config.ts | 7 +- src-gui/src/store/features/settingsSlice.ts | 11 +- src-gui/src/store/hooks.ts | 7 +- src-gui/vite.config.ts | 7 +- src-gui/yarn.lock | 107 +++++++++++++++++ src-tauri/Cargo.toml | 3 + src-tauri/capabilities/default.json | 3 +- src-tauri/capabilities/desktop.json | 11 ++ src-tauri/src/lib.rs | 12 +- src-tauri/tauri.conf.json | 14 ++- swap/src/cli/api/tauri_bindings.rs | 2 - swap/src/database/sqlite.rs | 26 ++-- 23 files changed, 310 insertions(+), 52 deletions(-) create mode 100644 src-tauri/capabilities/desktop.json diff --git a/.gitignore b/.gitignore index eb5a316cb..1de565933 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -target +target \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 7d12b924e..b7fc38aa3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -126,6 +126,55 @@ dependencies = [ "winapi", ] +[[package]] +name = "anstream" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" + +[[package]] +name = "anstyle-parse" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + [[package]] name = "anyhow" version = "1.0.86" @@ -1029,6 +1078,33 @@ dependencies = [ "vec_map", ] +[[package]] +name = "clap" +version = "4.5.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" +dependencies = [ + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.5.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim 0.11.1", +] + +[[package]] +name = "clap_lex" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" + [[package]] name = "clipboard-win" version = "5.4.0" @@ -1074,6 +1150,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" +[[package]] +name = "colorchoice" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" + [[package]] name = "colored" version = "2.1.0" @@ -3090,6 +3172,12 @@ dependencies = [ "once_cell", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + [[package]] name = "itertools" version = "0.10.5" @@ -6806,7 +6894,7 @@ version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10" dependencies = [ - "clap", + "clap 2.33.3", "lazy_static", "structopt-derive", ] @@ -7205,6 +7293,21 @@ dependencies = [ "walkdir", ] +[[package]] +name = "tauri-plugin-cli" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bec7345a851082058b1c7c516a48a9e1d173d2439baa35e27606fc4fbce3409" +dependencies = [ + "clap 4.5.20", + "log", + "serde", + "serde_json", + "tauri", + "tauri-plugin", + "thiserror", +] + [[package]] name = "tauri-plugin-clipboard-manager" version = "2.1.0-beta.7" @@ -8311,6 +8414,7 @@ dependencies = [ "swap", "tauri", "tauri-build", + "tauri-plugin-cli", "tauri-plugin-clipboard-manager", "tauri-plugin-devtools", "tauri-plugin-process", @@ -8361,6 +8465,12 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7" +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + [[package]] name = "uuid" version = "1.10.0" diff --git a/dprint.json b/dprint.json index 4c675de9f..c97d82acf 100644 --- a/dprint.json +++ b/dprint.json @@ -9,7 +9,7 @@ "rustfmt.associations": "**/*.rs" }, "includes": ["**/*.{md}", "**/*.{toml}", "**/*.{rs}"], - "excludes": ["target/"], + "excludes": ["target/", "src-tauri/Cargo.toml"], "plugins": [ "https://plugins.dprint.dev/markdown-0.13.1.wasm", "https://github.com/thomaseizinger/dprint-plugin-cargo-toml/releases/download/0.1.0/cargo-toml-0.1.0.wasm", diff --git a/src-gui/README.md b/src-gui/README.md index b10efc7cd..541c3a7d1 100644 --- a/src-gui/README.md +++ b/src-gui/README.md @@ -21,7 +21,7 @@ yarn install && yarn run dev ```bash cd src-tauri -cargo tauri dev +cargo tauri dev --no-watch -- -- --testnet # let this run as well ``` diff --git a/src-gui/index.html b/src-gui/index.html index 1e8a4c9b3..94b9ba4e3 100644 --- a/src-gui/index.html +++ b/src-gui/index.html @@ -30,8 +30,6 @@ height: 100%; margin: 0; overflow: auto; - overscroll-behavior: none; /* Prevents the bounce effect */ - overscroll-behavior-y: contain; /* Prevents the bounce effect on the y-axis */ } diff --git a/src-gui/package.json b/src-gui/package.json index 89cffe8fe..aa041a2a2 100644 --- a/src-gui/package.json +++ b/src-gui/package.json @@ -20,6 +20,7 @@ "@material-ui/lab": "^4.0.0-alpha.61", "@reduxjs/toolkit": "^2.2.6", "@tauri-apps/api": "^2.0.0", + "@tauri-apps/plugin-cli": "^2.0.0", "@tauri-apps/plugin-clipboard-manager": "^2.0.0", "@tauri-apps/plugin-process": "^2.0.0", "@tauri-apps/plugin-shell": "^2.0.0", @@ -58,6 +59,7 @@ "typescript": "^5.2.2", "typescript-eslint": "^8.1.0", "vite": "^5.3.1", + "vite-plugin-top-level-await": "^1.4.4", "vite-plugin-watch": "^0.3.1", "vite-tsconfig-paths": "^4.3.2", "vitest": "^2.1.1" diff --git a/src-gui/src/renderer/components/modal/feedback/FeedbackDialog.tsx b/src-gui/src/renderer/components/modal/feedback/FeedbackDialog.tsx index 6b42c2ec3..b4733f172 100644 --- a/src-gui/src/renderer/components/modal/feedback/FeedbackDialog.tsx +++ b/src-gui/src/renderer/components/modal/feedback/FeedbackDialog.tsx @@ -10,7 +10,6 @@ import { Select, TextField, } from "@material-ui/core"; -import { CliLog } from "models/cliModel"; import { useSnackbar } from "notistack"; import { useState } from "react"; import TruncatedText from "renderer/components/other/TruncatedText"; @@ -20,21 +19,22 @@ import { parseDateString } from "utils/parseUtils"; import { submitFeedbackViaHttp } from "../../../api"; import LoadingButton from "../../other/LoadingButton"; import { PiconeroAmount } from "../../other/Units"; +import { getLogsOfSwap } from "renderer/rpc"; async function submitFeedback(body: string, swapId: string | number) { let attachedBody = ""; if (swapId !== 0 && typeof swapId === "string") { const swapInfo = store.getState().rpc.state.swapInfos[swapId]; - const logs = [] as CliLog[]; - - throw new Error("Not implemented"); - + if (swapInfo === undefined) { throw new Error(`Swap with id ${swapId} not found`); } - attachedBody = `${JSON.stringify(swapInfo, null, 4)} \n\nLogs: ${logs + // Retrieve logs for the specific swap + const logs = await getLogsOfSwap(swapId, false); + + attachedBody = `${JSON.stringify(swapInfo, null, 4)} \n\nLogs: ${logs.logs .map((l) => JSON.stringify(l)) .join("\n====\n")}`; } diff --git a/src-gui/src/renderer/components/modal/swap/SwapDialog.tsx b/src-gui/src/renderer/components/modal/swap/SwapDialog.tsx index 0b61a48bb..270d96c75 100644 --- a/src-gui/src/renderer/components/modal/swap/SwapDialog.tsx +++ b/src-gui/src/renderer/components/modal/swap/SwapDialog.tsx @@ -31,11 +31,12 @@ export default function SwapDialog({ onClose: () => void; }) { const classes = useStyles(); + const swap = useAppSelector((state) => state.swap); const isSwapRunning = useIsSwapRunning(); - const [debug, setDebug] = useState(false); const [openSuspendAlert, setOpenSuspendAlert] = useState(false); + const dispatch = useAppDispatch(); function onCancel() { diff --git a/src-gui/src/renderer/components/pages/help/SettingsBox.tsx b/src-gui/src/renderer/components/pages/help/SettingsBox.tsx index f03329b8d..8e7704772 100644 --- a/src-gui/src/renderer/components/pages/help/SettingsBox.tsx +++ b/src-gui/src/renderer/components/pages/help/SettingsBox.tsx @@ -9,6 +9,7 @@ import { Box, makeStyles, Tooltip, + Switch, } from "@material-ui/core"; import InfoBox from "renderer/components/modal/swap/InfoBox"; import { @@ -16,7 +17,7 @@ import { setElectrumRpcUrl, setMoneroNodeUrl, } from "store/features/settingsSlice"; -import { useAppDispatch, useAppSelector } from "store/hooks"; +import { useAppDispatch, useSettings } from "store/hooks"; import ValidatedTextField from "renderer/components/other/ValidatedTextField"; import RefreshIcon from "@material-ui/icons/Refresh"; import HelpIcon from '@material-ui/icons/HelpOutline'; @@ -80,7 +81,7 @@ function isValidUrl(url: string, allowedProtocols: string[]): boolean { } function ElectrumRpcUrlSetting() { - const electrumRpcUrl = useAppSelector((s) => s.settings.electrum_rpc_url); + const electrumRpcUrl = useSettings((s) => s.electrum_rpc_url); const dispatch = useAppDispatch(); function isValid(url: string): boolean { @@ -123,7 +124,7 @@ function SettingLabel({ label, tooltip }: { label: ReactNode, tooltip: string | } function MoneroNodeUrlSetting() { - const moneroNodeUrl = useAppSelector((s) => s.settings.monero_node_url); + const moneroNodeUrl = useSettings((s) => s.monero_node_url); const dispatch = useAppDispatch(); function isValid(url: string): boolean { @@ -150,4 +151,4 @@ function MoneroNodeUrlSetting() { ); -} +} \ No newline at end of file diff --git a/src-gui/src/renderer/index.tsx b/src-gui/src/renderer/index.tsx index 43ad88b65..2fcf66eac 100644 --- a/src-gui/src/renderer/index.tsx +++ b/src-gui/src/renderer/index.tsx @@ -17,9 +17,11 @@ import { import App from "./components/App"; import { initEventListeners } from "./rpc"; import { persistor, store } from "./store/storeRenderer"; +import { Box } from "@material-ui/core"; const container = document.getElementById("root"); const root = createRoot(container!); + root.render( diff --git a/src-gui/src/renderer/rpc.ts b/src-gui/src/renderer/rpc.ts index ae1a3264a..e6e08de62 100644 --- a/src-gui/src/renderer/rpc.ts +++ b/src-gui/src/renderer/rpc.ts @@ -36,6 +36,7 @@ import { providerToConcatenatedMultiAddr } from "utils/multiAddrUtils"; import { MoneroRecoveryResponse } from "models/rpcModel"; import { ListSellersResponse } from "../models/tauriModel"; import logger from "utils/logger"; +import { isTestnet } from "store/config"; export async function initEventListeners() { // This operation is in-expensive @@ -201,7 +202,10 @@ export async function listSellersAtRendezvousPoint( export async function initializeContext() { const settings = store.getState().settings; + const testnet = isTestnet(); + await invokeUnsafe("initialize_context", { settings, + testnet, }); } diff --git a/src-gui/src/store/config.ts b/src-gui/src/store/config.ts index c9f60034f..87b69dbf0 100644 --- a/src-gui/src/store/config.ts +++ b/src-gui/src/store/config.ts @@ -1,7 +1,12 @@ import { ExtendedProviderStatus } from "models/apiModel"; import { splitPeerIdFromMultiAddress } from "utils/parseUtils"; +import { getMatches } from '@tauri-apps/plugin-cli'; -export const isTestnet = () => true; +const matches = await getMatches(); + +export function isTestnet() { + return matches.args.testnet?.value === true +} export const isDevelopment = true; diff --git a/src-gui/src/store/features/settingsSlice.ts b/src-gui/src/store/features/settingsSlice.ts index 5485941ef..b63675969 100644 --- a/src-gui/src/store/features/settingsSlice.ts +++ b/src-gui/src/store/features/settingsSlice.ts @@ -2,7 +2,6 @@ import { createSlice, PayloadAction } from "@reduxjs/toolkit"; import { TauriSettings } from "models/tauriModel"; const initialState: TauriSettings = { - bitcoin_confirmation_target: 1, electrum_rpc_url: null, monero_node_url: null, }; @@ -11,18 +10,15 @@ const alertsSlice = createSlice({ name: "settings", initialState, reducers: { - setBitcoinConfirmationTarget(slice, action: PayloadAction) { - slice.bitcoin_confirmation_target = action.payload; - }, setElectrumRpcUrl(slice, action: PayloadAction) { - if (action.payload === null || action.payload === "") { + if (action.payload === null || action.payload === "") { slice.electrum_rpc_url = null; } else { slice.electrum_rpc_url = action.payload; } }, setMoneroNodeUrl(slice, action: PayloadAction) { - if (action.payload === null || action.payload === "") { + if (action.payload === null || action.payload === "") { slice.monero_node_url = null; } else { slice.monero_node_url = action.payload; @@ -35,9 +31,8 @@ const alertsSlice = createSlice({ }); export const { - setBitcoinConfirmationTarget, setElectrumRpcUrl, setMoneroNodeUrl, - resetSettings + resetSettings, } = alertsSlice.actions; export default alertsSlice.reducer; diff --git a/src-gui/src/store/hooks.ts b/src-gui/src/store/hooks.ts index 9843d8557..66268f3a4 100644 --- a/src-gui/src/store/hooks.ts +++ b/src-gui/src/store/hooks.ts @@ -5,6 +5,7 @@ import type { AppDispatch, RootState } from "renderer/store/storeRenderer"; import { parseDateString } from "utils/parseUtils"; import { useMemo } from "react"; import { isCliLogRelatedToSwap } from "models/cliModel"; +import { TauriSettings } from "models/tauriModel"; export const useAppDispatch = () => useDispatch(); export const useAppSelector: TypedUseSelectorHook = useSelector; @@ -73,6 +74,6 @@ export function useSwapInfosSortedByDate() { ); } -export function useSettings() { - return useAppSelector((state) => state.settings); -} +export function useSettings(selector: (settings: TauriSettings) => T): T { + return useAppSelector((state) => selector(state.settings)); +} \ No newline at end of file diff --git a/src-gui/vite.config.ts b/src-gui/vite.config.ts index bb11f9059..50752b0a6 100644 --- a/src-gui/vite.config.ts +++ b/src-gui/vite.config.ts @@ -4,6 +4,7 @@ import { defineConfig } from "vite"; import tsconfigPaths from "vite-tsconfig-paths"; import { watch } from "vite-plugin-watch"; import path from "path"; +import topLevelAwait from "vite-plugin-top-level-await"; const mobile = !!/android|ios/.exec(process.env.TAURI_ENV_PLATFORM); @@ -12,7 +13,8 @@ export default defineConfig(async () => ({ plugins: [ react(), tsconfigPaths(), - // automatically regenerate the typescript bindings when there's a change + topLevelAwait(), + // Automatically regenerate the typescript bindings when there's a change to the rust code watch({ pattern: ["../swap/src/**/*"], command: "yarn run gen-bindings", @@ -25,9 +27,6 @@ export default defineConfig(async () => ({ server.watcher.add(path.resolve(__dirname, "../swap/src")); }, }, - // VitePluginRestart({ - // restart: ["../swap/src/**/*"] - // }) ], // Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build` // diff --git a/src-gui/yarn.lock b/src-gui/yarn.lock index 03386ef7c..d361efe71 100644 --- a/src-gui/yarn.lock +++ b/src-gui/yarn.lock @@ -557,6 +557,11 @@ resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.17.1.tgz#bf93997beb81863fde042ebd05013a2618471362" integrity sha512-mCOMec4BKd6BRGBZeSnGiIgwsbLGp3yhVqAD8H+PxiRNEHgDpZb8J1TnrSDlg97t0ySKMQJTHCWBCmBpSmkF6Q== +"@rollup/plugin-virtual@^3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@rollup/plugin-virtual/-/plugin-virtual-3.0.2.tgz#17e17eeecb4c9fa1c0a6e72c9e5f66382fddbb82" + integrity sha512-10monEYsBp3scM4/ND4LNH5Rxvh3e/cVeL3jWTgZ2SrQ+BmUoQcopVQvnaMcOnykb1VkxUFuDAN+0FnpTFRy2A== + "@rollup/rollup-android-arm-eabi@4.18.0": version "4.18.0" resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz#bbd0e616b2078cd2d68afc9824d1fadb2f2ffd27" @@ -717,6 +722,87 @@ resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.2.tgz#c770006ccc780b2de7b2151fc7f37b49121a21c1" integrity sha512-Yy8So+SoRz8I3NS4Bjh91BICPOSVgdompTIPYTByUqU66AXSIOgmW3Lv1ke3NORPqxdF+RdrZET+8vYai6f4aA== +"@swc/core-darwin-arm64@1.7.26": + version "1.7.26" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.7.26.tgz#5f4096c00e71771ca1b18c824f0c92a052c70760" + integrity sha512-FF3CRYTg6a7ZVW4yT9mesxoVVZTrcSWtmZhxKCYJX9brH4CS/7PRPjAKNk6kzWgWuRoglP7hkjQcd6EpMcZEAw== + +"@swc/core-darwin-x64@1.7.26": + version "1.7.26" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.7.26.tgz#867b7a4f094e6b64201090ca5fcbf3da7d0f3e22" + integrity sha512-az3cibZdsay2HNKmc4bjf62QVukuiMRh5sfM5kHR/JMTrLyS6vSw7Ihs3UTkZjUxkLTT8ro54LI6sV6sUQUbLQ== + +"@swc/core-linux-arm-gnueabihf@1.7.26": + version "1.7.26" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.7.26.tgz#35bb43894def296d92aaa2cc9372d48042f37777" + integrity sha512-VYPFVJDO5zT5U3RpCdHE5v1gz4mmR8BfHecUZTmD2v1JeFY6fv9KArJUpjrHEEsjK/ucXkQFmJ0jaiWXmpOV9Q== + +"@swc/core-linux-arm64-gnu@1.7.26": + version "1.7.26" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.7.26.tgz#8e2321cc4ec84cbfed8f8e16ff1ed7b854450443" + integrity sha512-YKevOV7abpjcAzXrhsl+W48Z9mZvgoVs2eP5nY+uoMAdP2b3GxC0Df1Co0I90o2lkzO4jYBpTMcZlmUXLdXn+Q== + +"@swc/core-linux-arm64-musl@1.7.26": + version "1.7.26" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.7.26.tgz#b1c16e4b23ffa9ff19973eda6ffee35d2a7de7b0" + integrity sha512-3w8iZICMkQQON0uIcvz7+Q1MPOW6hJ4O5ETjA0LSP/tuKqx30hIniCGOgPDnv3UTMruLUnQbtBwVCZTBKR3Rkg== + +"@swc/core-linux-x64-gnu@1.7.26": + version "1.7.26" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.7.26.tgz#388e2cc13a010cd28787aead2cecf31eb491836d" + integrity sha512-c+pp9Zkk2lqb06bNGkR2Looxrs7FtGDMA4/aHjZcCqATgp348hOKH5WPvNLBl+yPrISuWjbKDVn3NgAvfvpH4w== + +"@swc/core-linux-x64-musl@1.7.26": + version "1.7.26" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.7.26.tgz#51e0ff30981f26d7a5b97a7a7b5b291bad050d1a" + integrity sha512-PgtyfHBF6xG87dUSSdTJHwZ3/8vWZfNIXQV2GlwEpslrOkGqy+WaiiyE7Of7z9AvDILfBBBcJvJ/r8u980wAfQ== + +"@swc/core-win32-arm64-msvc@1.7.26": + version "1.7.26" + resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.7.26.tgz#a7fdcc4074c34ee6a026506b594d00323383c11f" + integrity sha512-9TNXPIJqFynlAOrRD6tUQjMq7KApSklK3R/tXgIxc7Qx+lWu8hlDQ/kVPLpU7PWvMMwC/3hKBW+p5f+Tms1hmA== + +"@swc/core-win32-ia32-msvc@1.7.26": + version "1.7.26" + resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.7.26.tgz#ae7be6dde798eebee2000b8fd84e01a439b5bd6a" + integrity sha512-9YngxNcG3177GYdsTum4V98Re+TlCeJEP4kEwEg9EagT5s3YejYdKwVAkAsJszzkXuyRDdnHUpYbTrPG6FiXrQ== + +"@swc/core-win32-x64-msvc@1.7.26": + version "1.7.26" + resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.7.26.tgz#310d607004d7319085a4dec20c0c38c3405cc05b" + integrity sha512-VR+hzg9XqucgLjXxA13MtV5O3C0bK0ywtLIBw/+a+O+Oc6mxFWHtdUeXDbIi5AiPbn0fjgVJMqYnyjGyyX8u0w== + +"@swc/core@^1.7.0": + version "1.7.26" + resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.7.26.tgz#beda9b82063fcec7b56c958804a4d175aecf9a9d" + integrity sha512-f5uYFf+TmMQyYIoxkn/evWhNGuUzC730dFwAKGwBVHHVoPyak1/GvJUm6i1SKl+2Hrj9oN0i3WSoWWZ4pgI8lw== + dependencies: + "@swc/counter" "^0.1.3" + "@swc/types" "^0.1.12" + optionalDependencies: + "@swc/core-darwin-arm64" "1.7.26" + "@swc/core-darwin-x64" "1.7.26" + "@swc/core-linux-arm-gnueabihf" "1.7.26" + "@swc/core-linux-arm64-gnu" "1.7.26" + "@swc/core-linux-arm64-musl" "1.7.26" + "@swc/core-linux-x64-gnu" "1.7.26" + "@swc/core-linux-x64-musl" "1.7.26" + "@swc/core-win32-arm64-msvc" "1.7.26" + "@swc/core-win32-ia32-msvc" "1.7.26" + "@swc/core-win32-x64-msvc" "1.7.26" + +"@swc/counter@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@swc/counter/-/counter-0.1.3.tgz#cc7463bd02949611c6329596fccd2b0ec782b0e9" + integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ== + +"@swc/types@^0.1.12": + version "0.1.12" + resolved "https://registry.yarnpkg.com/@swc/types/-/types-0.1.12.tgz#7f632c06ab4092ce0ebd046ed77ff7557442282f" + integrity sha512-wBJA+SdtkbFhHjTMYH+dEH1y4VpfGdAc2Kw/LK09i9bXd/K6j6PkDcFCEzb6iVfZMkPRrl/q0e3toqTAJdkIVA== + dependencies: + "@swc/counter" "^0.1.3" + "@tauri-apps/api@^2.0.0": version "2.0.1" resolved "https://registry.yarnpkg.com/@tauri-apps/api/-/api-2.0.1.tgz#dc49d899fb873b96ee1d46a171384625ba5ad404" @@ -788,6 +874,13 @@ "@tauri-apps/cli-win32-ia32-msvc" "2.0.1" "@tauri-apps/cli-win32-x64-msvc" "2.0.1" +"@tauri-apps/plugin-cli@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@tauri-apps/plugin-cli/-/plugin-cli-2.0.0.tgz#cf90232909a3f1c0ac963dcef9914ca0c9f874f9" + integrity sha512-glQmlL1IiCGEa1FHYa/PTPSeYhfu56omLRgHXWlJECDt6DbJyRuJWVgtkQfUxtqnVdYnnU+DGIGeiInoEqtjLw== + dependencies: + "@tauri-apps/api" "^2.0.0" + "@tauri-apps/plugin-clipboard-manager@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@tauri-apps/plugin-clipboard-manager/-/plugin-clipboard-manager-2.0.0.tgz#cf08df2338c055d15a60cbb61140766859e06a77" @@ -3633,6 +3726,11 @@ use-sync-external-store@^1.0.0: resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz#c3b6390f3a30eba13200d2302dcdf1e7b57b2ef9" integrity sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw== +uuid@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-10.0.0.tgz#5a95aa454e6e002725c79055fd42aaba30ca6294" + integrity sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ== + varint@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/varint/-/varint-6.0.0.tgz#9881eb0ce8feaea6512439d19ddf84bf551661d0" @@ -3653,6 +3751,15 @@ vite-node@2.1.1: pathe "^1.1.2" vite "^5.0.0" +vite-plugin-top-level-await@^1.4.4: + version "1.4.4" + resolved "https://registry.yarnpkg.com/vite-plugin-top-level-await/-/vite-plugin-top-level-await-1.4.4.tgz#4900e06bfb7179de20aaa9b4730d04022a9e259e" + integrity sha512-QyxQbvcMkgt+kDb12m2P8Ed35Sp6nXP+l8ptGrnHV9zgYDUpraO0CPdlqLSeBqvY2DToR52nutDG7mIHuysdiw== + dependencies: + "@rollup/plugin-virtual" "^3.0.2" + "@swc/core" "^1.7.0" + uuid "^10.0.0" + vite-plugin-watch@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/vite-plugin-watch/-/vite-plugin-watch-0.3.1.tgz#5000f7ded6eb1c42e9483d6ea3d812061ab8188f" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index edeb1cbb9..15fce35d9 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -27,3 +27,6 @@ tauri-plugin-process = "2.0.0" tauri-plugin-shell = "2.0.0" tauri-plugin-store = "2.0.0" tracing = "0.1.40" + +[target."cfg(not(any(target_os = \"android\", target_os = \"ios\")))".dependencies] +tauri-plugin-cli = "2.0.0" diff --git a/src-tauri/capabilities/default.json b/src-tauri/capabilities/default.json index 613d06148..245497ba6 100644 --- a/src-tauri/capabilities/default.json +++ b/src-tauri/capabilities/default.json @@ -9,6 +9,7 @@ "clipboard-manager:allow-write-text", "shell:allow-open", "store:default", - "process:default" + "process:default", + "cli:allow-cli-matches" ] } diff --git a/src-tauri/capabilities/desktop.json b/src-tauri/capabilities/desktop.json new file mode 100644 index 000000000..d40f3f23f --- /dev/null +++ b/src-tauri/capabilities/desktop.json @@ -0,0 +1,11 @@ +{ + "identifier": "desktop-capability", + "platforms": [ + "macOS", + "windows", + "linux" + ], + "permissions": [ + "cli:default" + ] +} \ No newline at end of file diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 732bc7e48..39d4dc9c6 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -114,6 +114,9 @@ impl State { fn setup(app: &mut tauri::App) -> Result<(), Box> { let app_handle = app.app_handle().to_owned(); + #[cfg(desktop)] + app_handle.plugin(tauri_plugin_cli::init())?; + // We need to set a value for the Tauri state right at the start // If we don't do this, Tauri commands will panic at runtime if no value is present app_handle.manage::>(RwLock::new(State::new())); @@ -201,6 +204,7 @@ async fn is_context_available(context: tauri::State<'_, RwLock>) -> Resul #[tauri::command] async fn initialize_context( settings: TauriSettings, + testnet: bool, app_handle: tauri::AppHandle, state: tauri::State<'_, RwLock>, ) -> Result<(), String> { @@ -213,13 +217,13 @@ async fn initialize_context( // Get app handle and create a Tauri handle let tauri_handle = TauriHandle::new(app_handle.clone()); - let context_result = ContextBuilder::new(true) + let context_result = ContextBuilder::new(testnet) .with_bitcoin(Bitcoin { - bitcoin_electrum_rpc_url: settings.electrum_rpc_url, - bitcoin_target_block: settings.bitcoin_confirmation_target.into(), + bitcoin_electrum_rpc_url: settings.electrum_rpc_url.clone(), + bitcoin_target_block: None, }) .with_monero(Monero { - monero_daemon_address: settings.monero_node_url, + monero_daemon_address: settings.monero_node_url.clone(), }) .with_json(false) .with_debug(true) diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 03186d6ca..640d894e2 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -5,10 +5,6 @@ "build": { "devUrl": "http://localhost:1420", "frontendDist": "../src-gui/dist", - "beforeDevCommand": { - "cwd": "../src-gui", - "script": "yarn run dev" - }, "beforeBuildCommand": { "cwd": "../src-gui", "script": "yarn run build" @@ -36,5 +32,15 @@ "icons/icon.icns", "icons/icon.ico" ] + }, + "plugins": { + "cli": { + "description": "Start the GUI application", + "args": [ + { + "name": "testnet" + } + ] + } } } diff --git a/swap/src/cli/api/tauri_bindings.rs b/swap/src/cli/api/tauri_bindings.rs index 82194f172..3dee7b2d0 100644 --- a/swap/src/cli/api/tauri_bindings.rs +++ b/swap/src/cli/api/tauri_bindings.rs @@ -214,8 +214,6 @@ pub struct TauriTimelockChangeEvent { #[typeshare] #[derive(Debug, Serialize, Deserialize, Clone)] pub struct TauriSettings { - /// This is used for estimating the target block for Bitcoin (fee) - pub bitcoin_confirmation_target: u16, /// The URL of the Monero node e.g `http://xmr.node:18081` pub monero_node_url: Option, /// The URL of the Electrum RPC server e.g `ssl://bitcoin.com:50001` diff --git a/swap/src/database/sqlite.rs b/swap/src/database/sqlite.rs index ba99ab0c7..d0d09e693 100644 --- a/swap/src/database/sqlite.rs +++ b/swap/src/database/sqlite.rs @@ -283,17 +283,27 @@ impl Database for SqliteDatabase { let result = rows .iter() - .map(|row| { - let swap_id = Uuid::from_str(&row.swap_id)?; + .filter_map(|row| { + let swap_id = match Uuid::from_str(&row.swap_id) { + Ok(id) => id, + Err(e) => { + tracing::error!(swap_id = %row.swap_id, error = ?e, "Failed to parse UUID"); + return None; + } + }; let state = match serde_json::from_str::(&row.state) { - Ok(a) => Ok(State::from(a)), - Err(e) => Err(e), - }?; - Ok((swap_id, state)) + Ok(a) => State::from(a), + Err(e) => { + tracing::error!(swap_id = %swap_id, error = ?e, "Failed to deserialize state"); + return None; + } + }; + + Some((swap_id, state)) }) - .collect::>>(); + .collect::>(); - result + Ok(result) } async fn get_states(&self, swap_id: Uuid) -> Result> {