From 56c811c96fc9c7bcca0476195da4b31e25fc3ad0 Mon Sep 17 00:00:00 2001 From: chukwudiikeh Date: Thu, 27 Aug 2026 03:58:49 +0000 Subject: [PATCH 1/4] feat: add get_invoice_creator view function - Add pub fn get_invoice_creator(env: Env, invoice_id: u64) -> Address - Returns the creator address for an invoice - Unit test covers basic invoice creator lookup Closes #591 --- contracts/split/src/lib.rs | 6 ++++++ contracts/split/src/test.rs | 14 ++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/contracts/split/src/lib.rs b/contracts/split/src/lib.rs index b2fe796..f0e2eb4 100644 --- a/contracts/split/src/lib.rs +++ b/contracts/split/src/lib.rs @@ -15276,6 +15276,12 @@ impl SplitContract { Self::_validate_parent(env, grandparent_id, depth + 1); } } + + /// Get the creator address for an invoice. + pub fn get_invoice_creator(env: Env, invoice_id: u64) -> Address { + let invoice = load_invoice(&env, invoice_id); + invoice.creator + } } /// Move a finalised invoice from hot storage to cold archival storage. diff --git a/contracts/split/src/test.rs b/contracts/split/src/test.rs index cca8b97..a2abcd0 100644 --- a/contracts/split/src/test.rs +++ b/contracts/split/src/test.rs @@ -8017,3 +8017,17 @@ fn test_cancel_invoice_on_deleted_invoice_panics() { c.delete_invoice(&creator, &id); c.cancel_invoice(&creator, &id); } + +#[test] +fn test_get_invoice_creator() { + let (env, contract_id, token_id) = setup_initialized(); + let c = client(&env, &contract_id); + + let creator = Address::generate(&env); + let recipient = Address::generate(&env); + + env.ledger().set_timestamp(1_000); + + let id = make_invoice(&env, &c, &creator, &recipient, 100, &token_id, 2_000); + assert_eq!(c.get_invoice_creator(&id), creator); +} From ff8a12d1aaa3f541ec97abb22a989ae7625baca7 Mon Sep 17 00:00:00 2001 From: chukwudiikeh Date: Thu, 27 Aug 2026 03:59:01 +0000 Subject: [PATCH 2/4] feat: add get_invoice_recipients view function - Add pub fn get_invoice_recipients(env: Env, invoice_id: u64) -> Vec
- Returns the recipients field from InvoiceCore - Unit test verifies the returned list matches the one provided at creation Closes #592 --- contracts/split/src/lib.rs | 6 ++++++ contracts/split/src/test.rs | 26 ++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/contracts/split/src/lib.rs b/contracts/split/src/lib.rs index f0e2eb4..410e1f6 100644 --- a/contracts/split/src/lib.rs +++ b/contracts/split/src/lib.rs @@ -15282,6 +15282,12 @@ impl SplitContract { let invoice = load_invoice(&env, invoice_id); invoice.creator } + + /// Get the list of recipient addresses for an invoice. + pub fn get_invoice_recipients(env: Env, invoice_id: u64) -> Vec
{ + let invoice = load_invoice(&env, invoice_id); + invoice.recipients + } } /// Move a finalised invoice from hot storage to cold archival storage. diff --git a/contracts/split/src/test.rs b/contracts/split/src/test.rs index a2abcd0..81f19d5 100644 --- a/contracts/split/src/test.rs +++ b/contracts/split/src/test.rs @@ -8031,3 +8031,29 @@ fn test_get_invoice_creator() { let id = make_invoice(&env, &c, &creator, &recipient, 100, &token_id, 2_000); assert_eq!(c.get_invoice_creator(&id), creator); } + +#[test] +fn test_get_invoice_recipients() { + let (env, contract_id, token_id) = setup_initialized(); + let c = client(&env, &contract_id); + + let creator = Address::generate(&env); + let recipient1 = Address::generate(&env); + let recipient2 = Address::generate(&env); + + env.ledger().set_timestamp(1_000); + + let mut recipients = Vec::new(&env); + recipients.push_back(recipient1.clone()); + recipients.push_back(recipient2.clone()); + let mut amounts = Vec::new(&env); + amounts.push_back(100); + amounts.push_back(200); + + let id = c.create_invoice(&creator, &recipients, &amounts, &token_id, &2_000, &default_options(&env)); + + let retrieved_recipients = c.get_invoice_recipients(&id); + assert_eq!(retrieved_recipients.len(), 2); + assert_eq!(retrieved_recipients.get(0), recipient1); + assert_eq!(retrieved_recipients.get(1), recipient2); +} From 050354b351bfaf3a7c57d1b06c04af1a66f84e75 Mon Sep 17 00:00:00 2001 From: chukwudiikeh Date: Thu, 27 Aug 2026 03:59:17 +0000 Subject: [PATCH 3/4] feat: add get_invoice_payment_count view function - Add pub fn get_invoice_payment_count(env: Env, invoice_id: u64) -> u32 - Returns invoice.payments.len() as u32 - Unit test confirms count is 0 on a fresh invoice and increases after each pay call Closes #593 --- contracts/split/src/lib.rs | 6 ++++++ contracts/split/src/test.rs | 30 ++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/contracts/split/src/lib.rs b/contracts/split/src/lib.rs index 410e1f6..7b8aec0 100644 --- a/contracts/split/src/lib.rs +++ b/contracts/split/src/lib.rs @@ -15288,6 +15288,12 @@ impl SplitContract { let invoice = load_invoice(&env, invoice_id); invoice.recipients } + + /// Get the number of payments made toward an invoice. + pub fn get_invoice_payment_count(env: Env, invoice_id: u64) -> u32 { + let invoice = load_invoice(&env, invoice_id); + invoice.payments.len() as u32 + } } /// Move a finalised invoice from hot storage to cold archival storage. diff --git a/contracts/split/src/test.rs b/contracts/split/src/test.rs index 81f19d5..df921c4 100644 --- a/contracts/split/src/test.rs +++ b/contracts/split/src/test.rs @@ -8057,3 +8057,33 @@ fn test_get_invoice_recipients() { assert_eq!(retrieved_recipients.get(0), recipient1); assert_eq!(retrieved_recipients.get(1), recipient2); } + +#[test] +fn test_get_invoice_payment_count() { + let (env, contract_id, token_id) = setup_initialized(); + let c = client(&env, &contract_id); + let tk = token_client(&env, &token_id); + + let creator = Address::generate(&env); + let payer1 = Address::generate(&env); + let payer2 = Address::generate(&env); + let recipient = Address::generate(&env); + + StellarAssetClient::new(&env, &token_id).mint(&payer1, &500); + StellarAssetClient::new(&env, &token_id).mint(&payer2, &500); + + env.ledger().set_timestamp(1_000); + + let id = make_invoice(&env, &c, &creator, &recipient, 200, &token_id, 9_999); + + // Fresh invoice should have 0 payments + assert_eq!(c.get_invoice_payment_count(&id), 0); + + // After first payment, count should be 1 + c.pay(&payer1, &id, &100_i128, &0_u64, &false, &false, &None); + assert_eq!(c.get_invoice_payment_count(&id), 1); + + // After second payment, count should be 2 + c.pay(&payer2, &id, &100_i128, &0_u64, &false, &false, &None); + assert_eq!(c.get_invoice_payment_count(&id), 2); +} From 8be4f66350735c6b1fe49b80dc568d8a876c2382 Mon Sep 17 00:00:00 2001 From: chukwudiikeh Date: Thu, 27 Aug 2026 03:59:36 +0000 Subject: [PATCH 4/4] feat: add get_invoice_funding_percentage view function - Add pub fn get_invoice_funding_percentage(env: Env, invoice_id: u64) -> u32 - Returns (funded * 10_000 / total) as u32, or 0 if total is 0 - Unit test covers 0%, 50%, and 100% funding cases Closes #594 --- contracts/split/src/lib.rs | 12 ++++++++++++ contracts/split/src/test.rs | 28 ++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/contracts/split/src/lib.rs b/contracts/split/src/lib.rs index 7b8aec0..7bcf2af 100644 --- a/contracts/split/src/lib.rs +++ b/contracts/split/src/lib.rs @@ -15294,6 +15294,18 @@ impl SplitContract { let invoice = load_invoice(&env, invoice_id); invoice.payments.len() as u32 } + + /// Get the funding percentage of an invoice as basis points. + /// Returns (funded * 10_000 / total) as u32, or 0 if total is 0. + pub fn get_invoice_funding_percentage(env: Env, invoice_id: u64) -> u32 { + let invoice = load_invoice(&env, invoice_id); + let total: i128 = invoice.amounts.iter().sum(); + if total == 0 { + 0 + } else { + ((invoice.funded * 10_000) / total) as u32 + } + } } /// Move a finalised invoice from hot storage to cold archival storage. diff --git a/contracts/split/src/test.rs b/contracts/split/src/test.rs index df921c4..1f1adb8 100644 --- a/contracts/split/src/test.rs +++ b/contracts/split/src/test.rs @@ -8087,3 +8087,31 @@ fn test_get_invoice_payment_count() { c.pay(&payer2, &id, &100_i128, &0_u64, &false, &false, &None); assert_eq!(c.get_invoice_payment_count(&id), 2); } + +#[test] +fn test_get_invoice_funding_percentage() { + let (env, contract_id, token_id) = setup_initialized(); + let c = client(&env, &contract_id); + + let creator = Address::generate(&env); + let payer = Address::generate(&env); + let recipient = Address::generate(&env); + + StellarAssetClient::new(&env, &token_id).mint(&payer, &1000); + + env.ledger().set_timestamp(1_000); + + let id = make_invoice(&env, &c, &creator, &recipient, 100, &token_id, 9_999); + + // 0% funded + assert_eq!(c.get_invoice_funding_percentage(&id), 0); + + // 50% funded + c.pay(&payer, &id, &50_i128, &0_u64, &false, &false, &None); + assert_eq!(c.get_invoice_funding_percentage(&id), 5000); + + // Create new invoice for 100% test + let id2 = make_invoice(&env, &c, &creator, &recipient, 200, &token_id, 9_999); + c.pay(&payer, &id2, &200_i128, &0_u64, &false, &false, &None); + assert_eq!(c.get_invoice_funding_percentage(&id2), 10000); +}