@@ -539,7 +539,9 @@ impl StellarEscrowContract {
539539 let fee_bps = tiers:: effective_fee_bps ( & env, & seller, base_fee_bps) ;
540540 let mut trade_ids = soroban_sdk:: Vec :: new ( & env) ;
541541 let mut total_amount: u64 = 0 ;
542+ let mut total_fees: u64 = 0 ;
542543 let now = env. ledger ( ) . sequence ( ) ;
544+ let currency = types:: Currency :: Usdc ;
543545 for ( buyer, amount, arbitrator) in trades. iter ( ) {
544546 if amount == 0 { return Err ( ContractError :: InvalidAmount ) ; }
545547 if let Some ( ref arb) = arbitrator {
@@ -552,14 +554,21 @@ impl StellarEscrowContract {
552554 id : trade_id, seller : seller. clone ( ) , buyer : buyer. clone ( ) ,
553555 amount, fee, arbitrator, status : TradeStatus :: Created ,
554556 created_at : now, updated_at : now, metadata : None ,
555- currency : types :: Currency :: Usdc , expiry_time : None ,
557+ currency : currency . clone ( ) , expiry_time : None ,
556558 } ;
557559 save_trade ( & env, trade_id, & trade) ;
558560 index_trade_for_address ( & env, & seller, trade_id) ;
559561 index_trade_for_address ( & env, & buyer, trade_id) ;
562+ append_timeline_entry ( & env, trade_id, TimelineEntry { status : TradeStatus :: Created , ledger : now } ) ;
563+ users:: record_trade_created ( & env, & seller, & buyer, amount) ;
564+ admin:: on_trade_created ( & env, amount) ;
560565 trade_ids. push_back ( trade_id) ;
561566 total_amount = total_amount. checked_add ( amount) . ok_or ( ContractError :: Overflow ) ?;
567+ total_fees = total_fees. checked_add ( fee) . ok_or ( ContractError :: Overflow ) ?;
562568 }
569+ let current_fees = get_accumulated_fees ( & env) ?;
570+ set_accumulated_fees ( & env, current_fees. checked_add ( total_fees) . ok_or ( ContractError :: Overflow ) ?) ;
571+ add_currency_fees ( & env, & currency, total_fees) ?;
563572 events:: emit_batch_trades_created ( & env, trade_ids. len ( ) as u32 , total_amount) ;
564573 Ok ( trade_ids)
565574 }
@@ -577,10 +586,21 @@ impl StellarEscrowContract {
577586 let token = get_usdc_token ( & env) ?;
578587 let token_client = TokenClient :: new ( & env, & token) ;
579588 let mut total_amount: u64 = 0 ;
589+ let mut seen: soroban_sdk:: Map < u64 , bool > = soroban_sdk:: Map :: new ( & env) ;
590+ let now_ts = env. ledger ( ) . timestamp ( ) ;
580591 for trade_id in trade_ids. iter ( ) {
592+ if seen. get ( trade_id) . is_some ( ) {
593+ return Err ( ContractError :: DuplicateTradeInBatch ) ;
594+ }
595+ seen. set ( trade_id, true ) ;
581596 let trade = get_trade ( & env, trade_id) ?;
582597 if trade. status != TradeStatus :: Created { return Err ( ContractError :: InvalidStatus ) ; }
583598 if trade. buyer != buyer { return Err ( ContractError :: Unauthorized ) ; }
599+ if let Some ( expiry) = trade. expiry_time {
600+ if now_ts >= expiry {
601+ return Err ( ContractError :: TradeExpired ) ;
602+ }
603+ }
584604 total_amount = total_amount. checked_add ( trade. amount ) . ok_or ( ContractError :: Overflow ) ?;
585605 }
586606 token_client. transfer ( & buyer, & env. current_contract_address ( ) , & ( total_amount as i128 ) ) ;
@@ -590,6 +610,7 @@ impl StellarEscrowContract {
590610 trade. status = TradeStatus :: Funded ;
591611 trade. updated_at = now;
592612 save_trade ( & env, trade_id, & trade) ;
613+ append_timeline_entry ( & env, trade_id, TimelineEntry { status : TradeStatus :: Funded , ledger : now } ) ;
593614 }
594615 events:: emit_batch_trades_funded ( & env, trade_ids. len ( ) as u32 , total_amount) ;
595616 Ok ( ( ) )
@@ -610,7 +631,12 @@ impl StellarEscrowContract {
610631 let mut total_payout: u64 = 0 ;
611632 let mut total_fees: u64 = 0 ;
612633 let mut seller_payouts: soroban_sdk:: Map < Address , u64 > = soroban_sdk:: Map :: new ( & env) ;
634+ let mut seen: soroban_sdk:: Map < u64 , bool > = soroban_sdk:: Map :: new ( & env) ;
613635 for trade_id in trade_ids. iter ( ) {
636+ if seen. get ( trade_id) . is_some ( ) {
637+ return Err ( ContractError :: DuplicateTradeInBatch ) ;
638+ }
639+ seen. set ( trade_id, true ) ;
614640 let trade = get_trade ( & env, trade_id) ?;
615641 if trade. status != TradeStatus :: Completed { return Err ( ContractError :: InvalidStatus ) ; }
616642 if trade. buyer != buyer { return Err ( ContractError :: Unauthorized ) ; }
@@ -629,6 +655,8 @@ impl StellarEscrowContract {
629655 let trade = get_trade ( & env, trade_id) ?;
630656 tiers:: record_volume ( & env, & trade. seller , trade. amount ) ?;
631657 tiers:: record_volume ( & env, & trade. buyer , trade. amount ) ?;
658+ users:: record_trade_completed ( & env, & trade. seller , & trade. buyer ) ;
659+ admin:: on_trade_completed ( & env, trade. fee ) ;
632660 }
633661 events:: emit_batch_trades_confirmed ( & env, trade_ids. len ( ) as u32 , total_payout, total_fees) ;
634662 Ok ( ( ) )
0 commit comments