#[cfg(test)]
mod tests {
use super::*;
use crate::core::scanner::{WalletScanner, OpenOrdersAccountInfo};
use solana_account_decoder::UiAccountEncoding;
use base64::{Engine as _, engine::general_purpose};
#[test]
fn test_parse_empty_open_orders_account() {
let scanner = WalletScanner::new();
let mut account_data = vec![0u8; 104];
account_data[0..8].copy_from_slice(&[1, 0, 0, 0, 0, 0, 0, 0]);
let dummy_market = [2u8; 32];
account_data[8..40].copy_from_slice(&dummy_market);
let dummy_owner = [3u8; 32];
account_data[40..72].copy_from_slice(&dummy_owner);
let encoded_data = general_purpose::STANDARD.encode(&account_data);
let result = scanner.parse_open_orders_account_from_binary(&encoded_data, &UiAccountEncoding::Base64);
assert!(result.is_ok(), "Failed to parse OpenOrders account: {:?}", result.err());
let open_orders = result.unwrap();
assert_eq!(open_orders.base_token_free, 0);
assert_eq!(open_orders.base_token_total, 0);
assert_eq!(open_orders.quote_token_free, 0);
assert_eq!(open_orders.quote_token_total, 0);
}
#[test]
fn test_parse_non_empty_open_orders_account() {
let scanner = WalletScanner::new();
let mut account_data = vec![0u8; 104];
account_data[0..8].copy_from_slice(&[1, 0, 0, 0, 0, 0, 0, 0]);
account_data[8..40].copy_from_slice(&[2u8; 32]);
account_data[40..72].copy_from_slice(&[3u8; 32]);
account_data[72..80].copy_from_slice(&1000u64.to_le_bytes());
account_data[96..104].copy_from_slice(&500u64.to_le_bytes());
let encoded_data = general_purpose::STANDARD.encode(&account_data);
let result = scanner.parse_open_orders_account_from_binary(&encoded_data, &UiAccountEncoding::Base64);
assert!(result.is_ok(), "Failed to parse OpenOrders account: {:?}", result.err());
let open_orders = result.unwrap();
assert_eq!(open_orders.base_token_free, 1000);
assert_eq!(open_orders.base_token_total, 0);
assert_eq!(open_orders.quote_token_free, 0);
assert_eq!(open_orders.quote_token_total, 500);
}
#[test]
fn test_open_orders_account_insufficient_data() {
let scanner = WalletScanner::new();
let short_data = vec![0u8; 50]; let encoded_data = general_purpose::STANDARD.encode(&short_data);
let result = scanner.parse_open_orders_account_from_binary(&encoded_data, &UiAccountEncoding::Base64);
assert!(result.is_err(), "Should have failed with insufficient data");
if let Err(e) = result {
assert!(matches!(e, crate::core::SolanaRecoverError::InternalError(msg)
if msg.contains("Invalid OpenOrders account data length")));
}
}
#[test]
fn test_open_orders_account_invalid_encoding() {
let scanner = WalletScanner::new();
let invalid_base64 = "invalid_base64_string!!!";
let result = scanner.parse_open_orders_account_from_binary(invalid_base64, &UiAccountEncoding::Base64);
assert!(result.is_err(), "Should have failed with invalid base64");
}
#[test]
fn test_openbook_program_ids() {
use std::str::FromStr;
let openbook_v2 = Pubkey::from_str("opnb2vDkSQsqmY24zQ4DDEZf1V3oEisPZ5bEErLNRsA").unwrap();
let serum_dex = Pubkey::from_str("srmqPvvk92GzrcCbKgSGx3mFHTEQuoE3jUuAM6gEKrP").unwrap();
assert_ne!(openbook_v2, Pubkey::default());
assert_ne!(serum_dex, Pubkey::default());
assert_ne!(openbook_v2, serum_dex);
}
#[test]
fn test_open_orders_safety_validation() {
let test_cases = vec![
(0, 0, 0, 0, true), (1, 0, 0, 0, false), (0, 1, 0, 0, false), (0, 0, 1, 0, false), (0, 0, 0, 1, false), (1, 1, 1, 1, false), ];
for (base_free, base_total, quote_free, quote_total, expected_recoverable) in test_cases {
let open_orders = OpenOrdersAccountInfo {
base_token_free: base_free,
base_token_total: base_total,
quote_token_free: quote_free,
quote_token_total: quote_total,
};
let is_recoverable = open_orders.base_token_free == 0 &&
open_orders.quote_token_free == 0 &&
open_orders.base_token_total == 0 &&
open_orders.quote_token_total == 0;
assert_eq!(is_recoverable, expected_recoverable,
"Failed for base_free={}, base_total={}, quote_free={}, quote_total={}",
base_free, base_total, quote_free, quote_total);
}
}
}