mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2025-12-16 17:14:13 -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
|
// workaround for warning over monero_rpc_process which we must own but not read
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub struct Context {
|
pub struct Context {
|
||||||
pub db: Arc<dyn Database + Send + Sync>,
|
db: Arc<dyn Database + Send + Sync>,
|
||||||
bitcoin_wallet: Option<Arc<bitcoin::Wallet>>,
|
bitcoin_wallet: Option<Arc<bitcoin::Wallet>>,
|
||||||
monero_wallet: Option<Arc<monero::Wallet>>,
|
monero_wallet: Option<Arc<monero::Wallet>>,
|
||||||
monero_rpc_process: Option<monero::WalletRpcProcess>,
|
monero_rpc_process: Option<monero::WalletRpcProcess>,
|
||||||
|
|
@ -205,6 +205,25 @@ impl Context {
|
||||||
|
|
||||||
Ok(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 {
|
impl fmt::Debug for Context {
|
||||||
|
|
@ -288,6 +307,25 @@ fn env_config_from(testnet: bool) -> EnvConfig {
|
||||||
Mainnet::get_config()
|
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)]
|
#[cfg(test)]
|
||||||
pub mod api_test {
|
pub mod api_test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
@ -350,38 +388,30 @@ pub mod api_test {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Request::new(
|
Request::new(Method::BuyXmr {
|
||||||
Method::BuyXmr {
|
|
||||||
seller,
|
seller,
|
||||||
bitcoin_change_address,
|
bitcoin_change_address,
|
||||||
monero_receive_address,
|
monero_receive_address,
|
||||||
swap_id: Uuid::new_v4(),
|
swap_id: Uuid::new_v4(),
|
||||||
},
|
})
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resume() -> Request {
|
pub fn resume() -> Request {
|
||||||
Request::new(
|
Request::new(Method::Resume {
|
||||||
Method::Resume {
|
|
||||||
swap_id: Uuid::from_str(SWAP_ID).unwrap(),
|
swap_id: Uuid::from_str(SWAP_ID).unwrap(),
|
||||||
},
|
})
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cancel() -> Request {
|
pub fn cancel() -> Request {
|
||||||
Request::new(
|
Request::new(Method::CancelAndRefund {
|
||||||
Method::CancelAndRefund {
|
|
||||||
swap_id: Uuid::from_str(SWAP_ID).unwrap(),
|
swap_id: Uuid::from_str(SWAP_ID).unwrap(),
|
||||||
},
|
})
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn refund() -> Request {
|
pub fn refund() -> Request {
|
||||||
Request::new(
|
Request::new(Method::CancelAndRefund {
|
||||||
Method::CancelAndRefund {
|
|
||||||
swap_id: Uuid::from_str(SWAP_ID).unwrap(),
|
swap_id: Uuid::from_str(SWAP_ID).unwrap(),
|
||||||
},
|
})
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -193,6 +193,9 @@ impl Request {
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.context("Could not get Bitcoin wallet")?;
|
.context("Could not get Bitcoin wallet")?;
|
||||||
|
|
||||||
|
let state = context.db.get_state(swap_id).await?;
|
||||||
|
let is_completed = state.swap_finished();
|
||||||
|
|
||||||
let peerId = context
|
let peerId = context
|
||||||
.db
|
.db
|
||||||
.get_peer_id(swap_id)
|
.get_peer_id(swap_id)
|
||||||
|
|
@ -205,9 +208,6 @@ impl Request {
|
||||||
.await
|
.await
|
||||||
.with_context(|| "Could not get addressess")?;
|
.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 start_date = context.db.get_swap_start_date(swap_id).await?;
|
||||||
|
|
||||||
let swap_state: BobState = state.try_into()?;
|
let swap_state: BobState = state.try_into()?;
|
||||||
|
|
@ -346,7 +346,7 @@ impl Request {
|
||||||
|
|
||||||
let (event_loop, mut event_loop_handle) =
|
let (event_loop, mut event_loop_handle) =
|
||||||
EventLoop::new(swap_id, swarm, seller_peer_id)?;
|
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 max_givable = || bitcoin_wallet.max_giveable(TxLock::script_size());
|
||||||
let estimate_fee = |amount| bitcoin_wallet.estimate_fee(TxLock::weight(), amount);
|
let estimate_fee = |amount| bitcoin_wallet.estimate_fee(TxLock::weight(), amount);
|
||||||
|
|
@ -429,7 +429,7 @@ impl Request {
|
||||||
.release_swap_lock()
|
.release_swap_lock()
|
||||||
.await
|
.await
|
||||||
.expect("Could not release swap lock");
|
.expect("Could not release swap lock");
|
||||||
}.instrument(Span::current()));
|
}.instrument(Span::none()));
|
||||||
|
|
||||||
Ok(json!({
|
Ok(json!({
|
||||||
"swapId": swap_id.to_string(),
|
"swapId": swap_id.to_string(),
|
||||||
|
|
@ -483,7 +483,7 @@ impl Request {
|
||||||
|
|
||||||
let (event_loop, event_loop_handle) =
|
let (event_loop, event_loop_handle) =
|
||||||
EventLoop::new(swap_id, swarm, seller_peer_id)?;
|
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 monero_receive_address = context.db.get_monero_address(swap_id).await?;
|
||||||
let swap = Swap::from_db(
|
let swap = Swap::from_db(
|
||||||
|
|
@ -529,7 +529,7 @@ impl Request {
|
||||||
.release_swap_lock()
|
.release_swap_lock()
|
||||||
.await
|
.await
|
||||||
.expect("Could not release swap lock");
|
.expect("Could not release swap lock");
|
||||||
}.instrument(Span::current()));
|
}.instrument(Span::none()));
|
||||||
Ok(json!({
|
Ok(json!({
|
||||||
"result": "ok",
|
"result": "ok",
|
||||||
}))
|
}))
|
||||||
|
|
@ -574,7 +574,7 @@ impl Request {
|
||||||
Method::GetRawStates => {
|
Method::GetRawStates => {
|
||||||
let raw_history = context.db.raw_all().await?;
|
let raw_history = context.db.raw_all().await?;
|
||||||
|
|
||||||
Ok(json!({ "raw_history": raw_history }))
|
Ok(json!({ "raw_states": raw_history }))
|
||||||
}
|
}
|
||||||
Method::Config => {
|
Method::Config => {
|
||||||
let data_dir_display = context.config.data_dir.display();
|
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!((amount, fees), (expected_amount, expected_fees));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
writer.captured(),
|
writer.captured(),
|
||||||
r" INFO swap: Received quote price=0.00100000 BTC minimum_amount=0.00000000 BTC maximum_amount=0.01000000 BTC
|
r" INFO swap::api::request: Received quote price=0.001 BTC minimum_amount=0 BTC maximum_amount=0.01 BTC
|
||||||
INFO swap: Deposit at least 0.00001000 BTC to cover the min quantity with fee!
|
INFO swap::api::request: Deposit at least 0.00001 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::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: Received Bitcoin new_balance=0.00100000 BTC max_giveable=0.00090000 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!((amount, fees), (expected_amount, expected_fees));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
writer.captured(),
|
writer.captured(),
|
||||||
r" INFO swap: Received quote price=0.00100000 BTC minimum_amount=0.00000000 BTC maximum_amount=0.01000000 BTC
|
r" INFO swap::api::request: Received quote price=0.001 BTC minimum_amount=0 BTC maximum_amount=0.01 BTC
|
||||||
INFO swap: Deposit at least 0.00001000 BTC to cover the min quantity with fee!
|
INFO swap::api::request: Deposit at least 0.00001 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::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: Received Bitcoin new_balance=0.10010000 BTC max_giveable=0.10000000 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!((amount, fees), (expected_amount, expected_fees));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
writer.captured(),
|
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!((amount, fees), (expected_amount, expected_fees));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
writer.captured(),
|
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!((amount, fees), (expected_amount, expected_fees));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
writer.captured(),
|
writer.captured(),
|
||||||
r" INFO swap: Received quote price=0.00100000 BTC minimum_amount=0.01000000 BTC maximum_amount=184467440737.09551615 BTC
|
r" INFO swap::api::request: Received quote price=0.001 BTC minimum_amount=0.01 BTC maximum_amount=184467440737.09551615 BTC
|
||||||
INFO swap: Deposit at least 0.01001000 BTC to cover the min quantity with fee!
|
INFO swap::api::request: Deposit at least 0.01001 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::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: Received Bitcoin new_balance=0.01010000 BTC max_giveable=0.01000000 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!((amount, fees), (expected_amount, expected_fees));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
writer.captured(),
|
writer.captured(),
|
||||||
r" INFO swap: Received quote price=0.00100000 BTC minimum_amount=0.01000000 BTC maximum_amount=184467440737.09551615 BTC
|
r" INFO swap::api::request: Received quote price=0.001 BTC minimum_amount=0.01 BTC maximum_amount=184467440737.09551615 BTC
|
||||||
INFO swap: Deposit at least 0.00991000 BTC to cover the min quantity with fee!
|
INFO swap::api::request: Deposit at least 0.00991 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::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: Received Bitcoin new_balance=0.01010000 BTC max_giveable=0.01000000 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!(matches!(error, tokio::time::error::Elapsed { .. }));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
writer.captured(),
|
writer.captured(),
|
||||||
r" INFO swap: Received quote price=0.00100000 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: Deposit at least 0.10001000 BTC to cover the min quantity with fee!
|
INFO swap::api::request: Deposit at least 0.10001 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::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: Received Bitcoin new_balance=0.01010000 BTC max_giveable=0.01000000 BTC
|
INFO swap::api::request: Received Bitcoin new_balance=0.0101 BTC max_giveable=0.01 BTC
|
||||||
INFO swap: Deposited amount is less than `min_quantity`
|
INFO swap::api::request: Deposited amount is less than `min_quantity`
|
||||||
INFO swap: Deposit at least 0.09001000 BTC to cover the min quantity with fee!
|
INFO swap::api::request: Deposit at least 0.09001 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
|
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!(
|
assert_eq!(
|
||||||
writer.captured(),
|
writer.captured(),
|
||||||
r" INFO swap: Received quote price=0.00100000 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: Deposit at least 0.10001000 BTC to cover the min quantity with fee!
|
INFO swap::api::request: Deposit at least 0.10001 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::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: Received Bitcoin new_balance=0.21000000 BTC max_giveable=0.20000000 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::env::{GetConfig, Regtest};
|
||||||
use crate::protocol::{alice, bob};
|
use crate::protocol::{alice, bob};
|
||||||
use rand::rngs::OsRng;
|
use rand::rngs::OsRng;
|
||||||
use uuid::Uuid;
|
|
||||||
use std::matches;
|
use std::matches;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn lock_confirmations_le_to_cancel_timelock_no_timelock_expired() {
|
fn lock_confirmations_le_to_cancel_timelock_no_timelock_expired() {
|
||||||
|
|
|
||||||
|
|
@ -194,6 +194,7 @@ impl Wallet {
|
||||||
tokio::time::sleep(Duration::from_secs(5)).await;
|
tokio::time::sleep(Duration::from_secs(5)).await;
|
||||||
}
|
}
|
||||||
}.instrument(Span::current()));
|
}.instrument(Span::current()));
|
||||||
|
}.instrument(Span::none()));
|
||||||
|
|
||||||
Subscription {
|
Subscription {
|
||||||
receiver,
|
receiver,
|
||||||
|
|
|
||||||
|
|
@ -499,16 +499,20 @@ mod tests {
|
||||||
|
|
||||||
use crate::api::api_test::*;
|
use crate::api::api_test::*;
|
||||||
use crate::api::Config;
|
use crate::api::Config;
|
||||||
use crate::fs::system_data_dir;
|
|
||||||
use crate::monero::monero_address::MoneroAddressNetworkMismatch;
|
use crate::monero::monero_address::MoneroAddressNetworkMismatch;
|
||||||
use serial_test::serial;
|
|
||||||
|
|
||||||
const BINARY_NAME: &str = "swap";
|
const BINARY_NAME: &str = "swap";
|
||||||
const ARGS_DATA_DIR: &str = "/tmp/dir/";
|
const ARGS_DATA_DIR: &str = "/tmp/dir/";
|
||||||
|
|
||||||
#[tokio::test]
|
#[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![
|
let raw_ars = vec![
|
||||||
BINARY_NAME,
|
BINARY_NAME,
|
||||||
"buy-xmr",
|
"buy-xmr",
|
||||||
|
|
@ -523,23 +527,31 @@ mod tests {
|
||||||
let args = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
let args = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
||||||
let (is_testnet, debug, json) = (false, false, false);
|
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 {
|
let (actual_config, actual_request) = match args {
|
||||||
ParseResult::Context(context, request) => (context.config.clone(), request),
|
ParseResult::Context(context, request) => (context.config.clone(), request),
|
||||||
_ => panic!("Couldn't parse result"),
|
_ => 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_config, expected_config);
|
||||||
assert_eq!(actual_request, Box::new(expected_request));
|
assert_eq!(actual_request, Box::new(expected_request));
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
// given_buy_xmr_on_testnet_then_defaults_to_testnet
|
||||||
#[serial]
|
|
||||||
async fn given_buy_xmr_on_testnet_then_defaults_to_testnet() {
|
|
||||||
let raw_ars = vec![
|
let raw_ars = vec![
|
||||||
BINARY_NAME,
|
BINARY_NAME,
|
||||||
"--testnet",
|
"--testnet",
|
||||||
|
|
@ -555,7 +567,7 @@ mod tests {
|
||||||
let args = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
let args = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
||||||
let (is_testnet, debug, json) = (true, false, false);
|
let (is_testnet, debug, json) = (true, false, false);
|
||||||
|
|
||||||
let (expected_config, expected_request) = (
|
let (expected_config, mut expected_request) = (
|
||||||
Config::default(is_testnet, None, debug, json),
|
Config::default(is_testnet, None, debug, json),
|
||||||
Request::buy_xmr(is_testnet),
|
Request::buy_xmr(is_testnet),
|
||||||
);
|
);
|
||||||
|
|
@ -565,13 +577,20 @@ mod tests {
|
||||||
_ => panic!("Couldn't parse result"),
|
_ => 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_config, expected_config);
|
||||||
assert_eq!(actual_request, Box::new(expected_request));
|
assert_eq!(actual_request, Box::new(expected_request));
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
// given_buy_xmr_on_mainnet_with_testnet_address_then_fails
|
||||||
#[serial]
|
|
||||||
async fn given_buy_xmr_on_mainnet_with_testnet_address_then_fails() {
|
|
||||||
let raw_ars = vec![
|
let raw_ars = vec![
|
||||||
BINARY_NAME,
|
BINARY_NAME,
|
||||||
"buy-xmr",
|
"buy-xmr",
|
||||||
|
|
@ -592,11 +611,8 @@ mod tests {
|
||||||
actual: monero::Network::Stagenet
|
actual: monero::Network::Stagenet
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
// given_buy_xmr_on_testnet_with_mainnet_address_then_fails
|
||||||
#[serial]
|
|
||||||
async fn given_buy_xmr_on_testnet_with_mainnet_address_then_fails() {
|
|
||||||
let raw_ars = vec![
|
let raw_ars = vec![
|
||||||
BINARY_NAME,
|
BINARY_NAME,
|
||||||
"--testnet",
|
"--testnet",
|
||||||
|
|
@ -618,11 +634,8 @@ mod tests {
|
||||||
actual: monero::Network::Mainnet
|
actual: monero::Network::Mainnet
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
// given_resume_on_mainnet_then_defaults_to_mainnet
|
||||||
#[serial]
|
|
||||||
async fn given_resume_on_mainnet_then_defaults_to_mainnet() {
|
|
||||||
let raw_ars = vec![BINARY_NAME, "resume", "--swap-id", SWAP_ID];
|
let raw_ars = vec![BINARY_NAME, "resume", "--swap-id", SWAP_ID];
|
||||||
|
|
||||||
let args = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
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_config, expected_config);
|
||||||
assert_eq!(actual_request, Box::new(expected_request));
|
assert_eq!(actual_request, Box::new(expected_request));
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
// given_resume_on_testnet_then_defaults_to_testnet
|
||||||
#[serial]
|
|
||||||
async fn given_resume_on_testnet_then_defaults_to_testnet() {
|
|
||||||
let raw_ars = vec![BINARY_NAME, "--testnet", "resume", "--swap-id", SWAP_ID];
|
let raw_ars = vec![BINARY_NAME, "--testnet", "resume", "--swap-id", SWAP_ID];
|
||||||
|
|
||||||
let args = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
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_config, expected_config);
|
||||||
assert_eq!(actual_request, Box::new(expected_request));
|
assert_eq!(actual_request, Box::new(expected_request));
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
// given_cancel_on_mainnet_then_defaults_to_mainnet
|
||||||
#[serial]
|
|
||||||
async fn given_cancel_on_mainnet_then_defaults_to_mainnet() {
|
|
||||||
let raw_ars = vec![BINARY_NAME, "cancel", "--swap-id", SWAP_ID];
|
let raw_ars = vec![BINARY_NAME, "cancel", "--swap-id", SWAP_ID];
|
||||||
|
|
||||||
let args = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
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_config, expected_config);
|
||||||
assert_eq!(actual_request, Box::new(expected_request));
|
assert_eq!(actual_request, Box::new(expected_request));
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
// given_cancel_on_testnet_then_defaults_to_testnet
|
||||||
#[serial]
|
|
||||||
async fn given_cancel_on_testnet_then_defaults_to_testnet() {
|
|
||||||
let raw_ars = vec![BINARY_NAME, "--testnet", "cancel", "--swap-id", SWAP_ID];
|
let raw_ars = vec![BINARY_NAME, "--testnet", "cancel", "--swap-id", SWAP_ID];
|
||||||
|
|
||||||
let args = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
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_config, expected_config);
|
||||||
assert_eq!(actual_request, Box::new(expected_request));
|
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 raw_ars = vec![BINARY_NAME, "refund", "--swap-id", SWAP_ID];
|
||||||
|
|
||||||
let args = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
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_config, expected_config);
|
||||||
assert_eq!(actual_request, Box::new(expected_request));
|
assert_eq!(actual_request, Box::new(expected_request));
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
// given_refund_on_testnet_then_defaults_to_testnet
|
||||||
#[serial]
|
|
||||||
async fn given_refund_on_testnet_then_defaults_to_testnet() {
|
|
||||||
let raw_ars = vec![BINARY_NAME, "--testnet", "refund", "--swap-id", SWAP_ID];
|
let raw_ars = vec![BINARY_NAME, "--testnet", "refund", "--swap-id", SWAP_ID];
|
||||||
|
|
||||||
let args = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
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_config, expected_config);
|
||||||
assert_eq!(actual_request, Box::new(expected_request));
|
assert_eq!(actual_request, Box::new(expected_request));
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
// given_buy_xmr_on_mainnet_with_data_dir_then_data_dir_set
|
||||||
#[serial]
|
|
||||||
async fn given_buy_xmr_on_mainnet_with_data_dir_then_data_dir_set() {
|
|
||||||
let raw_ars = vec![
|
let raw_ars = vec![
|
||||||
BINARY_NAME,
|
BINARY_NAME,
|
||||||
"--data-base-dir",
|
"--data-base-dir",
|
||||||
|
|
@ -773,7 +767,7 @@ mod tests {
|
||||||
let (is_testnet, debug, json) = (false, false, false);
|
let (is_testnet, debug, json) = (false, false, false);
|
||||||
let data_dir = PathBuf::from_str(ARGS_DATA_DIR).unwrap();
|
let data_dir = PathBuf::from_str(ARGS_DATA_DIR).unwrap();
|
||||||
|
|
||||||
let (expected_config, expected_request) = (
|
let (expected_config, mut expected_request) = (
|
||||||
Config::default(is_testnet, Some(data_dir.clone()), debug, json),
|
Config::default(is_testnet, Some(data_dir.clone()), debug, json),
|
||||||
Request::buy_xmr(is_testnet),
|
Request::buy_xmr(is_testnet),
|
||||||
);
|
);
|
||||||
|
|
@ -783,13 +777,20 @@ mod tests {
|
||||||
_ => panic!("Couldn't parse result"),
|
_ => 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_config, expected_config);
|
||||||
assert_eq!(actual_request, Box::new(expected_request));
|
assert_eq!(actual_request, Box::new(expected_request));
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
// given_buy_xmr_on_testnet_with_data_dir_then_data_dir_set
|
||||||
#[serial]
|
|
||||||
async fn given_buy_xmr_on_testnet_with_data_dir_then_data_dir_set() {
|
|
||||||
let raw_ars = vec![
|
let raw_ars = vec![
|
||||||
BINARY_NAME,
|
BINARY_NAME,
|
||||||
"--testnet",
|
"--testnet",
|
||||||
|
|
@ -808,7 +809,7 @@ mod tests {
|
||||||
let args = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
let args = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
||||||
let (is_testnet, debug, json) = (true, false, false);
|
let (is_testnet, debug, json) = (true, false, false);
|
||||||
|
|
||||||
let (expected_config, expected_request) = (
|
let (expected_config, mut expected_request) = (
|
||||||
Config::default(is_testnet, Some(data_dir.clone()), debug, json),
|
Config::default(is_testnet, Some(data_dir.clone()), debug, json),
|
||||||
Request::buy_xmr(is_testnet),
|
Request::buy_xmr(is_testnet),
|
||||||
);
|
);
|
||||||
|
|
@ -818,13 +819,20 @@ mod tests {
|
||||||
_ => panic!("Couldn't parse result"),
|
_ => 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_config, expected_config);
|
||||||
assert_eq!(actual_request, Box::new(expected_request));
|
assert_eq!(actual_request, Box::new(expected_request));
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
// given_resume_on_mainnet_with_data_dir_then_data_dir_set
|
||||||
#[serial]
|
|
||||||
async fn given_resume_on_mainnet_with_data_dir_then_data_dir_set() {
|
|
||||||
let raw_ars = vec![
|
let raw_ars = vec![
|
||||||
BINARY_NAME,
|
BINARY_NAME,
|
||||||
"--data-base-dir",
|
"--data-base-dir",
|
||||||
|
|
@ -838,11 +846,21 @@ mod tests {
|
||||||
let args = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
let args = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
||||||
let (is_testnet, debug, json) = (false, false, false);
|
let (is_testnet, debug, json) = (false, false, false);
|
||||||
|
|
||||||
let (expected_config, expected_request) = (
|
let (expected_config, mut expected_request) = (
|
||||||
Config::default(is_testnet, Some(data_dir.clone()), debug, json),
|
Config::default(is_testnet, Some(data_dir.clone()), debug, json),
|
||||||
Request::resume(),
|
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 {
|
let (actual_config, actual_request) = match args {
|
||||||
ParseResult::Context(context, request) => (context.config.clone(), request),
|
ParseResult::Context(context, request) => (context.config.clone(), request),
|
||||||
_ => panic!("Couldn't parse result"),
|
_ => panic!("Couldn't parse result"),
|
||||||
|
|
@ -850,11 +868,8 @@ mod tests {
|
||||||
|
|
||||||
assert_eq!(actual_config, expected_config);
|
assert_eq!(actual_config, expected_config);
|
||||||
assert_eq!(actual_request, Box::new(expected_request));
|
assert_eq!(actual_request, Box::new(expected_request));
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
// given_resume_on_testnet_with_data_dir_then_data_dir_set
|
||||||
#[serial]
|
|
||||||
async fn given_resume_on_testnet_with_data_dir_then_data_dir_set() {
|
|
||||||
let raw_ars = vec![
|
let raw_ars = vec![
|
||||||
BINARY_NAME,
|
BINARY_NAME,
|
||||||
"--testnet",
|
"--testnet",
|
||||||
|
|
@ -881,11 +896,8 @@ mod tests {
|
||||||
|
|
||||||
assert_eq!(actual_config, expected_config);
|
assert_eq!(actual_config, expected_config);
|
||||||
assert_eq!(actual_request, Box::new(expected_request));
|
assert_eq!(actual_request, Box::new(expected_request));
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
// given_buy_xmr_on_mainnet_with_debug_then_debug_set
|
||||||
#[serial]
|
|
||||||
async fn given_buy_xmr_on_mainnet_with_debug_then_debug_set() {
|
|
||||||
let raw_ars = vec![
|
let raw_ars = vec![
|
||||||
BINARY_NAME,
|
BINARY_NAME,
|
||||||
"--debug",
|
"--debug",
|
||||||
|
|
@ -901,7 +913,7 @@ mod tests {
|
||||||
let args = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
let args = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
||||||
let (is_testnet, debug, json) = (false, true, false);
|
let (is_testnet, debug, json) = (false, true, false);
|
||||||
|
|
||||||
let (expected_config, expected_request) = (
|
let (expected_config, mut expected_request) = (
|
||||||
Config::default(is_testnet, None, debug, json),
|
Config::default(is_testnet, None, debug, json),
|
||||||
Request::buy_xmr(is_testnet),
|
Request::buy_xmr(is_testnet),
|
||||||
);
|
);
|
||||||
|
|
@ -911,13 +923,20 @@ mod tests {
|
||||||
_ => panic!("Couldn't parse result"),
|
_ => 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_config, expected_config);
|
||||||
assert_eq!(actual_request, Box::new(expected_request));
|
assert_eq!(actual_request, Box::new(expected_request));
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
// given_buy_xmr_on_testnet_with_debug_then_debug_set
|
||||||
#[serial]
|
|
||||||
async fn given_buy_xmr_on_testnet_with_debug_then_debug_set() {
|
|
||||||
let raw_ars = vec![
|
let raw_ars = vec![
|
||||||
BINARY_NAME,
|
BINARY_NAME,
|
||||||
"--testnet",
|
"--testnet",
|
||||||
|
|
@ -934,7 +953,7 @@ mod tests {
|
||||||
let args = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
let args = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
||||||
let (is_testnet, debug, json) = (true, true, false);
|
let (is_testnet, debug, json) = (true, true, false);
|
||||||
|
|
||||||
let (expected_config, expected_request) = (
|
let (expected_config, mut expected_request) = (
|
||||||
Config::default(is_testnet, None, debug, json),
|
Config::default(is_testnet, None, debug, json),
|
||||||
Request::buy_xmr(is_testnet),
|
Request::buy_xmr(is_testnet),
|
||||||
);
|
);
|
||||||
|
|
@ -944,19 +963,26 @@ mod tests {
|
||||||
_ => panic!("Couldn't parse result"),
|
_ => 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_config, expected_config);
|
||||||
assert_eq!(actual_request, Box::new(expected_request));
|
assert_eq!(actual_request, Box::new(expected_request));
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
// given_resume_on_mainnet_with_debug_then_debug_set
|
||||||
#[serial]
|
|
||||||
async fn given_resume_on_mainnet_with_debug_then_debug_set() {
|
|
||||||
let raw_ars = vec![BINARY_NAME, "--debug", "resume", "--swap-id", SWAP_ID];
|
let raw_ars = vec![BINARY_NAME, "--debug", "resume", "--swap-id", SWAP_ID];
|
||||||
|
|
||||||
let args = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
let args = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
||||||
let (is_testnet, debug, json) = (false, true, false);
|
let (is_testnet, debug, json) = (false, true, false);
|
||||||
|
|
||||||
let (expected_config, expected_request) = (
|
let (expected_config, mut expected_request) = (
|
||||||
Config::default(is_testnet, None, debug, json),
|
Config::default(is_testnet, None, debug, json),
|
||||||
Request::resume(),
|
Request::resume(),
|
||||||
);
|
);
|
||||||
|
|
@ -966,13 +992,20 @@ mod tests {
|
||||||
_ => panic!("Couldn't parse result"),
|
_ => 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_config, expected_config);
|
||||||
assert_eq!(actual_request, Box::new(expected_request));
|
assert_eq!(actual_request, Box::new(expected_request));
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
// given_resume_on_testnet_with_debug_then_debug_set
|
||||||
#[serial]
|
|
||||||
async fn given_resume_on_testnet_with_debug_then_debug_set() {
|
|
||||||
let raw_ars = vec![
|
let raw_ars = vec![
|
||||||
BINARY_NAME,
|
BINARY_NAME,
|
||||||
"--testnet",
|
"--testnet",
|
||||||
|
|
@ -997,11 +1030,8 @@ mod tests {
|
||||||
|
|
||||||
assert_eq!(actual_config, expected_config);
|
assert_eq!(actual_config, expected_config);
|
||||||
assert_eq!(actual_request, Box::new(expected_request));
|
assert_eq!(actual_request, Box::new(expected_request));
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
// given_buy_xmr_on_mainnet_with_json_then_json_set
|
||||||
#[serial]
|
|
||||||
async fn given_buy_xmr_on_mainnet_with_json_then_json_set() {
|
|
||||||
let raw_ars = vec![
|
let raw_ars = vec![
|
||||||
BINARY_NAME,
|
BINARY_NAME,
|
||||||
"--json",
|
"--json",
|
||||||
|
|
@ -1016,9 +1046,8 @@ mod tests {
|
||||||
|
|
||||||
let args = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
let args = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
||||||
let (is_testnet, debug, json) = (false, false, true);
|
let (is_testnet, debug, json) = (false, false, true);
|
||||||
let data_dir = data_dir_path_cli(is_testnet);
|
|
||||||
|
|
||||||
let (expected_config, expected_request) = (
|
let (expected_config, mut expected_request) = (
|
||||||
Config::default(is_testnet, None, debug, json),
|
Config::default(is_testnet, None, debug, json),
|
||||||
Request::buy_xmr(is_testnet),
|
Request::buy_xmr(is_testnet),
|
||||||
);
|
);
|
||||||
|
|
@ -1028,13 +1057,20 @@ mod tests {
|
||||||
_ => panic!("Couldn't parse result"),
|
_ => 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_config, expected_config);
|
||||||
assert_eq!(actual_request, Box::new(expected_request));
|
assert_eq!(actual_request, Box::new(expected_request));
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
// given_buy_xmr_on_testnet_with_json_then_json_set
|
||||||
#[serial]
|
|
||||||
async fn given_buy_xmr_on_testnet_with_json_then_json_set() {
|
|
||||||
let raw_ars = vec![
|
let raw_ars = vec![
|
||||||
BINARY_NAME,
|
BINARY_NAME,
|
||||||
"--testnet",
|
"--testnet",
|
||||||
|
|
@ -1050,7 +1086,7 @@ mod tests {
|
||||||
|
|
||||||
let (is_testnet, debug, json) = (true, false, true);
|
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),
|
Config::default(is_testnet, None, debug, json),
|
||||||
Request::buy_xmr(is_testnet),
|
Request::buy_xmr(is_testnet),
|
||||||
);
|
);
|
||||||
|
|
@ -1061,13 +1097,20 @@ mod tests {
|
||||||
_ => panic!("Couldn't parse result"),
|
_ => 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_config, expected_config);
|
||||||
assert_eq!(actual_request, Box::new(expected_request));
|
assert_eq!(actual_request, Box::new(expected_request));
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
// given_resume_on_mainnet_with_json_then_json_set
|
||||||
#[serial]
|
|
||||||
async fn given_resume_on_mainnet_with_json_then_json_set() {
|
|
||||||
let raw_ars = vec![BINARY_NAME, "--json", "resume", "--swap-id", SWAP_ID];
|
let raw_ars = vec![BINARY_NAME, "--json", "resume", "--swap-id", SWAP_ID];
|
||||||
let args = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
let args = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
||||||
let (is_testnet, debug, json) = (false, false, true);
|
let (is_testnet, debug, json) = (false, false, true);
|
||||||
|
|
@ -1084,11 +1127,8 @@ mod tests {
|
||||||
|
|
||||||
assert_eq!(actual_config, expected_config);
|
assert_eq!(actual_config, expected_config);
|
||||||
assert_eq!(actual_request, Box::new(expected_request));
|
assert_eq!(actual_request, Box::new(expected_request));
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
// given_resume_on_testnet_with_json_then_json_set
|
||||||
#[serial]
|
|
||||||
async fn given_resume_on_testnet_with_json_then_json_set() {
|
|
||||||
let raw_ars = vec![
|
let raw_ars = vec![
|
||||||
BINARY_NAME,
|
BINARY_NAME,
|
||||||
"--testnet",
|
"--testnet",
|
||||||
|
|
@ -1113,11 +1153,8 @@ mod tests {
|
||||||
|
|
||||||
assert_eq!(actual_config, expected_config);
|
assert_eq!(actual_config, expected_config);
|
||||||
assert_eq!(actual_request, Box::new(expected_request));
|
assert_eq!(actual_request, Box::new(expected_request));
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
// only_bech32_addresses_mainnet_are_allowed
|
||||||
#[serial]
|
|
||||||
async fn only_bech32_addresses_mainnet_are_allowed() {
|
|
||||||
let raw_ars = vec![
|
let raw_ars = vec![
|
||||||
BINARY_NAME,
|
BINARY_NAME,
|
||||||
"buy-xmr",
|
"buy-xmr",
|
||||||
|
|
@ -1128,7 +1165,7 @@ mod tests {
|
||||||
"--seller",
|
"--seller",
|
||||||
MULTI_ADDRESS,
|
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![
|
let raw_ars = vec![
|
||||||
BINARY_NAME,
|
BINARY_NAME,
|
||||||
|
|
@ -1140,7 +1177,7 @@ mod tests {
|
||||||
"--seller",
|
"--seller",
|
||||||
MULTI_ADDRESS,
|
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![
|
let raw_ars = vec![
|
||||||
BINARY_NAME,
|
BINARY_NAME,
|
||||||
|
|
@ -1154,11 +1191,8 @@ mod tests {
|
||||||
];
|
];
|
||||||
let result = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
let result = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
||||||
assert!(matches!(result, ParseResult::Context(_, _)));
|
assert!(matches!(result, ParseResult::Context(_, _)));
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
// only_bech32_addresses_testnet_are_allowed
|
||||||
#[serial]
|
|
||||||
async fn only_bech32_addresses_testnet_are_allowed() {
|
|
||||||
let raw_ars = vec![
|
let raw_ars = vec![
|
||||||
BINARY_NAME,
|
BINARY_NAME,
|
||||||
"--testnet",
|
"--testnet",
|
||||||
|
|
@ -1170,7 +1204,7 @@ mod tests {
|
||||||
"--seller",
|
"--seller",
|
||||||
MULTI_ADDRESS,
|
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![
|
let raw_ars = vec![
|
||||||
BINARY_NAME,
|
BINARY_NAME,
|
||||||
|
|
@ -1183,7 +1217,7 @@ mod tests {
|
||||||
"--seller",
|
"--seller",
|
||||||
MULTI_ADDRESS,
|
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![
|
let raw_ars = vec![
|
||||||
BINARY_NAME,
|
BINARY_NAME,
|
||||||
|
|
@ -1199,12 +1233,4 @@ mod tests {
|
||||||
let result = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
let result = parse_args_and_apply_defaults(raw_ars).await.unwrap();
|
||||||
assert!(matches!(result, ParseResult::Context(_, _)));
|
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,
|
cmd: Method,
|
||||||
context: &Arc<Context>,
|
context: &Arc<Context>,
|
||||||
) -> Result<serde_json::Value, jsonrpsee_core::Error> {
|
) -> 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>>()
|
.parse::<HashMap<String, String>>()
|
||||||
.map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))?;
|
.ok()
|
||||||
|
.and_then(|params_parsed| params_parsed.get("log_reference_id").cloned());
|
||||||
let reference_id = params_parsed.get("log_reference_id");
|
|
||||||
|
|
||||||
let request = Request::with_id(cmd, reference_id.map(|s| s.clone()));
|
let request = Request::with_id(cmd, reference_id.map(|s| s.clone()));
|
||||||
request
|
request
|
||||||
|
|
|
||||||
|
|
@ -23,9 +23,9 @@ use swap::network::rendezvous::XmrBtcNamespace;
|
||||||
use swap::network::swarm;
|
use swap::network::swarm;
|
||||||
use swap::protocol::alice::{AliceState, Swap};
|
use swap::protocol::alice::{AliceState, Swap};
|
||||||
use swap::protocol::bob::BobState;
|
use swap::protocol::bob::BobState;
|
||||||
use swap::protocol::{alice, bob};
|
use swap::protocol::{alice, bob, Database};
|
||||||
use swap::seed::Seed;
|
use swap::seed::Seed;
|
||||||
use swap::{asb, bitcoin, cli, env, monero};
|
use swap::{api, asb, bitcoin, cli, env, monero};
|
||||||
use tempfile::{tempdir, NamedTempFile};
|
use tempfile::{tempdir, NamedTempFile};
|
||||||
use testcontainers::clients::Cli;
|
use testcontainers::clients::Cli;
|
||||||
use testcontainers::{Container, Docker, RunArgs};
|
use testcontainers::{Container, Docker, RunArgs};
|
||||||
|
|
@ -454,6 +454,8 @@ impl BobParams {
|
||||||
}
|
}
|
||||||
let db = Arc::new(SqliteDatabase::open(&self.db_path).await?);
|
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(
|
let swap = bob::Swap::new(
|
||||||
db,
|
db,
|
||||||
swap_id,
|
swap_id,
|
||||||
|
|
@ -534,6 +536,17 @@ pub struct TestContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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) {
|
pub async fn restart_alice(&mut self) {
|
||||||
self.alice_handle.abort();
|
self.alice_handle.abort();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,33 @@
|
||||||
|
pub mod harness;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
use jsonrpsee::rpc_params;
|
|
||||||
use jsonrpsee::ws_client::WsClientBuilder;
|
use jsonrpsee::ws_client::WsClientBuilder;
|
||||||
use jsonrpsee_core::client::ClientT;
|
use jsonrpsee_core::client::{Client, ClientT};
|
||||||
use jsonrpsee_core::params::ObjectParams;
|
use jsonrpsee_core::params::ObjectParams;
|
||||||
|
|
||||||
use serial_test::serial;
|
use serial_test::serial;
|
||||||
|
|
||||||
|
use serde_json::{json, Value};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::future::Future;
|
||||||
|
use std::net::SocketAddr;
|
||||||
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use swap::api::request::{Method, Request};
|
use swap::api::request::{Method, Request};
|
||||||
use swap::api::Context;
|
use swap::api::{Config, Context, SwapLock};
|
||||||
use swap::cli::command::{Bitcoin, Monero};
|
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;
|
use uuid::Uuid;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
@ -27,419 +41,511 @@ const MONERO_ADDR: &str = "53gEuGZUhP9JMEBZoGaFNzhwEgiG7hwQdMCqFxiyiTeFPmkbt1mAo
|
||||||
const SELLER: &str =
|
const SELLER: &str =
|
||||||
"/ip4/127.0.0.1/tcp/9939/p2p/12D3KooWCdMKjesXMJz1SiZ7HgotrxuqhQJbP5sgBm2BwP1cqThi";
|
"/ip4/127.0.0.1/tcp/9939/p2p/12D3KooWCdMKjesXMJz1SiZ7HgotrxuqhQJbP5sgBm2BwP1cqThi";
|
||||||
const SWAP_ID: &str = "ea030832-3be9-454f-bb98-5ea9a788406b";
|
const SWAP_ID: &str = "ea030832-3be9-454f-bb98-5ea9a788406b";
|
||||||
|
const SERVER_START_TIMEOUT_SECS: u64 = 50;
|
||||||
|
|
||||||
pub async fn initialize_context() -> (Arc<Context>, Request) {
|
pub async fn setup_daemon<T, F>(testfn: T)
|
||||||
let (is_testnet, debug, json) = (true, false, false);
|
where
|
||||||
// let data_dir = data::data_dir_from(None, is_testnet).unwrap();
|
T: Fn(TestContext, Client, MakeCapturingWriter, Arc<Context>) -> F,
|
||||||
let server_address = None;
|
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 {
|
let request = Request::new(Method::StartDaemon {
|
||||||
bitcoin_electrum_rpc_url: None,
|
server_address: Some(server_address),
|
||||||
bitcoin_target_block: None,
|
});
|
||||||
};
|
|
||||||
|
|
||||||
let _monero = Monero {
|
let context = Arc::new(harness_context.get_bob_context().await);
|
||||||
monero_daemon_address: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let request = Request::new(Method::StartDaemon { server_address: None });
|
let context_clone = context.clone();
|
||||||
|
|
||||||
let context = Context::build(
|
tokio::spawn(async move {
|
||||||
Some(bitcoin),
|
if let Err(err) = request.call(context_clone).await {
|
||||||
None,
|
println!("Failed to initialize daemon for testing: {}", err);
|
||||||
None,
|
}
|
||||||
None,
|
});
|
||||||
is_testnet,
|
|
||||||
debug,
|
for _ in 0..SERVER_START_TIMEOUT_SECS {
|
||||||
json,
|
if writer.captured().contains("Started RPC server") {
|
||||||
server_address,
|
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
|
.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]
|
#[tokio::test]
|
||||||
#[serial]
|
#[serial]
|
||||||
pub async fn can_start_server() {
|
pub async fn can_start_server() {
|
||||||
let (ctx, mut request) = initialize_context().await;
|
setup_daemon(|_, _, _, _| async move {
|
||||||
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);
|
assert!(true);
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[serial]
|
#[serial]
|
||||||
pub async fn get_bitcoin_balance() {
|
pub async fn get_bitcoin_balance() {
|
||||||
let (ctx, mut request) = initialize_context().await;
|
setup_daemon(|_, client| async move {
|
||||||
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 response: HashMap<String, i32> = client
|
let response: HashMap<String, i32> = client
|
||||||
.request("get_bitcoin_balance", rpc_params!["id"])
|
.request("get_bitcoin_balance", ObjectParams::new())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
assert_eq!(response, HashMap::from([("balance".to_string(), 0)]));
|
assert_eq!(response, HashMap::from([("balance".to_string(), 10000000)]));
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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]
|
#[tokio::test]
|
||||||
#[serial]
|
#[serial]
|
||||||
pub async fn get_history() {
|
pub async fn get_history() {
|
||||||
let (ctx, mut request) = initialize_context().await;
|
setup_daemon(|mut harness_ctx, client| async move {
|
||||||
let move_ctx = Arc::clone(&ctx);
|
// Start a swap and wait for xmr lock transaction to be published (XmrLockTransactionSent)
|
||||||
tokio::spawn(async move {
|
let (bob_swap, _) = harness_ctx.bob_swap().await;
|
||||||
request.call(Arc::clone(&move_ctx)).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);
|
let response: HashMap<String, Vec<(Uuid, String)>> = client
|
||||||
tokio::time::sleep(Duration::from_secs(3)).await;
|
.request("get_history", ObjectParams::new())
|
||||||
|
.await
|
||||||
let client = WsClientBuilder::default().build(&url).await.unwrap();
|
.unwrap();
|
||||||
let mut params = ObjectParams::new();
|
let swaps: Vec<(Uuid, String)> = vec![(bob_swap_id, "btc is locked".to_string())];
|
||||||
|
|
||||||
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)]));
|
assert_eq!(response, HashMap::from([("swaps".to_string(), swaps)]));
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[serial]
|
#[serial]
|
||||||
pub async fn get_raw_history() {
|
pub async fn get_raw_states() {
|
||||||
let (ctx, mut request) = initialize_context().await;
|
setup_daemon(|mut harness_ctx, client| async move {
|
||||||
let move_ctx = Arc::clone(&ctx);
|
// 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 {
|
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);
|
let response: HashMap<String, String> = client
|
||||||
tokio::time::sleep(Duration::from_secs(3)).await;
|
.request("suspend_current_swap", ObjectParams::new())
|
||||||
|
.await
|
||||||
let client = WsClientBuilder::default().build(&url).await.unwrap();
|
.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();
|
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
response,
|
response,
|
||||||
HashMap::from([("raw_history".to_string(), raw_history)])
|
HashMap::from([("swapId".to_string(), SWAP_ID.to_string())])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[serial]
|
#[serial]
|
||||||
pub async fn get_seller() {
|
pub async fn suspend_current_swap_timeout() {
|
||||||
let (ctx, mut request) = initialize_context().await;
|
let (client, _, ctx) = initialize_context().await;
|
||||||
let move_ctx = Arc::clone(&ctx);
|
ctx.swap_lock
|
||||||
tokio::spawn(async move {
|
.acquire_swap_lock(Uuid::parse_str(SWAP_ID).unwrap())
|
||||||
request.call(Arc::clone(&move_ctx)).await;
|
.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 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),
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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