spark_rust/spark_test_utils/
mod.rs

1#![cfg(feature = "integration-tests")]
2
3use std::str::FromStr;
4
5use crate::error::SparkSdkError;
6use crate::signer::default_signer::DefaultSigner;
7use crate::signer::traits::SparkSigner;
8use crate::SparkNetwork;
9use crate::SparkSdk;
10use bitcoin::Transaction;
11use rand::rngs::OsRng;
12
13pub mod bitcoind;
14pub mod deposit;
15pub mod faucet;
16pub mod polling;
17
18pub use faucet::MempoolFaucet;
19
20// Constants for wait times
21pub const DEPOSIT_CONFIRMATION_WAIT: u64 = 30;
22pub const LIGHTNING_CONFIRMATION_WAIT: u64 = 30;
23pub const WITHDRAWAL_CONFIRMATION_WAIT: u64 = 30;
24
25pub async fn init_self_signer_wallet_with_random_seed(
26    network: SparkNetwork,
27) -> Result<(SparkSdk, Vec<u8>), SparkSdkError> {
28    let mut rng = OsRng;
29    let master_seed = bitcoin::secp256k1::SecretKey::new(&mut rng);
30
31    let signer = DefaultSigner::from_master_seed(master_seed.secret_bytes().as_ref(), network)
32        .await
33        .unwrap();
34
35    let sdk = SparkSdk::new(SparkNetwork::Regtest, signer).await?;
36
37    Ok((sdk, master_seed.secret_bytes().to_vec()))
38}
39
40pub async fn init_self_signer_wallet_with_seed(
41    network: SparkNetwork,
42    seed: Vec<u8>,
43) -> Result<SparkSdk, SparkSdkError> {
44    let signer = DefaultSigner::from_master_seed(&seed, network).await?;
45    let sdk = SparkSdk::new(network, signer).await?;
46    Ok(sdk)
47}
48
49/// Creates a test P2TR transaction with a dummy input and output.
50///
51/// This function is useful for testing purposes where we need a valid transaction
52/// with a specific output amount and address. To generate different transaction IDs that run in parallel,
53/// the function randomly selects the actual `amount_sats` value, while the chosen value is always greater than `min_amount_sats`.
54///
55/// # Arguments
56///
57/// * `txid` - The previous output transaction ID.
58/// * `vout` - The previous output transaction index.
59/// * `address` - The P2TR address to send the funds to.
60/// * `amount` - The amount of satoshis to send.
61/// * `network` - The Bitcoin network (mainnet, testnet, etc.).
62///
63/// # Returns
64///
65/// A Bitcoin transaction with a dummy input and output.
66pub fn create_test_p2tr_transaction(
67    txid: &str,
68    vout: u32,
69    address: &str,
70    amount: u64,
71    network: bitcoin::Network,
72    _include_change: bool,
73) -> Transaction {
74    let prev_txid = bitcoin::Txid::from_str(txid).unwrap();
75    let outpoint = bitcoin::OutPoint::new(prev_txid, vout);
76    let addr = bitcoin::Address::from_str(address).unwrap();
77    let addr = addr.require_network(network).unwrap();
78
79    // Calculate a conservative fee (1 sat/vbyte)
80    let fee = 200; // Approximate size of transaction in vbytes * 1 sat/vbyte
81
82    let output_amount = amount.saturating_sub(fee);
83
84    Transaction {
85        version: bitcoin::transaction::Version::TWO,
86        lock_time: bitcoin::absolute::LockTime::ZERO,
87        input: vec![bitcoin::TxIn {
88            previous_output: outpoint,
89            script_sig: bitcoin::ScriptBuf::new(),
90            sequence: bitcoin::Sequence::MAX,
91            witness: bitcoin::Witness::new(),
92        }],
93        output: vec![bitcoin::TxOut {
94            value: bitcoin::Amount::from_sat(output_amount),
95            script_pubkey: addr.script_pubkey(),
96        }],
97    }
98}
99
100/// Helper function to verify wallet balance in both local and global state
101pub async fn verify_balance(
102    sdk: &mut SparkSdk,
103    expected_balance: u64,
104    user_name: &str,
105) -> Result<(), SparkSdkError> {
106    // Check local state first
107    assert_eq!(
108        sdk.get_bitcoin_balance(),
109        expected_balance,
110        "{}'s local balance should be {} sats",
111        user_name,
112        expected_balance
113    );
114
115    // Sync with global state and check again
116    sdk.sync_wallet().await?;
117    assert_eq!(
118        sdk.get_bitcoin_balance(),
119        expected_balance,
120        "{}'s global balance should be {} sats",
121        user_name,
122        expected_balance
123    );
124
125    Ok(())
126}