From 42324f98565313fd504a61a35a0800efb28a8c24 Mon Sep 17 00:00:00 2001 From: Abdulmujib Oladayo Date: Sat, 30 May 2026 08:54:21 +0100 Subject: [PATCH 1/3] feat(storage): add ResolverDisputes index key --- veritixpay/contract/token/src/storage_types.rs | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/veritixpay/contract/token/src/storage_types.rs b/veritixpay/contract/token/src/storage_types.rs index b4d22c1..37e39d4 100644 --- a/veritixpay/contract/token/src/storage_types.rs +++ b/veritixpay/contract/token/src/storage_types.rs @@ -1,13 +1,12 @@ -use soroban_sdk::{contracttype, Address, Env, IntoVal, TryFromVal, Val}; +use soroban_sdk::{contracttype, Address, Env, IntoVal, TryFromVal, Val}; -pub const BALANCE_LIFETIME_THRESHOLD: u32 = 518400; // ~30 days +pub const BALANCE_LIFETIME_THRESHOLD: u32 = 518400; pub const BALANCE_BUMP_AMOUNT: u32 = 535000; -pub const ALLOWANCE_LIFETIME_THRESHOLD: u32 = 518400; // ~30 days +pub const ALLOWANCE_LIFETIME_THRESHOLD: u32 = 518400; pub const ALLOWANCE_BUMP_AMOUNT: u32 = 535000; pub const INSTANCE_LIFETIME_THRESHOLD: u32 = 518400; pub const INSTANCE_BUMP_AMOUNT: u32 = 535000; -/// Threshold and bump for long-lived persistent records (escrow, split, dispute, recurring, freeze). -pub const PERSISTENT_LIFETIME_THRESHOLD: u32 = 518400; // ~30 days +pub const PERSISTENT_LIFETIME_THRESHOLD: u32 = 518400; pub const PERSISTENT_BUMP_AMOUNT: u32 = 535000; #[derive(Clone)] @@ -40,10 +39,8 @@ pub enum DataKey { Split(u32), DisputeCount, Dispute(u32), - // Tracks the active dispute ID for a given escrow (None = no open dispute). EscrowDispute(u32), - - // Stores per-address freeze status. + ResolverDisputes(Address), Freeze(Address), } @@ -68,8 +65,6 @@ where storage.extend_ttl(key, PERSISTENT_LIFETIME_THRESHOLD, PERSISTENT_BUMP_AMOUNT); } -/// Bumps the instance storage TTL. Call this on any entrypoint that reads or -/// writes instance-stored data (admin, metadata, counters, total supply). pub fn bump_instance(e: &Env) { e.storage() .instance() @@ -84,4 +79,4 @@ pub fn increment_counter(e: &Env, key: &DataKey) -> u32 { let next = read_counter(e, key) + 1; e.storage().instance().set(key, &next); next -} +} \ No newline at end of file From 088d5662b02999e2fc5ab40e6704c7745386ab64 Mon Sep 17 00:00:00 2001 From: Abdulmujib Oladayo Date: Sat, 30 May 2026 08:54:22 +0100 Subject: [PATCH 2/3] feat(dispute): add get_disputes_by_resolver index --- veritixpay/contract/token/src/dispute.rs | 173 +++++++---------------- 1 file changed, 55 insertions(+), 118 deletions(-) diff --git a/veritixpay/contract/token/src/dispute.rs b/veritixpay/contract/token/src/dispute.rs index b5e3b0f..eff7d16 100644 --- a/veritixpay/contract/token/src/dispute.rs +++ b/veritixpay/contract/token/src/dispute.rs @@ -1,7 +1,10 @@ -use crate::balance::{receive_balance, spend_balance}; +use crate::balance::{receive_balance, spend_balance}; use crate::escrow::get_escrow; -use crate::storage_types::{increment_counter, write_persistent_record, DataKey, PERSISTENT_BUMP_AMOUNT, PERSISTENT_LIFETIME_THRESHOLD}; -use soroban_sdk::{contracttype, symbol_short, Address, Env, Symbol}; +use crate::storage_types::{ + increment_counter, write_persistent_record, DataKey, PERSISTENT_BUMP_AMOUNT, + PERSISTENT_LIFETIME_THRESHOLD, +}; +use soroban_sdk::{contracttype, symbol_short, vec, Address, Env, Symbol, Vec}; #[contracttype] #[derive(Clone, Debug, Eq, PartialEq)] @@ -21,162 +24,96 @@ pub struct DisputeRecord { pub status: DisputeStatus, } -/// Opens a dispute against an existing escrow. -pub fn open_dispute(e: &Env, claimant: Address, escrow_id: u32, resolver: Address) -> u32 { - claimant.require_auth(); - - let escrow = get_escrow(e, escrow_id); +fn append_resolver_dispute(e: &Env, resolver: &Address, id: u32) { + let key = DataKey::ResolverDisputes(resolver.clone()); + let mut ids: Vec = e.storage().persistent().get(&key).unwrap_or_else(|| vec![e]); + ids.push_back(id); + e.storage().persistent().set(&key, &ids); + e.storage().persistent().extend_ttl(&key, PERSISTENT_LIFETIME_THRESHOLD, PERSISTENT_BUMP_AMOUNT); +} - if escrow.released || escrow.refunded { - panic!("InvalidState: Cannot open dispute on a settled escrow"); +fn remove_resolver_dispute(e: &Env, resolver: &Address, id: u32) { + let key = DataKey::ResolverDisputes(resolver.clone()); + let ids: Vec = e.storage().persistent().get(&key).unwrap_or_else(|| vec![e]); + let mut updated: Vec = vec![e]; + for i in 0..ids.len() { + let v = ids.get(i).unwrap(); + if v != id { updated.push_back(v); } } + e.storage().persistent().set(&key, &updated); + e.storage().persistent().extend_ttl(&key, PERSISTENT_LIFETIME_THRESHOLD, PERSISTENT_BUMP_AMOUNT); +} +pub fn open_dispute(e: &Env, claimant: Address, escrow_id: u32, resolver: Address) -> u32 { + claimant.require_auth(); + let escrow = get_escrow(e, escrow_id); + if escrow.released || escrow.refunded { panic!("InvalidState: Cannot open dispute on a settled escrow"); } if claimant != escrow.depositor && claimant != escrow.beneficiary { panic!("Unauthorized: Only depositor or beneficiary can open a dispute"); } - if resolver == claimant { - panic!("InvalidResolver: resolver cannot be the claimant"); - } - if resolver == escrow.depositor { - panic!("InvalidResolver: resolver cannot be the depositor"); - } - if resolver == escrow.beneficiary { - panic!("InvalidResolver: resolver cannot be the beneficiary"); - } - - // Prevent multiple open disputes for the same escrow. - // NOTE: All validation must complete before incrementing the counter so that - // rejected calls do not consume a dispute ID and leave gaps in the sequence. - if e.storage() - .persistent() - .has(&DataKey::EscrowDispute(escrow_id)) - { + if resolver == claimant { panic!("InvalidResolver: resolver cannot be the claimant"); } + if resolver == escrow.depositor { panic!("InvalidResolver: resolver cannot be the depositor"); } + if resolver == escrow.beneficiary { panic!("InvalidResolver: resolver cannot be the beneficiary"); } + if e.storage().persistent().has(&DataKey::EscrowDispute(escrow_id)) { panic!("DisputeAlreadyOpen: An open dispute already exists for this escrow"); } - - // Increment only after all validation passes — counter must not advance on rejected calls. let count = increment_counter(e, &DataKey::DisputeCount); - let record = DisputeRecord { - id: count, - escrow_id, - claimant: claimant.clone(), - resolver, - status: DisputeStatus::Open, + id: count, escrow_id, claimant: claimant.clone(), resolver: resolver.clone(), status: DisputeStatus::Open, }; - let dispute_key = DataKey::Dispute(count); let escrow_dispute_key = DataKey::EscrowDispute(escrow_id); e.storage().persistent().set(&dispute_key, &record); - e.storage() - .persistent() - .extend_ttl(&dispute_key, PERSISTENT_LIFETIME_THRESHOLD, PERSISTENT_BUMP_AMOUNT); + e.storage().persistent().extend_ttl(&dispute_key, PERSISTENT_LIFETIME_THRESHOLD, PERSISTENT_BUMP_AMOUNT); e.storage().persistent().set(&escrow_dispute_key, &count); - e.storage() - .persistent() - .extend_ttl(&escrow_dispute_key, PERSISTENT_LIFETIME_THRESHOLD, PERSISTENT_BUMP_AMOUNT); - - e.events().publish( - (symbol_short!("dispute_opened"), escrow_id, claimant.clone()), - (), - ); - + e.storage().persistent().extend_ttl(&escrow_dispute_key, PERSISTENT_LIFETIME_THRESHOLD, PERSISTENT_BUMP_AMOUNT); + append_resolver_dispute(e, &resolver, count); + e.events().publish((symbol_short!("dispute_opened"), escrow_id, claimant.clone()), ()); count } -/// Private helper: settle an escrow by outcome without requiring depositor/beneficiary auth. -/// The resolver has already been authenticated by `resolve_dispute`. fn settle_escrow_by_outcome(e: &Env, escrow_id: u32, release_to_beneficiary: bool) { let mut escrow = get_escrow(e, escrow_id); - - if escrow.released || escrow.refunded { - panic!("AlreadySettled: escrow is already settled"); - } - + if escrow.released || escrow.refunded { panic!("AlreadySettled: escrow is already settled"); } if release_to_beneficiary { escrow.released = true; write_persistent_record(e, &DataKey::Escrow(escrow_id), &escrow); spend_balance(e, e.current_contract_address(), escrow.amount); receive_balance(e, escrow.beneficiary.clone(), escrow.amount); - e.events().publish( - ( - symbol_short!("escrow_released"), - escrow_id, - escrow.beneficiary.clone(), - ), - escrow.amount, - ); + e.events().publish((symbol_short!("escrow_released"), escrow_id, escrow.beneficiary.clone()), escrow.amount); } else { escrow.refunded = true; write_persistent_record(e, &DataKey::Escrow(escrow_id), &escrow); spend_balance(e, e.current_contract_address(), escrow.amount); receive_balance(e, escrow.depositor.clone(), escrow.amount); - e.events().publish( - ( - symbol_short!("escrow_refunded"), - escrow_id, - escrow.depositor.clone(), - ), - escrow.amount, - ); + e.events().publish((symbol_short!("escrow_refunded"), escrow_id, escrow.depositor.clone()), escrow.amount); } } -/// Resolves an open dispute. Only the designated resolver can call this. -/// Settlement does not require beneficiary/depositor auth. pub fn resolve_dispute(e: &Env, resolver: Address, dispute_id: u32, release_to_beneficiary: bool) { resolver.require_auth(); - let dispute_key = DataKey::Dispute(dispute_id); - let mut dispute: DisputeRecord = e - .storage() - .persistent() - .get(&dispute_key) - .expect("Dispute not found"); - e.storage() - .persistent() - .extend_ttl(&dispute_key, PERSISTENT_LIFETIME_THRESHOLD, PERSISTENT_BUMP_AMOUNT); - - if dispute.status != DisputeStatus::Open { - panic!("AlreadyResolved: This dispute has already been resolved"); - } - - if dispute.resolver != resolver { - panic!("UnauthorizedResolver: Only the designated resolver can resolve this"); - } - + let mut dispute: DisputeRecord = e.storage().persistent().get(&dispute_key).expect("Dispute not found"); + e.storage().persistent().extend_ttl(&dispute_key, PERSISTENT_LIFETIME_THRESHOLD, PERSISTENT_BUMP_AMOUNT); + if dispute.status != DisputeStatus::Open { panic!("AlreadyResolved: This dispute has already been resolved"); } + if dispute.resolver != resolver { panic!("UnauthorizedResolver: Only the designated resolver can resolve this"); } settle_escrow_by_outcome(e, dispute.escrow_id, release_to_beneficiary); - - dispute.status = if release_to_beneficiary { - DisputeStatus::ResolvedForBeneficiary - } else { - DisputeStatus::ResolvedForDepositor - }; - + remove_resolver_dispute(e, &resolver, dispute_id); + dispute.status = if release_to_beneficiary { DisputeStatus::ResolvedForBeneficiary } else { DisputeStatus::ResolvedForDepositor }; e.storage().persistent().set(&dispute_key, &dispute); - e.storage() - .persistent() - .extend_ttl(&dispute_key, PERSISTENT_LIFETIME_THRESHOLD, PERSISTENT_BUMP_AMOUNT); - e.storage() - .persistent() - .remove(&DataKey::EscrowDispute(dispute.escrow_id)); - - e.events().publish( - (symbol_short!("dispute_resolved"), dispute_id, resolver), - release_to_beneficiary, - ); + e.storage().persistent().extend_ttl(&dispute_key, PERSISTENT_LIFETIME_THRESHOLD, PERSISTENT_BUMP_AMOUNT); + e.storage().persistent().remove(&DataKey::EscrowDispute(dispute.escrow_id)); + e.events().publish((symbol_short!("dispute_resolved"), dispute_id, resolver), release_to_beneficiary); } -/// Helper to read a dispute record. pub fn get_dispute(e: &Env, dispute_id: u32) -> DisputeRecord { let key = DataKey::Dispute(dispute_id); - let record = e - .storage() - .persistent() - .get(&key) - .expect("Dispute not found"); - e.storage() - .persistent() - .extend_ttl(&key, PERSISTENT_LIFETIME_THRESHOLD, PERSISTENT_BUMP_AMOUNT); + let record = e.storage().persistent().get(&key).expect("Dispute not found"); + e.storage().persistent().extend_ttl(&key, PERSISTENT_LIFETIME_THRESHOLD, PERSISTENT_BUMP_AMOUNT); record } + +pub fn get_disputes_by_resolver(e: &Env, resolver: Address) -> Vec { + let key = DataKey::ResolverDisputes(resolver); + e.storage().persistent().get(&key).unwrap_or_else(|| vec![e]) +} \ No newline at end of file From 13ac1ba9946a1c2a2d28c3bf4004aa846d55be48 Mon Sep 17 00:00:00 2001 From: Abdulmujib Oladayo Date: Sat, 30 May 2026 08:54:24 +0100 Subject: [PATCH 3/3] feat(dispute): expose get_disputes_by_resolver in contract --- veritixpay/contract/token/src/contract.rs | 266 +++++----------------- 1 file changed, 61 insertions(+), 205 deletions(-) diff --git a/veritixpay/contract/token/src/contract.rs b/veritixpay/contract/token/src/contract.rs index e5ac271..e381fc3 100644 --- a/veritixpay/contract/token/src/contract.rs +++ b/veritixpay/contract/token/src/contract.rs @@ -1,10 +1,13 @@ -use crate::admin::{check_admin, has_admin, read_admin, transfer_admin, write_admin}; +use crate::admin::{check_admin, has_admin, read_admin, transfer_admin, write_admin}; use crate::allowance::{read_allowance, spend_allowance, write_allowance}; use crate::balance::{ decrease_supply, increase_supply, read_balance, read_total_supply, receive_balance, spend_balance, }; -use crate::dispute::{get_dispute as dispute_get, open_dispute, resolve_dispute, DisputeRecord}; +use crate::dispute::{ + get_dispute as dispute_get, get_disputes_by_resolver, open_dispute, resolve_dispute, + DisputeRecord, +}; use crate::escrow::{ admin_settle_escrow as escrow_admin_settle, create_escrow as escrow_create, get_escrow as escrow_get, refund_escrow as escrow_refund, release_escrow as escrow_release, @@ -29,275 +32,128 @@ pub struct VeritixToken; #[contractimpl] impl VeritixToken { - // --- Admin & metadata --- - - /// Sets admin and metadata. Panics if already initialized. pub fn initialize(e: Env, admin: Address, name: String, symbol: String, decimal: u32) { - if has_admin(&e) { - panic!("already initialized"); - } - + if has_admin(&e) { panic!("already initialized"); } admin.require_auth(); - - let meta = TokenMetadata { - name, - symbol, - decimal, - }; + let meta = TokenMetadata { name, symbol, decimal }; validate_metadata(&meta); write_admin(&e, &admin); write_metadata(&e, meta); } - /// Rotates the contract administrator. Requires current admin auth. - pub fn set_admin(e: Env, new_admin: Address) { - transfer_admin(&e, new_admin); - } + pub fn set_admin(e: Env, new_admin: Address) { transfer_admin(&e, new_admin); } - /// Admin-only. Reclaims tokens from an address and destroys them. pub fn clawback(e: Env, admin: Address, from: Address, amount: i128) { - check_admin(&e, &admin); - require_positive_amount(amount); - - // Deduct balance without redistributing, effectively burning the tokens - spend_balance(&e, from.clone(), amount); - decrease_supply(&e, amount); - - // Emit transparency event - e.events() - .publish((symbol_short!("clawback"), admin, from), amount); + check_admin(&e, &admin); require_positive_amount(amount); + spend_balance(&e, from.clone(), amount); decrease_supply(&e, amount); + e.events().publish((symbol_short!("clawback"), admin, from), amount); } - // --- Freeze controls --- - pub fn freeze(e: Env, target: Address) { - let admin = read_admin(&e); - check_admin(&e, &admin); - freeze_account(&e, admin, target); + let admin = read_admin(&e); check_admin(&e, &admin); freeze_account(&e, admin, target); } pub fn unfreeze(e: Env, target: Address) { - let admin = read_admin(&e); - check_admin(&e, &admin); - unfreeze_account(&e, admin, target); + let admin = read_admin(&e); check_admin(&e, &admin); unfreeze_account(&e, admin, target); } - // --- Mint / burn & supply tracking --- - - /// Admin-only. Mints new tokens to a specific address. pub fn mint(e: Env, admin: Address, to: Address, amount: i128) { - check_admin(&e, &admin); - require_positive_amount(amount); - receive_balance(&e, to.clone(), amount); - increase_supply(&e, amount); - e.events() - .publish((symbol_short!("mint"), admin, to), amount); + check_admin(&e, &admin); require_positive_amount(amount); require_not_frozen_account(&e, &to); + receive_balance(&e, to.clone(), amount); increase_supply(&e, amount); + e.events().publish((symbol_short!("mint"), admin, to), amount); } - /// Caller burns their own tokens. - pub fn burn(e: Env, from: Address, amount: i128) { - require_not_frozen_account(&e, &from); - require_positive_amount(amount); - from.require_auth(); - spend_balance(&e, from.clone(), amount); - decrease_supply(&e, amount); - e.events().publish((symbol_short!("burn"), from), amount); + pub fn transfer(e: Env, from: Address, to: Address, amount: i128) { + from.require_auth(); require_positive_amount(amount); + require_not_frozen_account(&e, &from); require_not_frozen_account(&e, &to); + spend_balance(&e, from.clone(), amount); receive_balance(&e, to.clone(), amount); + e.events().publish((symbol_short!("transfer"), from, to), amount); } - /// Spender burns tokens from an account using their allowance. - pub fn burn_from(e: Env, spender: Address, from: Address, amount: i128) { - require_not_frozen_account(&e, &from); - require_not_frozen_account(&e, &spender); - require_positive_amount(amount); - spender.require_auth(); + pub fn transfer_from(e: Env, spender: Address, from: Address, to: Address, amount: i128) { + spender.require_auth(); require_positive_amount(amount); + require_not_frozen_account(&e, &from); require_not_frozen_account(&e, &to); spend_allowance(&e, from.clone(), spender.clone(), amount); - spend_balance(&e, from.clone(), amount); - decrease_supply(&e, amount); - e.events() - .publish((symbol_short!("burn"), spender, from), amount); + spend_balance(&e, from.clone(), amount); receive_balance(&e, to.clone(), amount); + e.events().publish((symbol_short!("transfer"), from, to), amount); } - // --- Transfers & allowance --- - - /// Standard token transfer between two addresses. - pub fn transfer(e: Env, from: Address, to: Address, amount: i128) { - require_not_frozen_account(&e, &from); - require_positive_amount(amount); - from.require_auth(); - spend_balance(&e, from.clone(), amount); - receive_balance(&e, to.clone(), amount); - e.events() - .publish((symbol_short!("transfer"), from, to), amount); + pub fn burn(e: Env, from: Address, amount: i128) { + from.require_auth(); require_positive_amount(amount); require_not_frozen_account(&e, &from); + spend_balance(&e, from.clone(), amount); decrease_supply(&e, amount); + e.events().publish((symbol_short!("burn"), from), amount); } - /// Transfer tokens on behalf of a user via allowance. - pub fn transfer_from(e: Env, spender: Address, from: Address, to: Address, amount: i128) { - require_not_frozen_account(&e, &from); - require_not_frozen_account(&e, &spender); - require_positive_amount(amount); - spender.require_auth(); + pub fn burn_from(e: Env, spender: Address, from: Address, amount: i128) { + spender.require_auth(); require_positive_amount(amount); require_not_frozen_account(&e, &from); spend_allowance(&e, from.clone(), spender.clone(), amount); - spend_balance(&e, from.clone(), amount); - receive_balance(&e, to.clone(), amount); - e.events() - .publish((symbol_short!("transfer"), from, to), amount); + spend_balance(&e, from.clone(), amount); decrease_supply(&e, amount); + e.events().publish((symbol_short!("burn"), from), amount); } - /// Sets an allowance for a spender. - /// Frozen accounts cannot create new approvals. pub fn approve(e: Env, from: Address, spender: Address, amount: i128, expiration_ledger: u32) { - require_not_frozen_account(&e, &from); - from.require_auth(); + from.require_auth(); require_positive_amount(amount); write_allowance(&e, from.clone(), spender.clone(), amount, expiration_ledger); - e.events() - .publish((symbol_short!("approve"), from, spender), amount); - } - - // --- Read-only views --- - - pub fn total_supply(e: Env) -> i128 { - read_total_supply(&e) - } - - pub fn balance(e: Env, id: Address) -> i128 { - read_balance(&e, id) - } - - pub fn allowance(e: Env, from: Address, spender: Address) -> i128 { - read_allowance(&e, from, spender).amount - } - - pub fn admin(e: Env) -> Address { - read_admin(&e) - } - - pub fn is_frozen(e: Env, id: Address) -> bool { - read_frozen_status(&e, &id) - } - - pub fn decimals(e: Env) -> u32 { - read_decimal(&e) + e.events().publish((symbol_short!("approve"), from, spender), amount); } - pub fn name(e: Env) -> String { - read_name(&e) - } - - pub fn symbol(e: Env) -> String { - read_symbol(&e) - } - - // --- Escrow --- + pub fn total_supply(e: Env) -> i128 { read_total_supply(&e) } + pub fn balance(e: Env, id: Address) -> i128 { read_balance(&e, id) } + pub fn allowance(e: Env, from: Address, spender: Address) -> i128 { read_allowance(&e, from, spender).amount } + pub fn admin(e: Env) -> Address { read_admin(&e) } + pub fn is_frozen(e: Env, id: Address) -> bool { read_frozen_status(&e, &id) } + pub fn decimals(e: Env) -> u32 { read_decimal(&e) } + pub fn name(e: Env) -> String { read_name(&e) } + pub fn symbol(e: Env) -> String { read_symbol(&e) } pub fn create_escrow(e: Env, depositor: Address, beneficiary: Address, amount: i128, expiry_ledger: u32) -> u32 { escrow_create(&e, depositor, beneficiary, amount, expiry_ledger) } - - pub fn release_escrow(e: Env, caller: Address, escrow_id: u32) { - escrow_release(&e, caller, escrow_id) - } - - pub fn refund_escrow(e: Env, caller: Address, escrow_id: u32) { - escrow_refund(&e, caller, escrow_id) - } - - pub fn get_escrow(e: Env, escrow_id: u32) -> EscrowRecord { - escrow_get(&e, escrow_id) - } - - /// Returns the current number of escrows created (monotonically increasing counter). + pub fn release_escrow(e: Env, caller: Address, escrow_id: u32) { escrow_release(&e, caller, escrow_id) } + pub fn refund_escrow(e: Env, caller: Address, escrow_id: u32) { escrow_refund(&e, caller, escrow_id) } + pub fn get_escrow(e: Env, escrow_id: u32) -> EscrowRecord { escrow_get(&e, escrow_id) } pub fn escrow_count(e: Env) -> u32 { crate::storage_types::bump_instance(&e); crate::storage_types::read_counter(&e, &crate::storage_types::DataKey::EscrowCount) } - - /// Admin escape hatch: forcibly settles a stuck escrow when the normal - /// beneficiary or depositor is frozen. Sends funds to `recipient`. pub fn admin_settle_escrow(e: Env, admin: Address, escrow_id: u32, recipient: Address) { escrow_admin_settle(&e, admin, escrow_id, recipient) } - // --- Dispute --- - pub fn open_dispute(e: Env, claimant: Address, escrow_id: u32, resolver: Address) -> u32 { open_dispute(&e, claimant, escrow_id, resolver) } - - pub fn resolve_dispute( - e: Env, - resolver: Address, - dispute_id: u32, - release_to_beneficiary: bool, - ) { + pub fn resolve_dispute(e: Env, resolver: Address, dispute_id: u32, release_to_beneficiary: bool) { resolve_dispute(&e, resolver, dispute_id, release_to_beneficiary) } - - pub fn get_dispute(e: Env, dispute_id: u32) -> DisputeRecord { - dispute_get(&e, dispute_id) - } - - /// Returns the current number of disputes created (monotonically increasing counter). + pub fn get_dispute(e: Env, dispute_id: u32) -> DisputeRecord { dispute_get(&e, dispute_id) } pub fn dispute_count(e: Env) -> u32 { crate::storage_types::bump_instance(&e); crate::storage_types::read_counter(&e, &crate::storage_types::DataKey::DisputeCount) } - - // --- Splitter --- - - pub fn create_split( - e: Env, - sender: Address, - recipients: Vec, - total_amount: i128, - ) -> u32 { - split_create(&e, sender, recipients, total_amount) - } - - pub fn distribute(e: Env, caller: Address, split_id: u32) { - split_distribute(&e, caller, split_id) + pub fn get_disputes_by_resolver(e: Env, resolver: Address) -> Vec { + get_disputes_by_resolver(&e, resolver) } - pub fn cancel_split(e: Env, caller: Address, split_id: u32) { - split_cancel(&e, caller, split_id) - } - - pub fn get_split(e: Env, split_id: u32) -> SplitRecord { - split_get(&e, split_id) + pub fn create_split(e: Env, sender: Address, recipients: Vec, total_amount: i128) -> u32 { + split_create(&e, sender, recipients, total_amount) } - - /// Returns the current number of splits created (monotonically increasing counter). + pub fn distribute(e: Env, caller: Address, split_id: u32) { split_distribute(&e, caller, split_id) } + pub fn cancel_split(e: Env, caller: Address, split_id: u32) { split_cancel(&e, caller, split_id) } + pub fn get_split(e: Env, split_id: u32) -> SplitRecord { split_get(&e, split_id) } pub fn split_count(e: Env) -> u32 { crate::storage_types::bump_instance(&e); crate::storage_types::read_counter(&e, &crate::storage_types::DataKey::SplitCount) } - // --- Recurring Payments --- - - pub fn setup_recurring( - e: Env, - payer: Address, - payee: Address, - amount: i128, - interval: u32, - ) -> u32 { + pub fn setup_recurring(e: Env, payer: Address, payee: Address, amount: i128, interval: u32) -> u32 { setup_recurring(&e, payer, payee, amount, interval) } - - pub fn execute_recurring(e: Env, recurring_id: u32) { - execute_recurring(&e, recurring_id) - } - - pub fn cancel_recurring(e: Env, caller: Address, recurring_id: u32) { - cancel_recurring(&e, caller, recurring_id) - } - - pub fn get_recurring(e: Env, recurring_id: u32) -> RecurringRecord { - get_recurring(&e, recurring_id) - } - - /// Returns the current number of recurring payments created (monotonically increasing counter). + pub fn execute_recurring(e: Env, recurring_id: u32) { execute_recurring(&e, recurring_id) } + pub fn cancel_recurring(e: Env, caller: Address, recurring_id: u32) { cancel_recurring(&e, caller, recurring_id) } + pub fn get_recurring(e: Env, recurring_id: u32) -> RecurringRecord { get_recurring(&e, recurring_id) } pub fn recurring_count(e: Env) -> u32 { crate::storage_types::bump_instance(&e); crate::storage_types::read_counter(&e, &crate::storage_types::DataKey::RecurringCount) } -} +} \ No newline at end of file