Update rpc tests

This commit is contained in:
binarybaron 2023-09-24 20:00:28 +02:00
parent d7b0d068b6
commit 202206a3e8
8 changed files with 432 additions and 259 deletions

View file

@ -22,12 +22,12 @@ pub struct Config {
tor_socks5_port: Option<u16>,
namespace: XmrBtcNamespace,
server_address: Option<SocketAddr>,
env_config: EnvConfig,
pub env_config: EnvConfig,
seed: Option<Seed>,
debug: bool,
json: bool,
data_dir: PathBuf,
pub is_testnet: bool,
is_testnet: bool,
}
use uuid::Uuid;
@ -127,7 +127,7 @@ pub struct Context {
bitcoin_wallet: Option<Arc<bitcoin::Wallet>>,
monero_wallet: Option<Arc<monero::Wallet>>,
monero_rpc_process: Option<monero::WalletRpcProcess>,
swap_lock: Arc<SwapLock>,
pub swap_lock: Arc<SwapLock>,
pub config: Config,
}

View file

@ -278,13 +278,10 @@ pub mod bitcoin_address {
Ok(address)
}
pub fn validate(address: bitcoin::Address, is_testnet: bool) -> Result<bitcoin::Address> {
let expected_network = if is_testnet {
bitcoin::Network::Testnet
} else {
bitcoin::Network::Bitcoin
};
pub fn validate(
address: bitcoin::Address,
expected_network: bitcoin::Network,
) -> Result<bitcoin::Address> {
if address.network != expected_network {
bail!(BitcoinAddressNetworkMismatch {
expected: expected_network,
@ -294,6 +291,18 @@ pub mod bitcoin_address {
Ok(address)
}
pub fn validate_is_testnet(
address: bitcoin::Address,
is_testnet: bool,
) -> Result<bitcoin::Address> {
let expected_network = if is_testnet {
bitcoin::Network::Testnet
} else {
bitcoin::Network::Bitcoin
};
return validate(address, expected_network);
}
}
/// Bitcoin error codes: https://github.com/bitcoin/bitcoin/blob/97d3500601c1d28642347d014a6de1e38f53ae4e/src/rpc/protocol.h#L23

View file

@ -193,7 +193,6 @@ impl Wallet {
tokio::time::sleep(Duration::from_secs(5)).await;
}
}.instrument(Span::current()));
}.instrument(Span::none()));
Subscription {
@ -787,10 +786,10 @@ impl Client {
if !self.script_history.contains_key(&script) {
self.script_history.insert(script.clone(), vec![]);
self.update_state(true)?;
}else {
} else {
self.update_state(false)?;
}
let history = self.script_history.entry(script).or_default();
let history_of_tx = history
@ -1007,7 +1006,6 @@ mod tests {
#[test]
fn given_depth_0_should_meet_confirmation_target_one() {
let script = ScriptStatus::Confirmed(Confirmed { depth: 0 });
let confirmed = script.is_confirmed_with(1 as u32);

View file

@ -70,9 +70,9 @@ where
tor,
} => {
let monero_receive_address =
monero_address::validate(monero_receive_address, is_testnet)?;
monero_address::validate_is_testnet(monero_receive_address, is_testnet)?;
let bitcoin_change_address =
bitcoin_address::validate(bitcoin_change_address, is_testnet)?;
bitcoin_address::validate_is_testnet(bitcoin_change_address, is_testnet)?;
let request = Request::new(Method::BuyXmr {
seller,
@ -150,8 +150,7 @@ where
amount,
address,
} => {
let address = bitcoin_address::validate(address, is_testnet)?;
let address = bitcoin_address::validate_is_testnet(address, is_testnet)?;
let request = Request::new(Method::WithdrawBtc { amount, address });
let context = Context::build(
@ -538,10 +537,13 @@ mod tests {
);
// since Uuid is random, copy before comparing requests
if let Method::BuyXmr { ref mut swap_id, .. } = expected_request.cmd {
if let Method::BuyXmr {
ref mut swap_id, ..
} = expected_request.cmd
{
*swap_id = match actual_request.cmd {
Method::BuyXmr { swap_id, .. } => { swap_id },
_ => panic!("Not the Method we expected")
Method::BuyXmr { swap_id, .. } => swap_id,
_ => panic!("Not the Method we expected"),
}
};
@ -574,10 +576,13 @@ mod tests {
_ => panic!("Couldn't parse result"),
};
if let Method::BuyXmr { ref mut swap_id, .. } = expected_request.cmd {
if let Method::BuyXmr {
ref mut swap_id, ..
} = expected_request.cmd
{
*swap_id = match actual_request.cmd {
Method::BuyXmr { swap_id, .. } => { swap_id },
_ => panic!("Not the Method we expected")
Method::BuyXmr { swap_id, .. } => swap_id,
_ => panic!("Not the Method we expected"),
}
};
@ -771,10 +776,13 @@ mod tests {
_ => panic!("Couldn't parse result"),
};
if let Method::BuyXmr { ref mut swap_id, .. } = expected_request.cmd {
if let Method::BuyXmr {
ref mut swap_id, ..
} = expected_request.cmd
{
*swap_id = match actual_request.cmd {
Method::BuyXmr { swap_id, .. } => { swap_id },
_ => panic!("Not the Method we expected")
Method::BuyXmr { swap_id, .. } => swap_id,
_ => panic!("Not the Method we expected"),
}
};
@ -810,10 +818,13 @@ mod tests {
_ => panic!("Couldn't parse result"),
};
if let Method::BuyXmr { ref mut swap_id, .. } = expected_request.cmd {
if let Method::BuyXmr {
ref mut swap_id, ..
} = expected_request.cmd
{
*swap_id = match actual_request.cmd {
Method::BuyXmr { swap_id, .. } => { swap_id },
_ => panic!("Not the Method we expected")
Method::BuyXmr { swap_id, .. } => swap_id,
_ => panic!("Not the Method we expected"),
}
};
@ -839,10 +850,13 @@ mod tests {
Request::resume(),
);
if let Method::BuyXmr { ref mut swap_id, .. } = expected_request.cmd {
if let Method::BuyXmr {
ref mut swap_id, ..
} = expected_request.cmd
{
*swap_id = match actual_request.cmd {
Method::BuyXmr { swap_id, .. } => { swap_id },
_ => panic!("Not the Method we expected")
Method::BuyXmr { swap_id, .. } => swap_id,
_ => panic!("Not the Method we expected"),
}
};
@ -908,10 +922,13 @@ mod tests {
_ => panic!("Couldn't parse result"),
};
if let Method::BuyXmr { ref mut swap_id, .. } = expected_request.cmd {
if let Method::BuyXmr {
ref mut swap_id, ..
} = expected_request.cmd
{
*swap_id = match actual_request.cmd {
Method::BuyXmr { swap_id, .. } => { swap_id },
_ => panic!("Not the Method we expected")
Method::BuyXmr { swap_id, .. } => swap_id,
_ => panic!("Not the Method we expected"),
}
};
@ -945,10 +962,13 @@ mod tests {
_ => panic!("Couldn't parse result"),
};
if let Method::BuyXmr { ref mut swap_id, .. } = expected_request.cmd {
if let Method::BuyXmr {
ref mut swap_id, ..
} = expected_request.cmd
{
*swap_id = match actual_request.cmd {
Method::BuyXmr { swap_id, .. } => { swap_id },
_ => panic!("Not the Method we expected")
Method::BuyXmr { swap_id, .. } => swap_id,
_ => panic!("Not the Method we expected"),
}
};
@ -971,10 +991,13 @@ mod tests {
_ => panic!("Couldn't parse result"),
};
if let Method::BuyXmr { ref mut swap_id, .. } = expected_request.cmd {
if let Method::BuyXmr {
ref mut swap_id, ..
} = expected_request.cmd
{
*swap_id = match actual_request.cmd {
Method::BuyXmr { swap_id, .. } => { swap_id },
_ => panic!("Not the Method we expected")
Method::BuyXmr { swap_id, .. } => swap_id,
_ => panic!("Not the Method we expected"),
}
};
@ -1033,10 +1056,13 @@ mod tests {
_ => panic!("Couldn't parse result"),
};
if let Method::BuyXmr { ref mut swap_id, .. } = expected_request.cmd {
if let Method::BuyXmr {
ref mut swap_id, ..
} = expected_request.cmd
{
*swap_id = match actual_request.cmd {
Method::BuyXmr { swap_id, .. } => { swap_id },
_ => panic!("Not the Method we expected")
Method::BuyXmr { swap_id, .. } => swap_id,
_ => panic!("Not the Method we expected"),
}
};
@ -1070,10 +1096,13 @@ mod tests {
_ => panic!("Couldn't parse result"),
};
if let Method::BuyXmr { ref mut swap_id, .. } = expected_request.cmd {
if let Method::BuyXmr {
ref mut swap_id, ..
} = expected_request.cmd
{
*swap_id = match actual_request.cmd {
Method::BuyXmr { swap_id, .. } => { swap_id },
_ => panic!("Not the Method we expected")
Method::BuyXmr { swap_id, .. } => swap_id,
_ => panic!("Not the Method we expected"),
}
};

View file

@ -347,13 +347,10 @@ pub mod monero_address {
})
}
pub fn validate(address: monero::Address, is_testnet: bool) -> Result<monero::Address> {
let expected_network = if is_testnet {
monero::Network::Stagenet
} else {
monero::Network::Mainnet
};
pub fn validate(
address: monero::Address,
expected_network: monero::Network,
) -> Result<monero::Address> {
if address.network != expected_network {
bail!(MoneroAddressNetworkMismatch {
expected: expected_network,
@ -362,6 +359,18 @@ pub mod monero_address {
}
Ok(address)
}
pub fn validate_is_testnet(
address: monero::Address,
is_testnet: bool,
) -> Result<monero::Address> {
let expected_network = if is_testnet {
monero::Network::Testnet
} else {
monero::Network::Mainnet
};
validate(address, expected_network)
}
}
#[cfg(test)]

View file

@ -125,8 +125,10 @@ pub fn register_modules(context: Arc<Context>) -> RpcModule<Arc<Context>> {
jsonrpsee_core::Error::Custom("Does not contain address".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.env_config.bitcoin_network,
)?;
execute_request(
params_raw,
@ -153,8 +155,10 @@ pub fn register_modules(context: Arc<Context>) -> RpcModule<Arc<Context>> {
)
.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.env_config.bitcoin_network,
)?;
let monero_receive_address = monero::Address::from_str(
params.get("monero_receive_address").ok_or_else(|| {
@ -165,8 +169,10 @@ pub fn register_modules(context: Arc<Context>) -> RpcModule<Arc<Context>> {
)
.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.env_config.monero_network,
)?;
let seller = Multiaddr::from_str(params.get("seller").ok_or_else(|| {
jsonrpsee_core::Error::Custom("Does not contain seller".to_string())

View file

@ -402,7 +402,7 @@ impl StartingBalances {
}
}
struct BobParams {
pub struct BobParams {
seed: Seed,
db_path: PathBuf,
bitcoin_wallet: Arc<bitcoin::Wallet>,
@ -413,6 +413,21 @@ struct BobParams {
}
impl BobParams {
pub fn get_concentenated_alice_address(&self) -> String {
format!(
"{}/p2p/{}",
self.alice_address.clone().to_string(),
self.alice_peer_id.clone().to_base58()
)
}
pub async fn get_change_receive_addresses(&self) -> (bitcoin::Address, monero::Address) {
(
self.bitcoin_wallet.new_address().await.unwrap(),
self.monero_wallet.get_main_address(),
)
}
pub async fn new_swap_from_db(&self, swap_id: Uuid) -> Result<(bob::Swap, cli::EventLoop)> {
let (event_loop, handle) = self.new_eventloop(swap_id).await?;
@ -529,7 +544,7 @@ pub struct TestContext {
alice_swap_handle: mpsc::Receiver<Swap>,
alice_handle: AliceApplicationHandle,
bob_params: BobParams,
pub bob_params: BobParams,
bob_starting_balances: StartingBalances,
bob_bitcoin_wallet: Arc<bitcoin::Wallet>,
bob_monero_wallet: Arc<monero::Wallet>,

View file

@ -7,82 +7,64 @@ use jsonrpsee_core::params::ObjectParams;
use serial_test::serial;
use serde_json::{json, Value};
use serde_json::Value;
use std::collections::HashMap;
use std::future::Future;
use std::net::SocketAddr;
use std::path::PathBuf;
use std::sync::Arc;
use std::time::Duration;
use swap::api::request::{Method, Request};
use swap::api::{Config, Context, SwapLock};
use swap::cli::command::{Bitcoin, Monero};
use tempfile::tempdir;
use swap::api::Context;
use tracing_subscriber::filter::LevelFilter;
use crate::harness::alice_run_until::is_xmr_lock_transaction_sent;
use crate::harness::bob_run_until::is_btc_locked;
use crate::harness::{setup_test, SlowCancelConfig, TestContext};
use swap::asb::FixedRate;
use swap::database::open_db;
use swap::network::rendezvous::XmrBtcNamespace;
use swap::protocol::{alice, bob};
use swap::tracing_ext::{capture_logs, MakeCapturingWriter};
use uuid::Uuid;
#[cfg(test)]
// to be replaced with actual "real" testing values
// 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_START_TIMEOUT_SECS: u64 = 50;
const BITCOIN_ADDR: &str = "tb1qr3em6k3gfnyl8r7q0v7t4tlnyxzgxma3lressv";
const MONERO_ADDR: &str = "53gEuGZUhP9JMEBZoGaFNzhwEgiG7hwQdMCqFxiyiTeFPmkbt1mAoNybEUvYBKHcnrSgxnVWgZsTvRBaHBNXPa8tHiCU51a";
const SELLER: &str =
"/ip4/127.0.0.1/tcp/9939/p2p/12D3KooWCdMKjesXMJz1SiZ7HgotrxuqhQJbP5sgBm2BwP1cqThi";
const SWAP_ID: &str = "ea030832-3be9-454f-bb98-5ea9a788406b";
const SERVER_START_TIMEOUT_SECS: u64 = 50;
pub async fn setup_daemon<T, F>(testfn: T)
where
T: Fn(TestContext, Client, MakeCapturingWriter, Arc<Context>) -> F,
F: Future<Output = Result<()>>,
{
setup_test(SlowCancelConfig, |harness_context| async move {
let writer = capture_logs(LevelFilter::DEBUG);
let server_address: SocketAddr = SERVER_ADDRESS.parse().unwrap();
pub async fn setup_daemon(harness_ctx: TestContext) -> (Client, MakeCapturingWriter, Arc<Context>) {
let writer = capture_logs(LevelFilter::DEBUG);
let server_address: SocketAddr = SERVER_ADDRESS.parse().unwrap();
let request = Request::new(Method::StartDaemon {
server_address: Some(server_address),
});
let request = Request::new(Method::StartDaemon {
server_address: Some(server_address),
});
let context = Arc::new(harness_context.get_bob_context().await);
let context = Arc::new(harness_ctx.get_bob_context().await);
let context_clone = context.clone();
let context_clone = context.clone();
tokio::spawn(async move {
if let Err(err) = request.call(context_clone).await {
println!("Failed to initialize daemon for testing: {}", err);
}
});
tokio::spawn(async move {
if let Err(err) = request.call(context_clone).await {
println!("Failed to initialize daemon for testing: {}", err);
}
});
for _ in 0..SERVER_START_TIMEOUT_SECS {
if writer.captured().contains("Started RPC server") {
let url = format!("ws://{}", SERVER_ADDRESS);
let client = WsClientBuilder::default().build(&url).await.unwrap();
for _ in 0..SERVER_START_TIMEOUT_SECS {
if writer.captured().contains("Started RPC server") {
let url = format!("ws://{}", SERVER_ADDRESS);
let client = WsClientBuilder::default().build(&url).await.unwrap();
return testfn(harness_context, client, writer, context).await;
}
tokio::time::sleep(Duration::from_secs(1)).await;
return (client, writer, context);
}
panic!(
"Failed to start RPC server after {} seconds",
SERVER_START_TIMEOUT_SECS
);
})
.await
tokio::time::sleep(Duration::from_secs(1)).await;
}
panic!(
"Failed to start RPC server after {} seconds",
SERVER_START_TIMEOUT_SECS
);
}
fn assert_has_keys_serde(map: &serde_json::Map<String, Value>, keys: &[&str]) {
@ -101,7 +83,8 @@ fn assert_has_keys_hashmap(map: &HashMap<String, Value>, keys: &[&str]) {
#[tokio::test]
#[serial]
pub async fn can_start_server() {
setup_daemon(|_, _, _, _| async move {
setup_test(SlowCancelConfig, |harness_ctx| async move {
let (_, _, _) = setup_daemon(harness_ctx).await;
assert!(true);
Ok(())
})
@ -111,7 +94,9 @@ pub async fn can_start_server() {
#[tokio::test]
#[serial]
pub async fn get_bitcoin_balance() {
setup_daemon(|_, client| async move {
setup_test(SlowCancelConfig, |harness_ctx| async move {
let (client, _, _) = setup_daemon(harness_ctx).await;
let response: HashMap<String, i32> = client
.request("get_bitcoin_balance", ObjectParams::new())
.await
@ -127,7 +112,9 @@ pub async fn get_bitcoin_balance() {
#[tokio::test]
#[serial]
pub async fn get_bitcoin_balance_with_log_reference_id() {
setup_daemon(|_, client, writer| async move {
setup_test(SlowCancelConfig, |harness_ctx| async move {
let (client, writer, _) = setup_daemon(harness_ctx).await;
let mut params = ObjectParams::new();
params.insert("log_reference_id", "test_ref_id").unwrap();
@ -144,7 +131,7 @@ pub async fn get_bitcoin_balance_with_log_reference_id() {
#[tokio::test]
#[serial]
pub async fn get_history() {
setup_daemon(|mut harness_ctx, client| async move {
setup_test(SlowCancelConfig, |mut harness_ctx| async move {
// Start a swap and wait for xmr lock transaction to be published (XmrLockTransactionSent)
let (bob_swap, _) = harness_ctx.bob_swap().await;
let bob_swap_id = bob_swap.id;
@ -157,6 +144,8 @@ pub async fn get_history() {
)
.await?;
let (client, _, _) = setup_daemon(harness_ctx).await;
let response: HashMap<String, Vec<(Uuid, String)>> = client
.request("get_history", ObjectParams::new())
.await
@ -173,7 +162,7 @@ pub async fn get_history() {
#[tokio::test]
#[serial]
pub async fn get_raw_states() {
setup_daemon(|mut harness_ctx, client| async move {
setup_test(SlowCancelConfig, |mut harness_ctx| async move {
// Start a swap and wait for xmr lock transaction to be published (XmrLockTransactionSent)
let (bob_swap, _) = harness_ctx.bob_swap().await;
let bob_swap_id = bob_swap.id;
@ -186,6 +175,8 @@ pub async fn get_raw_states() {
)
.await?;
let (client, _, _) = setup_daemon(harness_ctx).await;
let response: HashMap<String, HashMap<Uuid, Vec<Value>>> = client
.request("get_raw_states", ObjectParams::new())
.await
@ -204,7 +195,7 @@ pub async fn get_raw_states() {
#[tokio::test]
#[serial]
pub async fn get_swap_info_valid_swap_id() {
setup_daemon(|mut harness_ctx, client| async move {
setup_test(SlowCancelConfig, |mut harness_ctx| async move {
// Start a swap and wait for xmr lock transaction to be published (XmrLockTransactionSent)
let (bob_swap, _) = harness_ctx.bob_swap().await;
let bob_swap_id = bob_swap.id;
@ -217,6 +208,8 @@ pub async fn get_swap_info_valid_swap_id() {
)
.await?;
let (client, _, _) = setup_daemon(harness_ctx).await;
let mut params = ObjectParams::new();
params.insert("swap_id", bob_swap_id).unwrap();
let response: HashMap<String, Value> =
@ -291,7 +284,9 @@ pub async fn get_swap_info_valid_swap_id() {
#[tokio::test]
#[serial]
pub async fn swap_endpoints_invalid_or_missing_swap_id() {
setup_daemon(|_, client| async move {
setup_test(SlowCancelConfig, |mut harness_ctx| async move {
let (client, _, _) = setup_daemon(harness_ctx).await;
for method in ["get_swap_info", "resume_swap", "cancel_refund_swap"].iter() {
let mut params = ObjectParams::new();
params.insert("swap_id", "invalid_swap").unwrap();
@ -318,7 +313,9 @@ pub async fn swap_endpoints_invalid_or_missing_swap_id() {
#[tokio::test]
pub async fn list_sellers_missing_rendezvous_point() {
setup_daemon(|_, client| async move {
setup_test(SlowCancelConfig, |harness_ctx| async move {
let (client, _, _) = setup_daemon(harness_ctx).await;
let params = ObjectParams::new();
let result: Result<HashMap<String, String>, _> =
client.request("list_sellers", params).await;
@ -330,222 +327,332 @@ pub async fn list_sellers_missing_rendezvous_point() {
.await;
}
/*
#[tokio::test]
#[serial]
pub async fn resume_swap_valid_swap_id() {
let (client, _, _) = initialize_context().await;
let mut params = ObjectParams::new();
params.insert("swap_id", SWAP_ID).unwrap();
let response: Result<HashMap<String, String>, _> = client.request("resume_swap", params).await;
response.expect("Expected a HashMap, got an error");
setup_test(SlowCancelConfig, |harness_ctx| async move {
let (client, _, _) = setup_daemon(harness_ctx).await;
let params = ObjectParams::new();
let result: Result<HashMap<String, String>, _> =
client.request("list_sellers", params).await;
result.expect_err("Expected an error when rendezvous_point is missing");
Ok(())
})
.await;
}
#[tokio::test]
#[serial]
pub async fn withdraw_btc_missing_address() {
let (client, _, _) = initialize_context().await;
let params = ObjectParams::new();
let response: Result<HashMap<String, String>, _> = client.request("withdraw_btc", params).await;
response.expect_err("Expected an error when withdraw_address is missing");
setup_test(SlowCancelConfig, |harness_ctx| async move {
let (client, _, _) = setup_daemon(harness_ctx).await;
let params = ObjectParams::new();
let response: Result<HashMap<String, String>, _> =
client.request("withdraw_btc", params).await;
response.expect_err("Expected an error when withdraw_address is missing");
Ok(())
})
.await;
}
#[tokio::test]
#[serial]
pub async fn withdraw_btc_invalid_address() {
let (client, _, _) = initialize_context().await;
let mut params = ObjectParams::new();
params.insert("address", "invalid_address").unwrap();
let response: Result<HashMap<String, String>, _> = client.request("withdraw_btc", params).await;
response.expect_err("Expected an error when withdraw_address is malformed");
setup_test(SlowCancelConfig, |harness_ctx| async move {
let (client, _, _) = setup_daemon(harness_ctx).await;
let mut params = ObjectParams::new();
params.insert("address", "invalid_address").unwrap();
let response: Result<HashMap<String, String>, _> =
client.request("withdraw_btc", params).await;
response.expect_err("Expected an error when withdraw_address is malformed");
Ok(())
})
.await
}
#[tokio::test]
#[serial]
pub async fn withdraw_btc_zero_amount() {
let (client, _, _) = initialize_context().await;
let mut params = ObjectParams::new();
params.insert("address", BITCOIN_ADDR).unwrap();
params.insert("amount", "0").unwrap();
let response: Result<HashMap<String, String>, _> = client.request("withdraw_btc", params).await;
response.expect_err("Expected an error when amount is 0");
setup_test(SlowCancelConfig, |harness_ctx| async move {
let (client, _, _) = setup_daemon(harness_ctx).await;
let mut params = ObjectParams::new();
params.insert("address", BITCOIN_ADDR).unwrap();
params.insert("amount", "0").unwrap();
let response: Result<HashMap<String, String>, _> =
client.request("withdraw_btc", params).await;
response.expect_err("Expected an error when amount is 0");
Ok(())
})
.await;
}
#[tokio::test]
#[serial]
pub async fn withdraw_btc_valid_params() {
let (client, _, _) = initialize_context().await;
let mut params = ObjectParams::new();
params.insert("address", BITCOIN_ADDR).unwrap();
params.insert("amount", "0.1").unwrap();
let response: Result<HashMap<String, String>, _> = client.request("withdraw_btc", params).await;
response.expect("Expected a HashMap, got an error");
setup_test(SlowCancelConfig, |harness_ctx| async move {
let (client, _, _) = setup_daemon(harness_ctx).await;
let mut params = ObjectParams::new();
params
.insert("address", "mkHS9ne12qx9pS9VojpwU5xtRd4T7X7ZUt")
.unwrap();
params.insert("amount", 0.01).unwrap();
let response: HashMap<String, Value> = client
.request("withdraw_btc", params)
.await
.expect("Expected a valid response");
assert_has_keys_hashmap(&response, &["signed_tx", "amount", "txid"]);
assert!(response.get("amount").unwrap().as_f64().unwrap(), 1_000_000);
Ok(())
})
.await;
}
#[tokio::test]
#[serial]
pub async fn buy_xmr_no_params() {
let (client, _, _) = initialize_context().await;
let params = ObjectParams::new();
let response: Result<HashMap<String, String>, _> = client.request("buy_xmr", params).await;
response.expect_err("Expected an error when no params are given");
setup_test(SlowCancelConfig, |harness_ctx| async move {
let (client, _, _) = setup_daemon(harness_ctx).await;
let params = ObjectParams::new();
let response: Result<HashMap<String, String>, _> = client.request("buy_xmr", params).await;
response.expect_err("Expected an error when no params are given");
Ok(())
})
.await;
}
#[tokio::test]
#[serial]
pub async fn buy_xmr_missing_seller() {
let (client, _, _) = initialize_context().await;
let mut params = ObjectParams::new();
params
.insert("bitcoin_change_address", BITCOIN_ADDR)
.unwrap();
params
.insert("monero_receive_address", MONERO_ADDR)
.unwrap();
let response: Result<HashMap<String, String>, _> = client.request("buy_xmr", params).await;
response.expect_err("Expected an error when seller is missing");
setup_test(SlowCancelConfig, |harness_ctx| async move {
let (client, _, _) = setup_daemon(harness_ctx).await;
let mut params = ObjectParams::new();
params
.insert("bitcoin_change_address", BITCOIN_ADDR)
.unwrap();
params
.insert("monero_receive_address", MONERO_ADDR)
.unwrap();
let response: Result<HashMap<String, String>, _> = client.request("buy_xmr", params).await;
response.expect_err("Expected an error when seller is missing");
Ok(())
})
.await;
}
#[tokio::test]
#[serial]
pub async fn buy_xmr_missing_monero_address() {
let (client, _, _) = initialize_context().await;
let mut params = ObjectParams::new();
params
.insert("bitcoin_change_address", BITCOIN_ADDR)
.unwrap();
params.insert("seller", SELLER).unwrap();
let response: Result<HashMap<String, String>, _> = client.request("buy_xmr", params).await;
response.expect_err("Expected an error when monero_receive_address is missing");
}
setup_test(SlowCancelConfig, |harness_ctx| async move {
let (client, _, _) = setup_daemon(harness_ctx).await;
let mut params = ObjectParams::new();
params
.insert("bitcoin_change_address", BITCOIN_ADDR)
.unwrap();
params.insert("seller", SELLER).unwrap();
let response: Result<HashMap<String, String>, _> = client.request("buy_xmr", params).await;
response.expect_err("Expected an error when monero_receive_address is missing");
Ok(())
})
.await;
}
#[tokio::test]
#[serial]
pub async fn buy_xmr_missing_bitcoin_address() {
let (client, _, _) = initialize_context().await;
let mut params = ObjectParams::new();
params
.insert("monero_receive_address", MONERO_ADDR)
.unwrap();
params.insert("seller", SELLER).unwrap();
let response: Result<HashMap<String, String>, _> = client.request("buy_xmr", params).await;
response.expect_err("Expected an error when bitcoin_change_address is missing");
setup_test(SlowCancelConfig, |harness_ctx| async move {
let (client, _, _) = setup_daemon(harness_ctx).await;
let mut params = ObjectParams::new();
params
.insert("monero_receive_address", MONERO_ADDR)
.unwrap();
params.insert("seller", SELLER).unwrap();
let response: Result<HashMap<String, String>, _> = client.request("buy_xmr", params).await;
response.expect_err("Expected an error when bitcoin_change_address is missing");
Ok(())
})
.await;
}
#[tokio::test]
#[serial]
pub async fn buy_xmr_malformed_bitcoin_address() {
let (client, _, _) = initialize_context().await;
let mut params = ObjectParams::new();
params
.insert("bitcoin_change_address", "invalid_address")
.unwrap();
params
.insert("monero_receive_address", MONERO_ADDR)
.unwrap();
params.insert("seller", SELLER).unwrap();
let response: Result<HashMap<String, String>, _> = client.request("buy_xmr", params).await;
response.expect_err("Expected an error when bitcoin_change_address is malformed");
setup_test(SlowCancelConfig, |harness_ctx| async move {
let (client, writer, _) = setup_daemon(harness_ctx).await;
let mut params = ObjectParams::new();
params
.insert("bitcoin_change_address", "invalid_address")
.unwrap();
params
.insert("monero_receive_address", MONERO_ADDR)
.unwrap();
params.insert("seller", SELLER).unwrap();
let response: Result<HashMap<String, String>, _> = client.request("buy_xmr", params).await;
response.expect_err("Expected an error when bitcoin_change_address is malformed");
Ok(())
})
.await;
}
#[tokio::test]
#[serial]
pub async fn buy_xmr_malformed_monero_address() {
let (client, _, _) = initialize_context().await;
let mut params = ObjectParams::new();
params
.insert("bitcoin_change_address", BITCOIN_ADDR)
.unwrap();
params
.insert("monero_receive_address", "invalid_address")
.unwrap();
params.insert("seller", SELLER).unwrap();
let response: Result<HashMap<String, String>, _> = client.request("buy_xmr", params).await;
response.expect_err("Expected an error when monero_receive_address is malformed");
setup_test(SlowCancelConfig, |harness_ctx| async move {
let (client, _, _) = setup_daemon(harness_ctx).await;
let mut params = ObjectParams::new();
params
.insert("bitcoin_change_address", BITCOIN_ADDR)
.unwrap();
params
.insert("monero_receive_address", "invalid_address")
.unwrap();
params.insert("seller", SELLER).unwrap();
let response: Result<HashMap<String, String>, _> = client.request("buy_xmr", params).await;
response.expect_err("Expected an error when monero_receive_address is malformed");
Ok(())
})
.await;
}
#[tokio::test]
#[serial]
pub async fn buy_xmr_malformed_seller() {
let (client, _, _) = initialize_context().await;
let mut params = ObjectParams::new();
params
.insert("bitcoin_change_address", BITCOIN_ADDR)
.unwrap();
params
.insert("monero_receive_address", MONERO_ADDR)
.unwrap();
params.insert("seller", "invalid_seller").unwrap();
let response: Result<HashMap<String, String>, _> = client.request("buy_xmr", params).await;
response.expect_err("Expected an error when seller is malformed");
setup_test(SlowCancelConfig, |harness_ctx| async move {
let (client, _, _) = setup_daemon(harness_ctx).await;
let mut params = ObjectParams::new();
params
.insert("bitcoin_change_address", BITCOIN_ADDR)
.unwrap();
params
.insert("monero_receive_address", MONERO_ADDR)
.unwrap();
params.insert("seller", "invalid_seller").unwrap();
let response: Result<HashMap<String, String>, _> = client.request("buy_xmr", params).await;
response.expect_err("Expected an error when seller is malformed");
Ok(())
})
.await;
}
#[tokio::test]
#[serial]
pub async fn buy_xmr_valid_params() {
let (client, _, _) = initialize_context().await;
let mut params = ObjectParams::new();
params
.insert("bitcoin_change_address", BITCOIN_ADDR)
.unwrap();
params
.insert("monero_receive_address", MONERO_ADDR)
.unwrap();
params.insert("seller", SELLER).unwrap();
let response: Result<HashMap<String, String>, _> = client.request("buy_xmr", params).await;
response.expect("Expected a HashMap, got an error");
}
#[tokio::test]
#[serial]
pub async fn suspend_current_swap_no_swap_running() {
let (client, _, _) = initialize_context().await;
let response: Result<HashMap<String, String>, _> = client
.request("suspend_current_swap", ObjectParams::new())
.await;
response.expect_err("Expected an error when no swap is running");
setup_test(SlowCancelConfig, |harness_ctx| async move {
let (client, _, _) = setup_daemon(harness_ctx).await;
let response: Result<HashMap<String, String>, _> = client
.request("suspend_current_swap", ObjectParams::new())
.await;
response.expect_err("Expected an error when no swap is running");
Ok(())
})
.await;
}
#[tokio::test]
#[serial]
pub async fn suspend_current_swap_swap_running() {
let (client, _, ctx) = initialize_context().await;
ctx.swap_lock
.acquire_swap_lock(Uuid::parse_str(SWAP_ID).unwrap())
.await
.unwrap();
setup_test(SlowCancelConfig, |harness_ctx| async move {
let (client, _, ctx) = setup_daemon(harness_ctx).await;
tokio::spawn(async move {
// Immediately release lock when suspend signal is received. Mocks a running swap that is then cancelled.
ctx.swap_lock
.listen_for_swap_force_suspension()
.acquire_swap_lock(Uuid::parse_str(SWAP_ID).unwrap())
.await
.unwrap();
ctx.swap_lock.release_swap_lock().await.unwrap();
});
let response: HashMap<String, String> = client
.request("suspend_current_swap", ObjectParams::new())
.await
.unwrap();
assert_eq!(
response,
HashMap::from([("swapId".to_string(), SWAP_ID.to_string())])
);
tokio::spawn(async move {
// Immediately release lock when suspend signal is received. Mocks a running swap that is then cancelled.
ctx.swap_lock
.listen_for_swap_force_suspension()
.await
.unwrap();
ctx.swap_lock.release_swap_lock().await.unwrap();
});
let response: HashMap<String, String> = client
.request("suspend_current_swap", ObjectParams::new())
.await
.unwrap();
assert_eq!(
response,
HashMap::from([("swapId".to_string(), SWAP_ID.to_string())])
);
Ok(())
})
.await;
}
#[tokio::test]
#[serial]
pub async fn suspend_current_swap_timeout() {
let (client, _, ctx) = initialize_context().await;
ctx.swap_lock
.acquire_swap_lock(Uuid::parse_str(SWAP_ID).unwrap())
.await
.unwrap();
setup_test(SlowCancelConfig, |harness_ctx| async move {
let (client, _, ctx) = setup_daemon(harness_ctx).await;
let response: Result<HashMap<String, String>, _> = client
.request("suspend_current_swap", ObjectParams::new())
.await;
response.expect_err("Expected an error when suspend signal times out");
ctx.swap_lock
.acquire_swap_lock(Uuid::parse_str(SWAP_ID).unwrap())
.await
.unwrap();
let response: Result<HashMap<String, String>, _> = client
.request("suspend_current_swap", ObjectParams::new())
.await;
response.expect_err("Expected an error when suspend signal times out");
Ok(())
})
.await;
}
#[tokio::test]
#[serial]
pub async fn buy_xmr_valid_params() {
setup_test(SlowCancelConfig, |mut harness_ctx| async move {
let alice_addr = harness_ctx.bob_params.get_concentenated_alice_address();
let (change_address, receive_address) =
harness_ctx.bob_params.get_change_receive_addresses().await;
let (client, _, _) = setup_daemon(harness_ctx).await;
let mut params = ObjectParams::new();
params
.insert("bitcoin_change_address", change_address)
.unwrap();
params
.insert("monero_receive_address", receive_address)
.unwrap();
params.insert("seller", alice_addr).unwrap();
let response: HashMap<String, Value> = client
.request("buy_xmr", params)
.await
.expect("Expected a HashMap, got an error");
assert_has_keys_hashmap(&response, &["swapId"]);
Ok(())
})
.await;
}
*/