From 58d02018dc92f8821ecd5c717bf3f2e5679b85c5 Mon Sep 17 00:00:00 2001 From: bigben-7 Date: Thu, 23 Jul 2026 20:34:02 +0100 Subject: [PATCH 1/2] chore(contracts): remove stray non-compiling files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit vault.rs, multi.rs, ops.rs and rollback.rs were never declared as modules in lib.rs and reference undefined types (e.g. BatchWalletContract) — they are copy-pasted boilerplate from an unrelated wallet/multisig/governance project and are not part of the compiled crate. Only GistRegistry (lib.rs) is real. Remove the dead files. Fixes #864 Co-Authored-By: Claude Opus 4.8 --- contracts/src/multi.rs | 721 ----------------------------------- contracts/src/ops.rs | 775 -------------------------------------- contracts/src/rollback.rs | 634 ------------------------------- contracts/src/vault.rs | 139 ------- 4 files changed, 2269 deletions(-) delete mode 100644 contracts/src/multi.rs delete mode 100644 contracts/src/ops.rs delete mode 100644 contracts/src/rollback.rs delete mode 100644 contracts/src/vault.rs diff --git a/contracts/src/multi.rs b/contracts/src/multi.rs deleted file mode 100644 index 4c32b91d..00000000 --- a/contracts/src/multi.rs +++ /dev/null @@ -1,721 +0,0 @@ -#![no_std] -use soroban_sdk::{contract, contractimpl, contracttype, symbol_short, Address, Env, String, Vec}; - -// --------------------------------------------------------------------------- -// Data types -// --------------------------------------------------------------------------- - -#[contracttype] -#[derive(Clone)] -pub struct Gist { - pub gist_id: u64, - pub author: Option
, - pub location_cell: String, - pub content_hash: String, - pub created_at: u64, -} - -// --------------------------------------------------------------------------- -// Storage keys -// --------------------------------------------------------------------------- - -const GIST_COUNT: soroban_sdk::Symbol = symbol_short!("GCOUNT"); - -// --------------------------------------------------------------------------- -// Contract -// --------------------------------------------------------------------------- - -#[contract] -pub struct GistRegistry; - -#[contractimpl] -impl GistRegistry { - /// Register a new gist on-chain. Returns the assigned gist_id. - pub fn post_gist( - env: Env, - author: Option
, - location_cell: String, - content_hash: String, - ) -> u64 { - let gist_id: u64 = env.storage().instance().get(&GIST_COUNT).unwrap_or(0) + 1; - - let gist = Gist { - gist_id, - author, - location_cell: location_cell.clone(), - content_hash, - created_at: env.ledger().timestamp(), - }; - - env.storage().persistent().set(&gist_id, &gist); - env.storage().instance().set(&GIST_COUNT, &gist_id); - - gist_id - } - - /// Retrieve a gist record by its id. - pub fn get_gist(env: Env, gist_id: u64) -> Option { - env.storage().persistent().get(&gist_id) - } - - /// List gists whose location_cell matches the given cell string. - /// `cursor` is the gist_id to start scanning from (inclusive); `limit` caps results. - pub fn list_gists_by_cell( - env: Env, - location_cell: String, - cursor: u64, - limit: u32, - ) -> Vec { - let total: u64 = env.storage().instance().get(&GIST_COUNT).unwrap_or(0); - let mut results = Vec::new(&env); - let mut count: u32 = 0; - - let start = if cursor == 0 { 1 } else { cursor }; - - for id in start..=total { - if count >= limit { - break; - } - if let Some(gist) = env.storage().persistent().get::(&id) { - if gist.location_cell == location_cell { - results.push_back(gist); - count += 1; - } - } - } - - results - } -} - -// --------------------------------------------------------------------------- -// Tests -// --------------------------------------------------------------------------- - -#[cfg(test)] -mod tests { - use super::*; - use soroban_sdk::testutils::Ledger; - use soroban_sdk::{Env, String}; - - #[test] - fn test_post_and_get_gist() { - let env = Env::default(); - let contract_id = env.register(GistRegistry, ()); - let client = GistRegistryClient::new(&env, &contract_id); - - env.ledger().set_timestamp(1_000_000); - - let location = String::from_str(&env, "r3gx"); - let hash = String::from_str(&env, "QmTest123"); - - let id = client.post_gist(&None, &location, &hash); - assert_eq!(id, 1); - - let gist = client.get_gist(&id).expect("gist should exist"); - assert_eq!(gist.gist_id, 1); - assert_eq!(gist.location_cell, location); - assert_eq!(gist.content_hash, hash); - assert_eq!(gist.created_at, 1_000_000); - } - - #[test] - fn test_list_gists_by_cell() { - let env = Env::default(); - let contract_id = env.register(GistRegistry, ()); - let client = GistRegistryClient::new(&env, &contract_id); - - let cell_a = String::from_str(&env, "r3gx"); - let cell_b = String::from_str(&env, "u4ht"); - let hash = String::from_str(&env, "Qm000"); - - client.post_gist(&None, &cell_a, &hash); - client.post_gist(&None, &cell_b, &hash); - client.post_gist(&None, &cell_a, &hash); - - let results = client.list_gists_by_cell(&cell_a, &0, &10); - assert_eq!(results.len(), 2); - } -} -use soroban_sdk::{ - contracterror, contracttype, panic_with_error, symbol_short, Address, Env, Symbol, Vec, -}; - -#[derive(Clone)] -#[contracttype] -pub enum DataKey { - Admin, - Signers, - Threshold, - HighValueThreshold, - NextTxId, - PendingTx(u64), - Approval(u64, Address), - ApprovalCount(u64), - Balance(Address), -} - -#[derive(Clone)] -#[contracttype] -pub struct PendingTx { - pub id: u64, - pub from: Address, - pub to: Address, - pub amount: i128, - pub payload: Symbol, - pub asset: Option
, - pub created_at: u64, - pub executed: bool, -} - -#[contracterror] -#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] -#[repr(u32)] -pub enum MultiSigError { - NotInitialized = 1, - AlreadyInitialized = 2, - Unauthorized = 3, - InvalidThreshold = 4, - DuplicateSigner = 5, - InvalidAmount = 6, - PendingTxNotFound = 7, - UnauthorizedSigner = 8, - DuplicateApproval = 9, - AlreadyExecuted = 10, - InsufficientBalance = 11, - MultisigNotConfigured = 12, - Overflow = 13, -} - -pub struct MultisigEvents; - -impl MultisigEvents { - pub fn pending_created(env: &Env, tx: &PendingTx) { - let topics = (symbol_short!("tx"), symbol_short!("pending"), tx.id); - env.events().publish( - topics, - (tx.from.clone(), tx.to.clone(), tx.amount, tx.asset.clone()), - ); - } - - pub fn approval_recorded( - env: &Env, - tx_id: u64, - signer: &Address, - approvals_count: u32, - threshold: u32, - ) { - let topics = (symbol_short!("approve"), symbol_short!("record"), tx_id); - env.events() - .publish(topics, (signer.clone(), approvals_count, threshold)); - } - - pub fn transaction_executed(env: &Env, tx: &PendingTx, executor: &Address) { - let topics = (symbol_short!("tx"), symbol_short!("executed"), tx.id); - env.events().publish( - topics, - ( - executor.clone(), - tx.from.clone(), - tx.to.clone(), - tx.amount, - tx.asset.clone(), - ), - ); - } -} - -pub fn initialize_state(env: &Env, admin: Address) { - if env.storage().instance().has(&DataKey::Admin) { - panic_with_error!(env, MultiSigError::AlreadyInitialized); - } - - env.storage().instance().set(&DataKey::Admin, &admin); - env.storage() - .instance() - .set(&DataKey::Signers, &Vec::
::new(env)); - env.storage().instance().set(&DataKey::Threshold, &0u32); - env.storage() - .instance() - .set(&DataKey::HighValueThreshold, &i128::MAX); - env.storage().instance().set(&DataKey::NextTxId, &0u64); -} - -pub fn get_admin(env: &Env) -> Address { - env.storage() - .instance() - .get(&DataKey::Admin) - .unwrap_or_else(|| panic_with_error!(env, MultiSigError::NotInitialized)) -} - -pub fn require_admin(env: &Env, caller: &Address) { - caller.require_auth(); - let admin = get_admin(env); - if admin != caller.clone() { - panic_with_error!(env, MultiSigError::Unauthorized); - } -} - -pub fn set_signers(env: &Env, caller: Address, signers: Vec
, threshold: u32) { - require_admin(env, &caller); - validate_signer_config(env, &signers, threshold); - - env.storage().instance().set(&DataKey::Signers, &signers); - env.storage() - .instance() - .set(&DataKey::Threshold, &threshold); -} - -pub fn set_high_value_threshold(env: &Env, caller: Address, amount: i128) { - require_admin(env, &caller); - - if amount < 0 { - panic_with_error!(env, MultiSigError::InvalidAmount); - } - - env.storage() - .instance() - .set(&DataKey::HighValueThreshold, &amount); -} - -pub fn get_signers(env: &Env) -> Vec
{ - env.storage() - .instance() - .get(&DataKey::Signers) - .unwrap_or_else(|| Vec::new(env)) -} - -pub fn get_threshold(env: &Env) -> u32 { - env.storage() - .instance() - .get(&DataKey::Threshold) - .unwrap_or(0) -} - -pub fn get_high_value_threshold(env: &Env) -> i128 { - env.storage() - .instance() - .get(&DataKey::HighValueThreshold) - .unwrap_or(i128::MAX) -} - -pub fn ensure_multisig_configured(env: &Env) { - let signers = get_signers(env); - let threshold = get_threshold(env); - - if signers.len() == 0 || threshold == 0 || threshold > signers.len() { - panic_with_error!(env, MultiSigError::MultisigNotConfigured); - } -} - -pub fn require_signer(env: &Env, signer: &Address) { - if !is_signer(env, signer) { - panic_with_error!(env, MultiSigError::UnauthorizedSigner); - } -} - -pub fn is_signer(env: &Env, signer: &Address) -> bool { - let signers = get_signers(env); - for configured in signers.iter() { - if configured == signer.clone() { - return true; - } - } - false -} - -pub fn next_tx_id(env: &Env) -> u64 { - let current: u64 = env - .storage() - .instance() - .get(&DataKey::NextTxId) - .unwrap_or(0); - let next = current - .checked_add(1) - .unwrap_or_else(|| panic_with_error!(env, MultiSigError::Overflow)); - - env.storage().instance().set(&DataKey::NextTxId, &next); - next -} - -pub fn has_approval(env: &Env, tx_id: u64, signer: &Address) -> bool { - env.storage() - .persistent() - .has(&DataKey::Approval(tx_id, signer.clone())) -} - -pub fn get_approval_count(env: &Env, tx_id: u64) -> u32 { - env.storage() - .persistent() - .get(&DataKey::ApprovalCount(tx_id)) - .unwrap_or(0) -} - -pub fn record_approval(env: &Env, tx_id: u64, signer: &Address) -> u32 { - if has_approval(env, tx_id, signer) { - panic_with_error!(env, MultiSigError::DuplicateApproval); - } - - env.storage() - .persistent() - .set(&DataKey::Approval(tx_id, signer.clone()), &true); - - let current = get_approval_count(env, tx_id); - let next = current - .checked_add(1) - .unwrap_or_else(|| panic_with_error!(env, MultiSigError::Overflow)); - - env.storage() - .persistent() - .set(&DataKey::ApprovalCount(tx_id), &next); - - next -} - -fn validate_signer_config(env: &Env, signers: &Vec
, threshold: u32) { - let signer_count = signers.len(); - - if signer_count == 0 || threshold == 0 || threshold > signer_count { - panic_with_error!(env, MultiSigError::InvalidThreshold); - } - - for i in 0..signer_count { - let signer_i = signers - .get(i) - .unwrap_or_else(|| panic_with_error!(env, MultiSigError::InvalidThreshold)); - - for j in (i + 1)..signer_count { - let signer_j = signers - .get(j) - .unwrap_or_else(|| panic_with_error!(env, MultiSigError::InvalidThreshold)); - if signer_i == signer_j { - panic_with_error!(env, MultiSigError::DuplicateSigner); - } - } - } -} -use soroban_sdk::{ - contract, contracterror, contractimpl, contracttype, panic_with_error, symbol_short, Address, - Env, String, -}; - -#[derive(Clone)] -#[contracttype] -pub enum GovernanceDataKey { - Admin, // To manage governance settings - RequiredApprovals, - ProposalCount, - Proposal(u32), - UserVote(u32, Address), // Proposal ID, User -> bool - ConfigValue(String), // Stores the actual config data -} - -#[derive(Clone)] -#[contracttype] -pub struct Proposal { - pub id: u32, - pub proposer: Address, - pub config_key: String, - pub config_value: String, - pub approvals: u32, - pub executed: bool, - pub deadline: u64, -} - -#[contracterror] -#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] -#[repr(u32)] -pub enum GovernanceError { - NotInitialized = 1, - AlreadyInitialized = 2, - Unauthorized = 3, - ProposalNotFound = 4, - AlreadyVoted = 5, - ProposalExpired = 6, - AlreadyExecuted = 7, - NotEnoughApprovals = 8, - Overflow = 9, - InvalidInput = 10, -} - -pub struct GovernanceEvents; - -impl GovernanceEvents { - pub fn admin_updated(env: &Env, previous_admin: &Address, new_admin: &Address) { - let topics = (symbol_short!("gov"), symbol_short!("admin")); - env.events().publish( - topics, - ( - previous_admin.clone(), - new_admin.clone(), - env.ledger().timestamp(), - ), - ); - } - - pub fn proposal_created( - env: &Env, - id: u32, - proposer: &Address, - config_key: &String, - config_value: &String, - ) { - let topics = (symbol_short!("gov"), symbol_short!("created")); - env.events().publish( - topics, - ( - id, - proposer.clone(), - config_key.clone(), - config_value.clone(), - env.ledger().timestamp(), - ), - ); - } - - pub fn voted(env: &Env, id: u32, voter: &Address) { - let topics = (symbol_short!("gov"), symbol_short!("voted")); - env.events() - .publish(topics, (id, voter.clone(), env.ledger().timestamp())); - } - - pub fn proposal_executed(env: &Env, id: u32, config_key: &String, config_value: &String) { - let topics = (symbol_short!("gov"), symbol_short!("executed")); - env.events().publish( - topics, - ( - id, - config_key.clone(), - config_value.clone(), - env.ledger().timestamp(), - ), - ); - } -} - -pub fn initialize_governance(env: &Env, admin: Address, required_approvals: u32) { - if env.storage().instance().has(&GovernanceDataKey::Admin) { - panic_with_error!(env, GovernanceError::AlreadyInitialized); - } - env.storage() - .instance() - .set(&GovernanceDataKey::Admin, &admin); - env.storage() - .instance() - .set(&GovernanceDataKey::RequiredApprovals, &required_approvals); - env.storage() - .instance() - .set(&GovernanceDataKey::ProposalCount, &0u32); -} - -pub fn require_admin(env: &Env, caller: &Address) { - caller.require_auth(); - let admin: Address = env - .storage() - .instance() - .get(&GovernanceDataKey::Admin) - .unwrap_or_else(|| panic_with_error!(env, GovernanceError::NotInitialized)); - if admin != *caller { - panic_with_error!(env, GovernanceError::Unauthorized); - } -} - -pub fn update_admin(env: &Env, current_admin: Address, new_admin: Address) { - require_admin(env, ¤t_admin); - env.storage() - .instance() - .set(&GovernanceDataKey::Admin, &new_admin); - GovernanceEvents::admin_updated(env, ¤t_admin, &new_admin); -} - -/// Maximum length for config key and value strings -const MAX_CONFIG_STRING_LENGTH: u32 = 256; - -pub fn create_proposal( - env: &Env, - proposer: Address, - config_key: String, - config_value: String, - duration_seconds: u64, -) -> u32 { - proposer.require_auth(); - - // Validate input string lengths - if config_key.len() > MAX_CONFIG_STRING_LENGTH || config_key.len() == 0 { - panic_with_error!(env, GovernanceError::InvalidInput); - } - if config_value.len() > MAX_CONFIG_STRING_LENGTH { - panic_with_error!(env, GovernanceError::InvalidInput); - } - if duration_seconds == 0 { - panic_with_error!(env, GovernanceError::InvalidInput); - } - - let count: u32 = env - .storage() - .instance() - .get(&GovernanceDataKey::ProposalCount) - .unwrap_or_else(|| panic_with_error!(env, GovernanceError::NotInitialized)); - - let new_id = count - .checked_add(1) - .unwrap_or_else(|| panic_with_error!(env, GovernanceError::Overflow)); - let current_time = env.ledger().timestamp(); - let deadline = current_time - .checked_add(duration_seconds) - .unwrap_or_else(|| panic_with_error!(env, GovernanceError::Overflow)); - - let proposal = Proposal { - id: new_id, - proposer: proposer.clone(), - config_key: config_key.clone(), - config_value: config_value.clone(), - approvals: 0, - executed: false, - deadline, - }; - - env.storage() - .persistent() - .set(&GovernanceDataKey::Proposal(new_id), &proposal); - env.storage() - .instance() - .set(&GovernanceDataKey::ProposalCount, &new_id); - - GovernanceEvents::proposal_created(env, new_id, &proposer, &config_key, &config_value); - - new_id -} - -pub fn vote_proposal(env: &Env, voter: Address, proposal_id: u32) { - voter.require_auth(); - - let mut proposal: Proposal = env - .storage() - .persistent() - .get(&GovernanceDataKey::Proposal(proposal_id)) - .unwrap_or_else(|| panic_with_error!(env, GovernanceError::ProposalNotFound)); - - if proposal.executed { - panic_with_error!(env, GovernanceError::AlreadyExecuted); - } - - if env.ledger().timestamp() > proposal.deadline { - panic_with_error!(env, GovernanceError::ProposalExpired); - } - - let vote_key = GovernanceDataKey::UserVote(proposal_id, voter.clone()); - let has_voted: bool = env.storage().persistent().get(&vote_key).unwrap_or(false); - - if has_voted { - panic_with_error!(env, GovernanceError::AlreadyVoted); - } - - env.storage().persistent().set(&vote_key, &true); - proposal.approvals = proposal - .approvals - .checked_add(1) - .unwrap_or_else(|| panic_with_error!(env, GovernanceError::Overflow)); - env.storage() - .persistent() - .set(&GovernanceDataKey::Proposal(proposal_id), &proposal); - - GovernanceEvents::voted(env, proposal_id, &voter); -} - -pub fn execute_proposal(env: &Env, caller: Address, proposal_id: u32) { - caller.require_auth(); // Anyone can trigger execution if conditions met, but auth required to trace - - let mut proposal: Proposal = env - .storage() - .persistent() - .get(&GovernanceDataKey::Proposal(proposal_id)) - .unwrap_or_else(|| panic_with_error!(env, GovernanceError::ProposalNotFound)); - - if proposal.executed { - panic_with_error!(env, GovernanceError::AlreadyExecuted); - } - - if env.ledger().timestamp() > proposal.deadline { - panic_with_error!(env, GovernanceError::ProposalExpired); - } - - let required_approvals: u32 = env - .storage() - .instance() - .get(&GovernanceDataKey::RequiredApprovals) - .unwrap_or_else(|| panic_with_error!(env, GovernanceError::NotInitialized)); - - if proposal.approvals < required_approvals { - panic_with_error!(env, GovernanceError::NotEnoughApprovals); - } - - // Apply configuration changes - env.storage().persistent().set( - &GovernanceDataKey::ConfigValue(proposal.config_key.clone()), - &proposal.config_value, - ); - - proposal.executed = true; - env.storage() - .persistent() - .set(&GovernanceDataKey::Proposal(proposal_id), &proposal); - - GovernanceEvents::proposal_executed( - env, - proposal_id, - &proposal.config_key, - &proposal.config_value, - ); -} - -#[contract] -pub struct GovernanceContract; - -#[contractimpl] -impl GovernanceContract { - pub fn initialize(env: Env, admin: Address, required_approvals: u32) { - initialize_governance(&env, admin, required_approvals); - } - - pub fn update_admin(env: Env, current_admin: Address, new_admin: Address) { - update_admin(&env, current_admin, new_admin); - } - - pub fn get_admin(env: Env) -> Address { - env.storage() - .instance() - .get(&GovernanceDataKey::Admin) - .unwrap_or_else(|| panic_with_error!(&env, GovernanceError::NotInitialized)) - } - - pub fn create_proposal( - env: Env, - proposer: Address, - config_key: String, - config_value: String, - duration_seconds: u64, - ) -> u32 { - create_proposal(&env, proposer, config_key, config_value, duration_seconds) - } - - pub fn vote_proposal(env: Env, voter: Address, proposal_id: u32) { - vote_proposal(&env, voter, proposal_id); - } - - pub fn execute_proposal(env: Env, caller: Address, proposal_id: u32) { - execute_proposal(&env, caller, proposal_id); - } - - pub fn get_proposal(env: Env, proposal_id: u32) -> Option { - env.storage() - .persistent() - .get(&GovernanceDataKey::Proposal(proposal_id)) - } - - pub fn get_config(env: Env, config_key: String) -> Option { - env.storage() - .persistent() - .get(&GovernanceDataKey::ConfigValue(config_key)) - } -} diff --git a/contracts/src/ops.rs b/contracts/src/ops.rs deleted file mode 100644 index c6a83838..00000000 --- a/contracts/src/ops.rs +++ /dev/null @@ -1,775 +0,0 @@ -//! Integration tests for the Batch Wallet Creation Contract. - -#![cfg(test)] - -use crate::{ - BatchCreateResult, BatchRecoveryResult, BatchWalletContract, BatchWalletContractClient, - WalletCreateRequest, WalletCreateResult, WalletRecoveryRequest, WalletRecoveryResult, -}; -use soroban_sdk::{ - testutils::{Address as _, Events as _, Ledger}, - Address, Env, Vec, -}; - -/// Creates a test environment with the contract deployed and initialized. -fn setup_test_env() -> (Env, Address, BatchWalletContractClient<'static>) { - let env = Env::default(); - env.mock_all_auths(); - env.ledger().with_mut(|li| { - li.sequence_number = 12345; - }); - - // Deploy batch wallet contract - let contract_id = env.register(BatchWalletContract, ()); - let client = BatchWalletContractClient::new(&env, &contract_id); - - let admin = Address::generate(&env); - client.initialize(&admin); - - (env, admin, client) -} - -/// Helper to create a wallet creation request. -fn create_wallet_request(_env: &Env, owner: Address) -> WalletCreateRequest { - WalletCreateRequest { owner } -} - -fn create_recovery_request( - _env: &Env, - old_owner: Address, - new_owner: Address, -) -> WalletRecoveryRequest { - WalletRecoveryRequest { - old_owner, - new_owner, - } -} - -// Initialization Tests - -#[test] -fn test_initialize_contract() { - let (_env, admin, client) = setup_test_env(); - - assert_eq!(client.get_admin(), admin); - assert_eq!(client.get_total_batches(), 0); - assert_eq!(client.get_total_wallets_created(), 0); -} - -#[test] -#[should_panic(expected = "Contract already initialized")] -fn test_cannot_initialize_twice() { - let (env, admin, client) = setup_test_env(); - - let new_admin = Address::generate(&env); - client.initialize(&new_admin); -} - -// Batch Wallet Creation Tests - -#[test] -fn test_batch_create_wallets_single() { - let (env, admin, client) = setup_test_env(); - - let owner = Address::generate(&env); - - let mut requests: Vec = Vec::new(&env); - requests.push_back(create_wallet_request(&env, owner.clone())); - - let result = client.batch_create_wallets(&admin, &requests); - - assert_eq!(result.total_requests, 1); - assert_eq!(result.successful, 1); - assert_eq!(result.failed, 0); - assert_eq!(result.results.len(), 1); - - // Check wallet was created - let wallet = client.get_wallet(&owner).unwrap(); - assert_eq!(wallet.owner, owner); - assert_eq!(wallet.id, 1); -} - -#[test] -fn test_batch_create_wallets_multiple() { - let (env, admin, client) = setup_test_env(); - - let owner1 = Address::generate(&env); - let owner2 = Address::generate(&env); - let owner3 = Address::generate(&env); - - let mut requests: Vec = Vec::new(&env); - requests.push_back(create_wallet_request(&env, owner1.clone())); - requests.push_back(create_wallet_request(&env, owner2.clone())); - requests.push_back(create_wallet_request(&env, owner3.clone())); - - let result = client.batch_create_wallets(&admin, &requests); - - assert_eq!(result.total_requests, 3); - assert_eq!(result.successful, 3); - assert_eq!(result.failed, 0); - - // Check wallets were created with sequential IDs - let wallet1 = client.get_wallet(&owner1).unwrap(); - assert_eq!(wallet1.id, 1); - let wallet2 = client.get_wallet(&owner2).unwrap(); - assert_eq!(wallet2.id, 2); - let wallet3 = client.get_wallet(&owner3).unwrap(); - assert_eq!(wallet3.id, 3); -} - -#[test] -fn test_batch_create_wallets_partial_failures() { - let (env, admin, client) = setup_test_env(); - - let owner1 = Address::generate(&env); - let owner2 = Address::generate(&env); - let owner3 = Address::generate(&env); - - // First batch: create wallets for owner1 and owner2 - let mut requests1: Vec = Vec::new(&env); - requests1.push_back(create_wallet_request(&env, owner1.clone())); - requests1.push_back(create_wallet_request(&env, owner2.clone())); - client.batch_create_wallets(&admin, &requests1); - - // Second batch: try to create for owner1 (duplicate), owner2 (duplicate), owner3 (new) - let mut requests2: Vec = Vec::new(&env); - requests2.push_back(create_wallet_request(&env, owner1.clone())); // Duplicate - requests2.push_back(create_wallet_request(&env, owner2.clone())); // Duplicate - requests2.push_back(create_wallet_request(&env, owner3.clone())); // New - - let result = client.batch_create_wallets(&admin, &requests2); - - assert_eq!(result.total_requests, 3); - assert_eq!(result.successful, 1); - assert_eq!(result.failed, 2); - - // Check results - match result.results.get(0).unwrap() { - WalletCreateResult::Failure(addr, error_code) => { - assert_eq!(addr, owner1); - assert_eq!(error_code, 1); // Already exists - } - _ => panic!("Expected failure for duplicate"), - } - match result.results.get(1).unwrap() { - WalletCreateResult::Failure(addr, error_code) => { - assert_eq!(addr, owner2); - assert_eq!(error_code, 1); // Already exists - } - _ => panic!("Expected failure for duplicate"), - } - match result.results.get(2).unwrap() { - WalletCreateResult::Success(addr) => { - assert_eq!(addr, owner3); - } - _ => panic!("Expected success for new wallet"), - } - - // Check wallet3 was created - let wallet3 = client.get_wallet(&owner3).unwrap(); - assert_eq!(wallet3.id, 3); // IDs continue from previous batch -} - -#[test] -fn test_batch_create_wallets_events_emitted() { - let (env, admin, client) = setup_test_env(); - - let owner1 = Address::generate(&env); - let owner2 = Address::generate(&env); - - let mut requests: Vec = Vec::new(&env); - requests.push_back(create_wallet_request(&env, owner1.clone())); - requests.push_back(create_wallet_request(&env, owner2.clone())); - - client.batch_create_wallets(&admin, &requests); - - let events = env.events().all(); - // Should have: batch_started, wallet_created (2), batch_completed - assert!(events.len() >= 4); -} - -#[test] -fn test_batch_create_wallets_accumulates_stats() { - let (env, admin, client) = setup_test_env(); - - let owner1 = Address::generate(&env); - let owner2 = Address::generate(&env); - - let mut requests1: Vec = Vec::new(&env); - requests1.push_back(create_wallet_request(&env, owner1.clone())); - - let mut requests2: Vec = Vec::new(&env); - requests2.push_back(create_wallet_request(&env, owner2.clone())); - - assert_eq!(client.get_total_batches(), 0); - assert_eq!(client.get_total_wallets_created(), 0); - - client.batch_create_wallets(&admin, &requests1); - assert_eq!(client.get_total_batches(), 1); - assert_eq!(client.get_total_wallets_created(), 1); - - client.batch_create_wallets(&admin, &requests2); - assert_eq!(client.get_total_batches(), 2); - assert_eq!(client.get_total_wallets_created(), 2); -} - -#[test] -#[should_panic] -fn test_batch_create_wallets_empty_batch() { - let (env, admin, client) = setup_test_env(); - - let requests: Vec = Vec::new(&env); - client.batch_create_wallets(&admin, &requests); -} - -#[test] -#[should_panic] -fn test_batch_create_wallets_unauthorized() { - let (env, admin, client) = setup_test_env(); - - let unauthorized = Address::generate(&env); - let owner = Address::generate(&env); - - let mut requests: Vec = Vec::new(&env); - requests.push_back(create_wallet_request(&env, owner)); - - // This should panic due to unauthorized access - client.batch_create_wallets(&unauthorized, &requests); -} - -#[test] -fn test_batch_create_wallets_large_batch() { - let (env, admin, client) = setup_test_env(); - - // Create a batch with 50 owners - let mut requests: Vec = Vec::new(&env); - let mut owners: Vec
= Vec::new(&env); - - for _i in 0..50 { - let owner = Address::generate(&env); - owners.push_back(owner.clone()); - requests.push_back(create_wallet_request(&env, owner)); - } - - let result = client.batch_create_wallets(&admin, &requests); - - assert_eq!(result.total_requests, 50); - assert_eq!(result.successful, 50); - assert_eq!(result.failed, 0); - - // Check some wallets - let wallet1 = client.get_wallet(&owners.get(0).unwrap()).unwrap(); - assert_eq!(wallet1.id, 1); - let wallet50 = client.get_wallet(&owners.get(49).unwrap()).unwrap(); - assert_eq!(wallet50.id, 50); -} - -// Admin Tests - -#[test] -fn test_set_admin() { - let (env, admin, client) = setup_test_env(); - - let new_admin = Address::generate(&env); - client.set_admin(&admin, &new_admin); - - assert_eq!(client.get_admin(), new_admin); -} - -// Multiple Simultaneous Batch Creations - -#[test] -fn test_multiple_simultaneous_batch_creations() { - let (env, admin, client) = setup_test_env(); - - // First batch: 3 owners - let owner1 = Address::generate(&env); - let owner2 = Address::generate(&env); - let owner3 = Address::generate(&env); - - let mut batch1: Vec = Vec::new(&env); - batch1.push_back(create_wallet_request(&env, owner1.clone())); - batch1.push_back(create_wallet_request(&env, owner2.clone())); - batch1.push_back(create_wallet_request(&env, owner3.clone())); - - let result1 = client.batch_create_wallets(&admin, &batch1); - assert_eq!(result1.successful, 3); - - // Second batch: 2 owners (one new, one duplicate) - let owner4 = Address::generate(&env); - - let mut batch2: Vec = Vec::new(&env); - batch2.push_back(create_wallet_request(&env, owner1.clone())); // Duplicate - batch2.push_back(create_wallet_request(&env, owner4.clone())); // New - - let result2 = client.batch_create_wallets(&admin, &batch2); - assert_eq!(result2.successful, 1); - assert_eq!(result2.failed, 1); - - // Verify contract stats - assert_eq!(client.get_total_batches(), 2); - assert_eq!(client.get_total_wallets_created(), 4); // 3 + 1 -} - -#[test] -fn test_batch_recover_wallets_single_success() { - let (env, admin, client) = setup_test_env(); - - let original_owner = Address::generate(&env); - let new_owner = Address::generate(&env); - - let mut create_requests: Vec = Vec::new(&env); - create_requests.push_back(create_wallet_request(&env, original_owner.clone())); - let create_result: BatchCreateResult = client.batch_create_wallets(&admin, &create_requests); - assert_eq!(create_result.successful, 1); - - let mut recovery_requests: Vec = Vec::new(&env); - recovery_requests.push_back(create_recovery_request( - &env, - original_owner.clone(), - new_owner.clone(), - )); - - let recover_result: BatchRecoveryResult = - client.batch_recover_wallets(&admin, &recovery_requests); - - assert_eq!(recover_result.total_requests, 1); - assert_eq!(recover_result.successful, 1); - assert_eq!(recover_result.failed, 0); - assert_eq!(recover_result.results.len(), 1); - - match recover_result.results.get(0).unwrap() { - WalletRecoveryResult::Success(old, new_) => { - assert_eq!(old, original_owner); - assert_eq!(new_, new_owner); - } - _ => panic!("expected success result"), - } - - let original_wallet = client.get_wallet(&original_owner); - assert!(original_wallet.is_none()); - - let recovered_wallet = client.get_wallet(&new_owner).unwrap(); - assert_eq!(recovered_wallet.owner, new_owner); - assert_eq!(recovered_wallet.id, 1); -} - -#[test] -fn test_batch_recover_wallets_partial_failures() { - let (env, admin, client) = setup_test_env(); - - let existing_owner = Address::generate(&env); - let other_existing_owner = Address::generate(&env); - let non_existing_owner = Address::generate(&env); - let recovery_target_1 = Address::generate(&env); - let recovery_target_2 = Address::generate(&env); - - let mut create_requests: Vec = Vec::new(&env); - create_requests.push_back(create_wallet_request(&env, existing_owner.clone())); - create_requests.push_back(create_wallet_request(&env, other_existing_owner.clone())); - client.batch_create_wallets(&admin, &create_requests); - - let mut recovery_requests: Vec = Vec::new(&env); - recovery_requests.push_back(create_recovery_request( - &env, - non_existing_owner.clone(), - recovery_target_1.clone(), - )); - recovery_requests.push_back(create_recovery_request( - &env, - existing_owner.clone(), - existing_owner.clone(), - )); - recovery_requests.push_back(create_recovery_request( - &env, - existing_owner.clone(), - recovery_target_2.clone(), - )); - - let recover_result = client.batch_recover_wallets(&admin, &recovery_requests); - - assert_eq!(recover_result.total_requests, 3); - assert_eq!(recover_result.successful, 1); - assert_eq!(recover_result.failed, 2); - - match recover_result.results.get(0).unwrap() { - WalletRecoveryResult::Failure(old, new_, code) => { - assert_eq!(old, non_existing_owner); - assert_eq!(new_, recovery_target_1); - assert_eq!(code, 1); - } - _ => panic!("expected failure for non-existing source wallet"), - } - - match recover_result.results.get(1).unwrap() { - WalletRecoveryResult::Failure(old, new_, code) => { - assert_eq!(old, existing_owner); - assert_eq!(new_, existing_owner); - assert_eq!(code, 2); - } - _ => panic!("expected failure for invalid destination wallet"), - } - - match recover_result.results.get(2).unwrap() { - WalletRecoveryResult::Success(old, new_) => { - assert_eq!(old, existing_owner); - assert_eq!(new_, recovery_target_2); - } - _ => panic!("expected success for valid recovery"), - } - - let still_existing = client.get_wallet(&other_existing_owner).unwrap(); - assert_eq!(still_existing.owner, other_existing_owner); - - let recovered_wallet = client.get_wallet(&recovery_target_2).unwrap(); - assert_eq!(recovered_wallet.owner, recovery_target_2); -} - -#[test] -fn test_batch_recover_wallets_events_emitted() { - let (env, admin, client) = setup_test_env(); - - let original_owner = Address::generate(&env); - let new_owner = Address::generate(&env); - - let mut create_requests: Vec = Vec::new(&env); - create_requests.push_back(create_wallet_request(&env, original_owner.clone())); - client.batch_create_wallets(&admin, &create_requests); - - let mut recovery_requests: Vec = Vec::new(&env); - recovery_requests.push_back(create_recovery_request( - &env, - original_owner.clone(), - new_owner.clone(), - )); - - client.batch_recover_wallets(&admin, &recovery_requests); - - let events = env.events().all(); - assert!(events.len() >= 3); -} - -#[test] -#[should_panic] -fn test_batch_recover_wallets_empty_batch() { - let (env, admin, client) = setup_test_env(); - - let recovery_requests: Vec = Vec::new(&env); - client.batch_recover_wallets(&admin, &recovery_requests); -} - -#[test] -#[should_panic] -fn test_batch_recover_wallets_unauthorized() { - let (env, _admin, client) = setup_test_env(); - - let original_owner = Address::generate(&env); - let new_owner = Address::generate(&env); - - let mut recovery_requests: Vec = Vec::new(&env); - recovery_requests.push_back(create_recovery_request(&env, original_owner, new_owner)); - - let unauthorized = Address::generate(&env); - client.batch_recover_wallets(&unauthorized, &recovery_requests); -} - -// ─── Duplicate Wallet Detection Tests ────────────────────────────────────── - -#[test] -#[should_panic(expected = "Error(Contract, #6)")] -fn test_batch_create_wallets_duplicate_in_batch() { - let (env, admin, client) = setup_test_env(); - - let owner = Address::generate(&env); - let owner2 = Address::generate(&env); - - let mut requests: Vec = Vec::new(&env); - // Add duplicate requests for same owner within single batch - requests.push_back(create_wallet_request(&env, owner.clone())); - requests.push_back(create_wallet_request(&env, owner2.clone())); - requests.push_back(create_wallet_request(&env, owner.clone())); // Duplicate! - - // This should panic with DuplicateWallet error - client.batch_create_wallets(&admin, &requests); -} - -#[test] -#[should_panic(expected = "Error(Contract, #6)")] -fn test_batch_create_wallets_multiple_duplicates_in_batch() { - let (env, admin, client) = setup_test_env(); - - let owner1 = Address::generate(&env); - let owner2 = Address::generate(&env); - let owner3 = Address::generate(&env); - - let mut requests: Vec = Vec::new(&env); - requests.push_back(create_wallet_request(&env, owner1.clone())); - requests.push_back(create_wallet_request(&env, owner2.clone())); - requests.push_back(create_wallet_request(&env, owner1.clone())); // Duplicate! - requests.push_back(create_wallet_request(&env, owner3.clone())); - requests.push_back(create_wallet_request(&env, owner2.clone())); // Another duplicate! - - // This should panic with DuplicateWallet error - client.batch_create_wallets(&admin, &requests); -} - -#[test] -#[should_panic(expected = "Error(Contract, #6)")] -fn test_batch_create_wallets_consecutive_duplicates() { - let (env, admin, client) = setup_test_env(); - - let owner = Address::generate(&env); - - let mut requests: Vec = Vec::new(&env); - requests.push_back(create_wallet_request(&env, owner.clone())); - requests.push_back(create_wallet_request(&env, owner.clone())); // Duplicate! - requests.push_back(create_wallet_request(&env, owner.clone())); // Another duplicate! - - // This should panic with DuplicateWallet error - client.batch_create_wallets(&admin, &requests); -} - -#[test] -fn test_batch_create_wallets_no_duplicates_succeeds() { - let (env, admin, client) = setup_test_env(); - - let owner1 = Address::generate(&env); - let owner2 = Address::generate(&env); - let owner3 = Address::generate(&env); - - let mut requests: Vec = Vec::new(&env); - requests.push_back(create_wallet_request(&env, owner1.clone())); - requests.push_back(create_wallet_request(&env, owner2.clone())); - requests.push_back(create_wallet_request(&env, owner3.clone())); - - // This should succeed (no duplicates) - let result = client.batch_create_wallets(&admin, &requests); - - assert_eq!(result.total_requests, 3); - assert_eq!(result.successful, 3); - assert_eq!(result.failed, 0); -} - -#[test] -fn test_batch_create_wallets_duplicate_event_emitted() { - let (env, admin, client) = setup_test_env(); - - let owner = Address::generate(&env); - let owner2 = Address::generate(&env); - - let mut requests: Vec = Vec::new(&env); - requests.push_back(create_wallet_request(&env, owner.clone())); - requests.push_back(create_wallet_request(&env, owner2.clone())); - requests.push_back(create_wallet_request(&env, owner.clone())); // Duplicate - - // Attempt batch create - should fail with duplicate error - let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { - client.batch_create_wallets(&admin, &requests); - })); - - // Verify panic occurred - assert!(result.is_err()); - - // Verify duplicate event was published before panic - let events = env.events().all(); - let mut duplicate_event_found = false; - for (_, topics, _) in events.iter() { - let topic_vec = topics.clone(); - if topic_vec.len() >= 2 { - let topic1: soroban_sdk::Symbol = - topic_vec.get(0).unwrap().into_val(&env).try_into().ok(); - let topic2: soroban_sdk::Symbol = - topic_vec.get(1).unwrap().into_val(&env).try_into().ok(); - if topic1 == Some(soroban_sdk::Symbol::new(&env, "wallet")) - && topic2 == Some(soroban_sdk::Symbol::new(&env, "duplicate")) - { - duplicate_event_found = true; - break; - } - } - } - assert!(duplicate_event_found, "Duplicate event should be emitted"); -} - -#[test] -fn test_batch_create_wallets_duplicate_error_identifies_entry() { - let (env, admin, client) = setup_test_env(); - - let owner = Address::generate(&env); - let owner2 = Address::generate(&env); - let owner3 = Address::generate(&env); - - // First batch - success - let mut requests1: Vec = Vec::new(&env); - requests1.push_back(create_wallet_request(&env, owner.clone())); - requests1.push_back(create_wallet_request(&env, owner2.clone())); - client.batch_create_wallets(&admin, &requests1); - - // Second batch - with duplicate from first batch - let mut requests2: Vec = Vec::new(&env); - requests2.push_back(create_wallet_request(&env, owner.clone())); // Existed before - requests2.push_back(create_wallet_request(&env, owner3.clone())); // New - - let result = client.batch_create_wallets(&admin, &requests2); - - // Should process individually since duplicates are within-batch check - // Only existing wallets should fail, not in-batch duplicates - assert_eq!(result.total_requests, 2); - assert_eq!(result.successful, 1); - assert_eq!(result.failed, 1); - - match result.results.get(0).unwrap() { - WalletCreateResult::Failure(addr, _) => { - assert_eq!(addr, owner); // First request failed (already exists) - } - _ => panic!("Expected failure for existing wallet"), - } - - match result.results.get(1).unwrap() { - WalletCreateResult::Success(addr) => { - assert_eq!(addr, owner3); // New wallet created - } - _ => panic!("Expected success for new wallet"), - } -} - - -#![no_std] -use soroban_sdk::{contract, contractimpl, contracttype, symbol_short, Address, Env, String, Vec}; - -// --------------------------------------------------------------------------- -// Data types -// --------------------------------------------------------------------------- - -#[contracttype] -#[derive(Clone)] -pub struct Gist { - pub gist_id: u64, - pub author: Option
, - pub location_cell: String, - pub content_hash: String, - pub created_at: u64, -} - -// --------------------------------------------------------------------------- -// Storage keys -// --------------------------------------------------------------------------- - -const GIST_COUNT: soroban_sdk::Symbol = symbol_short!("GCOUNT"); - -// --------------------------------------------------------------------------- -// Contract -// --------------------------------------------------------------------------- - -#[contract] -pub struct GistRegistry; - -#[contractimpl] -impl GistRegistry { - /// Register a new gist on-chain. Returns the assigned gist_id. - pub fn post_gist( - env: Env, - author: Option
, - location_cell: String, - content_hash: String, - ) -> u64 { - let gist_id: u64 = env.storage().instance().get(&GIST_COUNT).unwrap_or(0) + 1; - - let gist = Gist { - gist_id, - author, - location_cell: location_cell.clone(), - content_hash, - created_at: env.ledger().timestamp(), - }; - - env.storage().persistent().set(&gist_id, &gist); - env.storage().instance().set(&GIST_COUNT, &gist_id); - - gist_id - } - - /// Retrieve a gist record by its id. - pub fn get_gist(env: Env, gist_id: u64) -> Option { - env.storage().persistent().get(&gist_id) - } - - /// List gists whose location_cell matches the given cell string. - /// `cursor` is the gist_id to start scanning from (inclusive); `limit` caps results. - pub fn list_gists_by_cell( - env: Env, - location_cell: String, - cursor: u64, - limit: u32, - ) -> Vec { - let total: u64 = env.storage().instance().get(&GIST_COUNT).unwrap_or(0); - let mut results = Vec::new(&env); - let mut count: u32 = 0; - - let start = if cursor == 0 { 1 } else { cursor }; - - for id in start..=total { - if count >= limit { - break; - } - if let Some(gist) = env.storage().persistent().get::(&id) { - if gist.location_cell == location_cell { - results.push_back(gist); - count += 1; - } - } - } - - results - } -} - -// --------------------------------------------------------------------------- -// Tests -// --------------------------------------------------------------------------- - -#[cfg(test)] -mod tests { - use super::*; - use soroban_sdk::testutils::Ledger; - use soroban_sdk::{Env, String}; - - #[test] - fn test_post_and_get_gist() { - let env = Env::default(); - let contract_id = env.register(GistRegistry, ()); - let client = GistRegistryClient::new(&env, &contract_id); - - env.ledger().set_timestamp(1_000_000); - - let location = String::from_str(&env, "r3gx"); - let hash = String::from_str(&env, "QmTest123"); - - let id = client.post_gist(&None, &location, &hash); - assert_eq!(id, 1); - - let gist = client.get_gist(&id).expect("gist should exist"); - assert_eq!(gist.gist_id, 1); - assert_eq!(gist.location_cell, location); - assert_eq!(gist.content_hash, hash); - assert_eq!(gist.created_at, 1_000_000); - } - - #[test] - fn test_list_gists_by_cell() { - let env = Env::default(); - let contract_id = env.register(GistRegistry, ()); - let client = GistRegistryClient::new(&env, &contract_id); - - let cell_a = String::from_str(&env, "r3gx"); - let cell_b = String::from_str(&env, "u4ht"); - let hash = String::from_str(&env, "Qm000"); - - client.post_gist(&None, &cell_a, &hash); - client.post_gist(&None, &cell_b, &hash); - client.post_gist(&None, &cell_a, &hash); - - let results = client.list_gists_by_cell(&cell_a, &0, &10); - assert_eq!(results.len(), 2); - } -} diff --git a/contracts/src/rollback.rs b/contracts/src/rollback.rs deleted file mode 100644 index b98ba82b..00000000 --- a/contracts/src/rollback.rs +++ /dev/null @@ -1,634 +0,0 @@ -//! Integration tests for the Batch Wallet Creation Contract. - -#![cfg(test)] - -use crate::{ - BatchCreateResult, BatchRecoveryResult, BatchWalletContract, BatchWalletContractClient, - WalletCreateRequest, WalletCreateResult, WalletRecoveryRequest, WalletRecoveryResult, -}; -use soroban_sdk::{ - testutils::{Address as _, Events as _, Ledger}, - Address, Env, Vec, -}; - -/// Creates a test environment with the contract deployed and initialized. -fn setup_test_env() -> (Env, Address, BatchWalletContractClient<'static>) { - let env = Env::default(); - env.mock_all_auths(); - env.ledger().with_mut(|li| { - li.sequence_number = 12345; - }); - - // Deploy batch wallet contract - let contract_id = env.register(BatchWalletContract, ()); - let client = BatchWalletContractClient::new(&env, &contract_id); - - let admin = Address::generate(&env); - client.initialize(&admin); - - (env, admin, client) -} - -/// Helper to create a wallet creation request. -fn create_wallet_request(_env: &Env, owner: Address) -> WalletCreateRequest { - WalletCreateRequest { owner } -} - -fn create_recovery_request( - _env: &Env, - old_owner: Address, - new_owner: Address, -) -> WalletRecoveryRequest { - WalletRecoveryRequest { - old_owner, - new_owner, - } -} - -// Initialization Tests - -#[test] -fn test_initialize_contract() { - let (_env, admin, client) = setup_test_env(); - - assert_eq!(client.get_admin(), admin); - assert_eq!(client.get_total_batches(), 0); - assert_eq!(client.get_total_wallets_created(), 0); -} - -#[test] -#[should_panic(expected = "Contract already initialized")] -fn test_cannot_initialize_twice() { - let (env, admin, client) = setup_test_env(); - - let new_admin = Address::generate(&env); - client.initialize(&new_admin); -} - -// Batch Wallet Creation Tests - -#[test] -fn test_batch_create_wallets_single() { - let (env, admin, client) = setup_test_env(); - - let owner = Address::generate(&env); - - let mut requests: Vec = Vec::new(&env); - requests.push_back(create_wallet_request(&env, owner.clone())); - - let result = client.batch_create_wallets(&admin, &requests); - - assert_eq!(result.total_requests, 1); - assert_eq!(result.successful, 1); - assert_eq!(result.failed, 0); - assert_eq!(result.results.len(), 1); - - // Check wallet was created - let wallet = client.get_wallet(&owner).unwrap(); - assert_eq!(wallet.owner, owner); - assert_eq!(wallet.id, 1); -} - -#[test] -fn test_batch_create_wallets_multiple() { - let (env, admin, client) = setup_test_env(); - - let owner1 = Address::generate(&env); - let owner2 = Address::generate(&env); - let owner3 = Address::generate(&env); - - let mut requests: Vec = Vec::new(&env); - requests.push_back(create_wallet_request(&env, owner1.clone())); - requests.push_back(create_wallet_request(&env, owner2.clone())); - requests.push_back(create_wallet_request(&env, owner3.clone())); - - let result = client.batch_create_wallets(&admin, &requests); - - assert_eq!(result.total_requests, 3); - assert_eq!(result.successful, 3); - assert_eq!(result.failed, 0); - - // Check wallets were created with sequential IDs - let wallet1 = client.get_wallet(&owner1).unwrap(); - assert_eq!(wallet1.id, 1); - let wallet2 = client.get_wallet(&owner2).unwrap(); - assert_eq!(wallet2.id, 2); - let wallet3 = client.get_wallet(&owner3).unwrap(); - assert_eq!(wallet3.id, 3); -} - -#[test] -fn test_batch_create_wallets_partial_failures() { - let (env, admin, client) = setup_test_env(); - - let owner1 = Address::generate(&env); - let owner2 = Address::generate(&env); - let owner3 = Address::generate(&env); - - // First batch: create wallets for owner1 and owner2 - let mut requests1: Vec = Vec::new(&env); - requests1.push_back(create_wallet_request(&env, owner1.clone())); - requests1.push_back(create_wallet_request(&env, owner2.clone())); - client.batch_create_wallets(&admin, &requests1); - - // Second batch: try to create for owner1 (duplicate), owner2 (duplicate), owner3 (new) - let mut requests2: Vec = Vec::new(&env); - requests2.push_back(create_wallet_request(&env, owner1.clone())); // Duplicate - requests2.push_back(create_wallet_request(&env, owner2.clone())); // Duplicate - requests2.push_back(create_wallet_request(&env, owner3.clone())); // New - - let result = client.batch_create_wallets(&admin, &requests2); - - assert_eq!(result.total_requests, 3); - assert_eq!(result.successful, 1); - assert_eq!(result.failed, 2); - - // Check results - match result.results.get(0).unwrap() { - WalletCreateResult::Failure(addr, error_code) => { - assert_eq!(addr, owner1); - assert_eq!(error_code, 1); // Already exists - } - _ => panic!("Expected failure for duplicate"), - } - match result.results.get(1).unwrap() { - WalletCreateResult::Failure(addr, error_code) => { - assert_eq!(addr, owner2); - assert_eq!(error_code, 1); // Already exists - } - _ => panic!("Expected failure for duplicate"), - } - match result.results.get(2).unwrap() { - WalletCreateResult::Success(addr) => { - assert_eq!(addr, owner3); - } - _ => panic!("Expected success for new wallet"), - } - - // Check wallet3 was created - let wallet3 = client.get_wallet(&owner3).unwrap(); - assert_eq!(wallet3.id, 3); // IDs continue from previous batch -} - -#[test] -fn test_batch_create_wallets_events_emitted() { - let (env, admin, client) = setup_test_env(); - - let owner1 = Address::generate(&env); - let owner2 = Address::generate(&env); - - let mut requests: Vec = Vec::new(&env); - requests.push_back(create_wallet_request(&env, owner1.clone())); - requests.push_back(create_wallet_request(&env, owner2.clone())); - - client.batch_create_wallets(&admin, &requests); - - let events = env.events().all(); - // Should have: batch_started, wallet_created (2), batch_completed - assert!(events.len() >= 4); -} - -#[test] -fn test_batch_create_wallets_accumulates_stats() { - let (env, admin, client) = setup_test_env(); - - let owner1 = Address::generate(&env); - let owner2 = Address::generate(&env); - - let mut requests1: Vec = Vec::new(&env); - requests1.push_back(create_wallet_request(&env, owner1.clone())); - - let mut requests2: Vec = Vec::new(&env); - requests2.push_back(create_wallet_request(&env, owner2.clone())); - - assert_eq!(client.get_total_batches(), 0); - assert_eq!(client.get_total_wallets_created(), 0); - - client.batch_create_wallets(&admin, &requests1); - assert_eq!(client.get_total_batches(), 1); - assert_eq!(client.get_total_wallets_created(), 1); - - client.batch_create_wallets(&admin, &requests2); - assert_eq!(client.get_total_batches(), 2); - assert_eq!(client.get_total_wallets_created(), 2); -} - -#[test] -#[should_panic] -fn test_batch_create_wallets_empty_batch() { - let (env, admin, client) = setup_test_env(); - - let requests: Vec = Vec::new(&env); - client.batch_create_wallets(&admin, &requests); -} - -#[test] -#[should_panic] -fn test_batch_create_wallets_unauthorized() { - let (env, admin, client) = setup_test_env(); - - let unauthorized = Address::generate(&env); - let owner = Address::generate(&env); - - let mut requests: Vec = Vec::new(&env); - requests.push_back(create_wallet_request(&env, owner)); - - // This should panic due to unauthorized access - client.batch_create_wallets(&unauthorized, &requests); -} - -#[test] -fn test_batch_create_wallets_large_batch() { - let (env, admin, client) = setup_test_env(); - - // Create a batch with 50 owners - let mut requests: Vec = Vec::new(&env); - let mut owners: Vec
= Vec::new(&env); - - for _i in 0..50 { - let owner = Address::generate(&env); - owners.push_back(owner.clone()); - requests.push_back(create_wallet_request(&env, owner)); - } - - let result = client.batch_create_wallets(&admin, &requests); - - assert_eq!(result.total_requests, 50); - assert_eq!(result.successful, 50); - assert_eq!(result.failed, 0); - - // Check some wallets - let wallet1 = client.get_wallet(&owners.get(0).unwrap()).unwrap(); - assert_eq!(wallet1.id, 1); - let wallet50 = client.get_wallet(&owners.get(49).unwrap()).unwrap(); - assert_eq!(wallet50.id, 50); -} - -// Admin Tests - -#[test] -fn test_set_admin() { - let (env, admin, client) = setup_test_env(); - - let new_admin = Address::generate(&env); - client.set_admin(&admin, &new_admin); - - assert_eq!(client.get_admin(), new_admin); -} - -// Multiple Simultaneous Batch Creations - -#[test] -fn test_multiple_simultaneous_batch_creations() { - let (env, admin, client) = setup_test_env(); - - // First batch: 3 owners - let owner1 = Address::generate(&env); - let owner2 = Address::generate(&env); - let owner3 = Address::generate(&env); - - let mut batch1: Vec = Vec::new(&env); - batch1.push_back(create_wallet_request(&env, owner1.clone())); - batch1.push_back(create_wallet_request(&env, owner2.clone())); - batch1.push_back(create_wallet_request(&env, owner3.clone())); - - let result1 = client.batch_create_wallets(&admin, &batch1); - assert_eq!(result1.successful, 3); - - // Second batch: 2 owners (one new, one duplicate) - let owner4 = Address::generate(&env); - - let mut batch2: Vec = Vec::new(&env); - batch2.push_back(create_wallet_request(&env, owner1.clone())); // Duplicate - batch2.push_back(create_wallet_request(&env, owner4.clone())); // New - - let result2 = client.batch_create_wallets(&admin, &batch2); - assert_eq!(result2.successful, 1); - assert_eq!(result2.failed, 1); - - // Verify contract stats - assert_eq!(client.get_total_batches(), 2); - assert_eq!(client.get_total_wallets_created(), 4); // 3 + 1 -} - -#[test] -fn test_batch_recover_wallets_single_success() { - let (env, admin, client) = setup_test_env(); - - let original_owner = Address::generate(&env); - let new_owner = Address::generate(&env); - - let mut create_requests: Vec = Vec::new(&env); - create_requests.push_back(create_wallet_request(&env, original_owner.clone())); - let create_result: BatchCreateResult = client.batch_create_wallets(&admin, &create_requests); - assert_eq!(create_result.successful, 1); - - let mut recovery_requests: Vec = Vec::new(&env); - recovery_requests.push_back(create_recovery_request( - &env, - original_owner.clone(), - new_owner.clone(), - )); - - let recover_result: BatchRecoveryResult = - client.batch_recover_wallets(&admin, &recovery_requests); - - assert_eq!(recover_result.total_requests, 1); - assert_eq!(recover_result.successful, 1); - assert_eq!(recover_result.failed, 0); - assert_eq!(recover_result.results.len(), 1); - - match recover_result.results.get(0).unwrap() { - WalletRecoveryResult::Success(old, new_) => { - assert_eq!(old, original_owner); - assert_eq!(new_, new_owner); - } - _ => panic!("expected success result"), - } - - let original_wallet = client.get_wallet(&original_owner); - assert!(original_wallet.is_none()); - - let recovered_wallet = client.get_wallet(&new_owner).unwrap(); - assert_eq!(recovered_wallet.owner, new_owner); - assert_eq!(recovered_wallet.id, 1); -} - -#[test] -fn test_batch_recover_wallets_partial_failures() { - let (env, admin, client) = setup_test_env(); - - let existing_owner = Address::generate(&env); - let other_existing_owner = Address::generate(&env); - let non_existing_owner = Address::generate(&env); - let recovery_target_1 = Address::generate(&env); - let recovery_target_2 = Address::generate(&env); - - let mut create_requests: Vec = Vec::new(&env); - create_requests.push_back(create_wallet_request(&env, existing_owner.clone())); - create_requests.push_back(create_wallet_request(&env, other_existing_owner.clone())); - client.batch_create_wallets(&admin, &create_requests); - - let mut recovery_requests: Vec = Vec::new(&env); - recovery_requests.push_back(create_recovery_request( - &env, - non_existing_owner.clone(), - recovery_target_1.clone(), - )); - recovery_requests.push_back(create_recovery_request( - &env, - existing_owner.clone(), - existing_owner.clone(), - )); - recovery_requests.push_back(create_recovery_request( - &env, - existing_owner.clone(), - recovery_target_2.clone(), - )); - - let recover_result = client.batch_recover_wallets(&admin, &recovery_requests); - - assert_eq!(recover_result.total_requests, 3); - assert_eq!(recover_result.successful, 1); - assert_eq!(recover_result.failed, 2); - - match recover_result.results.get(0).unwrap() { - WalletRecoveryResult::Failure(old, new_, code) => { - assert_eq!(old, non_existing_owner); - assert_eq!(new_, recovery_target_1); - assert_eq!(code, 1); - } - _ => panic!("expected failure for non-existing source wallet"), - } - - match recover_result.results.get(1).unwrap() { - WalletRecoveryResult::Failure(old, new_, code) => { - assert_eq!(old, existing_owner); - assert_eq!(new_, existing_owner); - assert_eq!(code, 2); - } - _ => panic!("expected failure for invalid destination wallet"), - } - - match recover_result.results.get(2).unwrap() { - WalletRecoveryResult::Success(old, new_) => { - assert_eq!(old, existing_owner); - assert_eq!(new_, recovery_target_2); - } - _ => panic!("expected success for valid recovery"), - } - - let still_existing = client.get_wallet(&other_existing_owner).unwrap(); - assert_eq!(still_existing.owner, other_existing_owner); - - let recovered_wallet = client.get_wallet(&recovery_target_2).unwrap(); - assert_eq!(recovered_wallet.owner, recovery_target_2); -} - -#[test] -fn test_batch_recover_wallets_events_emitted() { - let (env, admin, client) = setup_test_env(); - - let original_owner = Address::generate(&env); - let new_owner = Address::generate(&env); - - let mut create_requests: Vec = Vec::new(&env); - create_requests.push_back(create_wallet_request(&env, original_owner.clone())); - client.batch_create_wallets(&admin, &create_requests); - - let mut recovery_requests: Vec = Vec::new(&env); - recovery_requests.push_back(create_recovery_request( - &env, - original_owner.clone(), - new_owner.clone(), - )); - - client.batch_recover_wallets(&admin, &recovery_requests); - - let events = env.events().all(); - assert!(events.len() >= 3); -} - -#[test] -#[should_panic] -fn test_batch_recover_wallets_empty_batch() { - let (env, admin, client) = setup_test_env(); - - let recovery_requests: Vec = Vec::new(&env); - client.batch_recover_wallets(&admin, &recovery_requests); -} - -#[test] -#[should_panic] -fn test_batch_recover_wallets_unauthorized() { - let (env, _admin, client) = setup_test_env(); - - let original_owner = Address::generate(&env); - let new_owner = Address::generate(&env); - - let mut recovery_requests: Vec = Vec::new(&env); - recovery_requests.push_back(create_recovery_request(&env, original_owner, new_owner)); - - let unauthorized = Address::generate(&env); - client.batch_recover_wallets(&unauthorized, &recovery_requests); -} - -// ─── Duplicate Wallet Detection Tests ────────────────────────────────────── - -#[test] -#[should_panic(expected = "Error(Contract, #6)")] -fn test_batch_create_wallets_duplicate_in_batch() { - let (env, admin, client) = setup_test_env(); - - let owner = Address::generate(&env); - let owner2 = Address::generate(&env); - - let mut requests: Vec = Vec::new(&env); - // Add duplicate requests for same owner within single batch - requests.push_back(create_wallet_request(&env, owner.clone())); - requests.push_back(create_wallet_request(&env, owner2.clone())); - requests.push_back(create_wallet_request(&env, owner.clone())); // Duplicate! - - // This should panic with DuplicateWallet error - client.batch_create_wallets(&admin, &requests); -} - -#[test] -#[should_panic(expected = "Error(Contract, #6)")] -fn test_batch_create_wallets_multiple_duplicates_in_batch() { - let (env, admin, client) = setup_test_env(); - - let owner1 = Address::generate(&env); - let owner2 = Address::generate(&env); - let owner3 = Address::generate(&env); - - let mut requests: Vec = Vec::new(&env); - requests.push_back(create_wallet_request(&env, owner1.clone())); - requests.push_back(create_wallet_request(&env, owner2.clone())); - requests.push_back(create_wallet_request(&env, owner1.clone())); // Duplicate! - requests.push_back(create_wallet_request(&env, owner3.clone())); - requests.push_back(create_wallet_request(&env, owner2.clone())); // Another duplicate! - - // This should panic with DuplicateWallet error - client.batch_create_wallets(&admin, &requests); -} - -#[test] -#[should_panic(expected = "Error(Contract, #6)")] -fn test_batch_create_wallets_consecutive_duplicates() { - let (env, admin, client) = setup_test_env(); - - let owner = Address::generate(&env); - - let mut requests: Vec = Vec::new(&env); - requests.push_back(create_wallet_request(&env, owner.clone())); - requests.push_back(create_wallet_request(&env, owner.clone())); // Duplicate! - requests.push_back(create_wallet_request(&env, owner.clone())); // Another duplicate! - - // This should panic with DuplicateWallet error - client.batch_create_wallets(&admin, &requests); -} - -#[test] -fn test_batch_create_wallets_no_duplicates_succeeds() { - let (env, admin, client) = setup_test_env(); - - let owner1 = Address::generate(&env); - let owner2 = Address::generate(&env); - let owner3 = Address::generate(&env); - - let mut requests: Vec = Vec::new(&env); - requests.push_back(create_wallet_request(&env, owner1.clone())); - requests.push_back(create_wallet_request(&env, owner2.clone())); - requests.push_back(create_wallet_request(&env, owner3.clone())); - - // This should succeed (no duplicates) - let result = client.batch_create_wallets(&admin, &requests); - - assert_eq!(result.total_requests, 3); - assert_eq!(result.successful, 3); - assert_eq!(result.failed, 0); -} - -#[test] -fn test_batch_create_wallets_duplicate_event_emitted() { - let (env, admin, client) = setup_test_env(); - - let owner = Address::generate(&env); - let owner2 = Address::generate(&env); - - let mut requests: Vec = Vec::new(&env); - requests.push_back(create_wallet_request(&env, owner.clone())); - requests.push_back(create_wallet_request(&env, owner2.clone())); - requests.push_back(create_wallet_request(&env, owner.clone())); // Duplicate - - // Attempt batch create - should fail with duplicate error - let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { - client.batch_create_wallets(&admin, &requests); - })); - - // Verify panic occurred - assert!(result.is_err()); - - // Verify duplicate event was published before panic - let events = env.events().all(); - let mut duplicate_event_found = false; - for (_, topics, _) in events.iter() { - let topic_vec = topics.clone(); - if topic_vec.len() >= 2 { - let topic1: soroban_sdk::Symbol = - topic_vec.get(0).unwrap().into_val(&env).try_into().ok(); - let topic2: soroban_sdk::Symbol = - topic_vec.get(1).unwrap().into_val(&env).try_into().ok(); - if topic1 == Some(soroban_sdk::Symbol::new(&env, "wallet")) - && topic2 == Some(soroban_sdk::Symbol::new(&env, "duplicate")) - { - duplicate_event_found = true; - break; - } - } - } - assert!(duplicate_event_found, "Duplicate event should be emitted"); -} - -#[test] -fn test_batch_create_wallets_duplicate_error_identifies_entry() { - let (env, admin, client) = setup_test_env(); - - let owner = Address::generate(&env); - let owner2 = Address::generate(&env); - let owner3 = Address::generate(&env); - - // First batch - success - let mut requests1: Vec = Vec::new(&env); - requests1.push_back(create_wallet_request(&env, owner.clone())); - requests1.push_back(create_wallet_request(&env, owner2.clone())); - client.batch_create_wallets(&admin, &requests1); - - // Second batch - with duplicate from first batch - let mut requests2: Vec = Vec::new(&env); - requests2.push_back(create_wallet_request(&env, owner.clone())); // Existed before - requests2.push_back(create_wallet_request(&env, owner3.clone())); // New - - let result = client.batch_create_wallets(&admin, &requests2); - - // Should process individually since duplicates are within-batch check - // Only existing wallets should fail, not in-batch duplicates - assert_eq!(result.total_requests, 2); - assert_eq!(result.successful, 1); - assert_eq!(result.failed, 1); - - match result.results.get(0).unwrap() { - WalletCreateResult::Failure(addr, _) => { - assert_eq!(addr, owner); // First request failed (already exists) - } - _ => panic!("Expected failure for existing wallet"), - } - - match result.results.get(1).unwrap() { - WalletCreateResult::Success(addr) => { - assert_eq!(addr, owner3); // New wallet created - } - _ => panic!("Expected success for new wallet"), - } -} diff --git a/contracts/src/vault.rs b/contracts/src/vault.rs deleted file mode 100644 index fff45df8..00000000 --- a/contracts/src/vault.rs +++ /dev/null @@ -1,139 +0,0 @@ -#![no_std] -use soroban_sdk::{contract, contractimpl, contracttype, symbol_short, Address, Env, String, Vec}; - -// --------------------------------------------------------------------------- -// Data types -// --------------------------------------------------------------------------- - -#[contracttype] -#[derive(Clone)] -pub struct Gist { - pub gist_id: u64, - pub author: Option
, - pub location_cell: String, - pub content_hash: String, - pub created_at: u64, -} - -// --------------------------------------------------------------------------- -// Storage keys -// --------------------------------------------------------------------------- - -const GIST_COUNT: soroban_sdk::Symbol = symbol_short!("GCOUNT"); - -// --------------------------------------------------------------------------- -// Contract -// --------------------------------------------------------------------------- - -#[contract] -pub struct GistRegistry; - -#[contractimpl] -impl GistRegistry { - /// Register a new gist on-chain. Returns the assigned gist_id. - pub fn post_gist( - env: Env, - author: Option
, - location_cell: String, - content_hash: String, - ) -> u64 { - let gist_id: u64 = env.storage().instance().get(&GIST_COUNT).unwrap_or(0) + 1; - - let gist = Gist { - gist_id, - author, - location_cell: location_cell.clone(), - content_hash, - created_at: env.ledger().timestamp(), - }; - - env.storage().persistent().set(&gist_id, &gist); - env.storage().instance().set(&GIST_COUNT, &gist_id); - - gist_id - } - - /// Retrieve a gist record by its id. - pub fn get_gist(env: Env, gist_id: u64) -> Option { - env.storage().persistent().get(&gist_id) - } - - /// List gists whose location_cell matches the given cell string. - /// `cursor` is the gist_id to start scanning from (inclusive); `limit` caps results. - pub fn list_gists_by_cell( - env: Env, - location_cell: String, - cursor: u64, - limit: u32, - ) -> Vec { - let total: u64 = env.storage().instance().get(&GIST_COUNT).unwrap_or(0); - let mut results = Vec::new(&env); - let mut count: u32 = 0; - - let start = if cursor == 0 { 1 } else { cursor }; - - for id in start..=total { - if count >= limit { - break; - } - if let Some(gist) = env.storage().persistent().get::(&id) { - if gist.location_cell == location_cell { - results.push_back(gist); - count += 1; - } - } - } - - results - } -} - -// --------------------------------------------------------------------------- -// Tests -// --------------------------------------------------------------------------- - -#[cfg(test)] -mod tests { - use super::*; - use soroban_sdk::testutils::Ledger; - use soroban_sdk::{Env, String}; - - #[test] - fn test_post_and_get_gist() { - let env = Env::default(); - let contract_id = env.register(GistRegistry, ()); - let client = GistRegistryClient::new(&env, &contract_id); - - env.ledger().set_timestamp(1_000_000); - - let location = String::from_str(&env, "r3gx"); - let hash = String::from_str(&env, "QmTest123"); - - let id = client.post_gist(&None, &location, &hash); - assert_eq!(id, 1); - - let gist = client.get_gist(&id).expect("gist should exist"); - assert_eq!(gist.gist_id, 1); - assert_eq!(gist.location_cell, location); - assert_eq!(gist.content_hash, hash); - assert_eq!(gist.created_at, 1_000_000); - } - - #[test] - fn test_list_gists_by_cell() { - let env = Env::default(); - let contract_id = env.register(GistRegistry, ()); - let client = GistRegistryClient::new(&env, &contract_id); - - let cell_a = String::from_str(&env, "r3gx"); - let cell_b = String::from_str(&env, "u4ht"); - let hash = String::from_str(&env, "Qm000"); - - client.post_gist(&None, &cell_a, &hash); - client.post_gist(&None, &cell_b, &hash); - client.post_gist(&None, &cell_a, &hash); - - let results = client.list_gists_by_cell(&cell_a, &0, &10); - assert_eq!(results.len(), 2); - } -} From e8247423236d0289a60947b9365e157ba2dfe024 Mon Sep 17 00:00:00 2001 From: bigben-7 Date: Thu, 23 Jul 2026 20:34:02 +0100 Subject: [PATCH 2/2] chore(backend): remove unused ethers dependency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ethers (EVM library) had zero usages anywhere in Backend/src — leftover from an earlier direction. GistPin targets Stellar/Soroban. Remove it and sync the lockfile. Fixes #865 Co-Authored-By: Claude Opus 4.8 --- Backend/package-lock.json | 135 ++++---------------------------------- Backend/package.json | 1 - 2 files changed, 13 insertions(+), 123 deletions(-) diff --git a/Backend/package-lock.json b/Backend/package-lock.json index c80c7412..a9921e49 100644 --- a/Backend/package-lock.json +++ b/Backend/package-lock.json @@ -22,7 +22,6 @@ "@willsoto/nestjs-prometheus": "^6.1.0", "class-transformer": "^0.5.1", "class-validator": "^0.14.2", - "ethers": "^6.15.0", "iterare": "^1.2.1", "joi": "^18.2.1", "nest-winston": "^1.10.2", @@ -63,12 +62,6 @@ "typescript-eslint": "^8.20.0" } }, - "node_modules/@adraffy/ens-normalize": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", - "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==", - "license": "MIT" - }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", @@ -2876,30 +2869,6 @@ "typeorm": "^0.3.0" } }, - "node_modules/@noble/curves": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", - "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "1.3.2" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@noble/curves/node_modules/@noble/hashes": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", - "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", - "license": "MIT", - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/@noble/ed25519": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@noble/ed25519/-/ed25519-3.1.0.tgz", @@ -3250,7 +3219,7 @@ "version": "1.12.11", "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.12.11.tgz", "integrity": "sha512-P3GM+0lqjFctcp5HhR9mOcvLSX3SptI9L1aux0Fuvgt8oH4f92rCUrkodAa0U2ktmdjcyIiG37xg2mb/dSCYSA==", - "devOptional": true, + "dev": true, "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { @@ -3292,6 +3261,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -3308,6 +3278,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -3324,6 +3295,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -3340,6 +3312,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -3356,6 +3329,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -3372,6 +3346,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -3388,6 +3363,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -3404,6 +3380,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -3420,6 +3397,7 @@ "cpu": [ "ia32" ], + "dev": true, "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -3436,6 +3414,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -3449,14 +3428,14 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", - "devOptional": true, + "dev": true, "license": "Apache-2.0" }, "node_modules/@swc/types": { "version": "0.1.23", "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.23.tgz", "integrity": "sha512-u1iIVZV9Q0jxY+yM2vw/hZGDNudsN85bBpTqzAQ9rzkxW9D+e3aEM4Han+ow518gSewkXgjmEK0BD79ZcNVgPw==", - "devOptional": true, + "dev": true, "license": "Apache-2.0", "dependencies": { "@swc/counter": "^0.1.3" @@ -4922,12 +4901,6 @@ "node": ">=0.4.0" } }, - "node_modules/aes-js": { - "version": "4.0.0-beta.5", - "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", - "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==", - "license": "MIT" - }, "node_modules/agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", @@ -6893,67 +6866,6 @@ "node": ">= 0.6" } }, - "node_modules/ethers": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.15.0.tgz", - "integrity": "sha512-Kf/3ZW54L4UT0pZtsY/rf+EkBU7Qi5nnhonjUb8yTXcxH3cdcWrV2cRyk0Xk/4jK6OoHhxxZHriyhje20If2hQ==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/ethers-io/" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@adraffy/ens-normalize": "1.10.1", - "@noble/curves": "1.2.0", - "@noble/hashes": "1.3.2", - "@types/node": "22.7.5", - "aes-js": "4.0.0-beta.5", - "tslib": "2.7.0", - "ws": "8.17.1" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/ethers/node_modules/@noble/hashes": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", - "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", - "license": "MIT", - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/ethers/node_modules/@types/node": { - "version": "22.7.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz", - "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==", - "license": "MIT", - "dependencies": { - "undici-types": "~6.19.2" - } - }, - "node_modules/ethers/node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", - "license": "0BSD" - }, - "node_modules/ethers/node_modules/undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", - "license": "MIT" - }, "node_modules/events": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", @@ -13258,27 +13170,6 @@ "dev": true, "license": "ISC" }, - "node_modules/ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", diff --git a/Backend/package.json b/Backend/package.json index 143af2d4..c915fa2f 100644 --- a/Backend/package.json +++ b/Backend/package.json @@ -36,7 +36,6 @@ "@willsoto/nestjs-prometheus": "^6.1.0", "class-transformer": "^0.5.1", "class-validator": "^0.14.2", - "ethers": "^6.15.0", "iterare": "^1.2.1", "joi": "^18.2.1", "nest-winston": "^1.10.2",