use bdk_chain::{
indexed_tx_graph,
indexer::keychain_txout::KeychainTxOutIndex,
- local_chain::{
- self, ApplyHeaderError, CannotConnectError, CheckPoint, CheckPointIter, LocalChain,
- },
+ local_chain::{ApplyHeaderError, CannotConnectError, CheckPoint, CheckPointIter, LocalChain},
spk_client::{
FullScanRequest, FullScanRequestBuilder, FullScanResult, SyncRequest, SyncRequestBuilder,
SyncResult,
/// An update to [`Wallet`].
///
-/// It updates [`KeychainTxOutIndex`], [`bdk_chain::TxGraph`] and [`local_chain::LocalChain`] atomically.
+/// It updates [`KeychainTxOutIndex`], [`bdk_chain::TxGraph`] and [`LocalChain`] atomically.
#[derive(Debug, Clone, Default)]
pub struct Update {
/// Contains the last active derivation indices per keychain (`K`), which is used to update the
pub tx_update: TxUpdate<ConfirmationBlockTime>,
/// Update for the wallet's internal [`LocalChain`].
- ///
- /// [`LocalChain`]: local_chain::LocalChain
pub chain: Option<CheckPoint>,
}
})
}
- /// Add a new checkpoint to the wallet's internal view of the chain.
- ///
- /// Returns whether anything changed with the insertion (e.g. `false` if checkpoint was already
- /// there).
- ///
- /// **WARNING**: You must persist the changes resulting from one or more calls to this method
- /// if you need the inserted checkpoint data to be reloaded after closing the wallet.
- /// See [`Wallet::reveal_next_address`].
- pub fn insert_checkpoint(
- &mut self,
- block_id: BlockId,
- ) -> Result<bool, local_chain::AlterCheckPointError> {
- let changeset = self.chain.insert_block(block_id)?;
- let changed = !changeset.is_empty();
- self.stage.merge(changeset.into());
- Ok(changed)
- }
-
- /// Add a transaction to the wallet's internal view of the chain. This stages the change,
- /// you must persist it later.
- ///
- /// This method inserts the given `tx` and returns whether anything changed after insertion,
- /// which will be false if the same transaction already exists in the wallet's transaction
- /// graph. Any changes are staged but not committed.
- ///
- /// # Note
- ///
- /// By default the inserted `tx` won't be considered "canonical" because it's not known
- /// whether the transaction exists in the best chain. To know whether it exists, the tx
- /// must be broadcast to the network and the wallet synced via a chain source.
- pub fn insert_tx<T: Into<Arc<Transaction>>>(&mut self, tx: T) -> bool {
- let mut changeset = ChangeSet::default();
- changeset.merge(self.indexed_graph.insert_tx(tx).into());
- let ret = !changeset.is_empty();
- self.stage.merge(changeset);
- ret
- }
-
/// Iterate over the transactions in the wallet.
pub fn transactions(&self) -> impl Iterator<Item = WalletTx> + '_ {
self.indexed_graph
thread_safe::<Wallet>(); // compiles only if true
}
-#[test]
-fn test_insert_tx_balance_and_utxos() {
- // creating many txs has no effect on the wallet's available utxos
- let (mut wallet, _) = get_funded_wallet_single(get_test_tr_single_sig_xprv());
- let addr = Address::from_str("bcrt1qc6fweuf4xjvz4x3gx3t9e0fh4hvqyu2qw4wvxm")
- .unwrap()
- .assume_checked();
-
- let unspent: Vec<_> = wallet.list_unspent().collect();
- assert!(!unspent.is_empty());
-
- let balance = wallet.balance().total();
- let fee = Amount::from_sat(143);
- let amt = balance - fee;
-
- for _ in 0..3 {
- let mut builder = wallet.build_tx();
- builder.add_recipient(addr.script_pubkey(), amt);
- let mut psbt = builder.finish().unwrap();
- assert!(wallet.sign(&mut psbt, SignOptions::default()).unwrap());
- let tx = psbt.extract_tx().unwrap();
- let _ = wallet.insert_tx(tx);
- }
- assert_eq!(wallet.list_unspent().collect::<Vec<_>>(), unspent);
- assert_eq!(wallet.balance().confirmed, balance);
-
- // manually setting a tx last_seen will consume the wallet's available utxos
- let addr = Address::from_str("bcrt1qfjg5lv3dvc9az8patec8fjddrs4aqtauadnagr")
- .unwrap()
- .assume_checked();
- let mut builder = wallet.build_tx();
- builder.add_recipient(addr.script_pubkey(), amt);
- let mut psbt = builder.finish().unwrap();
- assert!(wallet.sign(&mut psbt, SignOptions::default()).unwrap());
- let tx = psbt.extract_tx().unwrap();
- let txid = tx.compute_txid();
- let _ = wallet.insert_tx(tx);
- insert_seen_at(&mut wallet, txid, 2);
- assert!(wallet.list_unspent().next().is_none());
- assert_eq!(wallet.balance().total().to_sat(), 0);
-}
-
#[test]
fn single_descriptor_wallet_can_create_tx_and_receive_change() {
// create single descriptor wallet and fund it