From f5983edb129f8bad176f81eb7e05ef42eae2c4c1 Mon Sep 17 00:00:00 2001 From: The-moving-man Date: Sat, 29 Aug 2026 09:00:39 +0000 Subject: [PATCH] feat: emit events for fee collection, phase transitions, and cosigner approvals Closes #683, #684, #685. Adds approvals_so_far to cosigner_approved, adds invoice_phase_changed emitted from set_invoice_phase, and adds creator_fee_collected emitted alongside creator_fee_paid on release. #682's invoice_paused/invoice_admin_frozen events were already wired up. Co- --- contracts/split/src/events.rs | 47 ++++++++++++++++++++++++++++++++--- contracts/split/src/lib.rs | 4 ++- 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/contracts/split/src/events.rs b/contracts/split/src/events.rs index 46db8b6..a7f052c 100644 --- a/contracts/split/src/events.rs +++ b/contracts/split/src/events.rs @@ -1,4 +1,4 @@ -use crate::types::{DisputeOutcome, FeeSplit, InvoiceStatus, RepScore, TimelockAction}; +use crate::types::{DisputeOutcome, FeeSplit, InvoicePhase, InvoiceStatus, RepScore, TimelockAction}; use soroban_sdk::{contracttype, symbol_short, Address, BytesN, Env, String, Vec}; // --------------------------------------------------------------------------- @@ -1448,15 +1448,15 @@ pub fn invoice_dispute_raised( /// Emitted on every individual cosigner approval recorded via `approve_release`. /// Topics: (split, CosignerApproved, invoice_id) -/// Data: (cosigner, ledger) -pub fn cosigner_approved(env: &Env, invoice_id: u64, cosigner: &Address) { +/// Data: (cosigner, approvals_so_far, ledger) +pub fn cosigner_approved(env: &Env, invoice_id: u64, cosigner: &Address, approvals_so_far: u32) { env.events().publish( ( symbol_short!("split"), soroban_sdk::Symbol::new(env, "CosignerApproved"), invoice_id, ), - (cosigner.clone(), env.ledger().sequence()), + (cosigner.clone(), approvals_so_far, env.ledger().sequence()), ); } @@ -1573,6 +1573,22 @@ pub fn creator_fee_paid(env: &Env, invoice_id: u64, creator: &Address, fee_amoun ); } +/// Issue #685: Emitted when a creator-declared fee (`creator_fee_bps`) is +/// deducted from recipient payouts at release time. +/// +/// Topics: (split, creator_fee_collected, invoice_id) +/// Data: (creator, fee_amount) +pub fn creator_fee_collected(env: &Env, invoice_id: u64, creator: &Address, fee_amount: i128) { + env.events().publish( + ( + symbol_short!("split"), + soroban_sdk::Symbol::new(env, "creator_fee_collected"), + invoice_id, + ), + (creator.clone(), fee_amount), + ); +} + // --------------------------------------------------------------------------- // Issue #560: Creator Migration // --------------------------------------------------------------------------- @@ -1652,6 +1668,29 @@ pub fn recipient_share_locked( ); } +/// Issue #684: Emitted at every `InvoicePhase` transition (Draft -> Active -> +/// Locked -> Released). +/// Topics: (split, phase_chg, invoice_id) +/// Data: (old_phase, new_phase, event_seq) +pub fn invoice_phase_changed( + env: &Env, + invoice_id: u64, + old_phase: &InvoicePhase, + new_phase: &InvoicePhase, +) { + let phase_sym = |phase: &InvoicePhase| match phase { + InvoicePhase::Draft => symbol_short!("draft"), + InvoicePhase::Active => symbol_short!("active"), + InvoicePhase::Locked => symbol_short!("locked"), + InvoicePhase::Released => symbol_short!("released"), + }; + let event_seq = next_seq(env, invoice_id); + env.events().publish( + (symbol_short!("split"), symbol_short!("phase_chg"), invoice_id), + (phase_sym(old_phase), phase_sym(new_phase), event_seq), + ); +} + /// Emitted when an admin unlocks a recipient's share of an invoice. pub fn recipient_share_unlocked( env: &Env, diff --git a/contracts/split/src/lib.rs b/contracts/split/src/lib.rs index d64b40c..1fd4a9a 100644 --- a/contracts/split/src/lib.rs +++ b/contracts/split/src/lib.rs @@ -7858,7 +7858,7 @@ impl SplitContract { env.storage() .persistent() .set(&cosign_key(invoice_id), &approvals); - events::cosigner_approved(&env, invoice_id, &cosigner); + events::cosigner_approved(&env, invoice_id, &cosigner, approvals.len()); append_audit_entry(&env, invoice_id, symbol_short!("cosign"), &cosigner); let threshold: u32 = env @@ -10277,6 +10277,7 @@ impl SplitContract { &total_creator_fee, ); events::creator_fee_paid(env, invoice_id, &invoice.creator, total_creator_fee); + events::creator_fee_collected(env, invoice_id, &invoice.creator, total_creator_fee); } } @@ -12451,6 +12452,7 @@ impl SplitContract { env.storage() .persistent() .set(&invoice_phase_key(invoice_id), &new_phase); + events::invoice_phase_changed(&env, invoice_id, ¤t_phase, &new_phase); } /// Issue #449: Get invoice phase.