- Fix get_next_address_index: use try_get::<i32> for PG SERIAL/INTEGER columns - Fix search_tx: use try_get::<i32> for PG status column - Fix execute_insert: parse locktime (String→i64) and in_vout (String→i32) before binding to PG INTEGER columns - Fix execute_insert: bind tbl_out vout as i32, amount as String for PG - Fix save_new_address: cast xpub i64 to i32 for PG INTEGER column - Fix get_pending_txs: cast i64 bind params to i32, use try_get::<i32> for reads - Fix get_stats: use try_get::<i32> for all numeric PG INTEGER columns - Add trace logging in parse_request_transactions for xpub address matching - Add trace logging in get_all_addresses_by_xpub for query debugging
71 lines
2.3 KiB
Rust
71 lines
2.3 KiB
Rust
use bal_server::db::{DatabasePool, create_database, get_all_addresses_by_xpub, open_database};
|
|
|
|
async fn setup_db_with_xpub() -> DatabasePool {
|
|
let pool = open_database("sqlite", "sqlite::memory:").await.unwrap();
|
|
create_database(&pool).await.unwrap();
|
|
|
|
if let DatabasePool::SQLite(p) = &pool {
|
|
sqlx::query("INSERT INTO tbl_xpub(id, network, xpub) VALUES(1, 'testnet', 'tpub_test')")
|
|
.execute(p)
|
|
.await
|
|
.unwrap();
|
|
|
|
for addr in ["addr1", "addr2", "addr3"] {
|
|
sqlx::query("INSERT INTO tbl_address(address, path, xpub) VALUES(?, 'm/0/1', 1)")
|
|
.bind(addr)
|
|
.execute(p)
|
|
.await
|
|
.unwrap();
|
|
}
|
|
}
|
|
|
|
pool
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_get_all_addresses_by_xpub_returns_known() {
|
|
let pool = setup_db_with_xpub().await;
|
|
let addresses = get_all_addresses_by_xpub(&pool, "tpub_test").await.unwrap();
|
|
assert!(addresses.contains("addr1"));
|
|
assert!(addresses.contains("addr2"));
|
|
assert!(addresses.contains("addr3"));
|
|
assert_eq!(addresses.len(), 3);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_get_all_addresses_by_xpub_empty_for_missing() {
|
|
let pool = setup_db_with_xpub().await;
|
|
let addresses = get_all_addresses_by_xpub(&pool, "tpub_nonexistent")
|
|
.await
|
|
.unwrap();
|
|
assert!(addresses.is_empty());
|
|
}
|
|
|
|
#[test]
|
|
fn test_network_unknown_returns_404() {
|
|
let networks = ["bitcoin", "testnet", "testnet4", "signet", "regtest"];
|
|
for n in networks {
|
|
assert!(networks.contains(&n), "{} should be a valid network", n);
|
|
}
|
|
assert!(
|
|
!networks.contains(&"attacker"),
|
|
"attacker should not be a valid network"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_txid_validation_is_hex_64() {
|
|
let valid = "abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890";
|
|
assert!(valid.chars().all(|c| c.is_ascii_hexdigit()));
|
|
assert_eq!(valid.len(), 64);
|
|
|
|
let too_short = "abcdef1234567890";
|
|
assert!(too_short.len() != 64);
|
|
|
|
let non_hex = "abcdef1234567890abcdef1234567890abcdef1234567890abcdef123456789g";
|
|
assert!(!non_hex.chars().all(|c| c.is_ascii_hexdigit()));
|
|
|
|
let with_dot = ".abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890";
|
|
assert!(!with_dot.chars().all(|c| c.is_ascii_hexdigit()));
|
|
}
|