feat(wallet)!: add NonEmptyDatabase
variant to NewError
`NewError` is the error type when constructing a wallet with `Wallet::new`. We want this to return an error when the database already contains data (in which case, the caller should use `load` or `new_or_load`).
This commit is contained in:
parent
9cc03324f4
commit
a1d34afa24
@ -237,6 +237,7 @@ impl Wallet {
|
||||
network: Network,
|
||||
) -> Result<Self, DescriptorError> {
|
||||
Self::new(descriptor, change_descriptor, (), network).map_err(|e| match e {
|
||||
NewError::NonEmptyDatabase => unreachable!("mock-database cannot have data"),
|
||||
NewError::Descriptor(e) => e,
|
||||
NewError::Write(_) => unreachable!("mock-write must always succeed"),
|
||||
})
|
||||
@ -251,6 +252,7 @@ impl Wallet {
|
||||
) -> Result<Self, crate::descriptor::DescriptorError> {
|
||||
Self::new_with_genesis_hash(descriptor, change_descriptor, (), network, genesis_hash)
|
||||
.map_err(|e| match e {
|
||||
NewError::NonEmptyDatabase => unreachable!("mock-database cannot have data"),
|
||||
NewError::Descriptor(e) => e,
|
||||
NewError::Write(_) => unreachable!("mock-write must always succeed"),
|
||||
})
|
||||
@ -288,6 +290,8 @@ where
|
||||
/// [`new_with_genesis_hash`]: Wallet::new_with_genesis_hash
|
||||
#[derive(Debug)]
|
||||
pub enum NewError<W> {
|
||||
/// Database already has data.
|
||||
NonEmptyDatabase,
|
||||
/// There was problem with the passed-in descriptor(s).
|
||||
Descriptor(crate::descriptor::DescriptorError),
|
||||
/// We were unable to write the wallet's data to the persistence backend.
|
||||
@ -300,6 +304,10 @@ where
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
NewError::NonEmptyDatabase => write!(
|
||||
f,
|
||||
"database already has data - use `load` or `new_or_load` methods instead"
|
||||
),
|
||||
NewError::Descriptor(e) => e.fmt(f),
|
||||
NewError::Write(e) => e.fmt(f),
|
||||
}
|
||||
@ -446,13 +454,18 @@ impl<D> Wallet<D> {
|
||||
pub fn new_with_genesis_hash<E: IntoWalletDescriptor>(
|
||||
descriptor: E,
|
||||
change_descriptor: Option<E>,
|
||||
db: D,
|
||||
mut db: D,
|
||||
network: Network,
|
||||
genesis_hash: BlockHash,
|
||||
) -> Result<Self, NewError<D::WriteError>>
|
||||
where
|
||||
D: PersistBackend<ChangeSet>,
|
||||
{
|
||||
if let Ok(changeset) = db.load_from_persistence() {
|
||||
if changeset.is_some() {
|
||||
return Err(NewError::NonEmptyDatabase);
|
||||
}
|
||||
}
|
||||
let secp = Secp256k1::new();
|
||||
let (chain, chain_changeset) = LocalChain::from_genesis_hash(genesis_hash);
|
||||
let mut index = KeychainTxOutIndex::<KeychainKind>::default();
|
||||
@ -615,6 +628,9 @@ impl<D> Wallet<D> {
|
||||
genesis_hash,
|
||||
)
|
||||
.map_err(|e| match e {
|
||||
NewError::NonEmptyDatabase => {
|
||||
unreachable!("database is already checked to have no data")
|
||||
}
|
||||
NewError::Descriptor(e) => NewOrLoadError::Descriptor(e),
|
||||
NewError::Write(e) => NewOrLoadError::Write(e),
|
||||
}),
|
||||
|
@ -7,8 +7,8 @@ use bdk::signer::{SignOptions, SignerError};
|
||||
use bdk::wallet::coin_selection::{self, LargestFirstCoinSelection};
|
||||
use bdk::wallet::error::CreateTxError;
|
||||
use bdk::wallet::tx_builder::AddForeignUtxoError;
|
||||
use bdk::wallet::AddressIndex::*;
|
||||
use bdk::wallet::{AddressIndex, AddressInfo, Balance, Wallet};
|
||||
use bdk::wallet::{AddressIndex::*, NewError};
|
||||
use bdk::{FeeRate, KeychainKind};
|
||||
use bdk_chain::COINBASE_MATURITY;
|
||||
use bdk_chain::{BlockId, ConfirmationTime};
|
||||
@ -92,6 +92,13 @@ fn load_recovers_wallet() {
|
||||
wallet_spk_index.last_revealed_indices()
|
||||
);
|
||||
}
|
||||
|
||||
// `new` can only be called on empty db
|
||||
{
|
||||
let db = bdk_file_store::Store::open(DB_MAGIC, &file_path).expect("must recover db");
|
||||
let result = Wallet::new(get_test_tr_single_sig_xprv(), None, db, Network::Testnet);
|
||||
assert!(matches!(result, Err(NewError::NonEmptyDatabase)));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
Loading…
x
Reference in New Issue
Block a user