mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2025-08-24 14:15:55 -04:00
refactor(workspace): swap-fs, swap-serde, swap-env crates (#459)
* refactor: Remove monero-wallet crate * refactor: swap-fs, swap-env, swap-serde subcrates, move dependencies into workspace root * remove unrelated diff * remove uncommented code * remove unncessary diff * merge * refactor: remove env.rs, fix clippy error
This commit is contained in:
parent
e29dd4dcf2
commit
bc96586acf
53 changed files with 1074 additions and 924 deletions
936
Cargo.lock
generated
936
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
22
Cargo.toml
22
Cargo.toml
|
@ -1,6 +1,26 @@
|
|||
[workspace]
|
||||
resolver = "2"
|
||||
members = ["electrum-pool", "monero-rpc", "monero-rpc-pool", "monero-sys", "seed", "src-tauri", "swap"]
|
||||
members = [ "electrum-pool", "monero-rpc", "monero-rpc-pool", "monero-sys", "seed", "src-tauri", "swap", "swap-env", "swap-fs", "swap-serde"]
|
||||
|
||||
[workspace.dependencies]
|
||||
anyhow = "1"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
tokio = { version = "1", features = ["rt-multi-thread", "time", "macros", "sync"] }
|
||||
futures = { version = "0.3", default-features = false, features = ["std"] }
|
||||
tracing = { version = "0.1", features = ["attributes"] }
|
||||
bitcoin = { version = "0.32", features = ["rand", "serde"] }
|
||||
monero = { version = "0.12", features = ["serde_support"] }
|
||||
rand = "0.8"
|
||||
uuid = { version = "1", features = ["v4"] }
|
||||
typeshare = "1.0"
|
||||
thiserror = "1"
|
||||
reqwest = { version = "0.12", default-features = false, features = ["json"] }
|
||||
rust_decimal = { version = "1", features = ["serde-float"] }
|
||||
rust_decimal_macros = "1"
|
||||
libp2p = { version = "0.53.2" }
|
||||
url = { version = "2", features = ["serde"] }
|
||||
hex = "0.4"
|
||||
|
||||
[patch.crates-io]
|
||||
# patch until new release https://github.com/thomaseizinger/rust-jsonrpc-client/pull/51
|
||||
|
|
|
@ -7,11 +7,11 @@ edition = "2021"
|
|||
[dependencies]
|
||||
backoff = { version = "0.4", features = ["tokio"] }
|
||||
bdk_electrum = { version = "0.19", default-features = false, features = ["use-rustls-ring"] }
|
||||
bitcoin = { version = "0.32", features = ["rand", "serde"] }
|
||||
futures = { version = "0.3", default-features = false, features = ["std"] }
|
||||
bitcoin = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
once_cell = "1.19"
|
||||
tokio = { version = "1", features = ["rt-multi-thread", "time", "macros", "sync"] }
|
||||
tracing = { version = "0.1", features = ["attributes"] }
|
||||
tokio = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
serde_json = "1"
|
||||
serde_json = { workspace = true }
|
||||
|
|
|
@ -6,14 +6,14 @@ edition = "2021"
|
|||
publish = false
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1"
|
||||
futures = "0.3"
|
||||
monero = "0.12"
|
||||
anyhow = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
monero = { workspace = true }
|
||||
monero-rpc = { path = "../monero-rpc" }
|
||||
monero-sys = { path = "../monero-sys" }
|
||||
rand = "0.7"
|
||||
reqwest = "0.12.15"
|
||||
rand = { workspace = true }
|
||||
reqwest = { workspace = true }
|
||||
testcontainers = "0.15"
|
||||
tokio = { version = "1", default-features = false, features = ["rt-multi-thread", "time", "macros"] }
|
||||
tracing = "0.1"
|
||||
tokio = { workspace = true, features = ["rt-multi-thread", "time", "macros"] }
|
||||
tracing = { workspace = true }
|
||||
tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt", "ansi", "env-filter", "tracing-log"] }
|
||||
|
|
|
@ -9,27 +9,27 @@ name = "monero-rpc-pool"
|
|||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1"
|
||||
anyhow = { workspace = true }
|
||||
axum = { version = "0.7", features = ["macros"] }
|
||||
chrono = { version = "0.4", features = ["serde"] }
|
||||
clap = { version = "4.0", features = ["derive"] }
|
||||
futures = "0.3"
|
||||
monero = { version = "0.12", features = ["serde_support"] }
|
||||
futures = { workspace = true }
|
||||
monero = { workspace = true }
|
||||
monero-rpc = { path = "../monero-rpc" }
|
||||
rand = "0.8"
|
||||
rand = { workspace = true }
|
||||
regex = "1.0"
|
||||
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
reqwest = { workspace = true, features = ["rustls-tls"] }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
sqlx = { version = "0.8", features = ["runtime-tokio-rustls", "sqlite", "chrono", "migrate"] }
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
tokio = { workspace = true, features = ["full"] }
|
||||
tower = "0.4"
|
||||
tower-http = { version = "0.5", features = ["cors"] }
|
||||
tracing = "0.1"
|
||||
tracing = { workspace = true }
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
typeshare = "1.0.3"
|
||||
typeshare = { workspace = true }
|
||||
url = "2.0"
|
||||
uuid = { version = "1.0", features = ["v4"] }
|
||||
uuid = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
tokio-test = "0.4"
|
||||
|
|
|
@ -5,19 +5,19 @@ authors = ["CoBloX Team <team@coblox.tech>"]
|
|||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1"
|
||||
anyhow = { workspace = true }
|
||||
curve25519-dalek = "3.1"
|
||||
hex = "0.4"
|
||||
jsonrpc_client = { version = "0.7", features = ["reqwest"] }
|
||||
monero = "0.12"
|
||||
monero = { workspace = true }
|
||||
monero-epee-bin-serde = "1"
|
||||
rand = "0.7"
|
||||
reqwest = { version = "0.12", default-features = false, features = ["json"] }
|
||||
rust_decimal = { version = "1", features = ["serde-float"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
tracing = "0.1"
|
||||
rand = { workspace = true }
|
||||
reqwest = { workspace = true }
|
||||
rust_decimal = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
hex-literal = "0.4"
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
tokio = { workspace = true, features = ["full"] }
|
||||
|
|
|
@ -4,12 +4,17 @@ version = "0.1.0"
|
|||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.98"
|
||||
anyhow = { workspace = true }
|
||||
backoff = { version = "0.4.0", features = ["futures", "tokio"] }
|
||||
cxx = "1.0.137"
|
||||
monero = { version = "0.12", features = ["serde_support"] }
|
||||
tokio = { version = "1.44.2", features = ["sync", "time", "rt"] }
|
||||
tracing = "0.1.41"
|
||||
monero = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
sqlx = { version = "0.8", features = ["sqlite", "runtime-tokio-rustls", "macros", "chrono"] }
|
||||
swap-serde = { path = "../swap-serde" }
|
||||
tokio = { workspace = true, features = ["sync", "time", "rt"] }
|
||||
tracing = { workspace = true }
|
||||
typeshare = { workspace = true }
|
||||
uuid = { workspace = true }
|
||||
|
||||
[build-dependencies]
|
||||
cmake = "0.1.54"
|
||||
|
@ -17,12 +22,12 @@ cxx-build = "1.0.137"
|
|||
diffy = "0.4.2"
|
||||
|
||||
[dev-dependencies]
|
||||
anyhow = "1.0.98"
|
||||
futures = "0.3.31"
|
||||
anyhow = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
quickcheck = "1.0"
|
||||
quickcheck_macros = "1.0"
|
||||
tempfile = "3.19.1"
|
||||
testcontainers = "0.15"
|
||||
tokio = { version = "1.44.2", features = ["full"] }
|
||||
tokio = { workspace = true, features = ["full"] }
|
||||
tracing-subscriber = { version = "0.3.19", features = ["env-filter"] }
|
||||
uuid = { version = "1.16.0", features = ["v4"] }
|
||||
uuid = { workspace = true }
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
[package]
|
||||
name = "monero-wallet"
|
||||
version = "0.1.0"
|
||||
authors = ["CoBloX Team <team@coblox.tech>"]
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1"
|
||||
monero = "0.12"
|
||||
monero-rpc = { path = "../monero-rpc" }
|
||||
rand = "0.7"
|
||||
|
||||
[dev-dependencies]
|
||||
curve25519-dalek = "3"
|
||||
monero-harness = { path = "../monero-harness" }
|
||||
rand = "0.7"
|
||||
testcontainers = "0.15"
|
||||
tokio = { version = "1", features = ["rt-multi-thread", "time", "macros", "sync", "process", "fs"] }
|
||||
tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt", "ansi", "env-filter", "chrono", "tracing-log"] }
|
|
@ -17,12 +17,9 @@ workspace = true
|
|||
|
||||
[dependencies]
|
||||
std-shims = { git = "https://github.com/serai-dex/serai", version = "^0.1.1", default-features = false }
|
||||
|
||||
thiserror = { version = "1", default-features = false, optional = true }
|
||||
|
||||
thiserror = { workspace = true, optional = true }
|
||||
rand_core = { version = "0.6", default-features = false }
|
||||
zeroize = { version = "^1.5", default-features = false, features = ["zeroize_derive"] }
|
||||
|
||||
curve25519-dalek = { version = "4", default-features = false, features = ["alloc", "zeroize"] }
|
||||
|
||||
[dev-dependencies]
|
||||
|
@ -32,9 +29,7 @@ monero-primitives = { git = "https://github.com/serai-dex/serai", default-featur
|
|||
[features]
|
||||
std = [
|
||||
"std-shims/std",
|
||||
|
||||
"thiserror",
|
||||
|
||||
"zeroize/std",
|
||||
"rand_core/std",
|
||||
]
|
||||
|
|
|
@ -15,11 +15,11 @@ crate-type = [ "lib", "staticlib" ]
|
|||
tauri-build = { version = "^2.0.0", features = [ "config-json5" ] }
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1"
|
||||
anyhow = { workspace = true }
|
||||
monero-rpc-pool = { path = "../monero-rpc-pool" }
|
||||
rustls = { version = "0.23.26", default-features = false, features = ["ring"] }
|
||||
serde = { version = "1", features = [ "derive" ] }
|
||||
serde_json = "1"
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
swap = { path = "../swap", features = [ "tauri" ] }
|
||||
sysinfo = "=0.32.1"
|
||||
tauri = { version = "^2.0.0", features = [ "config-json5" ] }
|
||||
|
@ -30,8 +30,8 @@ tauri-plugin-process = "^2.0.0"
|
|||
tauri-plugin-shell = "^2.0.0"
|
||||
tauri-plugin-store = "^2.0.0"
|
||||
tauri-plugin-updater = "^2.0.0"
|
||||
tracing = "0.1"
|
||||
uuid = "1.16.0"
|
||||
tracing = { workspace = true }
|
||||
uuid = { workspace = true }
|
||||
zip = "4.0.0"
|
||||
|
||||
[target."cfg(not(any(target_os = \"android\", target_os = \"ios\")))".dependencies]
|
||||
|
|
24
swap-env/Cargo.toml
Normal file
24
swap-env/Cargo.toml
Normal file
|
@ -0,0 +1,24 @@
|
|||
[package]
|
||||
name = "swap-env"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
serde = { workspace = true }
|
||||
time = "0.3"
|
||||
swap-serde = { path = "../swap-serde" }
|
||||
bitcoin = { workspace = true }
|
||||
monero = { workspace = true }
|
||||
anyhow = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
swap-fs = { path = "../swap-fs" }
|
||||
dialoguer = "0.11"
|
||||
config = { version = "0.14", default-features = false, features = ["toml"] }
|
||||
libp2p = { workspace = true, features = ["serde"] }
|
||||
thiserror = { workspace = true }
|
||||
rust_decimal = { workspace = true }
|
||||
url = { workspace = true }
|
||||
toml = "0.8"
|
||||
|
||||
[lints]
|
||||
workspace = true
|
|
@ -1,5 +1,5 @@
|
|||
use crate::env::{Mainnet, Testnet};
|
||||
use crate::fs::{ensure_directory_exists, system_config_dir, system_data_dir};
|
||||
use swap_fs::{ensure_directory_exists, system_config_dir, system_data_dir};
|
||||
use anyhow::{bail, Context, Result};
|
||||
use config::ConfigError;
|
||||
use dialoguer::theme::ColorfulTheme;
|
||||
|
@ -15,7 +15,7 @@ use std::str::FromStr;
|
|||
use url::Url;
|
||||
|
||||
pub trait GetDefaults {
|
||||
fn getConfigFileDefaults() -> Result<Defaults>;
|
||||
fn get_config_file_defaults() -> Result<Defaults>;
|
||||
}
|
||||
|
||||
pub struct Defaults {
|
||||
|
@ -29,7 +29,7 @@ pub struct Defaults {
|
|||
}
|
||||
|
||||
impl GetDefaults for Testnet {
|
||||
fn getConfigFileDefaults() -> Result<Defaults> {
|
||||
fn get_config_file_defaults() -> Result<Defaults> {
|
||||
let defaults = Defaults {
|
||||
config_path: default_asb_config_dir()?
|
||||
.join("testnet")
|
||||
|
@ -47,7 +47,7 @@ impl GetDefaults for Testnet {
|
|||
}
|
||||
|
||||
impl GetDefaults for Mainnet {
|
||||
fn getConfigFileDefaults() -> Result<Defaults> {
|
||||
fn get_config_file_defaults() -> Result<Defaults> {
|
||||
let defaults = Defaults {
|
||||
config_path: default_asb_config_dir()?
|
||||
.join("mainnet")
|
||||
|
@ -128,104 +128,22 @@ pub struct Data {
|
|||
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Network {
|
||||
#[serde(deserialize_with = "addr_list::deserialize")]
|
||||
#[serde(deserialize_with = "swap_serde::libp2p::multiaddresses::deserialize")]
|
||||
pub listen: Vec<Multiaddr>,
|
||||
#[serde(default, deserialize_with = "addr_list::deserialize")]
|
||||
#[serde(default, deserialize_with = "swap_serde::libp2p::multiaddresses::deserialize")]
|
||||
pub rendezvous_point: Vec<Multiaddr>,
|
||||
#[serde(default, deserialize_with = "addr_list::deserialize")]
|
||||
#[serde(default, deserialize_with = "swap_serde::libp2p::multiaddresses::deserialize")]
|
||||
pub external_addresses: Vec<Multiaddr>,
|
||||
}
|
||||
|
||||
mod addr_list {
|
||||
use libp2p::Multiaddr;
|
||||
use serde::de::Unexpected;
|
||||
use serde::{de, Deserialize, Deserializer};
|
||||
use serde_json::Value;
|
||||
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<Multiaddr>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let s = Value::deserialize(deserializer)?;
|
||||
match s {
|
||||
Value::String(s) => {
|
||||
let list: Result<Vec<_>, _> = s
|
||||
.split(',')
|
||||
.filter(|s| !s.is_empty())
|
||||
.map(|s| s.trim().parse().map_err(de::Error::custom))
|
||||
.collect();
|
||||
Ok(list?)
|
||||
}
|
||||
Value::Array(a) => {
|
||||
let list: Result<Vec<_>, _> = a
|
||||
.iter()
|
||||
.map(|v| {
|
||||
if let Value::String(s) = v {
|
||||
s.trim().parse().map_err(de::Error::custom)
|
||||
} else {
|
||||
Err(de::Error::custom("expected a string"))
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
Ok(list?)
|
||||
}
|
||||
value => Err(de::Error::invalid_type(
|
||||
Unexpected::Other(&value.to_string()),
|
||||
&"a string or array",
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod electrum_urls {
|
||||
use serde::de::Unexpected;
|
||||
use serde::{de, Deserialize, Deserializer};
|
||||
use serde_json::Value;
|
||||
use url::Url;
|
||||
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<Url>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let s = Value::deserialize(deserializer)?;
|
||||
match s {
|
||||
Value::String(s) => {
|
||||
let list: Result<Vec<_>, _> = s
|
||||
.split(',')
|
||||
.filter(|s| !s.is_empty())
|
||||
.map(|s| s.trim().parse().map_err(de::Error::custom))
|
||||
.collect();
|
||||
Ok(list?)
|
||||
}
|
||||
Value::Array(a) => {
|
||||
let list: Result<Vec<_>, _> = a
|
||||
.iter()
|
||||
.map(|v| {
|
||||
if let Value::String(s) = v {
|
||||
s.trim().parse().map_err(de::Error::custom)
|
||||
} else {
|
||||
Err(de::Error::custom("expected a string"))
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
Ok(list?)
|
||||
}
|
||||
value => Err(de::Error::invalid_type(
|
||||
Unexpected::Other(&value.to_string()),
|
||||
&"a string or array",
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Bitcoin {
|
||||
#[serde(deserialize_with = "electrum_urls::deserialize")]
|
||||
#[serde(deserialize_with = "swap_serde::electrum::urls::deserialize")]
|
||||
pub electrum_rpc_urls: Vec<Url>,
|
||||
pub target_block: u16,
|
||||
pub finality_confirmations: Option<u32>,
|
||||
#[serde(with = "crate::bitcoin::network")]
|
||||
#[serde(with = "swap_serde::bitcoin::network")]
|
||||
pub network: bitcoin::Network,
|
||||
#[serde(default = "default_use_mempool_space_fee_estimation")]
|
||||
pub use_mempool_space_fee_estimation: bool,
|
||||
|
@ -240,7 +158,7 @@ fn default_use_mempool_space_fee_estimation() -> bool {
|
|||
pub struct Monero {
|
||||
pub daemon_url: Url,
|
||||
pub finality_confirmations: Option<u64>,
|
||||
#[serde(with = "crate::monero::network")]
|
||||
#[serde(with = "swap_serde::monero::network")]
|
||||
pub network: monero::Network,
|
||||
#[serde(default = "default_monero_node_pool")]
|
||||
pub monero_node_pool: bool,
|
||||
|
@ -266,7 +184,7 @@ pub struct Maker {
|
|||
pub max_buy_btc: bitcoin::Amount,
|
||||
pub ask_spread: Decimal,
|
||||
pub price_ticker_ws_url: Url,
|
||||
#[serde(default, with = "crate::bitcoin::address_serde::option")]
|
||||
#[serde(default, with = "swap_serde::bitcoin::address_serde::option")]
|
||||
pub external_bitcoin_redeem_address: Option<bitcoin::Address>,
|
||||
}
|
||||
|
||||
|
@ -318,14 +236,14 @@ pub fn query_user_for_initial_config(testnet: bool) -> Result<Config> {
|
|||
|
||||
let bitcoin_network = bitcoin::Network::Testnet;
|
||||
let monero_network = monero::Network::Stagenet;
|
||||
let defaults = Testnet::getConfigFileDefaults()?;
|
||||
let defaults = Testnet::get_config_file_defaults()?;
|
||||
|
||||
(bitcoin_network, monero_network, defaults)
|
||||
} else {
|
||||
tracing::info!("Running initial setup for mainnet");
|
||||
let bitcoin_network = bitcoin::Network::Bitcoin;
|
||||
let monero_network = monero::Network::Mainnet;
|
||||
let defaults = Mainnet::getConfigFileDefaults()?;
|
||||
let defaults = Mainnet::get_config_file_defaults()?;
|
||||
|
||||
(bitcoin_network, monero_network, defaults)
|
||||
};
|
||||
|
@ -382,7 +300,8 @@ pub fn query_user_for_initial_config(testnet: bool) -> Result<Config> {
|
|||
.with_prompt(prompt)
|
||||
.allow_empty(true)
|
||||
.interact_text()?;
|
||||
if electrum_url.as_str().is_empty() {
|
||||
|
||||
if electrum_url.is_empty() {
|
||||
electrum_done = true;
|
||||
} else if electrum_rpc_urls
|
||||
.iter()
|
||||
|
@ -500,7 +419,7 @@ mod tests {
|
|||
let temp_dir = tempdir().unwrap().path().to_path_buf();
|
||||
let config_path = Path::join(&temp_dir, "config.toml");
|
||||
|
||||
let defaults = Testnet::getConfigFileDefaults().unwrap();
|
||||
let defaults = Testnet::get_config_file_defaults().unwrap();
|
||||
|
||||
let expected = Config {
|
||||
data: Data {
|
||||
|
@ -546,7 +465,7 @@ mod tests {
|
|||
let temp_dir = tempdir().unwrap().path().to_path_buf();
|
||||
let config_path = Path::join(&temp_dir, "config.toml");
|
||||
|
||||
let defaults = Mainnet::getConfigFileDefaults().unwrap();
|
||||
let defaults = Mainnet::get_config_file_defaults().unwrap();
|
||||
|
||||
let expected = Config {
|
||||
data: Data {
|
||||
|
@ -592,7 +511,7 @@ mod tests {
|
|||
let temp_dir = tempfile::tempdir().unwrap().path().to_path_buf();
|
||||
let config_path = Path::join(&temp_dir, "config.toml");
|
||||
|
||||
let defaults = Mainnet::getConfigFileDefaults().unwrap();
|
||||
let defaults = Mainnet::get_config_file_defaults().unwrap();
|
||||
|
||||
let dir = PathBuf::from("/tmp/dir");
|
||||
std::env::set_var("ASB__DATA__DIR", dir.clone());
|
|
@ -1,9 +1,8 @@
|
|||
use crate::asb;
|
||||
use crate::bitcoin::{CancelTimelock, PunishTimelock};
|
||||
use serde::Serialize;
|
||||
use std::cmp::max;
|
||||
use std::time::Duration;
|
||||
use time::ext::NumericalStdDuration;
|
||||
use crate::config::Config as AsbConfig;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize)]
|
||||
pub struct Config {
|
||||
|
@ -11,8 +10,8 @@ pub struct Config {
|
|||
pub bitcoin_lock_confirmed_timeout: Duration,
|
||||
pub bitcoin_finality_confirmations: u32,
|
||||
pub bitcoin_avg_block_time: Duration,
|
||||
pub bitcoin_cancel_timelock: CancelTimelock,
|
||||
pub bitcoin_punish_timelock: PunishTimelock,
|
||||
pub bitcoin_cancel_timelock: u32,
|
||||
pub bitcoin_punish_timelock: u32,
|
||||
pub bitcoin_network: bitcoin::Network,
|
||||
pub monero_avg_block_time: Duration,
|
||||
pub monero_finality_confirmations: u64,
|
||||
|
@ -20,7 +19,7 @@ pub struct Config {
|
|||
pub monero_lock_retry_timeout: Duration,
|
||||
// After this many confirmations we assume that the Monero transaction is safe from double spending
|
||||
pub monero_double_spend_safe_confirmations: u64,
|
||||
#[serde(with = "monero_network")]
|
||||
#[serde(with = "swap_serde::monero::network")]
|
||||
pub monero_network: monero::Network,
|
||||
}
|
||||
|
||||
|
@ -54,8 +53,8 @@ impl GetConfig for Mainnet {
|
|||
bitcoin_lock_confirmed_timeout: 2.std_hours(),
|
||||
bitcoin_finality_confirmations: 1,
|
||||
bitcoin_avg_block_time: 10.std_minutes(),
|
||||
bitcoin_cancel_timelock: CancelTimelock::new(72),
|
||||
bitcoin_punish_timelock: PunishTimelock::new(144),
|
||||
bitcoin_cancel_timelock: 72,
|
||||
bitcoin_punish_timelock: 144,
|
||||
bitcoin_network: bitcoin::Network::Bitcoin,
|
||||
monero_avg_block_time: 2.std_minutes(),
|
||||
// If Alice cannot lock her Monero within this timeout,
|
||||
|
@ -75,8 +74,8 @@ impl GetConfig for Testnet {
|
|||
bitcoin_lock_confirmed_timeout: 1.std_hours(),
|
||||
bitcoin_finality_confirmations: 1,
|
||||
bitcoin_avg_block_time: 10.std_minutes(),
|
||||
bitcoin_cancel_timelock: CancelTimelock::new(12),
|
||||
bitcoin_punish_timelock: PunishTimelock::new(24),
|
||||
bitcoin_cancel_timelock: 12,
|
||||
bitcoin_punish_timelock: 24,
|
||||
bitcoin_network: bitcoin::Network::Testnet,
|
||||
monero_avg_block_time: 2.std_minutes(),
|
||||
monero_lock_retry_timeout: 10.std_minutes(),
|
||||
|
@ -94,8 +93,8 @@ impl GetConfig for Regtest {
|
|||
bitcoin_lock_confirmed_timeout: 5.std_minutes(),
|
||||
bitcoin_finality_confirmations: 1,
|
||||
bitcoin_avg_block_time: 5.std_seconds(),
|
||||
bitcoin_cancel_timelock: CancelTimelock::new(100),
|
||||
bitcoin_punish_timelock: PunishTimelock::new(50),
|
||||
bitcoin_cancel_timelock: 100,
|
||||
bitcoin_punish_timelock: 50,
|
||||
bitcoin_network: bitcoin::Network::Regtest,
|
||||
monero_avg_block_time: 1.std_seconds(),
|
||||
monero_lock_retry_timeout: 1.std_minutes(),
|
||||
|
@ -110,7 +109,7 @@ fn sync_interval(avg_block_time: Duration) -> Duration {
|
|||
max(avg_block_time / 10, Duration::from_secs(1))
|
||||
}
|
||||
|
||||
pub fn new(is_testnet: bool, asb_config: &asb::config::Config) -> Config {
|
||||
pub fn new(is_testnet: bool, asb_config: &AsbConfig) -> Config {
|
||||
let env_config = if is_testnet {
|
||||
Testnet::get_config()
|
||||
} else {
|
||||
|
@ -137,22 +136,7 @@ pub fn new(is_testnet: bool, asb_config: &asb::config::Config) -> Config {
|
|||
}
|
||||
}
|
||||
|
||||
mod monero_network {
|
||||
use crate::monero::Network;
|
||||
use serde::Serializer;
|
||||
|
||||
pub fn serialize<S>(x: &monero::Network, s: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let str = match x {
|
||||
Network::Mainnet => "mainnet",
|
||||
Network::Stagenet => "stagenet",
|
||||
Network::Testnet => "testnet",
|
||||
};
|
||||
s.serialize_str(str)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
2
swap-env/src/lib.rs
Normal file
2
swap-env/src/lib.rs
Normal file
|
@ -0,0 +1,2 @@
|
|||
pub mod env;
|
||||
pub mod config;
|
12
swap-fs/Cargo.toml
Normal file
12
swap-fs/Cargo.toml
Normal file
|
@ -0,0 +1,12 @@
|
|||
[package]
|
||||
name = "swap-fs"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
anyhow = { workspace = true }
|
||||
directories-next = "2"
|
||||
tracing = { workspace = true }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
18
swap-serde/Cargo.toml
Normal file
18
swap-serde/Cargo.toml
Normal file
|
@ -0,0 +1,18 @@
|
|||
[package]
|
||||
name = "swap-serde"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
serde = { workspace = true }
|
||||
monero = { workspace = true }
|
||||
bitcoin = { workspace = true }
|
||||
libp2p = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
url = { workspace = true }
|
||||
hex = { workspace = true }
|
||||
anyhow = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
76
swap-serde/src/bitcoin.rs
Normal file
76
swap-serde/src/bitcoin.rs
Normal file
|
@ -0,0 +1,76 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use bitcoin::{Network};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(remote = "Network")]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[non_exhaustive]
|
||||
pub enum network {
|
||||
#[serde(rename = "Mainnet")]
|
||||
Bitcoin,
|
||||
Testnet,
|
||||
Signet,
|
||||
Regtest,
|
||||
}
|
||||
|
||||
/// This module is used to serialize and deserialize bitcoin addresses
|
||||
/// even though the bitcoin crate does not support it for Address<NetworkChecked>.
|
||||
pub mod address_serde {
|
||||
use std::str::FromStr;
|
||||
|
||||
use bitcoin::address::{Address, NetworkChecked, NetworkUnchecked};
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
pub fn serialize<S>(address: &Address<NetworkChecked>, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
address.to_string().serialize(serializer)
|
||||
}
|
||||
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<Address<NetworkChecked>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let unchecked: Address<NetworkUnchecked> =
|
||||
Address::from_str(&String::deserialize(deserializer)?)
|
||||
.map_err(serde::de::Error::custom)?;
|
||||
|
||||
Ok(unchecked.assume_checked())
|
||||
}
|
||||
|
||||
/// This submodule supports Option<Address>.
|
||||
pub mod option {
|
||||
use super::*;
|
||||
|
||||
pub fn serialize<S>(
|
||||
address: &Option<Address<NetworkChecked>>,
|
||||
serializer: S,
|
||||
) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
match address {
|
||||
Some(addr) => addr.to_string().serialize(serializer),
|
||||
None => serializer.serialize_none(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn deserialize<'de, D>(
|
||||
deserializer: D,
|
||||
) -> Result<Option<Address<NetworkChecked>>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let opt: Option<String> = Option::deserialize(deserializer)?;
|
||||
match opt {
|
||||
Some(s) => {
|
||||
let unchecked: Address<NetworkUnchecked> =
|
||||
Address::from_str(&s).map_err(serde::de::Error::custom)?;
|
||||
Ok(Some(unchecked.assume_checked()))
|
||||
}
|
||||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
40
swap-serde/src/electrum.rs
Normal file
40
swap-serde/src/electrum.rs
Normal file
|
@ -0,0 +1,40 @@
|
|||
pub mod urls {
|
||||
use serde::de::Unexpected;
|
||||
use serde::{de, Deserialize, Deserializer};
|
||||
use serde_json::Value;
|
||||
use url::Url;
|
||||
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<Url>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let s = Value::deserialize(deserializer)?;
|
||||
match s {
|
||||
Value::String(s) => {
|
||||
let list: Result<Vec<_>, _> = s
|
||||
.split(',')
|
||||
.filter(|s| !s.is_empty())
|
||||
.map(|s| s.trim().parse().map_err(de::Error::custom))
|
||||
.collect();
|
||||
Ok(list?)
|
||||
}
|
||||
Value::Array(a) => {
|
||||
let list: Result<Vec<_>, _> = a
|
||||
.iter()
|
||||
.map(|v| {
|
||||
if let Value::String(s) = v {
|
||||
s.trim().parse().map_err(de::Error::custom)
|
||||
} else {
|
||||
Err(de::Error::custom("expected a string"))
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
Ok(list?)
|
||||
}
|
||||
value => Err(de::Error::invalid_type(
|
||||
Unexpected::Other(&value.to_string()),
|
||||
&"a string or array",
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
4
swap-serde/src/lib.rs
Normal file
4
swap-serde/src/lib.rs
Normal file
|
@ -0,0 +1,4 @@
|
|||
pub mod monero;
|
||||
pub mod bitcoin;
|
||||
pub mod libp2p;
|
||||
pub mod electrum;
|
40
swap-serde/src/libp2p.rs
Normal file
40
swap-serde/src/libp2p.rs
Normal file
|
@ -0,0 +1,40 @@
|
|||
pub mod multiaddresses {
|
||||
use libp2p::Multiaddr;
|
||||
use serde::de::Unexpected;
|
||||
use serde::{de, Deserialize, Deserializer};
|
||||
use serde_json::Value;
|
||||
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<Multiaddr>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let s = Value::deserialize(deserializer)?;
|
||||
match s {
|
||||
Value::String(s) => {
|
||||
let list: Result<Vec<_>, _> = s
|
||||
.split(',')
|
||||
.filter(|s| !s.is_empty())
|
||||
.map(|s| s.trim().parse().map_err(de::Error::custom))
|
||||
.collect();
|
||||
Ok(list?)
|
||||
}
|
||||
Value::Array(a) => {
|
||||
let list: Result<Vec<_>, _> = a
|
||||
.iter()
|
||||
.map(|v| {
|
||||
if let Value::String(s) = v {
|
||||
s.trim().parse().map_err(de::Error::custom)
|
||||
} else {
|
||||
Err(de::Error::custom("expected a string"))
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
Ok(list?)
|
||||
}
|
||||
value => Err(de::Error::invalid_type(
|
||||
Unexpected::Other(&value.to_string()),
|
||||
&"a string or array",
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
146
swap-serde/src/monero.rs
Normal file
146
swap-serde/src/monero.rs
Normal file
|
@ -0,0 +1,146 @@
|
|||
use monero::{Network, Amount};
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(remote = "Network")]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub enum network {
|
||||
Mainnet,
|
||||
Stagenet,
|
||||
Testnet,
|
||||
}
|
||||
|
||||
pub mod private_key {
|
||||
use monero::consensus::{Decodable, Encodable};
|
||||
use monero::PrivateKey;
|
||||
use serde::de::Visitor;
|
||||
use serde::ser::Error;
|
||||
use serde::{de, Deserializer, Serializer};
|
||||
use std::fmt;
|
||||
use std::io::Cursor;
|
||||
use hex;
|
||||
|
||||
struct BytesVisitor;
|
||||
|
||||
impl Visitor<'_> for BytesVisitor {
|
||||
type Value = PrivateKey;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(formatter, "a byte array representing a Monero private key")
|
||||
}
|
||||
|
||||
fn visit_bytes<E>(self, s: &[u8]) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
let mut s = s;
|
||||
PrivateKey::consensus_decode(&mut s).map_err(|err| E::custom(format!("{:?}", err)))
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
let bytes = hex::decode(s).map_err(|err| E::custom(format!("{:?}", err)))?;
|
||||
PrivateKey::consensus_decode(&mut bytes.as_slice())
|
||||
.map_err(|err| E::custom(format!("{:?}", err)))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn serialize<S>(x: &PrivateKey, s: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let mut bytes = Cursor::new(vec![]);
|
||||
x.consensus_encode(&mut bytes)
|
||||
.map_err(|err| S::Error::custom(format!("{:?}", err)))?;
|
||||
if s.is_human_readable() {
|
||||
s.serialize_str(&hex::encode(bytes.into_inner()))
|
||||
} else {
|
||||
s.serialize_bytes(bytes.into_inner().as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn deserialize<'de, D>(
|
||||
deserializer: D,
|
||||
) -> Result<PrivateKey, <D as Deserializer<'de>>::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let key = {
|
||||
if deserializer.is_human_readable() {
|
||||
deserializer.deserialize_string(BytesVisitor)?
|
||||
} else {
|
||||
deserializer.deserialize_bytes(BytesVisitor)?
|
||||
}
|
||||
};
|
||||
Ok(key)
|
||||
}
|
||||
}
|
||||
|
||||
pub mod amount {
|
||||
use super::*;
|
||||
|
||||
pub fn serialize<S>(x: &Amount, s: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
s.serialize_u64(x.as_pico())
|
||||
}
|
||||
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<Amount, <D as Deserializer<'de>>::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let picos = u64::deserialize(deserializer)?;
|
||||
let amount = Amount::from_pico(picos);
|
||||
|
||||
Ok(amount)
|
||||
}
|
||||
}
|
||||
|
||||
pub mod address {
|
||||
use anyhow::{bail, Context, Result};
|
||||
use std::str::FromStr;
|
||||
|
||||
#[derive(thiserror::Error, Debug, Clone, Copy, PartialEq)]
|
||||
#[error("Invalid monero address provided, expected address on network {expected:?} but address provided is on {actual:?}")]
|
||||
pub struct MoneroAddressNetworkMismatch {
|
||||
pub expected: monero::Network,
|
||||
pub actual: monero::Network,
|
||||
}
|
||||
|
||||
pub fn parse(s: &str) -> Result<monero::Address> {
|
||||
monero::Address::from_str(s).with_context(|| {
|
||||
format!(
|
||||
"Failed to parse {} as a monero address, please make sure it is a valid address",
|
||||
s
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn validate(
|
||||
address: monero::Address,
|
||||
expected_network: monero::Network,
|
||||
) -> Result<monero::Address> {
|
||||
if address.network != expected_network {
|
||||
bail!(MoneroAddressNetworkMismatch {
|
||||
expected: expected_network,
|
||||
actual: address.network,
|
||||
});
|
||||
}
|
||||
Ok(address)
|
||||
}
|
||||
|
||||
pub fn validate_is_testnet(
|
||||
address: monero::Address,
|
||||
is_testnet: bool,
|
||||
) -> Result<monero::Address> {
|
||||
let expected_network = if is_testnet {
|
||||
monero::Network::Stagenet
|
||||
} else {
|
||||
monero::Network::Mainnet
|
||||
};
|
||||
validate(address, expected_network)
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@ name = "swap"
|
|||
tauri = ["dep:tauri"]
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1"
|
||||
anyhow = { workspace = true }
|
||||
arti-client = { version = "0.25.0", features = ["static-sqlite", "tokio", "rustls", "onion-service-service"], default-features = false }
|
||||
async-compression = { version = "0.3", features = ["bzip2", "tokio"] }
|
||||
async-trait = "0.1"
|
||||
|
@ -25,7 +25,7 @@ bdk_chain = { version = "0.20" }
|
|||
bdk_electrum = { version = "0.19", default-features = false, features = ["use-rustls-ring"] }
|
||||
bdk_wallet = { version = "1.0.0-beta.5", features = ["rusqlite", "test-utils"] }
|
||||
big-bytes = "1"
|
||||
bitcoin = { version = "0.32", features = ["rand", "serde"] }
|
||||
bitcoin = { workspace = true }
|
||||
bmrng = "0.5.2"
|
||||
comfy-table = "7.1"
|
||||
config = { version = "0.14", default-features = false, features = ["toml"] }
|
||||
|
@ -34,16 +34,16 @@ curve25519-dalek = { package = "curve25519-dalek-ng", version = "4" }
|
|||
data-encoding = "2.6"
|
||||
derive_builder = "0.20.2"
|
||||
dialoguer = "0.11"
|
||||
directories-next = "2"
|
||||
ecdsa_fun = { version = "0.10", default-features = false, features = ["libsecp_compat", "serde", "adaptor"] }
|
||||
ed25519-dalek = "1"
|
||||
electrum-pool = { path = "../electrum-pool" }
|
||||
futures = { version = "0.3", default-features = false, features = ["std"] }
|
||||
hex = "0.4"
|
||||
libp2p = { version = "0.53.2", features = ["tcp", "yamux", "dns", "noise", "request-response", "ping", "rendezvous", "identify", "macros", "cbor", "json", "tokio", "serde", "rsa"] }
|
||||
fns = "0.0.7"
|
||||
futures = { workspace = true }
|
||||
hex = { workspace = true }
|
||||
libp2p = { workspace = true, features = ["tcp", "yamux", "dns", "noise", "request-response", "ping", "rendezvous", "identify", "macros", "cbor", "json", "tokio", "serde", "rsa"] }
|
||||
libp2p-community-tor = { git = "https://github.com/umgefahren/libp2p-tor", rev = "e6b913e0f1ac1fc90b3ee4dd31b5511140c4a9af", features = ["listen-onion-service"] }
|
||||
moka = { version = "0.12", features = ["sync", "future"] }
|
||||
monero = { version = "0.12", features = ["serde_support"] }
|
||||
monero = { workspace = true }
|
||||
monero-rpc = { path = "../monero-rpc" }
|
||||
monero-rpc-pool = { path = "../monero-rpc-pool" }
|
||||
monero-seed = { version = "0.1.0", path = "../seed" }
|
||||
|
@ -51,42 +51,44 @@ monero-sys = { path = "../monero-sys" }
|
|||
once_cell = "1.19"
|
||||
pem = "3.0"
|
||||
proptest = "1"
|
||||
rand = "0.8"
|
||||
rand = { workspace = true }
|
||||
rand_chacha = "0.3"
|
||||
regex = "1.10"
|
||||
reqwest = { version = "0.12", features = ["http2", "rustls-tls-native-roots", "stream", "socks"], default-features = false }
|
||||
reqwest = { workspace = true, features = ["http2", "rustls-tls-native-roots", "stream", "socks"] }
|
||||
rust_decimal = { version = "1", features = ["serde-float"] }
|
||||
rust_decimal_macros = "1"
|
||||
rustls = { version = "0.23", default-features = false, features = ["ring"] }
|
||||
semver = "1.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde = { workspace = true }
|
||||
serde_cbor = "0.11"
|
||||
serde_json = "1"
|
||||
serde_json = { workspace = true }
|
||||
serde_with = { version = "1", features = ["macros"] }
|
||||
sha2 = "0.10"
|
||||
swap-serde = { path = "../swap-serde" }
|
||||
swap-env = { path = "../swap-env" }
|
||||
sigma_fun = { version = "0.7", default-features = false, features = ["ed25519", "serde", "secp256k1", "alloc"] }
|
||||
sqlx = { version = "0.8", features = ["sqlite", "runtime-tokio-rustls"] }
|
||||
structopt = "0.3"
|
||||
strum = { version = "0.26", features = ["derive"] }
|
||||
tauri = { version = "2.0", features = ["config-json5"], optional = true, default-features = false }
|
||||
thiserror = "1"
|
||||
thiserror = { workspace = true }
|
||||
time = "0.3"
|
||||
tokio = { version = "1", features = ["rt-multi-thread", "time", "macros", "sync", "process", "fs", "net", "parking_lot", "rt"] }
|
||||
tokio = { workspace = true, features = ["process", "fs", "net", "parking_lot", "rt"] }
|
||||
tokio-tungstenite = { version = "0.15", features = ["rustls-tls"] }
|
||||
tokio-util = { version = "0.7", features = ["io", "codec", "rt"] }
|
||||
toml = "0.8"
|
||||
tor-rtcompat = { version = "0.25.0", features = ["tokio"] }
|
||||
tower = { version = "0.4.13", features = ["full"] }
|
||||
tower-http = { version = "0.3.4", features = ["full"] }
|
||||
tracing = { version = "0.1", features = ["attributes"] }
|
||||
tracing = { workspace = true }
|
||||
tracing-appender = "0.2"
|
||||
tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt", "ansi", "env-filter", "time", "tracing-log", "json"] }
|
||||
typeshare = "1.0.3"
|
||||
typeshare = { workspace = true }
|
||||
unsigned-varint = { version = "0.8.0", features = ["codec", "asynchronous_codec"] }
|
||||
url = { version = "2", features = ["serde"] }
|
||||
uuid = { version = "1.9", features = ["serde", "v4"] }
|
||||
url = { workspace = true }
|
||||
uuid = { workspace = true, features = ["serde"] }
|
||||
void = "1"
|
||||
zeroize = "1.8.1"
|
||||
swap-fs = { path = "../swap-fs" }
|
||||
|
||||
[target.'cfg(not(windows))'.dependencies]
|
||||
tokio-tar = "0.3"
|
||||
|
@ -106,5 +108,5 @@ tempfile = "3"
|
|||
testcontainers = "0.15"
|
||||
|
||||
[build-dependencies]
|
||||
anyhow = "1"
|
||||
anyhow = { workspace = true }
|
||||
vergen = { version = "8.3", default-features = false, features = ["build", "git", "git2"] }
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
pub mod command;
|
||||
pub mod config;
|
||||
mod event_loop;
|
||||
mod network;
|
||||
mod rate;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::asb::config::GetDefaults;
|
||||
use swap_env::config::GetDefaults;
|
||||
use crate::bitcoin::{bitcoin_address, Amount};
|
||||
use crate::env;
|
||||
use crate::env::GetConfig;
|
||||
use swap_env::env;
|
||||
use swap_env::env::GetConfig;
|
||||
use anyhow::Result;
|
||||
use bitcoin::address::NetworkUnchecked;
|
||||
use bitcoin::Address;
|
||||
|
@ -163,9 +163,9 @@ fn config_path(config: Option<PathBuf>, is_testnet: bool) -> Result<PathBuf> {
|
|||
let config_path = if let Some(config_path) = config {
|
||||
config_path
|
||||
} else if is_testnet {
|
||||
env::Testnet::getConfigFileDefaults()?.config_path
|
||||
env::Testnet::get_config_file_defaults()?.config_path
|
||||
} else {
|
||||
env::Mainnet::getConfigFileDefaults()?.config_path
|
||||
env::Mainnet::get_config_file_defaults()?.config_path
|
||||
};
|
||||
|
||||
Ok(config_path)
|
||||
|
@ -182,9 +182,9 @@ fn env_config(is_testnet: bool) -> env::Config {
|
|||
#[derive(thiserror::Error, Debug, Clone, Copy, PartialEq, Eq, Serialize)]
|
||||
#[error("Invalid Bitcoin address provided, expected address on network {expected:?} but address provided is on {actual:?}")]
|
||||
pub struct BitcoinAddressNetworkMismatch {
|
||||
#[serde(with = "crate::bitcoin::network")]
|
||||
#[serde(with = "swap_serde::bitcoin::network")]
|
||||
expected: bitcoin::Network,
|
||||
#[serde(with = "crate::bitcoin::network")]
|
||||
#[serde(with = "swap_serde::bitcoin::network")]
|
||||
actual: bitcoin::Network,
|
||||
}
|
||||
|
||||
|
@ -402,7 +402,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn ensure_start_command_mapping_mainnet() {
|
||||
let default_mainnet_conf_path = env::Mainnet::getConfigFileDefaults().unwrap().config_path;
|
||||
let default_mainnet_conf_path = env::Mainnet::get_config_file_defaults().unwrap().config_path;
|
||||
let mainnet_env_config = env::Mainnet::get_config();
|
||||
|
||||
let raw_ars = vec![BINARY_NAME, "start"];
|
||||
|
@ -420,7 +420,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn ensure_history_command_mapping_mainnet() {
|
||||
let default_mainnet_conf_path = env::Mainnet::getConfigFileDefaults().unwrap().config_path;
|
||||
let default_mainnet_conf_path = env::Mainnet::get_config_file_defaults().unwrap().config_path;
|
||||
let mainnet_env_config = env::Mainnet::get_config();
|
||||
|
||||
let raw_ars = vec![BINARY_NAME, "history"];
|
||||
|
@ -440,7 +440,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn ensure_balance_command_mapping_mainnet() {
|
||||
let default_mainnet_conf_path = env::Mainnet::getConfigFileDefaults().unwrap().config_path;
|
||||
let default_mainnet_conf_path = env::Mainnet::get_config_file_defaults().unwrap().config_path;
|
||||
let mainnet_env_config = env::Mainnet::get_config();
|
||||
|
||||
let raw_ars = vec![BINARY_NAME, "balance"];
|
||||
|
@ -458,7 +458,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn ensure_withdraw_command_mapping_mainnet() {
|
||||
let default_mainnet_conf_path = env::Mainnet::getConfigFileDefaults().unwrap().config_path;
|
||||
let default_mainnet_conf_path = env::Mainnet::get_config_file_defaults().unwrap().config_path;
|
||||
let mainnet_env_config = env::Mainnet::get_config();
|
||||
let raw_ars = vec![
|
||||
BINARY_NAME,
|
||||
|
@ -484,7 +484,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn ensure_cancel_command_mapping_mainnet() {
|
||||
let default_mainnet_conf_path = env::Mainnet::getConfigFileDefaults().unwrap().config_path;
|
||||
let default_mainnet_conf_path = env::Mainnet::get_config_file_defaults().unwrap().config_path;
|
||||
let mainnet_env_config = env::Mainnet::get_config();
|
||||
|
||||
let raw_ars = vec![
|
||||
|
@ -510,7 +510,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn ensure_refund_command_mappin_mainnet() {
|
||||
let default_mainnet_conf_path = env::Mainnet::getConfigFileDefaults().unwrap().config_path;
|
||||
let default_mainnet_conf_path = env::Mainnet::get_config_file_defaults().unwrap().config_path;
|
||||
let mainnet_env_config = env::Mainnet::get_config();
|
||||
|
||||
let raw_ars = vec![
|
||||
|
@ -536,7 +536,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn ensure_punish_command_mapping_mainnet() {
|
||||
let default_mainnet_conf_path = env::Mainnet::getConfigFileDefaults().unwrap().config_path;
|
||||
let default_mainnet_conf_path = env::Mainnet::get_config_file_defaults().unwrap().config_path;
|
||||
let mainnet_env_config = env::Mainnet::get_config();
|
||||
|
||||
let raw_ars = vec![
|
||||
|
@ -562,7 +562,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn ensure_safely_abort_command_mapping_mainnet() {
|
||||
let default_mainnet_conf_path = env::Mainnet::getConfigFileDefaults().unwrap().config_path;
|
||||
let default_mainnet_conf_path = env::Mainnet::get_config_file_defaults().unwrap().config_path;
|
||||
let mainnet_env_config = env::Mainnet::get_config();
|
||||
|
||||
let raw_ars = vec![
|
||||
|
@ -588,7 +588,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn ensure_start_command_mapping_for_testnet() {
|
||||
let default_testnet_conf_path = env::Testnet::getConfigFileDefaults().unwrap().config_path;
|
||||
let default_testnet_conf_path = env::Testnet::get_config_file_defaults().unwrap().config_path;
|
||||
let testnet_env_config = env::Testnet::get_config();
|
||||
|
||||
let raw_ars = vec![BINARY_NAME, "--testnet", "start"];
|
||||
|
@ -606,7 +606,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn ensure_history_command_mapping_testnet() {
|
||||
let default_testnet_conf_path = env::Testnet::getConfigFileDefaults().unwrap().config_path;
|
||||
let default_testnet_conf_path = env::Testnet::get_config_file_defaults().unwrap().config_path;
|
||||
let testnet_env_config = env::Testnet::get_config();
|
||||
|
||||
let raw_ars = vec![BINARY_NAME, "--testnet", "history"];
|
||||
|
@ -626,7 +626,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn ensure_balance_command_mapping_testnet() {
|
||||
let default_testnet_conf_path = env::Testnet::getConfigFileDefaults().unwrap().config_path;
|
||||
let default_testnet_conf_path = env::Testnet::get_config_file_defaults().unwrap().config_path;
|
||||
let testnet_env_config = env::Testnet::get_config();
|
||||
|
||||
let raw_ars = vec![BINARY_NAME, "--testnet", "balance"];
|
||||
|
@ -644,7 +644,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn ensure_export_monero_command_mapping_testnet() {
|
||||
let default_testnet_conf_path = env::Testnet::getConfigFileDefaults().unwrap().config_path;
|
||||
let default_testnet_conf_path = env::Testnet::get_config_file_defaults().unwrap().config_path;
|
||||
let testnet_env_config = env::Testnet::get_config();
|
||||
|
||||
let raw_ars = vec![BINARY_NAME, "--testnet", "export-monero-wallet"];
|
||||
|
@ -663,7 +663,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn ensure_withdraw_command_mapping_testnet() {
|
||||
let default_testnet_conf_path = env::Testnet::getConfigFileDefaults().unwrap().config_path;
|
||||
let default_testnet_conf_path = env::Testnet::get_config_file_defaults().unwrap().config_path;
|
||||
let testnet_env_config = env::Testnet::get_config();
|
||||
|
||||
let raw_ars = vec![
|
||||
|
@ -690,7 +690,7 @@ mod tests {
|
|||
}
|
||||
#[test]
|
||||
fn ensure_cancel_command_mapping_testnet() {
|
||||
let default_testnet_conf_path = env::Testnet::getConfigFileDefaults().unwrap().config_path;
|
||||
let default_testnet_conf_path = env::Testnet::get_config_file_defaults().unwrap().config_path;
|
||||
let testnet_env_config = env::Testnet::get_config();
|
||||
|
||||
let raw_ars = vec![
|
||||
|
@ -717,7 +717,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn ensure_refund_command_mapping_testnet() {
|
||||
let default_testnet_conf_path = env::Testnet::getConfigFileDefaults().unwrap().config_path;
|
||||
let default_testnet_conf_path = env::Testnet::get_config_file_defaults().unwrap().config_path;
|
||||
let testnet_env_config = env::Testnet::get_config();
|
||||
|
||||
let raw_ars = vec![
|
||||
|
@ -744,7 +744,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn ensure_punish_command_mapping_testnet() {
|
||||
let default_testnet_conf_path = env::Testnet::getConfigFileDefaults().unwrap().config_path;
|
||||
let default_testnet_conf_path = env::Testnet::get_config_file_defaults().unwrap().config_path;
|
||||
let testnet_env_config = env::Testnet::get_config();
|
||||
|
||||
let raw_ars = vec![
|
||||
|
@ -771,7 +771,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn ensure_safely_abort_command_mapping_testnet() {
|
||||
let default_testnet_conf_path = env::Testnet::getConfigFileDefaults().unwrap().config_path;
|
||||
let default_testnet_conf_path = env::Testnet::get_config_file_defaults().unwrap().config_path;
|
||||
let testnet_env_config = env::Testnet::get_config();
|
||||
|
||||
let raw_ars = vec![
|
||||
|
@ -798,7 +798,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn ensure_disable_timestamp_mapping() {
|
||||
let default_mainnet_conf_path = env::Mainnet::getConfigFileDefaults().unwrap().config_path;
|
||||
let default_mainnet_conf_path = env::Mainnet::get_config_file_defaults().unwrap().config_path;
|
||||
let mainnet_env_config = env::Mainnet::get_config();
|
||||
|
||||
let raw_ars = vec![BINARY_NAME, "--disable-timestamp", "start"];
|
||||
|
@ -816,7 +816,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn ensure_trace_mapping() {
|
||||
let default_mainnet_conf_path = env::Mainnet::getConfigFileDefaults().unwrap().config_path;
|
||||
let default_mainnet_conf_path = env::Mainnet::get_config_file_defaults().unwrap().config_path;
|
||||
let mainnet_env_config = env::Mainnet::get_config();
|
||||
|
||||
let raw_ars = vec![BINARY_NAME, "--trace", "start"];
|
||||
|
|
|
@ -7,7 +7,8 @@ use crate::network::transfer_proof;
|
|||
use crate::protocol::alice::swap::has_already_processed_enc_sig;
|
||||
use crate::protocol::alice::{AliceState, ReservesMonero, State3, Swap};
|
||||
use crate::protocol::{Database, State};
|
||||
use crate::{bitcoin, env, kraken, monero};
|
||||
use crate::{bitcoin, kraken, monero};
|
||||
use swap_env::env;
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use futures::future;
|
||||
use futures::future::{BoxFuture, FutureExt};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::asb::event_loop::LatestRate;
|
||||
use crate::env;
|
||||
use swap_env::env;
|
||||
use crate::network::quote::BidQuote;
|
||||
use crate::network::rendezvous::XmrBtcNamespace;
|
||||
use crate::network::swap_setup::alice;
|
||||
|
|
|
@ -24,7 +24,7 @@ use std::sync::Arc;
|
|||
use structopt::clap;
|
||||
use structopt::clap::ErrorKind;
|
||||
use swap::asb::command::{parse_args, Arguments, Command};
|
||||
use swap::asb::config::{
|
||||
use swap_env::config::{
|
||||
initial_setup, query_user_for_initial_config, read_config, Config, ConfigNotInitialized,
|
||||
};
|
||||
use swap::asb::{cancel, punish, redeem, refund, safely_abort, EventLoop, Finality, KrakenRate};
|
||||
|
@ -444,8 +444,7 @@ pub async fn main() -> Result<()> {
|
|||
async fn init_bitcoin_wallet(
|
||||
config: &Config,
|
||||
seed: &Seed,
|
||||
env_config: swap::env::Config,
|
||||
sync: bool,
|
||||
env_config: swap_env::env::Config,
|
||||
) -> Result<bitcoin::Wallet> {
|
||||
tracing::debug!("Opening Bitcoin wallet");
|
||||
let wallet = bitcoin::wallet::WalletBuilder::default()
|
||||
|
@ -481,7 +480,7 @@ async fn init_bitcoin_wallet(
|
|||
|
||||
async fn init_monero_wallet(
|
||||
config: &Config,
|
||||
env_config: swap::env::Config,
|
||||
env_config: swap_env::env::Config,
|
||||
) -> Result<Arc<monero::Wallets>> {
|
||||
tracing::debug!("Initializing Monero wallets");
|
||||
|
||||
|
|
|
@ -42,80 +42,6 @@ use serde::{Deserialize, Serialize};
|
|||
use sha2::Sha256;
|
||||
use std::str::FromStr;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(remote = "Network")]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[non_exhaustive]
|
||||
pub enum network {
|
||||
#[serde(rename = "Mainnet")]
|
||||
Bitcoin,
|
||||
Testnet,
|
||||
Signet,
|
||||
Regtest,
|
||||
}
|
||||
|
||||
/// This module is used to serialize and deserialize bitcoin addresses
|
||||
/// even though the bitcoin crate does not support it for Address<NetworkChecked>.
|
||||
pub mod address_serde {
|
||||
use std::str::FromStr;
|
||||
|
||||
use bitcoin::address::{Address, NetworkChecked, NetworkUnchecked};
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
pub fn serialize<S>(address: &Address<NetworkChecked>, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
address.to_string().serialize(serializer)
|
||||
}
|
||||
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<Address<NetworkChecked>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let unchecked: Address<NetworkUnchecked> =
|
||||
Address::from_str(&String::deserialize(deserializer)?)
|
||||
.map_err(serde::de::Error::custom)?;
|
||||
|
||||
Ok(unchecked.assume_checked())
|
||||
}
|
||||
|
||||
/// This submodule supports Option<Address>.
|
||||
pub mod option {
|
||||
use super::*;
|
||||
|
||||
pub fn serialize<S>(
|
||||
address: &Option<Address<NetworkChecked>>,
|
||||
serializer: S,
|
||||
) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
match address {
|
||||
Some(addr) => addr.to_string().serialize(serializer),
|
||||
None => serializer.serialize_none(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn deserialize<'de, D>(
|
||||
deserializer: D,
|
||||
) -> Result<Option<Address<NetworkChecked>>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let opt: Option<String> = Option::deserialize(deserializer)?;
|
||||
match opt {
|
||||
Some(s) => {
|
||||
let unchecked: Address<NetworkUnchecked> =
|
||||
Address::from_str(&s).map_err(serde::de::Error::custom)?;
|
||||
Ok(Some(unchecked.assume_checked()))
|
||||
}
|
||||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
|
||||
pub struct SecretKey {
|
||||
inner: Scalar,
|
||||
|
@ -336,9 +262,9 @@ pub mod bitcoin_address {
|
|||
#[derive(thiserror::Error, Debug, Clone, Copy, PartialEq, Serialize)]
|
||||
#[error("Invalid Bitcoin address provided, expected address on network {expected:?} but address provided is on {actual:?}")]
|
||||
pub struct BitcoinAddressNetworkMismatch {
|
||||
#[serde(with = "crate::bitcoin::network")]
|
||||
#[serde(with = "swap_serde::bitcoin::network")]
|
||||
expected: bitcoin::Network,
|
||||
#[serde(with = "crate::bitcoin::network")]
|
||||
#[serde(with = "swap_serde::bitcoin::network")]
|
||||
actual: bitcoin::Network,
|
||||
}
|
||||
|
||||
|
@ -555,7 +481,7 @@ pub struct NotThreeWitnesses(usize);
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::env::{GetConfig, Regtest};
|
||||
use swap_env::env::{GetConfig, Regtest};
|
||||
use crate::monero::TransferProof;
|
||||
use crate::protocol::{alice, bob};
|
||||
use bitcoin::secp256k1;
|
||||
|
|
|
@ -35,6 +35,12 @@ impl From<CancelTimelock> for u32 {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<u32> for CancelTimelock {
|
||||
fn from(number_of_blocks: u32) -> Self {
|
||||
Self(number_of_blocks)
|
||||
}
|
||||
}
|
||||
|
||||
impl CancelTimelock {
|
||||
pub const fn new(number_of_blocks: u32) -> Self {
|
||||
Self(number_of_blocks)
|
||||
|
@ -86,6 +92,12 @@ impl From<PunishTimelock> for u32 {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<u32> for PunishTimelock {
|
||||
fn from(number_of_blocks: u32) -> Self {
|
||||
Self(number_of_blocks)
|
||||
}
|
||||
}
|
||||
|
||||
impl PunishTimelock {
|
||||
pub const fn new(number_of_blocks: u32) -> Self {
|
||||
Self(number_of_blocks)
|
||||
|
|
|
@ -441,7 +441,7 @@ impl Wallet {
|
|||
finality_confirmations: u32,
|
||||
target_block: u32,
|
||||
sync_interval: Duration,
|
||||
env_config: crate::env::Config,
|
||||
env_config: swap_env::env::Config,
|
||||
tauri_handle: Option<TauriHandle>,
|
||||
) -> Result<Wallet<bdk_wallet::rusqlite::Connection, Client>> {
|
||||
// Construct the private key, directory and wallet file for the new (>= 1.0.0) bdk wallet
|
||||
|
|
|
@ -5,9 +5,8 @@ use crate::cli::command::{Bitcoin, Monero};
|
|||
use crate::common::tor::init_tor_client;
|
||||
use crate::common::tracing_util::Format;
|
||||
use crate::database::{open_db, AccessMode};
|
||||
use crate::env::{Config as EnvConfig, GetConfig, Mainnet, Testnet};
|
||||
use crate::fs::system_data_dir;
|
||||
use crate::monero::Wallets;
|
||||
use swap_env::env::{Config as EnvConfig, GetConfig, Mainnet, Testnet};
|
||||
use swap_fs::system_data_dir;
|
||||
use crate::network::rendezvous::XmrBtcNamespace;
|
||||
use crate::protocol::Database;
|
||||
use crate::seed::Seed;
|
||||
|
|
|
@ -155,7 +155,7 @@ pub struct WithdrawBtcArgs {
|
|||
#[serde(default, with = "::bitcoin::amount::serde::as_sat::opt")]
|
||||
pub amount: Option<bitcoin::Amount>,
|
||||
#[typeshare(serialized_as = "string")]
|
||||
#[serde(with = "crate::bitcoin::address_serde")]
|
||||
#[serde(with = "swap_serde::bitcoin::address_serde")]
|
||||
pub address: bitcoin::Address,
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,8 @@ use crate::network::{
|
|||
cooperative_xmr_redeem_after_punish, encrypted_signature, quote, redial, transfer_proof,
|
||||
};
|
||||
use crate::protocol::bob::State2;
|
||||
use crate::{bitcoin, env};
|
||||
use crate::bitcoin;
|
||||
use swap_env::env;
|
||||
use anyhow::{anyhow, Error, Result};
|
||||
use libp2p::request_response::{
|
||||
InboundFailure, InboundRequestId, OutboundFailure, OutboundRequestId, ResponseChannel,
|
||||
|
|
|
@ -4,7 +4,7 @@ use crate::cli::api::request::{
|
|||
GetHistoryArgs, ListSellersArgs, MoneroRecoveryArgs, Request, ResumeSwapArgs, WithdrawBtcArgs,
|
||||
};
|
||||
use crate::cli::api::Context;
|
||||
use crate::monero::monero_address;
|
||||
use swap_serde::monero::address;
|
||||
use crate::monero::{self, MoneroAddressPool};
|
||||
use anyhow::Result;
|
||||
use bitcoin::address::NetworkUnchecked;
|
||||
|
@ -69,7 +69,7 @@ where
|
|||
tor,
|
||||
} => {
|
||||
let monero_receive_pool: MoneroAddressPool =
|
||||
monero_address::validate_is_testnet(monero_receive_address, is_testnet)?.into();
|
||||
swap_serde::monero::address::validate_is_testnet(monero_receive_address, is_testnet)?.into();
|
||||
|
||||
let bitcoin_change_address = bitcoin_change_address
|
||||
.map(|address| bitcoin_address::validate(address, is_testnet))
|
||||
|
@ -354,7 +354,7 @@ enum CliCommand {
|
|||
|
||||
#[structopt(long = "receive-address",
|
||||
help = "The monero address where you would like to receive monero",
|
||||
parse(try_from_str = monero_address::parse)
|
||||
parse(try_from_str = swap_serde::monero::address::parse)
|
||||
)]
|
||||
monero_receive_address: monero::Address,
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ pub use bob::Bob;
|
|||
pub use sqlite::SqliteDatabase;
|
||||
|
||||
use crate::cli::api::tauri_bindings::TauriHandle;
|
||||
use crate::fs::ensure_directory_exists;
|
||||
use swap_fs::ensure_directory_exists;
|
||||
use crate::protocol::{Database, State};
|
||||
use anyhow::{bail, Result};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::bitcoin::EncryptedSignature;
|
||||
use crate::monero;
|
||||
use crate::monero::BlockHeight;
|
||||
use crate::monero::{monero_private_key, TransferProof};
|
||||
use crate::monero::TransferProof;
|
||||
use crate::protocol::alice;
|
||||
use crate::protocol::alice::AliceState;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -68,7 +68,7 @@ pub enum Alice {
|
|||
monero_wallet_restore_blockheight: BlockHeight,
|
||||
transfer_proof: TransferProof,
|
||||
state3: alice::State3,
|
||||
#[serde(with = "monero_private_key")]
|
||||
#[serde(with = "swap_serde::monero::private_key")]
|
||||
spend_key: monero::PrivateKey,
|
||||
},
|
||||
Done(AliceEndState),
|
||||
|
|
|
@ -10,7 +10,7 @@ pub enum Bob {
|
|||
Started {
|
||||
#[serde(with = "::bitcoin::amount::serde::as_sat")]
|
||||
btc_amount: bitcoin::Amount,
|
||||
#[serde(with = "crate::bitcoin::address_serde")]
|
||||
#[serde(with = "swap_serde::bitcoin::address_serde")]
|
||||
change_address: bitcoin::Address,
|
||||
tx_lock_fee: bitcoin::Amount,
|
||||
},
|
||||
|
|
|
@ -21,8 +21,6 @@ pub mod bitcoin;
|
|||
pub mod cli;
|
||||
pub mod common;
|
||||
pub mod database;
|
||||
pub mod env;
|
||||
pub mod fs;
|
||||
pub mod kraken;
|
||||
pub mod libp2p_ext;
|
||||
pub mod monero;
|
||||
|
|
|
@ -52,7 +52,7 @@ pub fn private_key_from_secp256k1_scalar(scalar: bitcoin::Scalar) -> PrivateKey
|
|||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct PrivateViewKey(#[serde(with = "monero_private_key")] PrivateKey);
|
||||
pub struct PrivateViewKey(#[serde(with = "swap_serde::monero::private_key")] PrivateKey);
|
||||
|
||||
impl fmt::Display for PrivateViewKey {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
|
@ -445,7 +445,7 @@ impl fmt::Display for Amount {
|
|||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct TransferProof {
|
||||
tx_hash: TxHash,
|
||||
#[serde(with = "monero_private_key")]
|
||||
#[serde(with = "swap_serde::monero::private_key")]
|
||||
tx_key: PrivateKey,
|
||||
}
|
||||
|
||||
|
@ -494,73 +494,6 @@ pub struct InsufficientFunds {
|
|||
#[error("Overflow, cannot convert {0} to u64")]
|
||||
pub struct OverflowError(pub String);
|
||||
|
||||
pub mod monero_private_key {
|
||||
use monero::consensus::{Decodable, Encodable};
|
||||
use monero::PrivateKey;
|
||||
use serde::de::Visitor;
|
||||
use serde::ser::Error;
|
||||
use serde::{de, Deserializer, Serializer};
|
||||
use std::fmt;
|
||||
use std::io::Cursor;
|
||||
|
||||
struct BytesVisitor;
|
||||
|
||||
impl Visitor<'_> for BytesVisitor {
|
||||
type Value = PrivateKey;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(formatter, "a byte array representing a Monero private key")
|
||||
}
|
||||
|
||||
fn visit_bytes<E>(self, s: &[u8]) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
let mut s = s;
|
||||
PrivateKey::consensus_decode(&mut s).map_err(|err| E::custom(format!("{:?}", err)))
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
let bytes = hex::decode(s).map_err(|err| E::custom(format!("{:?}", err)))?;
|
||||
PrivateKey::consensus_decode(&mut bytes.as_slice())
|
||||
.map_err(|err| E::custom(format!("{:?}", err)))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn serialize<S>(x: &PrivateKey, s: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let mut bytes = Cursor::new(vec![]);
|
||||
x.consensus_encode(&mut bytes)
|
||||
.map_err(|err| S::Error::custom(format!("{:?}", err)))?;
|
||||
if s.is_human_readable() {
|
||||
s.serialize_str(&hex::encode(bytes.into_inner()))
|
||||
} else {
|
||||
s.serialize_bytes(bytes.into_inner().as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn deserialize<'de, D>(
|
||||
deserializer: D,
|
||||
) -> Result<PrivateKey, <D as Deserializer<'de>>::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let key = {
|
||||
if deserializer.is_human_readable() {
|
||||
deserializer.deserialize_string(BytesVisitor)?
|
||||
} else {
|
||||
deserializer.deserialize_bytes(BytesVisitor)?
|
||||
}
|
||||
};
|
||||
Ok(key)
|
||||
}
|
||||
}
|
||||
|
||||
pub mod monero_amount {
|
||||
use crate::monero::Amount;
|
||||
use serde::{Deserialize, Deserializer, Serializer};
|
||||
|
@ -583,52 +516,6 @@ pub mod monero_amount {
|
|||
}
|
||||
}
|
||||
|
||||
pub mod monero_address {
|
||||
use anyhow::{bail, Context, Result};
|
||||
use std::str::FromStr;
|
||||
|
||||
#[derive(thiserror::Error, Debug, Clone, Copy, PartialEq)]
|
||||
#[error("Invalid monero address provided, expected address on network {expected:?} but address provided is on {actual:?}")]
|
||||
pub struct MoneroAddressNetworkMismatch {
|
||||
pub expected: monero::Network,
|
||||
pub actual: monero::Network,
|
||||
}
|
||||
|
||||
pub fn parse(s: &str) -> Result<monero::Address> {
|
||||
monero::Address::from_str(s).with_context(|| {
|
||||
format!(
|
||||
"Failed to parse {} as a monero address, please make sure it is a valid address",
|
||||
s
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn validate(
|
||||
address: monero::Address,
|
||||
expected_network: monero::Network,
|
||||
) -> Result<monero::Address> {
|
||||
if address.network != expected_network {
|
||||
bail!(MoneroAddressNetworkMismatch {
|
||||
expected: expected_network,
|
||||
actual: address.network,
|
||||
});
|
||||
}
|
||||
Ok(address)
|
||||
}
|
||||
|
||||
pub fn validate_is_testnet(
|
||||
address: monero::Address,
|
||||
is_testnet: bool,
|
||||
) -> Result<monero::Address> {
|
||||
let expected_network = if is_testnet {
|
||||
monero::Network::Stagenet
|
||||
} else {
|
||||
monero::Network::Mainnet
|
||||
};
|
||||
validate(address, expected_network)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
|
@ -36,9 +36,9 @@ pub mod protocol {
|
|||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct BlockchainNetwork {
|
||||
#[serde(with = "crate::bitcoin::network")]
|
||||
#[serde(with = "swap_serde::bitcoin::network")]
|
||||
pub bitcoin: bitcoin::Network,
|
||||
#[serde(with = "crate::monero::network")]
|
||||
#[serde(with = "swap_serde::monero::network")]
|
||||
pub monero: monero::Network,
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,8 @@ use crate::network::swap_setup::{
|
|||
};
|
||||
use crate::protocol::alice::{State0, State3};
|
||||
use crate::protocol::{Message0, Message2, Message4};
|
||||
use crate::{asb, bitcoin, env, monero};
|
||||
use crate::{asb, bitcoin, monero};
|
||||
use swap_env::env;
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use futures::future::{BoxFuture, OptionFuture};
|
||||
use futures::AsyncWriteExt;
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use crate::network::swap_setup::{protocol, BlockchainNetwork, SpotPriceError, SpotPriceResponse};
|
||||
use crate::protocol::bob::{State0, State2};
|
||||
use crate::protocol::{Message1, Message3};
|
||||
use crate::{bitcoin, cli, env, monero};
|
||||
use crate::{bitcoin, cli, monero};
|
||||
use swap_env::env;
|
||||
use anyhow::{Context, Result};
|
||||
use futures::future::{BoxFuture, OptionFuture};
|
||||
use futures::AsyncWriteExt;
|
||||
|
@ -210,8 +211,8 @@ impl ConnectionHandler for Handler {
|
|||
&mut rand::thread_rng(),
|
||||
new_swap_request.btc,
|
||||
xmr,
|
||||
env_config.bitcoin_cancel_timelock,
|
||||
env_config.bitcoin_punish_timelock,
|
||||
env_config.bitcoin_cancel_timelock.into(),
|
||||
env_config.bitcoin_punish_timelock.into(),
|
||||
new_swap_request.bitcoin_refund_address.clone(),
|
||||
env_config.monero_finality_confirmations,
|
||||
new_swap_request.tx_refund_fee,
|
||||
|
|
|
@ -2,7 +2,8 @@ use crate::asb::{LatestRate, RendezvousNode};
|
|||
use crate::libp2p_ext::MultiAddrExt;
|
||||
use crate::network::rendezvous::XmrBtcNamespace;
|
||||
use crate::seed::Seed;
|
||||
use crate::{asb, bitcoin, cli, env};
|
||||
use crate::{asb, bitcoin, cli};
|
||||
use swap_env::env;
|
||||
use anyhow::Result;
|
||||
use arti_client::TorClient;
|
||||
use libp2p::swarm::NetworkBehaviour;
|
||||
|
|
|
@ -35,7 +35,7 @@ pub struct Message0 {
|
|||
S_b_bitcoin: bitcoin::PublicKey,
|
||||
dleq_proof_s_b: CrossCurveDLEQProof,
|
||||
v_b: monero::PrivateViewKey,
|
||||
#[serde(with = "crate::bitcoin::address_serde")]
|
||||
#[serde(with = "swap_serde::bitcoin::address_serde")]
|
||||
refund_address: bitcoin::Address,
|
||||
#[serde(with = "::bitcoin::amount::serde::as_sat")]
|
||||
tx_refund_fee: bitcoin::Amount,
|
||||
|
@ -50,9 +50,9 @@ pub struct Message1 {
|
|||
S_a_bitcoin: bitcoin::PublicKey,
|
||||
dleq_proof_s_a: CrossCurveDLEQProof,
|
||||
v_a: monero::PrivateViewKey,
|
||||
#[serde(with = "crate::bitcoin::address_serde")]
|
||||
#[serde(with = "swap_serde::bitcoin::address_serde")]
|
||||
redeem_address: bitcoin::Address,
|
||||
#[serde(with = "crate::bitcoin::address_serde")]
|
||||
#[serde(with = "swap_serde::bitcoin::address_serde")]
|
||||
punish_address: bitcoin::Address,
|
||||
#[serde(with = "::bitcoin::amount::serde::as_sat")]
|
||||
tx_redeem_fee: bitcoin::Amount,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! Run an XMR/BTC swap in the role of Alice.
|
||||
//! Alice holds XMR and wishes receive BTC.
|
||||
use crate::env::Config;
|
||||
use swap_env::env::Config;
|
||||
use crate::protocol::Database;
|
||||
use crate::{asb, bitcoin, monero};
|
||||
use std::sync::Arc;
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::bitcoin::{
|
|||
current_epoch, CancelTimelock, ExpiredTimelocks, PunishTimelock, Transaction, TxCancel,
|
||||
TxEarlyRefund, TxPunish, TxRedeem, TxRefund, Txid,
|
||||
};
|
||||
use crate::env::Config;
|
||||
use swap_env::env::Config;
|
||||
use crate::monero::wallet::{TransferRequest, WatchRequest};
|
||||
use crate::monero::BlockHeight;
|
||||
use crate::monero::TransferProof;
|
||||
|
@ -170,8 +170,8 @@ impl State0 {
|
|||
punish_address,
|
||||
btc,
|
||||
xmr,
|
||||
cancel_timelock: env_config.bitcoin_cancel_timelock,
|
||||
punish_timelock: env_config.bitcoin_punish_timelock,
|
||||
cancel_timelock: env_config.bitcoin_cancel_timelock.into(),
|
||||
punish_timelock: env_config.bitcoin_punish_timelock.into(),
|
||||
tx_redeem_fee,
|
||||
tx_punish_fee,
|
||||
}
|
||||
|
@ -413,11 +413,11 @@ pub struct State3 {
|
|||
pub xmr: monero::Amount,
|
||||
pub cancel_timelock: CancelTimelock,
|
||||
pub punish_timelock: PunishTimelock,
|
||||
#[serde(with = "crate::bitcoin::address_serde")]
|
||||
#[serde(with = "swap_serde::bitcoin::address_serde")]
|
||||
refund_address: bitcoin::Address,
|
||||
#[serde(with = "crate::bitcoin::address_serde")]
|
||||
#[serde(with = "swap_serde::bitcoin::address_serde")]
|
||||
redeem_address: bitcoin::Address,
|
||||
#[serde(with = "crate::bitcoin::address_serde")]
|
||||
#[serde(with = "swap_serde::bitcoin::address_serde")]
|
||||
punish_address: bitcoin::Address,
|
||||
pub tx_lock: bitcoin::TxLock,
|
||||
tx_punish_sig_bob: bitcoin::Signature,
|
||||
|
|
|
@ -7,7 +7,7 @@ use std::time::Duration;
|
|||
use crate::asb::{EventLoopHandle, LatestRate};
|
||||
use crate::bitcoin::ExpiredTimelocks;
|
||||
use crate::common::retry;
|
||||
use crate::env::Config;
|
||||
use swap_env::env::Config;
|
||||
use crate::monero::TransferProof;
|
||||
use crate::protocol::alice::{AliceState, Swap};
|
||||
use crate::{bitcoin, monero};
|
||||
|
|
|
@ -6,7 +6,8 @@ use uuid::Uuid;
|
|||
use crate::cli::api::tauri_bindings::TauriHandle;
|
||||
use crate::monero::MoneroAddressPool;
|
||||
use crate::protocol::Database;
|
||||
use crate::{bitcoin, cli, env, monero};
|
||||
use crate::{bitcoin, cli, monero};
|
||||
use swap_env::env;
|
||||
|
||||
pub use self::state::*;
|
||||
pub use self::swap::{run, run_until};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::bitcoin::address_serde;
|
||||
use swap_serde::bitcoin::address_serde;
|
||||
use crate::bitcoin::wallet::{EstimateFeeRate, Subscription};
|
||||
use crate::bitcoin::{
|
||||
self, current_epoch, CancelTimelock, ExpiredTimelocks, PunishTimelock, Transaction, TxCancel,
|
||||
|
@ -6,7 +6,7 @@ use crate::bitcoin::{
|
|||
};
|
||||
use crate::monero::wallet::WatchRequest;
|
||||
use crate::monero::{self, MoneroAddressPool, TxHash};
|
||||
use crate::monero::{monero_private_key, TransferProof};
|
||||
use crate::monero::{TransferProof};
|
||||
use crate::monero_ext::ScalarExt;
|
||||
use crate::protocol::{Message0, Message1, Message2, Message3, Message4, CROSS_CURVE_PROOF_SYSTEM};
|
||||
use anyhow::{anyhow, bail, Context, Result};
|
||||
|
@ -685,7 +685,7 @@ impl State4 {
|
|||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
|
||||
pub struct State5 {
|
||||
#[serde(with = "monero_private_key")]
|
||||
#[serde(with = "swap_serde::monero::private_key")]
|
||||
s_a: monero::PrivateKey,
|
||||
s_b: monero::Scalar,
|
||||
v: monero::PrivateViewKey,
|
||||
|
|
|
@ -9,7 +9,8 @@ use crate::network::cooperative_xmr_redeem_after_punish::Response::{Fullfilled,
|
|||
use crate::network::swap_setup::bob::NewSwap;
|
||||
use crate::protocol::bob::state::*;
|
||||
use crate::protocol::{bob, Database};
|
||||
use crate::{bitcoin, env, monero};
|
||||
use crate::{bitcoin, monero};
|
||||
use swap_env::env;
|
||||
use anyhow::{bail, Context as AnyContext, Result};
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::cli::api::tauri_bindings::{SeedChoice, TauriEmitter, TauriHandle};
|
||||
use crate::fs::ensure_directory_exists;
|
||||
use swap_fs::ensure_directory_exists;
|
||||
use ::bitcoin::bip32::Xpriv as ExtendedPrivKey;
|
||||
use anyhow::{Context, Result};
|
||||
use bitcoin::hashes::{sha256, Hash, HashEngine};
|
||||
|
|
|
@ -21,8 +21,8 @@ use swap::asb::FixedRate;
|
|||
use swap::bitcoin::{CancelTimelock, PunishTimelock};
|
||||
use swap::cli::api;
|
||||
use swap::database::{AccessMode, SqliteDatabase};
|
||||
use swap::env::{Config, GetConfig};
|
||||
use swap::fs::ensure_directory_exists;
|
||||
use swap_env::env::{Config, GetConfig};
|
||||
use swap_fs::ensure_directory_exists;
|
||||
use swap::monero::wallet::no_listener;
|
||||
use swap::monero::Wallets;
|
||||
use swap::network::rendezvous::XmrBtcNamespace;
|
||||
|
@ -31,7 +31,8 @@ use swap::protocol::alice::{AliceState, Swap};
|
|||
use swap::protocol::bob::BobState;
|
||||
use swap::protocol::{alice, bob, Database};
|
||||
use swap::seed::Seed;
|
||||
use swap::{asb, bitcoin, cli, env, monero};
|
||||
use swap::{asb, bitcoin, cli, monero};
|
||||
use swap_env::env;
|
||||
use tempfile::{NamedTempFile, TempDir};
|
||||
use testcontainers::clients::Cli;
|
||||
use testcontainers::{Container, RunnableImage};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue