Skip to content

feat: Read only logic for transactions#66

Merged
NicoMolinaOZ merged 3 commits intomainfrom
simulation-read-only-transactions
Feb 11, 2026
Merged

feat: Read only logic for transactions#66
NicoMolinaOZ merged 3 commits intomainfrom
simulation-read-only-transactions

Conversation

@NicoMolinaOZ
Copy link
Contributor

@NicoMolinaOZ NicoMolinaOZ commented Feb 11, 2026

Summary:

  • Read-only logic for transactions to avoid sending the tx on-chain when it is read-only

Summary by CodeRabbit

  • New Features

    • Detects and short-circuits read-only Soroban calls before submission; read-only responses return status "readonly" with null transactionId and hash, plus returnValue (base64) and latestLedger.
    • Uses simulation results to assemble and submit transactions more efficiently, reducing redundant network work.
  • Tests

    • Added comprehensive tests covering read-only detection, response fields, error propagation, and simulation behavior.

@coderabbitai
Copy link

coderabbitai bot commented Feb 11, 2026

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • ✅ Review completed - (🔄 Check again to review again)

Walkthrough

Added read-only transaction detection to prevent unnecessary channel acquisition. New simulateReadOnlyCheck function evaluates whether transactions require authentication or write footprints. Handler now calls this check before channel acquisition; if read-only is detected, it returns early with status 'readonly' and simulation results. Response types updated with optional returnValue and latestLedger fields.

Changes

Cohort / File(s) Summary
Type Definitions
src/client/types.ts, src/plugin/types.ts
Added optional returnValue (base64 xdr.ScVal) and latestLedger fields to response interfaces for read-only call results.
Simulation Logic
src/plugin/simulation.ts
Introduced ReadOnlyCheckResult interface and new simulateReadOnlyCheck function that constructs throwaway read-only simulations, determines read-only status by checking for auth entries and read-write footprints, and returns results with latestLedger.
Handler Integration
src/plugin/handler.ts
Integrated pre-execution read-only check in func+auth submission path; returns early with 'readonly' status and simulation results if read-only is detected, bypassing channel acquisition.
Test Coverage
test/read-only.test.ts, test/client.test.ts
Added comprehensive unit tests for simulateReadOnlyCheck covering auth/footprint scenarios, error handling, and network propagation; added integration test for read-only response handling in client.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Handler
    participant Simulation
    participant Relayer
    participant Channel

    Client->>Handler: submitSorobanTransaction
    Handler->>Simulation: simulateReadOnlyCheck
    Simulation->>Relayer: simulateTransaction (read-only check)
    Relayer-->>Simulation: simulation result
    alt isReadOnly detected
        Simulation-->>Handler: {isReadOnly: true, returnValue, latestLedger}
        Handler-->>Client: {status: 'readonly', returnValue, latestLedger, transactionId: null, hash: null}
    else requires submission
        Simulation-->>Handler: {isReadOnly: false}
        Handler->>Channel: acquireChannel
        Handler->>Relayer: submitTransaction
        Relayer-->>Handler: submission result
        Handler-->>Client: result
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested reviewers

  • tirumerla

Poem

🐰 A rabbit hops through transactions today,
Read-only? No channel to pay!
Early returns save time and space,
Simulation checks set the pace,
Efficient flows in every way! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 57.14% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly describes the main feature being added: read-only logic for transactions to determine and handle read-only calls without on-chain submission.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch simulation-read-only-transactions

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/plugin/simulation.ts`:
- Around line 109-115: ReadOnlyCheckResult declares latestLedger: number but
simResult.latestLedger (from RawSimulateTransactionResponse) can be undefined;
either make ReadOnlyCheckResult.latestLedger optional (latestLedger?: number) to
match the source type, or when building/returning the ReadOnlyCheckResult set
latestLedger using a safe fallback (e.g., latestLedger: simResult.latestLedger
?? 0) so you never assign undefined; locate the assignment where the
ReadOnlyCheckResult is constructed/returned (the code that reads
simResult.latestLedger) and apply one of these two fixes.

@NicoMolinaOZ NicoMolinaOZ linked an issue Feb 11, 2026 that may be closed by this pull request
tracker?: FeeTracker
): Promise<ChannelAccountsResponse> {
// Read-only check: simulate before acquiring a channel to detect read-only calls
const readOnlyCheck = await simulateReadOnlyCheck(func, auth, fundAddress, fundRelayer, networkPassphrase);
Copy link
Member

Choose a reason for hiding this comment

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

We are simulating below this also, lets check if we can extract smulation result somehow to reuse for both so we only have to simulate once. Its a network call so we should try and only do it once

@NicoMolinaOZ NicoMolinaOZ merged commit 5c143cb into main Feb 11, 2026
11 checks passed
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.

Simulate-only read operations

2 participants