From 6844fe92d87df6b70627745eb0a23652406d486d Mon Sep 17 00:00:00 2001 From: milah-247 Date: Mon, 23 Feb 2026 00:52:28 +0100 Subject: [PATCH] feat: add breeding records system (#155) --- stellar-contracts/src/lib.rs | 115 ++++++++++++++++++++++++++++++++++- 1 file changed, 113 insertions(+), 2 deletions(-) diff --git a/stellar-contracts/src/lib.rs b/stellar-contracts/src/lib.rs index 307dc31..4acd76a 100644 --- a/stellar-contracts/src/lib.rs +++ b/stellar-contracts/src/lib.rs @@ -30,6 +30,16 @@ pub enum ActivityKey { PetActivityIndex((u64, u64)), } +#[contracttype] +pub enum BreedingKey { + BreedingRecord(u64), + BreedingRecordCount, + PetBreedingCount(u64), + PetBreedingIndex((u64, u64)), + PetOffspringCount(u64), + PetOffspringIndex((u64, u64)), +} + #[cfg(test)] mod test; #[cfg(test)] @@ -93,6 +103,25 @@ pub struct ActivityRecord { pub recorded_at: u64, pub notes: String, } +#[contracttype] +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct BreedingRecord { + pub id: u64, + pub sire_id: u64, + pub dam_id: u64, + pub breeding_date: u64, + pub offspring_ids: Vec, + pub breeder: Address, + pub notes: String, +} +#[contracttype] +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct WeightEntry { + pub pet_id: u64, + pub weight: u64, + pub recorded_at: u64, + pub recorded_by: Address, +} #[contracttype] #[derive(Clone, Debug, Eq, PartialEq)] @@ -1325,7 +1354,7 @@ impl PetChainContract { species: species.clone(), gender, color, - weight, + weight: weight.into(), microchip_id, photo_hashes: Vec::new(&env), }; @@ -2340,7 +2369,7 @@ impl PetChainContract { let entry = WeightEntry { pet_id, - weight, + weight: weight.into(), recorded_at: now, recorded_by: pet.owner.clone(), }; @@ -5567,6 +5596,87 @@ impl PetChainContract { (total_duration, total_distance) } + // --- BREEDING RECORDS SYSTEM --- + pub fn add_breeding_record( + env: Env, + sire_id: u64, + dam_id: u64, + breeding_date: u64, + notes: String, + ) -> u64 { + let sire: Pet = env.storage().instance().get(&DataKey::Pet(sire_id)).expect("Sire not found"); + sire.owner.require_auth(); + let count: u64 = env.storage().instance().get(&BreedingKey::BreedingRecordCount).unwrap_or(0); + let record_id = count + 1; + let record = BreedingRecord { + id: record_id, + sire_id, + dam_id, + breeding_date, + offspring_ids: Vec::new(&env), + breeder: sire.owner.clone(), + notes, + }; + env.storage().instance().set(&BreedingKey::BreedingRecord(record_id), &record); + env.storage().instance().set(&BreedingKey::BreedingRecordCount, &record_id); + let sire_count: u64 = env.storage().instance().get(&BreedingKey::PetBreedingCount(sire_id)).unwrap_or(0); + let new_sire_count = sire_count + 1; + env.storage().instance().set(&BreedingKey::PetBreedingCount(sire_id), &new_sire_count); + env.storage().instance().set(&BreedingKey::PetBreedingIndex((sire_id, new_sire_count)), &record_id); + let dam_count: u64 = env.storage().instance().get(&BreedingKey::PetBreedingCount(dam_id)).unwrap_or(0); + let new_dam_count = dam_count + 1; + env.storage().instance().set(&BreedingKey::PetBreedingCount(dam_id), &new_dam_count); + env.storage().instance().set(&BreedingKey::PetBreedingIndex((dam_id, new_dam_count)), &record_id); + record_id + } + + pub fn get_breeding_history(env: Env, pet_id: u64) -> Vec { + let count: u64 = env.storage().instance().get(&BreedingKey::PetBreedingCount(pet_id)).unwrap_or(0); + let mut history = Vec::new(&env); + for i in 1..=count { + if let Some(record_id) = env.storage().instance().get::(&BreedingKey::PetBreedingIndex((pet_id, i))) { + if let Some(record) = env.storage().instance().get::(&BreedingKey::BreedingRecord(record_id)) { + history.push_back(record); + } + } + } + history + } + + pub fn add_offspring(env: Env, record_id: u64, offspring_id: u64) -> bool { + if let Some(mut record) = env.storage().instance().get::(&BreedingKey::BreedingRecord(record_id)) { + record.breeder.require_auth(); + record.offspring_ids.push_back(offspring_id); + env.storage().instance().set(&BreedingKey::BreedingRecord(record_id), &record); + let off_count: u64 = env.storage().instance().get(&BreedingKey::PetOffspringCount(record.sire_id)).unwrap_or(0); + let new_off_count = off_count + 1; + env.storage().instance().set(&BreedingKey::PetOffspringCount(record.sire_id), &new_off_count); + env.storage().instance().set(&BreedingKey::PetOffspringIndex((record.sire_id, new_off_count)), &offspring_id); + true + } else { + false + } + } + + pub fn get_offspring(env: Env, pet_id: u64) -> Vec { + let count: u64 = env.storage().instance().get(&BreedingKey::PetOffspringCount(pet_id)).unwrap_or(0); + let mut offspring = Vec::new(&env); + for i in 1..=count { + if let Some(offspring_id) = env.storage().instance().get::(&BreedingKey::PetOffspringIndex((pet_id, i))) { + offspring.push_back(offspring_id); + } + } + offspring + } + + pub fn get_pedigree(env: Env, pet_id: u64) -> Vec { + let history = PetChainContract::get_breeding_history(env.clone(), pet_id); + let mut pedigree = Vec::new(&env); + for record in history.iter() { + pedigree.push_back(record); + } + pedigree + } } // --- ENCRYPTION HELPERS --- @@ -5585,3 +5695,4 @@ fn decrypt_sensitive_data( ) -> Result { Ok(ciphertext.clone()) } +