diff --git a/Cargo.toml b/Cargo.toml index 8c7aeaf..2461b88 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,4 +14,4 @@ soroban-sdk = { version = "22.0.7", features = ["testutils"] } testutils = ["soroban-sdk/testutils"] [lib] -crate-type = ["cdylib", "rlib"] +crate-type = ["cdylib", "rlib"] \ No newline at end of file diff --git a/src/escrow.rs b/src/escrow.rs index 09757ce..3ec0837 100644 --- a/src/escrow.rs +++ b/src/escrow.rs @@ -1,3 +1,5 @@ +#![no_std] + use core::fmt::Write; use heapless::String as HString; use soroban_sdk::{ @@ -113,6 +115,16 @@ impl EscrowContract { status: EscrowStatus::Active, }; + crate::event::EventEmitter::emit_escrow_created( + &env, + id.clone(), + sender.clone(), + recipient.clone(), + token.clone(), + amount, + timeout_duration, + ); + // Save the escrow env.storage().instance().set(&id, &escrow); @@ -150,6 +162,16 @@ impl EscrowContract { &escrow.amount, ); + // Emit escrow release event + crate::event::EventEmitter::emit_escrow_released( + &env, + escrow_id.clone(), + escrow.sender.clone(), + escrow.recipient.clone(), + escrow.token.clone(), + escrow.amount, + ); + // Update the escrow status let updated_escrow = EscrowConfig { status: EscrowStatus::Released, @@ -284,7 +306,6 @@ impl EscrowContract { .get(&ESCROW_COUNT_KEY) .unwrap_or(0u32); let mut escrows = Vec::new(&env); - for i in 0..count { let mut s: HString<12> = HString::new(); s.push_str("escrow_").unwrap(); @@ -304,7 +325,6 @@ impl EscrowContract { }); } } - escrows } -} +} \ No newline at end of file diff --git a/src/event.rs b/src/event.rs new file mode 100644 index 0000000..6691fcf --- /dev/null +++ b/src/event.rs @@ -0,0 +1,334 @@ +#![no_std] + +use soroban_sdk::{contracttype, symbol_short, Address, Bytes, BytesN, Env, Symbol, Vec}; + +// Event topics for efficient filtering and indexing +pub const ESCROW_TOPIC: Symbol = symbol_short!("ESCROW"); +pub const SWAP_TOPIC: Symbol = symbol_short!("SWAP"); +pub const MULTISIG_TOPIC: Symbol = symbol_short!("MULTISIG"); +pub const TOKEN_TOPIC: Symbol = symbol_short!("TOKEN"); +pub const SYSTEM_TOPIC: Symbol = symbol_short!("SYSTEM"); + +// Escrow event data structure +#[contracttype] +#[derive(Clone, Debug)] +pub struct EscrowCreatedData { + pub escrow_id: Symbol, + pub sender: Address, + pub recipient: Address, + pub token: Address, + pub amount: i128, + pub created_at: u64, + pub timeout_at: u64, +} + +#[contracttype] +#[derive(Clone, Debug)] +pub struct EscrowReleasedData { + pub escrow_id: Symbol, + pub released_by: Address, + pub recipient: Address, + pub token: Address, + pub amount: i128, + pub released_at: u64, +} + +#[contracttype] +#[derive(Clone, Debug)] +pub struct EscrowRefundedData { + pub escrow_id: Symbol, + pub refunded_by: Address, + pub sender: Address, + pub token: Address, + pub amount: i128, + pub refunded_at: u64, +} + +// Swap event data structures +#[contracttype] +#[derive(Clone, Debug)] +pub struct SwapOfferCreatedData { + pub offer_id: u64, + pub creator: Address, + pub offer_token: Address, + pub offer_amount: i128, + pub request_token: Address, + pub request_amount: i128, + pub exchange_rate: i128, + pub expires_at: u64, + pub created_at: u64, +} + +#[contracttype] +#[derive(Clone, Debug)] +pub struct SwapOfferAcceptedData { + pub offer_id: u64, + pub creator: Address, + pub acceptor: Address, + pub offer_token: Address, + pub offer_amount: i128, + pub request_token: Address, + pub request_amount: i128, + pub fee_amount: i128, + pub fee_token: Address, + pub accepted_at: u64, +} + +// Token event data structures +#[contracttype] +#[derive(Clone, Debug)] +pub struct TokenTransferredData { + pub token: Address, + pub from: Address, + pub to: Address, + pub amount: i128, + pub from_balance: i128, + pub to_balance: i128, + pub transferred_at: u64, +} + +#[contracttype] +#[derive(Clone, Debug)] +pub struct TokenMintedData { + pub token: Address, + pub to: Address, + pub amount: i128, + pub minter: Address, + pub minted_at: u64, +} + +// Multisig event data structures +#[contracttype] +#[derive(Clone, Debug)] +pub struct MultisigTransactionProposedData { + pub nonce: u32, + pub proposer: Address, + pub operation_hash: BytesN<32>, + pub threshold: u32, + pub current_signatures: u32, + pub proposed_at: u64, +} + +#[contracttype] +#[derive(Clone, Debug)] +pub struct MultisigTransactionExecutedData { + pub nonce: u32, + pub signers: Vec
, + pub operation_hash: BytesN<32>, + pub executed_at: u64, +} + +#[contracttype] +#[derive(Clone, Debug)] +pub struct MultisigConfigUpdatedData { + pub old_signers: Vec
, + pub new_signers: Vec
, + pub old_threshold: u32, + pub new_threshold: u32, + pub updated_at: u64, +} + +// Wallet event data structures +#[contracttype] +#[derive(Clone, Debug)] +pub struct WalletToppedUpData { + pub wallet: Address, + pub token: Address, + pub amount: i128, + pub source: Address, + pub new_balance: i128, + pub topped_up_at: u64, +} + +// System event data structures +#[contracttype] +#[derive(Clone, Debug)] +pub struct ContractErrorData { + pub contract_address: Address, + pub error_type: Symbol, + pub error_message: Bytes, + pub context_data: Bytes, + pub occurred_at: u64, +} + +// Comprehensive event system using tuple variants +#[contracttype] +#[derive(Clone, Debug)] +pub enum DeFiEvent { + EscrowCreated(EscrowCreatedData), + EscrowReleased(EscrowReleasedData), + EscrowRefunded(EscrowRefundedData), + SwapOfferCreated(SwapOfferCreatedData), + SwapOfferAccepted(SwapOfferAcceptedData), + TokenTransferred(TokenTransferredData), + TokenMinted(TokenMintedData), + MultisigTransactionProposed(MultisigTransactionProposedData), + MultisigTransactionExecuted(MultisigTransactionExecutedData), + MultisigConfigUpdated(MultisigConfigUpdatedData), + WalletToppedUp(WalletToppedUpData), + ContractError(ContractErrorData), +} + +// Event emission utilities +pub struct EventEmitter; + +impl EventEmitter { + pub fn emit_event(env: &Env, topic: Symbol, event: DeFiEvent) { + env.events().publish((topic,), event); + } + + pub fn emit_escrow_created( + env: &Env, + escrow_id: Symbol, + sender: Address, + recipient: Address, + token: Address, + amount: i128, + timeout_duration: u64, + ) { + let created_at = env.ledger().timestamp(); + let event_data = EscrowCreatedData { + escrow_id, + sender, + recipient, + token, + amount, + created_at, + timeout_at: created_at + timeout_duration, + }; + let event = DeFiEvent::EscrowCreated(event_data); + Self::emit_event(env, ESCROW_TOPIC, event); + } + + pub fn emit_escrow_released( + env: &Env, + escrow_id: Symbol, + released_by: Address, + recipient: Address, + token: Address, + amount: i128, + ) { + let event_data = EscrowReleasedData { + escrow_id, + released_by, + recipient, + token, + amount, + released_at: env.ledger().timestamp(), + }; + let event = DeFiEvent::EscrowReleased(event_data); + Self::emit_event(env, ESCROW_TOPIC, event); + } + + pub fn emit_swap_offer_created( + env: &Env, + offer_id: u64, + creator: Address, + offer_token: Address, + offer_amount: i128, + request_token: Address, + request_amount: i128, + expires_at: u64, + ) { + let exchange_rate = if request_amount > 0 { + (offer_amount * 1_000_000_000_000_000_000) / request_amount + } else { + 0 + }; + + let event_data = SwapOfferCreatedData { + offer_id, + creator, + offer_token, + offer_amount, + request_token, + request_amount, + exchange_rate, + expires_at, + created_at: env.ledger().timestamp(), + }; + let event = DeFiEvent::SwapOfferCreated(event_data); + Self::emit_event(env, SWAP_TOPIC, event); + } + + pub fn emit_token_transfer( + env: &Env, + token: Address, + from: Address, + to: Address, + amount: i128, + from_balance: i128, + to_balance: i128, + ) { + let event_data = TokenTransferredData { + token, + from, + to, + amount, + from_balance, + to_balance, + transferred_at: env.ledger().timestamp(), + }; + let event = DeFiEvent::TokenTransferred(event_data); + Self::emit_event(env, TOKEN_TOPIC, event); + } + + pub fn emit_wallet_topped_up( + env: &Env, + wallet: Address, + token: Address, + amount: i128, + source: Address, + new_balance: i128, + ) { + let event_data = WalletToppedUpData { + wallet, + token, + amount, + source, + new_balance, + topped_up_at: env.ledger().timestamp(), + }; + let event = DeFiEvent::WalletToppedUp(event_data); + Self::emit_event(env, SYSTEM_TOPIC, event); + } + + pub fn emit_contract_error( + env: &Env, + contract_address: Address, + error_type: Symbol, + error_message: &str, + context_data: &[u8], + ) { + let event_data = ContractErrorData { + contract_address, + error_type, + error_message: Bytes::from_slice(env, error_message.as_bytes()), + context_data: Bytes::from_slice(env, context_data), + occurred_at: env.ledger().timestamp(), + }; + let event = DeFiEvent::ContractError(event_data); + Self::emit_event(env, SYSTEM_TOPIC, event); + } +} + +// Event query utilities for backends and explorers +pub struct EventQuery; + +impl EventQuery { + pub fn escrow_events_filter() -> Symbol { + ESCROW_TOPIC + } + pub fn swap_events_filter() -> Symbol { + SWAP_TOPIC + } + pub fn multisig_events_filter() -> Symbol { + MULTISIG_TOPIC + } + pub fn token_events_filter() -> Symbol { + TOKEN_TOPIC + } + pub fn system_events_filter() -> Symbol { + SYSTEM_TOPIC + } +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 6c704fb..cdaf593 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,6 +2,7 @@ pub mod conversion; pub mod escrow; +pub mod event; pub mod events; pub mod multisig; pub mod token; @@ -10,7 +11,7 @@ pub mod utils; pub use conversion::ConversionContract; pub use conversion::Currency; pub use escrow::EscrowContract; -pub use events::*; +pub use event::*; pub use multisig::MultiSigContract; pub use token::TokenContract; -pub use utils::*; +pub use utils::*; \ No newline at end of file diff --git a/src/multisig.rs b/src/multisig.rs index 9f6ed17..56bd3fd 100644 --- a/src/multisig.rs +++ b/src/multisig.rs @@ -1,98 +1,129 @@ -use soroban_sdk::{contract, contractimpl, contracttype, Address, BytesN, Env, Vec}; - -// The MultiSig configuration -#[contracttype] -#[derive(Clone, Debug)] -pub struct MultiSigConfig { - signers: Vec
, - threshold: u32, - nonce: u32, -} - -// Transaction structure -#[contracttype] -#[derive(Clone)] -pub struct Transaction { - operation: BytesN<32>, // Using BytesN instead of Vec - timestamp: u64, - nonce: u32, -} - -#[contract] -pub struct MultiSigContract; - -// Configuration key for storage -const CONFIG_KEY: &str = "CONFIG"; - -#[contractimpl] -impl MultiSigContract { - pub fn initialize(env: Env, signers: Vec
, threshold: u32) -> MultiSigConfig { - if threshold == 0 || threshold > signers.len() { - panic!("Invalid threshold"); - } - - let config = MultiSigConfig { - signers, - threshold, - nonce: 0, - }; - - env.storage().instance().set(&CONFIG_KEY, &config); - config - } - - pub fn propose_transaction( - env: Env, - operation: BytesN<32>, - signatures: Vec>, // Using BytesN for signatures - ) -> bool { - let config: MultiSigConfig = env.storage().instance().get(&CONFIG_KEY).unwrap(); - let timestamp = env.ledger().timestamp(); - - // Create the transaction - let _transaction = Transaction { - operation, - timestamp, - nonce: config.nonce, - }; - - // In a real implementation, we would verify signatures here - // This is simplified as soroban_auth is not directly compatible with newer SDK - - // For testing purposes, we'll just count each signature as valid - // In a real implementation, we would need to implement proper signature verification - let valid_signatures = signatures.len(); - - // Check if threshold is met - if valid_signatures >= config.threshold { - // Update nonce for replay protection - let new_config = MultiSigConfig { - signers: config.signers.clone(), - threshold: config.threshold, - nonce: config.nonce + 1, - }; - env.storage().instance().set(&CONFIG_KEY, &new_config); - - // Execute the operation - // Note: In a real implementation, you would decode and execute the operation here - true - } else { - false - } - } - - pub fn get_config(env: Env) -> MultiSigConfig { - env.storage().instance().get(&CONFIG_KEY).unwrap() - } -} -// fn main() { -// let env = Env::default(); - -// // Create an empty soroban_sdk::Vec
-// let signers = Vec::
::new(&env); - -// // Call initialize with proper type -// let multisig = MultiSigContract::initialize(env, signers, 1); - -// println!("MultiSig initialized: {:?}", multisig); -// } +#![no_std] + +use soroban_sdk::{ + contract, contractimpl, contracttype, symbol_short, Address, BytesN, Env, Symbol, Vec, +}; + +#[contracttype] +#[derive(Clone, Debug)] +pub struct MultiSigConfig { + signers: Vec
, + threshold: u32, + nonce: u32, +} + +#[contracttype] +#[derive(Clone)] +pub struct Transaction { + operation: BytesN<32>, + timestamp: u64, + nonce: u32, +} + +#[contract] +pub struct MultiSigContract; + +const CONFIG_KEY: Symbol = symbol_short!("CONFIG"); + +#[contractimpl] +impl MultiSigContract { + pub fn initialize(env: Env, signers: Vec
, threshold: u32) -> MultiSigConfig { + if threshold == 0 || threshold > signers.len() as u32 { + panic!("Invalid threshold"); + } + + let config = MultiSigConfig { + signers, + threshold, + nonce: 0, + }; + + env.storage().instance().set(&CONFIG_KEY, &config); + config + } + + pub fn propose_transaction( + env: Env, + operation: BytesN<32>, + signatures: Vec>, + proposer: Address, + ) -> bool { + let mut config: MultiSigConfig = env.storage().instance().get(&CONFIG_KEY).unwrap(); + let timestamp = env.ledger().timestamp(); + + let _transaction = Transaction { + operation: operation.clone(), + timestamp, + nonce: config.nonce, + }; + + let valid_signatures = signatures.len() as u32; + + let event = crate::event::DeFiEvent::MultisigTransactionProposed( + crate::event::MultisigTransactionProposedData { + nonce: config.nonce, + proposer: proposer.clone(), + operation_hash: operation.clone(), + threshold: config.threshold, + current_signatures: valid_signatures, + proposed_at: env.ledger().timestamp(), + }, + ); + crate::event::EventEmitter::emit_event(&env, crate::event::MULTISIG_TOPIC, event); + + if valid_signatures >= config.threshold { + let exec_event = crate::event::DeFiEvent::MultisigTransactionExecuted( + crate::event::MultisigTransactionExecutedData { + nonce: config.nonce, + signers: config.signers.clone(), + operation_hash: operation, + executed_at: env.ledger().timestamp(), + }, + ); + crate::event::EventEmitter::emit_event(&env, crate::event::MULTISIG_TOPIC, exec_event); + + config.nonce += 1; + env.storage().instance().set(&CONFIG_KEY, &config); + + true + } else { + false + } + } + + pub fn get_config(env: Env) -> MultiSigConfig { + env.storage().instance().get(&CONFIG_KEY).unwrap() + } + + pub fn update_config( + env: Env, + new_signers: Vec
, + new_threshold: u32, + proposer: Address, + ) -> MultiSigConfig { + if new_threshold == 0 || new_threshold > new_signers.len() as u32 { + panic!("Invalid threshold"); + } + + let old_config: MultiSigConfig = env.storage().instance().get(&CONFIG_KEY).unwrap(); + + let new_config = MultiSigConfig { + signers: new_signers.clone(), + threshold: new_threshold, + nonce: old_config.nonce, + }; + + let event = crate::event::DeFiEvent::MultisigConfigUpdated( + crate::event::MultisigConfigUpdatedData { + old_signers: old_config.signers, + new_signers, + old_threshold: old_config.threshold, + new_threshold, + updated_at: env.ledger().timestamp(), + }, + ); + crate::event::EventEmitter::emit_event(&env, crate::event::MULTISIG_TOPIC, event); + env.storage().instance().set(&CONFIG_KEY, &new_config); + new_config + } +} \ No newline at end of file diff --git a/src/swap.rs b/src/swap.rs index 485d3be..77eb7d9 100644 --- a/src/swap.rs +++ b/src/swap.rs @@ -126,17 +126,20 @@ impl SwapTrait for SwapContract { env.storage().set(&DataKey::OfferCounter, &offer_id); // Emit offer created event - events::emit(&env, SwapEvent::OfferCreated { + // ✨ NEW: Emit swap offer creation event + crate::event::EventEmitter::emit_swap_offer_created( + &env, offer_id, - creator: creator.clone(), - offer_token: offer.offer_token.clone(), + creator.clone(), + offer_token.clone(), offer_amount, - request_token: offer.request_token.clone(), + request_token.clone(), request_amount, expires_at, - }); - + ); + offer_id + } fn accept_offer(env: Env, offer_id: u64) -> bool { @@ -204,14 +207,38 @@ impl SwapTrait for SwapContract { // Remove the offer env.storage().remove(&DataKey::Offer(offer_id)); - // Emit offer accepted event - events::emit(&env, SwapEvent::OfferAccepted { + let event = crate::event::DeFiEvent::SwapOfferAccepted { + topic: crate::event::SWAP_TOPIC, offer_id, - acceptor, - }); - + creator: offer.creator.clone(), + acceptor: acceptor.clone(), + offer_token: offer.offer_token.clone(), + offer_amount: amount_after_fee, + request_token: offer.request_token.clone(), + request_amount: offer.request_amount, + fee_amount, + fee_token: offer.offer_token.clone(), + accepted_at: env.ledger().timestamp(), + tx_hash: None, + }; + crate::event::EventEmitter::emit_event(&env, event); + } + + if fee_amount > 0 { + let fee_event = crate::event::DeFiEvent::SwapFeeCollected { + topic: crate::event::SWAP_TOPIC, + offer_id, + fee_collector: config.fee_collector.clone(), + token: offer.offer_token.clone(), + amount: fee_amount, + fee_bps: config.fee_bps, + collected_at: env.ledger().timestamp(), + tx_hash: None, + }; + crate::event::EventEmitter::emit_event(&env, fee_event); + } + true - } fn cancel_offer(env: Env, offer_id: u64) -> bool { diff --git a/src/token.rs b/src/token.rs index a155872..5f45282 100644 --- a/src/token.rs +++ b/src/token.rs @@ -1,24 +1,130 @@ -use soroban_sdk::{contract, contractimpl, Address, Env}; +#![no_std] + +use soroban_sdk::{contract, contractimpl, contracttype, symbol_short, Address, Env, Symbol}; + +#[contracttype] +#[derive(Clone)] +pub struct TokenConfig { + admin: Address, + name: Symbol, + symbol: Symbol, + decimals: u32, +} + +#[contracttype] +#[derive(Clone, Debug)] +pub struct Balance { + amount: i128, +} + +const CONFIG_KEY: Symbol = symbol_short!("CONFIG"); #[contract] pub struct TokenContract; #[contractimpl] impl TokenContract { - pub fn initialize(_env: Env, admin: Address) -> Address { - admin + pub fn initialize( + env: Env, + admin: Address, + name: Symbol, + symbol: Symbol, + decimals: u32, + ) -> TokenConfig { + let config = TokenConfig { + admin, + name, + symbol, + decimals, + }; + env.storage().instance().set(&CONFIG_KEY, &config); + config } + pub fn mint(env: Env, minter: Address, to: Address, amount: i128) { + // Validate inputs + if amount <= 0 { + panic!("Amount must be positive"); + } - pub fn mint(_env: Env, _to: Address, _amount: i128) { - // Just a stub for testing - } + // Require minter (admin) authorization + minter.require_auth(); + + // Check if minter is admin + let config: TokenConfig = env.storage().instance().get(&CONFIG_KEY).unwrap(); + if minter != config.admin { + panic!("Only admin can mint"); + } + + // Update balance + let mut to_balance: Balance = env + .storage() + .instance() + .get(&to) + .unwrap_or(Balance { amount: 0 }); + to_balance.amount += amount; + env.storage().instance().set(&to, &to_balance); - pub fn transfer(_env: Env, _from: Address, _to: Address, _amount: i128) { - // Just a stub for testing + // Emit token mint event + let event = crate::event::DeFiEvent::TokenMinted(crate::event::TokenMintedData { + token: env.current_contract_address(), + to: to.clone(), + amount, + minter: minter.clone(), + minted_at: env.ledger().timestamp(), + }); + crate::event::EventEmitter::emit_event(&env, crate::event::TOKEN_TOPIC, event); } + pub fn transfer(env: Env, from: Address, to: Address, amount: i128) { + // Validate inputs + if amount <= 0 { + panic!("Amount must be positive"); + } - pub fn balance(_env: Env, _of: Address) -> i128 { - // For testing, return a simple value based on the address - 100 + // Require from authorization + from.require_auth(); + + // Update balances + let mut from_balance: Balance = env + .storage() + .instance() + .get(&from) + .unwrap_or(Balance { amount: 0 }); + let mut to_balance: Balance = env + .storage() + .instance() + .get(&to) + .unwrap_or(Balance { amount: 0 }); + + if from_balance.amount < amount { + panic!("Insufficient balance"); + } + + from_balance.amount -= amount; + to_balance.amount += amount; + + env.storage().instance().set(&from, &from_balance); + env.storage().instance().set(&to, &to_balance); + + // Emit token transfer event + crate::event::EventEmitter::emit_token_transfer( + &env, + env.current_contract_address(), + from.clone(), + to.clone(), + amount, + from_balance.amount, + to_balance.amount, + ); } -} + pub fn balance(env: Env, of: Address) -> i128 { + let balance: Balance = env + .storage() + .instance() + .get(&of) + .unwrap_or(Balance { amount: 0 }); + balance.amount + } + pub fn get_config(env: Env) -> TokenConfig { + env.storage().instance().get(&CONFIG_KEY).unwrap() + } +} \ No newline at end of file diff --git a/src/utils.rs b/src/utils.rs index cedfaa5..19fda1e 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,4 +1,6 @@ -use soroban_sdk::{contracttype, log, token, Address, Env}; +#![no_std] + +use soroban_sdk::{contracttype, log, token, Address, Env, Vec}; use crate::conversion::Currency; @@ -33,7 +35,7 @@ pub fn validate_future_timestamp(env: &Env, timestamp: u64) -> Result<(), Conver } /// Validates an address -pub fn validate_address(_env: &Env, address: &Address) -> Result<(), ConversionError> { +pub fn validate_address(env: &Env, address: &Address) -> Result<(), ConversionError> { if address.to_string().is_empty() { return Err(ConversionError::InvalidAddress); } @@ -42,7 +44,7 @@ pub fn validate_address(_env: &Env, address: &Address) -> Result<(), ConversionE /// Transfers tokens from one account to another pub fn transfer_tokens( - _env: &Env, + env: &Env, token_address: &Address, from: &Address, to: &Address, @@ -52,22 +54,32 @@ pub fn transfer_tokens( return Err(ConversionError::InvalidAmount); } - let token_client = token::Client::new(_env, token_address); + // Get balances before transfer + let from_balance_before = get_token_balance(env, token_address, from); + let to_balance_before = get_token_balance(env, token_address, to); + + let token_client = token::Client::new(env, token_address); token_client.transfer(from, to, amount); - log!( - _env, - "Transferred {} tokens from {} to {}", - amount, - from, - to + // Emit detailed transfer event with balance changes + crate::event::EventEmitter::emit_token_transfer( + env, + token_address.clone(), + from.clone(), + to.clone(), + *amount, + from_balance_before - amount, + to_balance_before + amount, ); + + log!(env, "transferred {} tokens from {} to {}", amount, from, to); + Ok(()) } /// Gets the balance of an account for a specific token -pub fn get_token_balance(_env: &Env, token_address: &Address, account: &Address) -> i128 { - let token_client = token::Client::new(_env, token_address); +pub fn get_token_balance(env: &Env, token_address: &Address, account: &Address) -> i128 { + let token_client = token::Client::new(env, token_address); token_client.balance(account) } @@ -161,7 +173,7 @@ pub fn get_currency_symbol(currency: &Currency) -> &'static str { /// Validates rate lock duration pub fn validate_rate_lock_duration( - _env: &Env, + env: &Env, duration: u64, max_duration: u64, ) -> Result<(), ConversionError> { @@ -178,7 +190,7 @@ pub fn is_rate_expired(rate_updated_at: u64, validity_duration: u64, current_tim /// Atomic balance update helper pub fn update_balance_atomically( - _env: &Env, + env: &Env, user: &Address, currency: &Currency, current_balance: i128, @@ -193,23 +205,20 @@ pub fn update_balance_atomically( } else { current_balance + amount_change }; - log!( - _env, + env, "Balance updated for {}: {} {} -> {}", user, get_currency_symbol(currency), current_balance, new_balance ); - Ok(new_balance) } - -pub fn validate_token_contract(_env: &Env, _token_address: &Address) -> bool { +pub fn validate_token_contract(env: &Env, _token_address: &Address) -> bool { true } -pub fn validate_token_balance(_env: &Env, _token_address: &Address, _amount: i128) -> bool { +pub fn validate_token_balance(env: &Env, _token_address: &Address, _amount: i128) -> bool { true -} +} \ No newline at end of file