mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2025-11-30 20:46:33 -05:00
WIP: Integration tests for RPC server
This commit is contained in:
parent
3c39a34a6e
commit
d3bb838806
9 changed files with 746 additions and 568 deletions
|
|
@ -123,7 +123,7 @@ impl SwapLock {
|
|||
// workaround for warning over monero_rpc_process which we must own but not read
|
||||
#[allow(dead_code)]
|
||||
pub struct Context {
|
||||
pub db: Arc<dyn Database + Send + Sync>,
|
||||
db: Arc<dyn Database + Send + Sync>,
|
||||
bitcoin_wallet: Option<Arc<bitcoin::Wallet>>,
|
||||
monero_wallet: Option<Arc<monero::Wallet>>,
|
||||
monero_rpc_process: Option<monero::WalletRpcProcess>,
|
||||
|
|
@ -205,6 +205,25 @@ impl Context {
|
|||
|
||||
Ok(context)
|
||||
}
|
||||
|
||||
pub async fn for_harness(
|
||||
seed: Seed,
|
||||
env_config: EnvConfig,
|
||||
db_path: PathBuf,
|
||||
bob_bitcoin_wallet: Arc<bitcoin::Wallet>,
|
||||
bob_monero_wallet: Arc<monero::Wallet>,
|
||||
) -> Self {
|
||||
let config = Config::for_harness(seed, env_config);
|
||||
|
||||
Self {
|
||||
bitcoin_wallet: Some(bob_bitcoin_wallet),
|
||||
monero_wallet: Some(bob_monero_wallet),
|
||||
config,
|
||||
db: open_db(db_path).await.unwrap(),
|
||||
monero_rpc_process: None,
|
||||
swap_lock: Arc::new(SwapLock::new()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Context {
|
||||
|
|
@ -288,6 +307,25 @@ fn env_config_from(testnet: bool) -> EnvConfig {
|
|||
Mainnet::get_config()
|
||||
}
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn for_harness(seed: Seed, env_config: EnvConfig) -> Self {
|
||||
let data_dir = data::data_dir_from(None, false).unwrap();
|
||||
|
||||
Self {
|
||||
tor_socks5_port: None,
|
||||
namespace: XmrBtcNamespace::from_is_testnet(false),
|
||||
server_address: None,
|
||||
env_config,
|
||||
seed: Some(seed),
|
||||
debug: false,
|
||||
json: false,
|
||||
is_testnet: false,
|
||||
data_dir,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod api_test {
|
||||
use super::*;
|
||||
|
|
@ -350,38 +388,30 @@ pub mod api_test {
|
|||
}
|
||||
};
|
||||
|
||||
Request::new(
|
||||
Method::BuyXmr {
|
||||
seller,
|
||||
bitcoin_change_address,
|
||||
monero_receive_address,
|
||||
swap_id: Uuid::new_v4(),
|
||||
},
|
||||
)
|
||||
Request::new(Method::BuyXmr {
|
||||
seller,
|
||||
bitcoin_change_address,
|
||||
monero_receive_address,
|
||||
swap_id: Uuid::new_v4(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn resume() -> Request {
|
||||
Request::new(
|
||||
Method::Resume {
|
||||
swap_id: Uuid::from_str(SWAP_ID).unwrap(),
|
||||
},
|
||||
)
|
||||
Request::new(Method::Resume {
|
||||
swap_id: Uuid::from_str(SWAP_ID).unwrap(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn cancel() -> Request {
|
||||
Request::new(
|
||||
Method::CancelAndRefund {
|
||||
swap_id: Uuid::from_str(SWAP_ID).unwrap(),
|
||||
},
|
||||
)
|
||||
Request::new(Method::CancelAndRefund {
|
||||
swap_id: Uuid::from_str(SWAP_ID).unwrap(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn refund() -> Request {
|
||||
Request::new(
|
||||
Method::CancelAndRefund {
|
||||
swap_id: Uuid::from_str(SWAP_ID).unwrap(),
|
||||
},
|
||||
)
|
||||
Request::new(Method::CancelAndRefund {
|
||||
swap_id: Uuid::from_str(SWAP_ID).unwrap(),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -193,6 +193,9 @@ impl Request {
|
|||
.as_ref()
|
||||
.context("Could not get Bitcoin wallet")?;
|
||||
|
||||
let state = context.db.get_state(swap_id).await?;
|
||||
let is_completed = state.swap_finished();
|
||||
|
||||
let peerId = context
|
||||
.db
|
||||
.get_peer_id(swap_id)
|
||||
|
|
@ -205,9 +208,6 @@ impl Request {
|
|||
.await
|
||||
.with_context(|| "Could not get addressess")?;
|
||||
|
||||
let state = context.db.get_state(swap_id).await?;
|
||||
let is_completed = state.swap_finished();
|
||||
|
||||
let start_date = context.db.get_swap_start_date(swap_id).await?;
|
||||
|
||||
let swap_state: BobState = state.try_into()?;
|
||||
|
|
@ -346,7 +346,7 @@ impl Request {
|
|||
|
||||
let (event_loop, mut event_loop_handle) =
|
||||
EventLoop::new(swap_id, swarm, seller_peer_id)?;
|
||||
let event_loop = tokio::spawn(event_loop.run().instrument(Span::current()));
|
||||
let event_loop = tokio::spawn(event_loop.run().instrument(Span::none()));
|
||||
|
||||
let max_givable = || bitcoin_wallet.max_giveable(TxLock::script_size());
|
||||
let estimate_fee = |amount| bitcoin_wallet.estimate_fee(TxLock::weight(), amount);
|
||||
|
|
@ -429,7 +429,7 @@ impl Request {
|
|||
.release_swap_lock()
|
||||
.await
|
||||
.expect("Could not release swap lock");
|
||||
}.instrument(Span::current()));
|
||||
}.instrument(Span::none()));
|
||||
|
||||
Ok(json!({
|
||||
"swapId": swap_id.to_string(),
|
||||
|
|
@ -483,7 +483,7 @@ impl Request {
|
|||
|
||||
let (event_loop, event_loop_handle) =
|
||||
EventLoop::new(swap_id, swarm, seller_peer_id)?;
|
||||
let handle = tokio::spawn(event_loop.run().instrument(Span::current()));
|
||||
let handle = tokio::spawn(event_loop.run().instrument(Span::none()));
|
||||
|
||||
let monero_receive_address = context.db.get_monero_address(swap_id).await?;
|
||||
let swap = Swap::from_db(
|
||||
|
|
@ -529,7 +529,7 @@ impl Request {
|
|||
.release_swap_lock()
|
||||
.await
|
||||
.expect("Could not release swap lock");
|
||||
}.instrument(Span::current()));
|
||||
}.instrument(Span::none()));
|
||||
Ok(json!({
|
||||
"result": "ok",
|
||||
}))
|
||||
|
|
@ -574,7 +574,7 @@ impl Request {
|
|||
Method::GetRawStates => {
|
||||
let raw_history = context.db.raw_all().await?;
|
||||
|
||||
Ok(json!({ "raw_history": raw_history }))
|
||||
Ok(json!({ "raw_states": raw_history }))
|
||||
}
|
||||
Method::Config => {
|
||||
let data_dir_display = context.config.data_dir.display();
|
||||
|
|
|
|||
|
|
@ -75,10 +75,10 @@ mod tests {
|
|||
assert_eq!((amount, fees), (expected_amount, expected_fees));
|
||||
assert_eq!(
|
||||
writer.captured(),
|
||||
r" INFO swap: Received quote price=0.00100000 BTC minimum_amount=0.00000000 BTC maximum_amount=0.01000000 BTC
|
||||
INFO swap: Deposit at least 0.00001000 BTC to cover the min quantity with fee!
|
||||
INFO swap: Waiting for Bitcoin deposit deposit_address=1PdfytjS7C8wwd9Lq5o4x9aXA2YRqaCpH6 min_deposit=0.00001000 BTC max_giveable=0.00000000 BTC minimum_amount=0.00000000 BTC maximum_amount=0.01000000 BTC
|
||||
INFO swap: Received Bitcoin new_balance=0.00100000 BTC max_giveable=0.00090000 BTC
|
||||
r" INFO swap::api::request: Received quote price=0.001 BTC minimum_amount=0 BTC maximum_amount=0.01 BTC
|
||||
INFO swap::api::request: Deposit at least 0.00001 BTC to cover the min quantity with fee!
|
||||
INFO swap::api::request: Waiting for Bitcoin deposit deposit_address=1PdfytjS7C8wwd9Lq5o4x9aXA2YRqaCpH6 min_deposit=0.00001 BTC max_giveable=0 BTC minimum_amount=0 BTC maximum_amount=0.01 BTC
|
||||
INFO swap::api::request: Received Bitcoin new_balance=0.001 BTC max_giveable=0.0009 BTC
|
||||
"
|
||||
);
|
||||
}
|
||||
|
|
@ -112,10 +112,10 @@ mod tests {
|
|||
assert_eq!((amount, fees), (expected_amount, expected_fees));
|
||||
assert_eq!(
|
||||
writer.captured(),
|
||||
r" INFO swap: Received quote price=0.00100000 BTC minimum_amount=0.00000000 BTC maximum_amount=0.01000000 BTC
|
||||
INFO swap: Deposit at least 0.00001000 BTC to cover the min quantity with fee!
|
||||
INFO swap: Waiting for Bitcoin deposit deposit_address=1PdfytjS7C8wwd9Lq5o4x9aXA2YRqaCpH6 min_deposit=0.00001000 BTC max_giveable=0.00000000 BTC minimum_amount=0.00000000 BTC maximum_amount=0.01000000 BTC
|
||||
INFO swap: Received Bitcoin new_balance=0.10010000 BTC max_giveable=0.10000000 BTC
|
||||
r" INFO swap::api::request: Received quote price=0.001 BTC minimum_amount=0 BTC maximum_amount=0.01 BTC
|
||||
INFO swap::api::request: Deposit at least 0.00001 BTC to cover the min quantity with fee!
|
||||
INFO swap::api::request: Waiting for Bitcoin deposit deposit_address=1PdfytjS7C8wwd9Lq5o4x9aXA2YRqaCpH6 min_deposit=0.00001 BTC max_giveable=0 BTC minimum_amount=0 BTC maximum_amount=0.01 BTC
|
||||
INFO swap::api::request: Received Bitcoin new_balance=0.1001 BTC max_giveable=0.1 BTC
|
||||
"
|
||||
);
|
||||
}
|
||||
|
|
@ -149,7 +149,7 @@ mod tests {
|
|||
assert_eq!((amount, fees), (expected_amount, expected_fees));
|
||||
assert_eq!(
|
||||
writer.captured(),
|
||||
" INFO swap: Received quote price=0.00100000 BTC minimum_amount=0.00000000 BTC maximum_amount=0.01000000 BTC\n"
|
||||
" INFO swap::api::request: Received quote price=0.001 BTC minimum_amount=0 BTC maximum_amount=0.01 BTC\n"
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -182,7 +182,7 @@ mod tests {
|
|||
assert_eq!((amount, fees), (expected_amount, expected_fees));
|
||||
assert_eq!(
|
||||
writer.captured(),
|
||||
" INFO swap: Received quote price=0.00100000 BTC minimum_amount=0.00000000 BTC maximum_amount=0.01000000 BTC\n"
|
||||
" INFO swap::api::request: Received quote price=0.001 BTC minimum_amount=0 BTC maximum_amount=0.01 BTC\n"
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -215,10 +215,10 @@ mod tests {
|
|||
assert_eq!((amount, fees), (expected_amount, expected_fees));
|
||||
assert_eq!(
|
||||
writer.captured(),
|
||||
r" INFO swap: Received quote price=0.00100000 BTC minimum_amount=0.01000000 BTC maximum_amount=184467440737.09551615 BTC
|
||||
INFO swap: Deposit at least 0.01001000 BTC to cover the min quantity with fee!
|
||||
INFO swap: Waiting for Bitcoin deposit deposit_address=1PdfytjS7C8wwd9Lq5o4x9aXA2YRqaCpH6 min_deposit=0.01001000 BTC max_giveable=0.00000000 BTC minimum_amount=0.01000000 BTC maximum_amount=184467440737.09551615 BTC
|
||||
INFO swap: Received Bitcoin new_balance=0.01010000 BTC max_giveable=0.01000000 BTC
|
||||
r" INFO swap::api::request: Received quote price=0.001 BTC minimum_amount=0.01 BTC maximum_amount=184467440737.09551615 BTC
|
||||
INFO swap::api::request: Deposit at least 0.01001 BTC to cover the min quantity with fee!
|
||||
INFO swap::api::request: Waiting for Bitcoin deposit deposit_address=1PdfytjS7C8wwd9Lq5o4x9aXA2YRqaCpH6 min_deposit=0.01001 BTC max_giveable=0 BTC minimum_amount=0.01 BTC maximum_amount=184467440737.09551615 BTC
|
||||
INFO swap::api::request: Received Bitcoin new_balance=0.0101 BTC max_giveable=0.01 BTC
|
||||
"
|
||||
);
|
||||
}
|
||||
|
|
@ -252,10 +252,10 @@ mod tests {
|
|||
assert_eq!((amount, fees), (expected_amount, expected_fees));
|
||||
assert_eq!(
|
||||
writer.captured(),
|
||||
r" INFO swap: Received quote price=0.00100000 BTC minimum_amount=0.01000000 BTC maximum_amount=184467440737.09551615 BTC
|
||||
INFO swap: Deposit at least 0.00991000 BTC to cover the min quantity with fee!
|
||||
INFO swap: Waiting for Bitcoin deposit deposit_address=1PdfytjS7C8wwd9Lq5o4x9aXA2YRqaCpH6 min_deposit=0.00991000 BTC max_giveable=0.00010000 BTC minimum_amount=0.01000000 BTC maximum_amount=184467440737.09551615 BTC
|
||||
INFO swap: Received Bitcoin new_balance=0.01010000 BTC max_giveable=0.01000000 BTC
|
||||
r" INFO swap::api::request: Received quote price=0.001 BTC minimum_amount=0.01 BTC maximum_amount=184467440737.09551615 BTC
|
||||
INFO swap::api::request: Deposit at least 0.00991 BTC to cover the min quantity with fee!
|
||||
INFO swap::api::request: Waiting for Bitcoin deposit deposit_address=1PdfytjS7C8wwd9Lq5o4x9aXA2YRqaCpH6 min_deposit=0.00991 BTC max_giveable=0.0001 BTC minimum_amount=0.01 BTC maximum_amount=184467440737.09551615 BTC
|
||||
INFO swap::api::request: Received Bitcoin new_balance=0.0101 BTC max_giveable=0.01 BTC
|
||||
"
|
||||
);
|
||||
}
|
||||
|
|
@ -292,13 +292,13 @@ mod tests {
|
|||
assert!(matches!(error, tokio::time::error::Elapsed { .. }));
|
||||
assert_eq!(
|
||||
writer.captured(),
|
||||
r" INFO swap: Received quote price=0.00100000 BTC minimum_amount=0.10000000 BTC maximum_amount=184467440737.09551615 BTC
|
||||
INFO swap: Deposit at least 0.10001000 BTC to cover the min quantity with fee!
|
||||
INFO swap: Waiting for Bitcoin deposit deposit_address=1PdfytjS7C8wwd9Lq5o4x9aXA2YRqaCpH6 min_deposit=0.10001000 BTC max_giveable=0.00000000 BTC minimum_amount=0.10000000 BTC maximum_amount=184467440737.09551615 BTC
|
||||
INFO swap: Received Bitcoin new_balance=0.01010000 BTC max_giveable=0.01000000 BTC
|
||||
INFO swap: Deposited amount is less than `min_quantity`
|
||||
INFO swap: Deposit at least 0.09001000 BTC to cover the min quantity with fee!
|
||||
INFO swap: Waiting for Bitcoin deposit deposit_address=1PdfytjS7C8wwd9Lq5o4x9aXA2YRqaCpH6 min_deposit=0.09001000 BTC max_giveable=0.01000000 BTC minimum_amount=0.10000000 BTC maximum_amount=184467440737.09551615 BTC
|
||||
r" INFO swap::api::request: Received quote price=0.001 BTC minimum_amount=0.1 BTC maximum_amount=184467440737.09551615 BTC
|
||||
INFO swap::api::request: Deposit at least 0.10001 BTC to cover the min quantity with fee!
|
||||
INFO swap::api::request: Waiting for Bitcoin deposit deposit_address=1PdfytjS7C8wwd9Lq5o4x9aXA2YRqaCpH6 min_deposit=0.10001 BTC max_giveable=0 BTC minimum_amount=0.1 BTC maximum_amount=184467440737.09551615 BTC
|
||||
INFO swap::api::request: Received Bitcoin new_balance=0.0101 BTC max_giveable=0.01 BTC
|
||||
INFO swap::api::request: Deposited amount is less than `min_quantity`
|
||||
INFO swap::api::request: Deposit at least 0.09001 BTC to cover the min quantity with fee!
|
||||
INFO swap::api::request: Waiting for Bitcoin deposit deposit_address=1PdfytjS7C8wwd9Lq5o4x9aXA2YRqaCpH6 min_deposit=0.09001 BTC max_giveable=0.01 BTC minimum_amount=0.1 BTC maximum_amount=184467440737.09551615 BTC
|
||||
"
|
||||
);
|
||||
}
|
||||
|
|
@ -341,10 +341,10 @@ mod tests {
|
|||
|
||||
assert_eq!(
|
||||
writer.captured(),
|
||||
r" INFO swap: Received quote price=0.00100000 BTC minimum_amount=0.10000000 BTC maximum_amount=184467440737.09551615 BTC
|
||||
INFO swap: Deposit at least 0.10001000 BTC to cover the min quantity with fee!
|
||||
INFO swap: Waiting for Bitcoin deposit deposit_address=1PdfytjS7C8wwd9Lq5o4x9aXA2YRqaCpH6 min_deposit=0.10001000 BTC max_giveable=0.00000000 BTC minimum_amount=0.10000000 BTC maximum_amount=184467440737.09551615 BTC
|
||||
INFO swap: Received Bitcoin new_balance=0.21000000 BTC max_giveable=0.20000000 BTC
|
||||
r" INFO swap::api::request: Received quote price=0.001 BTC minimum_amount=0.1 BTC maximum_amount=184467440737.09551615 BTC
|
||||
INFO swap::api::request: Deposit at least 0.10001 BTC to cover the min quantity with fee!
|
||||
INFO swap::api::request: Waiting for Bitcoin deposit deposit_address=1PdfytjS7C8wwd9Lq5o4x9aXA2YRqaCpH6 min_deposit=0.10001 BTC max_giveable=0 BTC minimum_amount=0.1 BTC maximum_amount=184467440737.09551615 BTC
|
||||
INFO swap::api::request: Received Bitcoin new_balance=0.21 BTC max_giveable=0.2 BTC
|
||||
"
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -370,8 +370,8 @@ mod tests {
|
|||
use crate::env::{GetConfig, Regtest};
|
||||
use crate::protocol::{alice, bob};
|
||||
use rand::rngs::OsRng;
|
||||
use uuid::Uuid;
|
||||
use std::matches;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[test]
|
||||
fn lock_confirmations_le_to_cancel_timelock_no_timelock_expired() {
|
||||
|
|
@ -400,7 +400,7 @@ mod tests {
|
|||
tx_cancel_status,
|
||||
);
|
||||
|
||||
assert!(matches!(expired_timelock, ExpiredTimelocks::Cancel {..}));
|
||||
assert!(matches!(expired_timelock, ExpiredTimelocks::Cancel { .. }));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -194,6 +194,7 @@ impl Wallet {
|
|||
tokio::time::sleep(Duration::from_secs(5)).await;
|
||||
}
|
||||
}.instrument(Span::current()));
|
||||
}.instrument(Span::none()));
|
||||
|
||||
Subscription {
|
||||
receiver,
|
||||
|
|
|
|||
|
|
@ -499,16 +499,20 @@ mod tests {
|
|||
|
||||
use crate::api::api_test::*;
|
||||
use crate::api::Config;
|
||||
use crate::fs::system_data_dir;
|
||||
use crate::monero::monero_address::MoneroAddressNetworkMismatch;
|
||||
use serial_test::serial;
|
||||
|
||||
const BINARY_NAME: &str = "swap";
|
||||
const ARGS_DATA_DIR: &str = "/tmp/dir/";
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn given_buy_xmr_on_mainnet_then_defaults_to_mainnet() {
|
||||
|
||||
// this test is very long, however it just checks that various CLI arguments sets the
|
||||
// internal Context and Request properly. It is unlikely to fail and splitting it in various
|
||||
// tests would require to run the tests sequantially which is very slow (due to the context
|
||||
// need to access files like the Bitcoin wallet).
|
||||
async fn test_cli_arguments() {
|
||||
// given_buy_xmr_on_mainnet_then_defaults_to_mainnet
|
||||
|
||||
let raw_ars = vec![
|
||||
BINARY_NAME,
|
||||
"buy-xmr",
|
||||
|
|
@ -523,23 +527,31 @@ mod tests {
|
|||
let args = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
||||
let (is_testnet, debug, json) = (false, false, false);
|
||||
|
||||
let (expected_config, expected_request) = (
|
||||
Config::default(is_testnet, None, debug, json),
|
||||
Request::buy_xmr(is_testnet),
|
||||
);
|
||||
|
||||
let (actual_config, actual_request) = match args {
|
||||
ParseResult::Context(context, request) => (context.config.clone(), request),
|
||||
_ => panic!("Couldn't parse result"),
|
||||
};
|
||||
|
||||
let (expected_config, mut expected_request) = (
|
||||
Config::default(is_testnet, None, debug, json),
|
||||
Request::buy_xmr(is_testnet),
|
||||
);
|
||||
|
||||
// since Uuid is random, copy before comparing requests
|
||||
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"),
|
||||
}
|
||||
};
|
||||
|
||||
assert_eq!(actual_config, expected_config);
|
||||
assert_eq!(actual_request, Box::new(expected_request));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn given_buy_xmr_on_testnet_then_defaults_to_testnet() {
|
||||
// given_buy_xmr_on_testnet_then_defaults_to_testnet
|
||||
let raw_ars = vec![
|
||||
BINARY_NAME,
|
||||
"--testnet",
|
||||
|
|
@ -555,7 +567,7 @@ mod tests {
|
|||
let args = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
||||
let (is_testnet, debug, json) = (true, false, false);
|
||||
|
||||
let (expected_config, expected_request) = (
|
||||
let (expected_config, mut expected_request) = (
|
||||
Config::default(is_testnet, None, debug, json),
|
||||
Request::buy_xmr(is_testnet),
|
||||
);
|
||||
|
|
@ -565,13 +577,20 @@ mod tests {
|
|||
_ => panic!("Couldn't parse result"),
|
||||
};
|
||||
|
||||
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"),
|
||||
}
|
||||
};
|
||||
|
||||
assert_eq!(actual_config, expected_config);
|
||||
assert_eq!(actual_request, Box::new(expected_request));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn given_buy_xmr_on_mainnet_with_testnet_address_then_fails() {
|
||||
// given_buy_xmr_on_mainnet_with_testnet_address_then_fails
|
||||
let raw_ars = vec![
|
||||
BINARY_NAME,
|
||||
"buy-xmr",
|
||||
|
|
@ -592,11 +611,8 @@ mod tests {
|
|||
actual: monero::Network::Stagenet
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn given_buy_xmr_on_testnet_with_mainnet_address_then_fails() {
|
||||
// given_buy_xmr_on_testnet_with_mainnet_address_then_fails
|
||||
let raw_ars = vec![
|
||||
BINARY_NAME,
|
||||
"--testnet",
|
||||
|
|
@ -618,11 +634,8 @@ mod tests {
|
|||
actual: monero::Network::Mainnet
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn given_resume_on_mainnet_then_defaults_to_mainnet() {
|
||||
// given_resume_on_mainnet_then_defaults_to_mainnet
|
||||
let raw_ars = vec![BINARY_NAME, "resume", "--swap-id", SWAP_ID];
|
||||
|
||||
let args = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
||||
|
|
@ -640,11 +653,8 @@ mod tests {
|
|||
|
||||
assert_eq!(actual_config, expected_config);
|
||||
assert_eq!(actual_request, Box::new(expected_request));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn given_resume_on_testnet_then_defaults_to_testnet() {
|
||||
// given_resume_on_testnet_then_defaults_to_testnet
|
||||
let raw_ars = vec![BINARY_NAME, "--testnet", "resume", "--swap-id", SWAP_ID];
|
||||
|
||||
let args = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
||||
|
|
@ -662,11 +672,8 @@ mod tests {
|
|||
|
||||
assert_eq!(actual_config, expected_config);
|
||||
assert_eq!(actual_request, Box::new(expected_request));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn given_cancel_on_mainnet_then_defaults_to_mainnet() {
|
||||
// given_cancel_on_mainnet_then_defaults_to_mainnet
|
||||
let raw_ars = vec![BINARY_NAME, "cancel", "--swap-id", SWAP_ID];
|
||||
|
||||
let args = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
||||
|
|
@ -685,11 +692,8 @@ mod tests {
|
|||
|
||||
assert_eq!(actual_config, expected_config);
|
||||
assert_eq!(actual_request, Box::new(expected_request));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn given_cancel_on_testnet_then_defaults_to_testnet() {
|
||||
// given_cancel_on_testnet_then_defaults_to_testnet
|
||||
let raw_ars = vec![BINARY_NAME, "--testnet", "cancel", "--swap-id", SWAP_ID];
|
||||
|
||||
let args = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
||||
|
|
@ -707,11 +711,7 @@ mod tests {
|
|||
|
||||
assert_eq!(actual_config, expected_config);
|
||||
assert_eq!(actual_request, Box::new(expected_request));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn given_refund_on_mainnet_then_defaults_to_mainnet() {
|
||||
let raw_ars = vec![BINARY_NAME, "refund", "--swap-id", SWAP_ID];
|
||||
|
||||
let args = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
||||
|
|
@ -729,11 +729,8 @@ mod tests {
|
|||
|
||||
assert_eq!(actual_config, expected_config);
|
||||
assert_eq!(actual_request, Box::new(expected_request));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn given_refund_on_testnet_then_defaults_to_testnet() {
|
||||
// given_refund_on_testnet_then_defaults_to_testnet
|
||||
let raw_ars = vec![BINARY_NAME, "--testnet", "refund", "--swap-id", SWAP_ID];
|
||||
|
||||
let args = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
||||
|
|
@ -751,11 +748,8 @@ mod tests {
|
|||
|
||||
assert_eq!(actual_config, expected_config);
|
||||
assert_eq!(actual_request, Box::new(expected_request));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn given_buy_xmr_on_mainnet_with_data_dir_then_data_dir_set() {
|
||||
// given_buy_xmr_on_mainnet_with_data_dir_then_data_dir_set
|
||||
let raw_ars = vec![
|
||||
BINARY_NAME,
|
||||
"--data-base-dir",
|
||||
|
|
@ -773,7 +767,7 @@ mod tests {
|
|||
let (is_testnet, debug, json) = (false, false, false);
|
||||
let data_dir = PathBuf::from_str(ARGS_DATA_DIR).unwrap();
|
||||
|
||||
let (expected_config, expected_request) = (
|
||||
let (expected_config, mut expected_request) = (
|
||||
Config::default(is_testnet, Some(data_dir.clone()), debug, json),
|
||||
Request::buy_xmr(is_testnet),
|
||||
);
|
||||
|
|
@ -783,13 +777,20 @@ mod tests {
|
|||
_ => panic!("Couldn't parse result"),
|
||||
};
|
||||
|
||||
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"),
|
||||
}
|
||||
};
|
||||
|
||||
assert_eq!(actual_config, expected_config);
|
||||
assert_eq!(actual_request, Box::new(expected_request));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn given_buy_xmr_on_testnet_with_data_dir_then_data_dir_set() {
|
||||
// given_buy_xmr_on_testnet_with_data_dir_then_data_dir_set
|
||||
let raw_ars = vec![
|
||||
BINARY_NAME,
|
||||
"--testnet",
|
||||
|
|
@ -808,7 +809,7 @@ mod tests {
|
|||
let args = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
||||
let (is_testnet, debug, json) = (true, false, false);
|
||||
|
||||
let (expected_config, expected_request) = (
|
||||
let (expected_config, mut expected_request) = (
|
||||
Config::default(is_testnet, Some(data_dir.clone()), debug, json),
|
||||
Request::buy_xmr(is_testnet),
|
||||
);
|
||||
|
|
@ -818,13 +819,20 @@ mod tests {
|
|||
_ => panic!("Couldn't parse result"),
|
||||
};
|
||||
|
||||
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"),
|
||||
}
|
||||
};
|
||||
|
||||
assert_eq!(actual_config, expected_config);
|
||||
assert_eq!(actual_request, Box::new(expected_request));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn given_resume_on_mainnet_with_data_dir_then_data_dir_set() {
|
||||
// given_resume_on_mainnet_with_data_dir_then_data_dir_set
|
||||
let raw_ars = vec![
|
||||
BINARY_NAME,
|
||||
"--data-base-dir",
|
||||
|
|
@ -838,11 +846,21 @@ mod tests {
|
|||
let args = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
||||
let (is_testnet, debug, json) = (false, false, false);
|
||||
|
||||
let (expected_config, expected_request) = (
|
||||
let (expected_config, mut expected_request) = (
|
||||
Config::default(is_testnet, Some(data_dir.clone()), debug, json),
|
||||
Request::resume(),
|
||||
);
|
||||
|
||||
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"),
|
||||
}
|
||||
};
|
||||
|
||||
let (actual_config, actual_request) = match args {
|
||||
ParseResult::Context(context, request) => (context.config.clone(), request),
|
||||
_ => panic!("Couldn't parse result"),
|
||||
|
|
@ -850,11 +868,8 @@ mod tests {
|
|||
|
||||
assert_eq!(actual_config, expected_config);
|
||||
assert_eq!(actual_request, Box::new(expected_request));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn given_resume_on_testnet_with_data_dir_then_data_dir_set() {
|
||||
// given_resume_on_testnet_with_data_dir_then_data_dir_set
|
||||
let raw_ars = vec![
|
||||
BINARY_NAME,
|
||||
"--testnet",
|
||||
|
|
@ -881,11 +896,8 @@ mod tests {
|
|||
|
||||
assert_eq!(actual_config, expected_config);
|
||||
assert_eq!(actual_request, Box::new(expected_request));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn given_buy_xmr_on_mainnet_with_debug_then_debug_set() {
|
||||
// given_buy_xmr_on_mainnet_with_debug_then_debug_set
|
||||
let raw_ars = vec![
|
||||
BINARY_NAME,
|
||||
"--debug",
|
||||
|
|
@ -901,7 +913,7 @@ mod tests {
|
|||
let args = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
||||
let (is_testnet, debug, json) = (false, true, false);
|
||||
|
||||
let (expected_config, expected_request) = (
|
||||
let (expected_config, mut expected_request) = (
|
||||
Config::default(is_testnet, None, debug, json),
|
||||
Request::buy_xmr(is_testnet),
|
||||
);
|
||||
|
|
@ -911,13 +923,20 @@ mod tests {
|
|||
_ => panic!("Couldn't parse result"),
|
||||
};
|
||||
|
||||
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"),
|
||||
}
|
||||
};
|
||||
|
||||
assert_eq!(actual_config, expected_config);
|
||||
assert_eq!(actual_request, Box::new(expected_request));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn given_buy_xmr_on_testnet_with_debug_then_debug_set() {
|
||||
// given_buy_xmr_on_testnet_with_debug_then_debug_set
|
||||
let raw_ars = vec![
|
||||
BINARY_NAME,
|
||||
"--testnet",
|
||||
|
|
@ -934,7 +953,7 @@ mod tests {
|
|||
let args = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
||||
let (is_testnet, debug, json) = (true, true, false);
|
||||
|
||||
let (expected_config, expected_request) = (
|
||||
let (expected_config, mut expected_request) = (
|
||||
Config::default(is_testnet, None, debug, json),
|
||||
Request::buy_xmr(is_testnet),
|
||||
);
|
||||
|
|
@ -944,19 +963,26 @@ mod tests {
|
|||
_ => panic!("Couldn't parse result"),
|
||||
};
|
||||
|
||||
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"),
|
||||
}
|
||||
};
|
||||
|
||||
assert_eq!(actual_config, expected_config);
|
||||
assert_eq!(actual_request, Box::new(expected_request));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn given_resume_on_mainnet_with_debug_then_debug_set() {
|
||||
// given_resume_on_mainnet_with_debug_then_debug_set
|
||||
let raw_ars = vec![BINARY_NAME, "--debug", "resume", "--swap-id", SWAP_ID];
|
||||
|
||||
let args = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
||||
let (is_testnet, debug, json) = (false, true, false);
|
||||
|
||||
let (expected_config, expected_request) = (
|
||||
let (expected_config, mut expected_request) = (
|
||||
Config::default(is_testnet, None, debug, json),
|
||||
Request::resume(),
|
||||
);
|
||||
|
|
@ -966,13 +992,20 @@ mod tests {
|
|||
_ => panic!("Couldn't parse result"),
|
||||
};
|
||||
|
||||
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"),
|
||||
}
|
||||
};
|
||||
|
||||
assert_eq!(actual_config, expected_config);
|
||||
assert_eq!(actual_request, Box::new(expected_request));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn given_resume_on_testnet_with_debug_then_debug_set() {
|
||||
// given_resume_on_testnet_with_debug_then_debug_set
|
||||
let raw_ars = vec![
|
||||
BINARY_NAME,
|
||||
"--testnet",
|
||||
|
|
@ -997,11 +1030,8 @@ mod tests {
|
|||
|
||||
assert_eq!(actual_config, expected_config);
|
||||
assert_eq!(actual_request, Box::new(expected_request));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn given_buy_xmr_on_mainnet_with_json_then_json_set() {
|
||||
// given_buy_xmr_on_mainnet_with_json_then_json_set
|
||||
let raw_ars = vec![
|
||||
BINARY_NAME,
|
||||
"--json",
|
||||
|
|
@ -1016,9 +1046,8 @@ mod tests {
|
|||
|
||||
let args = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
||||
let (is_testnet, debug, json) = (false, false, true);
|
||||
let data_dir = data_dir_path_cli(is_testnet);
|
||||
|
||||
let (expected_config, expected_request) = (
|
||||
let (expected_config, mut expected_request) = (
|
||||
Config::default(is_testnet, None, debug, json),
|
||||
Request::buy_xmr(is_testnet),
|
||||
);
|
||||
|
|
@ -1028,13 +1057,20 @@ mod tests {
|
|||
_ => panic!("Couldn't parse result"),
|
||||
};
|
||||
|
||||
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"),
|
||||
}
|
||||
};
|
||||
|
||||
assert_eq!(actual_config, expected_config);
|
||||
assert_eq!(actual_request, Box::new(expected_request));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn given_buy_xmr_on_testnet_with_json_then_json_set() {
|
||||
// given_buy_xmr_on_testnet_with_json_then_json_set
|
||||
let raw_ars = vec![
|
||||
BINARY_NAME,
|
||||
"--testnet",
|
||||
|
|
@ -1050,7 +1086,7 @@ mod tests {
|
|||
|
||||
let (is_testnet, debug, json) = (true, false, true);
|
||||
|
||||
let (expected_config, expected_request) = (
|
||||
let (expected_config, mut expected_request) = (
|
||||
Config::default(is_testnet, None, debug, json),
|
||||
Request::buy_xmr(is_testnet),
|
||||
);
|
||||
|
|
@ -1061,13 +1097,20 @@ mod tests {
|
|||
_ => panic!("Couldn't parse result"),
|
||||
};
|
||||
|
||||
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"),
|
||||
}
|
||||
};
|
||||
|
||||
assert_eq!(actual_config, expected_config);
|
||||
assert_eq!(actual_request, Box::new(expected_request));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn given_resume_on_mainnet_with_json_then_json_set() {
|
||||
// given_resume_on_mainnet_with_json_then_json_set
|
||||
let raw_ars = vec![BINARY_NAME, "--json", "resume", "--swap-id", SWAP_ID];
|
||||
let args = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
||||
let (is_testnet, debug, json) = (false, false, true);
|
||||
|
|
@ -1084,11 +1127,8 @@ mod tests {
|
|||
|
||||
assert_eq!(actual_config, expected_config);
|
||||
assert_eq!(actual_request, Box::new(expected_request));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn given_resume_on_testnet_with_json_then_json_set() {
|
||||
// given_resume_on_testnet_with_json_then_json_set
|
||||
let raw_ars = vec![
|
||||
BINARY_NAME,
|
||||
"--testnet",
|
||||
|
|
@ -1113,11 +1153,8 @@ mod tests {
|
|||
|
||||
assert_eq!(actual_config, expected_config);
|
||||
assert_eq!(actual_request, Box::new(expected_request));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn only_bech32_addresses_mainnet_are_allowed() {
|
||||
// only_bech32_addresses_mainnet_are_allowed
|
||||
let raw_ars = vec![
|
||||
BINARY_NAME,
|
||||
"buy-xmr",
|
||||
|
|
@ -1128,7 +1165,7 @@ mod tests {
|
|||
"--seller",
|
||||
MULTI_ADDRESS,
|
||||
];
|
||||
let result = parse_args_and_apply_defaults(raw_ars).await.unwrap_err();
|
||||
parse_args_and_apply_defaults(raw_ars).await.unwrap_err();
|
||||
|
||||
let raw_ars = vec![
|
||||
BINARY_NAME,
|
||||
|
|
@ -1140,7 +1177,7 @@ mod tests {
|
|||
"--seller",
|
||||
MULTI_ADDRESS,
|
||||
];
|
||||
let result = parse_args_and_apply_defaults(raw_ars).await.unwrap_err();
|
||||
parse_args_and_apply_defaults(raw_ars).await.unwrap_err();
|
||||
|
||||
let raw_ars = vec![
|
||||
BINARY_NAME,
|
||||
|
|
@ -1154,11 +1191,8 @@ mod tests {
|
|||
];
|
||||
let result = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
||||
assert!(matches!(result, ParseResult::Context(_, _)));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn only_bech32_addresses_testnet_are_allowed() {
|
||||
// only_bech32_addresses_testnet_are_allowed
|
||||
let raw_ars = vec![
|
||||
BINARY_NAME,
|
||||
"--testnet",
|
||||
|
|
@ -1170,7 +1204,7 @@ mod tests {
|
|||
"--seller",
|
||||
MULTI_ADDRESS,
|
||||
];
|
||||
let result = parse_args_and_apply_defaults(raw_ars).await.unwrap_err();
|
||||
parse_args_and_apply_defaults(raw_ars).await.unwrap_err();
|
||||
|
||||
let raw_ars = vec![
|
||||
BINARY_NAME,
|
||||
|
|
@ -1183,7 +1217,7 @@ mod tests {
|
|||
"--seller",
|
||||
MULTI_ADDRESS,
|
||||
];
|
||||
let result = parse_args_and_apply_defaults(raw_ars).await.unwrap_err();
|
||||
parse_args_and_apply_defaults(raw_ars).await.unwrap_err();
|
||||
|
||||
let raw_ars = vec![
|
||||
BINARY_NAME,
|
||||
|
|
@ -1199,12 +1233,4 @@ mod tests {
|
|||
let result = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
||||
assert!(matches!(result, ParseResult::Context(_, _)));
|
||||
}
|
||||
|
||||
fn data_dir_path_cli(is_testnet: bool) -> PathBuf {
|
||||
if is_testnet {
|
||||
system_data_dir().unwrap().join("cli").join("testnet")
|
||||
} else {
|
||||
system_data_dir().unwrap().join("cli").join("mainnet")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -219,11 +219,13 @@ async fn execute_request(
|
|||
cmd: Method,
|
||||
context: &Arc<Context>,
|
||||
) -> Result<serde_json::Value, jsonrpsee_core::Error> {
|
||||
let params_parsed = params
|
||||
// If we fail to parse the params as a String HashMap, it's most likely because its an empty object
|
||||
// In that case, we want to make sure not to fail the request, so we set the log_reference_id to None
|
||||
// and swallow the error
|
||||
let reference_id = params
|
||||
.parse::<HashMap<String, String>>()
|
||||
.map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))?;
|
||||
|
||||
let reference_id = params_parsed.get("log_reference_id");
|
||||
.ok()
|
||||
.and_then(|params_parsed| params_parsed.get("log_reference_id").cloned());
|
||||
|
||||
let request = Request::with_id(cmd, reference_id.map(|s| s.clone()));
|
||||
request
|
||||
|
|
|
|||
|
|
@ -23,9 +23,9 @@ use swap::network::rendezvous::XmrBtcNamespace;
|
|||
use swap::network::swarm;
|
||||
use swap::protocol::alice::{AliceState, Swap};
|
||||
use swap::protocol::bob::BobState;
|
||||
use swap::protocol::{alice, bob};
|
||||
use swap::protocol::{alice, bob, Database};
|
||||
use swap::seed::Seed;
|
||||
use swap::{asb, bitcoin, cli, env, monero};
|
||||
use swap::{api, asb, bitcoin, cli, env, monero};
|
||||
use tempfile::{tempdir, NamedTempFile};
|
||||
use testcontainers::clients::Cli;
|
||||
use testcontainers::{Container, Docker, RunArgs};
|
||||
|
|
@ -454,6 +454,8 @@ impl BobParams {
|
|||
}
|
||||
let db = Arc::new(SqliteDatabase::open(&self.db_path).await?);
|
||||
|
||||
db.insert_peer_id(swap_id, self.alice_peer_id).await?;
|
||||
|
||||
let swap = bob::Swap::new(
|
||||
db,
|
||||
swap_id,
|
||||
|
|
@ -534,6 +536,17 @@ pub struct TestContext {
|
|||
}
|
||||
|
||||
impl TestContext {
|
||||
pub async fn get_bob_context(self) -> api::Context {
|
||||
api::Context::for_harness(
|
||||
self.bob_params.seed,
|
||||
self.env_config,
|
||||
self.bob_params.db_path,
|
||||
self.bob_bitcoin_wallet,
|
||||
self.bob_monero_wallet,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn restart_alice(&mut self) {
|
||||
self.alice_handle.abort();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,19 +1,33 @@
|
|||
pub mod harness;
|
||||
use anyhow::Result;
|
||||
|
||||
use jsonrpsee::rpc_params;
|
||||
use jsonrpsee::ws_client::WsClientBuilder;
|
||||
use jsonrpsee_core::client::ClientT;
|
||||
use jsonrpsee_core::client::{Client, ClientT};
|
||||
use jsonrpsee_core::params::ObjectParams;
|
||||
|
||||
use serial_test::serial;
|
||||
|
||||
use serde_json::{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::Context;
|
||||
use swap::api::request::{Method, Request};
|
||||
use swap::api::{Config, Context, SwapLock};
|
||||
use swap::cli::command::{Bitcoin, Monero};
|
||||
use tempfile::tempdir;
|
||||
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)]
|
||||
|
|
@ -27,419 +41,511 @@ const MONERO_ADDR: &str = "53gEuGZUhP9JMEBZoGaFNzhwEgiG7hwQdMCqFxiyiTeFPmkbt1mAo
|
|||
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 initialize_context() -> (Arc<Context>, Request) {
|
||||
let (is_testnet, debug, json) = (true, false, false);
|
||||
// let data_dir = data::data_dir_from(None, is_testnet).unwrap();
|
||||
let server_address = None;
|
||||
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();
|
||||
|
||||
let bitcoin = Bitcoin {
|
||||
bitcoin_electrum_rpc_url: None,
|
||||
bitcoin_target_block: None,
|
||||
};
|
||||
let request = Request::new(Method::StartDaemon {
|
||||
server_address: Some(server_address),
|
||||
});
|
||||
|
||||
let _monero = Monero {
|
||||
monero_daemon_address: None,
|
||||
};
|
||||
let context = Arc::new(harness_context.get_bob_context().await);
|
||||
|
||||
let request = Request::new(Method::StartDaemon { server_address: None });
|
||||
let context_clone = context.clone();
|
||||
|
||||
let context = Context::build(
|
||||
Some(bitcoin),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
is_testnet,
|
||||
debug,
|
||||
json,
|
||||
server_address,
|
||||
)
|
||||
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();
|
||||
|
||||
return testfn(harness_context, client, writer, context).await;
|
||||
}
|
||||
|
||||
tokio::time::sleep(Duration::from_secs(1)).await;
|
||||
}
|
||||
|
||||
panic!(
|
||||
"Failed to start RPC server after {} seconds",
|
||||
SERVER_START_TIMEOUT_SECS
|
||||
);
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
(Arc::new(context), request)
|
||||
fn assert_has_keys_serde(map: &serde_json::Map<String, Value>, keys: &[&str]) {
|
||||
for &key in keys {
|
||||
assert!(map.contains_key(key), "Key {} is missing", key);
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function for HashMap
|
||||
fn assert_has_keys_hashmap(map: &HashMap<String, Value>, keys: &[&str]) {
|
||||
for &key in keys {
|
||||
assert!(map.contains_key(key), "Key {} is missing", key);
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
pub async fn can_start_server() {
|
||||
let (ctx, mut request) = initialize_context().await;
|
||||
let move_ctx = Arc::clone(&ctx);
|
||||
tokio::spawn(async move {
|
||||
request.call(Arc::clone(&move_ctx)).await;
|
||||
});
|
||||
tokio::time::sleep(Duration::from_secs(3)).await;
|
||||
assert!(true);
|
||||
setup_daemon(|_, _, _, _| async move {
|
||||
assert!(true);
|
||||
Ok(())
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
pub async fn get_bitcoin_balance() {
|
||||
let (ctx, mut request) = initialize_context().await;
|
||||
let move_ctx = Arc::clone(&ctx);
|
||||
tokio::spawn(async move {
|
||||
request.call(Arc::clone(&move_ctx)).await;
|
||||
});
|
||||
setup_daemon(|_, client| async move {
|
||||
let response: HashMap<String, i32> = client
|
||||
.request("get_bitcoin_balance", ObjectParams::new())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let url = format!("ws://{}", SERVER_ADDRESS);
|
||||
tokio::time::sleep(Duration::from_secs(3)).await;
|
||||
assert_eq!(response, HashMap::from([("balance".to_string(), 10000000)]));
|
||||
|
||||
let client = WsClientBuilder::default().build(&url).await.unwrap();
|
||||
let response: HashMap<String, i32> = client
|
||||
.request("get_bitcoin_balance", rpc_params!["id"])
|
||||
.await
|
||||
.unwrap();
|
||||
Ok(())
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
assert_eq!(response, HashMap::from([("balance".to_string(), 0)]));
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
pub async fn get_bitcoin_balance_with_log_reference_id() {
|
||||
setup_daemon(|_, client, writer| async move {
|
||||
let mut params = ObjectParams::new();
|
||||
params.insert("log_reference_id", "test_ref_id").unwrap();
|
||||
|
||||
let _: HashMap<String, i32> = client.request("get_bitcoin_balance", params).await.unwrap();
|
||||
|
||||
assert!(writer.captured().contains(
|
||||
"log_reference_id=\"test_ref_id\"}: swap::api::request: Checked Bitcoin balance balance=0"
|
||||
));
|
||||
|
||||
Ok(())
|
||||
}).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
pub async fn get_history() {
|
||||
let (ctx, mut request) = initialize_context().await;
|
||||
let move_ctx = Arc::clone(&ctx);
|
||||
tokio::spawn(async move {
|
||||
request.call(Arc::clone(&move_ctx)).await;
|
||||
});
|
||||
setup_daemon(|mut harness_ctx, client| 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;
|
||||
tokio::spawn(bob::run_until(bob_swap, is_btc_locked));
|
||||
let alice_swap = harness_ctx.alice_next_swap().await;
|
||||
alice::run_until(
|
||||
alice_swap,
|
||||
is_xmr_lock_transaction_sent,
|
||||
FixedRate::default(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
let url = format!("ws://{}", SERVER_ADDRESS);
|
||||
tokio::time::sleep(Duration::from_secs(3)).await;
|
||||
let response: HashMap<String, Vec<(Uuid, String)>> = client
|
||||
.request("get_history", ObjectParams::new())
|
||||
.await
|
||||
.unwrap();
|
||||
let swaps: Vec<(Uuid, String)> = vec![(bob_swap_id, "btc is locked".to_string())];
|
||||
|
||||
let client = WsClientBuilder::default().build(&url).await.unwrap();
|
||||
let mut params = ObjectParams::new();
|
||||
assert_eq!(response, HashMap::from([("swaps".to_string(), swaps)]));
|
||||
|
||||
let response: HashMap<String, Vec<(Uuid, String)>> =
|
||||
client.request("get_history", params).await.unwrap();
|
||||
let swaps: Vec<(Uuid, String)> = Vec::new();
|
||||
|
||||
assert_eq!(response, HashMap::from([("swaps".to_string(), swaps)]));
|
||||
Ok(())
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
pub async fn get_raw_history() {
|
||||
let (ctx, mut request) = initialize_context().await;
|
||||
let move_ctx = Arc::clone(&ctx);
|
||||
pub async fn get_raw_states() {
|
||||
setup_daemon(|mut harness_ctx, client| 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;
|
||||
tokio::spawn(bob::run_until(bob_swap, is_btc_locked));
|
||||
let alice_swap = harness_ctx.alice_next_swap().await;
|
||||
alice::run_until(
|
||||
alice_swap,
|
||||
is_xmr_lock_transaction_sent,
|
||||
FixedRate::default(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
let response: HashMap<String, HashMap<Uuid, Vec<Value>>> = client
|
||||
.request("get_raw_states", ObjectParams::new())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let response_raw_states = response.get("raw_states").unwrap();
|
||||
|
||||
assert!(response_raw_states.contains_key(&bob_swap_id));
|
||||
assert_eq!(response_raw_states.get(&bob_swap_id).unwrap().len(), 2);
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
pub async fn get_swap_info_valid_swap_id() {
|
||||
setup_daemon(|mut harness_ctx, client| 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;
|
||||
tokio::spawn(bob::run_until(bob_swap, is_btc_locked));
|
||||
let alice_swap = harness_ctx.alice_next_swap().await;
|
||||
alice::run_until(
|
||||
alice_swap,
|
||||
is_xmr_lock_transaction_sent,
|
||||
FixedRate::default(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
let mut params = ObjectParams::new();
|
||||
params.insert("swap_id", bob_swap_id).unwrap();
|
||||
let response: HashMap<String, Value> =
|
||||
client.request("get_swap_info", params).await.unwrap();
|
||||
|
||||
// Check primary keys in response
|
||||
assert_has_keys_hashmap(
|
||||
&response,
|
||||
&[
|
||||
"txRefundFee",
|
||||
"swapId",
|
||||
"cancelTimelock",
|
||||
"timelock",
|
||||
"punishTimelock",
|
||||
"stateName",
|
||||
"btcAmount",
|
||||
"startDate",
|
||||
"btcRefundAddress",
|
||||
"txCancelFee",
|
||||
"xmrAmount",
|
||||
"completed",
|
||||
"txLockId",
|
||||
"seller",
|
||||
],
|
||||
);
|
||||
|
||||
// Assert specific fields
|
||||
assert_eq!(response.get("swapId").unwrap(), &bob_swap_id.to_string());
|
||||
assert_eq!(
|
||||
response.get("stateName").unwrap(),
|
||||
&"btc is locked".to_string()
|
||||
);
|
||||
assert_eq!(response.get("completed").unwrap(), &Value::Bool(false));
|
||||
|
||||
// Check seller object and its keys
|
||||
let seller = response
|
||||
.get("seller")
|
||||
.expect("Field 'seller' is missing from response")
|
||||
.as_object()
|
||||
.expect("'seller' is not an object");
|
||||
assert_has_keys_serde(seller, &["peerId"]);
|
||||
|
||||
// Check timelock object, nested 'None' object, and blocks_left
|
||||
let timelock = response
|
||||
.get("timelock")
|
||||
.expect("Field 'timelock' is missing from response")
|
||||
.as_object()
|
||||
.expect("'timelock' is not an object");
|
||||
let none_obj = timelock
|
||||
.get("None")
|
||||
.expect("Field 'None' is missing from 'timelock'")
|
||||
.as_object()
|
||||
.expect("'None' is not an object in 'timelock'");
|
||||
let blocks_left = none_obj
|
||||
.get("blocks_left")
|
||||
.expect("Field 'blocks_left' is missing from 'None'")
|
||||
.as_i64()
|
||||
.expect("'blocks_left' is not an integer");
|
||||
|
||||
// Validate blocks_left
|
||||
assert!(
|
||||
blocks_left > 0 && blocks_left <= 180,
|
||||
"Field 'blocks_left' should be > 0 and <= 180 but got {}",
|
||||
blocks_left
|
||||
);
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
pub async fn swap_endpoints_invalid_or_missing_swap_id() {
|
||||
setup_daemon(|_, client| async move {
|
||||
for method in ["get_swap_info", "resume_swap", "cancel_refund_swap"].iter() {
|
||||
let mut params = ObjectParams::new();
|
||||
params.insert("swap_id", "invalid_swap").unwrap();
|
||||
|
||||
let response: Result<HashMap<String, String>, _> = client.request(method, params).await;
|
||||
response.expect_err(&format!(
|
||||
"Expected an error when swap_id is invalid for method {}",
|
||||
method
|
||||
));
|
||||
|
||||
let params = ObjectParams::new();
|
||||
|
||||
let response: Result<HashMap<String, String>, _> = client.request(method, params).await;
|
||||
response.expect_err(&format!(
|
||||
"Expected an error when swap_id is missing for method {}",
|
||||
method
|
||||
));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
pub async fn list_sellers_missing_rendezvous_point() {
|
||||
setup_daemon(|_, client| async move {
|
||||
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 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");
|
||||
}
|
||||
|
||||
#[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");
|
||||
}
|
||||
|
||||
#[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");
|
||||
}
|
||||
|
||||
#[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");
|
||||
}
|
||||
|
||||
#[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");
|
||||
}
|
||||
|
||||
#[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");
|
||||
}
|
||||
|
||||
#[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");
|
||||
}
|
||||
|
||||
#[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");
|
||||
}
|
||||
|
||||
#[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");
|
||||
}
|
||||
|
||||
#[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");
|
||||
}
|
||||
|
||||
#[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");
|
||||
}
|
||||
|
||||
#[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");
|
||||
}
|
||||
|
||||
#[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");
|
||||
}
|
||||
|
||||
#[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();
|
||||
|
||||
tokio::spawn(async move {
|
||||
request.call(Arc::clone(&move_ctx)).await;
|
||||
// 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 url = format!("ws://{}", SERVER_ADDRESS);
|
||||
tokio::time::sleep(Duration::from_secs(3)).await;
|
||||
|
||||
let client = WsClientBuilder::default().build(&url).await.unwrap();
|
||||
let mut params = ObjectParams::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, String> = client
|
||||
.request("suspend_current_swap", ObjectParams::new())
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
response,
|
||||
HashMap::from([("raw_history".to_string(), raw_history)])
|
||||
HashMap::from([("swapId".to_string(), SWAP_ID.to_string())])
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
pub async fn get_seller() {
|
||||
let (ctx, mut request) = initialize_context().await;
|
||||
let move_ctx = Arc::clone(&ctx);
|
||||
tokio::spawn(async move {
|
||||
request.call(Arc::clone(&move_ctx)).await;
|
||||
});
|
||||
|
||||
let url = format!("ws://{}", SERVER_ADDRESS);
|
||||
tokio::time::sleep(Duration::from_secs(3)).await;
|
||||
|
||||
let client = WsClientBuilder::default().build(&url).await.unwrap();
|
||||
let mut params = ObjectParams::new();
|
||||
|
||||
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)
|
||||
// Err(jsonrpsee_core::Error::Call(CallError::InvalidParams(e))) => (),
|
||||
// Err(e) => panic!("ErrorType was not ParseError but {e:?}"),
|
||||
|
||||
match response {
|
||||
Err(e) => (),
|
||||
_ => panic!("Expected an error when swap_id is missing"),
|
||||
}
|
||||
|
||||
let mut params = ObjectParams::new();
|
||||
params.insert("swap_id", "invalid_swap");
|
||||
|
||||
let response: Result<HashMap<String, String>, _> = client.request("get_seller", params).await;
|
||||
|
||||
match response {
|
||||
Err(e) => (),
|
||||
_ => panic!("Expected an error swap_id is malformed"),
|
||||
}
|
||||
|
||||
let mut params = ObjectParams::new();
|
||||
params.insert("swap_id", SWAP_ID);
|
||||
|
||||
let response: Result<HashMap<String, String>, _> = client.request("get_seller", params).await;
|
||||
|
||||
match response {
|
||||
Ok(hash) => (),
|
||||
Err(e) => panic!(
|
||||
"Expected a HashMap with correct params, got an error: {}",
|
||||
e
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
pub async fn get_swap_start_date() {
|
||||
let (ctx, mut request) = initialize_context().await;
|
||||
let move_ctx = Arc::clone(&ctx);
|
||||
tokio::spawn(async move {
|
||||
request.call(Arc::clone(&move_ctx)).await;
|
||||
});
|
||||
|
||||
let url = format!("ws://{}", SERVER_ADDRESS);
|
||||
tokio::time::sleep(Duration::from_secs(3)).await;
|
||||
|
||||
let client = WsClientBuilder::default().build(&url).await.unwrap();
|
||||
let mut params = ObjectParams::new();
|
||||
|
||||
let response: Result<HashMap<String, String>, _> =
|
||||
client.request("get_swap_start_date", params).await;
|
||||
|
||||
match response {
|
||||
Err(e) => (),
|
||||
_ => panic!("Expected an error when swap_id is missing"),
|
||||
}
|
||||
|
||||
let mut params = ObjectParams::new();
|
||||
params.insert("swap_id", "invalid_swap");
|
||||
|
||||
let response: Result<HashMap<String, String>, _> =
|
||||
client.request("get_swap_start_date", params).await;
|
||||
|
||||
match response {
|
||||
Err(e) => (),
|
||||
_ => panic!("Expected an error when swap_id is malformed"),
|
||||
}
|
||||
|
||||
let mut params = ObjectParams::new();
|
||||
params.insert("swap_id", SWAP_ID);
|
||||
|
||||
let response: Result<HashMap<String, String>, _> =
|
||||
client.request("get_swap_start_date", params).await;
|
||||
|
||||
match response {
|
||||
Ok(hash) => (),
|
||||
Err(e) => panic!("Expected a HashMap, got an error: {}", e),
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
pub async fn resume_swap() {
|
||||
let (ctx, mut request) = initialize_context().await;
|
||||
let move_ctx = Arc::clone(&ctx);
|
||||
tokio::spawn(async move {
|
||||
request.call(Arc::clone(&move_ctx)).await;
|
||||
});
|
||||
|
||||
let url = format!("ws://{}", SERVER_ADDRESS);
|
||||
tokio::time::sleep(Duration::from_secs(3)).await;
|
||||
|
||||
let client = WsClientBuilder::default().build(&url).await.unwrap();
|
||||
let mut params = ObjectParams::new();
|
||||
|
||||
let response: Result<HashMap<String, String>, _> =
|
||||
client.request("get_swap_start_date", params).await;
|
||||
|
||||
match response {
|
||||
Err(e) => (),
|
||||
_ => panic!("Expected an error when swap_id is missing"),
|
||||
}
|
||||
|
||||
let mut params = ObjectParams::new();
|
||||
params.insert("swap_id", "invalid_swap");
|
||||
|
||||
let response: Result<HashMap<String, String>, _> =
|
||||
client.request("get_swap_start_date", params).await;
|
||||
|
||||
match response {
|
||||
Err(e) => (),
|
||||
_ => panic!("Expected an error when swap_id is malformed"),
|
||||
}
|
||||
|
||||
let mut params = ObjectParams::new();
|
||||
params.insert("swap_id", SWAP_ID);
|
||||
|
||||
let response: Result<HashMap<String, String>, _> =
|
||||
client.request("get_swap_start_date", params).await;
|
||||
|
||||
match response {
|
||||
Ok(hash) => (),
|
||||
Err(e) => panic!("Expected a HashMap, got an error: {}", e),
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
pub async fn withdraw_btc() {
|
||||
let (ctx, mut request) = initialize_context().await;
|
||||
let move_ctx = Arc::clone(&ctx);
|
||||
tokio::spawn(async move {
|
||||
request.call(Arc::clone(&move_ctx)).await;
|
||||
});
|
||||
|
||||
let url = format!("ws://{}", SERVER_ADDRESS);
|
||||
tokio::time::sleep(Duration::from_secs(3)).await;
|
||||
|
||||
let client = WsClientBuilder::default().build(&url).await.unwrap();
|
||||
let mut params = ObjectParams::new();
|
||||
|
||||
let response: Result<HashMap<String, String>, _> = client.request("withdraw_btc", params).await;
|
||||
|
||||
match response {
|
||||
Err(e) => (),
|
||||
_ => panic!("Expected an error when withdraw_address is missing"),
|
||||
}
|
||||
|
||||
let mut params = ObjectParams::new();
|
||||
params.insert("address", "invalid_address");
|
||||
|
||||
let response: Result<HashMap<String, String>, _> = client.request("withdraw_btc", params).await;
|
||||
|
||||
match response {
|
||||
Err(e) => (),
|
||||
_ => panic!("Expected an error when withdraw_address is malformed"),
|
||||
}
|
||||
|
||||
let mut params = ObjectParams::new();
|
||||
params.insert("address", BITCOIN_ADDR);
|
||||
params.insert("amount", "0");
|
||||
|
||||
let response: Result<HashMap<String, String>, _> = client.request("withdraw_btc", params).await;
|
||||
|
||||
match response {
|
||||
Err(e) => (),
|
||||
_ => panic!("Expected an error when amount is 0"),
|
||||
}
|
||||
|
||||
let mut params = ObjectParams::new();
|
||||
params.insert("address", BITCOIN_ADDR);
|
||||
params.insert("amount", "0.1");
|
||||
|
||||
let response: Result<HashMap<String, String>, _> = client.request("withdraw_btc", params).await;
|
||||
|
||||
match response {
|
||||
Ok(hash) => (),
|
||||
Err(e) => panic!("Expected a HashMap, got an error: {}", e),
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
pub async fn buy_xmr() {
|
||||
let (ctx, mut request) = initialize_context().await;
|
||||
let move_ctx = Arc::clone(&ctx);
|
||||
tokio::spawn(async move {
|
||||
request.call(Arc::clone(&move_ctx)).await;
|
||||
});
|
||||
|
||||
let url = format!("ws://{}", SERVER_ADDRESS);
|
||||
tokio::time::sleep(Duration::from_secs(3)).await;
|
||||
|
||||
let client = WsClientBuilder::default().build(&url).await.unwrap();
|
||||
let mut params = ObjectParams::new();
|
||||
|
||||
let response: Result<HashMap<String, String>, _> = client.request("buy_xmr", params).await;
|
||||
|
||||
match response {
|
||||
Err(e) => (),
|
||||
_ => panic!("Expected an error when no params are given"),
|
||||
}
|
||||
|
||||
let mut params = ObjectParams::new();
|
||||
params.insert("bitcoin_change_address", BITCOIN_ADDR);
|
||||
params.insert("monero_receive_address", MONERO_ADDR);
|
||||
|
||||
let response: Result<HashMap<String, String>, _> = client.request("buy_xmr", params).await;
|
||||
|
||||
match response {
|
||||
Err(e) => (),
|
||||
_ => panic!("Expected an error when seller is missing"),
|
||||
}
|
||||
|
||||
let mut params = ObjectParams::new();
|
||||
params.insert("bitcoin_change_address", BITCOIN_ADDR);
|
||||
params.insert("seller", SELLER);
|
||||
|
||||
let response: Result<HashMap<String, String>, _> = client.request("buy_xmr", params).await;
|
||||
|
||||
match response {
|
||||
Err(e) => (),
|
||||
_ => panic!("Expected an error when monero_receive_address is missing"),
|
||||
}
|
||||
|
||||
let mut params = ObjectParams::new();
|
||||
params.insert("monero_receive_address", MONERO_ADDR);
|
||||
params.insert("seller", SELLER);
|
||||
|
||||
let response: Result<HashMap<String, String>, _> = client.request("buy_xmr", params).await;
|
||||
|
||||
match response {
|
||||
Err(e) => (),
|
||||
_ => panic!("Expected an error when bitcoin_change_address is missing"),
|
||||
}
|
||||
|
||||
let mut params = ObjectParams::new();
|
||||
params.insert("bitcoin_change_address", "invalid_address");
|
||||
params.insert("monero_receive_address", MONERO_ADDR);
|
||||
params.insert("seller", SELLER);
|
||||
|
||||
let response: Result<HashMap<String, String>, _> = client.request("buy_xmr", params).await;
|
||||
|
||||
match response {
|
||||
Err(e) => (),
|
||||
_ => panic!("Expected an error when bitcoin_change_address is malformed"),
|
||||
}
|
||||
|
||||
let mut params = ObjectParams::new();
|
||||
params.insert("bitcoin_change_address", BITCOIN_ADDR);
|
||||
params.insert("monero_receive_address", "invalid_address");
|
||||
params.insert("seller", SELLER);
|
||||
|
||||
let response: Result<HashMap<String, String>, _> = client.request("buy_xmr", params).await;
|
||||
|
||||
match response {
|
||||
Err(e) => (),
|
||||
_ => panic!("Expected an error when monero_receive_address is malformed"),
|
||||
}
|
||||
|
||||
let mut params = ObjectParams::new();
|
||||
params.insert("bitcoin_change_address", BITCOIN_ADDR);
|
||||
params.insert("monero_receive_address", MONERO_ADDR);
|
||||
params.insert("seller", "invalid_seller");
|
||||
|
||||
let response: Result<HashMap<String, String>, _> = client.request("buy_xmr", params).await;
|
||||
|
||||
match response {
|
||||
Err(e) => (),
|
||||
_ => panic!("Expected an error when seller is malformed"),
|
||||
}
|
||||
|
||||
let mut params = ObjectParams::new();
|
||||
params.insert("bitcoin_change_address", BITCOIN_ADDR);
|
||||
params.insert("monero_receive_address", MONERO_ADDR);
|
||||
params.insert("seller", SELLER);
|
||||
|
||||
let response: Result<HashMap<String, String>, _> = client.request("buy_xmr", params).await;
|
||||
|
||||
match response {
|
||||
Ok(hash) => (),
|
||||
Err(e) => panic!("Expected a HashMap, got an error: {}", e),
|
||||
}
|
||||
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();
|
||||
|
||||
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");
|
||||
}
|
||||
*/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue