diff --git a/veritixpay/contract/token/src/contract.rs b/veritixpay/contract/token/src/contract.rs index 151ae9d..3cd1b71 100644 --- a/veritixpay/contract/token/src/contract.rs +++ b/veritixpay/contract/token/src/contract.rs @@ -5,6 +5,8 @@ use crate::balance::{ spend_balance, }; use crate::dispute::{ + get_dispute as dispute_get, get_disputes_by_resolver, open_dispute, resolve_dispute, + DisputeRecord, get_dispute as dispute_get, get_open_disputes, open_dispute, resolve_dispute, DisputeRecord, }; use crate::escrow::{ @@ -38,6 +40,8 @@ impl VeritixToken { if has_admin(&e) { panic!("already initialized"); } pub fn initialize(e: Env, admin: Address, name: String, symbol: String, decimal: u32) { if has_admin(&e) { panic!("already initialized"); } + pub fn initialize(e: Env, admin: Address, name: String, symbol: String, decimal: u32) { + if has_admin(&e) { panic!("already initialized"); } // --- Admin & metadata --- pub fn initialize(e: Env, admin: Address, name: String, symbol: String, decimal: u32) { @@ -53,6 +57,10 @@ impl VeritixToken { pub fn set_admin(e: Env, new_admin: Address) { transfer_admin(&e, new_admin); } + pub fn clawback(e: Env, admin: Address, from: Address, amount: i128) { + check_admin(&e, &admin); require_positive_amount(amount); + spend_balance(&e, from.clone(), amount); decrease_supply(&e, amount); + pub fn clawback(e: Env, admin: Address, from: Address, amount: i128) { check_admin(&e, &admin); require_positive_amount(amount); spend_balance(&e, from.clone(), amount); decrease_supply(&e, amount); @@ -82,6 +90,9 @@ impl VeritixToken { pub fn mint(e: Env, admin: Address, to: Address, amount: i128) { check_admin(&e, &admin); require_positive_amount(amount); require_not_frozen_account(&e, &to); receive_balance(&e, to.clone(), amount); increase_supply(&e, amount); + pub fn mint(e: Env, admin: Address, to: Address, amount: i128) { + check_admin(&e, &admin); require_positive_amount(amount); require_not_frozen_account(&e, &to); + receive_balance(&e, to.clone(), amount); increase_supply(&e, amount); // --- Token interface --- pub fn mint(e: Env, admin: Address, to: Address, amount: i128) { @@ -113,6 +124,8 @@ impl VeritixToken { spend_balance(&e, from.clone(), amount); receive_balance(&e, to.clone(), amount); spend_allowance(&e, from.clone(), spender.clone(), amount); spend_balance(&e, from.clone(), amount); receive_balance(&e, to.clone(), amount); + spend_allowance(&e, from.clone(), spender.clone(), amount); + spend_balance(&e, from.clone(), amount); receive_balance(&e, to.clone(), amount); spender.require_auth(); require_positive_amount(amount); require_not_frozen_account(&e, &from); @@ -140,6 +153,8 @@ impl VeritixToken { spend_balance(&e, from.clone(), amount); decrease_supply(&e, amount); spend_allowance(&e, from.clone(), spender.clone(), amount); spend_balance(&e, from.clone(), amount); decrease_supply(&e, amount); + spend_allowance(&e, from.clone(), spender.clone(), amount); + spend_balance(&e, from.clone(), amount); decrease_supply(&e, amount); spender.require_auth(); require_positive_amount(amount); require_not_frozen_account(&e, &from); @@ -211,6 +226,9 @@ impl VeritixToken { pub fn get_dispute(e: Env, dispute_id: u32) -> DisputeRecord { dispute_get(&e, dispute_id) } resolve_dispute(&e, resolver, dispute_id, release_to_beneficiary) } + pub fn get_dispute(e: Env, dispute_id: u32) -> DisputeRecord { dispute_get(&e, dispute_id) } + resolve_dispute(&e, resolver, dispute_id, release_to_beneficiary) + } pub fn get_dispute(e: Env, dispute_id: u32) -> DisputeRecord { dispute_get(&e, dispute_id) } pub fn resolve_dispute(e: Env, resolver: Address, dispute_id: u32, release_to_beneficiary: bool) { @@ -225,6 +243,8 @@ impl VeritixToken { crate::storage_types::bump_instance(&e); crate::storage_types::read_counter(&e, &crate::storage_types::DataKey::DisputeCount) } + pub fn get_disputes_by_resolver(e: Env, resolver: Address) -> Vec { + get_disputes_by_resolver(&e, resolver) pub fn get_open_disputes(e: Env) -> Vec { get_open_disputes(&e) } pub fn create_split(e: Env, sender: Address, recipients: Vec, total_amount: i128) -> u32 { @@ -248,13 +268,12 @@ impl VeritixToken { 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 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 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); @@ -271,6 +290,11 @@ impl VeritixToken { } 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) } + 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) } // --- Recurring Payments --- diff --git a/veritixpay/contract/token/src/dispute.rs b/veritixpay/contract/token/src/dispute.rs index 5f2f4db..23fed13 100644 --- a/veritixpay/contract/token/src/dispute.rs +++ b/veritixpay/contract/token/src/dispute.rs @@ -24,6 +24,8 @@ pub struct DisputeRecord { pub status: DisputeStatus, } +fn append_resolver_dispute(e: &Env, resolver: &Address, id: u32) { + let key = DataKey::ResolverDisputes(resolver.clone()); fn append_open_dispute(e: &Env, id: u32) { let key = DataKey::OpenDisputes; let mut ids: Vec = e.storage().persistent().get(&key).unwrap_or_else(|| vec![e]); @@ -32,12 +34,24 @@ fn append_open_dispute(e: &Env, id: u32) { e.storage().persistent().extend_ttl(&key, PERSISTENT_LIFETIME_THRESHOLD, PERSISTENT_BUMP_AMOUNT); } +fn remove_resolver_dispute(e: &Env, resolver: &Address, id: u32) { + let key = DataKey::ResolverDisputes(resolver.clone()); fn remove_open_dispute(e: &Env, id: u32) { let key = DataKey::OpenDisputes; 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 v != id { updated.push_back(v); } @@ -63,6 +77,7 @@ pub fn open_dispute(e: &Env, claimant: Address, escrow_id: u32, resolver: Addres } let count = increment_counter(e, &DataKey::DisputeCount); let record = DisputeRecord { + id: count, escrow_id, claimant: claimant.clone(), resolver: resolver.clone(), status: DisputeStatus::Open, id: count, escrow_id, claimant: claimant.clone(), resolver, status: DisputeStatus::Open, }; let dispute_key = DataKey::Dispute(count); @@ -71,6 +86,7 @@ pub fn open_dispute(e: &Env, claimant: Address, escrow_id: u32, resolver: Addres 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); + append_resolver_dispute(e, &resolver, count); append_open_dispute(e, count); e.events().publish((symbol_short!("dispute_opened"), escrow_id, claimant.clone()), ()); count @@ -102,6 +118,7 @@ pub fn resolve_dispute(e: &Env, resolver: Address, dispute_id: u32, release_to_b 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); + 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); @@ -117,6 +134,8 @@ pub fn get_dispute(e: &Env, dispute_id: u32) -> DisputeRecord { record } +pub fn get_disputes_by_resolver(e: &Env, resolver: Address) -> Vec { + let key = DataKey::ResolverDisputes(resolver); pub fn get_open_disputes(e: &Env) -> Vec { let key = DataKey::OpenDisputes; e.storage().persistent().get(&key).unwrap_or_else(|| vec![e]) diff --git a/veritixpay/contract/token/src/storage_types.rs b/veritixpay/contract/token/src/storage_types.rs index fbb923a..9bea610 100644 --- a/veritixpay/contract/token/src/storage_types.rs +++ b/veritixpay/contract/token/src/storage_types.rs @@ -41,6 +41,7 @@ pub enum DataKey { DisputeCount, Dispute(u32), EscrowDispute(u32), + ResolverDisputes(Address), OpenDisputes, Freeze(Address), }