Skip to content

Feature/cli improvements#644

Open
kpob wants to merge 5 commits intorelease/2.6.0from
feature/cli-improvements
Open

Feature/cli improvements#644
kpob wants to merge 5 commits intorelease/2.6.0from
feature/cli-improvements

Conversation

@kpob
Copy link
Copy Markdown
Contributor

@kpob kpob commented Apr 2, 2026

No description provided.

Copy link
Copy Markdown

@llamapreview llamapreview bot left a comment

Choose a reason for hiding this comment

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

AI Code Review by LlamaPReview

🎯 TL;DR & Recommendation

Recommendation: Request Changes

This PR introduces a breaking public API change by switching map key-value separators from ':' to '=', which will break existing CLI usage without a migration path.

🌟 Strengths

  • Better error messages and enum support improve user experience and developer ergonomics.
Priority File Category Impact Summary (≤12 words) Anchors
P1 odra-cli/src/types/mod.rs Architecture Breaking change: map separators ':'→'=' breaks existing CLI commands. path:odra-cli/src/types/error.rs, path:odra-cli/src/types/into_bytes.rs
P2 odra-cli/src/cli.rs Maintainability Removed success logging reduces feedback, could confuse script users.
P2 odra-cli/src/parser.rs Architecture Enum parsing assumes u8 discriminants, may fail for custom enums.
P2 odra-cli/src/parser.rs Maintainability Improved error messages, but arg name may be 'unknown'.
P2 odra-cli/src/entry_point/utils.rs Bug Empty enum description in CLI help reduces discoverability.
P2 odra-cli/src/cmd/whoami.rs Testing Public key formatting change risks non-human-readable output.

📈 Risk Diagram

This diagram illustrates the breaking change in map argument parsing from colon to equals separator.

sequenceDiagram
participant U as User
participant P as CLI Parser
participant M as Map Parsing Logic
U->>P: Provide map argument "key:value" (old format)
P->>M: Parse input
note over M: R1(P1): Map separator changed from ':' to '=', breaking existing usage
M->>P: Error due to unexpected ':' separator
P-->>U: Error message indicating invalid format
Loading
⚠️ **Unanchored Suggestions (Manual Review Recommended)**

The following suggestions could not be precisely anchored to a specific line in the diff. This can happen if the code is outside the changed lines, has been significantly refactored, or if the suggestion is a general observation. Please review them carefully in the context of the full file.


📁 File: odra-cli/src/parser.rs

The error message improvement is excellent for user experience, providing structured feedback with value, expected format, and cause. However, get_arg_long may return "unknown" if the argument has no long form (e.g., positional args). While CLI arguments in Odra typically use --long format, defensive coding could handle short args or provide more context.

Suggestion:

Consider extracting argument display name (preferring long, then short, then "arg").

Related Code:

fn get_arg_long(arg: Option<&Arg>) -> &str {
    arg.and_then(|a| a.get_long()).unwrap_or("unknown")
}

fn make_parse_error(...) {
    let message = format!(
        "Failed to parse --{}\n Value:    '{}'\n Expected: {}\n Cause:    {}\n",
        get_arg_long(arg),
        value,
        types::format_type_hint(ty),
        err
    );
}


💡 Have feedback? We'd love to hear it in our GitHub Discussions.
✨ This review was generated by LlamaPReview Advanced, which is free for all open-source projects. Learn more.

Comment on lines 197 to 200
match result {
Ok(_) => prettycli::info("Command executed successfully"),
Err(err) => prettycli::error(&format!("{:?}", err))
Ok(_) => {}
Err(err) => prettycli::error(&format!("{err}"))
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 | Confidence: High

The removal of success logging ("Command executed successfully") reduces user feedback. While this may be intentional to reduce noise, it leaves users without positive confirmation that commands succeeded. This could be confusing in scripts or when debugging. The change is local to the CLI entry point and doesn't break functionality, hence P2.

Code Suggestion:

Consider adding a verbose flag or restoring the success message for non-silent operation.

Comment on lines +88 to +95
pub struct EnumCLParser {
variants: Vec<(String, u16)>
}

impl EnumCLParser {
pub fn new(variants: Vec<(String, u16)>) -> Self {
Self { variants }
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 | Confidence: High

New enum support is architecturally sound. The Evidence Anchors show CommandArg now has enum_variants field and entry_point/utils.rs passes enum variant info. However, there's potential risk: enums are parsed as U8 discriminants via NamedCLType::U8. This assumes all enums fit in u8 and that discriminant values match the CLI's mapping. While the test in contract.rs shows it works for the test enum, there's no compile-time guarantee that custom enums with non-u8 discriminants or custom discriminants would serialize correctly.

Comment on lines +47 to +52
let mut ca = CommandArg::new(
&arg.name,
&arg.description.clone().unwrap_or_default(),
NamedCLType::U8
)
.with_enum_variants(variant_info);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 | Confidence: Medium

Speculative: The arg.description is cloned then unwrap_or_default is used, but description is Option<String>. This is safe, but there's a potential mismatch: the arg.description might be None, resulting in empty help text for enum arguments in CLI help output. This reduces discoverability of enum variants.

Code Suggestion:

Consider generating a default description like "Enum: {variants}" if description is None.

Comment on lines +28 to +29
let pk = env.public_key(&caller);
prettycli::info(&format!("Public key: {pk}"));
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 | Confidence: Low

Speculative: The change uses Display formatting ({pk}) instead of debug formatting ({:?}). This assumes PublicKey implements Display with user-friendly output. While likely correct, if Display isn't implemented or produces non-human-readable output (like raw bytes), the UX degrades. The related_context doesn't show PublicKey type definition to verify.

Code Suggestion:

Verify `PublicKey` has appropriate `Display` impl, or fall back to `to_string()` if uncertain.

@@ -185,7 +231,7 @@ pub(crate) fn into_bytes(ty: &NamedCLType, input: &str) -> TypeResult<Vec<u8>> {
let parts = input
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[Contextual Comment]
This comment refers to code near real line 230. Anchored to nearest_changed(231) line 231.


P1 | Confidence: High

The change from colon : to equals = for map key-value separators is a breaking public API change. The Evidence Anchors show the error message format and test cases were updated to use key1=value1 instead of key1:value1. This will break all existing CLI usage where map arguments use colon syntax, requiring users to update their command invocations. The severity is P1 because it's a deterministic public API change that will break existing callers without migration path.

Code Suggestion:

Consider adding backward compatibility by accepting both separators, or document as a breaking change requiring user migration.

Evidence: path:odra-cli/src/types/error.rs, path:odra-cli/src/types/into_bytes.rs

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 3, 2026

Benchmark report

Action Details Gas diff
Wasm Deploy Filename: Benchmark.wasm 🟢 -40.422668153 CSPR (13.02%)
Contract Call Entry point: set_variable 🟢 -0.000294075 CSPR (0.21%)
Contract Call Entry point: get_variable 🟢 -0.00042597 CSPR (0.08%)
Contract Call Entry point: set_struct_variable 🟢 -0.00000525 CSPR (0.00%)
Contract Call Entry point: get_struct_variable 🔴 +0.00192744 CSPR (0.51%)
Contract Call Entry point: set_mapping 🟢 -0.000254535 CSPR (0.18%)
Contract Call Entry point: get_mapping 🔴 +0.00134586 CSPR (0.39%)
Contract Call Entry point: push_list 🟢 -0.00042783 CSPR (0.15%)
Contract Call Entry point: get_list 🔴 +0.00139242 CSPR (0.40%)
Contract Call Entry point: init_submodule 🔴 +0.002051025 CSPR (0.23%)
Contract Call Entry point: call_submodule 🔴 +0.0010608 CSPR (0.31%)
Contract Call Entry point: call_payable 🔴 +0.00516006 CSPR (0.09%)
Contract Call Entry point: transfer_back 🔴 +0.000439485 CSPR (0.02%)
Contract Call Entry point: emit_event 🔴 +0.00015501 CSPR (0.12%)
Contract Call Entry point: set_named_key 🟢 -0.000067935 CSPR (0.04%)
Contract Call Entry point: get_named_key 🔴 +0.00158328 CSPR (0.43%)
Contract Call Entry point: set_dictionary 🟢 -0.000379125 CSPR (0.13%)
Contract Call Entry point: get_dictionary 🔴 +0.001392225 CSPR (0.40%)

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 3, 2026

Benchmark report

Action Details Gas diff
Wasm Deploy Filename: Benchmark.wasm 🟢 -40.422668153 CSPR (13.02%)
Contract Call Entry point: set_variable 🟢 -0.000294075 CSPR (0.21%)
Contract Call Entry point: get_variable 🟢 -0.00042597 CSPR (0.08%)
Contract Call Entry point: set_struct_variable 🟢 -0.00000525 CSPR (0.00%)
Contract Call Entry point: get_struct_variable 🔴 +0.00192744 CSPR (0.51%)
Contract Call Entry point: set_mapping 🟢 -0.000254535 CSPR (0.18%)
Contract Call Entry point: get_mapping 🔴 +0.00134586 CSPR (0.39%)
Contract Call Entry point: push_list 🟢 -0.00042783 CSPR (0.15%)
Contract Call Entry point: get_list 🔴 +0.00139242 CSPR (0.40%)
Contract Call Entry point: init_submodule 🔴 +0.002051025 CSPR (0.23%)
Contract Call Entry point: call_submodule 🔴 +0.0010608 CSPR (0.31%)
Contract Call Entry point: call_payable 🔴 +0.00516006 CSPR (0.09%)
Contract Call Entry point: transfer_back 🔴 +0.000439485 CSPR (0.02%)
Contract Call Entry point: emit_event 🔴 +0.00015501 CSPR (0.12%)
Contract Call Entry point: set_named_key 🟢 -0.000067935 CSPR (0.04%)
Contract Call Entry point: get_named_key 🔴 +0.00158328 CSPR (0.43%)
Contract Call Entry point: set_dictionary 🟢 -0.000379125 CSPR (0.13%)
Contract Call Entry point: get_dictionary 🔴 +0.001392225 CSPR (0.40%)

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