wip: WithdrawDialog migrated to Tauri IPC

This commit is contained in:
binarybaron 2024-08-09 19:03:28 +02:00
parent 92034a5be8
commit 47821cbe79
No known key found for this signature in database
GPG key ID: 99B75D3E1476A26E
14 changed files with 185 additions and 166 deletions

View file

@ -6,6 +6,7 @@ import { ReactNode, useEffect, useState } from "react";
interface IpcInvokeButtonProps<T> { interface IpcInvokeButtonProps<T> {
onSuccess?: (data: T) => void; onSuccess?: (data: T) => void;
onClick: () => Promise<T>; onClick: () => Promise<T>;
onPendingChange?: (bool) => void;
isLoadingOverride?: boolean; isLoadingOverride?: boolean;
isIconButton?: boolean; isIconButton?: boolean;
loadIcon?: ReactNode; loadIcon?: ReactNode;
@ -24,26 +25,22 @@ export default function PromiseInvokeButton<T>({
isIconButton, isIconButton,
displayErrorSnackbar, displayErrorSnackbar,
tooltipTitle, tooltipTitle,
onPendingChange,
...rest ...rest
}: IpcInvokeButtonProps<T> & ButtonProps) { }: IpcInvokeButtonProps<T> & ButtonProps) {
const { enqueueSnackbar } = useSnackbar(); const { enqueueSnackbar } = useSnackbar();
const [isPending, setIsPending] = useState(false); const [isPending, setIsPending] = useState(false);
const [hasMinLoadingTimePassed, setHasMinLoadingTimePassed] = useState(false);
const isLoading = (isPending && hasMinLoadingTimePassed) || isLoadingOverride; const isLoading = isPending || isLoadingOverride;
const actualEndIcon = isLoading const actualEndIcon = isLoading
? loadIcon || <CircularProgress size="1em" /> ? loadIcon || <CircularProgress size="1em" />
: endIcon; : endIcon;
useEffect(() => {
setHasMinLoadingTimePassed(false);
setTimeout(() => setHasMinLoadingTimePassed(true), 100);
}, [isPending]);
async function handleClick(event: React.MouseEvent<HTMLButtonElement>) { async function handleClick(event: React.MouseEvent<HTMLButtonElement>) {
if (!isPending) { if (!isPending) {
try { try {
onPendingChange?.(true);
setIsPending(true); setIsPending(true);
let result = await onClick(); let result = await onClick();
onSuccess?.(result); onSuccess?.(result);
@ -56,21 +53,15 @@ export default function PromiseInvokeButton<T>({
} }
} finally { } finally {
setIsPending(false); setIsPending(false);
onPendingChange?.(false);
} }
} }
} }
const isDisabled = disabled || isLoading; const isDisabled = disabled || isLoading;
return ( return isIconButton ? (
<Tooltip title={tooltipTitle}> <IconButton onClick={handleClick} disabled={isDisabled} {...(rest as any)}>
<span>
{isIconButton ? (
<IconButton
onClick={handleClick}
disabled={isDisabled}
{...(rest as any)}
>
{actualEndIcon} {actualEndIcon}
</IconButton> </IconButton>
) : ( ) : (
@ -80,8 +71,5 @@ export default function PromiseInvokeButton<T>({
endIcon={actualEndIcon} endIcon={actualEndIcon}
{...rest} {...rest}
/> />
)}
</span>
</Tooltip>
); );
} }

View file

@ -1,9 +1,14 @@
import { Dialog } from '@material-ui/core'; import { Button, Dialog, DialogActions } from "@material-ui/core";
import { useAppDispatch, useIsRpcEndpointBusy } from 'store/hooks'; import { useAppDispatch, useIsRpcEndpointBusy } from "store/hooks";
import { RpcMethod } from 'models/rpcModel'; import { RpcMethod } from "models/rpcModel";
import { rpcResetWithdrawTxId } from 'store/features/rpcSlice'; import { rpcResetWithdrawTxId } from "store/features/rpcSlice";
import WithdrawStatePage from './WithdrawStatePage'; import WithdrawStatePage from "./WithdrawStatePage";
import DialogHeader from '../DialogHeader'; import DialogHeader from "../DialogHeader";
import PromiseInvokeButton from "renderer/components/PromiseInvokeButton";
import { useState } from "react";
import { withdrawBtc } from "renderer/rpc";
import BtcTxInMempoolPageContent from "./pages/BitcoinWithdrawTxInMempoolPage";
import AddressInputPage from "./pages/AddressInputPage";
export default function WithdrawDialog({ export default function WithdrawDialog({
open, open,
@ -12,23 +17,60 @@ export default function WithdrawDialog({
open: boolean; open: boolean;
onClose: () => void; onClose: () => void;
}) { }) {
const isRpcEndpointBusy = useIsRpcEndpointBusy(RpcMethod.WITHDRAW_BTC); const [pending, setPending] = useState(false);
const dispatch = useAppDispatch(); const [withdrawTxId, setWithdrawTxId] = useState<string | null>(null);
const [withdrawAddressValid, setWithdrawAddressValid] = useState(false);
const [withdrawAddress, setWithdrawAddress] = useState<string>("");
function onCancel() { function onCancel() {
if (!isRpcEndpointBusy) { if (!pending) {
setWithdrawTxId(null);
setWithdrawAddress("");
onClose(); onClose();
dispatch(rpcResetWithdrawTxId());
} }
} }
// This prevents an issue where the Dialog is shown for a split second without a present withdraw state // This prevents an issue where the Dialog is shown for a split second without a present withdraw state
if (!open && !isRpcEndpointBusy) return null; if (!open) return null;
return ( return (
<Dialog open onClose={onCancel} maxWidth="sm" fullWidth> <Dialog open onClose={onCancel} maxWidth="sm" fullWidth>
<DialogHeader title="Withdraw Bitcoin" /> <DialogHeader title="Withdraw Bitcoin" />
<WithdrawStatePage onCancel={onCancel} /> {withdrawTxId === null ? (
<AddressInputPage
setWithdrawAddress={setWithdrawAddress}
withdrawAddress={withdrawAddress}
setWithdrawAddressValid={setWithdrawAddressValid}
/>
) : (
<BtcTxInMempoolPageContent
withdrawTxId={withdrawTxId}
onCancel={onCancel}
/>
)}
<DialogActions>
{withdrawTxId === null ? (
<PromiseInvokeButton
variant="contained"
color="primary"
disabled={!withdrawAddressValid}
onClick={() => withdrawBtc(withdrawAddress)}
onPendingChange={(pending) => {
console.log("pending", pending);
setPending(pending);
}}
onSuccess={(txId) => {
setWithdrawTxId(txId);
}}
>
Withdraw
</PromiseInvokeButton>
) : (
<Button onClick={onCancel} color="primary" disabled={pending}>
Close
</Button>
)}
</DialogActions>
</Dialog> </Dialog>
); );
} }

View file

@ -1,17 +1,18 @@
import { useState } from 'react'; import { useState } from "react";
import { Button, DialogActions, DialogContentText } from '@material-ui/core'; import { Button, DialogActions, DialogContentText } from "@material-ui/core";
import BitcoinAddressTextField from '../../../inputs/BitcoinAddressTextField'; import BitcoinAddressTextField from "../../../inputs/BitcoinAddressTextField";
import WithdrawDialogContent from '../WithdrawDialogContent'; import WithdrawDialogContent from "../WithdrawDialogContent";
import IpcInvokeButton from '../../../IpcInvokeButton'; import IpcInvokeButton from "../../../IpcInvokeButton";
export default function AddressInputPage({ export default function AddressInputPage({
onCancel, withdrawAddress,
setWithdrawAddress,
setWithdrawAddressValid,
}: { }: {
onCancel: () => void; withdrawAddress: string;
setWithdrawAddress: (address: string) => void;
setWithdrawAddressValid: (valid: boolean) => void;
}) { }) {
const [withdrawAddressValid, setWithdrawAddressValid] = useState(false);
const [withdrawAddress, setWithdrawAddress] = useState('');
return ( return (
<> <>
<WithdrawDialogContent> <WithdrawDialogContent>
@ -28,22 +29,6 @@ export default function AddressInputPage({
fullWidth fullWidth
/> />
</WithdrawDialogContent> </WithdrawDialogContent>
<DialogActions>
<Button onClick={onCancel} variant="text">
Cancel
</Button>
<IpcInvokeButton
disabled={!withdrawAddressValid}
ipcChannel="spawn-withdraw-btc"
ipcArgs={[withdrawAddress]}
color="primary"
variant="contained"
requiresRpc
>
Withdraw
</IpcInvokeButton>
</DialogActions>
</> </>
); );
} }

View file

@ -1,6 +1,6 @@
import { Button, DialogActions, DialogContentText } from '@material-ui/core'; import { Button, DialogActions, DialogContentText } from "@material-ui/core";
import BitcoinTransactionInfoBox from '../../swap/BitcoinTransactionInfoBox'; import BitcoinTransactionInfoBox from "../../swap/BitcoinTransactionInfoBox";
import WithdrawDialogContent from '../WithdrawDialogContent'; import WithdrawDialogContent from "../WithdrawDialogContent";
export default function BtcTxInMempoolPageContent({ export default function BtcTxInMempoolPageContent({
withdrawTxId, withdrawTxId,
@ -23,14 +23,6 @@ export default function BtcTxInMempoolPageContent({
additionalContent={null} additionalContent={null}
/> />
</WithdrawDialogContent> </WithdrawDialogContent>
<DialogActions>
<Button onClick={onCancel} variant="text">
Cancel
</Button>
<Button onClick={onCancel} color="primary" variant="contained">
Done
</Button>
</DialogActions>
</> </>
); );
} }

View file

@ -1,21 +0,0 @@
import { Button, DialogActions } from '@material-ui/core';
import CircularProgressWithSubtitle from '../../swap/CircularProgressWithSubtitle';
import WithdrawDialogContent from '../WithdrawDialogContent';
export default function InitiatedPage({ onCancel }: { onCancel: () => void }) {
return (
<>
<WithdrawDialogContent>
<CircularProgressWithSubtitle description="Withdrawing Bitcoin" />
</WithdrawDialogContent>
<DialogActions>
<Button onClick={onCancel} variant="text">
Cancel
</Button>
<Button disabled color="primary" variant="contained">
Done
</Button>
</DialogActions>
</>
);
}

View file

@ -3,7 +3,6 @@ import { store } from "./store/storeRenderer";
import { rpcSetBalance, rpcSetSwapInfo } from "store/features/rpcSlice"; import { rpcSetBalance, rpcSetSwapInfo } from "store/features/rpcSlice";
export async function checkBitcoinBalance() { export async function checkBitcoinBalance() {
// TODO: use tauri-bindgen here
const response = (await invoke("get_balance")) as { const response = (await invoke("get_balance")) as {
balance: number; balance: number;
}; };
@ -16,3 +15,17 @@ export async function getRawSwapInfos() {
(response as any[]).forEach((info) => store.dispatch(rpcSetSwapInfo(info))); (response as any[]).forEach((info) => store.dispatch(rpcSetSwapInfo(info)));
} }
export async function withdrawBtc(address: string): Promise<string> {
const response = (await invoke("withdraw_btc", {
args: {
address,
amount: null,
},
})) as {
txid: string;
amount: number;
};
return response.txid;
}

View file

@ -1,18 +1,15 @@
import { ExtendedProviderStatus } from 'models/apiModel'; import { ExtendedProviderStatus } from "models/apiModel";
export const isTestnet = () => export const isTestnet = () => true;
false
export const isExternalRpc = () => export const isExternalRpc = () => true;
true
export const isDevelopment = export const isDevelopment = true;
true
export function getStubTestnetProvider(): ExtendedProviderStatus | null { export function getStubTestnetProvider(): ExtendedProviderStatus | null {
return null; return null;
} }
export const getPlatform = () => { export const getPlatform = () => {
return 'mac'; return "mac";
}; };

View file

@ -1,20 +1,17 @@
use std::sync::Arc;
use once_cell::sync::OnceCell;
use std::result::Result; use std::result::Result;
use std::sync::Arc;
use swap::{ use swap::{
api::{ api::{
request::{ request::{
get_balance as get_balance_impl, get_swap_infos_all as get_swap_infos_all_impl, get_balance as get_balance_impl, get_swap_infos_all as get_swap_infos_all_impl,
BalanceArgs, BalanceResponse, GetSwapInfoResponse, withdraw_btc as withdraw_btc_impl, BalanceArgs, BalanceResponse, GetSwapInfoResponse,
WithdrawBtcArgs, WithdrawBtcResponse,
}, },
Context, Context,
}, },
cli::command::{Bitcoin, Monero}, cli::command::{Bitcoin, Monero},
}; };
use tauri::{Manager, State};
// Lazy load the Context
static CONTEXT: OnceCell<Arc<Context>> = OnceCell::new();
trait ToStringResult<T> { trait ToStringResult<T> {
fn to_string_result(self) -> Result<T, String>; fn to_string_result(self) -> Result<T, String>;
@ -31,24 +28,46 @@ impl<T, E: ToString> ToStringResult<T> for Result<T, E> {
} }
#[tauri::command] #[tauri::command]
async fn get_balance() -> Result<BalanceResponse, String> { async fn get_balance(context: State<'_, Arc<Context>>) -> Result<BalanceResponse, String> {
let context = CONTEXT.get().unwrap();
get_balance_impl( get_balance_impl(
BalanceArgs { BalanceArgs {
force_refresh: true, force_refresh: true,
}, },
context.clone(), context.inner().clone(),
) )
.await .await
.to_string_result() .to_string_result()
} }
#[tauri::command] #[tauri::command]
async fn get_swap_infos_all() -> Result<Vec<GetSwapInfoResponse>, String> { async fn get_swap_infos_all(
let context = CONTEXT.get().unwrap(); context: State<'_, Arc<Context>>,
) -> Result<Vec<GetSwapInfoResponse>, String> {
get_swap_infos_all_impl(context.inner().clone())
.await
.to_string_result()
}
get_swap_infos_all_impl(context.clone()) /*macro_rules! tauri_command {
($command_name:ident, $command_args:ident, $command_response:ident) => {
#[tauri::command]
async fn $command_name(
context: State<'_, Context>,
args: $command_args,
) -> Result<$command_response, String> {
swap::api::request::$command_name(args, context)
.await
.to_string_result()
}
};
}*/
#[tauri::command]
async fn withdraw_btc(
context: State<'_, Arc<Context>>,
args: WithdrawBtcArgs,
) -> Result<WithdrawBtcResponse, String> {
withdraw_btc_impl(args, context.inner().clone())
.await .await
.to_string_result() .to_string_result()
} }
@ -73,9 +92,7 @@ fn setup<'a>(app: &'a mut tauri::App) -> Result<(), Box<dyn std::error::Error>>
.await .await
.unwrap(); .unwrap();
CONTEXT app.manage(Arc::new(context));
.set(Arc::new(context))
.expect("Failed to initialize cli context");
}); });
Ok(()) Ok(())
@ -84,7 +101,11 @@ fn setup<'a>(app: &'a mut tauri::App) -> Result<(), Box<dyn std::error::Error>>
#[cfg_attr(mobile, tauri::mobile_entry_point)] #[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() { pub fn run() {
tauri::Builder::default() tauri::Builder::default()
.invoke_handler(tauri::generate_handler![get_balance, get_swap_infos_all]) .invoke_handler(tauri::generate_handler![
get_balance,
get_swap_infos_all,
withdraw_btc
])
.setup(setup) .setup(setup)
.run(tauri::generate_context!()) .run(tauri::generate_context!())
.expect("error while running tauri application"); .expect("error while running tauri application");

View file

@ -21,7 +21,7 @@ use std::future::Future;
use std::net::SocketAddr; use std::net::SocketAddr;
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use tracing::{debug_span, field, Instrument, Span}; use tracing::Instrument;
use uuid::Uuid; use uuid::Uuid;
#[derive(PartialEq, Debug)] #[derive(PartialEq, Debug)]
@ -53,9 +53,9 @@ pub struct MoneroRecoveryArgs {
pub swap_id: Uuid, pub swap_id: Uuid,
} }
#[derive(Debug, Eq, PartialEq)] #[derive(Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct WithdrawBtcArgs { pub struct WithdrawBtcArgs {
pub amount: Option<Amount>, pub amount: Option<u64>,
pub address: bitcoin::Address, pub address: bitcoin::Address,
} }
@ -119,6 +119,12 @@ pub struct GetSwapInfoResponse {
pub timelock: Option<ExpiredTimelocks>, pub timelock: Option<ExpiredTimelocks>,
} }
#[derive(Serialize, Deserialize, Debug)]
pub struct WithdrawBtcResponse {
amount: u64,
txid: String,
}
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct Seller { pub struct Seller {
pub peer_id: String, pub peer_id: String,
@ -645,7 +651,7 @@ pub async fn get_config(context: Arc<Context>) -> Result<serde_json::Value> {
pub async fn withdraw_btc( pub async fn withdraw_btc(
withdraw_btc: WithdrawBtcArgs, withdraw_btc: WithdrawBtcArgs,
context: Arc<Context>, context: Arc<Context>,
) -> Result<serde_json::Value> { ) -> Result<WithdrawBtcResponse> {
let WithdrawBtcArgs { address, amount } = withdraw_btc; let WithdrawBtcArgs { address, amount } = withdraw_btc;
let bitcoin_wallet = context let bitcoin_wallet = context
.bitcoin_wallet .bitcoin_wallet
@ -653,7 +659,7 @@ pub async fn withdraw_btc(
.context("Could not get Bitcoin wallet")?; .context("Could not get Bitcoin wallet")?;
let amount = match amount { let amount = match amount {
Some(amount) => amount, Some(amount) => Amount::from_sat(amount),
None => { None => {
bitcoin_wallet bitcoin_wallet
.max_giveable(address.script_pubkey().len()) .max_giveable(address.script_pubkey().len())
@ -669,11 +675,10 @@ pub async fn withdraw_btc(
.broadcast(signed_tx.clone(), "withdraw") .broadcast(signed_tx.clone(), "withdraw")
.await?; .await?;
Ok(json!({ Ok(WithdrawBtcResponse {
"signed_tx": signed_tx, txid: signed_tx.txid().to_string(),
"amount": amount.to_sat(), amount: amount.to_sat(),
"txid": signed_tx.txid(), })
}))
} }
#[tracing::instrument(fields(method = "start_daemon"), skip(context))] #[tracing::instrument(fields(method = "start_daemon"), skip(context))]
@ -848,17 +853,7 @@ impl Request {
} }
} }
async fn handle_cmd(self, context: Arc<Context>) -> Result<Box<dyn erased_serde::Serialize>> { pub async fn call(self, _: Arc<Context>) -> Result<JsonValue> {
match self.cmd {
Method::Balance(args) => {
let response = get_balance(args, context).await?;
Ok(Box::new(response) as Box<dyn erased_serde::Serialize>)
}
_ => todo!(),
}
}
pub async fn call(self, context: Arc<Context>) -> Result<JsonValue> {
unreachable!("This function should never be called") unreachable!("This function should never be called")
} }
} }

View file

@ -1,7 +1,6 @@
#![warn( #![warn(
unused_extern_crates, unused_extern_crates,
missing_copy_implementations, missing_copy_implementations,
rust_2018_idioms,
clippy::cast_possible_truncation, clippy::cast_possible_truncation,
clippy::cast_sign_loss, clippy::cast_sign_loss,
clippy::fallible_impl_from, clippy::fallible_impl_from,
@ -12,8 +11,10 @@
#![forbid(unsafe_code)] #![forbid(unsafe_code)]
#![allow(non_snake_case)] #![allow(non_snake_case)]
use crate::cli::command::{parse_args_and_apply_defaults, ParseResult}; use crate::{
use crate::common::check_latest_version; cli::command::{parse_args_and_apply_defaults, ParseResult},
common::check_latest_version,
};
use anyhow::Result; use anyhow::Result;
use std::env; use std::env;

View file

@ -1,8 +1,8 @@
use crate::api::request::{ use crate::api::request::{
buy_xmr, cancel_and_refund, export_bitcoin_wallet, get_balance, get_config, get_history, buy_xmr, cancel_and_refund, export_bitcoin_wallet, get_balance, get_config, get_history,
list_sellers, monero_recovery, resume_swap, start_daemon, withdraw_btc, BalanceArgs, list_sellers, monero_recovery, resume_swap, start_daemon, withdraw_btc, BalanceArgs,
BuyXmrArgs, CancelAndRefundArgs, ListSellersArgs, Method, MoneroRecoveryArgs, Request, BuyXmrArgs, CancelAndRefundArgs, ListSellersArgs, MoneroRecoveryArgs, ResumeArgs,
ResumeArgs, StartDaemonArgs, WithdrawBtcArgs, StartDaemonArgs, WithdrawBtcArgs,
}; };
use crate::api::Context; use crate::api::Context;
use crate::bitcoin::{bitcoin_address, Amount}; use crate::bitcoin::{bitcoin_address, Amount};
@ -10,7 +10,6 @@ use crate::monero;
use crate::monero::monero_address; use crate::monero::monero_address;
use anyhow::Result; use anyhow::Result;
use libp2p::core::Multiaddr; use libp2p::core::Multiaddr;
use serde_json::Value;
use std::ffi::OsString; use std::ffi::OsString;
use std::net::SocketAddr; use std::net::SocketAddr;
use std::path::PathBuf; use std::path::PathBuf;
@ -193,7 +192,14 @@ where
.await?, .await?,
); );
withdraw_btc(WithdrawBtcArgs { amount, address }, context).await?; withdraw_btc(
WithdrawBtcArgs {
amount: amount.map(Amount::to_sat),
address,
},
context,
)
.await?;
Ok(()) Ok(())
} }

View file

@ -1,11 +1,11 @@
use crate::api::Context; use crate::api::Context;
use std::{net::SocketAddr, sync::Arc}; use std::net::SocketAddr;
use thiserror::Error; use thiserror::Error;
use tower_http::cors::CorsLayer; use tower_http::cors::CorsLayer;
use jsonrpsee::{ use jsonrpsee::{
core::server::host_filtering::AllowHosts, core::server::host_filtering::AllowHosts,
server::{RpcModule, ServerBuilder, ServerHandle}, server::{ServerBuilder, ServerHandle},
}; };
pub mod methods; pub mod methods;

View file

@ -13,7 +13,6 @@ use jsonrpsee::server::RpcModule;
use libp2p::core::Multiaddr; use libp2p::core::Multiaddr;
use std::collections::HashMap; use std::collections::HashMap;
use std::str::FromStr; use std::str::FromStr;
use std::sync::Arc;
use uuid::Uuid; use uuid::Uuid;
trait ConvertToJsonRpseeError<T> { trait ConvertToJsonRpseeError<T> {
@ -29,7 +28,7 @@ impl<T> ConvertToJsonRpseeError<T> for Result<T, anyhow::Error> {
pub fn register_modules(outer_context: Context) -> Result<RpcModule<Context>> { pub fn register_modules(outer_context: Context) -> Result<RpcModule<Context>> {
let mut module = RpcModule::new(outer_context); let mut module = RpcModule::new(outer_context);
module.register_async_method("suspend_current_swap", |params, context| async move { module.register_async_method("suspend_current_swap", |_, context| async move {
suspend_current_swap(context).await.to_jsonrpsee_result() suspend_current_swap(context).await.to_jsonrpsee_result()
})?; })?;
@ -66,11 +65,11 @@ pub fn register_modules(outer_context: Context) -> Result<RpcModule<Context>> {
.to_jsonrpsee_result() .to_jsonrpsee_result()
})?; })?;
module.register_async_method("get_history", |params, context| async move { module.register_async_method("get_history", |_, context| async move {
get_history(context).await.to_jsonrpsee_result() get_history(context).await.to_jsonrpsee_result()
})?; })?;
module.register_async_method("get_raw_states", |params, context| async move { module.register_async_method("get_raw_states", |_, context| async move {
get_raw_states(context).await.to_jsonrpsee_result() get_raw_states(context).await.to_jsonrpsee_result()
})?; })?;
@ -131,7 +130,8 @@ pub fn register_modules(outer_context: Context) -> Result<RpcModule<Context>> {
::bitcoin::Amount::from_str_in(amount_str, ::bitcoin::Denomination::Bitcoin) ::bitcoin::Amount::from_str_in(amount_str, ::bitcoin::Denomination::Bitcoin)
.map_err(|_| { .map_err(|_| {
jsonrpsee_core::Error::Custom("Unable to parse amount".to_string()) jsonrpsee_core::Error::Custom("Unable to parse amount".to_string())
})?, })?
.to_sat(),
) )
} else { } else {
None None
@ -224,7 +224,7 @@ pub fn register_modules(outer_context: Context) -> Result<RpcModule<Context>> {
.to_jsonrpsee_result() .to_jsonrpsee_result()
})?; })?;
module.register_async_method("get_current_swap", |params, context| async move { module.register_async_method("get_current_swap", |_, context| async move {
get_current_swap(context).await.to_jsonrpsee_result() get_current_swap(context).await.to_jsonrpsee_result()
})?; })?;