Update EsploraConfig, Blockchain broadcast, Wallet sync
This commit is contained in:
		
							parent
							
								
									907540d214
								
							
						
					
					
						commit
						4665c551dd
					
				
							
								
								
									
										19
									
								
								src/bdk.udl
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								src/bdk.udl
									
									
									
									
									
								
							| @ -101,9 +101,9 @@ dictionary ElectrumConfig { | |||||||
| dictionary EsploraConfig { | dictionary EsploraConfig { | ||||||
|   string base_url; |   string base_url; | ||||||
|   string? proxy; |   string? proxy; | ||||||
|   u64 timeout_read; |   u8? concurrency; | ||||||
|   u64 timeout_write; |  | ||||||
|   u64 stop_gap; |   u64 stop_gap; | ||||||
|  |   u64? timeout; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| [Enum] | [Enum] | ||||||
| @ -112,13 +112,20 @@ interface BlockchainConfig { | |||||||
|   Esplora(EsploraConfig config); |   Esplora(EsploraConfig config); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| callback interface BdkProgress { | interface Blockchain { | ||||||
|  |   [Throws=BdkError] | ||||||
|  |   constructor(BlockchainConfig config); | ||||||
|  |   [Throws=BdkError] | ||||||
|  |   string broadcast([ByRef] PartiallySignedBitcoinTransaction psbt); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | callback interface Progress { | ||||||
|   void update(f32 progress, string? message); |   void update(f32 progress, string? message); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| interface Wallet { | interface Wallet { | ||||||
|   [Throws=BdkError] |   [Throws=BdkError] | ||||||
|   constructor(string descriptor, string? change_descriptor, Network network, DatabaseConfig database_config, BlockchainConfig blockchain_config); |   constructor(string descriptor, string? change_descriptor, Network network, DatabaseConfig database_config); | ||||||
|   string get_new_address(); |   string get_new_address(); | ||||||
|   string get_last_unused_address(); |   string get_last_unused_address(); | ||||||
|   [Throws=BdkError] |   [Throws=BdkError] | ||||||
| @ -129,9 +136,7 @@ interface Wallet { | |||||||
|   sequence<Transaction> get_transactions(); |   sequence<Transaction> get_transactions(); | ||||||
|   Network get_network(); |   Network get_network(); | ||||||
|   [Throws=BdkError] |   [Throws=BdkError] | ||||||
|   void sync(BdkProgress progress_update, u32? max_address_param); |   void sync([ByRef] Blockchain blockchain, Progress? progress); | ||||||
|   [Throws=BdkError] |  | ||||||
|   string broadcast([ByRef] PartiallySignedBitcoinTransaction psbt); |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| interface PartiallySignedBitcoinTransaction { | interface PartiallySignedBitcoinTransaction { | ||||||
|  | |||||||
							
								
								
									
										125
									
								
								src/lib.rs
									
									
									
									
									
								
							
							
						
						
									
										125
									
								
								src/lib.rs
									
									
									
									
									
								
							| @ -3,18 +3,22 @@ use bdk::bitcoin::secp256k1::Secp256k1; | |||||||
| use bdk::bitcoin::util::psbt::PartiallySignedTransaction; | use bdk::bitcoin::util::psbt::PartiallySignedTransaction; | ||||||
| use bdk::bitcoin::{Address, Network, Script}; | use bdk::bitcoin::{Address, Network, Script}; | ||||||
| use bdk::blockchain::any::{AnyBlockchain, AnyBlockchainConfig}; | use bdk::blockchain::any::{AnyBlockchain, AnyBlockchainConfig}; | ||||||
| use bdk::blockchain::Progress; |  | ||||||
| use bdk::blockchain::{ | use bdk::blockchain::{ | ||||||
|     electrum::ElectrumBlockchainConfig, esplora::EsploraBlockchainConfig, ConfigurableBlockchain, |     electrum::ElectrumBlockchainConfig, esplora::EsploraBlockchainConfig, ConfigurableBlockchain, | ||||||
| }; | }; | ||||||
|  | use bdk::blockchain::{Blockchain as BdkBlockchain, Progress as BdkProgress}; | ||||||
| use bdk::database::any::{AnyDatabase, SledDbConfiguration, SqliteDbConfiguration}; | use bdk::database::any::{AnyDatabase, SledDbConfiguration, SqliteDbConfiguration}; | ||||||
| use bdk::database::{AnyDatabaseConfig, ConfigurableDatabase}; | use bdk::database::{AnyDatabaseConfig, ConfigurableDatabase}; | ||||||
| use bdk::keys::bip39::{Language, Mnemonic, WordCount}; | use bdk::keys::bip39::{Language, Mnemonic, WordCount}; | ||||||
| use bdk::keys::{DerivableKey, ExtendedKey, GeneratableKey, GeneratedKey}; | use bdk::keys::{DerivableKey, ExtendedKey, GeneratableKey, GeneratedKey}; | ||||||
| use bdk::miniscript::BareCtx; | use bdk::miniscript::BareCtx; | ||||||
| use bdk::wallet::AddressIndex; | use bdk::wallet::AddressIndex; | ||||||
| use bdk::{BlockTime, Error, FeeRate, SignOptions, Wallet as BdkWallet}; | use bdk::{ | ||||||
|  |     BlockTime, Error, FeeRate, SignOptions, SyncOptions as BdkSyncOptions, Wallet as BdkWallet, | ||||||
|  | }; | ||||||
| use std::convert::TryFrom; | use std::convert::TryFrom; | ||||||
|  | use std::fmt; | ||||||
|  | use std::ops::Deref; | ||||||
| use std::str::FromStr; | use std::str::FromStr; | ||||||
| use std::sync::{Arc, Mutex, MutexGuard}; | use std::sync::{Arc, Mutex, MutexGuard}; | ||||||
| 
 | 
 | ||||||
| @ -39,9 +43,9 @@ pub struct ElectrumConfig { | |||||||
| pub struct EsploraConfig { | pub struct EsploraConfig { | ||||||
|     pub base_url: String, |     pub base_url: String, | ||||||
|     pub proxy: Option<String>, |     pub proxy: Option<String>, | ||||||
|     pub timeout_read: u64, |     pub concurrency: Option<u8>, | ||||||
|     pub timeout_write: u64, |  | ||||||
|     pub stop_gap: u64, |     pub stop_gap: u64, | ||||||
|  |     pub timeout: Option<u64>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub enum BlockchainConfig { | pub enum BlockchainConfig { | ||||||
| @ -93,25 +97,76 @@ impl From<&bdk::TransactionDetails> for Transaction { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| struct Wallet { | struct Blockchain { | ||||||
|     wallet_mutex: Mutex<BdkWallet<AnyBlockchain, AnyDatabase>>, |     blockchain_mutex: Mutex<AnyBlockchain>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub trait BdkProgress: Send + Sync { | impl Blockchain { | ||||||
|  |     fn new(blockchain_config: BlockchainConfig) -> Result<Self, BdkError> { | ||||||
|  |         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, | ||||||
|  |                     concurrency: config.concurrency, | ||||||
|  |                     stop_gap: usize::try_from(config.stop_gap).unwrap(), | ||||||
|  |                     timeout: config.timeout, | ||||||
|  |                 }) | ||||||
|  |             } | ||||||
|  |         }; | ||||||
|  |         let blockchain = AnyBlockchain::from_config(&any_blockchain_config)?; | ||||||
|  |         Ok(Self { | ||||||
|  |             blockchain_mutex: Mutex::new(blockchain), | ||||||
|  |         }) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn get_blockchain(&self) -> MutexGuard<AnyBlockchain> { | ||||||
|  |         self.blockchain_mutex.lock().expect("blockchain") | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn broadcast(&self, psbt: &PartiallySignedBitcoinTransaction) -> Result<String, Error> { | ||||||
|  |         let tx = psbt.internal.lock().unwrap().clone().extract_tx(); | ||||||
|  |         self.get_blockchain().broadcast(&tx)?; | ||||||
|  |         // TODO move txid getter to PartiallySignedBitcoinTransaction
 | ||||||
|  |         let txid = tx.txid(); | ||||||
|  |         Ok(txid.to_hex()) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | struct Wallet { | ||||||
|  |     wallet_mutex: Mutex<BdkWallet<AnyDatabase>>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | pub trait Progress: Send + Sync + 'static { | ||||||
|     fn update(&self, progress: f32, message: Option<String>); |     fn update(&self, progress: f32, message: Option<String>); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| struct BdkProgressHolder { | struct ProgressHolder { | ||||||
|     progress_update: Box<dyn BdkProgress>, |     progress: Box<dyn Progress>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Progress for BdkProgressHolder { | impl BdkProgress for ProgressHolder { | ||||||
|     fn update(&self, progress: f32, message: Option<String>) -> Result<(), Error> { |     fn update(&self, progress: f32, message: Option<String>) -> Result<(), Error> { | ||||||
|         self.progress_update.update(progress, message); |         self.progress.update(progress, message); | ||||||
|         Ok(()) |         Ok(()) | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | impl fmt::Debug for ProgressHolder { | ||||||
|  |     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||||||
|  |         f.debug_struct("ProgressHolder").finish_non_exhaustive() | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| struct PartiallySignedBitcoinTransaction { | struct PartiallySignedBitcoinTransaction { | ||||||
|     internal: Mutex<PartiallySignedTransaction>, |     internal: Mutex<PartiallySignedTransaction>, | ||||||
| @ -137,46 +192,23 @@ impl Wallet { | |||||||
|         change_descriptor: Option<String>, |         change_descriptor: Option<String>, | ||||||
|         network: Network, |         network: Network, | ||||||
|         database_config: DatabaseConfig, |         database_config: DatabaseConfig, | ||||||
|         blockchain_config: BlockchainConfig, |  | ||||||
|     ) -> Result<Self, BdkError> { |     ) -> Result<Self, BdkError> { | ||||||
|         let any_database_config = match database_config { |         let any_database_config = match database_config { | ||||||
|             DatabaseConfig::Memory => AnyDatabaseConfig::Memory(()), |             DatabaseConfig::Memory => AnyDatabaseConfig::Memory(()), | ||||||
|             DatabaseConfig::Sled { config } => AnyDatabaseConfig::Sled(config), |             DatabaseConfig::Sled { config } => AnyDatabaseConfig::Sled(config), | ||||||
|             DatabaseConfig::Sqlite { config } => AnyDatabaseConfig::Sqlite(config), |             DatabaseConfig::Sqlite { config } => AnyDatabaseConfig::Sqlite(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 database = AnyDatabase::from_config(&any_database_config)?; | ||||||
|         let blockchain = AnyBlockchain::from_config(&any_blockchain_config)?; |  | ||||||
|         let wallet_mutex = Mutex::new(BdkWallet::new( |         let wallet_mutex = Mutex::new(BdkWallet::new( | ||||||
|             &descriptor, |             &descriptor, | ||||||
|             change_descriptor.as_ref(), |             change_descriptor.as_ref(), | ||||||
|             network, |             network, | ||||||
|             database, |             database, | ||||||
|             blockchain, |  | ||||||
|         )?); |         )?); | ||||||
|         Ok(Wallet { wallet_mutex }) |         Ok(Wallet { wallet_mutex }) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn get_wallet(&self) -> MutexGuard<BdkWallet<AnyBlockchain, AnyDatabase>> { |     fn get_wallet(&self) -> MutexGuard<BdkWallet<AnyDatabase>> { | ||||||
|         self.wallet_mutex.lock().expect("wallet") |         self.wallet_mutex.lock().expect("wallet") | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -186,11 +218,20 @@ impl Wallet { | |||||||
| 
 | 
 | ||||||
|     fn sync( |     fn sync( | ||||||
|         &self, |         &self, | ||||||
|         progress_update: Box<dyn BdkProgress>, |         blockchain: &Blockchain, | ||||||
|         max_address_param: Option<u32>, |         progress: Option<Box<dyn Progress>>, | ||||||
|  |         //progress_update: Box<dyn BdkProgress>,
 | ||||||
|  |         //max_address_param: Option<u32>,
 | ||||||
|     ) -> Result<(), BdkError> { |     ) -> Result<(), BdkError> { | ||||||
|         self.get_wallet() |         let bdk_sync_opts = BdkSyncOptions { | ||||||
|             .sync(BdkProgressHolder { progress_update }, max_address_param) |             progress: progress.map(|p| { | ||||||
|  |                 Box::new(ProgressHolder { progress: p }) | ||||||
|  |                     as Box<(dyn bdk::blockchain::Progress + 'static)> | ||||||
|  |             }), | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         let blockchain = blockchain.get_blockchain(); | ||||||
|  |         self.get_wallet().sync(blockchain.deref(), bdk_sync_opts) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn get_new_address(&self) -> String { |     fn get_new_address(&self) -> String { | ||||||
| @ -229,12 +270,6 @@ impl Wallet { | |||||||
|         let transactions = self.get_wallet().list_transactions(true)?; |         let transactions = self.get_wallet().list_transactions(true)?; | ||||||
|         Ok(transactions.iter().map(Transaction::from).collect()) |         Ok(transactions.iter().map(Transaction::from).collect()) | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
|     fn broadcast(&self, psbt: &PartiallySignedBitcoinTransaction) -> Result<String, Error> { |  | ||||||
|         let tx = psbt.internal.lock().unwrap().clone().extract_tx(); |  | ||||||
|         let txid = self.get_wallet().broadcast(&tx)?; |  | ||||||
|         Ok(txid.to_hex()) |  | ||||||
|     } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub struct ExtendedKeyInfo { | pub struct ExtendedKeyInfo { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user