Skip to content

Conversation

@EehMauro
Copy link
Contributor

@EehMauro EehMauro commented Oct 26, 2025

Summary by CodeRabbit

  • Refactor

    • Introduced a domain facade layer to consolidate chain data access and compiler initialization.
    • Restructured compiler loading to streamline configuration and initialization.
  • New Features

    • Added enhanced error reporting for chain resolution and tip retrieval operations.
    • Extended UTXO store with dependency-aware retrieval capabilities.
  • Chores

    • Updated build dependencies to utilize git-based sources for improved development workflow.

@coderabbitai
Copy link

coderabbitai bot commented Oct 26, 2025

Walkthrough

Changes introduce a Facade wrapper struct providing domain data access methods (chain summary, slot config, chain tip, pparams), refactor load_compiler to accept the wrapped domain and return tx3_cardano::Compiler, add two new error variants, extend UtxoStore with fetch_utxos_deps, and update Cargo.toml dependencies to git-based sources for tx3-* crates.

Changes

Cohort / File(s) Summary
Dependency Management
crates/trp/Cargo.toml
Replaced hardcoded version specs (0.11.4) with git-based sources for tx3-lang, tx3-cardano, and tx3-resolver; tx3-sdk remains version-based.
Error Handling Enhancements
crates/trp/src/error.rs
Added two new error variants: TipNotResolved and ChainSummaryNotResolved(String) with corresponding error codes CODE_TIP_NOT_RESOLVED (-32004) and CODE_CHAIN_SUMMARY_NOT_RESOLVED (-32005).
Facade Pattern Introduction
crates/trp/src/lib.rs
Introduced public generic struct Facade<D: Domain> with Deref implementation and four public methods: get_chain_summary(), get_slot_config(), get_chain_tip(), and get_pparams() for orchestrating chain data retrieval.
Compiler Loading Refactor
crates/trp/src/compiler.rs
Modified load_compiler() signature to accept domain: &Facade<D> instead of raw Domain, retrieve chain data via facade methods, and return tx3_cardano::Compiler instead of internal PParams-like struct.
Facade Integration
crates/trp/src/methods.rs
Updated trp_resolve to wrap context.domain in a Facade instance before passing to load_compiler.
UTXO Storage Extension
crates/trp/src/utxos.rs
Added new async method fetch_utxos_deps() to UtxoStore impl for UtxoStoreAdapter<D>, converting UTXOs into UtxoMap with proper type conversions via Era::try_from.

Sequence Diagram

sequenceDiagram
    participant C as Consumer
    participant M as methods
    participant F as Facade
    participant CMP as compiler
    participant D as Domain

    Note over C,D: Previous Flow
    C->>M: trp_resolve()
    M->>CMP: load_compiler(domain)
    CMP->>D: build_pparams()

    Note over C,D: New Flow
    C->>M: trp_resolve()
    M->>F: Facade::new(domain)
    M->>CMP: load_compiler(&facade)
    CMP->>F: get_chain_summary()
    F->>D: retrieve era summary
    CMP->>F: get_slot_config()
    CMP->>F: get_chain_tip()
    F->>D: read state cursor
    CMP->>F: get_pparams()
    F->>D: load effective pparams
    CMP-->>C: Return tx3_cardano::Compiler
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Facade pattern implementation (lib.rs): Verify error handling paths in data retrieval methods, especially fallbacks for missing chain tip and error mapping from domain operations
  • Compiler loading integration (compiler.rs): Ensure all domain-derived values (chain_tip, pparams, costs, slot_config) are correctly threaded through to tx3_cardano::Compiler constructor; validate return type compatibility
  • Error variant usage (error.rs): Confirm new error codes are used appropriately in Facade methods and don't conflict with existing codes
  • UtxoMap conversion (utxos.rs): Review Era type conversion and UtxoRef → TxoRef mapping logic in fetch_utxos_deps

Possibly related PRs

Suggested reviewers

  • scarmuega

🐰✨ A facade fair, so neat and clean,
Wraps the domain like never seen!
Data flows through methods bright,
Compiler loads with newfound might,
Chain and tips now organized right! 🌟

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The PR title "feat(trp): update tx3 to latest version" is partially related to the changeset. It accurately references the Cargo.toml changes where tx3 dependencies are updated from hard-coded versions (0.11.4) to git-based sources, which is a real and visible part of the PR. However, the title is overly broad and doesn't capture the primary architectural changes that constitute the substance of this pull request: the introduction of a new Facade abstraction pattern in lib.rs, the refactoring of the public load_compiler API to use this Facade, and the related updates throughout methods.rs and error handling. While the dependency updates are present, the significant refactoring of the domain layer and API surface represents the main point of this change.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@EehMauro EehMauro marked this pull request as ready for review October 26, 2025 22:21
@EehMauro EehMauro requested a review from scarmuega as a code owner October 26, 2025 22:21
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: 5

🧹 Nitpick comments (3)
crates/trp/Cargo.toml (1)

27-37: Pin tx3 git dependencies for reproducible builds; consider aligning tx3-sdk source.

Moving to git HEADs risks non-deterministic builds and surprise API breaks. Pin commits and keep all tx3 crates in lockstep. Also consider pinning tx3-sdk or switching it to the same repo/rev if required by the new APIs.

Apply something like:

-tx3-lang = { git = "https://github.com/tx3-lang/tx3.git" }
-tx3-cardano = { git = "https://github.com/tx3-lang/tx3.git" }
-tx3-resolver = { git = "https://github.com/tx3-lang/tx3.git" }
+tx3-lang     = { git = "https://github.com/tx3-lang/tx3.git", rev = "<commit-sha>" }
+tx3-cardano  = { git = "https://github.com/tx3-lang/tx3.git", rev = "<same-commit-sha>" }
+tx3-resolver = { git = "https://github.com/tx3-lang/tx3.git", rev = "<same-commit-sha>" }

Optionally, align SDK:

-tx3-sdk = { version = "^0" }
+# tx3-sdk = { git = "https://github.com/tx3-lang/rust-sdk.git", rev = "<sdk-commit-sha>" }
crates/trp/src/error.rs (1)

56-61: New variants look good; consider adding error data for client diagnostics.

TipNotResolved and ChainSummaryNotResolved are appropriate. Add a small JSON payload in data() so clients can programmatically inspect causes (e.g., the underlying summary error string).

Example addition in data():

             _ => None,
+            Error::TipNotResolved => None,
+            Error::ChainSummaryNotResolved(msg) => {
+                Some(json!({ "reason": msg }))
+            }
crates/trp/src/methods.rs (1)

11-11: Facade integration is correct; minor cohesion nit.

Constructing Facade locally and passing it to load_compiler is fine. For consistency, consider also deriving the state via the same Facade (or clone the same domain into both) to avoid mixing domain clones, though it’s likely harmless if D internally Arc’s state.

Example:

-    let facade = Facade { inner: context.domain.clone() };
-    let mut compiler = load_compiler::<D>(&facade, &context.config)?;
-    let utxos = UtxoStoreAdapter::<D>::new(context.domain.state().clone());
+    let facade = Facade { inner: context.domain.clone() };
+    let mut compiler = load_compiler::<D>(&facade, &context.config)?;
+    let utxos = UtxoStoreAdapter::<D>::new(facade.state().clone());

Also applies to: 80-83

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f98781f and b9bcc33.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (6)
  • crates/trp/Cargo.toml (1 hunks)
  • crates/trp/src/compiler.rs (2 hunks)
  • crates/trp/src/error.rs (3 hunks)
  • crates/trp/src/lib.rs (2 hunks)
  • crates/trp/src/methods.rs (2 hunks)
  • crates/trp/src/utxos.rs (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
crates/trp/src/methods.rs (2)
crates/trp/src/compiler.rs (1)
  • load_compiler (32-58)
crates/minibf/src/routes/addresses.rs (1)
  • utxos (128-148)
crates/trp/src/lib.rs (3)
src/mempool.rs (4)
  • dolos_cardano (85-85)
  • dolos_cardano (133-133)
  • dolos_cardano (135-135)
  • validate (67-124)
crates/cardano/src/lib.rs (3)
  • eras (153-153)
  • eras (178-178)
  • load_effective_pparams (327-332)
crates/core/src/lib.rs (3)
  • chain (712-712)
  • slot (497-497)
  • hash (498-498)
crates/trp/src/utxos.rs (2)
src/mempool.rs (1)
  • validate (67-124)
crates/trp/src/mapping.rs (1)
  • from_tx3_utxoref (99-103)
🪛 GitHub Actions: CI
crates/trp/src/utxos.rs

[error] 80-80: method fetch_utxos_deps is not a member of trait UtxoStore.

🪛 GitHub Check: Check Build
crates/trp/src/compiler.rs

[failure] 46-46:
this function takes 3 arguments but 6 arguments were supplied

crates/trp/src/utxos.rs

[failure] 80-80:
method fetch_utxos_deps is not a member of trait UtxoStore

🔇 Additional comments (5)
crates/trp/src/utxos.rs (1)

8-9: LGTM!

The new imports support the fetch_utxos_deps functionality and are appropriately scoped.

crates/trp/src/error.rs (1)

137-139: JSON‑RPC code mapping consistent.

Codes are in the custom range and mapped correctly in code(). LGTM.

Also applies to: 160-162

crates/trp/src/lib.rs (2)

3-7: Imports look correct and scoped.

New uses for ChainPoint, ChainSummary, PParamsSet, and SlotConfig are appropriate.

Also applies to: 13-17


149-156: Timestamp and hash handling contain real bugs; fix approach is sound but requires verification of external type compatibility.

The review comment correctly identifies two issues:

  1. Timestamp calculation bug: The current (slot * 1000) is a placeholder (indicated by TODO). The codebase includes EraSummary.slot_time() which correctly computes self.start.timestamp + (slot - self.start.slot) * self.slot_length, validating the reviewer's suggested approach.

  2. Hash error handling: Using unwrap_or_default() silently converts missing hash to an empty vector. Raising Error::TipNotResolved is more explicit and correct.

However, the proposed diff cannot be fully verified because tx3_cardano re-exports ChainPoint from the Pallas crate, and the exact field names and types in pallas::interop::utxorpc::spec::query::ChainPoint could not be confirmed. The diff assumes fields slot, hash, and timestamp with matching types, but this must be verified against the Pallas crate definition before applying the fix.

crates/trp/src/compiler.rs (1)

46-55: Compiler::new arity mismatch identified, but review comment contains incorrect solution patterns.

The actual tx3-cardano 0.11.4 Compiler::new signature is:

pub fn new(pparams: PParams, config: Config) -> Self

It takes 2 arguments, not 3. The current call at lines 46-55 passes 6 arguments, causing the build to fail. The correct call should be:

let compiler = tx3_cardano::Compiler::new(
    pparams,
    tx3_cardano::Config {
        extra_fees: config.extra_fees,
    },
);

The parameters network, chain_tip, map_cost_models(costs), and slot_config should be removed from this call. Verify they are either no longer needed or set elsewhere in the flow.

Likely an incorrect or invalid review comment.

domain: &Facade<D>,
config: &Config,
) -> Result<tx3_cardano::Compiler, Error> {
let network = network_id_from_genesis(&domain.genesis()).unwrap();
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Don’t unwrap network id; propagate a typed error.

Unwrap will panic on unknown/missing network_id. Map to an Error instead.

-    let network = network_id_from_genesis(&domain.genesis()).unwrap();
+    let network = network_id_from_genesis(&domain.genesis())
+        .ok_or_else(|| {
+            jsonrpsee::types::ErrorObjectOwned::owned(
+                jsonrpsee::types::ErrorCode::InternalError.code(),
+                "unsupported or missing network_id in genesis",
+                None::<serde_json::Value>,
+            )
+        })?
+        .into();

Note: Using JsonRpcError keeps behavior consistent with existing Error conversions.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In crates/trp/src/compiler.rs around line 36, replace the unwrap on
network_id_from_genesis(&domain.genesis()) with error propagation: call
network_id_from_genesis(...)? or map its None/Err into the crate Error using
JsonRpcError (or convert into the existing Error enum) and return it instead of
panicking; ensure the function signature returns Result so the propagated error
flows up and maintain existing Error conversion behavior by constructing a
JsonRpcError with a clear message when network id is missing/unknown.

Comment on lines +132 to +137
pub fn get_chain_summary(&self) -> Result<ChainSummary, error::Error> {
let summary = dolos_cardano::eras::load_era_summary::<D>(&self.inner.state())
.map_err(|e| error::Error::ChainSummaryNotResolved(e.to_string()))?;

Ok(summary)
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Remove extra reference when passing state().

state() likely already returns a reference; passing &state() produces &&State. Call with state() directly.

-        let summary = dolos_cardano::eras::load_era_summary::<D>(&self.inner.state())
+        let summary = dolos_cardano::eras::load_era_summary::<D>(self.inner.state())
             .map_err(|e| error::Error::ChainSummaryNotResolved(e.to_string()))?;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
pub fn get_chain_summary(&self) -> Result<ChainSummary, error::Error> {
let summary = dolos_cardano::eras::load_era_summary::<D>(&self.inner.state())
.map_err(|e| error::Error::ChainSummaryNotResolved(e.to_string()))?;
Ok(summary)
}
pub fn get_chain_summary(&self) -> Result<ChainSummary, error::Error> {
let summary = dolos_cardano::eras::load_era_summary::<D>(self.inner.state())
.map_err(|e| error::Error::ChainSummaryNotResolved(e.to_string()))?;
Ok(summary)
}
🤖 Prompt for AI Agents
crates/trp/src/lib.rs around lines 132 to 137: the call currently passes
&self.inner.state() which creates a double reference (&&State); remove the extra
reference and pass self.inner.state() directly to
dolos_cardano::eras::load_era_summary::<D>() so the function receives the
expected &State (or move) value. Update the call to use self.inner.state()
without the leading & and keep the map_err handling intact.

Comment on lines +158 to +163
pub fn get_pparams(&self) -> Result<PParamsSet, error::Error> {
let pparams = dolos_cardano::load_effective_pparams::<D>(&self.inner.state())
.map_err(|_| Error::PParamsNotAvailable)?;

Ok(pparams)
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Same extra reference issue for pparams.

Pass state() directly; also consider preserving the source error message.

-        let pparams = dolos_cardano::load_effective_pparams::<D>(&self.inner.state())
-            .map_err(|_| Error::PParamsNotAvailable)?;
+        let pparams = dolos_cardano::load_effective_pparams::<D>(self.inner.state())
+            .map_err(|e| {
+                tracing::debug!(error = %e, "effective pparams not available");
+                Error::PParamsNotAvailable
+            })?;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
pub fn get_pparams(&self) -> Result<PParamsSet, error::Error> {
let pparams = dolos_cardano::load_effective_pparams::<D>(&self.inner.state())
.map_err(|_| Error::PParamsNotAvailable)?;
Ok(pparams)
}
pub fn get_pparams(&self) -> Result<PParamsSet, error::Error> {
let pparams = dolos_cardano::load_effective_pparams::<D>(self.inner.state())
.map_err(|e| {
tracing::debug!(error = %e, "effective pparams not available");
Error::PParamsNotAvailable
})?;
Ok(pparams)
}
🤖 Prompt for AI Agents
In crates/trp/src/lib.rs around lines 158 to 163, the code passes
&self.inner.state() producing an extra reference and also discards the original
error; call dolos_cardano::load_effective_pparams::<D>(self.inner.state()) (i.e.
pass state() directly, removing the &), and when mapping the error convert it
while preserving context by using map_err(|e|
Error::PParamsNotAvailable.into_with_source(e)) or otherwise include the source
error in the Error::PParamsNotAvailable construction so the original error
message is retained in the returned Result.

Comment on lines +80 to +103
async fn fetch_utxos_deps(
&self,
refs: HashSet<UtxoRef>
) -> Result<UtxoMap, tx3_lang::backend::Error> {
let refs: Vec<_> = refs.into_iter().map(from_tx3_utxoref).collect();

let utxos = self.state().get_utxos(refs).map_err(Error::from)?;

let utxos = utxos
.into_iter()
.map(|(txoref, eracbor)| {
let TxoRef(a, b) = txoref;
let EraCbor(c, d) = eracbor.as_ref();
let era = pallas::ledger::traverse::Era::try_from(*c).expect("era out of range");

(
pallas::ledger::validate::utils::TxoRef::from((a, b)),
pallas::ledger::validate::utils::EraCbor::from((era, d.clone())),
)
})
.collect();

Ok(utxos)
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Critical: Method not part of trait UtxoStore.

The implementation cannot compile because fetch_utxos_deps is not defined in the tx3_lang::backend::UtxoStore trait. This indicates either:

  1. The trait definition hasn't been updated to include this method
  2. The tx3-lang dependency version is incorrect or not yet updated

Verify that the tx3-lang dependency has been updated to a version that includes this method in the trait definition.

Run the following script to check the trait definition:


🏁 Script executed:

#!/bin/bash
# Description: Verify the UtxoStore trait definition includes fetch_utxos_deps

# Search for the UtxoStore trait definition
rg -n -A 20 'trait UtxoStore' --type rust

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Description: Find imports and usage of UtxoStore in the target file

# First, show the imports and struct/impl context in utxos.rs
echo "=== FILE: crates/trp/src/utxos.rs (beginning) ==="
head -n 110 crates/trp/src/utxos.rs

echo -e "\n=== SEARCH: UtxoStore references ==="
rg -n 'UtxoStore' crates/trp/src/utxos.rs -B 2 -A 2

echo -e "\n=== SEARCH: impl blocks in utxos.rs ==="
rg -n '^impl' crates/trp/src/utxos.rs -A 5

Length of output: 3936



🏁 Script executed:

#!/bin/bash
# Description: Check tx3_lang dependency version and search for compilation context

echo "=== SEARCH: Cargo.toml for tx3_lang dependency ==="
rg -n 'tx3_lang' crates/trp/Cargo.toml -B 1 -A 1

echo -e "\n=== SEARCH: Cargo.lock or dependency resolution ==="
fd -n 'Cargo.lock' . -exec grep -A 10 'name = "tx3_lang"' {} \;

echo -e "\n=== SEARCH: Error or diagnostic comments in utxos.rs ==="
rg -n 'TODO|FIXME|XXX|ERROR|WARN' crates/trp/src/utxos.rs

echo -e "\n=== SEARCH: All methods in UtxoStore impl ==="
rg -n 'async fn|fn ' crates/trp/src/utxos.rs | grep -A 1 -B 1 'fetch\|narrow'

Length of output: 633



🏁 Script executed:

#!/bin/bash
# Description: Find Cargo.toml files and tx3_lang dependency info

echo "=== SEARCH: All Cargo.toml files ==="
fd 'Cargo.toml' . -type f

echo -e "\n=== ROOT Cargo.toml for tx3_lang ==="
rg -n 'tx3_lang' Cargo.toml -B 1 -A 1 2>/dev/null || echo "Not found in root"

echo -e "\n=== SEARCH: Cargo.lock for tx3_lang ==="
if [ -f Cargo.lock ]; then
  grep -A 5 'name = "tx3_lang"' Cargo.lock || echo "tx3_lang not in Cargo.lock"
else
  echo "No Cargo.lock found"
fi

echo -e "\n=== CONTEXT: Is fetch_utxos_deps the only questionable method? ==="
sed -n '48,110p' crates/trp/src/utxos.rs | head -65

Length of output: 2290


🏁 Script executed:

#!/bin/bash
# Description: Find tx3_lang crate and check UtxoStore trait definition

echo "=== SEARCH: Find tx3-lang or tx3_lang directories ==="
find . -maxdepth 2 -type d -name '*tx3*' 2>/dev/null

echo -e "\n=== SEARCH: Find Cargo.toml files that define tx3_lang ==="
rg -l 'name = "tx3' . 

echo -e "\n=== SEARCH: UtxoStore trait definition ==="
rg -n 'trait UtxoStore' . -A 30 --type rust

echo -e "\n=== SEARCH: fetch_utxos_deps in any file ==="
rg -n 'fetch_utxos_deps' . -B 2 -A 2 --type rust

Length of output: 445


🏁 Script executed:

#!/bin/bash
# Description: Extract tx3_lang version and check .expect() usage safety

echo "=== EXTRACT: tx3_lang version from Cargo.lock ==="
grep -A 3 'name = "tx3_lang"' Cargo.lock | head -6

echo -e "\n=== ANALYZE: Line 93 with .expect() ==="
sed -n '85,100p' crates/trp/src/utxos.rs

echo -e "\n=== SEARCH: How Era::try_from is used elsewhere ==="
rg -n 'Era::try_from' . --type rust -B 2 -A 2

echo -e "\n=== SEARCH: Error handling patterns in this file ==="
rg -n '\.expect\(|\.unwrap\(\)' crates/trp/src/utxos.rs

Length of output: 2900


Replace .expect() with proper error handling at line 93.

The .expect() will panic if Era::try_from(*c) fails. Other parts of the codebase handle this conversion with the ? operator (e.g., crates/trp/src/mapping.rs:117). Use error propagation instead:

let era = pallas::ledger::traverse::Era::try_from(*c)?;

This allows the function to return the conversion error rather than panicking at runtime.

🧰 Tools
🪛 GitHub Actions: CI

[error] 80-80: method fetch_utxos_deps is not a member of trait UtxoStore.

🪛 GitHub Check: Check Build

[failure] 80-80:
method fetch_utxos_deps is not a member of trait UtxoStore

🤖 Prompt for AI Agents
In crates/trp/src/utxos.rs around lines 80 to 103, the closure uses
Era::try_from(...).expect(...) which will panic on conversion failure; replace
the panic with proper error propagation by using the ? operator (or map_err to
convert the conversion error into the function's Result error type) so the
function returns an Err instead of panicking. Modify the mapping to propagate
the conversion error (e.g., use Era::try_from(*c)? or
Era::try_from(*c).map_err(|e| Error::from(e)) as needed) and adjust the closure
or surrounding code to return a Result that can be collected into the final
UtxoMap, ensuring types align with tx3_lang::backend::Error.

.map(|(txoref, eracbor)| {
let TxoRef(a, b) = txoref;
let EraCbor(c, d) = eracbor.as_ref();
let era = pallas::ledger::traverse::Era::try_from(*c).expect("era out of range");
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Replace panic with proper error handling.

Using .expect() will panic at runtime if the era conversion fails. This is particularly risky for production code handling external/untrusted data.

Apply this diff to handle the error gracefully:

-                let era = pallas::ledger::traverse::Era::try_from(*c).expect("era out of range");
+                let era = pallas::ledger::traverse::Era::try_from(*c)
+                    .map_err(|_| tx3_lang::backend::Error::Storage(format!("Invalid era value: {}", c)))?;

Note: You'll need to refactor the closure in the map call (lines 90-99) to return a Result and use collect::<Result<_, _>>() on line 100, similar to the pattern in fetch_utxos (lines 72-75).

Committable suggestion skipped: line range outside the PR's diff.

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.

1 participant