diff --git a/Cargo.lock b/Cargo.lock
index 9815a686..99136123 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -134,9 +134,9 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
[[package]]
name = "arboard"
-version = "3.4.0"
+version = "3.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9fb4009533e8ff8f1450a5bcbc30f4242a1d34442221f72314bea1f5dc9c7f89"
+checksum = "df099ccb16cd014ff054ac1bf392c67feeef57164b05c42f037cd40f5d4357f4"
dependencies = [
"clipboard-win",
"core-graphics 0.23.2",
@@ -850,9 +850,9 @@ dependencies = [
[[package]]
name = "cc"
-version = "1.1.15"
+version = "1.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6"
+checksum = "07b1695e2c7e8fc85310cde85aeaab7e3097f593c91d209d3f9df76c928100f0"
dependencies = [
"jobserver",
"libc",
@@ -1776,9 +1776,9 @@ dependencies = [
[[package]]
name = "error-code"
-version = "3.2.0"
+version = "3.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a0474425d51df81997e2f90a21591180b38eccf27292d755f3e30750225c175b"
+checksum = "a5d9305ccc6942a704f4335694ecd3de2ea531b114ac2d51f5f843750787a92f"
[[package]]
name = "event-listener"
@@ -2803,9 +2803,9 @@ dependencies = [
[[package]]
name = "iana-time-zone"
-version = "0.1.60"
+version = "0.1.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
+checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220"
dependencies = [
"android_system_properties",
"core-foundation-sys",
@@ -2926,9 +2926,9 @@ dependencies = [
[[package]]
name = "infer"
-version = "0.15.0"
+version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb33622da908807a06f9513c19b3c1ad50fab3e4137d82a78107d502075aa199"
+checksum = "bc150e5ce2330295b8616ce0e3f53250e53af31759a9dbedad1621ba29151847"
dependencies = [
"cfb",
]
@@ -4234,7 +4234,7 @@ version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56"
dependencies = [
- "proc-macro-crate 2.0.2",
+ "proc-macro-crate 1.1.0",
"proc-macro2",
"quote",
"syn 2.0.46",
@@ -4329,7 +4329,6 @@ checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8"
dependencies = [
"bitflags 2.6.0",
"block2",
- "dispatch",
"libc",
"objc2",
]
@@ -4572,9 +4571,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
name = "pest"
-version = "2.7.11"
+version = "2.7.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95"
+checksum = "fdbef9d1d47087a895abd220ed25eb4ad973a5e26f6a4367b038c25e28dfc2d9"
dependencies = [
"memchr",
"thiserror",
@@ -4583,9 +4582,9 @@ dependencies = [
[[package]]
name = "pest_derive"
-version = "2.7.11"
+version = "2.7.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a548d2beca6773b1c244554d36fcf8548a8a58e74156968211567250e48e49a"
+checksum = "4d3a6e3394ec80feb3b6393c725571754c6188490265c61aaf260810d6b95aa0"
dependencies = [
"pest",
"pest_generator",
@@ -4593,9 +4592,9 @@ dependencies = [
[[package]]
name = "pest_generator"
-version = "2.7.11"
+version = "2.7.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c93a82e8d145725dcbaf44e5ea887c8a869efdcc28706df2d08c69e17077183"
+checksum = "94429506bde1ca69d1b5601962c73f4172ab4726571a59ea95931218cb0e930e"
dependencies = [
"pest",
"pest_meta",
@@ -4606,9 +4605,9 @@ dependencies = [
[[package]]
name = "pest_meta"
-version = "2.7.11"
+version = "2.7.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a941429fea7e08bedec25e4f6785b6ffaacc6b755da98df5ef3e7dcf4a124c4f"
+checksum = "ac8a071862e93690b6e34e9a5fb8e33ff3734473ac0245b27232222c4906a33f"
dependencies = [
"once_cell",
"pest",
@@ -4819,9 +4818,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pkg-config"
-version = "0.3.30"
+version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
+checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
[[package]]
name = "plist"
@@ -5312,9 +5311,9 @@ dependencies = [
[[package]]
name = "redox_syscall"
-version = "0.5.3"
+version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4"
+checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853"
dependencies = [
"bitflags 2.6.0",
]
@@ -5331,9 +5330,9 @@ dependencies = [
[[package]]
name = "regex"
-version = "1.10.5"
+version = "1.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f"
+checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619"
dependencies = [
"aho-corasick 1.1.3",
"memchr",
@@ -6393,25 +6392,24 @@ dependencies = [
[[package]]
name = "softbuffer"
-version = "0.4.5"
+version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d623bff5d06f60d738990980d782c8c866997d9194cfe79ecad00aa2f76826dd"
+checksum = "18051cdd562e792cad055119e0cdb2cfc137e44e3987532e0f9659a77931bb08"
dependencies = [
"bytemuck",
"cfg_aliases",
- "core-graphics 0.23.2",
+ "core-graphics 0.24.0",
"foreign-types",
"js-sys",
"log",
"objc2",
- "objc2-app-kit",
"objc2-foundation",
"objc2-quartz-core",
"raw-window-handle",
- "redox_syscall 0.5.3",
+ "redox_syscall 0.5.4",
"wasm-bindgen",
"web-sys",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
]
[[package]]
@@ -6862,9 +6860,9 @@ dependencies = [
[[package]]
name = "tao"
-version = "0.29.1"
+version = "0.30.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3a97abbc7d6cfd0720da3e06fcb1cf2ac87cbfdb5bbbce103a1279a211c4d81"
+checksum = "82e7ede56f9ef03a0bb384c7b2bed4f3985ee7f3f79ec887c50d8466eec21096"
dependencies = [
"bitflags 2.6.0",
"cocoa",
@@ -6918,13 +6916,12 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
[[package]]
name = "tauri"
-version = "2.0.0-rc.8"
+version = "2.0.0-rc.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8345ccc676ef16e26b61fc0f5340b4e770678b1e1f53f08c69ebdac5e56b422"
+checksum = "eb3c3b1c7ac5b72d59da307b84af900a0098c74c9d7369f65018cd8ec0eb50fb"
dependencies = [
"anyhow",
"bytes",
- "cocoa",
"dirs",
"dunce",
"embed_plist",
@@ -6939,8 +6936,11 @@ dependencies = [
"log",
"mime",
"muda",
- "objc",
+ "objc2",
+ "objc2-app-kit",
+ "objc2-foundation",
"percent-encoding",
+ "plist",
"raw-window-handle",
"reqwest",
"serde",
@@ -6967,9 +6967,9 @@ dependencies = [
[[package]]
name = "tauri-build"
-version = "2.0.0-rc.7"
+version = "2.0.0-rc.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d5ad5fcfaf02cf79aa6727f6c5df38567d8dce172b00b62690c6bc46c08b7ce"
+checksum = "6ff5713e81e02e0b99f5219b275abbd7d2c0cc0f30180e25b1b650e08feeac63"
dependencies = [
"anyhow",
"cargo_toml",
@@ -6989,9 +6989,9 @@ dependencies = [
[[package]]
name = "tauri-codegen"
-version = "2.0.0-rc.7"
+version = "2.0.0-rc.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "809ef6316726fc72593d296cf6f4e7461326e310c313d6a6c42b6e7f1e2671cf"
+checksum = "5370f2591dcc93d4ff08d9dd168f5097f79b34e859883586a409c627544190e3"
dependencies = [
"base64 0.22.1",
"brotli 6.0.0",
@@ -7016,9 +7016,9 @@ dependencies = [
[[package]]
name = "tauri-macros"
-version = "2.0.0-rc.6"
+version = "2.0.0-rc.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1359e8861d210d25731f8b1bfbb4d111dd06406cf73c59659366ef450364d811"
+checksum = "19442dc8ee002ab1926586f6aecb90114f3a1226766008b0c9ac2d9fec9eeb7e"
dependencies = [
"heck 0.5.0",
"proc-macro2",
@@ -7030,9 +7030,9 @@ dependencies = [
[[package]]
name = "tauri-plugin"
-version = "2.0.0-rc.7"
+version = "2.0.0-rc.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7dded420c86183f592d0fe925ef9447f41e26fa79f0bdfef8d3f17bfbcdbfb7"
+checksum = "5e3368e91a98aa55ea4e3e8ccff516bc1ed2f85872c335ec35e9b345469032e0"
dependencies = [
"anyhow",
"glob",
@@ -7084,9 +7084,9 @@ dependencies = [
[[package]]
name = "tauri-runtime"
-version = "2.0.0-rc.7"
+version = "2.0.0-rc.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75c72b844f387bfc3341c355f3e16b8cbf4161848fa4e348670effb222cd3ba5"
+checksum = "c5f38d8aaa1e81d20e8e208e3e317f81b59fb75c530fbae8a90e72d02001d687"
dependencies = [
"dpi",
"gtk",
@@ -7103,15 +7103,17 @@ dependencies = [
[[package]]
name = "tauri-runtime-wry"
-version = "2.0.0-rc.7"
+version = "2.0.0-rc.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "73accf936a7cd01d1382de7850726fdf6c1f6ab3b01ccb7a0950cb852e332596"
+checksum = "cf1ef5171e14c8fe3b5a63e75004c20d057747bc3e7fdc5f8ded625f0b29f5c7"
dependencies = [
- "cocoa",
"gtk",
"http 1.1.0",
"jni",
"log",
+ "objc2",
+ "objc2-app-kit",
+ "objc2-foundation",
"percent-encoding",
"raw-window-handle",
"softbuffer",
@@ -7127,9 +7129,9 @@ dependencies = [
[[package]]
name = "tauri-utils"
-version = "2.0.0-rc.7"
+version = "2.0.0-rc.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d53d9fe87e985b273696ae22ce2b9f099a8f1b44bc8fb127467bda5fcb3e4371"
+checksum = "31fe4c9148e1b35225e1c00753f24b517ce00041d02eb4b4d6fd10613a47736c"
dependencies = [
"brotli 6.0.0",
"cargo_metadata",
@@ -7728,9 +7730,9 @@ dependencies = [
[[package]]
name = "tray-icon"
-version = "0.16.0"
+version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "131a65b2cef2081bc14dbcd414c906edbfa3bb5323dd7e748cc298614681196b"
+checksum = "044d7738b3d50f288ddef035b793228740ad4d927f5466b0af55dc15e7e03cfe"
dependencies = [
"core-graphics 0.24.0",
"crossbeam-channel",
@@ -7951,9 +7953,9 @@ dependencies = [
[[package]]
name = "unicode-segmentation"
-version = "1.11.0"
+version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
+checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
[[package]]
name = "unicode-width"
@@ -8036,11 +8038,10 @@ dependencies = [
[[package]]
name = "urlpattern"
-version = "0.2.0"
+version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f9bd5ff03aea02fa45b13a7980151fe45009af1980ba69f651ec367121a31609"
+checksum = "70acd30e3aa1450bc2eece896ce2ad0d178e9c079493819301573dae3c37ba6d"
dependencies = [
- "derive_more",
"regex",
"serde",
"unic-ucd-ident",
@@ -8450,12 +8451,13 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "window-vibrancy"
-version = "0.5.1"
+version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d8cdd6999298d969289d8078dae02ce798ad23452075985cccba8b6326711ecf"
+checksum = "3ea403deff7b51fff19e261330f71608ff2cdef5721d72b64180bb95be7c4150"
dependencies = [
- "cocoa",
- "objc",
+ "objc2",
+ "objc2-app-kit",
+ "objc2-foundation",
"raw-window-handle",
"windows-sys 0.59.0",
"windows-version",
@@ -8850,9 +8852,9 @@ dependencies = [
[[package]]
name = "wry"
-version = "0.42.0"
+version = "0.43.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49b8049c8f239cdbfaaea4bacb9646f6b208938ceec0acd5b3e99cd05f70903f"
+checksum = "f4d715cf5fe88e9647f3d17b207b6d060d4a88e7171d4ccb2d2c657dd1d44728"
dependencies = [
"base64 0.22.1",
"block",
diff --git a/src-gui/src/models/cliModel.ts b/src-gui/src/models/cliModel.ts
index 587c6197..aff0c66c 100644
--- a/src-gui/src/models/cliModel.ts
+++ b/src-gui/src/models/cliModel.ts
@@ -37,7 +37,7 @@ export function parseCliLogString(log: string): CliLog | string {
} else {
return log;
}
- } catch (err) {
+ } catch {
return log;
}
}
diff --git a/src-gui/src/renderer/components/modal/provider/ProviderListDialog.tsx b/src-gui/src/renderer/components/modal/provider/ProviderListDialog.tsx
index a0e0021a..d2cf106e 100644
--- a/src-gui/src/renderer/components/modal/provider/ProviderListDialog.tsx
+++ b/src-gui/src/renderer/components/modal/provider/ProviderListDialog.tsx
@@ -1,7 +1,6 @@
import {
Avatar,
Button,
- CircularProgress,
Dialog,
DialogActions,
DialogContent,
@@ -15,14 +14,9 @@ import {
import AddIcon from "@material-ui/icons/Add";
import SearchIcon from "@material-ui/icons/Search";
import { ExtendedProviderStatus } from "models/apiModel";
-import { RpcMethod } from "models/rpcModel";
import { useState } from "react";
import { setSelectedProvider } from "store/features/providersSlice";
-import {
- useAllProviders,
- useAppDispatch,
- useIsRpcEndpointBusy,
-} from "store/hooks";
+import { useAllProviders, useAppDispatch } from "store/hooks";
import ListSellersDialog from "../listSellers/ListSellersDialog";
import ProviderInfo from "./ProviderInfo";
import ProviderSubmitDialog from "./ProviderSubmitDialog";
@@ -65,13 +59,11 @@ export function ProviderSubmitDialogOpenButton() {
export function ListSellersDialogOpenButton() {
const [open, setOpen] = useState(false);
- const running = useIsRpcEndpointBusy(RpcMethod.LIST_SELLERS);
return (
{
// Prevents background from being clicked and reopening dialog
if (!open) {
@@ -81,7 +73,9 @@ export function ListSellersDialogOpenButton() {
>
setOpen(false)} />
- {running ? : }
+
+
+
diff --git a/src-gui/src/renderer/components/pages/help/RpcControlBox.tsx b/src-gui/src/renderer/components/pages/help/RpcControlBox.tsx
index 333b88c2..0dbc32a4 100644
--- a/src-gui/src/renderer/components/pages/help/RpcControlBox.tsx
+++ b/src-gui/src/renderer/components/pages/help/RpcControlBox.tsx
@@ -3,7 +3,7 @@ import FolderOpenIcon from "@material-ui/icons/FolderOpen";
import PlayArrowIcon from "@material-ui/icons/PlayArrow";
import StopIcon from "@material-ui/icons/Stop";
import PromiseInvokeButton from "renderer/components/PromiseInvokeButton";
-import { useIsContextAvailable } from "store/hooks";
+import { useAppSelector, useIsContextAvailable } from "store/hooks";
import InfoBox from "../../modal/swap/InfoBox";
import CliLogsBox from "../../other/RenderedCliLog";
@@ -18,17 +18,16 @@ const useStyles = makeStyles((theme) => ({
export default function RpcControlBox() {
const isRunning = useIsContextAvailable();
const classes = useStyles();
+ const logs = useAppSelector((s) => s.rpc.logs);
return (
- ) : null
+
}
additionalContent={
diff --git a/src-gui/src/renderer/components/pages/wallet/WithdrawWidget.tsx b/src-gui/src/renderer/components/pages/wallet/WithdrawWidget.tsx
index 6cbcf9f9..248a1b48 100644
--- a/src-gui/src/renderer/components/pages/wallet/WithdrawWidget.tsx
+++ b/src-gui/src/renderer/components/pages/wallet/WithdrawWidget.tsx
@@ -3,7 +3,7 @@ import SendIcon from "@material-ui/icons/Send";
import { RpcMethod } from "models/rpcModel";
import { useState } from "react";
import { SatsAmount } from "renderer/components/other/Units";
-import { useAppSelector, useIsRpcEndpointBusy } from "store/hooks";
+import { useAppSelector } from "store/hooks";
import BitcoinIcon from "../../icons/BitcoinIcon";
import InfoBox from "../../modal/swap/InfoBox";
import WithdrawDialog from "../../modal/wallet/WithdrawDialog";
@@ -20,7 +20,6 @@ const useStyles = makeStyles((theme) => ({
export default function WithdrawWidget() {
const classes = useStyles();
const walletBalance = useAppSelector((state) => state.rpc.state.balance);
- const checkingBalance = useIsRpcEndpointBusy(RpcMethod.GET_BTC_BALANCE);
const [showDialog, setShowDialog] = useState(false);
function onShowDialog() {
@@ -50,7 +49,7 @@ export default function WithdrawWidget() {
size="large"
onClick={onShowDialog}
disabled={
- walletBalance === null || checkingBalance || walletBalance <= 0
+ walletBalance === null || walletBalance <= 0
}
>
Withdraw
diff --git a/src-gui/src/renderer/rpc.ts b/src-gui/src/renderer/rpc.ts
index 9005a0aa..76ee9796 100644
--- a/src-gui/src/renderer/rpc.ts
+++ b/src-gui/src/renderer/rpc.ts
@@ -5,6 +5,7 @@ import {
BalanceResponse,
BuyXmrArgs,
BuyXmrResponse,
+ CliLogEmittedEvent,
GetLogsArgs,
GetLogsResponse,
GetSwapInfoResponse,
@@ -20,6 +21,7 @@ import {
} from "models/tauriModel";
import {
contextStatusEventReceived,
+ receivedCliLog,
rpcSetBalance,
rpcSetSwapInfo,
} from "store/features/rpcSlice";
@@ -47,6 +49,11 @@ export async function initEventListeners() {
console.log("Received context init progress event", event.payload);
store.dispatch(contextStatusEventReceived(event.payload));
});
+
+ listen("cli-log-emitted", (event) => {
+ console.log("Received cli log event", event.payload);
+ store.dispatch(receivedCliLog(event.payload))
+ })
}
async function invoke(
diff --git a/src-gui/src/store/features/rpcSlice.ts b/src-gui/src/store/features/rpcSlice.ts
index 4bebd3fe..085545a0 100644
--- a/src-gui/src/store/features/rpcSlice.ts
+++ b/src-gui/src/store/features/rpcSlice.ts
@@ -1,11 +1,14 @@
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { ExtendedProviderStatus, ProviderStatus } from "models/apiModel";
import {
+ CliLogEmittedEvent,
GetSwapInfoResponse,
TauriContextStatusEvent,
} from "models/tauriModel";
import { MoneroRecoveryResponse } from "../../models/rpcModel";
import { GetSwapInfoResponseExt } from "models/tauriModelExt";
+import { getLogsAndStringsFromRawFileString } from "utils/parseUtils";
+import { CliLog } from "models/cliModel";
interface State {
balance: number | null;
@@ -27,7 +30,7 @@ interface State {
export interface RPCSlice {
status: TauriContextStatusEvent | null;
state: State;
- busyEndpoints: string[];
+ logs: (CliLog | string)[];
}
const initialState: RPCSlice = {
@@ -42,13 +45,18 @@ const initialState: RPCSlice = {
updateState: false,
},
},
- busyEndpoints: [],
+ logs: [],
};
export const rpcSlice = createSlice({
name: "rpc",
initialState,
reducers: {
+ receivedCliLog(slice, action: PayloadAction) {
+ const buffer = action.payload.buffer;
+ const logs = getLogsAndStringsFromRawFileString(buffer);
+ slice.logs = slice.logs.concat(logs);
+ },
contextStatusEventReceived(
slice,
action: PayloadAction,
@@ -74,17 +82,6 @@ export const rpcSlice = createSlice({
slice.state.swapInfos[action.payload.swap_id] =
action.payload as GetSwapInfoResponseExt;
},
- rpcSetEndpointBusy(slice, action: PayloadAction) {
- if (!slice.busyEndpoints.includes(action.payload)) {
- slice.busyEndpoints.push(action.payload);
- }
- },
- rpcSetEndpointFree(slice, action: PayloadAction) {
- const index = slice.busyEndpoints.indexOf(action.payload);
- if (index >= 0) {
- slice.busyEndpoints.splice(index);
- }
- },
rpcSetMoneroRecoveryKeys(
slice,
action: PayloadAction<[string, MoneroRecoveryResponse]>,
@@ -105,11 +102,10 @@ export const rpcSlice = createSlice({
export const {
contextStatusEventReceived,
+ receivedCliLog,
rpcSetBalance,
rpcSetWithdrawTxId,
rpcResetWithdrawTxId,
- rpcSetEndpointBusy,
- rpcSetEndpointFree,
rpcSetRendezvousDiscoveredProviders,
rpcSetSwapInfo,
rpcSetMoneroRecoveryKeys,
diff --git a/src-gui/src/store/hooks.ts b/src-gui/src/store/hooks.ts
index de956687..47d03a20 100644
--- a/src-gui/src/store/hooks.ts
+++ b/src-gui/src/store/hooks.ts
@@ -42,10 +42,6 @@ export function useActiveSwapInfo() {
return useSwapInfo(swapId);
}
-export function useIsRpcEndpointBusy(method: string) {
- return useAppSelector((state) => state.rpc.busyEndpoints.includes(method));
-}
-
export function useAllProviders() {
return useAppSelector((state) => {
const registryProviders = state.providers.registry.providers || [];
diff --git a/src-gui/src/utils/parseUtils.ts b/src-gui/src/utils/parseUtils.ts
index d4badd8e..12c9cfab 100644
--- a/src-gui/src/utils/parseUtils.ts
+++ b/src-gui/src/utils/parseUtils.ts
@@ -1,4 +1,4 @@
-import { CliLog } from "models/cliModel";
+import { CliLog, parseCliLogString } from "models/cliModel";
import { Multiaddr } from "multiaddr";
/*
@@ -55,19 +55,7 @@ export function getLinesOfString(data: string): string[] {
export function getLogsAndStringsFromRawFileString(
rawFileData: string,
): (CliLog | string)[] {
- return getLinesOfString(rawFileData).map((line) => {
- try {
- return JSON.parse(line);
- } catch {
- return line;
- }
- });
-}
-
-export function getLogsFromRawFileString(rawFileData: string): CliLog[] {
- // TODO: Reimplement this using Tauri
- return [];
- return getLogsAndStringsFromRawFileString(rawFileData).filter(isCliLog);
+ return getLinesOfString(rawFileData).map(parseCliLogString);
}
export function logsToRawString(logs: (CliLog | string)[]): string {
diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs
index 141f28bc..e1f0bb27 100644
--- a/src-tauri/src/lib.rs
+++ b/src-tauri/src/lib.rs
@@ -138,15 +138,12 @@ fn setup(app: &mut tauri::App) -> Result<(), Box> {
match context {
Ok(context) => {
let state = app_handle.state::>();
-
state.write().await.set_context(Arc::new(context));
-
// To display to the user that the setup is done, we emit an event to the Tauri frontend
tauri_handle.emit_context_init_progress_event(TauriContextStatusEvent::Available);
}
Err(e) => {
println!("Error while initializing context: {:?}", e);
-
// To display to the user that the setup failed, we emit an event to the Tauri frontend
tauri_handle.emit_context_init_progress_event(TauriContextStatusEvent::Failed);
}
@@ -182,7 +179,8 @@ pub fn run() {
RunEvent::Exit | RunEvent::ExitRequested { .. } => {
// Here we cleanup the Context when the application is closed
// This is necessary to among other things stop the monero-wallet-rpc process
- // If the application is forcibly closed, this may not be called
+ // If the application is forcibly closed, this may not be called.
+ // TODO: fix that
let context = app.state::>().inner().try_read();
match context {
diff --git a/swap/src/bin/asb.rs b/swap/src/bin/asb.rs
index 84fefc66..7d021b35 100644
--- a/swap/src/bin/asb.rs
+++ b/swap/src/bin/asb.rs
@@ -81,7 +81,8 @@ pub async fn main() -> Result<()> {
// initialize tracing
let format = if json { Format::Json } else { Format::Raw };
let log_dir = config.data.dir.join("logs");
- common::tracing_util::init(LevelFilter::DEBUG, format, log_dir).expect("initialize tracing");
+ common::tracing_util::init(LevelFilter::DEBUG, format, log_dir, None)
+ .expect("initialize tracing");
// check for conflicting env / config values
if config.monero.network != env_config.monero_network {
diff --git a/swap/src/cli/api.rs b/swap/src/cli/api.rs
index e32764eb..7c3e3d21 100644
--- a/swap/src/cli/api.rs
+++ b/swap/src/cli/api.rs
@@ -288,7 +288,12 @@ impl ContextBuilder {
};
START.call_once(|| {
- let _ = common::tracing_util::init(level_filter, format, data_dir.join("logs"));
+ let _ = common::tracing_util::init(
+ level_filter,
+ format,
+ data_dir.join("logs"),
+ self.tauri_handle.clone(),
+ );
});
let seed = Seed::from_file_or_generate(data_dir.as_path())
diff --git a/swap/src/cli/api/tauri_bindings.rs b/swap/src/cli/api/tauri_bindings.rs
index 675dd329..d10ee328 100644
--- a/swap/src/cli/api/tauri_bindings.rs
+++ b/swap/src/cli/api/tauri_bindings.rs
@@ -6,8 +6,9 @@ use strum::Display;
use typeshare::typeshare;
use uuid::Uuid;
-static SWAP_PROGRESS_EVENT_NAME: &str = "swap-progress-update";
-static CONTEXT_INIT_PROGRESS_EVENT_NAME: &str = "context-init-progress-update";
+const SWAP_PROGRESS_EVENT_NAME: &str = "swap-progress-update";
+const CONTEXT_INIT_PROGRESS_EVENT_NAME: &str = "context-init-progress-update";
+const CLI_LOG_EMITTED_EVENT_NAME: &str = "cli-log-emitted";
#[derive(Debug, Clone)]
pub struct TauriHandle(
@@ -47,6 +48,12 @@ pub trait TauriEmitter {
fn emit_context_init_progress_event(&self, event: TauriContextStatusEvent) {
let _ = self.emit_tauri_event(CONTEXT_INIT_PROGRESS_EVENT_NAME, event);
}
+
+ fn emit_cli_log_event(&self, event: CliLogEmittedEvent) {
+ let _ = self
+ .emit_tauri_event(CLI_LOG_EMITTED_EVENT_NAME, event)
+ .ok();
+ }
}
impl TauriEmitter for TauriHandle {
@@ -158,3 +165,14 @@ pub enum TauriSwapProgressEvent {
},
Released,
}
+
+/// This event is emitted whenever there is a log message issued in the CLI.
+///
+/// It contains a json serialized object containing the log message and metadata.
+#[typeshare]
+#[derive(Debug, Serialize, Clone)]
+#[typeshare]
+pub struct CliLogEmittedEvent {
+ /// The serialized object containing the log message and metadata.
+ pub buffer: String
+}
diff --git a/swap/src/common/tracing_util.rs b/swap/src/common/tracing_util.rs
index 191c43bf..8be333ab 100644
--- a/swap/src/common/tracing_util.rs
+++ b/swap/src/common/tracing_util.rs
@@ -1,13 +1,17 @@
+use std::io;
use std::path::Path;
use std::str::FromStr;
use anyhow::Result;
use tracing_subscriber::filter::{Directive, LevelFilter};
use tracing_subscriber::fmt::time::UtcTime;
+use tracing_subscriber::fmt::MakeWriter;
use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::util::SubscriberInitExt;
use tracing_subscriber::{fmt, EnvFilter, Layer};
+use crate::cli::api::tauri_bindings::{CliLogEmittedEvent, TauriEmitter, TauriHandle};
+
/// Output formats for logging messages.
pub enum Format {
/// Standard, human readable format.
@@ -20,11 +24,12 @@ pub enum Format {
/// Besides printing to `stdout`, this will append to a log file.
/// Said file will contain JSON-formatted logs of all levels,
/// disregarding the arguments to this function.
-pub fn init(level_filter: LevelFilter, format: Format, dir: impl AsRef) -> Result<()> {
- let env_filter = EnvFilter::from_default_env()
- .add_directive(Directive::from_str(&format!("asb={}", &level_filter))?)
- .add_directive(Directive::from_str(&format!("swap={}", &level_filter))?);
-
+pub fn init(
+ level_filter: LevelFilter,
+ format: Format,
+ dir: impl AsRef,
+ tauri_handle: Option,
+) -> Result<()> {
// file logger will always write in JSON format and with timestamps
let file_appender = tracing_appender::rolling::never(&dir, "swap-all.log");
@@ -34,9 +39,9 @@ pub fn init(level_filter: LevelFilter, format: Format, dir: impl AsRef) ->
.with_timer(UtcTime::rfc_3339())
.with_target(false)
.json()
- .with_filter(env_filter);
+ .with_filter(env_filter(level_filter)?);
- // terminal logger
+ // terminal loger
let is_terminal = atty::is(atty::Stream::Stderr);
let terminal_layer = fmt::layer()
.with_writer(std::io::stdout)
@@ -44,21 +49,83 @@ pub fn init(level_filter: LevelFilter, format: Format, dir: impl AsRef) ->
.with_timer(UtcTime::rfc_3339())
.with_target(false);
+ // tauri layer (forwards logs to the tauri guest when connected)
+ let tauri_layer = fmt::layer()
+ .with_writer(TauriWriter::new(tauri_handle))
+ .with_ansi(false)
+ .with_timer(UtcTime::rfc_3339())
+ .with_target(false)
+ .json()
+ .with_filter(env_filter(level_filter)?);
+
// combine the layers and start logging, format with json if specified
if let Format::Json = format {
tracing_subscriber::registry()
.with(file_layer)
+ .with(tauri_layer)
.with(terminal_layer.json().with_filter(level_filter))
.init();
} else {
tracing_subscriber::registry()
.with(file_layer)
+ .with(tauri_layer)
.with(terminal_layer.with_filter(level_filter))
.init();
}
- // now we can use the tracing macros to log messages
+ // Now we can use the tracing macros to log messages
tracing::info!(%level_filter, logs_dir=%dir.as_ref().display(), "Initialized tracing");
Ok(())
}
+
+/// This function controls which crate's logs actually get logged and from which level.
+fn env_filter(level_filter: LevelFilter) -> Result {
+ Ok(EnvFilter::from_default_env()
+ .add_directive(Directive::from_str(&format!("asb={}", &level_filter))?)
+ .add_directive(Directive::from_str(&format!("swap={}", &level_filter))?))
+}
+
+/// A writer that forwards tracing log messages to the tauri guest.
+#[derive(Clone)]
+pub struct TauriWriter {
+ tauri_handle: Option,
+}
+
+impl TauriWriter {
+ /// Create a new Tauri writer that sends log messages to the tauri guest.
+ pub fn new(tauri_handle: Option) -> Self {
+ Self { tauri_handle }
+ }
+}
+
+/// This is needed for tracing to accept this as a writer.
+impl<'a> MakeWriter<'a> for TauriWriter {
+ type Writer = TauriWriter;
+
+ fn make_writer(&'a self) -> Self::Writer {
+ self.clone()
+ }
+}
+
+/// For every write issued by tracing we simply pass the string on as an event to the tauri guest.
+impl std::io::Write for TauriWriter {
+ fn write(&mut self, buf: &[u8]) -> std::io::Result {
+ // Since this function accepts bytes, we need to pass to utf8 first
+ let owned_buf = buf.to_owned();
+ let utf8_string = String::from_utf8(owned_buf)
+ .map_err(|err| io::Error::new(io::ErrorKind::InvalidInput, err))?;
+
+ // Then send to tauri
+ self.tauri_handle.emit_cli_log_event(CliLogEmittedEvent {
+ buffer: utf8_string,
+ });
+
+ Ok(buf.len())
+ }
+
+ fn flush(&mut self) -> std::io::Result<()> {
+ // No-op, we don't need to flush anything
+ Ok(())
+ }
+}