Skip to content

feat: add on-chain event logging for transfers and conversions#23

Merged
portableDD merged 8 commits into
Nexacore-Org:mainfrom
Samuel1505:event-logging
Jun 5, 2025
Merged

feat: add on-chain event logging for transfers and conversions#23
portableDD merged 8 commits into
Nexacore-Org:mainfrom
Samuel1505:event-logging

Conversation

@Samuel1505
Copy link
Copy Markdown
Contributor

Description

Added an on-chain event logging for transfers and conversions in the contract

This PR introduces a robust event emission system for tracking all DeFi operations across escrow, swap, token, multisig, and system functions. The implementation provides structured event data that enables efficient monitoring, indexing for both on-chain and off-chain applications.

Related Issues #21

Changes Made

  • Created an event.rs file in the contract/src

  • Core Event Infrastructure

  • Event Topics: Added 5 categorized topics (ESCROW, SWAP, MULTISIG, TOKEN, SYSTEM) for efficient event filtering

  • Event Data Structures: Implemented 12 comprehensive event data types covering all DeFi operations

  • Unified Event Enum: Created DeFiEvent enum with tuple variants for type-safe event handling

Event Types Implemented

Escrow Events: EscrowCreated, EscrowReleased, EscrowRefunded
Swap Events: SwapOfferCreated, SwapOfferAccepted
Token Events: TokenTransferred, TokenMinted
Multisig Events: MultisigTransactionProposed, MultisigTransactionExecuted, MultisigConfigUpdated
System Events: WalletToppedUp, ContractError

Utilities

EventEmitter: Static helper methods for easy event emission with automatic timestamp handling
EventQuery: Filter utilities for backend integration and event querying

🔧 Key Features
Automatic Data Population

Timestamps automatically set using env.ledger().timestamp()
Exchange rate calculations for swap events
Timeout calculations for escrow events

Backend Integration Ready

Topic-based filtering for efficient event indexing
Structured data format compatible with block explorers
Support for real-time event streaming

Error Handling

Comprehensive error event tracking with context data
Contract address attribution for debugging
Serialized error messages and context

How to Test

Screenshots (if applicable)

Checklist

  • My code follows the project's coding style.
  • I have tested these changes locally.
  • Documentation has been updated where necessary.

@portableDD
Copy link
Copy Markdown
Contributor

@Samuel1505 please resolve confilct and fix build error

@Samuel1505
Copy link
Copy Markdown
Contributor Author

Conflict fixed @portableDD

Copy link
Copy Markdown
Contributor

@portableDD portableDD left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix build error, your work is failing to build, o please find the error throughthe ci/cd, and fix

@Samuel1505
Copy link
Copy Markdown
Contributor Author

build error fixed @portableDD

@Samuel1505 Samuel1505 requested a review from portableDD June 3, 2025 18:50
Copy link
Copy Markdown
Contributor

@portableDD portableDD left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please check properly build is still failing

@Samuel1505
Copy link
Copy Markdown
Contributor Author

can you check now? @portableDD

@portableDD
Copy link
Copy Markdown
Contributor

@Samuel1505 BUILD IS STILL FAILING

this os the error

Compiling stellar-multisig-contract v0.1.0 (/home/runner/work/NexaFx-contract/NexaFx-contract)
Running /home/runner/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/bin/rustc --crate-name stellar_multisig_contract --edition=2021 src/lib.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --crate-type cdylib --crate-type rlib --emit=dep-info,link -C embed-bitcode=no -C debuginfo=2 --check-cfg 'cfg(docsrs,test)' --check-cfg 'cfg(feature, values("testutils"))' -C metadata=11b4e65a17f28a42 --out-dir /home/runner/work/NexaFx-contract/NexaFx-contract/target/debug/deps -L dependency=/home/runner/work/NexaFx-contract/NexaFx-contract/target/debug/deps --extern heapless=/home/runner/work/NexaFx-contract/NexaFx-contract/target/debug/deps/libheapless-1ec2f96271b4ec16.rlib --extern soroban_sdk=/home/runner/work/NexaFx-contract/NexaFx-contract/target/debug/deps/libsoroban_sdk-89444520206a2aea.rlib
error: this file contains an unclosed delimiter
--> src/escrow.rs:329:7
|
62 | impl EscrowContract {
| - unclosed delimiter
...
329 | }
| ^

error: could not compile stellar-multisig-contract (lib) due to 1 previous error

Caused by:
process didn't exit successfully: /home/runner/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/bin/rustc --crate-name stellar_multisig_contract --edition=2021 src/lib.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --crate-type cdylib --crate-type rlib --emit=dep-info,link -C embed-bitcode=no -C debuginfo=2 --check-cfg 'cfg(docsrs,test)' --check-cfg 'cfg(feature, values("testutils"))' -C metadata=11b4e65a17f28a42 --out-dir /home/runner/work/NexaFx-contract/NexaFx-contract/target/debug/deps -L dependency=/home/runner/work/NexaFx-contract/NexaFx-contract/target/debug/deps --extern heapless=/home/runner/work/NexaFx-contract/NexaFx-contract/target/debug/deps/libheapless-1ec2f96271b4ec16.rlib --extern soroban_sdk=/home/runner/work/NexaFx-contract/NexaFx-contract/target/debug/deps/libsoroban_sdk-89444520206a2aea.rlib (exit status: 1)
Error: Process completed with exit code 101.

@portableDD
Copy link
Copy Markdown
Contributor

well done @Samuel1505 but you still got some errors

format error

Run cargo fmt --all -- --check
Diff in /home/runner/work/NexaFx-contract/NexaFx-contract/src/escrow.rs:328:
escrows
}
}
+
Diff in /home/runner/work/NexaFx-contract/NexaFx-contract/src/event.rs:1:
-use soroban_sdk::{contracttype, Address, Symbol, Env, Vec, BytesN, Bytes};
+use soroban_sdk::{contracttype, Address, Bytes, BytesN, Env, Symbol, Vec};

// Event topics for efficient filtering and indexing
pub const ESCROW_TOPIC: Symbol = symbol_short!("ESCROW");
Diff in /home/runner/work/NexaFx-contract/NexaFx-contract/src/event.rs:337:

// Helper macro for importing symbol_short
use soroban_sdk::symbol_short;

Diff in /home/runner/work/NexaFx-contract/NexaFx-contract/src/lib.rs:2:

pub mod conversion;
pub mod escrow;
+pub mod event;
pub mod events;
pub mod multisig;
pub mod token;
Diff in /home/runner/work/NexaFx-contract/NexaFx-contract/src/lib.rs:8:
-pub mod event;
pub mod utils;

pub use conversion::ConversionContract;
pub use conversion::Currency;
Diff in /home/runner/work/NexaFx-contract/NexaFx-contract/src/multisig.rs:1:
#![no_std]

-use soroban_sdk::{contract, contractimpl, contracttype, Address, Env, Vec, BytesN, Symbol, symbol_short};
+use soroban_sdk::{

  • contract, contractimpl, contracttype, symbol_short, Address, BytesN, Env, Symbol, Vec,
    +};

#[contracttype]
#[derive(Clone, Debug)]
Diff in /home/runner/work/NexaFx-contract/NexaFx-contract/src/multisig.rs:245:
// }
// }
// }
+
Diff in /home/runner/work/NexaFx-contract/NexaFx-contract/src/token.rs:1:
-use soroban_sdk::{contract, contractimpl, contracttype, Address, Env, Symbol, symbol_short};
+use soroban_sdk::{contract, contractimpl, contracttype, symbol_short, Address, Env, Symbol};

#[contracttype]
#[derive(Clone)]
Diff in /home/runner/work/NexaFx-contract/NexaFx-contract/src/token.rs:23:

#[contractimpl]
impl TokenContract {

  • pub fn initialize(env: Env, admin: Address, name: Symbol, symbol: Symbol, decimals: u32) -> TokenConfig {
  • pub fn initialize(

  •    env: Env,
    
  •    admin: Address,
    
  •    name: Symbol,
    
  •    symbol: Symbol,
    
  •    decimals: u32,
    
  • ) -> TokenConfig {
    let config = TokenConfig {
    admin,
    name,
    Diff in /home/runner/work/NexaFx-contract/NexaFx-contract/src/token.rs:50:
    }

    // Update balance
    
  •    let mut to_balance: Balance = env.storage().instance().get(&to).unwrap_or(Balance { amount: 0 });
    
  •    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);
    

Diff in /home/runner/work/NexaFx-contract/NexaFx-contract/src/token.rs:75:
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 });
    
  •    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");
    

Diff in /home/runner/work/NexaFx-contract/NexaFx-contract/src/token.rs:101:
}

 pub fn balance(env: Env, of: Address) -> i128 {
  •    let balance: Balance = env.storage().instance().get(&of).unwrap_or(Balance { amount: 0 });
    
  •    let balance: Balance = env
    
  •        .storage()
    
  •        .instance()
    
  •        .get(&of)
    
  •        .unwrap_or(Balance { amount: 0 });
       balance.amount
    
    }

Diff in /home/runner/work/NexaFx-contract/NexaFx-contract/src/token.rs:109:
env.storage().instance().get(&CONFIG_KEY).unwrap()
}
}

pub fn mint(_env: Env, _to: Address, _amount: i128) {
// Just a stub for testing
Diff in /home/runner/work/NexaFx-contract/NexaFx-contract/src/utils.rs:52:
return Err(ConversionError::InvalidAmount);
}

  • // 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);
    Diff in /home/runner/work/NexaFx-contract/NexaFx-contract/src/utils.rs:59:
  • let token_client = token::Client::new(env, token_address);
    token_client.transfer(from, to, amount);

Diff in /home/runner/work/NexaFx-contract/NexaFx-contract/src/utils.rs:70:
from_balance_before - amount,
to_balance_before + amount,
);

  • log!(env, "transferred {} tokens from {} to {}", amount, from, to);

    let token_client = token::Client::new(env, token_address);
    Diff in /home/runner/work/NexaFx-contract/NexaFx-contract/src/utils.rs:77:
    token_client.transfer(from, to, amount);

  • log!(
  •    env,
    
  •    "Transferred {} tokens from {} to {}",
    
  •    amount,
    
  •    from,
    
  •    to
    
  • );
  • log!(env, "Transferred {} tokens from {} to {}", amount, from, to);

    Ok(())
    }

@portableDD portableDD merged commit 0c942d2 into Nexacore-Org:main Jun 5, 2025
1 check failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants