Skip to content

Update order quote wasm bindings to use wasm export macro #1706

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

findolor
Copy link
Collaborator

@findolor findolor commented Apr 28, 2025

Motivation

See issue: rainlanguage/rain.wasm#17

Solution

Checks

By submitting this for review, I'm confirming I've done the following:

  • made this PR as small as possible
  • unit-tested any new functionality
  • linked any relevant issues or PRs
  • [ ] included screenshots (if this involves a front-end change)

Summary by CodeRabbit

  • Refactor

    • Improved error handling and result structures for quoting operations in the JavaScript API, providing clearer and more consistent error messages.
    • Enhanced internal code organization and error propagation for quote-related functions.
  • Bug Fixes

    • Updated UI component logic to properly handle and display errors from quote requests.
    • Improved test coverage and reliability by making error checks and assertions more explicit.
  • Chores

    • Updated dependency management for improved build consistency.
    • Cleaned up imports to restrict certain utilities to test code only.

@findolor findolor added rust Related to rust crates webapp labels Apr 28, 2025
@findolor findolor added this to the Test coverage, tech debt milestone Apr 28, 2025
@findolor findolor requested a review from hardyjosh April 28, 2025 13:55
@findolor findolor self-assigned this Apr 28, 2025
Copy link
Contributor

coderabbitai bot commented Apr 28, 2025

Walkthrough

The changes update the Rust and JavaScript codebases to improve error handling and result typing for quote-related operations. The Rust API for quoting is refactored to use strongly typed result wrapper structs and a unified error enum, replacing generic JavaScript values and manual error handling. This leads to updated function signatures and the introduction of new result structs and error types. Corresponding test files and Svelte components are modified to explicitly check for errors and handle result objects more robustly. Additionally, dependency management is updated to use a specific Git commit for a utility crate, and some imports are confined to test scopes.

Changes

File(s) Change Summary
Cargo.toml Changed wasm-bindgen-utils dependency from a versioned crate to a Git dependency pointing to a specific commit.
crates/js_api/src/gui/state_management.rs Moved js_sys::{eval, Reflect} imports from the main module scope into the tests module, limiting their usage to tests only.
crates/quote/src/js_api/mod.rs Refactored JavaScript API bindings for quoting: replaced wasm_bindgen macros with wasm_export, introduced strongly typed result wrapper structs, unified error handling with QuoteBindingsError enum, updated function signatures to return Result types, and improved error propagation and serialization for JS interop.
packages/orderbook/test/quote/test.test.ts Updated tests to explicitly check for .value or .error properties on results, used expect to fail early on unexpected results, removed try/catch blocks, and improved clarity on success and failure conditions.
packages/ui-components/src/lib/components/detail/TanstackOrderQuote.svelte Changed the orderQuoteQuery function to await getOrderQuote, check for errors in the result, throw on error, and return the value on success, adding explicit error handling to the query.
packages/ui-components/src/tests/TanstackOrderQuote.test.ts Updated mocks of getOrderQuote to return an object with a value property containing the array of quotes, reflecting the new result structure from the Rust API.

Sequence Diagram(s)

sequenceDiagram
    participant JS_Client as JavaScript Client
    participant Wasm_API as Rust Wasm API
    participant QuoteEngine as Quote Engine

    JS_Client->>Wasm_API: Call do_quote_targets(params)
    Wasm_API->>QuoteEngine: Perform quote operation
    QuoteEngine-->>Wasm_API: Return quote result or error
    Wasm_API-->>JS_Client: Return DoQuoteTargetsResult (Success/Error)

    JS_Client->>Wasm_API: Call get_order_quote(order, rpcUrl)
    Wasm_API->>QuoteEngine: Perform order quote
    QuoteEngine-->>Wasm_API: Return quote or error
    Wasm_API-->>JS_Client: Return DoOrderQuoteResult (Success/Error)
Loading

Suggested labels

test

Suggested reviewers

  • hardyjosh
✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@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: 6

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f460fc4 and 1d963f8.

⛔ Files ignored due to path filters (2)
  • Cargo.lock is excluded by !**/*.lock
  • tauri-app/src-tauri/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (5)
  • Cargo.toml (1 hunks)
  • crates/js_api/src/gui/state_management.rs (1 hunks)
  • crates/quote/src/js_api/mod.rs (1 hunks)
  • packages/orderbook/test/quote/test.test.ts (8 hunks)
  • packages/ui-components/src/lib/components/detail/TanstackOrderQuote.svelte (1 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
packages/orderbook/test/quote/test.test.ts

[error] 192-192: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.

(lint/style/useTemplate)


[error] 334-334: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.

(lint/style/useTemplate)


[error] 347-347: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.

(lint/style/useTemplate)

⏰ Context from checks skipped due to timeout of 90000ms (7)
  • GitHub Check: standard-tests (ubuntu-latest, rainix-rs-static)
  • GitHub Check: standard-tests (ubuntu-latest, test-js-bindings)
  • GitHub Check: test
  • GitHub Check: test
  • GitHub Check: test
  • GitHub Check: build-tauri (ubuntu-22.04, true)
  • GitHub Check: git-clean
🔇 Additional comments (9)
crates/js_api/src/gui/state_management.rs (1)

291-291: Good security improvement: eval and Reflect are now limited to the test scope.

Moving these imports from the module level to the test module scope is a positive change that confines potentially unsafe JavaScript evaluation functions to testing code only. This aligns with the overall PR objective of improving the safety and robustness of the WebAssembly bindings.

Cargo.toml (1)

56-56:

✅ Verification successful

Dependency updated to specific Git commit hash.

The dependency for wasm-bindgen-utils is now pinned to a specific commit in the rain.wasm repository. This provides better versioning control but introduces a potential maintenance concern.


🏁 Script executed:

#!/bin/bash
# Check if this dependency is being actively maintained
curl -s "https://api.github.com/repos/rainlanguage/rain.wasm/commits?sha=4379d24a671742a58ec5cdab2c39fecbda59619d" | jq '.[] | {date: .commit.author.date, message: .commit.message}' | head -n 10

Length of output: 379


Pinning to a Git commit is intentional—but keep it up-to-date

The dependency for wasm-bindgen-utils is pinned to commit 4379d24a671742a58ec5cdab2c39fecbda59619d to ensure reproducible builds. Our check shows the rain.wasm repo is actively maintained (latest commits on 2025-04-28), so you’ll be able to track updates easily.

• No immediate issue—just remember that this won’t auto-update.
• Consider periodically bumping the commit or switching to a published crate version (if available) to surface new fixes and improvements.
• If you rely on semver guarantees, evaluate whether a crates.io release could better suit your workflow.

packages/orderbook/test/quote/test.test.ts (6)

3-3: Added proper test assertion tools from Vitest.

Importing expect from Vitest enhances the test suite with more explicit assertion capabilities.


26-27: Enhanced result validation with explicit error checking.

Now properly validating the structured result object by checking for error presence before accessing the value.


117-118: Improved error handling and result type validation.

The tests now explicitly check for the presence of the value property before proceeding with assertions, making the tests more robust against unexpected result structures.

Also applies to: 192-194


276-277: Added explicit error checking before assertions.

Properly verifying the success case before accessing the result value, improving test reliability.

Also applies to: 290-290


334-343: Explicit error case testing with proper error message validation.

Now testing both the presence of an error and the specific error message, providing better test coverage for failure scenarios.

🧰 Tools
🪛 Biome (1.9.4)

[error] 334-334: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.

(lint/style/useTemplate)


345-356: Added proper gas parameter testing with result validation.

The test now correctly verifies successful execution with the gas parameter and validates the returned result structure.

🧰 Tools
🪛 Biome (1.9.4)

[error] 347-347: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.

(lint/style/useTemplate)

crates/quote/src/js_api/mod.rs (1)

57-61: U256::from_str expects decimal – hex order hashes will fail

U256::from_str in Alloy parses base-10. Most on-chain order hashes are supplied as 0x-prefixed hex strings, which will trigger U256ParseError.

-let order_hash = U256::from_str(order_hash)?;
+let order_hash = U256::from_hex(order_hash)?;

Please either switch to from_hex or document the expected format and adjust callers.

Comment on lines +47 to +51
queryFn: async () => {
const result = await getOrderQuote([order], rpcUrl);
if (result.error) throw new Error(result.error.msg);
return result.value;
},
Copy link
Contributor

@coderabbitai coderabbitai bot Apr 28, 2025

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Improved error handling in order quote query.

The code now properly handles potential error responses from the WebAssembly binding by explicitly checking for error objects and throwing JavaScript exceptions with appropriate messages. This is a significant improvement over the previous implementation which didn't distinguish between success and error cases.

Consider adding a more descriptive error message that includes context about the order being queried:

-			if (result.error) throw new Error(result.error.msg);
+			if (result.error) throw new Error(`Failed to get quote for order ${order.id}: ${result.error.msg}`);
📝 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
queryFn: async () => {
const result = await getOrderQuote([order], rpcUrl);
if (result.error) throw new Error(result.error.msg);
return result.value;
},
queryFn: async () => {
const result = await getOrderQuote([order], rpcUrl);
if (result.error) throw new Error(`Failed to get quote for order ${order.id}: ${result.error.msg}`);
return result.value;
},

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

No need to do this

Copy link
Contributor

Choose a reason for hiding this comment

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

@findolor Understood! The existing error handling you've implemented is already a good improvement, and the additional context in the error message isn't necessary. Thanks for considering my suggestion.

console.log(error);
assert.fail('expected to resolve, but failed');
}
const result = await doQuoteTargets([target], mockServer.url + '/rpc-url');
Copy link
Contributor

@coderabbitai coderabbitai bot Apr 28, 2025

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Use template literals instead of string concatenation.

Static analysis identified style issues with string concatenation.

Apply these style improvements:

-		const result = await doQuoteTargets([target], mockServer.url + '/rpc-url');
+		const result = await doQuoteTargets([target], `${mockServer.url}/rpc-url`);

-		const doQuoteTargetsResult = await doQuoteTargets([target], mockServer.url + '/rpc-url');
+		const doQuoteTargetsResult = await doQuoteTargets([target], `${mockServer.url}/rpc-url`);

-			mockServer.url + '/rpc-url',
+			`${mockServer.url}/rpc-url`,

Also applies to: 334-334, 347-347

🧰 Tools
🪛 Biome (1.9.4)

[error] 192-192: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.

(lint/style/useTemplate)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

No need to do this

Copy link
Contributor

Choose a reason for hiding this comment

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

@findolor Understood! I'll respect your preference to keep the string concatenation as is.


✏️ Learnings added
Learnt from: findolor
PR: rainlanguage/rain.orderbook#1706
File: packages/orderbook/test/quote/test.test.ts:192-192
Timestamp: 2025-04-28T14:02:08.650Z
Learning: In the rain.orderbook repository, string concatenation (using +) is acceptable and preferred over template literals in some cases, despite linter suggestions.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Comment on lines +225 to +233
pub fn to_readable_msg(&self) -> String {
match self {
Self::QuoteError(e) => format!("Quote error: {}", e),
Self::FromHexError(e) => format!("Failed to parse orderbook address: {}", e),
Self::U256ParseError(e) => format!("Failed to parse u256 value: {}", e),
Self::SerdeWasmBindgenError(err) => format!("Data serialization error: {}", err),
}
}
}
Copy link
Contributor

@coderabbitai coderabbitai bot Apr 28, 2025

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

to_readable_msg is easy to forget when new variants are added

Manually matching every variant is brittle. Implementing Display (or relying on thiserror’s autogenerated messages) lets you delegate:

impl std::fmt::Display for QuoteBindingsError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        std::fmt::Debug::fmt(self, f)
    }
}

impl QuoteBindingsError {
    pub fn to_readable_msg(&self) -> String { self.to_string() }
}

Reduces maintenance overhead.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

No need to do this

Copy link
Contributor

Choose a reason for hiding this comment

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

@findolor Understood! I'll respect your preference to keep the explicit error message formatting in the to_readable_msg method. Thanks for the feedback.

Comment on lines +235 to +239
impl From<QuoteBindingsError> for JsValue {
fn from(value: QuoteBindingsError) -> Self {
JsError::new(&value.to_string()).into()
}
}
Copy link
Contributor

@coderabbitai coderabbitai bot Apr 28, 2025

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Preserve structured error info when bubbling to JS

Wrapping in JsError hides readable_msg. Consider passing the already-defined WasmEncodedError instead:

-fn from(value: QuoteBindingsError) -> Self {
-    JsError::new(&value.to_string()).into()
-}
+fn from(value: QuoteBindingsError) -> Self {
+    WasmEncodedError::from(value).into_js_value()
+}

This keeps both machine-readable (msg) and user-friendly (readable_msg) fields available to consumers.

📝 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
impl From<QuoteBindingsError> for JsValue {
fn from(value: QuoteBindingsError) -> Self {
JsError::new(&value.to_string()).into()
}
}
impl From<QuoteBindingsError> for JsValue {
fn from(value: QuoteBindingsError) -> Self {
WasmEncodedError::from(value).into_js_value()
}
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We are not using JsError

Copy link
Contributor

Choose a reason for hiding this comment

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

Unable to process this comment: maximum number of iterations reached.

🧩 Analysis chain

@findolor I see the current implementation does use JsError. Are you perhaps planning to remove this usage in a future update? I'd like to understand your comment better so I can provide a more helpful suggestion.


🏁 Script executed:

#!/bin/bash
# Look for the implementation of From<QuoteBindingsError> for JsValue
rg "impl From<QuoteBindingsError> for JsValue" -A 5 --context-separator=""

Length of output: 410


@findolor I see that JsError is being used in the implementation of From<QuoteBindingsError> for JsValue. It's likely imported through wasm_bindgen_utils::prelude::*.

Looking at the original review suggestion, I think I understand your point now - you might want to use the WasmEncodedError directly instead of JsError for better error handling.

Would you like me to help create a revised suggestion that avoids using JsError and uses WasmEncodedError instead?


🏁 Script executed:

#!/bin/bash
# Check the imports in the file to see JsError
rg "use.*JsError" crates/quote/src/js_api/mod.rs
# Check if JsError is imported via prelude
rg "use wasm_bindgen_utils::prelude::\*" crates/quote/src/js_api/mod.rs
# Check what's included in wasm_bindgen_utils::prelude
rg "pub use.*JsError" --type rust

Length of output: 160


🏁 Script executed:

#!/bin/bash
# Look at the imports in the file
cat crates/quote/src/js_api/mod.rs | head -20

# Check if JsError is available in wasm_bindgen_utils
rg -U "JsError" -C 5 -g "*.rs" --glob="**/wasm_bindgen_utils/**/*.rs"

# Check what prelude contains
rg -U "mod prelude" -C 10 -g "*.rs" --glob="**/wasm_bindgen_utils/**/*.rs"

Length of output: 9475


🏁 Script executed:

#!/bin/bash
# Check where WasmEncodedError is defined
rg -U "struct WasmEncodedError" -A 5 --type rust

# Check where JsError is imported from
rg -U "use wasm_bindgen.*JsError" --type rust

# Check for WasmEncodedError::into_js_value
rg -U "impl.*WasmEncodedError.*into_js_value" -A 5 --type rust

Length of output: 256


🏁 Script executed:

#!/bin/bash
# Check where WasmEncodedError is defined in the project
rg -U "pub struct WasmEncodedError" --type rust

# Check for imports of WasmEncodedError
rg "use.*WasmEncodedError" --type rust

# Check if wasm_bindgen_utils is a external dependency or internal project
grep -A 10 "wasm-bindgen-utils" crates/quote/Cargo.toml

Length of output: 509


🏁 Script executed:

#!/bin/bash
# Check workspace Cargo.toml for wasm-bindgen-utils
grep -A 10 "wasm-bindgen-utils" Cargo.toml

# Check for the definition of WasmEncodedError in wasm-bindgen-utils
git grep -A 10 "pub struct WasmEncodedError" -- "*/wasm_bindgen_utils/**"

# Look more broadly for WasmEncodedError in dependencies
fd -e rs -x grep -l "WasmEncodedError" {} \;

Length of output: 599


🏁 Script executed:

#!/bin/bash
# Let's check if WasmEncodedError has direct conversion to JsValue
rg -U "impl From<WasmEncodedError> for JsValue" -A 5 --type rust

# Check what the WasmEncodedError struct might have - check one of the files where it's used
grep -A 20 "WasmEncodedError" crates/quote/src/js_api/mod.rs

# Look at the whole implementation of the conversion to WasmEncodedError
rg -U "impl From<.*Error> for WasmEncodedError" -A 10 --type rust

Length of output: 2066


🏁 Script executed:

#!/bin/bash
# Check in wasm-bindgen-utils crate for the WasmEncodedError implementation
# since it's an external dependency from GitHub
git clone --depth 1 --branch master --single-branch https://github.com/rainlanguage/rain.wasm /tmp/rain.wasm
grep -r "pub struct WasmEncodedError" /tmp/rain.wasm
grep -r "into_js_value" /tmp/rain.wasm

Length of output: 507


🏁 Script executed:

#!/bin/bash
# Let's try cloning using the specific commit mentioned in Cargo.toml
git clone https://github.com/rainlanguage/rain.wasm /tmp/rain.wasm
cd /tmp/rain.wasm
git checkout 4379d24a671742a58ec5cdab2c39fecbda59619d
grep -r "pub struct WasmEncodedError" .
grep -r "into_js_value" .

Length of output: 2135


🏁 Script executed:

#!/bin/bash
# Check the full definition of WasmEncodedError
cd /tmp/rain.wasm
cat src/result.rs

# Check if there's any implementation for converting WasmEncodedError to JsValue
grep -r "impl.*WasmEncodedError" --include="*.rs" .

# Check what's in the prelude module
cat src/prelude.rs

Length of output: 2778



🧬 Code Graph Analysis Results

Relevant code snippets for crates/quote/src/js_api/mod.rs

File: crates/quote/src/js_api/mod.rs (lines 1-130)

  • The file defines several Rust structs and enums for quoting operations exposed to JavaScript via wasm-bindgen.
  • The QuoteBindingsError enum is defined as the main error type for this module, wrapping several error types (Error, FromHexError, ParseError, serde_wasm_bindgen::Error).
  • The impl From<QuoteBindingsError> for JsValue converts QuoteBindingsError into a JsValue by creating a JsError with the error's string representation.
  • The impl From<QuoteBindingsError> for WasmEncodedError converts the error into a structured error with a message and a readable message.
  • Notably, the code uses JsError in the conversion from QuoteBindingsError to JsValue, but there is no direct usage of a JsError type elsewhere in the file.
  • The user comment "We are not using JsError" likely refers to the fact that JsError is only used in the From<QuoteBindingsError> for JsValue implementation and not elsewhere.

Key relevant excerpt:

impl From<QuoteBindingsError> for JsValue {
    fn from(value: QuoteBindingsError) -> Self {
        JsError::new(&value.to_string()).into()
    }
}

This shows that JsError is used here to convert Rust errors into JavaScript errors.


No other relevant snippets found

The snippet from packages/ui-components/src/lib/errors/DeploymentStepsError.ts is unrelated to this Rust file and its usage of JsError.


Summary

  • The only usage of JsError in crates/quote/src/js_api/mod.rs is in the From<QuoteBindingsError> for JsValue conversion.
  • There is no other usage or import of JsError in the file.
  • This context is relevant to the user comment about not using JsError.

Comment on lines +18 to +31
#[derive(Serialize, Deserialize, Debug, Clone, Tsify)]
#[serde(untagged)]
pub enum QuoteResultEnum {
Success {
value: OrderQuoteValue,
#[tsify(type = "undefined")]
error: Option<String>,
},
Err {
#[tsify(type = "undefined")]
value: Option<OrderQuoteValue>,
error: String,
},
}
Copy link
Contributor

@coderabbitai coderabbitai bot Apr 28, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue

Ambiguous untagged enum – serde cannot reliably pick a variant

Both variants expose identical keys (value, error) wrapped in Option.
During deserialization Serde selects the first variant whose fields can be populated, meaning payloads that contain only error will still match Success if value is omitted – leading to silent logic errors.

Recommended fixes:

-#[serde(untagged)]
+// Option 1 – add an explicit discriminator
+#[serde(tag = "type", rename_all = "lowercase")]
 //  Success { … }  =>  { "type": "success", value: … }
 //  Err { … }      =>  { "type": "err", error: … }

-or keep `untagged` but make field-sets disjoint:
-  * rename one of the fields, or
-  * remove the `error` field from `Success` and the `value` field from `Err`.
+// Option 2 – keep `untagged` but remove the unused option from each
+Success { value: … }
+Err    { error: … }

This guarantees deterministic (de)serialization.

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

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This works with no issues

Copy link
Contributor

Choose a reason for hiding this comment

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

@findolor I understand that the current implementation is working for your specific use case. The warning was about a theoretical edge case in Serde's untagged enum deserialization that might not manifest in your particular usage pattern.

Thanks for confirming that it works as intended in your implementation! Let me know if you need any further assistance with the WebAssembly bindings.

Copy link
Contributor

@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

♻️ Duplicate comments (2)
crates/quote/src/js_api/mod.rs (2)

229-233: Structured error lost by converting through JsError

Previous feedback noted that wrapping in JsError discards the readable_msg produced by to_readable_msg(). The current code still does so:

JsError::new(&value.to_string()).into()

If retaining detailed error metadata for JS callers is desirable, convert via WasmEncodedError instead:

-        JsError::new(&value.to_string()).into()
+        WasmEncodedError::from(value).into_js_value()

Re-surfacing this in case it was left in unintentionally.


18-31: serde(untagged) enum remains potentially ambiguous

Both variants expose the same optional fields (value, error), so payloads missing value could deserialize to Success rather than Err, depending on variant order. Earlier review highlighted this edge-case; re-flagging for awareness should requirements change.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1d963f8 and 4a0b6c2.

📒 Files selected for processing (1)
  • crates/quote/src/js_api/mod.rs (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Deploy-Preview
  • GitHub Check: test
🔇 Additional comments (1)
crates/quote/src/js_api/mod.rs (1)

134-136: 🧹 Nitpick (assertive)

Redundant mut res declaration duplicated here

The same pattern appears in do_quote_specs. Deleting it keeps the codebase consistent and warning-free.

-    let mut res: Vec<QuoteResultEnum> = vec![];

Likely an incorrect or invalid review comment.

Copy link
Contributor

@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

🔭 Outside diff range comments (1)
packages/ui-components/src/__tests__/TanstackOrderQuote.test.ts (1)

2-13: 🛠️ Refactor suggestion

Add afterEach hook to avoid cross-test mock leakage

getOrderQuote is re-mocked in every test, but Vitest will preserve previous mockResolvedValueOnce calls if the module isn’t reset.
Adding an afterEach that clears all mocks prevents brittle order-dependent failures when the file grows or tests are reordered.

-import { test, vi, type Mock } from 'vitest';
+import { afterEach, test, vi, type Mock } from 'vitest';+afterEach(() => {
+	vi.resetAllMocks();
+});
♻️ Duplicate comments (1)
crates/quote/src/js_api/mod.rs (1)

225-229: Consider returning structured WasmEncodedError instead of opaque JsError
(Same concern raised previously – re-flagging for visibility)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4a0b6c2 and fb5809d.

📒 Files selected for processing (2)
  • crates/quote/src/js_api/mod.rs (1 hunks)
  • packages/ui-components/src/__tests__/TanstackOrderQuote.test.ts (5 hunks)
🔇 Additional comments (2)
packages/ui-components/src/__tests__/TanstackOrderQuote.test.ts (2)

117-121: Verify expected pair text (ETH/USD vs ETH/USDT)

The refreshed mock still returns pairName: 'ETH/USDT', yet the assertion looks for 'ETH/USD' (missing T).
If the UI is truly supposed to show the trimmed symbol it should do so consistently, otherwise this expectation will fail or hide a bug.

Please double-check the component output and adjust either the mock or the assertion accordingly.


14-25: Mock shape update matches new API – looks good

Wrapping the quote array in a { value: [...] } object aligns the tests with the refactored getOrderQuote return type. No further changes required here.

Comment on lines +57 to +61
#[wasm_export(js_name = "getId", unchecked_return_type = "string")]
pub fn get_id(orderbook: &str, order_hash: &str) -> Result<String, QuoteBindingsError> {
let orderbook = Address::from_hex(orderbook)?;
let order_hash = U256::from_str(order_hash)?;
Ok(encode_prefixed(make_order_id(orderbook, order_hash)))
Copy link
Contributor

@coderabbitai coderabbitai bot Apr 29, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue

order_hash parsing fails for hex strings

U256::from_str expects a decimal representation; passing the common "0x…" hash will raise U256ParseError.
Since the public JS API forwards hex, use FromHex instead:

-    let order_hash = U256::from_str(order_hash)?;
+    let order_hash = U256::from_hex(order_hash)?;

This keeps the function symmetrical with the Address::from_hex call above.

📝 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
#[wasm_export(js_name = "getId", unchecked_return_type = "string")]
pub fn get_id(orderbook: &str, order_hash: &str) -> Result<String, QuoteBindingsError> {
let orderbook = Address::from_hex(orderbook)?;
let order_hash = U256::from_str(order_hash)?;
Ok(encode_prefixed(make_order_id(orderbook, order_hash)))
#[wasm_export(js_name = "getId", unchecked_return_type = "string")]
pub fn get_id(orderbook: &str, order_hash: &str) -> Result<String, QuoteBindingsError> {
let orderbook = Address::from_hex(orderbook)?;
let order_hash = U256::from_hex(order_hash)?;
Ok(encode_prefixed(make_order_id(orderbook, order_hash)))
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We don't need to do this

Copy link
Contributor

Choose a reason for hiding this comment

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

@findolor Understood, I'll respect your decision not to make this change. Thanks for the clarification.


✏️ Learnings added
Learnt from: findolor
PR: rainlanguage/rain.orderbook#1706
File: crates/quote/src/js_api/mod.rs:57-61
Timestamp: 2025-04-29T06:19:15.422Z
Learning: In the rain.orderbook codebase, the `get_id` function is designed to use `U256::from_str()` rather than `U256::from_hex()` for parsing order hashes, despite the potential for hex string inputs.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
rust Related to rust crates webapp
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant