[blockchain] Simplify the architecture of blockchain traits
Instead of having two traits, `Blockchain` and `OnlineBlockchain` that need to be implemented by the user, only the relevant one (`OnlineBlockchain`, here renamed to `Blockchain`) will need to be implemented, since we provide a blanket implementation for the "marker" trait (previously `Blockchain`, here renamed to `BlockchainMarker`). Users of the library will probably never need to implement `BlockchainMarker` by itself, since we expose the `OfflineBlockchain` type that already does that and should be good for any "offline" wallet. Still, it's exposed since they might need to import it to define types with generics.
This commit is contained in:
@@ -73,7 +73,7 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
use miniscript::{Descriptor, ScriptContext, Terminal};
|
||||
|
||||
use crate::blockchain::Blockchain;
|
||||
use crate::blockchain::BlockchainMarker;
|
||||
use crate::database::BatchDatabase;
|
||||
use crate::wallet::Wallet;
|
||||
|
||||
@@ -115,7 +115,7 @@ impl WalletExport {
|
||||
///
|
||||
/// If the database is empty or `include_blockheight` is false, the `blockheight` field
|
||||
/// returned will be `0`.
|
||||
pub fn export_wallet<B: Blockchain, D: BatchDatabase>(
|
||||
pub fn export_wallet<B: BlockchainMarker, D: BatchDatabase>(
|
||||
wallet: &Wallet<B, D>,
|
||||
label: &str,
|
||||
include_blockheight: bool,
|
||||
|
||||
@@ -58,7 +58,7 @@ use signer::{Signer, SignerId, SignerOrdering, SignersContainer};
|
||||
use tx_builder::TxBuilder;
|
||||
use utils::{After, Older};
|
||||
|
||||
use crate::blockchain::{Blockchain, OfflineBlockchain, OnlineBlockchain, Progress};
|
||||
use crate::blockchain::{Blockchain, BlockchainMarker, OfflineBlockchain, Progress};
|
||||
use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils};
|
||||
use crate::descriptor::{
|
||||
get_checksum, DescriptorMeta, DescriptorScripts, ExtendedDescriptor, ExtractPolicy, Policy,
|
||||
@@ -80,9 +80,9 @@ pub type OfflineWallet<D> = Wallet<OfflineBlockchain, D>;
|
||||
/// [creating transactions](Wallet::create_tx), etc.
|
||||
///
|
||||
/// A wallet can be either "online" if the [`blockchain`](crate::blockchain) type provided
|
||||
/// implements [`OnlineBlockchain`], or "offline" if it doesn't. Offline wallets only expose
|
||||
/// implements [`Blockchain`], or "offline" [`OfflineBlockchain`] is used. Offline wallets only expose
|
||||
/// methods that don't need any interaction with the blockchain to work.
|
||||
pub struct Wallet<B: Blockchain, D: BatchDatabase> {
|
||||
pub struct Wallet<B: BlockchainMarker, D: BatchDatabase> {
|
||||
descriptor: ExtendedDescriptor,
|
||||
change_descriptor: Option<ExtendedDescriptor>,
|
||||
|
||||
@@ -95,14 +95,14 @@ pub struct Wallet<B: Blockchain, D: BatchDatabase> {
|
||||
|
||||
current_height: Option<u32>,
|
||||
|
||||
client: B,
|
||||
client: Option<B>,
|
||||
database: RefCell<D>,
|
||||
}
|
||||
|
||||
// offline actions, always available
|
||||
impl<B, D> Wallet<B, D>
|
||||
where
|
||||
B: Blockchain,
|
||||
B: BlockchainMarker,
|
||||
D: BatchDatabase,
|
||||
{
|
||||
/// Create a new "offline" wallet
|
||||
@@ -147,7 +147,7 @@ where
|
||||
|
||||
current_height: None,
|
||||
|
||||
client: B::offline(),
|
||||
client: None,
|
||||
database: RefCell::new(database),
|
||||
})
|
||||
}
|
||||
@@ -1076,7 +1076,7 @@ where
|
||||
|
||||
impl<B, D> Wallet<B, D>
|
||||
where
|
||||
B: OnlineBlockchain,
|
||||
B: Blockchain,
|
||||
D: BatchDatabase,
|
||||
{
|
||||
/// Create a new "online" wallet
|
||||
@@ -1091,7 +1091,7 @@ where
|
||||
let mut wallet = Self::new_offline(descriptor, change_descriptor, network, database)?;
|
||||
|
||||
wallet.current_height = Some(maybe_await!(client.get_height())? as u32);
|
||||
wallet.client = client;
|
||||
wallet.client = Some(client);
|
||||
|
||||
Ok(wallet)
|
||||
}
|
||||
@@ -1144,13 +1144,13 @@ where
|
||||
// TODO: what if i generate an address first and cache some addresses?
|
||||
// TODO: we should sync if generating an address triggers a new batch to be stored
|
||||
if run_setup {
|
||||
maybe_await!(self.client.setup(
|
||||
maybe_await!(self.client.as_ref().ok_or(Error::OfflineClient)?.setup(
|
||||
None,
|
||||
self.database.borrow_mut().deref_mut(),
|
||||
progress_update,
|
||||
))
|
||||
} else {
|
||||
maybe_await!(self.client.sync(
|
||||
maybe_await!(self.client.as_ref().ok_or(Error::OfflineClient)?.sync(
|
||||
None,
|
||||
self.database.borrow_mut().deref_mut(),
|
||||
progress_update,
|
||||
@@ -1159,14 +1159,18 @@ where
|
||||
}
|
||||
|
||||
/// Return a reference to the internal blockchain client
|
||||
pub fn client(&self) -> &B {
|
||||
&self.client
|
||||
pub fn client(&self) -> Option<&B> {
|
||||
self.client.as_ref()
|
||||
}
|
||||
|
||||
/// Broadcast a transaction to the network
|
||||
#[maybe_async]
|
||||
pub fn broadcast(&self, tx: Transaction) -> Result<Txid, Error> {
|
||||
maybe_await!(self.client.broadcast(&tx))?;
|
||||
maybe_await!(self
|
||||
.client
|
||||
.as_ref()
|
||||
.ok_or(Error::OfflineClient)?
|
||||
.broadcast(&tx))?;
|
||||
|
||||
Ok(tx.txid())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user