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

Closed
wants to merge 4 commits into 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

Important

Review skipped

Review was skipped due to path filters

⛔ Files ignored due to path filters (1)
  • tauri-app/src-tauri/Cargo.lock is excluded by !**/*.lock

CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including **/dist/** will override the default block on the dist directory, by removing the pattern from both the lists.

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

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, the wasm-bindgen-utils dependency version is updated, and some imports are confined to test scopes.

Changes

File(s) Change Summary
Cargo.toml Updated wasm-bindgen-utils dependency version from "0.0.7" to "0.0.8".
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, improved error propagation, and added serialization for JS interop. Added QuoteResultEnum and multiple result wrapper structs to represent quote results with success or error states.
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

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.
    • Explain this complex logic.
    • 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 explain this code block.
    • @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 explain its main purpose.
    • @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.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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.

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.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Template literals are usually a bit more readable IMO but in this case it doesn't make a difference

Copy link
Contributor

Choose a reason for hiding this comment

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

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Comment on lines 225 to 211
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.

Copy link
Collaborator

Choose a reason for hiding this comment

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

The AI comment doesn't really make sense. Since there is no catch all case, adding new variants will result in a compilation error, which makes it hard to forget

Copy link
Contributor

Choose a reason for hiding this comment

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

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

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.

@hardyjosh hardyjosh requested a review from 0xgleb May 7, 2025 22:51
Copy link
Collaborator

@0xgleb 0xgleb left a comment

Choose a reason for hiding this comment

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

Left some minor comments. Looks good overall

Comment on lines 225 to 211
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
Collaborator

Choose a reason for hiding this comment

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

The AI comment doesn't really make sense. Since there is no catch all case, adding new variants will result in a compilation error, which makes it hard to forget

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

Choose a reason for hiding this comment

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

Template literals are usually a bit more readable IMO but in this case it doesn't make a difference

@findolor
Copy link
Collaborator Author

Closing this one as the changes in this PR somehow ended up in main and this only changes a lockfile

@findolor findolor closed this May 19, 2025
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.

3 participants