Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 62 additions & 1 deletion bdk-ffi/src/tests/wallet.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
use crate::bitcoin::{Network, NetworkKind};
use crate::bitcoin::{Network, NetworkKind, Transaction};
use crate::descriptor::Descriptor;
use crate::store::Persister;
use crate::types::{ChainPosition, UnconfirmedTx};
use crate::wallet::Wallet;

use bdk_wallet::bitcoin::absolute::LockTime;
use bdk_wallet::bitcoin::transaction::Version;
use bdk_wallet::bitcoin::{
Amount as BdkAmount, OutPoint as BdkOutPoint, ScriptBuf, Sequence,
Transaction as BdkTransaction, TxIn as BdkTxIn, TxOut as BdkTxOut, Txid as BdkTxid, Witness,
};
use bdk_wallet::KeychainKind;

use std::str::FromStr;
use std::sync::Arc;

const EXTERNAL_DESCRIPTOR: &str = "wpkh(tprv8ZgxMBicQKsPf2qfrEygW6fdYseJDDrVnDv26PH5BHdvSuG6ecCbHqLVof9yZcMoM31z9ur3tTYbSnr1WBqbGX97CbXcmp5H6qeMpyvx35B/84h/1h/1h/0/*)";
Expand Down Expand Up @@ -35,6 +43,33 @@ fn build_wallet() -> Wallet {
.unwrap()
}

fn unconfirmed_tx_to_wallet(wallet: &Wallet) -> Arc<Transaction> {
let address_info = wallet.reveal_next_address(KeychainKind::External);
let script_pubkey = ScriptBuf::from_bytes(address_info.address.script_pubkey().to_bytes());
let tx = BdkTransaction {
version: Version::TWO,
lock_time: LockTime::ZERO,
input: vec![BdkTxIn {
previous_output: BdkOutPoint {
txid: BdkTxid::from_str(
"0101010101010101010101010101010101010101010101010101010101010101",
)
.unwrap(),
vout: 0,
},
script_sig: ScriptBuf::new(),
sequence: Sequence::MAX,
witness: Witness::default(),
}],
output: vec![BdkTxOut {
value: BdkAmount::from_sat(50_000),
script_pubkey,
}],
};

Arc::new(Transaction::from(tx))
}

#[test]
fn test_create_wallet() {
let wallet = build_wallet();
Expand Down Expand Up @@ -150,3 +185,29 @@ fn test_create_two_path_wallet() {
assert_eq!(wallet.derivation_index(KeychainKind::External), Some(0));
assert_eq!(wallet.derivation_index(KeychainKind::Internal), Some(0));
}

#[test]
fn test_chain_position_preserves_first_and_last_seen() {
let wallet = build_wallet();
let tx = unconfirmed_tx_to_wallet(&wallet);

wallet.apply_unconfirmed_txs(vec![UnconfirmedTx {
tx: tx.clone(),
last_seen: 10,
}]);
wallet.apply_unconfirmed_txs(vec![UnconfirmedTx { tx, last_seen: 20 }]);

let transactions = wallet.transactions();

assert_eq!(transactions.len(), 1);
match &transactions[0].chain_position {
ChainPosition::Unconfirmed {
first_seen,
last_seen,
} => {
assert_eq!(*first_seen, Some(10));
assert_eq!(*last_seen, Some(20));
}
other => panic!("expected unconfirmed chain position, got {:?}", other),
}
}
22 changes: 18 additions & 4 deletions bdk-ffi/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,18 @@ pub enum ChainPosition {
/// or equal to this child TXID.
transitively: Option<Arc<Txid>>,
},
/// The transaction was last seen in the mempool at this timestamp.
Unconfirmed { timestamp: Option<u64> },
/// The chain data is not confirmed.
Unconfirmed {
/// When the chain data was first seen in the mempool.
///
/// This value will be `None` if the chain data was never seen in the mempool.
first_seen: Option<u64>,
/// When the chain data is last seen in the mempool.
///
/// This value will be `None` if the chain data was never seen in the mempool and only seen
/// in a conflicting chain.
last_seen: Option<u64>,
},
}

impl From<BdkChainPosition<BdkConfirmationBlockTime>> for ChainPosition {
Expand All @@ -100,8 +110,12 @@ impl From<BdkChainPosition<BdkConfirmationBlockTime>> for ChainPosition {
transitively: transitively.map(|t| Arc::new(Txid(t))),
}
}
BdkChainPosition::Unconfirmed { last_seen, .. } => ChainPosition::Unconfirmed {
timestamp: last_seen,
BdkChainPosition::Unconfirmed {
first_seen,
last_seen,
} => ChainPosition::Unconfirmed {
first_seen,
last_seen,
},
}
}
Expand Down
4 changes: 2 additions & 2 deletions bdk-ffi/src/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -534,8 +534,8 @@ impl Wallet {
/// in the best chain.
/// * The [`ChainPosition`] of the transaction in the best chain - whether the transaction is
/// confirmed or unconfirmed. If the transaction is confirmed, the anchor which proves the
/// confirmation is provided. If the transaction is unconfirmed, the unix timestamp of when
/// the transaction was last seen in the mempool is provided.
/// confirmation is provided. If the transaction is unconfirmed, the unix timestamps of when
/// the transaction was first and last seen in the mempool are provided.
pub fn get_tx(&self, txid: Arc<Txid>) -> Result<Option<CanonicalTx>, TxidParseError> {
Ok(self.get_wallet().get_tx(txid.0).map(|tx| tx.into()))
}
Expand Down
Loading