mod helpers;
use dig_coinstore::{ChiaCoinRecord, CoinId, CoinRecord, CoinState};
#[test]
fn vv_req_api_002_all_fields_accessible() {
let coin = helpers::test_coin(1, 2, 3);
let r = CoinRecord {
coin,
confirmed_height: 10,
spent_height: Some(20),
coinbase: true,
timestamp: 1_700_000_001,
ff_eligible: true,
};
assert_eq!(r.confirmed_height, 10);
assert_eq!(r.spent_height, Some(20));
assert!(r.coinbase);
assert_eq!(r.timestamp, 1_700_000_001);
assert!(r.ff_eligible);
assert_eq!(r.coin, coin);
}
#[test]
fn vv_req_api_002_new_creates_unspent_ff_false() {
let coin = helpers::test_coin(7, 8, 9);
let r = CoinRecord::new(coin, 100, 1_234, false);
assert!(!r.is_spent(), "new() must leave spent_height unset");
assert_eq!(r.spent_height, None);
assert!(!r.ff_eligible);
assert_eq!(r.confirmed_height, 100);
assert_eq!(r.timestamp, 1_234);
}
#[test]
fn vv_req_api_002_spend_marks_spent() {
let mut r = CoinRecord::new(helpers::test_coin(1, 1, 1), 1, 0, false);
r.spend(500);
assert_eq!(r.spent_height, Some(500));
assert!(r.is_spent());
}
#[test]
fn vv_req_api_002_coin_id_matches_coin() {
let coin = helpers::test_coin(11, 22, 33);
let r = CoinRecord::new(coin, 5, 0, false);
assert_eq!(r.coin_id(), coin.coin_id());
let _: CoinId = r.coin_id();
}
#[test]
fn vv_req_api_002_to_coin_state_maps_heights() {
let coin = helpers::test_coin(3, 3, 3);
let mut r = CoinRecord::new(coin, 42, 0, false);
r.spend(100);
let cs: CoinState = r.to_coin_state();
assert_eq!(cs.coin, coin);
assert_eq!(cs.created_height, Some(42));
assert_eq!(cs.spent_height, Some(100));
}
#[test]
fn vv_req_api_002_clone_round_trip_fields() {
let r1 = CoinRecord::new(helpers::test_coin(9, 9, 9), 9, 9, true);
let r2 = r1.clone();
assert_eq!(r1, r2);
}
#[test]
fn vv_req_api_002_serde_bincode_roundtrip() {
let original = CoinRecord::new(helpers::test_coin(4, 5, 6), 77, 88, false);
let bytes = bincode::serialize(&original).expect("bincode serialize");
let back: CoinRecord = bincode::deserialize(&bytes).expect("bincode deserialize");
assert_eq!(original, back);
}
#[test]
fn vv_req_api_002_double_spend_overwrites_height() {
let mut r = CoinRecord::new(helpers::test_coin(1, 2, 3), 1, 0, false);
r.spend(10);
r.spend(99);
assert_eq!(r.spent_height, Some(99));
}
#[test]
fn vv_req_api_002_to_coin_state_u32_boundary() {
let h = u64::from(u32::MAX);
let r = CoinRecord::new(helpers::test_coin(1, 1, 1), h, 0, false);
let cs = r.to_coin_state();
assert_eq!(cs.created_height, Some(u32::MAX));
}
#[test]
fn vv_req_api_002_from_chia_unspent() {
let coin = helpers::test_coin(5, 5, 5);
let chia = ChiaCoinRecord::new(coin, 300, 0, false, 1_111);
let r = CoinRecord::from_chia_coin_record(chia);
assert_eq!(r.spent_height, None);
assert!(!r.is_spent());
assert!(!r.ff_eligible);
assert_eq!(r.confirmed_height, 300);
assert_eq!(r.timestamp, 1_111);
assert_eq!(r.coin, coin);
}
#[test]
fn vv_req_api_002_from_chia_spent() {
let coin = helpers::test_coin(6, 6, 6);
let chia = ChiaCoinRecord::new(coin, 1, 500, false, 2_222);
let r = CoinRecord::from_chia_coin_record(chia);
assert_eq!(r.spent_height, Some(500));
assert!(r.is_spent());
}
#[test]
fn vv_req_api_002_to_chia_coin_record() {
let coin = helpers::test_coin(7, 7, 7);
let mut r = CoinRecord::new(coin, 50, 0, true);
r.spend(60);
let chia = r.to_chia_coin_record();
assert_eq!(chia.confirmed_block_index, 50);
assert_eq!(chia.spent_block_index, 60);
assert!(chia.coinbase);
assert_eq!(chia.coin, coin);
}
#[test]
fn vv_req_api_002_chia_roundtrip_resets_ff_eligible() {
let coin = helpers::test_coin(8, 8, 8);
let mut native = CoinRecord::new(coin, 1000, 0, false);
native.ff_eligible = true;
native.spend(1001);
let roundtrip = CoinRecord::from_chia_coin_record(native.to_chia_coin_record());
assert_eq!(roundtrip.coin, native.coin);
assert_eq!(roundtrip.confirmed_height, native.confirmed_height);
assert_eq!(roundtrip.spent_height, native.spent_height);
assert_eq!(roundtrip.coinbase, native.coinbase);
assert_eq!(roundtrip.timestamp, native.timestamp);
assert!(
!roundtrip.ff_eligible,
"ff_eligible is not carried on Chia row; must default false after roundtrip"
);
}