diff --git a/soroban-contracts/contracts/single_rwa_vault/src/lib.rs b/soroban-contracts/contracts/single_rwa_vault/src/lib.rs index ba063af..fa2e51e 100644 --- a/soroban-contracts/contracts/single_rwa_vault/src/lib.rs +++ b/soroban-contracts/contracts/single_rwa_vault/src/lib.rs @@ -507,6 +507,16 @@ impl SingleRWAVault { get_redemption_request(e, request_id) } + /// Returns the current redemption request counter (total number of requests ever made). + pub fn redemption_counter(e: &Env) -> u32 { + get_redemption_counter(e) + } + + /// Returns all redemption request IDs for a given user. + pub fn get_user_redemption_requests(e: &Env, user: Address) -> Vec { + get_user_redemption_requests(e, &user) + } + // ───────────────────────────────────────────────────────────────── // ERC-4626 max helpers // ───────────────────────────────────────────────────────────────── @@ -1211,12 +1221,14 @@ impl SingleRWAVault { e, id, RedemptionRequest { - user: caller, + user: caller.clone(), shares, request_time: e.ledger().timestamp(), processed: false, }, ); + // Track the request ID in the user's list for queryability + push_user_redemption_request(e, &user, id); emit_early_redemption_requested(e, user, id, shares); bump_instance(e); diff --git a/soroban-contracts/contracts/single_rwa_vault/src/storage.rs b/soroban-contracts/contracts/single_rwa_vault/src/storage.rs index 43e8377..f1efdaa 100644 --- a/soroban-contracts/contracts/single_rwa_vault/src/storage.rs +++ b/soroban-contracts/contracts/single_rwa_vault/src/storage.rs @@ -12,7 +12,7 @@ //! INSTANCE_BUMP_AMOUNT ≈ 30 days //! BALANCE_BUMP_AMOUNT ≈ 60 days -use soroban_sdk::{contracttype, panic_with_error, Address, Env, String}; +use soroban_sdk::{contracttype, panic_with_error, Address, Env, String, Vec}; use crate::errors::Error; use crate::types::{RedemptionRequest, Role, VaultState}; @@ -112,6 +112,7 @@ pub enum DataKey { RedemptionCounter, RedemptionRequest(u32), EscrowedShares(Address), + // UserRedemptionRequests(Address) - removed due to contracttype size limits // --- Blacklist --- Blacklisted(Address), @@ -633,6 +634,39 @@ pub fn put_escrowed_shares(e: &Env, addr: &Address, amount: i128) { .extend_ttl(&key, BALANCE_LIFETIME_THRESHOLD, BALANCE_BUMP_AMOUNT); } +// ───────────────────────────────────────────────────────────────────────────── +// User redemption request tracking (persistent) +// Uses a custom key struct to avoid adding to DataKey enum +// ───────────────────────────────────────────────────────────────────────────── + +/// Custom storage key for per-user redemption request lists. +/// This avoids adding to the DataKey enum which has reached size limits. +#[contracttype] +#[derive(Clone)] +pub struct UserRedemptionKey { + pub user: Address, +} + +/// Returns the list of redemption request IDs for a given user. +pub fn get_user_redemption_requests(e: &Env, user: &Address) -> Vec { + let key = UserRedemptionKey { user: user.clone() }; + e.storage() + .persistent() + .get(&key) + .unwrap_or(Vec::new(e)) +} + +/// Appends a new redemption request ID to the user's list. +pub fn push_user_redemption_request(e: &Env, user: &Address, request_id: u32) { + let key = UserRedemptionKey { user: user.clone() }; + let mut requests = get_user_redemption_requests(e, user); + requests.push_back(request_id); + e.storage().persistent().set(&key, &requests); + e.storage() + .persistent() + .extend_ttl(&key, BALANCE_LIFETIME_THRESHOLD, BALANCE_BUMP_AMOUNT); +} + // ───────────────────────────────────────────────────────────────────────────── // Transfer KYC gate (instance storage) // ─────────────────────────────────────────────────────────────────────────────