Skip to content

Commit

Permalink
wallet: separate indexer from wallet structure
Browse files Browse the repository at this point in the history
  • Loading branch information
dr-orlovsky committed Jul 4, 2024
1 parent e6a02cf commit aecefa2
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 77 deletions.
66 changes: 28 additions & 38 deletions src/cli/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ use strict_encoding::Ident;
use crate::cli::{
Config, DescrStdOpts, DescriptorOpts, ExecError, GeneralOpts, ResolverOpt, WalletOpts,
};
use crate::indexers::AnyIndexerError;
use crate::{AnyIndexer, MayError, Wallet};

/// Command-line arguments
Expand Down Expand Up @@ -96,49 +95,18 @@ impl<C: Clone + Eq + Debug + Subcommand, O: DescriptorOpts> Args<C, O> {
pub fn bp_wallet<D: Descriptor>(
&self,
conf: &Config,
) -> Result<Wallet<XpubDerivable, D, AnyIndexer>, ExecError>
) -> Result<Wallet<XpubDerivable, D>, ExecError>
where
for<'de> D: From<O::Descr> + serde::Serialize + serde::Deserialize<'de>,
{
fn print_errors(errors: Option<Vec<AnyIndexerError>>) {
if let Some(errors) = errors {
eprintln!(" partial, some requests has failed:");
for err in errors {
eprintln!("- {err}");
}
} else {
eprintln!(" success");
}
}

eprint!("Loading descriptor");
let mut sync = self.sync || self.wallet.descriptor_opts.is_some();

let indexer = match (&self.resolver.esplora, &self.resolver.electrum) {
(None, Some(url)) => AnyIndexer::Electrum(Box::new(electrum::Client::new(url)?)),
(Some(url), None) => {
AnyIndexer::Esplora(Box::new(esplora::Builder::new(url).build_blocking()?))
}
_ if sync => {
eprintln!(
" - error: no blockchain indexer specified; use either --esplora or \
--electrum argument"
);
exit(1);
}
_ => AnyIndexer::None,
};

let mut wallet: Wallet<XpubDerivable, D, AnyIndexer> =
let mut wallet: Wallet<XpubDerivable, D> =
if let Some(d) = self.wallet.descriptor_opts.descriptor() {
eprintln!(" from command-line argument");
eprint!("Syncing");
let MayError {
ok: wallet,
err: errors,
} = Wallet::new_layer1(d.into(), self.general.network, indexer);
print_errors(errors);
wallet
Wallet::new_layer1(d.into(), self.general.network)
} else {
let path = if let Some(wallet_path) = self.wallet.wallet_path.clone() {
eprint!(" from specified wallet directory ... ");
Expand All @@ -153,7 +121,7 @@ impl<C: Clone + Eq + Debug + Subcommand, O: DescriptorOpts> Args<C, O> {
eprint!(" from wallet {wallet_name} ... ");
self.general.wallet_dir(wallet_name)
};
let (wallet, warnings) = Wallet::load(&path, true, indexer, false)?;
let (wallet, warnings) = Wallet::load(&path, true)?;
if warnings.is_empty() {
eprintln!("success");
} else {
Expand All @@ -167,9 +135,31 @@ impl<C: Clone + Eq + Debug + Subcommand, O: DescriptorOpts> Args<C, O> {
};

if sync {
let indexer = match (&self.resolver.esplora, &self.resolver.electrum) {
(None, Some(url)) => AnyIndexer::Electrum(Box::new(electrum::Client::new(url)?)),
(Some(url), None) => {
AnyIndexer::Esplora(Box::new(esplora::Builder::new(url).build_blocking()?))
}
_ => {
eprintln!(
" - error: no blockchain indexer specified; use either --esplora or \
--electrum argument"
);
exit(1);
}
};
eprint!("Syncing");
let MayError { err, .. } = wallet.update();
print_errors(err);
if let MayError {
err: Some(errors), ..
} = wallet.update(&indexer)
{
eprintln!(" partial, some requests has failed:");
for err in errors {
eprintln!("- {err}");
}
} else {
eprintln!(" success");
}
}

Ok(wallet)
Expand Down
3 changes: 0 additions & 3 deletions src/indexers/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ pub enum AnyIndexer {
#[from]
/// Esplora indexer
Esplora(Box<esplora::blocking::BlockingClient>),
None,
}

#[allow(clippy::large_enum_variant)]
Expand Down Expand Up @@ -74,7 +73,6 @@ impl Indexer for AnyIndexer {
err: result.err.map(|v| v.into_iter().map(|e| e.into()).collect()),
}
}
_ => unreachable!(),
}
}

Expand All @@ -100,7 +98,6 @@ impl Indexer for AnyIndexer {
err: result.err.map(|v| v.into_iter().map(|e| e.into()).collect()),
}
}
_ => unreachable!(),
}
}
}
Expand Down
55 changes: 19 additions & 36 deletions src/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,28 +260,27 @@ pub trait Save {
}

#[derive(Clone, Eq, PartialEq, Debug)]
pub struct Wallet<K, D: Descriptor<K>, I: Indexer, L2: Layer2 = NoLayer2>
pub struct Wallet<K, D: Descriptor<K>, L2: Layer2 = NoLayer2>
where Self: Save
{
descr: WalletDescr<K, D, L2::Descr>,
data: WalletData<L2::Data>,
cache: WalletCache<L2::Cache>,
layer2: L2,
indexer: I,
#[cfg(feature = "fs")]
fs: Option<FsConfig>,
dirty: bool,
}

impl<K, D: Descriptor<K>, I: Indexer, L2: Layer2> Deref for Wallet<K, D, I, L2>
impl<K, D: Descriptor<K>, L2: Layer2> Deref for Wallet<K, D, L2>
where Self: Save
{
type Target = WalletDescr<K, D, L2::Descr>;

fn deref(&self) -> &Self::Target { &self.descr }
}

impl<K, D: Descriptor<K>, I: Indexer, L2: Layer2> PsbtConstructor for Wallet<K, D, I, L2>
impl<K, D: Descriptor<K>, L2: Layer2> PsbtConstructor for Wallet<K, D, L2>
where Self: Save
{
type Key = K;
Expand All @@ -308,43 +307,33 @@ where Self: Save
}
}

impl<K, D: Descriptor<K>, I: Indexer> Wallet<K, D, I>
impl<K, D: Descriptor<K>> Wallet<K, D>
where Self: Save
{
pub fn new_layer1(descr: D, network: Network, indexer: I) -> MayError<Self, Vec<I::Error>> {
let mut wallet = Wallet {
pub fn new_layer1(descr: D, network: Network) -> Self {
Wallet {
descr: WalletDescr::new_standard(descr, network),
data: empty!(),
cache: WalletCache::new(),
layer2: None,
indexer,
dirty: false,
fs: None,
};
wallet.update().map(|_| wallet)
}
}
}

impl<K, D: Descriptor<K>, I: Indexer, L2: Layer2> Wallet<K, D, I, L2>
impl<K, D: Descriptor<K>, L2: Layer2> Wallet<K, D, L2>
where Self: Save
{
pub fn new_layer2(
descr: D,
l2_descr: L2::Descr,
layer2: L2,
network: Network,
indexer: I,
) -> MayError<Self, Vec<I::Error>> {
let mut wallet = Wallet {
pub fn new_layer2(descr: D, l2_descr: L2::Descr, layer2: L2, network: Network) -> Self {
Wallet {
descr: WalletDescr::new_layer2(descr, l2_descr, network),
data: empty!(),
cache: WalletCache::new(),
layer2,
indexer,
dirty: false,
fs: None,
};
wallet.update().map(|_| wallet)
}
}

#[cfg(feature = "fs")]
Expand All @@ -365,11 +354,11 @@ where Self: Save
self.set_dirty();
}

pub fn update(&mut self) -> MayError<(), Vec<I::Error>> {
pub fn update<I: Indexer>(&mut self, indexer: &I) -> MayError<(), Vec<I::Error>> {
// Not yet implemented:
// self.cache.update::<B, K, D, L2>(&self.descr, &self.indexer)

WalletCache::with::<_, K, _, L2>(&self.descr, &self.indexer).map(|cache| {
WalletCache::with::<_, K, _, L2>(&self.descr, indexer).map(|cache| {
self.cache = cache;
self.set_dirty();
})
Expand Down Expand Up @@ -547,7 +536,7 @@ pub(crate) mod fs {
}
}

impl<K, D: Descriptor<K>, I: Indexer, L2: Layer2> Wallet<K, D, I, L2>
impl<K, D: Descriptor<K>, L2: Layer2> Wallet<K, D, L2>
where
for<'de> WalletDescr<K, D>: serde::Serialize + serde::Deserialize<'de>,
for<'de> D: serde::Serialize + serde::Deserialize<'de>,
Expand All @@ -559,8 +548,6 @@ pub(crate) mod fs {
pub fn load(
path: &Path,
autosave: bool,
indexer: I,
update: bool,
) -> Result<(Self, Vec<Warning>), LoadError<L2::LoadError>> {
let mut warnings = Vec::new();

Expand Down Expand Up @@ -589,23 +576,19 @@ pub(crate) mod fs {
autosave,
});

let mut wallet = Wallet::<K, D, I, L2> {
let wallet = Wallet::<K, D, L2> {
descr,
data,
cache,
layer2,
indexer,
dirty: false,
fs,
};
if update {
wallet.update();
}
Ok((wallet, warnings))
}
}

impl<K, D: Descriptor<K>, I: Indexer, L2: Layer2> Save for Wallet<K, D, I, L2>
impl<K, D: Descriptor<K>, L2: Layer2> Save for Wallet<K, D, L2>
where
for<'de> WalletDescr<K, D>: serde::Serialize + serde::Deserialize<'de>,
for<'de> D: serde::Serialize + serde::Deserialize<'de>,
Expand Down Expand Up @@ -633,8 +616,8 @@ pub(crate) mod fs {
}
}

impl<K, D: Descriptor<K>, I: Indexer, L2: Layer2> Drop for Wallet<K, D, I, L2>
where Wallet<K, D, I, L2>: Save
impl<K, D: Descriptor<K>, L2: Layer2> Drop for Wallet<K, D, L2>
where Wallet<K, D, L2>: Save
{
fn drop(&mut self) {
if self.dirty && self.fs.as_ref().map(|fs| fs.autosave).unwrap_or_default() {
Expand All @@ -645,7 +628,7 @@ pub(crate) mod fs {
}

#[cfg(not(feature = "fs"))]
impl<K, D: Descriptor<K>, I: Indexer, L2: Layer2> Save for Wallet<K, D, I, L2> {
impl<K, D: Descriptor<K>, L2: Layer2> Save for Wallet<K, D, L2> {
type SaveErr = ();

fn save(&self) -> Result<bool, Self::SaveErr> {
Expand Down

0 comments on commit aecefa2

Please sign in to comment.