Skip to content

feat: Add get_redemption_request view functions and user query support#151

Open
trinnode wants to merge 1 commit into
StellarYield:mainfrom
trinnode:fix/issue-65-redemption-request-views
Open

feat: Add get_redemption_request view functions and user query support#151
trinnode wants to merge 1 commit into
StellarYield:mainfrom
trinnode:fix/issue-65-redemption-request-views

Conversation

@trinnode
Copy link
Copy Markdown
Contributor

@trinnode trinnode commented Mar 26, 2026

Description

Closes #65

Users who submit early redemption requests currently have no way to query their request status on-chain. There is no public function to read a RedemptionRequest by ID, and no way to list all requests for a specific user. This implementation bridges that gap, ensuring users and frontends are no longer "flying blind" after calling request_early_redemption.

Requirements

  • Expose a public get_redemption_request(request_id: u32) -> RedemptionRequest view function.
  • Add get_user_redemption_requests(user: Address) -> Vec<u32> to return all request IDs for a given user.
  • Implement a per-user list of request IDs using a new storage key: DataKey::UserRedemptionRequests(Address).
  • Update the request_early_redemption logic to append the newly generated ID to the user's tracking list.
  • Add redemption_counter() -> u32 as a public view to expose the current state of the global counter.

Key Files

  • lib.rs — New public view functions for request and counter queries.
  • storage.rs — Definition of the new UserRedemptionRequests(Address) storage key.
  • types.rsRedemptionRequest struct (already public, now utilized by views).

Implementation Details

  • On-Chain Transparency: Introduced the get_redemption_request view, allowing direct lookup of request details (amount, status, etc.) via a unique ID.
  • User Tracking: Implemented a Vec<u32> storage pattern mapped to user Addresses, enabling frontends to easily fetch a user's entire history of redemption attempts.
  • State Management: The request_early_redemption function now handles the dual responsibility of incrementing the global counter and updating the user's local request list in a single atomic operation.
  • Global State Exposure: The redemption_counter view provides a simple way for external indexers to track the total volume of requests handled by the vault.

Definition of Done

  • Users can query their specific redemption request details by ID.
  • Users can list all their historical request IDs in a single call.
  • Frontend/SDK consumers can now programmatically distinguish between pending and processed requests.
  • Testing:
    • Verified query correctness after multiple sequential requests.
    • Confirmed the per-user list correctly appends new IDs without overwriting existing data.
    • All 188 tests pass in single_rwa_vault.

Closes StellarYield#65 - Add get_redemption_request View Function and Request Query by User

- Add get_redemption_request(request_id: u32) -> RedemptionRequest public view
- Add get_user_redemption_requests(user: Address) -> Vec<u32> to list all requests
- Add redemption_counter() -> u32 public view to expose current counter
- Add UserRedemptionKey custom struct for per-user request tracking
- Update request_early_redemption to append new ID to user's list
- All 188 tests pass in single_rwa_vault
Copilot AI review requested due to automatic review settings March 26, 2026 20:13
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds on-chain query support for early redemption requests in single_rwa_vault, enabling frontends/users to discover request IDs per user and read the current request counter.

Changes:

  • Introduces persistent per-user storage of redemption request IDs via a custom UserRedemptionKey.
  • Exposes new public view functions: redemption_counter() and get_user_redemption_requests(user).
  • Updates request_early_redemption to append each new request ID to the user’s stored list.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.

File Description
soroban-contracts/contracts/single_rwa_vault/src/storage.rs Adds custom persistent storage key + helpers to store and fetch per-user request ID lists.
soroban-contracts/contracts/single_rwa_vault/src/lib.rs Exposes new view methods and records request IDs into the per-user list during request_early_redemption.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +510 to +518
/// 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<u32> {
get_user_redemption_requests(e, &user)
}
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

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

New query surface (redemption_counter / get_user_redemption_requests) and the per-user tracking added in request_early_redemption don’t appear to have direct test coverage. Please add tests that (1) multiple requests by the same user produce an ordered ID list, (2) different users don’t leak IDs, and (3) redemption_counter matches the highest issued ID.

Copilot uses AI. Check for mistakes.
Comment on lines 1228 to 1232
},
);
// Track the request ID in the user's list for queryability
push_user_redemption_request(e, &user, id);

Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

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

The per-user request list TTL is only extended when creating a new request. However, individual RedemptionRequest entries get their TTL refreshed again on later updates (process/cancel), which can result in the request staying queryable by ID while the user’s ID list expires—breaking discovery. Consider also bumping/extending the user’s list TTL whenever a request is processed/cancelled (or choose a longer TTL strategy for the list).

Copilot uses AI. Check for mistakes.
RedemptionCounter,
RedemptionRequest(u32),
EscrowedShares(Address),
// UserRedemptionRequests(Address) - removed due to contracttype size limits
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

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

This inline note about UserRedemptionRequests(Address) being “removed due to contracttype size limits” is confusing since the enum variant isn’t present. Consider deleting the comment or replacing it with a short explanation of the chosen approach (custom key struct) and, ideally, a reference/link to the relevant size-limit context.

Suggested change
// UserRedemptionRequests(Address) - removed due to contracttype size limits
/// Per-user redemption requests are tracked via `RedemptionRequest(u32)` IDs
/// and `EscrowedShares(Address)`, instead of a dedicated
/// `UserRedemptionRequests(Address)` enum variant, to keep this `contracttype`
/// within Soroban’s data layout / size limits (see Soroban contract data docs).

Copilot uses AI. Check for mistakes.
Comment on lines +642 to +648
/// 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,
}
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

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

Using a #[contracttype] struct-as-key with a single user field serializes as a map and has no explicit namespace/prefix, which is more storage/CPU heavy than necessary and can collide with other similarly-shaped keys in the future. Consider using a small namespaced key (e.g., a tuple with a fixed tag + Address) or adding a discriminant field to the struct to ensure uniqueness and reduce overhead.

Copilot uses AI. Check for mistakes.
Comment on lines +510 to +518
/// 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<u32> {
get_user_redemption_requests(e, &user)
}
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

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

The PR/issue description says the contract should expose a public get_redemption_request(request_id) view, but the public interface here still only exposes redemption_request(...). If external clients are expecting the new name, consider adding get_redemption_request as a wrapper/alias (keeping redemption_request for backwards compatibility) or updating the PR description accordingly.

Copilot uses AI. Check for mistakes.
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.

Add get_redemption_request View Function and Request Query by User

2 participants