fixing formatting and cargo clippy warnings

This commit is contained in:
Lorenzo Tucci 2023-01-11 14:52:42 +01:00
parent 925c7bc179
commit 9d1a39b2ff
No known key found for this signature in database
GPG Key ID: D98C4FA2CDF590A0
13 changed files with 374 additions and 209 deletions

View File

@ -194,7 +194,7 @@ mod monero_serde_hex_block {
{ {
let hex = String::deserialize(deserializer)?; let hex = String::deserialize(deserializer)?;
let bytes = hex::decode(&hex).map_err(D::Error::custom)?; let bytes = hex::decode(hex).map_err(D::Error::custom)?;
let mut cursor = Cursor::new(bytes); let mut cursor = Cursor::new(bytes);
let block = monero::Block::consensus_decode(&mut cursor).map_err(D::Error::custom)?; let block = monero::Block::consensus_decode(&mut cursor).map_err(D::Error::custom)?;

View File

@ -79,17 +79,17 @@ zip = "0.5"
bitcoin-harness = "0.2.2" bitcoin-harness = "0.2.2"
get-port = "3" get-port = "3"
hyper = "0.14" hyper = "0.14"
monero-harness = { path = "../monero-harness" }
jsonrpsee = { version = "0.16.2", features = [ "ws-client" ] } jsonrpsee = { version = "0.16.2", features = [ "ws-client" ] }
jsonrpsee-types = { version = "0.16.2" } jsonrpsee-types = { version = "0.16.2" }
monero-harness = { path = "../monero-harness" }
port_check = "0.1" port_check = "0.1"
proptest = "1" proptest = "1"
sequential-test = "0.2.4"
serde_cbor = "0.11" serde_cbor = "0.11"
serial_test = "0.10" serial_test = "0.10"
spectral = "0.6" spectral = "0.6"
tempfile = "3" tempfile = "3"
testcontainers = "0.12" testcontainers = "0.12"
sequential-test = "0.2.4"
[build-dependencies] [build-dependencies]
anyhow = "1" anyhow = "1"

View File

@ -11,10 +11,9 @@ use anyhow::{Context as AnyContext, Result};
use std::fmt; use std::fmt;
use std::net::SocketAddr; use std::net::SocketAddr;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::{Arc}; use std::sync::{Arc, Once};
use url::Url;
use std::sync::Once;
use tokio::sync::{broadcast, Mutex}; use tokio::sync::{broadcast, Mutex};
use url::Url;
static START: Once = Once::new(); static START: Once = Once::new();
@ -42,7 +41,6 @@ pub struct Context {
pub shutdown: Arc<broadcast::Sender<()>>, pub shutdown: Arc<broadcast::Sender<()>>,
} }
impl Context { impl Context {
pub async fn build( pub async fn build(
bitcoin: Option<Bitcoin>, bitcoin: Option<Bitcoin>,
@ -91,19 +89,12 @@ impl Context {
} }
}; };
let tor_socks5_port = { let tor_socks5_port = tor.map(|tor| tor.tor_socks5_port);
if let Some(tor) = tor {
Some(tor.tor_socks5_port)
} else {
None
}
};
START.call_once(|| { START.call_once(|| {
let _ = cli::tracing::init(debug, json, data_dir.join("logs"), None); let _ = cli::tracing::init(debug, json, data_dir.join("logs"), None);
}); });
let init = Context { let init = Context {
db: open_db(data_dir.join("sqlite")).await?, db: open_db(data_dir.join("sqlite")).await?,
bitcoin_wallet, bitcoin_wallet,
@ -125,16 +116,14 @@ impl Context {
Ok(init) Ok(init)
} }
} }
impl fmt::Debug for Context { impl fmt::Debug for Context {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Testing {}", true) write!(f, "")
} }
} }
async fn init_bitcoin_wallet( async fn init_bitcoin_wallet(
electrum_rpc_url: Url, electrum_rpc_url: Url,
seed: &Seed, seed: &Seed,
@ -159,7 +148,6 @@ async fn init_bitcoin_wallet(
Ok(wallet) Ok(wallet)
} }
async fn init_monero_wallet( async fn init_monero_wallet(
data_dir: PathBuf, data_dir: PathBuf,
monero_daemon_address: String, monero_daemon_address: String,
@ -213,12 +201,12 @@ fn env_config_from(testnet: bool) -> EnvConfig {
} }
#[cfg(test)] #[cfg(test)]
pub mod api_test { pub mod api_test {
use crate::api::request::{Method, Params, Request, Shutdown};
use crate::tor::DEFAULT_SOCKS5_PORT; use crate::tor::DEFAULT_SOCKS5_PORT;
use std::str::FromStr;
use uuid::Uuid;
use crate::api::request::{Request, Params, Method, Shutdown};
use libp2p::Multiaddr; use libp2p::Multiaddr;
use std::str::FromStr;
use tokio::sync::broadcast; use tokio::sync::broadcast;
use uuid::Uuid;
pub const MULTI_ADDRESS: &str = pub const MULTI_ADDRESS: &str =
"/ip4/127.0.0.1/tcp/9939/p2p/12D3KooWCdMKjesXMJz1SiZ7HgotrxuqhQJbP5sgBm2BwP1cqThi"; "/ip4/127.0.0.1/tcp/9939/p2p/12D3KooWCdMKjesXMJz1SiZ7HgotrxuqhQJbP5sgBm2BwP1cqThi";
@ -251,7 +239,6 @@ pub mod api_test {
is_testnet, is_testnet,
} }
} }
} }
impl Request { impl Request {
pub fn buy_xmr(is_testnet: bool, tx: broadcast::Sender<()>) -> Request { pub fn buy_xmr(is_testnet: bool, tx: broadcast::Sender<()>) -> Request {

View File

@ -1,10 +1,11 @@
use crate::api::Context;
use crate::bitcoin::{Amount, TxLock}; use crate::bitcoin::{Amount, TxLock};
use crate::cli::{list_sellers, EventLoop, SellerStatus}; use crate::cli::{list_sellers, EventLoop, SellerStatus};
use crate::libp2p_ext::MultiAddrExt; use crate::libp2p_ext::MultiAddrExt;
use crate::network::quote::{BidQuote, ZeroQuoteReceived}; use crate::network::quote::{BidQuote, ZeroQuoteReceived};
use crate::network::swarm; use crate::network::swarm;
use crate::protocol::bob::{BobState, Swap};
use crate::protocol::bob; use crate::protocol::bob;
use crate::protocol::bob::{BobState, Swap};
use crate::{bitcoin, cli, monero, rpc}; use crate::{bitcoin, cli, monero, rpc};
use anyhow::{bail, Context as AnyContext, Result}; use anyhow::{bail, Context as AnyContext, Result};
use libp2p::core::Multiaddr; use libp2p::core::Multiaddr;
@ -16,10 +17,8 @@ use std::convert::TryInto;
use std::future::Future; use std::future::Future;
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use uuid::Uuid;
use crate::api::Context;
use tokio::sync::broadcast; use tokio::sync::broadcast;
use uuid::Uuid;
#[derive(PartialEq, Debug)] #[derive(PartialEq, Debug)]
pub struct Request { pub struct Request {
@ -61,11 +60,11 @@ impl Shutdown {
#[derive(Debug)] #[derive(Debug)]
pub struct Shutdown { pub struct Shutdown {
shutdown: bool, shutdown: bool,
notify: broadcast::Receiver<()> notify: broadcast::Receiver<()>,
} }
impl PartialEq for Shutdown { impl PartialEq for Shutdown {
fn eq(&self, other: &Shutdown) -> bool { fn eq(&self, other: &Shutdown) -> bool {
self.shutdown == other.shutdown self.shutdown == other.shutdown
} }
} }
@ -81,7 +80,6 @@ pub struct Params {
pub address: Option<bitcoin::Address>, pub address: Option<bitcoin::Address>,
} }
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub enum Method { pub enum Method {
BuyXmr, BuyXmr,
@ -93,8 +91,7 @@ pub enum Method {
GetSeller, GetSeller,
SwapStartDate, SwapStartDate,
Resume, Resume,
Cancel, CancelAndRefund,
Refund,
ListSellers, ListSellers,
ExportBitcoinWallet, ExportBitcoinWallet,
MoneroRecovery, MoneroRecovery,
@ -107,19 +104,29 @@ impl Request {
Method::BuyXmr => { Method::BuyXmr => {
let swap_id = Uuid::new_v4(); let swap_id = Uuid::new_v4();
let seed = context.config.seed.as_ref().unwrap(); let seed = context.config.seed.as_ref().context("Could not get seed")?;
let env_config = context.config.env_config; let env_config = context.config.env_config;
let btc = context.bitcoin_wallet.as_ref().unwrap(); let btc = context
let seller = self.params.seller.clone().unwrap(); .bitcoin_wallet
let monero_receive_address = self.params.monero_receive_address.unwrap(); .as_ref()
let bitcoin_change_address = self.params.bitcoin_change_address.clone().unwrap(); .context("Could not get Bitcoin wallet")?;
let seller = self
let bitcoin_wallet = btc;
let seller_peer_id = self
.params .params
.seller .seller
.as_ref() .clone()
.unwrap() .context("Parameter seller is missing")?;
let monero_receive_address = self
.params
.monero_receive_address
.context("Parameter monero_receive_address is missing")?;
let bitcoin_change_address = self
.params
.bitcoin_change_address
.clone()
.context("Parameter bitcoin_change_address is missing")?;
let bitcoin_wallet = btc;
let seller_peer_id = seller
.extract_peer_id() .extract_peer_id()
.context("Seller address must contain peer ID")?; .context("Seller address must contain peer ID")?;
context context
@ -135,7 +142,10 @@ impl Request {
); );
let mut swarm = swarm::cli( let mut swarm = swarm::cli(
seed.derive_libp2p_identity(), seed.derive_libp2p_identity(),
context.config.tor_socks5_port.unwrap(), context
.config
.tor_socks5_port
.context("Could not get Tor SOCKS5 port")?,
behaviour, behaviour,
) )
.await?; .await?;
@ -178,13 +188,16 @@ impl Request {
.db .db
.insert_monero_address(swap_id, monero_receive_address) .insert_monero_address(swap_id, monero_receive_address)
.await?; .await?;
let monero_wallet = context.monero_wallet.as_ref().unwrap(); let monero_wallet = context
.monero_wallet
.as_ref()
.context("Could not get Monero wallet")?;
let swap = Swap::new( let swap = Swap::new(
Arc::clone(&context.db), Arc::clone(&context.db),
swap_id, swap_id,
Arc::clone(&bitcoin_wallet), Arc::clone(bitcoin_wallet),
Arc::clone(&monero_wallet), Arc::clone(monero_wallet),
env_config, env_config,
event_loop_handle, event_loop_handle,
monero_receive_address, monero_receive_address,
@ -217,15 +230,21 @@ impl Request {
} }
Method::RawHistory => { Method::RawHistory => {
let raw_history = context.db.raw_all().await?; let raw_history = context.db.raw_all().await?;
json!({ json!({ "raw_history": raw_history })
"raw_history": raw_history
})
} }
Method::GetSeller => { Method::GetSeller => {
let swap_id = self.params.swap_id.with_context(|| "A swap_id is needed")?; let swap_id = self.params.swap_id.context("Parameter swap_id is needed")?;
let peerId = context.db.get_peer_id(swap_id).await.with_context(|| "Could not get PeerID")?; let peerId = context
.db
.get_peer_id(swap_id)
.await
.with_context(|| "Could not get PeerID")?;
let addresses = context.db.get_addresses(peerId).await.with_context(|| "Could not get addressess")?; let addresses = context
.db
.get_addresses(peerId)
.await
.with_context(|| "Could not get addressess")?;
json!({ json!({
"peerId": peerId.to_base58(), "peerId": peerId.to_base58(),
@ -233,12 +252,12 @@ impl Request {
}) })
} }
Method::SwapStartDate => { Method::SwapStartDate => {
let swap_id = self.params.swap_id.with_context(|| "A swap_id is needed")?; let swap_id = self
.params
.swap_id
.context("Parameter swap_id is missing")?;
let start_date = context let start_date = context.db.get_swap_start_date(swap_id).await?;
.db
.get_swap_start_date(swap_id)
.await?;
json!({ json!({
"start_date": start_date, "start_date": start_date,
@ -262,9 +281,16 @@ impl Request {
}) })
} }
Method::WithdrawBtc => { Method::WithdrawBtc => {
let bitcoin_wallet = context.bitcoin_wallet.as_ref().unwrap(); let bitcoin_wallet = context
.bitcoin_wallet
.as_ref()
.context("Could not get Bitcoin wallet")?;
let address = self.params.address.clone().unwrap(); let address = self
.params
.address
.clone()
.context("Parameter address is missing")?;
let amount = match self.params.amount { let amount = match self.params.amount {
Some(amount) => amount, Some(amount) => amount,
@ -306,7 +332,10 @@ impl Request {
} }
} }
Method::Balance => { Method::Balance => {
let bitcoin_wallet = context.bitcoin_wallet.as_ref().unwrap(); let bitcoin_wallet = context
.bitcoin_wallet
.as_ref()
.context("Could not get Bitcoin wallet")?;
bitcoin_wallet.sync().await?; bitcoin_wallet.sync().await?;
let bitcoin_balance = bitcoin_wallet.balance().await?; let bitcoin_balance = bitcoin_wallet.balance().await?;
@ -320,22 +349,38 @@ impl Request {
}) })
} }
Method::Resume => { Method::Resume => {
let swap_id = self.params.swap_id.unwrap(); let swap_id = self
.params
.swap_id
.context("Parameter swap_id is missing")?;
let seller_peer_id = context.db.get_peer_id(swap_id).await?; let seller_peer_id = context.db.get_peer_id(swap_id).await?;
let seller_addresses = context.db.get_addresses(seller_peer_id).await?; let seller_addresses = context.db.get_addresses(seller_peer_id).await?;
let seed = context.config.seed.as_ref().unwrap().derive_libp2p_identity(); let seed = context
.config
.seed
.as_ref()
.context("Could not get seed")?
.derive_libp2p_identity();
let behaviour = cli::Behaviour::new( let behaviour = cli::Behaviour::new(
seller_peer_id, seller_peer_id,
context.config.env_config, context.config.env_config,
Arc::clone(context.bitcoin_wallet.as_ref().unwrap()), Arc::clone(
context
.bitcoin_wallet
.as_ref()
.context("Could not get Bitcoin wallet")?,
),
(seed.clone(), context.config.namespace), (seed.clone(), context.config.namespace),
); );
let mut swarm = swarm::cli( let mut swarm = swarm::cli(
seed.clone(), seed.clone(),
context.config.tor_socks5_port.clone().unwrap(), context
.config
.tor_socks5_port
.context("Could not get Tor SOCKS5 port")?,
behaviour, behaviour,
) )
.await?; .await?;
@ -357,8 +402,18 @@ impl Request {
let swap = Swap::from_db( let swap = Swap::from_db(
Arc::clone(&context.db), Arc::clone(&context.db),
swap_id, swap_id,
Arc::clone(context.bitcoin_wallet.as_ref().unwrap()), Arc::clone(
Arc::clone(context.monero_wallet.as_ref().unwrap()), context
.bitcoin_wallet
.as_ref()
.context("Could not get Bitcoin wallet")?,
),
Arc::clone(
context
.monero_wallet
.as_ref()
.context("Could not get Monero wallet")?,
),
context.config.env_config, context.config.env_config,
event_loop_handle, event_loop_handle,
monero_receive_address, monero_receive_address,
@ -378,39 +433,49 @@ impl Request {
}) })
} }
Method::CancelAndRefund => { Method::CancelAndRefund => {
let bitcoin_wallet = context.bitcoin_wallet.as_ref().unwrap(); let bitcoin_wallet = context
.bitcoin_wallet
.as_ref()
.context("Could not get Bitcoin wallet")?;
let (txid, _) = cli::cancel_and_refund(swap_id, Arc::clone(bitcoin_wallet), Arc::clone(&context.db).await?; let state = cli::cancel_and_refund(
self.params
json!({ .swap_id
"txid": txid, .context("Parameter swap_id is missing")?,
})
}
Method::Refund => {
let bitcoin_wallet = context.bitcoin_wallet.as_ref().unwrap();
let state = cli::refund(
self.params.swap_id.unwrap(),
Arc::clone(bitcoin_wallet), Arc::clone(bitcoin_wallet),
Arc::clone(&context.db), Arc::clone(&context.db),
) )
.await?; .await?;
json!({ "result": state }) json!({
"result": state,
})
} }
Method::ListSellers => { Method::ListSellers => {
let rendezvous_point = self.params.rendezvous_point.clone().unwrap(); let rendezvous_point = self
.params
.rendezvous_point
.clone()
.context("Parameter rendezvous_point is missing")?;
let rendezvous_node_peer_id = rendezvous_point let rendezvous_node_peer_id = rendezvous_point
.extract_peer_id() .extract_peer_id()
.context("Rendezvous node address must contain peer ID")?; .context("Rendezvous node address must contain peer ID")?;
let identity = context.config.seed.as_ref().unwrap().derive_libp2p_identity(); let identity = context
.config
.seed
.as_ref()
.context("Cannot extract seed")?
.derive_libp2p_identity();
let sellers = list_sellers( let sellers = list_sellers(
rendezvous_node_peer_id, rendezvous_node_peer_id,
rendezvous_point, rendezvous_point,
context.config.namespace, context.config.namespace,
context.config.tor_socks5_port.unwrap(), context
.config
.tor_socks5_port
.context("Could not get Tor SOCKS5 port")?,
identity, identity,
) )
.await?; .await?;
@ -440,7 +505,10 @@ impl Request {
json!({ "sellers": sellers }) json!({ "sellers": sellers })
} }
Method::ExportBitcoinWallet => { Method::ExportBitcoinWallet => {
let bitcoin_wallet = context.bitcoin_wallet.as_ref().unwrap(); let bitcoin_wallet = context
.bitcoin_wallet
.as_ref()
.context("Could not get Bitcoin wallet")?;
let wallet_export = bitcoin_wallet.wallet_export("cli").await?; let wallet_export = bitcoin_wallet.wallet_export("cli").await?;
tracing::info!(descriptor=%wallet_export.to_string(), "Exported bitcoin wallet"); tracing::info!(descriptor=%wallet_export.to_string(), "Exported bitcoin wallet");
@ -451,7 +519,11 @@ impl Request {
Method::MoneroRecovery => { Method::MoneroRecovery => {
let swap_state: BobState = context let swap_state: BobState = context
.db .db
.get_state(self.params.swap_id.clone().unwrap()) .get_state(
self.params
.swap_id
.context("Parameter swap_id is missing")?,
)
.await? .await?
.try_into()?; .try_into()?;
@ -495,7 +567,6 @@ impl Request {
} }
} }
fn qr_code(value: &impl ToString) -> Result<String> { fn qr_code(value: &impl ToString) -> Result<String> {
let code = QrCode::new(value.to_string())?; let code = QrCode::new(value.to_string())?;
let qr_code = code let qr_code = code

View File

@ -54,7 +54,7 @@ impl Wallet {
) -> Result<Self> { ) -> Result<Self> {
let data_dir = data_dir.as_ref(); let data_dir = data_dir.as_ref();
let wallet_dir = data_dir.join(WALLET); let wallet_dir = data_dir.join(WALLET);
let database = bdk::sled::open(&wallet_dir)?.open_tree(SLED_TREE_NAME)?; let database = bdk::sled::open(wallet_dir)?.open_tree(SLED_TREE_NAME)?;
let network = env_config.bitcoin_network; let network = env_config.bitcoin_network;
let wallet = match bdk::Wallet::new( let wallet = match bdk::Wallet::new(
@ -97,7 +97,7 @@ impl Wallet {
std::fs::rename(from, to)?; std::fs::rename(from, to)?;
let wallet_dir = data_dir.join(WALLET); let wallet_dir = data_dir.join(WALLET);
let database = bdk::sled::open(&wallet_dir)?.open_tree(SLED_TREE_NAME)?; let database = bdk::sled::open(wallet_dir)?.open_tree(SLED_TREE_NAME)?;
let wallet = bdk::Wallet::new( let wallet = bdk::Wallet::new(
bdk::template::Bip84(xprivkey, KeychainKind::External), bdk::template::Bip84(xprivkey, KeychainKind::External),

View File

@ -28,7 +28,7 @@ pub async fn cancel_and_refund(
pub async fn cancel( pub async fn cancel(
swap_id: Uuid, swap_id: Uuid,
bitcoin_wallet: Arc<Wallet>, bitcoin_wallet: Arc<Wallet>,
db: Arc<dyn Database>, db: Arc<dyn Database + Send + Sync>,
) -> Result<(Txid, Subscription, BobState)> { ) -> Result<(Txid, Subscription, BobState)> {
let state = db.get_state(swap_id).await?.try_into()?; let state = db.get_state(swap_id).await?.try_into()?;
@ -80,7 +80,7 @@ pub async fn cancel(
pub async fn refund( pub async fn refund(
swap_id: Uuid, swap_id: Uuid,
bitcoin_wallet: Arc<Wallet>, bitcoin_wallet: Arc<Wallet>,
db: Arc<dyn Database>, db: Arc<dyn Database + Send + Sync>,
) -> Result<BobState> { ) -> Result<BobState> {
let state = db.get_state(swap_id).await?.try_into()?; let state = db.get_state(swap_id).await?.try_into()?;

View File

@ -1,8 +1,8 @@
use crate::api::request::{Method, Params, Request, Shutdown};
use crate::api::Context; use crate::api::Context;
use crate::api::request::{Request, Params, Method, Shutdown}; use crate::bitcoin::{bitcoin_address, Amount};
use crate::bitcoin::{Amount, bitcoin_address};
use crate::monero::monero_address;
use crate::monero; use crate::monero;
use crate::monero::monero_address;
use anyhow::Result; use anyhow::Result;
use libp2p::core::Multiaddr; use libp2p::core::Multiaddr;
use std::ffi::OsString; use std::ffi::OsString;
@ -11,9 +11,9 @@ use std::path::PathBuf;
use std::str::FromStr; use std::str::FromStr;
use std::sync::Arc; use std::sync::Arc;
use structopt::{clap, StructOpt}; use structopt::{clap, StructOpt};
use tokio::sync::broadcast;
use url::Url; use url::Url;
use uuid::Uuid; use uuid::Uuid;
use tokio::sync::broadcast;
// See: https://moneroworld.com/ // See: https://moneroworld.com/
pub const DEFAULT_MONERO_DAEMON_ADDRESS: &str = "node.community.rino.io:18081"; pub const DEFAULT_MONERO_DAEMON_ADDRESS: &str = "node.community.rino.io:18081";
@ -42,7 +42,10 @@ pub enum ParseResult {
PrintAndExitZero { message: String }, PrintAndExitZero { message: String },
} }
pub async fn parse_args_and_apply_defaults<I, T>(raw_args: I, rx: broadcast::Sender<()>) -> Result<ParseResult> pub async fn parse_args_and_apply_defaults<I, T>(
raw_args: I,
rx: broadcast::Sender<()>,
) -> Result<ParseResult>
where where
I: IntoIterator<Item = T>, I: IntoIterator<Item = T>,
T: Into<OsString> + Clone, T: Into<OsString> + Clone,
@ -70,8 +73,10 @@ where
monero_receive_address, monero_receive_address,
tor, tor,
} => { } => {
let monero_receive_address = monero_address::validate(monero_receive_address, is_testnet)?; let monero_receive_address =
let bitcoin_change_address = bitcoin_address::validate(bitcoin_change_address, is_testnet)?; monero_address::validate(monero_receive_address, is_testnet)?;
let bitcoin_change_address =
bitcoin_address::validate(bitcoin_change_address, is_testnet)?;
let request = Request { let request = Request {
params: Params { params: Params {
@ -268,8 +273,18 @@ where
shutdown: Shutdown::new(rx.subscribe()), shutdown: Shutdown::new(rx.subscribe()),
}; };
let context = let context = Context::build(
Context::build(None, None, Some(tor), data, is_testnet, debug, json, None, rx).await?; None,
None,
Some(tor),
data,
is_testnet,
debug,
json,
None,
rx,
)
.await?;
(context, request) (context, request)
} }
@ -563,10 +578,10 @@ mod tests {
use crate::tor::DEFAULT_SOCKS5_PORT; use crate::tor::DEFAULT_SOCKS5_PORT;
use crate::api::api_test::*; use crate::api::api_test::*;
use sequential_test::sequential;
use crate::monero::monero_address::MoneroAddressNetworkMismatch;
use crate::api::Config; use crate::api::Config;
use crate::fs::system_data_dir; use crate::fs::system_data_dir;
use crate::monero::monero_address::MoneroAddressNetworkMismatch;
use sequential_test::sequential;
const BINARY_NAME: &str = "swap"; const BINARY_NAME: &str = "swap";
const ARGS_DATA_DIR: &str = "/tmp/dir/"; const ARGS_DATA_DIR: &str = "/tmp/dir/";
@ -586,7 +601,9 @@ mod tests {
]; ];
let (tx, _) = broadcast::channel(1); let (tx, _) = broadcast::channel(1);
let args = parse_args_and_apply_defaults(raw_ars, tx.clone()).await.unwrap(); let args = parse_args_and_apply_defaults(raw_ars, tx.clone())
.await
.unwrap();
let (is_testnet, debug, json) = (false, false, false); let (is_testnet, debug, json) = (false, false, false);
let (expected_config, expected_request) = ( let (expected_config, expected_request) = (
@ -619,7 +636,9 @@ mod tests {
]; ];
let (tx, _) = broadcast::channel(1); let (tx, _) = broadcast::channel(1);
let args = parse_args_and_apply_defaults(raw_ars, tx.clone()).await.unwrap(); let args = parse_args_and_apply_defaults(raw_ars, tx.clone())
.await
.unwrap();
let (is_testnet, debug, json) = (true, false, false); let (is_testnet, debug, json) = (true, false, false);
let (expected_config, expected_request) = ( let (expected_config, expected_request) = (
@ -651,7 +670,9 @@ mod tests {
]; ];
let (tx, _) = broadcast::channel(1); let (tx, _) = broadcast::channel(1);
let err = parse_args_and_apply_defaults(raw_ars, tx.clone()).await.unwrap_err(); let err = parse_args_and_apply_defaults(raw_ars, tx.clone())
.await
.unwrap_err();
assert_eq!( assert_eq!(
err.downcast_ref::<MoneroAddressNetworkMismatch>().unwrap(), err.downcast_ref::<MoneroAddressNetworkMismatch>().unwrap(),
@ -678,7 +699,9 @@ mod tests {
]; ];
let (tx, _) = broadcast::channel(1); let (tx, _) = broadcast::channel(1);
let err = parse_args_and_apply_defaults(raw_ars, tx.clone()).await.unwrap_err(); let err = parse_args_and_apply_defaults(raw_ars, tx.clone())
.await
.unwrap_err();
assert_eq!( assert_eq!(
err.downcast_ref::<MoneroAddressNetworkMismatch>().unwrap(), err.downcast_ref::<MoneroAddressNetworkMismatch>().unwrap(),
@ -695,7 +718,9 @@ mod tests {
let raw_ars = vec![BINARY_NAME, "resume", "--swap-id", SWAP_ID]; let raw_ars = vec![BINARY_NAME, "resume", "--swap-id", SWAP_ID];
let (tx, _) = broadcast::channel(1); let (tx, _) = broadcast::channel(1);
let args = parse_args_and_apply_defaults(raw_ars, tx.clone()).await.unwrap(); let args = parse_args_and_apply_defaults(raw_ars, tx.clone())
.await
.unwrap();
let (is_testnet, debug, json) = (false, false, false); let (is_testnet, debug, json) = (false, false, false);
let (expected_config, expected_request) = ( let (expected_config, expected_request) = (
@ -718,7 +743,9 @@ mod tests {
let raw_ars = vec![BINARY_NAME, "--testnet", "resume", "--swap-id", SWAP_ID]; let raw_ars = vec![BINARY_NAME, "--testnet", "resume", "--swap-id", SWAP_ID];
let (tx, _) = broadcast::channel(1); let (tx, _) = broadcast::channel(1);
let args = parse_args_and_apply_defaults(raw_ars, tx.clone()).await.unwrap(); let args = parse_args_and_apply_defaults(raw_ars, tx.clone())
.await
.unwrap();
let (is_testnet, debug, json) = (true, false, false); let (is_testnet, debug, json) = (true, false, false);
let (expected_config, expected_request) = ( let (expected_config, expected_request) = (
@ -741,7 +768,9 @@ mod tests {
let raw_ars = vec![BINARY_NAME, "cancel", "--swap-id", SWAP_ID]; let raw_ars = vec![BINARY_NAME, "cancel", "--swap-id", SWAP_ID];
let (tx, _) = broadcast::channel(1); let (tx, _) = broadcast::channel(1);
let args = parse_args_and_apply_defaults(raw_ars, tx.clone()).await.unwrap(); let args = parse_args_and_apply_defaults(raw_ars, tx.clone())
.await
.unwrap();
let (is_testnet, debug, json) = (false, false, false); let (is_testnet, debug, json) = (false, false, false);
@ -765,7 +794,9 @@ mod tests {
let raw_ars = vec![BINARY_NAME, "--testnet", "cancel", "--swap-id", SWAP_ID]; let raw_ars = vec![BINARY_NAME, "--testnet", "cancel", "--swap-id", SWAP_ID];
let (tx, _) = broadcast::channel(1); let (tx, _) = broadcast::channel(1);
let args = parse_args_and_apply_defaults(raw_ars, tx.clone()).await.unwrap(); let args = parse_args_and_apply_defaults(raw_ars, tx.clone())
.await
.unwrap();
let (is_testnet, debug, json) = (true, false, false); let (is_testnet, debug, json) = (true, false, false);
let (expected_config, expected_request) = ( let (expected_config, expected_request) = (
@ -788,7 +819,9 @@ mod tests {
let raw_ars = vec![BINARY_NAME, "refund", "--swap-id", SWAP_ID]; let raw_ars = vec![BINARY_NAME, "refund", "--swap-id", SWAP_ID];
let (tx, _) = broadcast::channel(1); let (tx, _) = broadcast::channel(1);
let args = parse_args_and_apply_defaults(raw_ars, tx.clone()).await.unwrap(); let args = parse_args_and_apply_defaults(raw_ars, tx.clone())
.await
.unwrap();
let (is_testnet, debug, json) = (false, false, false); let (is_testnet, debug, json) = (false, false, false);
let (expected_config, expected_request) = ( let (expected_config, expected_request) = (
@ -811,7 +844,9 @@ mod tests {
let raw_ars = vec![BINARY_NAME, "--testnet", "refund", "--swap-id", SWAP_ID]; let raw_ars = vec![BINARY_NAME, "--testnet", "refund", "--swap-id", SWAP_ID];
let (tx, _) = broadcast::channel(1); let (tx, _) = broadcast::channel(1);
let args = parse_args_and_apply_defaults(raw_ars, tx.clone()).await.unwrap(); let args = parse_args_and_apply_defaults(raw_ars, tx.clone())
.await
.unwrap();
let (is_testnet, debug, json) = (true, false, false); let (is_testnet, debug, json) = (true, false, false);
let (expected_config, expected_request) = ( let (expected_config, expected_request) = (
@ -845,7 +880,9 @@ mod tests {
]; ];
let (tx, _) = broadcast::channel(1); let (tx, _) = broadcast::channel(1);
let args = parse_args_and_apply_defaults(raw_ars, tx.clone()).await.unwrap(); let args = parse_args_and_apply_defaults(raw_ars, tx.clone())
.await
.unwrap();
let (is_testnet, debug, json) = (false, false, false); let (is_testnet, debug, json) = (false, false, false);
let data_dir = PathBuf::from_str(ARGS_DATA_DIR).unwrap(); let data_dir = PathBuf::from_str(ARGS_DATA_DIR).unwrap();
@ -863,7 +900,6 @@ mod tests {
assert_eq!(actual_request, Box::new(expected_request)); assert_eq!(actual_request, Box::new(expected_request));
} }
#[tokio::test] #[tokio::test]
#[sequential] #[sequential]
async fn given_buy_xmr_on_testnet_with_data_dir_then_data_dir_set() { async fn given_buy_xmr_on_testnet_with_data_dir_then_data_dir_set() {
@ -883,7 +919,9 @@ mod tests {
let (tx, _) = broadcast::channel(1); let (tx, _) = broadcast::channel(1);
let data_dir = PathBuf::from_str(ARGS_DATA_DIR).unwrap(); let data_dir = PathBuf::from_str(ARGS_DATA_DIR).unwrap();
let args = parse_args_and_apply_defaults(raw_ars, tx.clone()).await.unwrap(); let args = parse_args_and_apply_defaults(raw_ars, tx.clone())
.await
.unwrap();
let (is_testnet, debug, json) = (true, false, false); let (is_testnet, debug, json) = (true, false, false);
let (expected_config, expected_request) = ( let (expected_config, expected_request) = (
@ -903,7 +941,6 @@ mod tests {
#[tokio::test] #[tokio::test]
#[sequential] #[sequential]
async fn given_resume_on_mainnet_with_data_dir_then_data_dir_set() { async fn given_resume_on_mainnet_with_data_dir_then_data_dir_set() {
let raw_ars = vec![ let raw_ars = vec![
BINARY_NAME, BINARY_NAME,
"--data-base-dir", "--data-base-dir",
@ -915,7 +952,9 @@ mod tests {
let (tx, _) = broadcast::channel(1); let (tx, _) = broadcast::channel(1);
let data_dir = PathBuf::from_str(ARGS_DATA_DIR).unwrap(); let data_dir = PathBuf::from_str(ARGS_DATA_DIR).unwrap();
let args = parse_args_and_apply_defaults(raw_ars, tx.clone()).await.unwrap(); let args = parse_args_and_apply_defaults(raw_ars, tx.clone())
.await
.unwrap();
let (is_testnet, debug, json) = (false, false, false); let (is_testnet, debug, json) = (false, false, false);
let (expected_config, expected_request) = ( let (expected_config, expected_request) = (
@ -935,7 +974,6 @@ mod tests {
#[tokio::test] #[tokio::test]
#[sequential] #[sequential]
async fn given_resume_on_testnet_with_data_dir_then_data_dir_set() { async fn given_resume_on_testnet_with_data_dir_then_data_dir_set() {
let raw_ars = vec![ let raw_ars = vec![
BINARY_NAME, BINARY_NAME,
"--testnet", "--testnet",
@ -948,7 +986,9 @@ mod tests {
let (tx, _) = broadcast::channel(1); let (tx, _) = broadcast::channel(1);
let data_dir = PathBuf::from_str(ARGS_DATA_DIR).unwrap(); let data_dir = PathBuf::from_str(ARGS_DATA_DIR).unwrap();
let args = parse_args_and_apply_defaults(raw_ars, tx.clone()).await.unwrap(); let args = parse_args_and_apply_defaults(raw_ars, tx.clone())
.await
.unwrap();
let (is_testnet, debug, json) = (true, false, false); let (is_testnet, debug, json) = (true, false, false);
let (expected_config, expected_request) = ( let (expected_config, expected_request) = (
@ -981,7 +1021,9 @@ mod tests {
]; ];
let (tx, _) = broadcast::channel(1); let (tx, _) = broadcast::channel(1);
let args = parse_args_and_apply_defaults(raw_ars, tx.clone()).await.unwrap(); let args = parse_args_and_apply_defaults(raw_ars, tx.clone())
.await
.unwrap();
let (is_testnet, debug, json) = (false, true, false); let (is_testnet, debug, json) = (false, true, false);
let (expected_config, expected_request) = ( let (expected_config, expected_request) = (
@ -1015,7 +1057,9 @@ mod tests {
]; ];
let (tx, _) = broadcast::channel(1); let (tx, _) = broadcast::channel(1);
let args = parse_args_and_apply_defaults(raw_ars, tx.clone()).await.unwrap(); let args = parse_args_and_apply_defaults(raw_ars, tx.clone())
.await
.unwrap();
let (is_testnet, debug, json) = (true, true, false); let (is_testnet, debug, json) = (true, true, false);
let (expected_config, expected_request) = ( let (expected_config, expected_request) = (
@ -1035,11 +1079,12 @@ mod tests {
#[tokio::test] #[tokio::test]
#[sequential] #[sequential]
async fn given_resume_on_mainnet_with_debug_then_debug_set() { async fn given_resume_on_mainnet_with_debug_then_debug_set() {
let raw_ars = vec![BINARY_NAME, "--debug", "resume", "--swap-id", SWAP_ID]; let raw_ars = vec![BINARY_NAME, "--debug", "resume", "--swap-id", SWAP_ID];
let (tx, _) = broadcast::channel(1); let (tx, _) = broadcast::channel(1);
let args = parse_args_and_apply_defaults(raw_ars, tx.clone()).await.unwrap(); let args = parse_args_and_apply_defaults(raw_ars, tx.clone())
.await
.unwrap();
let (is_testnet, debug, json) = (false, true, false); let (is_testnet, debug, json) = (false, true, false);
let (expected_config, expected_request) = ( let (expected_config, expected_request) = (
@ -1056,7 +1101,6 @@ mod tests {
assert_eq!(actual_request, Box::new(expected_request)); assert_eq!(actual_request, Box::new(expected_request));
} }
#[tokio::test] #[tokio::test]
#[sequential] #[sequential]
async fn given_resume_on_testnet_with_debug_then_debug_set() { async fn given_resume_on_testnet_with_debug_then_debug_set() {
@ -1070,7 +1114,9 @@ mod tests {
]; ];
let (tx, _) = broadcast::channel(1); let (tx, _) = broadcast::channel(1);
let args = parse_args_and_apply_defaults(raw_ars, tx.clone()).await.unwrap(); let args = parse_args_and_apply_defaults(raw_ars, tx.clone())
.await
.unwrap();
let (is_testnet, debug, json) = (true, true, false); let (is_testnet, debug, json) = (true, true, false);
let (expected_config, expected_request) = ( let (expected_config, expected_request) = (
@ -1103,7 +1149,9 @@ mod tests {
]; ];
let (tx, _) = broadcast::channel(1); let (tx, _) = broadcast::channel(1);
let args = parse_args_and_apply_defaults(raw_ars, tx.clone()).await.unwrap(); let args = parse_args_and_apply_defaults(raw_ars, tx.clone())
.await
.unwrap();
let (is_testnet, debug, json) = (false, false, true); let (is_testnet, debug, json) = (false, false, true);
let data_dir = data_dir_path_cli(is_testnet); let data_dir = data_dir_path_cli(is_testnet);
@ -1138,7 +1186,9 @@ mod tests {
]; ];
let (tx, _) = broadcast::channel(1); let (tx, _) = broadcast::channel(1);
let args = parse_args_and_apply_defaults(raw_ars, tx.clone()).await.unwrap(); let args = parse_args_and_apply_defaults(raw_ars, tx.clone())
.await
.unwrap();
let (is_testnet, debug, json) = (true, false, true); let (is_testnet, debug, json) = (true, false, true);
let (expected_config, expected_request) = ( let (expected_config, expected_request) = (
@ -1158,10 +1208,11 @@ mod tests {
#[tokio::test] #[tokio::test]
#[sequential] #[sequential]
async fn given_resume_on_mainnet_with_json_then_json_set() { async fn given_resume_on_mainnet_with_json_then_json_set() {
let (tx, _) = broadcast::channel(1); let (tx, _) = broadcast::channel(1);
let raw_ars = vec![BINARY_NAME, "--json", "resume", "--swap-id", SWAP_ID]; let raw_ars = vec![BINARY_NAME, "--json", "resume", "--swap-id", SWAP_ID];
let args = parse_args_and_apply_defaults(raw_ars, tx.clone()).await.unwrap(); let args = parse_args_and_apply_defaults(raw_ars, tx.clone())
.await
.unwrap();
let (is_testnet, debug, json) = (false, false, true); let (is_testnet, debug, json) = (false, false, true);
let (expected_config, expected_request) = ( let (expected_config, expected_request) = (
@ -1181,7 +1232,6 @@ mod tests {
#[tokio::test] #[tokio::test]
#[sequential] #[sequential]
async fn given_resume_on_testnet_with_json_then_json_set() { async fn given_resume_on_testnet_with_json_then_json_set() {
let raw_ars = vec![ let raw_ars = vec![
BINARY_NAME, BINARY_NAME,
"--testnet", "--testnet",
@ -1192,7 +1242,9 @@ mod tests {
]; ];
let (tx, _) = broadcast::channel(1); let (tx, _) = broadcast::channel(1);
let args = parse_args_and_apply_defaults(raw_ars, tx.clone()).await.unwrap(); let args = parse_args_and_apply_defaults(raw_ars, tx.clone())
.await
.unwrap();
let (is_testnet, debug, json) = (true, false, true); let (is_testnet, debug, json) = (true, false, true);
let (expected_config, expected_request) = ( let (expected_config, expected_request) = (
@ -1223,7 +1275,9 @@ mod tests {
MULTI_ADDRESS, MULTI_ADDRESS,
]; ];
let (tx, _) = broadcast::channel(1); let (tx, _) = broadcast::channel(1);
let result = parse_args_and_apply_defaults(raw_ars, tx.clone()).await.unwrap_err(); let result = parse_args_and_apply_defaults(raw_ars, tx.clone())
.await
.unwrap_err();
let raw_ars = vec![ let raw_ars = vec![
BINARY_NAME, BINARY_NAME,
@ -1235,7 +1289,9 @@ mod tests {
"--seller", "--seller",
MULTI_ADDRESS, MULTI_ADDRESS,
]; ];
let result = parse_args_and_apply_defaults(raw_ars, tx.clone()).await.unwrap_err(); let result = parse_args_and_apply_defaults(raw_ars, tx.clone())
.await
.unwrap_err();
let raw_ars = vec![ let raw_ars = vec![
BINARY_NAME, BINARY_NAME,
@ -1247,7 +1303,9 @@ mod tests {
"--seller", "--seller",
MULTI_ADDRESS, MULTI_ADDRESS,
]; ];
let result = parse_args_and_apply_defaults(raw_ars, tx.clone()).await.unwrap(); let result = parse_args_and_apply_defaults(raw_ars, tx.clone())
.await
.unwrap();
assert!(matches!(result, ParseResult::Context(_, _))); assert!(matches!(result, ParseResult::Context(_, _)));
} }
@ -1266,7 +1324,9 @@ mod tests {
"--seller", "--seller",
MULTI_ADDRESS, MULTI_ADDRESS,
]; ];
let result = parse_args_and_apply_defaults(raw_ars, tx.clone()).await.unwrap_err(); let result = parse_args_and_apply_defaults(raw_ars, tx.clone())
.await
.unwrap_err();
let raw_ars = vec![ let raw_ars = vec![
BINARY_NAME, BINARY_NAME,
@ -1279,7 +1339,9 @@ mod tests {
"--seller", "--seller",
MULTI_ADDRESS, MULTI_ADDRESS,
]; ];
let result = parse_args_and_apply_defaults(raw_ars, tx.clone()).await.unwrap_err(); let result = parse_args_and_apply_defaults(raw_ars, tx.clone())
.await
.unwrap_err();
let raw_ars = vec![ let raw_ars = vec![
BINARY_NAME, BINARY_NAME,
@ -1292,7 +1354,9 @@ mod tests {
"--seller", "--seller",
MULTI_ADDRESS, MULTI_ADDRESS,
]; ];
let result = parse_args_and_apply_defaults(raw_ars, tx.clone()).await.unwrap(); let result = parse_args_and_apply_defaults(raw_ars, tx.clone())
.await
.unwrap();
assert!(matches!(result, ParseResult::Context(_, _))); assert!(matches!(result, ParseResult::Context(_, _)));
} }

View File

@ -1,7 +1,7 @@
use crate::database::Swap; use crate::database::Swap;
use crate::monero::Address; use crate::monero::Address;
use crate::protocol::{Database, State}; use crate::protocol::{Database, State};
use anyhow::{Context, Result}; use anyhow::{anyhow, Context, Result};
use async_trait::async_trait; use async_trait::async_trait;
use libp2p::{Multiaddr, PeerId}; use libp2p::{Multiaddr, PeerId};
use sqlx::sqlite::Sqlite; use sqlx::sqlite::Sqlite;
@ -185,7 +185,8 @@ impl Database for SqliteDatabase {
.fetch_one(&mut conn) .fetch_one(&mut conn)
.await?; .await?;
return Ok(row.start_date.unwrap()); row.start_date
.ok_or_else(|| anyhow!("Could not get swap start date"))
} }
async fn insert_latest_state(&self, swap_id: Uuid, state: State) -> Result<()> { async fn insert_latest_state(&self, swap_id: Uuid, state: State) -> Result<()> {
@ -283,13 +284,16 @@ impl Database for SqliteDatabase {
let mut swaps: HashMap<Uuid, Vec<serde_json::Value>> = HashMap::new(); let mut swaps: HashMap<Uuid, Vec<serde_json::Value>> = HashMap::new();
for row in &rows { for row in &rows {
let swap_id = Uuid::from_str(&row.swap_id).unwrap(); let swap_id = Uuid::from_str(&row.swap_id)?;
let state = serde_json::from_str(&row.state).unwrap(); let state = serde_json::from_str(&row.state)?;
if swaps.contains_key(&swap_id) { if let std::collections::hash_map::Entry::Vacant(e) = swaps.entry(swap_id) {
swaps.get_mut(&swap_id).unwrap().push(state); e.insert(vec![state]);
} else { } else {
swaps.insert(swap_id, vec![state]); swaps
.get_mut(&swap_id)
.ok_or_else(|| anyhow!("Error while retrieving the swap"))?
.push(state);
} }
} }

View File

@ -321,7 +321,7 @@ pub mod monero_amount {
} }
pub mod monero_address { pub mod monero_address {
use anyhow::{bail, Result, Context}; use anyhow::{bail, Context, Result};
use std::str::FromStr; use std::str::FromStr;
#[derive(thiserror::Error, Debug, Clone, Copy, PartialEq)] #[derive(thiserror::Error, Debug, Clone, Copy, PartialEq)]

View File

@ -1,5 +1,5 @@
use crate::api::Context; use crate::api::Context;
use jsonrpsee::server::{ServerBuilder, ServerHandle, RpcModule}; use jsonrpsee::server::{RpcModule, ServerBuilder, ServerHandle};
use std::net::SocketAddr; use std::net::SocketAddr;
use std::sync::Arc; use std::sync::Arc;
use thiserror::Error; use thiserror::Error;
@ -21,7 +21,7 @@ pub async fn run_server(
{ {
modules modules
.merge(methods::register_modules(Arc::clone(&context))) .merge(methods::register_modules(Arc::clone(&context)))
.unwrap() .expect("Could not register RPC modules")
} }
let addr = server.local_addr()?; let addr = server.local_addr()?;

View File

@ -1,8 +1,9 @@
use crate::api::{Context}; use crate::api::request::{Method, Params, Request, Shutdown};
use crate::api::request::{Params, Request, Method, Shutdown}; use crate::api::Context;
use anyhow::Result; use crate::bitcoin::bitcoin_address;
use crate::monero::monero_address;
use crate::{bitcoin, monero}; use crate::{bitcoin, monero};
use crate::{bitcoin::bitcoin_address, monero::monero_address}; use anyhow::Result;
use jsonrpsee::server::RpcModule; use jsonrpsee::server::RpcModule;
use libp2p::core::Multiaddr; use libp2p::core::Multiaddr;
use std::collections::HashMap; use std::collections::HashMap;
@ -16,17 +17,17 @@ pub fn register_modules(context: Arc<Context>) -> RpcModule<Arc<Context>> {
.register_async_method("get_bitcoin_balance", |_, context| async move { .register_async_method("get_bitcoin_balance", |_, context| async move {
get_bitcoin_balance(&context).await get_bitcoin_balance(&context).await
}) })
.unwrap(); .expect("Could not register RPC method get_bitcoin_balance");
module module
.register_async_method("get_history", |_, context| async move { .register_async_method("get_history", |_, context| async move {
get_history(&context).await get_history(&context).await
}) })
.unwrap(); .expect("Could not register RPC method get_history");
module module
.register_async_method("get_raw_history", |_, context| async move { .register_async_method("get_raw_history", |_, context| async move {
get_raw_history(&context).await get_raw_history(&context).await
}) })
.unwrap(); .expect("Could not register RPC method get_history");
module module
.register_async_method("get_seller", |params, context| async move { .register_async_method("get_seller", |params, context| async move {
let params: HashMap<String, Uuid> = params.parse()?; let params: HashMap<String, Uuid> = params.parse()?;
@ -37,7 +38,7 @@ pub fn register_modules(context: Arc<Context>) -> RpcModule<Arc<Context>> {
get_seller(*swap_id, &context).await get_seller(*swap_id, &context).await
}) })
.unwrap(); .expect("Could not register RPC method get_seller");
module module
.register_async_method("get_swap_start_date", |params, context| async move { .register_async_method("get_swap_start_date", |params, context| async move {
let params: HashMap<String, Uuid> = params.parse()?; let params: HashMap<String, Uuid> = params.parse()?;
@ -48,7 +49,7 @@ pub fn register_modules(context: Arc<Context>) -> RpcModule<Arc<Context>> {
get_swap_start_date(*swap_id, &context).await get_swap_start_date(*swap_id, &context).await
}) })
.unwrap(); .expect("Could not register RPC method get_swap_start_date");
module module
.register_async_method("resume_swap", |params, context| async move { .register_async_method("resume_swap", |params, context| async move {
let params: HashMap<String, Uuid> = params.parse()?; let params: HashMap<String, Uuid> = params.parse()?;
@ -59,7 +60,7 @@ pub fn register_modules(context: Arc<Context>) -> RpcModule<Arc<Context>> {
resume_swap(*swap_id, &context).await resume_swap(*swap_id, &context).await
}) })
.unwrap(); .expect("Could not register RPC method resume_swap");
module module
.register_async_method("withdraw_btc", |params, context| async move { .register_async_method("withdraw_btc", |params, context| async move {
let params: HashMap<String, String> = params.parse()?; let params: HashMap<String, String> = params.parse()?;
@ -80,11 +81,12 @@ pub fn register_modules(context: Arc<Context>) -> RpcModule<Arc<Context>> {
jsonrpsee_core::Error::Custom("Does not contain address".to_string()) jsonrpsee_core::Error::Custom("Does not contain address".to_string())
})?) })?)
.map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))?; .map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))?;
let withdraw_address = bitcoin_address::validate(withdraw_address, context.config.is_testnet)?; let withdraw_address =
bitcoin_address::validate(withdraw_address, context.config.is_testnet)?;
withdraw_btc(withdraw_address, amount, &context).await withdraw_btc(withdraw_address, amount, &context).await
}) })
.unwrap(); .expect("Could not register RPC method withdraw_btc");
module module
.register_async_method("buy_xmr", |params, context| async move { .register_async_method("buy_xmr", |params, context| async move {
let params: HashMap<String, String> = params.parse()?; let params: HashMap<String, String> = params.parse()?;
@ -98,7 +100,8 @@ pub fn register_modules(context: Arc<Context>) -> RpcModule<Arc<Context>> {
) )
.map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))?; .map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))?;
let bitcoin_change_address = bitcoin_address::validate(bitcoin_change_address, context.config.is_testnet)?; let bitcoin_change_address =
bitcoin_address::validate(bitcoin_change_address, context.config.is_testnet)?;
let monero_receive_address = monero::Address::from_str( let monero_receive_address = monero::Address::from_str(
params.get("monero_receive_address").ok_or_else(|| { params.get("monero_receive_address").ok_or_else(|| {
@ -109,7 +112,8 @@ pub fn register_modules(context: Arc<Context>) -> RpcModule<Arc<Context>> {
) )
.map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))?; .map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))?;
let monero_receive_address = monero_address::validate(monero_receive_address, context.config.is_testnet)?; let monero_receive_address =
monero_address::validate(monero_receive_address, context.config.is_testnet)?;
let seller = Multiaddr::from_str(params.get("seller").ok_or_else(|| { let seller = Multiaddr::from_str(params.get("seller").ok_or_else(|| {
jsonrpsee_core::Error::Custom("Does not contain seller".to_string()) jsonrpsee_core::Error::Custom("Does not contain seller".to_string())
@ -121,29 +125,33 @@ pub fn register_modules(context: Arc<Context>) -> RpcModule<Arc<Context>> {
monero_receive_address, monero_receive_address,
seller, seller,
&context, &context,
).await )
.await
}) })
.unwrap(); .expect("Could not register RPC method buy_xmr");
module module
.register_async_method("list_sellers", |params, context| async move { .register_async_method("list_sellers", |params, context| async move {
let params: HashMap<String, Multiaddr> = params.parse()?; let params: HashMap<String, Multiaddr> = params.parse()?;
let rendezvous_point = params.get("rendezvous_point").ok_or_else(|| { let rendezvous_point = params.get("rendezvous_point").ok_or_else(|| {
jsonrpsee_core::Error::Custom("Does not contain rendezvous_point".to_string()) jsonrpsee_core::Error::Custom("Does not contain rendezvous_point".to_string())
})?; })?;
list_sellers(rendezvous_point.clone(), &context).await list_sellers(rendezvous_point.clone(), &context).await
}) })
.unwrap(); .expect("Could not register RPC method list_sellers");
module module
} }
async fn get_bitcoin_balance(context: &Arc<Context>) -> Result<serde_json::Value, jsonrpsee_core::Error> { async fn get_bitcoin_balance(
context: &Arc<Context>,
) -> Result<serde_json::Value, jsonrpsee_core::Error> {
let mut request = Request { let mut request = Request {
params: Params::default(), params: Params::default(),
cmd: Method::Balance, cmd: Method::Balance,
shutdown: Shutdown::new(context.shutdown.subscribe()), shutdown: Shutdown::new(context.shutdown.subscribe()),
}; };
let balance = request.call(Arc::clone(context)) let balance = request
.call(Arc::clone(context))
.await .await
.map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))?; .map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))?;
@ -156,19 +164,23 @@ async fn get_history(context: &Arc<Context>) -> Result<serde_json::Value, jsonrp
cmd: Method::History, cmd: Method::History,
shutdown: Shutdown::new(context.shutdown.subscribe()), shutdown: Shutdown::new(context.shutdown.subscribe()),
}; };
let history = request.call(Arc::clone(context)) let history = request
.call(Arc::clone(context))
.await .await
.map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))?; .map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))?;
Ok(history) Ok(history)
} }
async fn get_raw_history(context: &Arc<Context>) -> Result<serde_json::Value, jsonrpsee_core::Error> { async fn get_raw_history(
context: &Arc<Context>,
) -> Result<serde_json::Value, jsonrpsee_core::Error> {
let mut request = Request { let mut request = Request {
params: Params::default(), params: Params::default(),
cmd: Method::RawHistory, cmd: Method::RawHistory,
shutdown: Shutdown::new(context.shutdown.subscribe()), shutdown: Shutdown::new(context.shutdown.subscribe()),
}; };
let history = request.call(Arc::clone(context)) let history = request
.call(Arc::clone(context))
.await .await
.map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))?; .map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))?;
@ -177,7 +189,7 @@ async fn get_raw_history(context: &Arc<Context>) -> Result<serde_json::Value, js
async fn get_seller( async fn get_seller(
swap_id: Uuid, swap_id: Uuid,
context: &Arc<Context> context: &Arc<Context>,
) -> Result<serde_json::Value, jsonrpsee_core::Error> { ) -> Result<serde_json::Value, jsonrpsee_core::Error> {
let mut request = Request { let mut request = Request {
params: Params { params: Params {
@ -187,7 +199,8 @@ async fn get_seller(
cmd: Method::GetSeller, cmd: Method::GetSeller,
shutdown: Shutdown::new(context.shutdown.subscribe()), shutdown: Shutdown::new(context.shutdown.subscribe()),
}; };
let result = request.call(Arc::clone(context)) let result = request
.call(Arc::clone(context))
.await .await
.map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))?; .map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))?;
@ -196,7 +209,7 @@ async fn get_seller(
async fn get_swap_start_date( async fn get_swap_start_date(
swap_id: Uuid, swap_id: Uuid,
context: &Arc<Context> context: &Arc<Context>,
) -> Result<serde_json::Value, jsonrpsee_core::Error> { ) -> Result<serde_json::Value, jsonrpsee_core::Error> {
let mut request = Request { let mut request = Request {
params: Params { params: Params {
@ -206,7 +219,8 @@ async fn get_swap_start_date(
cmd: Method::SwapStartDate, cmd: Method::SwapStartDate,
shutdown: Shutdown::new(context.shutdown.subscribe()), shutdown: Shutdown::new(context.shutdown.subscribe()),
}; };
let result = request.call(Arc::clone(context)) let result = request
.call(Arc::clone(context))
.await .await
.map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))?; .map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))?;
@ -226,7 +240,8 @@ async fn resume_swap(
shutdown: Shutdown::new(context.shutdown.subscribe()), shutdown: Shutdown::new(context.shutdown.subscribe()),
}; };
let result = request.call(Arc::clone(context)) let result = request
.call(Arc::clone(context))
.await .await
.map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))?; .map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))?;
Ok(result) Ok(result)
@ -245,7 +260,8 @@ async fn withdraw_btc(
cmd: Method::WithdrawBtc, cmd: Method::WithdrawBtc,
shutdown: Shutdown::new(context.shutdown.subscribe()), shutdown: Shutdown::new(context.shutdown.subscribe()),
}; };
let result = request.call(Arc::clone(context)) let result = request
.call(Arc::clone(context))
.await .await
.map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))?; .map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))?;
Ok(result) Ok(result)
@ -267,7 +283,8 @@ async fn buy_xmr(
cmd: Method::BuyXmr, cmd: Method::BuyXmr,
shutdown: Shutdown::new(context.shutdown.subscribe()), shutdown: Shutdown::new(context.shutdown.subscribe()),
}; };
let swap = request.call(Arc::clone(context)) let swap = request
.call(Arc::clone(context))
.await .await
.map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))?; .map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))?;
Ok(swap) Ok(swap)
@ -285,7 +302,8 @@ async fn list_sellers(
cmd: Method::ListSellers, cmd: Method::ListSellers,
shutdown: Shutdown::new(context.shutdown.subscribe()), shutdown: Shutdown::new(context.shutdown.subscribe()),
}; };
let result = request.call(Arc::clone(context)) let result = request
.call(Arc::clone(context))
.await .await
.map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))?; .map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))?;
Ok(result) Ok(result)

View File

@ -61,7 +61,7 @@ impl Seed {
let file_path = Path::new(&file_path_buf); let file_path = Path::new(&file_path_buf);
if file_path.exists() { if file_path.exists() {
return Self::from_file(&file_path); return Self::from_file(file_path);
} }
tracing::debug!("No seed file found, creating at {}", file_path.display()); tracing::debug!("No seed file found, creating at {}", file_path.display());

View File

@ -1,37 +1,39 @@
use testcontainers::clients::Cli;
use testcontainers::{Container, Docker, RunArgs};
use anyhow::{bail, Context as AnyContext, Result}; use anyhow::{bail, Context as AnyContext, Result};
use futures::Future; use futures::Future;
use swap::api::{Context, Config};
use swap::api::request::{Request, Params, Method, Shutdown};
use std::sync::Arc;
use tokio::time::{interval, timeout};
use std::time::Duration;
use jsonrpsee::ws_client::WsClientBuilder; use jsonrpsee::ws_client::WsClientBuilder;
use jsonrpsee_core::{client::ClientT, params::ObjectParams};
use jsonrpsee::{rpc_params, RpcModule}; use jsonrpsee::{rpc_params, RpcModule};
use jsonrpsee_core::client::ClientT;
use jsonrpsee_core::params::ObjectParams;
use jsonrpsee_types::error::CallError; use jsonrpsee_types::error::CallError;
use tokio::sync::broadcast;
use swap::cli::command::{Bitcoin, Monero};
use std::collections::HashMap;
use uuid::Uuid;
use serde_json::{json, Value};
use sequential_test::sequential; use sequential_test::sequential;
use serde_json::{json, Value};
use std::collections::HashMap;
use std::sync::Arc;
use std::time::Duration;
use swap::api::request::{Method, Params, Request, Shutdown};
use swap::api::{Config, Context};
use swap::cli::command::{Bitcoin, Monero};
use testcontainers::clients::Cli;
use testcontainers::{Container, Docker, RunArgs};
use tokio::sync::broadcast;
use tokio::time::{interval, timeout};
use uuid::Uuid;
#[cfg(test)] #[cfg(test)]
// to be replaced with actual "real" testing values // to be replaced with actual "real" testing values
// need to create some kind of swap database and bitcoin environment with some funds // need to create some kind of swap database and bitcoin environment with some
// funds
const SERVER_ADDRESS: &str = "127.0.0.1:1234"; const SERVER_ADDRESS: &str = "127.0.0.1:1234";
const BITCOIN_ADDR: &str = "tb1qr3em6k3gfnyl8r7q0v7t4tlnyxzgxma3lressv"; const BITCOIN_ADDR: &str = "tb1qr3em6k3gfnyl8r7q0v7t4tlnyxzgxma3lressv";
const MONERO_ADDR: &str = "53gEuGZUhP9JMEBZoGaFNzhwEgiG7hwQdMCqFxiyiTeFPmkbt1mAoNybEUvYBKHcnrSgxnVWgZsTvRBaHBNXPa8tHiCU51a"; const MONERO_ADDR: &str = "53gEuGZUhP9JMEBZoGaFNzhwEgiG7hwQdMCqFxiyiTeFPmkbt1mAoNybEUvYBKHcnrSgxnVWgZsTvRBaHBNXPa8tHiCU51a";
const SELLER: &str = "/ip4/127.0.0.1/tcp/9939/p2p/12D3KooWCdMKjesXMJz1SiZ7HgotrxuqhQJbP5sgBm2BwP1cqThi"; const SELLER: &str =
"/ip4/127.0.0.1/tcp/9939/p2p/12D3KooWCdMKjesXMJz1SiZ7HgotrxuqhQJbP5sgBm2BwP1cqThi";
const SWAP_ID: &str = "ea030832-3be9-454f-bb98-5ea9a788406b"; const SWAP_ID: &str = "ea030832-3be9-454f-bb98-5ea9a788406b";
pub async fn initialize_context() -> (Arc<Context>, Request) { pub async fn initialize_context() -> (Arc<Context>, Request) {
let (is_testnet, debug, json) = (true, false, false); let (is_testnet, debug, json) = (true, false, false);
//let data_dir = data::data_dir_from(None, is_testnet).unwrap(); // let data_dir = data::data_dir_from(None, is_testnet).unwrap();
let server_address = None; let server_address = None;
let (tx, _) = broadcast::channel(1); let (tx, _) = broadcast::channel(1);
@ -60,12 +62,13 @@ pub async fn initialize_context() -> (Arc<Context>, Request) {
json, json,
server_address, server_address,
tx, tx,
).await.unwrap(); )
.await
.unwrap();
(Arc::new(context), request) (Arc::new(context), request)
} }
#[tokio::test] #[tokio::test]
#[sequential] #[sequential]
pub async fn can_start_server() { pub async fn can_start_server() {
@ -92,7 +95,10 @@ pub async fn get_bitcoin_balance() {
tokio::time::sleep(Duration::from_secs(3)).await; tokio::time::sleep(Duration::from_secs(3)).await;
let client = WsClientBuilder::default().build(&url).await.unwrap(); let client = WsClientBuilder::default().build(&url).await.unwrap();
let response: HashMap<String, i32> = client.request("get_bitcoin_balance", rpc_params!["id"]).await.unwrap(); let response: HashMap<String, i32> = client
.request("get_bitcoin_balance", rpc_params!["id"])
.await
.unwrap();
assert_eq!(response, HashMap::from([("balance".to_string(), 0)])); assert_eq!(response, HashMap::from([("balance".to_string(), 0)]));
ctx.shutdown.send(()); ctx.shutdown.send(());
@ -113,7 +119,8 @@ pub async fn get_history() {
let client = WsClientBuilder::default().build(&url).await.unwrap(); let client = WsClientBuilder::default().build(&url).await.unwrap();
let mut params = ObjectParams::new(); let mut params = ObjectParams::new();
let response: HashMap<String, Vec<(Uuid, String)>> = client.request("get_history", params).await.unwrap(); let response: HashMap<String, Vec<(Uuid, String)>> =
client.request("get_history", params).await.unwrap();
let swaps: Vec<(Uuid, String)> = Vec::new(); let swaps: Vec<(Uuid, String)> = Vec::new();
assert_eq!(response, HashMap::from([("swaps".to_string(), swaps)])); assert_eq!(response, HashMap::from([("swaps".to_string(), swaps)]));
@ -136,9 +143,13 @@ pub async fn get_raw_history() {
let mut params = ObjectParams::new(); let mut params = ObjectParams::new();
let raw_history: HashMap<Uuid, String> = HashMap::new(); let raw_history: HashMap<Uuid, String> = HashMap::new();
let response: HashMap<String, HashMap<Uuid, String>> = client.request("get_raw_history", params).await.unwrap(); let response: HashMap<String, HashMap<Uuid, String>> =
client.request("get_raw_history", params).await.unwrap();
assert_eq!(response, HashMap::from([("raw_history".to_string(), raw_history)])); assert_eq!(
response,
HashMap::from([("raw_history".to_string(), raw_history)])
);
ctx.shutdown.send(()); ctx.shutdown.send(());
} }
@ -159,7 +170,8 @@ pub async fn get_seller() {
let response: Result<HashMap<String, String>, _> = client.request("get_seller", params).await; let response: Result<HashMap<String, String>, _> = client.request("get_seller", params).await;
// We should ideally match the expected error and panic if it's different one, but the request returns a custom error (to investigate) // We should ideally match the expected error and panic if it's different one,
// but the request returns a custom error (to investigate)
// Err(jsonrpsee_core::Error::Call(CallError::InvalidParams(e))) => (), // Err(jsonrpsee_core::Error::Call(CallError::InvalidParams(e))) => (),
// Err(e) => panic!("ErrorType was not ParseError but {e:?}"), // Err(e) => panic!("ErrorType was not ParseError but {e:?}"),
@ -185,7 +197,10 @@ pub async fn get_seller() {
match response { match response {
Ok(hash) => (), Ok(hash) => (),
Err(e) => panic!("Expected a HashMap with correct params, got an error: {}", e), Err(e) => panic!(
"Expected a HashMap with correct params, got an error: {}",
e
),
} }
ctx.shutdown.send(()); ctx.shutdown.send(());
} }
@ -205,7 +220,8 @@ pub async fn get_swap_start_date() {
let client = WsClientBuilder::default().build(&url).await.unwrap(); let client = WsClientBuilder::default().build(&url).await.unwrap();
let mut params = ObjectParams::new(); let mut params = ObjectParams::new();
let response: Result<HashMap<String, String>, _> = client.request("get_swap_start_date", params).await; let response: Result<HashMap<String, String>, _> =
client.request("get_swap_start_date", params).await;
match response { match response {
Err(e) => (), Err(e) => (),
@ -215,7 +231,8 @@ pub async fn get_swap_start_date() {
let mut params = ObjectParams::new(); let mut params = ObjectParams::new();
params.insert("swap_id", "invalid_swap"); params.insert("swap_id", "invalid_swap");
let response: Result<HashMap<String, String>, _> = client.request("get_swap_start_date", params).await; let response: Result<HashMap<String, String>, _> =
client.request("get_swap_start_date", params).await;
match response { match response {
Err(e) => (), Err(e) => (),
@ -225,7 +242,8 @@ pub async fn get_swap_start_date() {
let mut params = ObjectParams::new(); let mut params = ObjectParams::new();
params.insert("swap_id", SWAP_ID); params.insert("swap_id", SWAP_ID);
let response: Result<HashMap<String, String>, _> = client.request("get_swap_start_date", params).await; let response: Result<HashMap<String, String>, _> =
client.request("get_swap_start_date", params).await;
match response { match response {
Ok(hash) => (), Ok(hash) => (),
@ -249,7 +267,8 @@ pub async fn resume_swap() {
let client = WsClientBuilder::default().build(&url).await.unwrap(); let client = WsClientBuilder::default().build(&url).await.unwrap();
let mut params = ObjectParams::new(); let mut params = ObjectParams::new();
let response: Result<HashMap<String, String>, _> = client.request("get_swap_start_date", params).await; let response: Result<HashMap<String, String>, _> =
client.request("get_swap_start_date", params).await;
match response { match response {
Err(e) => (), Err(e) => (),
@ -259,7 +278,8 @@ pub async fn resume_swap() {
let mut params = ObjectParams::new(); let mut params = ObjectParams::new();
params.insert("swap_id", "invalid_swap"); params.insert("swap_id", "invalid_swap");
let response: Result<HashMap<String, String>, _> = client.request("get_swap_start_date", params).await; let response: Result<HashMap<String, String>, _> =
client.request("get_swap_start_date", params).await;
match response { match response {
Err(e) => (), Err(e) => (),
@ -269,7 +289,8 @@ pub async fn resume_swap() {
let mut params = ObjectParams::new(); let mut params = ObjectParams::new();
params.insert("swap_id", SWAP_ID); params.insert("swap_id", SWAP_ID);
let response: Result<HashMap<String, String>, _> = client.request("get_swap_start_date", params).await; let response: Result<HashMap<String, String>, _> =
client.request("get_swap_start_date", params).await;
match response { match response {
Ok(hash) => (), Ok(hash) => (),