diff --git a/Cargo.toml b/Cargo.toml index d59366f..954e596 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ edition = "2018" crate-type = ["cdylib"] [dependencies] -bdk = { version = "^0.12.1-dev", features = ["all-keys"] } +bdk = { version = "^0.12.1-dev", features = ["all-keys", "use-esplora-ureq"] } uniffi_macros = "0.14.0" uniffi = "0.14.0" thiserror = "1.0" diff --git a/src/bdk.udl b/src/bdk.udl index 2ae60cc..1994bc1 100644 --- a/src/bdk.udl +++ b/src/bdk.udl @@ -41,6 +41,7 @@ enum BdkError { "Psbt", "PsbtParse", "Electrum", + "Esplora", "Sled", }; @@ -59,7 +60,7 @@ dictionary SledDbConfiguration { [Enum] interface DatabaseConfig { Memory(string junk); - Sled(SledDbConfiguration configuration); + Sled(SledDbConfiguration config); }; interface OfflineWallet { @@ -67,3 +68,30 @@ interface OfflineWallet { constructor(string descriptor, Network network, DatabaseConfig database_config); string get_new_address(); }; + +dictionary ElectrumConfig { + string url; + string? socks5; + u8 retry; + u8? timeout; + u64 stop_gap; +}; + +dictionary EsploraConfig { + string base_url; + string? proxy; + u64 timeout_read; + u64 timeout_write; + u64 stop_gap; +}; + +[Enum] +interface BlockchainConfig { + Electrum(ElectrumConfig config); + Esplora(EsploraConfig config); +}; + +interface OnlineWallet { + [Throws=BdkError] + constructor(string descriptor, Network network, DatabaseConfig database_config, BlockchainConfig blockchain_config); +}; diff --git a/src/lib.rs b/src/lib.rs index cf0f756..ae6fcc3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,10 +1,14 @@ use bdk::bitcoin::Network; +use bdk::blockchain::any::{AnyBlockchain, AnyBlockchainConfig}; +use bdk::blockchain::{ + electrum::ElectrumBlockchainConfig, esplora::EsploraBlockchainConfig, ConfigurableBlockchain, +}; use bdk::database::any::{AnyDatabase, SledDbConfiguration}; use bdk::database::{AnyDatabaseConfig, ConfigurableDatabase}; use bdk::wallet::AddressIndex; use bdk::Error; use bdk::Wallet; - +use std::convert::TryFrom; use std::sync::Mutex; uniffi_macros::include_scaffolding!("bdk"); @@ -13,7 +17,28 @@ type BdkError = Error; pub enum DatabaseConfig { Memory { junk: String }, - Sled { configuration: SledDbConfiguration }, + Sled { config: SledDbConfiguration }, +} + +pub struct ElectrumConfig { + pub url: String, + pub socks5: Option, + pub retry: u8, + pub timeout: Option, + pub stop_gap: u64, +} + +pub struct EsploraConfig { + pub base_url: String, + pub proxy: Option, + pub timeout_read: u64, + pub timeout_write: u64, + pub stop_gap: u64, +} + +pub enum BlockchainConfig { + Electrum { config: ElectrumConfig }, + Esplora { config: EsploraConfig }, } struct OfflineWallet { @@ -28,7 +53,7 @@ impl OfflineWallet { ) -> Result { let any_database_config = match database_config { DatabaseConfig::Memory { .. } => AnyDatabaseConfig::Memory(()), - DatabaseConfig::Sled { configuration } => AnyDatabaseConfig::Sled(configuration), + DatabaseConfig::Sled { config } => AnyDatabaseConfig::Sled(config), }; let database = AnyDatabase::from_config(&any_database_config)?; let wallet = Mutex::new(Wallet::new_offline(&descriptor, None, network, database)?); @@ -46,4 +71,53 @@ impl OfflineWallet { } } +struct OnlineWallet { + wallet: Mutex>, +} + +impl OnlineWallet { + fn new( + descriptor: String, + network: Network, + database_config: DatabaseConfig, + blockchain_config: BlockchainConfig, + ) -> Result { + let any_database_config = match database_config { + DatabaseConfig::Memory { .. } => AnyDatabaseConfig::Memory(()), + DatabaseConfig::Sled { config } => AnyDatabaseConfig::Sled(config), + }; + let any_blockchain_config = match blockchain_config { + BlockchainConfig::Electrum { config } => { + AnyBlockchainConfig::Electrum(ElectrumBlockchainConfig { + retry: config.retry, + socks5: config.socks5, + timeout: config.timeout, + url: config.url, + stop_gap: usize::try_from(config.stop_gap).unwrap(), + }) + } + BlockchainConfig::Esplora { config } => { + AnyBlockchainConfig::Esplora(EsploraBlockchainConfig { + base_url: config.base_url, + proxy: config.proxy, + timeout_read: config.timeout_read, + timeout_write: config.timeout_write, + stop_gap: usize::try_from(config.stop_gap).unwrap(), + }) + } + }; + let database = AnyDatabase::from_config(&any_database_config)?; + let blockchain = AnyBlockchain::from_config(&any_blockchain_config)?; + let wallet = Mutex::new(Wallet::new( + &descriptor, + None, + network, + database, + blockchain, + )?); + Ok(OnlineWallet { wallet }) + } +} + uniffi::deps::static_assertions::assert_impl_all!(OfflineWallet: Sync, Send); +uniffi::deps::static_assertions::assert_impl_all!(OnlineWallet: Sync, Send);