Skip to content

Implement wasm macro to js api subgraph functions and add tests#1744

Merged
findolor merged 21 commits intomainfrom
2025-05-05-js-api-subgraph-tests
May 18, 2025
Merged

Implement wasm macro to js api subgraph functions and add tests#1744
findolor merged 21 commits intomainfrom
2025-05-05-js-api-subgraph-tests

Conversation

@findolor
Copy link
Copy Markdown
Collaborator

@findolor findolor commented May 6, 2025

Motivation

The sdk functions for subgraph were using the old wasm bindgen logic and they were missing rust tests. This PR adds both of these things.

See issue: #1634

Solution

  • Use the new wasm macro for all of the functions.
  • Update UI with the latest changes.
  • Add and update existing tests.

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)

fix #1634

Summary by CodeRabbit

  • New Features

    • Added new API functions for fetching trade data, including trade lists, trade details, and trade counts, with improved error handling and TypeScript bindings.
    • Introduced strongly typed result wrappers for all major API functions, replacing generic return types for better type safety and WASM interop.
  • Refactor

    • Unified and simplified error handling across the app and UI, now returning results in a { value, error } structure instead of throwing exceptions.
    • Consolidated multiple calldata types into a single VaultCalldataResult type for deposit, withdraw, and approval operations.
    • Updated all UI and test code to use the new result structure and types, ensuring consistent error and data handling.
  • Bug Fixes

    • Improved error propagation and display in UI components, ensuring users receive clear feedback when API errors occur.
  • Tests

    • Expanded and improved test coverage for all API functions, including comprehensive integration and unit tests for order, vault, transaction, and trade data.
  • Chores

    • Updated internal dependencies and TypeScript bindings for improved maintainability and cross-platform compatibility.

@findolor findolor added this to the Raindex SDK v1 milestone May 6, 2025
@findolor findolor self-assigned this May 6, 2025
@findolor findolor added test test code rust Related to rust crates labels May 6, 2025
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 6, 2025

Walkthrough

This change refactors the JS API crate and its consumers to return strongly typed Rust structs wrapped in a unified result type, replacing generic JsValue results and exception-based error handling. It unifies error types, introduces explicit error property checking in TypeScript/JavaScript consumers, consolidates calldata types, and adds comprehensive Rust and JS/TS tests for subgraph APIs.

Changes

File(s) Change Summary
crates/js_api/src/subgraph/order.rs, crates/js_api/src/subgraph/add_order.rs, crates/js_api/src/subgraph/remove_order.rs, crates/js_api/src/subgraph/transaction.rs, crates/js_api/src/subgraph/vault.rs Refactored all subgraph-related API functions to return strongly typed Rust structs in a unified result wrapper, replacing JsValue and exception-based error handling. Unified error types to SubgraphError. Replaced wasm_bindgen with wasm_export. Added/updated wrapper result structs, removed redundant serialization, and added comprehensive async tests using HTTP mocks. Consolidated calldata types in vault APIs.
crates/js_api/src/subgraph/mod.rs, crates/js_api/src/subgraph/trades.rs Added new trades submodule with trade-related API functions and result wrappers. Extended SubgraphError with UrlParseError and conversion to WasmEncodedError.
crates/js_api/Cargo.toml Added url crate with serde feature and serde_json as dev-dependency.
crates/js_api/src/lib.rs Changed conditional compilation for subgraph module to include test builds.
crates/subgraph/src/multi_orderbook_client.rs, crates/subgraph/src/pagination.rs, crates/subgraph/src/types/common.rs Made wasm trait derivations and implementations unconditional for various argument and result structs, and made fields in MultiSubgraphArgs public.
crates/subgraph/src/orderbook_client.rs Made From<OrderbookSubgraphClientError> for JsValue unconditional and updated imports for error types.
packages/orderbook/test/js_api/*.test.ts Refactored all JS API tests to check for explicit error property on result objects instead of relying on exceptions. Updated assertions to use value property.
packages/ui-components/src/__tests__/*.test.ts Updated all mocks and assertions to expect API results as { value: ... } or { error: ... } objects, matching new result structure.
packages/ui-components/src/lib/components/**/*.svelte Updated all query functions to explicitly check for error property in API results, throw on error, and return value property. Simplified type imports for vault balance changes.
packages/ui-components/src/lib/components/CodeMirrorRainlang.svelte Refactored to handle explicit error property from extendOrder result, displaying error message in template if present.
packages/ui-components/src/lib/services/awaitTransactionIndexing.ts Updated to expect WasmEncodedResult wrapper for all subgraph fetches, adjusting polling and result extraction logic.
packages/ui-components/src/lib/stores/transactionStore.ts Consolidated calldata types to use VaultCalldataResult in transaction argument types.
packages/webapp/src/__tests__/DepositOrWithdrawModal.test.ts, packages/webapp/src/lib/components/DepositOrWithdrawModal.svelte Updated mocks, assertions, and logic to use unified VaultCalldataResult type and explicit error property checks for calldata APIs.

Sequence Diagram(s)

sequenceDiagram
    participant JS/TS UI
    participant WASM API
    participant Rust Subgraph Client

    JS/TS UI->>WASM API: call getOrderByHash(args)
    WASM API->>Rust Subgraph Client: fetch order by hash
    Rust Subgraph Client-->>WASM API: SgOrder or SubgraphError
    WASM API-->>JS/TS UI: { value: SgOrder } or { error: SubgraphError }

    Note over JS/TS UI: UI checks for 'error' property, throws or uses 'value'
Loading
sequenceDiagram
    participant JS/TS UI
    participant WASM API

    JS/TS UI->>WASM API: call getVaultDepositCalldata(vault, amount)
    WASM API-->>JS/TS UI: { value: VaultCalldataResult } or { error: SubgraphError }

    Note over JS/TS UI: UI checks for 'error', uses 'value' if no error
Loading

Assessment against linked issues

Objective Addressed Explanation
Add missing tests for JS API crate (#1634)

Possibly related PRs

Suggested labels

js/wasm

Suggested reviewers

  • hardyjosh

📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 60672d7 and 792b061.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (2)
  • crates/js_api/src/lib.rs (1 hunks)
  • crates/subgraph/src/types/common.rs (4 hunks)
🧰 Additional context used
🧠 Learnings (1)
crates/js_api/src/lib.rs (2)
Learnt from: findolor
PR: rainlanguage/rain.orderbook#1744
File: crates/subgraph/src/orderbook_client.rs:44-46
Timestamp: 2025-05-14T05:13:59.713Z
Learning: In the rain.orderbook project, WASM dependencies are intentionally made available in non-WASM targets to facilitate testing of WASM-related functionality, so conditional compilation guards like `#[cfg(target_family = "wasm")]` should not be added to imports or implementations that may be needed for tests.
Learnt from: findolor
PR: rainlanguage/rain.orderbook#1715
File: crates/js_api/src/common/mod.rs:111-118
Timestamp: 2025-04-30T09:28:36.960Z
Learning: In the rain.orderbook repository, the WASM tests are already properly configured with conditional compilation using `#[cfg(target_family = "wasm")]` and `#[cfg(not(target_family = "wasm"))]`, and don't require additional `wasm_bindgen_test_configure!(run_in_browser)` directives.
⏰ Context from checks skipped due to timeout of 90000ms (14)
  • GitHub Check: test
  • GitHub Check: standard-tests (ubuntu-latest, rainix-sol-legal)
  • GitHub Check: test
  • GitHub Check: standard-tests (ubuntu-latest, test-js-bindings)
  • GitHub Check: Deploy-Preview
  • GitHub Check: build-tauri (ubuntu-22.04, true)
  • GitHub Check: standard-tests (ubuntu-latest, rainix-rs-static)
  • GitHub Check: standard-tests (ubuntu-latest, rainix-wasm-test)
  • GitHub Check: standard-tests (ubuntu-latest, rainix-sol-test)
  • GitHub Check: standard-tests (ubuntu-latest, rainix-wasm-artifacts)
  • GitHub Check: standard-tests (ubuntu-latest, rainix-sol-static)
  • GitHub Check: standard-tests (ubuntu-latest, rainix-sol-artifacts)
  • GitHub Check: standard-tests (ubuntu-latest, ob-rs-test, true)
  • GitHub Check: standard-tests (ubuntu-latest, rainix-rs-artifacts, true)
🔇 Additional comments (5)
crates/js_api/src/lib.rs (1)

7-8: Enable subgraph module during tests
Broadening the cfg to any(target_family = "wasm", test) ensures that the subgraph APIs are compiled in non-WASM test targets, which is necessary for the newly added Rust tests to import and exercise this module. This aligns with the project’s approach of making WASM dependencies available in tests without adding extra conditional guards.

crates/subgraph/src/types/common.rs (4)

20-20: LGTM: Aligns with migration from conditional to unconditional wasm trait implementations.

This change improves the codebase by moving the wasm trait implementation for SgOrdersListFilterArgs out of the conditional compilation block, making it consistent with the new pattern being implemented throughout the codebase.


110-110: LGTM: Migrating wasm trait implementation for better type safety.

Moving the wasm trait implementation for SgOrderWithSubgraphName out of the conditional module allows for more consistent usage in the JS API refactoring. This supports the goal of returning strongly typed Rust structs instead of generic JsValue results.


135-135: LGTM: Consistent approach to wasm trait implementation.

Making the SgVaultsListFilterArgs wasm trait implementation unconditional aligns with the pattern being established in this PR. This change simplifies the code structure and ensures these traits are consistently available.


356-356: LGTM: Improving type safety for JS API interactions.

Adding an unconditional wasm trait implementation for SgAddOrderWithOrder supports the PR's goal of replacing generic JsValue with strongly typed Rust structs in the JS API. This change enables more direct and safer use of this struct in the JS API functions.

✨ 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.
    • 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.

@findolor findolor marked this pull request as ready for review May 9, 2025 05:02
@findolor findolor requested review from 0xgleb and hardyjosh May 9, 2025 05:02
Copy link
Copy Markdown
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: 24

🔭 Outside diff range comments (7)
packages/orderbook/test/js_api/order.test.ts (1)

693-724: 🧹 Nitpick (assertive)

Updated order fetching by hash

The tests for fetching orders by hash are correctly updated to handle the new result wrapper pattern.

Consider using template literals in both instances:

-const result = await getOrderByHash(mockServer.url + '/sg1', order1.orderHash);
+const result = await getOrderByHash(`${mockServer.url}/sg1`, order1.orderHash);
🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Use a template literal.

(lint/style/useTemplate)


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

Unsafe fix: Use a template literal.

(lint/style/useTemplate)

packages/orderbook/test/js_api/vault.test.ts (1)

85-107: ⚠️ Potential issue

Test assumes a deterministic ordering that the implementation may not guarantee

getVaults aggregates results coming from two different subgraph calls executed in parallel.
Unless the underlying implementation explicitly preserves the original subgraphs array order, vaults[0] could refer to either network.

Using find or Array.prototype.some instead of relying on index positions will make the test robust:

-assert.equal(vaults[0].vault.id, vault1.id);
-assert.equal(vaults[0].subgraphName, 'network-one');
-assert.equal(vaults[1].vault.id, vault2.id);
-assert.equal(vaults[1].subgraphName, 'network-two');
+const one = vaults.find(v => v.subgraphName === 'network-one')!;
+const two = vaults.find(v => v.subgraphName === 'network-two')!;
+assert.strictEqual(one.vault.id, vault1.id);
+assert.strictEqual(two.vault.id, vault2.id);

This avoids sporadic test failures when execution order changes.

🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Use a template literal.

(lint/style/useTemplate)


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

Unsafe fix: Use a template literal.

(lint/style/useTemplate)

packages/ui-components/src/lib/services/awaitTransactionIndexing.ts (1)

126-147: 🛠️ Refactor suggestion

Polling loop ignores explicit error responses – may hang until timeout

If the subgraph replies with { error: … }, the current logic just treats it as
“not successful” and continues polling until maxAttempts, potentially hiding
real problems and wasting time.

A minimal fix:

-const data = await fetchData(subgraphUrl, txHash);
-if (data.value && isSuccess(data.value)) {
+const data = await fetchData(subgraphUrl, txHash);
+if (data.error) {
+  clearInterval(checkInterval);
+  resolve({ error: data.error.msg ?? data.error.toString() });
+  return;
+}
+if (data.value && isSuccess(data.value)) {

That way callers get immediate feedback instead of a generic timeout.

crates/subgraph/src/types/common.rs (1)

169-188: ⚠️ Potential issue

Duplicate impl_wasm_traits! risk

impl_wasm_traits!(SgVault); appears here, while a second invocation for the same type exists in the impls module gated to wasm (lines 691-707).
If the outer call is now unconditional, compiling with --target wasm32-unknown-unknown will produce duplicate trait impl errors.

Please remove one of the two invocations or guard them consistently.

crates/js_api/src/subgraph/order.rs (1)

46-77: 🧹 Nitpick (assertive)

Use BTreeMap to guarantee deterministic vault ordering in tests & WASM output

sort_vaults uses a HashMap; key iteration order is non-deterministic, which:

  • Makes serialised JSON order unstable
  • Can break snapshot / golden tests
  • Causes flickering UI diffs when iterating keys in JS

Replacing with BTreeMap<String, Vec<SgVault>> preserves insertion order by key and incurs negligible overhead for the three keys involved.

-use std::collections::{HashMap, HashSet};
+use std::collections::{BTreeMap, HashSet};

-fn sort_vaults(order: &SgOrder) -> HashMap<String, Vec<SgVault>> {
-    let mut sorted_vaults: HashMap<String, Vec<SgVault>> = HashMap::new();
+fn sort_vaults(order: &SgOrder) -> BTreeMap<String, Vec<SgVault>> {
+    let mut sorted_vaults: BTreeMap<String, Vec<SgVault>> = BTreeMap::new();
crates/js_api/src/subgraph/vault.rs (2)

139-148: ⚠️ Potential issue

Allowance comparison should be >=, not >

If allowance == deposit_amount, no approval is needed, yet the current logic will generate approval calldata because the > guard passes.

-    if allowance > deposit_amount {
+    if allowance >= deposit_amount {
         return Err(SubgraphError::InvalidAmount);
     }

Adjust the accompanying tests that expect an error for the equality case instead of the “less than” case.


170-176: 🧹 Nitpick (assertive)

Early-exit on negative / malformed amounts

U256::from_str will happily parse negative-looking strings like “-1” as Err, but the error message bubbles up from U256 and may confuse JS callers.

Wrap with a domain-specific error:

let amount = U256::from_str(amount).map_err(|_| SubgraphError::InvalidAmount)?;

This keeps the error surface uniform.

♻️ Duplicate comments (1)
packages/ui-components/src/lib/services/awaitTransactionIndexing.ts (1)

199-200: Keep TransactionConfig.fetchData consistent with awaitSubgraphIndexing

See comment above – duplicate but still present here. Defining a single helper
type such as

export type Encoded<T> = WasmEncodedResult<T | null | undefined>;

and re-using it in both places avoids future drift.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 6c9827d and bec5259.

⛔ 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 (42)
  • Cargo.toml (1 hunks)
  • crates/js_api/Cargo.toml (1 hunks)
  • crates/js_api/src/lib.rs (1 hunks)
  • crates/js_api/src/subgraph/add_order.rs (1 hunks)
  • crates/js_api/src/subgraph/mod.rs (2 hunks)
  • crates/js_api/src/subgraph/order.rs (3 hunks)
  • crates/js_api/src/subgraph/remove_order.rs (1 hunks)
  • crates/js_api/src/subgraph/trades.rs (1 hunks)
  • crates/js_api/src/subgraph/transaction.rs (1 hunks)
  • crates/js_api/src/subgraph/vault.rs (5 hunks)
  • crates/subgraph/Cargo.toml (0 hunks)
  • crates/subgraph/src/multi_orderbook_client.rs (1 hunks)
  • crates/subgraph/src/orderbook_client.rs (2 hunks)
  • crates/subgraph/src/pagination.rs (1 hunks)
  • crates/subgraph/src/types/common.rs (8 hunks)
  • packages/orderbook/test/js_api/addOrder.test.ts (1 hunks)
  • packages/orderbook/test/js_api/order.test.ts (7 hunks)
  • packages/orderbook/test/js_api/removeOrder.test.ts (1 hunks)
  • packages/orderbook/test/js_api/transaction.test.ts (1 hunks)
  • packages/orderbook/test/js_api/vault.test.ts (8 hunks)
  • packages/ui-components/src/__tests__/OrderAPY.test.ts (1 hunks)
  • packages/ui-components/src/__tests__/OrderDetail.test.ts (3 hunks)
  • packages/ui-components/src/__tests__/OrderVaultsVolTable.test.ts (1 hunks)
  • packages/ui-components/src/__tests__/VaultBalanceChangesTable.test.ts (3 hunks)
  • packages/ui-components/src/__tests__/VaultDetail.test.ts (2 hunks)
  • packages/ui-components/src/__tests__/awaitTransactionIndexing.test.ts (5 hunks)
  • packages/ui-components/src/__tests__/transactionStore.test.ts (2 hunks)
  • packages/ui-components/src/lib/components/CodeMirrorRainlang.svelte (2 hunks)
  • packages/ui-components/src/lib/components/charts/OrderTradesChart.svelte (1 hunks)
  • packages/ui-components/src/lib/components/charts/VaultBalanceChart.svelte (2 hunks)
  • packages/ui-components/src/lib/components/detail/OrderDetail.svelte (1 hunks)
  • packages/ui-components/src/lib/components/detail/VaultDetail.svelte (1 hunks)
  • packages/ui-components/src/lib/components/tables/OrderAPY.svelte (2 hunks)
  • packages/ui-components/src/lib/components/tables/OrderTradesListTable.svelte (2 hunks)
  • packages/ui-components/src/lib/components/tables/OrderVaultsVolTable.svelte (1 hunks)
  • packages/ui-components/src/lib/components/tables/OrdersListTable.svelte (2 hunks)
  • packages/ui-components/src/lib/components/tables/VaultBalanceChangesTable.svelte (3 hunks)
  • packages/ui-components/src/lib/components/tables/VaultsListTable.svelte (1 hunks)
  • packages/ui-components/src/lib/services/awaitTransactionIndexing.ts (5 hunks)
  • packages/ui-components/src/lib/stores/transactionStore.ts (2 hunks)
  • packages/webapp/src/__tests__/DepositOrWithdrawModal.test.ts (5 hunks)
  • packages/webapp/src/lib/components/DepositOrWithdrawModal.svelte (3 hunks)
💤 Files with no reviewable changes (1)
  • crates/subgraph/Cargo.toml
🧰 Additional context used
🧬 Code Graph Analysis (2)
packages/ui-components/src/__tests__/OrderDetail.test.ts (1)
packages/ui-components/src/lib/__fixtures__/orderDetail.ts (1)
  • mockOrder (68-210)
packages/ui-components/src/lib/services/awaitTransactionIndexing.ts (1)
tauri-app/src/lib/stores/settings.ts (2)
  • subgraphUrl (83-87)
  • orderHash (268-273)
🪛 Biome (1.9.4)
packages/orderbook/test/js_api/addOrder.test.ts

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

Unsafe fix: Use a template literal.

(lint/style/useTemplate)

packages/orderbook/test/js_api/transaction.test.ts

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

Unsafe fix: Use a template literal.

(lint/style/useTemplate)

packages/orderbook/test/js_api/removeOrder.test.ts

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

Unsafe fix: Use a template literal.

(lint/style/useTemplate)

packages/orderbook/test/js_api/vault.test.ts

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

Unsafe fix: Use a template literal.

(lint/style/useTemplate)


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

Unsafe fix: Use a template literal.

(lint/style/useTemplate)


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

Unsafe fix: Use a template literal.

(lint/style/useTemplate)


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

Unsafe fix: Use a template literal.

(lint/style/useTemplate)


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

Unsafe fix: Use a template literal.

(lint/style/useTemplate)

packages/orderbook/test/js_api/order.test.ts

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

Unsafe fix: Use a template literal.

(lint/style/useTemplate)


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

Unsafe fix: Use a template literal.

(lint/style/useTemplate)


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

Unsafe fix: Use a template literal.

(lint/style/useTemplate)


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

Unsafe fix: Use a template literal.

(lint/style/useTemplate)


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

Unsafe fix: Use a template literal.

(lint/style/useTemplate)


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

Unsafe fix: Use a template literal.

(lint/style/useTemplate)


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

Unsafe fix: Use a template literal.

(lint/style/useTemplate)


[error] 722-722: 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 (15)
  • GitHub Check: standard-tests (ubuntu-latest, test-js-bindings)
  • GitHub Check: standard-tests (ubuntu-latest, rainix-wasm-test)
  • GitHub Check: standard-tests (ubuntu-latest, rainix-rs-static)
  • GitHub Check: standard-tests (ubuntu-latest, rainix-wasm-artifacts)
  • GitHub Check: standard-tests (ubuntu-latest, rainix-sol-test)
  • GitHub Check: standard-tests (ubuntu-latest, rainix-sol-artifacts)
  • GitHub Check: standard-tests (ubuntu-latest, rainix-rs-artifacts, true)
  • GitHub Check: standard-tests (ubuntu-latest, ob-rs-test, true)
  • GitHub Check: standard-tests (ubuntu-latest, rainix-sol-static)
  • GitHub Check: Deploy-Preview
  • GitHub Check: git-clean
  • GitHub Check: build-tauri (ubuntu-22.04, true)
  • GitHub Check: test
  • GitHub Check: test
  • GitHub Check: test
🔇 Additional comments (62)
crates/js_api/Cargo.toml (2)

33-33: Good addition of the url crate with serde support

Adding the url crate with serde features is appropriate for the refactoring to strongly typed result wrappers. This will help with proper URL parsing and validation in the subgraph functions.


37-37: Appropriate dev dependency for testing

Adding serde_json as a dev-dependency is suitable for testing the serialization/deserialization of the new strongly typed result wrappers in the subgraph modules.

packages/ui-components/src/__tests__/OrderVaultsVolTable.test.ts (1)

11-11: Good adaptation to the new result wrapper pattern

The mock implementation has been correctly updated to return a Promise that resolves to an object with a value property containing the data, which aligns with the new strongly typed result wrapper pattern introduced in this PR.

packages/ui-components/src/__tests__/OrderAPY.test.ts (1)

10-10: Good adaptation to the new result wrapper pattern

The mock for getOrderPerformance has been correctly updated to return a Promise that resolves to an object with a value property, which aligns with the new strongly typed result wrapper pattern introduced in this PR.

packages/orderbook/test/js_api/transaction.test.ts (1)

23-25: Good adaptation to the new result wrapper pattern

The test has been correctly updated to handle the new API response format with explicit error checking and accessing the result via the value property. This aligns with the refactoring of the JS API functions to use strongly typed result wrappers.

🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Use a template literal.

(lint/style/useTemplate)

crates/js_api/src/lib.rs (1)

3-3: Good change for test enablement

Adding test to the conditional compilation attribute properly aligns with the gui module and will allow the subgraph module to be tested outside of a WebAssembly context, supporting the extensive test additions mentioned in the PR objectives.

Cargo.toml (1)

56-56: Dependency updated to use Git reference

The change to use a Git dependency with a specific commit hash is appropriate for the refactoring effort described in the PR. This ensures a consistent version of wasm-bindgen-utils across the workspace.

Just be aware that Git dependencies can make builds more brittle than published crates since they depend on the availability of the Git repository.

packages/ui-components/src/lib/components/detail/OrderDetail.svelte (1)

69-73: Improved error handling with explicit checks

The refactored query function now properly handles the new result structure by:

  1. Using async/await to handle the Promise-based API
  2. Explicitly checking for errors before accessing values
  3. Converting Rust errors to native JavaScript exceptions with meaningful messages

This is a good pattern that makes error handling more robust and explicit.

packages/orderbook/test/js_api/removeOrder.test.ts (1)

134-136: Improved error handling pattern

The refactored test now correctly uses the new error handling pattern by checking for an error property on the result object, rather than relying on exceptions. This is consistent with the broader changes in the codebase and provides more explicit error checking.

🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Use a template literal.

(lint/style/useTemplate)

packages/ui-components/src/lib/components/detail/VaultDetail.svelte (1)

47-53: Good update to explicit error handling

The refactoring to use async/await with explicit error checking improves the code by properly handling the new result structure. The function now checks if an error exists in the response and throws it appropriately, while returning the value property on success.

packages/ui-components/src/lib/components/tables/OrderVaultsVolTable.svelte (1)

21-36: Proper implementation of async error handling

This change correctly updates the query function to handle the new WASM-encoded result format. The function now:

  1. Awaits the asynchronous API call
  2. Checks for errors and throws them if present
  3. Returns the value property when successful

This approach aligns with the PR's goal of modernizing the SDK functions and improving error handling.

packages/ui-components/src/lib/components/tables/OrdersListTable.svelte (1)

67-79: Good refactoring to async/await with proper error handling

The implementation correctly updates the query function to handle the new result format from the refactored Rust API. The change properly awaits the API call, checks for errors in the result, and returns the value property when successful.

packages/ui-components/src/lib/components/tables/VaultsListTable.svelte (1)

71-82: Well-implemented async error handling pattern

This refactoring follows the same pattern as the other components, properly implementing the async/await pattern with explicit error checking. The code now correctly handles the new WasmEncodedResult structure returned by the Rust API.

packages/ui-components/src/__tests__/OrderDetail.test.ts (3)

132-140: API return structure updated to include value wrapper

The mock implementation of getOrderByHash now returns data wrapped in a value property, correctly reflecting the updated API structure in the Rust subgraph modules. This change is part of the broader refactoring where all API functions now return strongly typed result wrappers.


154-154: Consistent error handling with null value wrapped in result structure

The mock for the "no data" case now returns { value: null } instead of a direct null, maintaining consistency with the new API return structure.


217-228: Properly adjusted mock for inactive order test case

The test case for checking the inactive order behavior correctly uses the new response structure with a value wrapper containing the modified order and empty vaults. This ensures the test accurately reflects how the component would handle real API responses.

packages/ui-components/src/lib/components/charts/OrderTradesChart.svelte (1)

26-27: Added explicit error handling for the updated API response structure

The query function now properly checks for data.error and throws an error with the message from data.error.msg if present. Otherwise, it passes data.value to prepareHistoricalOrderChartData. This ensures proper error handling with the new WASM result wrapper pattern.

packages/ui-components/src/__tests__/VaultDetail.test.ts (2)

85-85: Mock return updated to match new WASM-exported function structure

The getVault mock now returns { value: mockData } instead of directly returning the mock data, correctly reflecting the updated API structure where results are wrapped in a value property.


101-101: Consistent null return format with the new API structure

The mock for the "no data" case now returns { value: null } within the standardized result wrapper, maintaining consistency with the updated API return structure.

packages/ui-components/src/__tests__/VaultBalanceChangesTable.test.ts (3)

2-2: Added Mock type import for proper typing

Added the Mock type import from vitest, which is used to properly type-cast the mocked functions, improving type safety in the tests.


49-49: Updated mock implementation to follow new result wrapper pattern

The getVaultBalanceChanges mock now returns { value: mockVaultBalanceChanges } instead of directly returning the mock data, correctly reflecting the updated API structure where results are wrapped in a value property.


100-100: Consistent mock structure in second test case

The second test case also properly uses the updated mock implementation pattern of wrapping results in a value property, ensuring consistency across the test file.

packages/ui-components/src/lib/components/tables/OrderAPY.svelte (2)

5-5: Import updated for new API structure

The import statement has been updated to only import the getOrderPerformance function, removing the OrderPerformance type import which is no longer needed with the new API structure.


22-24: API error handling updated

The query function has been refactored to handle the new return format where results are wrapped in an object with value and error properties. This aligns with the broader pattern of explicit error handling across the codebase.

The error handling is now more robust, checking for the presence of an error property and throwing a properly formatted error message when necessary.

crates/subgraph/src/pagination.rs (1)

7-7: Unconditional TypeScript binding support

The SgPaginationArgs struct now derives Tsify unconditionally, rather than only for wasm targets. This ensures consistent TypeScript bindings regardless of compilation target.

This change supports the broader refactoring effort to standardize the WASM export mechanism and provide uniform TypeScript bindings across the codebase.

crates/js_api/src/subgraph/mod.rs (3)

10-10: Added new trades submodule

A new trades submodule has been added to the subgraph API. This module likely consolidates trade-related functionality that was previously scattered elsewhere.

This improves code organization by grouping related functionality together, aligning with good software engineering practices.


34-36: Extended error handling for URL parsing

Added a new error variant UrlParseError to handle URL parsing errors from the url crate. This expands the error handling capabilities of the API.

This enhancement allows for more specific error reporting when dealing with subgraph endpoints, which improves the developer experience by providing clearer error messages.


42-49: Added conversion from SubgraphError to WasmEncodedError

Implemented the From trait to convert SubgraphError into a WasmEncodedError, mapping both the error message and readable message fields. This supports the new WASM export mechanism using strongly typed result wrappers.

This implementation ensures consistent error handling across the JavaScript/TypeScript bindings by properly formatting error messages when they cross the WASM boundary. The choice to use the same string for both msg and readable_msg is appropriate for this use case, though in the future you might want to consider providing more user-friendly messages in the readable_msg field.

crates/subgraph/src/orderbook_client.rs (3)

22-22: Simplified import through prelude usage

Using the glob import of wasm_bindgen_utils::prelude::* simplifies the import statement and makes the code more maintainable when multiple utilities from this module are needed.


44-46: Improved error type organization

The SerdeWasmBindgenError variant now directly uses serde_wasm_bindgen::Error instead of the fully qualified path, making the code more readable while maintaining the same functionality.


51-55: Removed conditional compilation for error conversion

The #[cfg(target_family = "wasm")] attribute has been removed, making the From<OrderbookSubgraphClientError> for JsValue implementation unconditional. This aligns with the PR's goal of modernizing the SDK functions by applying the new wasm macro approach that unifies error handling across targets.

packages/ui-components/src/lib/components/tables/OrderTradesListTable.svelte (1)

30-50: Improved error handling for API responses

The code now properly handles the new result wrapper format from the updated wasm macro APIs. Instead of directly destructuring results, it first stores them in variables, checks for errors explicitly, and then extracts the values. This approach is more robust as it:

  1. Explicitly handles potential errors before accessing data
  2. Provides clear error messages when something goes wrong
  3. Aligns with the new typed result pattern used throughout the codebase
packages/ui-components/src/__tests__/awaitTransactionIndexing.test.ts (6)

41-42: Updated mock to use new result wrapper format

The mock now returns an object with a value property that contains the actual data, matching the updated API response structure that uses typed result wrappers.


75-75: Updated array data mock to use result wrapper format

The mock for array data now follows the new pattern of wrapping results in a value property, consistent with the updated API.


98-99: Updated null result mock to use wrapper format

The null result mock now follows the new pattern of wrapping results in a value property, consistent with the updated API.


123-124: Changed error handling approach

Instead of rejecting the promise to simulate an error, the mock now resolves with an object containing an error property. This reflects the shift from exception-based error handling to a more structured approach using typed error objects.


148-150: Updated sequential mocks to use result wrapper format

The sequential mock responses now consistently use the value property wrapper pattern, ensuring proper testing of the updated API.


273-275: Added test case for handling approval errors

This test now properly verifies that the component can handle an error from the approval calldata fetch while still proceeding with the deposit operation. It uses the new error object format { error: { msg: 'Approval not needed' } } instead of throwing an exception.

packages/webapp/src/__tests__/DepositOrWithdrawModal.test.ts (4)

19-23: Simplified mock returns using result wrapper format

The mocks for vault operation calldata functions now return objects with a single value property containing the calldata string, instead of more complex objects. This aligns with the refactored WASM API that uses typed result wrappers.


107-114: Updated test assertions for new calldata format

The test now correctly accesses the calldata as direct string values from the result's value property, reflecting the simplified response format from the updated API.


138-146: Simplified withdraw transaction calldata handling

The withdraw transaction test now correctly accesses the calldata as a direct string value from the value property, consistent with the new API response format.


273-299: Added robust error handling test for approval failures

This test properly verifies that the component can handle cases where approval calldata returns an error while still proceeding with the deposit operation. It shows the component correctly distinguishes between a critical error and a non-critical one (like "Approval not needed"), allowing the transaction to proceed without approval when appropriate.

packages/ui-components/src/lib/components/charts/VaultBalanceChart.svelte (3)

4-4: Correctly simplified the import for vault balance changes.

The code now uses a consolidated SgVaultBalanceChangeUnwrapped type instead of multiple specific types, which aligns with the unified type system introduced in the PR's wasm macro implementation.


17-24: Proper error handling implementation for the updated wasm API.

The function has been correctly refactored to use async/await pattern and explicitly handle errors from the new wasm macro result structure. This ensures proper propagation of errors from the Rust backend to the UI.


28-28: Updated generic type for chart component.

Correctly updated the generic type parameter for the TanstackLightweightChartLine component to use the consolidated SgVaultBalanceChangeUnwrapped type.

packages/ui-components/src/lib/components/CodeMirrorRainlang.svelte (3)

13-18: Good implementation of structured error handling.

The code properly handles the new result type structure returned by the wasm macro by:

  1. Storing the raw result in a separate variable
  2. Extracting the value only when no error exists
  3. Capturing the error in a dedicated variable for display

This pattern aligns well with the PR's goal of modernizing the wasm API.


23-24: Safe property access with optional chaining.

The use of optional chaining for extendedOrder?.rainlang is correct and prevents errors when extendedOrder is undefined.


36-39: User-friendly error messaging.

The addition of an error display block improves the user experience by showing readable error messages when the API returns errors, rather than silently failing.

packages/ui-components/src/lib/stores/transactionStore.ts (3)

6-10: Simplified type imports with consolidated VaultCalldataResult.

The code now imports a unified VaultCalldataResult type instead of separate types for deposits and withdrawals, which matches the backend changes that standardize return types across the subgraph API.


59-67: Updated transaction argument type with unified calldata result.

The DepositOrWithdrawTransactionArgs interface correctly uses the consolidated VaultCalldataResult type for both approval and transaction calldata, simplifying the codebase while maintaining type safety.


303-369:

Details

❓ Verification inconclusive

Verify compatibility with unwrapped calldata usages.

The handleDepositOrWithdrawTransaction function currently casts the calldata as unknown before casting to 0x${string}. This suggests that the VaultCalldataResult type might not be directly compatible with the expected string format.


🏁 Script executed:

#!/bin/bash
# Check the implementation of VaultCalldataResult type and how it's used in the transaction handler

# First, let's check what the VaultCalldataResult type looks like
rg -A 5 "export (type|interface) VaultCalldataResult" --type ts

# Then check how the calldata is being used in other places
rg "transactionCalldata as" --type ts

# Finally check if there are any type errors related to this
rg "Type.*VaultCalldataResult.*not assignable" --type text

Length of output: 311


I couldn’t locate a definition for VaultCalldataResult in the codebase—let’s search more broadly for it:


🏁 Script executed:

#!/bin/bash
# Search for VaultCalldataResult anywhere in the repo
rg -n "VaultCalldataResult" --glob '*.ts' || echo "No matches found"

# Also search for any related 'VaultCalldata' identifiers
rg -n "VaultCalldata" --glob '*.ts' || echo "No matches found"

Length of output: 1269


Investigate VaultCalldataResult’s exact shape in the external package
I couldn’t find a local definition of VaultCalldataResult—it’s imported from @rainlanguage/orderbook. Before removing the as unknown as \0x${string}`` workaround, please confirm whether:

  • VaultCalldataResult is already a plain hex string type (e.g. string & { __hex: true })
  • Or if it carries additional metadata that needs serialization (in which case a helper to extract the raw hex string is required).

• Check the type declaration in @rainlanguage/orderbook (e.g. in your IDE or in the package’s d.ts files).
• If it’s already \0x${string}`, you can cast directly and drop the unknown`.
• Otherwise add an explicit conversion/map to pull out the hex value.

packages/ui-components/src/lib/components/tables/VaultBalanceChangesTable.svelte (3)

7-8: Correctly updated import to use consolidated type.

The code now uses the unified SgVaultBalanceChangeUnwrapped type, maintaining consistency with the other UI components and the updated wasm exports.


20-27: Proper async error handling for query function.

The query function has been correctly updated to:

  1. Use async/await syntax
  2. Check for errors in the result
  3. Throw a descriptive error message when needed
  4. Return the unwrapped value on success

This matches the new wasm macro return structure that includes both value and error properties.


35-35: Updated generic type for table component.

The generic type parameter for the TanstackAppTable component has been properly updated to use the consolidated SgVaultBalanceChangeUnwrapped type, ensuring type safety throughout the component.

packages/ui-components/src/__tests__/transactionStore.test.ts (2)

8-8: Type import update looks good

The import has been updated to use the new consolidated VaultCalldataResult type, which aligns with the changes made to unify deposit and withdraw calldata types in the subgraph module.


476-477: Type annotation updated correctly

The type annotation for mockTransactionCalldata has been updated to use the consolidated VaultCalldataResult type, which matches the import change on line 8.

crates/subgraph/src/multi_orderbook_client.rs (1)

13-19: Improved struct visibility and trait implementation

The changes to MultiSubgraphArgs correctly:

  1. Add an unconditional Tsify derive
  2. Make the url and name fields public
  3. Apply impl_wasm_traits! without conditional compilation

This aligns with the broader effort to make wasm bindings more consistent and less fragmented throughout the codebase.

crates/js_api/src/subgraph/transaction.rs (2)

1-13: Successfully modernized WASM API function

The refactoring of get_transaction is well-executed:

  1. Uses SubgraphError for unified error handling
  2. Returns a strongly typed SgTransaction instead of generic JsValue
  3. Uses wasm_export with unchecked return type annotation

This transformation aligns perfectly with the PR objective of modernizing the SDK functions with the new wasm macro approach.


15-50: Good test coverage added

The new non-wasm test module is a valuable addition that:

  1. Uses httpmock to simulate subgraph responses
  2. Verifies correct deserialization of transaction data
  3. Tests important fields like id, from, blockNumber, and timestamp

This helps ensure the reliability of the refactored function and improves overall test coverage.

packages/orderbook/test/js_api/order.test.ts (1)

522-605: Updated error handling pattern for performance measurement

The test has been correctly updated to check for errors in the result and access the data via the value property.

🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Use a template literal.

(lint/style/useTemplate)

crates/subgraph/src/types/common.rs (1)

12-22: Un-gated Tsify/impl_wasm_traits may break non-WASM targets

Tsify generates wasm_bindgen code. With the cfg_attr(target_family = "wasm") guard removed, these derives will now compile for every target.
Most host targets (e.g. x86_64-unknown-linux-gnu) don’t have wasm-bindgen in the standard preload set, so builds could fail outside CI’s WASM matrix.

Please either:

  1. Re-introduce the #[cfg_attr(target_family = "wasm", ...)] guard, or
  2. Add wasm-bindgen as an unconditional dependency and confirm non-WASM compilation passes.

Would you run cargo check --workspace --all-targets for a non-WASM target and confirm it still compiles?

crates/js_api/src/subgraph/vault.rs (1)

90-101: validate_amount rejects hex/0x-prefixed values

U256::from_str supports decimal/hex without 0x prefix.
Because calldata methods accept hex in other contexts, clarify expectations or strip the prefix before parsing to avoid surprises.

Example:

let sanitized = amount.trim_start_matches("0x");
let amount = U256::from_str(sanitized)?;

Comment thread packages/orderbook/test/js_api/transaction.test.ts
Comment thread packages/orderbook/test/js_api/removeOrder.test.ts
Comment thread packages/orderbook/test/js_api/addOrder.test.ts
Comment on lines +382 to +384
const result = await getOrderByHash(mockServer.url + '/sg1', order1.orderHash);
if (result.error) assert.fail('expected to resolve, but failed');
assert.equal(result.value.order.id, order1.id);
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot May 9, 2025

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Updated error handling pattern

The test has been correctly updated to work with the new result wrapper structure, checking for an error property instead of using try-catch blocks.

Consider using template literals instead of string concatenation for better readability:

-const result = await getOrderByHash(mockServer.url + '/sg1', order1.orderHash);
+const result = await getOrderByHash(`${mockServer.url}/sg1`, order1.orderHash);
📝 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
const result = await getOrderByHash(mockServer.url + '/sg1', order1.orderHash);
if (result.error) assert.fail('expected to resolve, but failed');
assert.equal(result.value.order.id, order1.id);
const result = await getOrderByHash(`${mockServer.url}/sg1`, order1.orderHash);
if (result.error) assert.fail('expected to resolve, but failed');
assert.equal(result.value.order.id, order1.id);
🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Use a template literal.

(lint/style/useTemplate)

Copy link
Copy Markdown
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
Copy Markdown
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. The functional changes to the error handling pattern are what matter most here.

Comment thread packages/orderbook/test/js_api/order.test.ts
Comment thread crates/js_api/src/subgraph/trades.rs
Comment thread crates/js_api/src/subgraph/order.rs
Comment thread crates/js_api/src/subgraph/order.rs
Comment thread crates/js_api/src/subgraph/order.rs
Comment thread crates/js_api/src/subgraph/vault.rs
Copy link
Copy Markdown
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 questions and minor suggestions but overall seems good.

I guess this would also benefit from a manual test since integration of the different layers wouldn't be covered by unit tests. What are the rough steps I should take to check that everything is working as expected?

Comment thread crates/js_api/src/subgraph/add_order.rs
"removeEvents": []
})
}
fn get_order1() -> SgOrder {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

looks like formatting got a bit messed up here

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I don't get what you mean in here, what happened?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Just some indentation stuff for the sample SgOrder value

Screenshot 2025-05-13 at 16 41 03 Screenshot 2025-05-13 at 16 41 52

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

yeah i see now. i wonder why it didn't get formatted by fmt. i think i will leave it as it is for now as it does not seem critical and looks fine for our case

Comment thread crates/js_api/src/subgraph/order.rs
);
}
}
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

maybe a non-happy-path case or two would be useful. if so then this also would apply to subgraph tests in other sibling modules. alternatively, that can be covered in the module that implements OrderbookSubgraphClient since those tests are be more logically related to subgraph than js_api stuff (no tests there atm)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I haven't added any non happy tests in here because we don't return any custom errors from the bindings in this file. The error comes from the internal logic the libraries use so not sure what to cover over there

When you say the module that implements OrderbookSubgraphClient, which module do you mean?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I meant this one

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

i think we can add non happy tests in the client just like you've said so that we do not need to repeat the same logic in the wasm bindings. we can make sure that we are consistently getting the errors in inner functions

Comment thread crates/subgraph/src/multi_orderbook_client.rs
Comment thread packages/ui-components/src/lib/components/detail/VaultDetail.svelte
Comment on lines 73 to 76
async function handleTransaction(
transactionCalldata: DepositCalldataResult | WithdrawCalldataResult,
approvalCalldata?: ApprovalCalldata | undefined
transactionCalldata: VaultCalldataResult,
approvalCalldata?: VaultCalldataResult | undefined
) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

As far as I can tell, seems like a reasonable suggestion for correcting the type signature

@findolor
Copy link
Copy Markdown
Collaborator Author

@0xgleb we also have js tests for all of these functions. in reality we are catching up on the rust testing and nothing is changed in terms of the core logic

@findolor findolor requested a review from 0xgleb May 14, 2025 04:58
Copy link
Copy Markdown
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: 2

🔭 Outside diff range comments (1)
crates/subgraph/src/orderbook_client.rs (1)

51-55: 🛠️ Refactor suggestion

Consider adding conditional compilation for WASM-specific implementation

This implementation converts OrderbookSubgraphClientError to JsValue using WASM-specific types. If this code is compiled for non-WASM targets where these types might not be available, it could cause compilation errors.

+#[cfg(target_family = "wasm")]
 impl From<OrderbookSubgraphClientError> for JsValue {
     fn from(value: OrderbookSubgraphClientError) -> Self {
         JsError::new(&value.to_string()).into()
     }
 }
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between bec5259 and 60672d7.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (16)
  • crates/js_api/Cargo.toml (1 hunks)
  • crates/js_api/src/lib.rs (1 hunks)
  • crates/subgraph/Cargo.toml (0 hunks)
  • crates/subgraph/src/orderbook_client.rs (2 hunks)
  • packages/ui-components/src/__tests__/VaultBalanceChangesTable.test.ts (3 hunks)
  • packages/ui-components/src/__tests__/VaultDetail.test.ts (2 hunks)
  • packages/ui-components/src/lib/components/charts/VaultBalanceChart.svelte (2 hunks)
  • packages/ui-components/src/lib/components/detail/OrderDetail.svelte (1 hunks)
  • packages/ui-components/src/lib/components/detail/VaultDetail.svelte (1 hunks)
  • packages/ui-components/src/lib/components/tables/OrderTradesListTable.svelte (2 hunks)
  • packages/ui-components/src/lib/components/tables/OrdersListTable.svelte (2 hunks)
  • packages/ui-components/src/lib/components/tables/VaultBalanceChangesTable.svelte (3 hunks)
  • packages/ui-components/src/lib/components/tables/VaultsListTable.svelte (1 hunks)
  • packages/ui-components/src/lib/stores/transactionStore.ts (2 hunks)
  • packages/webapp/src/__tests__/DepositOrWithdrawModal.test.ts (5 hunks)
  • packages/webapp/src/lib/components/DepositOrWithdrawModal.svelte (3 hunks)
💤 Files with no reviewable changes (1)
  • crates/subgraph/Cargo.toml
🧰 Additional context used
🧠 Learnings (2)
crates/js_api/src/lib.rs (1)
Learnt from: findolor
PR: rainlanguage/rain.orderbook#1715
File: crates/js_api/src/common/mod.rs:111-118
Timestamp: 2025-04-30T09:28:36.960Z
Learning: In the rain.orderbook repository, the WASM tests are already properly configured with conditional compilation using `#[cfg(target_family = "wasm")]` and `#[cfg(not(target_family = "wasm"))]`, and don't require additional `wasm_bindgen_test_configure!(run_in_browser)` directives.
packages/webapp/src/lib/components/DepositOrWithdrawModal.svelte (1)
Learnt from: findolor
PR: rainlanguage/rain.orderbook#1744
File: packages/webapp/src/lib/components/DepositOrWithdrawModal.svelte:73-76
Timestamp: 2025-05-09T05:30:02.520Z
Learning: In Rain.orderbook, `VaultCalldataResult` is a wrapper type that contains both `error` and `value` properties. When using this in the `DepositOrWithdrawModal` component, only the inner `value` field is passed to the `handleTransaction` function, not the complete wrapper.
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: test
  • GitHub Check: Deploy-Preview
🔇 Additional comments (30)
crates/js_api/Cargo.toml (2)

32-32: Good addition of URL dependency with serde feature

Adding the URL crate with serde support aligns with the PR objective of updating the subgraph functions to use strongly typed structures rather than generic JsValue returns.


36-36: Appropriate dev dependency for JSON testing

Adding serde_json as a dev-dependency is appropriate for the new test suites that deserialize JSON responses from subgraph endpoints.

crates/js_api/src/lib.rs (1)

5-5: Good conditional compilation update for testing

Changing the attribute to #[cfg(any(target_family = "wasm", test))] correctly enables the subgraph module to be included during testing as well as when targeting WebAssembly. This supports the PR objective of adding Rust tests for the subgraph functions.

packages/ui-components/src/lib/components/detail/VaultDetail.svelte (1)

49-52: Correctly updated error handling for WASM exports

The query function has been properly refactored to handle the new result structure returned by the WASM-exported functions. The async/await pattern with explicit error checking ensures errors are properly surfaced as exceptions.

packages/ui-components/src/lib/components/detail/OrderDetail.svelte (1)

69-72: Correctly updated error handling for WASM exports

The query function has been properly refactored to handle the new result structure returned by the WASM-exported functions. The async/await pattern with explicit error checking ensures errors are properly surfaced as exceptions.

packages/ui-components/src/lib/components/tables/VaultsListTable.svelte (1)

68-79: LGTM! This change properly handles the new result structure from the updated API.

The queryFn has been properly updated to handle the new result structure returned by the getVaults function. It now correctly:

  1. Uses async/await syntax for better readability
  2. Checks for errors in the result object and throws them if present
  3. Returns the value property from the result when successful

This aligns with the broader refactoring where subgraph-related APIs now return strongly typed Rust structs with unified error handling.

packages/ui-components/src/lib/components/tables/OrdersListTable.svelte (1)

67-79: LGTM! Updated to handle the new result structure consistently.

The queryFn has been updated to handle the new result structure from getOrders, matching the pattern used in VaultsListTable and other components. This ensures consistent error handling across the application.

packages/ui-components/src/__tests__/VaultBalanceChangesTable.test.ts (3)

2-2: LGTM! Required import added for the Mock type.

Adding the Mock type import from vitest is necessary for properly typing the mocked functions below.


49-49: LGTM! Updated mock to match the new API contract.

The mock implementation now correctly returns an object with a value property containing the mock data, matching the updated structure of the getVaultBalanceChanges function.


100-100: LGTM! Consistent mock update in the second test.

The mock is consistently updated here as well, maintaining the same pattern across all test cases.

packages/ui-components/src/__tests__/VaultDetail.test.ts (2)

85-85: LGTM! Updated mock to match the new API response structure.

The mock for getVault now returns an object with a value property containing the mock data, correctly reflecting the changes to the Rust SDK.


101-101: LGTM! Consistent mock update for the null case.

The mock for the "no data" case has been correctly updated to return { value: null } instead of directly returning null, matching the unified error handling approach.

packages/ui-components/src/lib/components/tables/OrderTradesListTable.svelte (1)

30-49: Proper error handling for async API calls

This change improves the error handling for the subgraph API calls by explicitly checking for errors in the response objects before accessing the values. The code now properly throws meaningful errors when the API calls fail.

packages/ui-components/src/lib/components/charts/VaultBalanceChart.svelte (3)

4-4: Improved type consolidation with unified type

The change from specific types to the consolidated SgVaultBalanceChangeUnwrapped type aligns with the project's effort to unify the API's type system.


17-23: Proper async/await pattern with explicit error handling

This refactoring from a synchronous function returning a promise to an async function with proper error checking is a solid improvement. The code now explicitly checks for errors in the API response before proceeding.


28-28: Updated type parameter to match API changes

The type parameter update maintains consistency with the API changes and ensures type safety throughout the component.

packages/ui-components/src/lib/stores/transactionStore.ts (2)

9-9: Simplified type imports with unified VaultCalldataResult

The consolidation to a single VaultCalldataResult type improves code consistency and simplifies the type system.


61-62: Unified transaction calldata types

The update to use the consolidated VaultCalldataResult type for both approval and transaction calldata improves consistency in the transaction handling interface.

packages/webapp/src/__tests__/DepositOrWithdrawModal.test.ts (4)

20-22: Updated mocks to match new API response structure

The mock implementations now correctly return objects with a value property, matching the new WASM export pattern implemented in the Rust code.


112-114: Updated test expectations for deposit transaction

The test expectations now correctly extract the calldata values from the result objects, matching how the actual component would process these values.


140-141: Updated test expectations for withdraw transaction

Similar to the deposit transaction update, the withdraw transaction test now correctly extracts the calldata value.


273-275: Added error case testing for approval calldata

This new test case properly verifies the component's error handling behavior when the approval calldata request returns an error. This is a good addition to ensure robust error handling.

packages/ui-components/src/lib/components/tables/VaultBalanceChangesTable.svelte (3)

7-7: Improved type handling with unified type import

Good job consolidating the import to use a single unified type SgVaultBalanceChangeUnwrapped instead of multiple specific types. This simplifies the imports and aligns with the broader refactoring effort to strengthen the type system.


20-26: Properly handling the new result structure with error checking

This change correctly implements the new async/await pattern and adds explicit error handling for the refactored API. The code now correctly:

  1. Awaits the result from the async getVaultBalanceChanges function
  2. Checks for an error property and throws if present
  3. Returns only the value property when successful

This pattern ensures errors are properly propagated and handled in the UI's query system.


35-35: Updated generic type parameter correctly

The generic type parameter update for TanstackAppTable ensures type safety throughout the component with the new unified type.

packages/webapp/src/lib/components/DepositOrWithdrawModal.svelte (5)

11-12: Updated imports to support the new calldata result type

Good job updating the imports to include the consolidated VaultCalldataResult type, which is part of the broader refactoring to standardize return types across the API.


92-99: Improved error handling for approval calldata

The code now correctly checks for errors in the approval calldata result by examining the error property. This is more robust than relying on exception handling or null checks.


101-109: Properly handling deposit calldata with conditional approval

The implementation correctly:

  1. Awaits the deposit calldata result
  2. Checks for errors and sets an error message if found
  3. Only proceeds with the transaction if no errors are present
  4. Passes the inner .value property to handleTransaction
  5. Conditionally includes the approval calldata only if it has no errors

This ensures proper error handling and a better user experience.


111-116: Withdraw calldata handling matches the new result pattern

The withdraw calldata handling follows the same pattern as deposit calldata, with proper error checking and passing only the inner .value property to handleTransaction when successful.


73-76:

Details

✅ Verification successful

Parameter types in handleTransaction now align with the WASM exports

The function signature now correctly reflects that it accepts VaultCalldataResult types for both the transaction and approval calldata. Note that based on the previous conversation in review comments, the actual value passed to this function is the inner .value property, not the full wrapper object.


🌐 Web query:

What is the common pattern for handling result types in Rust WASM exports?

💡 Result:

In Rust WASM (WebAssembly) exports, a common pattern for handling result types (i.e., functions that may return a success value or an error) involves converting Rust's Result<T, E> types into a format that's easily consumable by JavaScript or other WASM environments.

Common Patterns:

  1. Using wasm-bindgen with Result support:

    • The wasm-bindgen crate has built-in support for mapping Rust's Result<T, JsValue> to JavaScript's exceptions.
    • When a Rust function returns Result<T, JsValue>, wasm-bindgen will:
      • Return the Ok(T) value to JavaScript.
      • Convert the Err(JsValue) into a JavaScript exception, which can be caught with try/catch in JS.
    • Example:
      #[wasm_bindgen]
      pub fn do_something() -> Result<(), JsValue> {
          if some_condition {
              Ok(())
          } else {
              Err(JsValue::from_str("An error occurred"))
          }
      }
    • On the JS side:
      try {
        wasm.do_something();
        console.log("Success");
      } catch (e) {
        console.error("Error:", e);
      }
  2. Manual error handling using return value wrapping:

    • Sometimes you want to avoid exceptions or wasm-bindgen for more lightweight bindings.
    • Return a packed struct or tuple from Rust that includes both an error code and the actual result.
    • Example custom struct or tuple:
      #[repr(C)]
      pub struct ResultWrapper {
          pub ok: bool,
          pub value: Option<i32>, // or whatever type
          pub error_code: u32,
      }
      
      #[no_mangle]
      pub extern "C" fn do_something() -> ResultWrapper {
          if some_condition {
              ResultWrapper { ok: true, value: Some(42), error_code: 0 }
          } else {
              ResultWrapper { ok: false, value: None, error_code: 1 } // 1 = some error
          }
      }
    • The consumer can check ok and handle error codes accordingly.
  3. Returning nullable pointers or sentinel values:

    • For functions returning pointers or handles, use null or sentinel values to indicate errors.
    • For example, return 0 or null pointer in case of failure and use a separate mechanism (error callback, global state) for error details.
  4. Using anyhow or thiserror and mapping errors to strings:

    • If errors are converted into strings, the WASM function returns a tuple (result, error_message).
    • JavaScript reads these and checks if error_message is null or empty to determine success.

Summary:

  • The idiomatic Rust WASM pattern leverages wasm-bindgen's support for Result<T, JsValue>, enabling easy integration with JS try/catch.
  • For lower-level or manual ABI, use structs or tuples that encode success/failure explicitly.
  • Avoid panics and prefer explicit error signaling so WASM consumers can handle errors gracefully.

If you want, I can provide more concrete examples or focus on a particular approach.


🏁 Script executed:

#!/bin/bash
set -e

echo "Searching for VaultCalldataResult definition..."
rg "interface VaultCalldataResult" -n || echo "No interface declaration found"
rg "type VaultCalldataResult" -n || echo "No type declaration found"

echo
echo "Searching for handleTransaction usage in the file..."
rg "handleTransaction" -n packages/webapp/src/lib/components/DepositOrWithdrawModal.svelte || echo "No occurrences found"

echo
echo "Printing context around handleTransaction invocations..."
rg -C2 "handleTransaction" -n packages/webapp/src/lib/components/DepositOrWithdrawModal.svelte || echo "No context available"

Length of output: 1614


🏁 Script executed:

#!/bin/bash
set -e

echo "Showing handleTransaction implementation context..."
rg -A20 "async function handleTransaction" -n packages/webapp/src/lib/components/DepositOrWithdrawModal.svelte

Length of output: 801


🏁 Script executed:

#!/bin/bash
set -e

echo "Listing packages directory..."
ls -1 packages

Length of output: 125


🏁 Script executed:

#!/bin/bash
set -e

echo "Inspecting VaultCalldataResult definition in orderbook package..."
rg -C5 "VaultCalldataResult" -n packages/orderbook

Length of output: 200


Align handleTransaction parameters with VaultCalldataResult

The handleTransaction signature now correctly accepts VaultCalldataResult for both the transaction and optional approval calldata, matching the manual ABI wrapper emitted by the WASM export. Upstream we pass in depositCalldataResult.value and approvalCalldataResult.value, ensuring only the raw calldata object is handed off to this handler—no further changes are needed.

use thiserror::Error;
#[cfg(target_family = "wasm")]
use wasm_bindgen_utils::prelude::{JsError, JsValue};
use wasm_bindgen_utils::prelude::*;
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot May 14, 2025

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Consider using explicit imports instead of glob imports

While glob imports (*) provide convenience, they can make it less clear which specific imports are being used in the code. For better code clarity and maintenance, consider explicitly importing the specific types needed from wasm_bindgen_utils::prelude.

-use wasm_bindgen_utils::prelude::*;
+use wasm_bindgen_utils::prelude::{JsError, JsValue};
📝 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
use wasm_bindgen_utils::prelude::*;
-use wasm_bindgen_utils::prelude::*;
+use wasm_bindgen_utils::prelude::{JsError, JsValue};

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

we are importing multiple things at the same time and it is a lot of dependencies so using this syntax is better for our use case

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@findolor Understood! You're right - when importing many items from a prelude module (which is designed for glob importing), the glob syntax makes sense. I'll respect your preference on this case since you're working with multiple dependencies from this module. Thank you for explaining your reasoning.

Comment on lines 44 to +46
#[cfg(target_family = "wasm")]
#[error(transparent)]
SerdeWasmBindgenError(#[from] wasm_bindgen_utils::prelude::serde_wasm_bindgen::Error),
SerdeWasmBindgenError(#[from] serde_wasm_bindgen::Error),
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot May 14, 2025

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Potential inconsistency in conditional compilation

The SerdeWasmBindgenError variant is conditionally compiled with #[cfg(target_family = "wasm")], but the From<OrderbookSubgraphClientError> for JsValue implementation (lines 51-55) has no such attribute despite using WASM-specific types. This could cause compilation errors in non-WASM targets.


🏁 Script executed:

#!/bin/bash
# Check if From implementation is used in non-WASM contexts
rg -A 3 -B 3 "impl\s+From<OrderbookSubgraphClientError>" --glob "!*orderbook_client.rs"

# Check for other conditionally compiled WASM code
rg "#\[cfg\(target_family\s*=\s*\"wasm\"\)\]" -A 3

Length of output: 34740


I’d like to inspect the imports and the impl From block to confirm whether JsValue/JsError are unguarded. Let me dump the top ~200 lines of orderbook_client.rs:


🏁 Script executed:

#!/bin/bash
sed -n '1,200p' crates/subgraph/src/orderbook_client.rs

Length of output: 6853


Guard WASM-specific conversion behind #[cfg(target_family = "wasm")]

The JsError/JsValue import and the impl From<OrderbookSubgraphClientError> for JsValue are unconditionally compiled, yet depend on WASM-only types (and your error enum only includes the SerdeWasmBindgenError variant under #[cfg(target_family = "wasm")]). Non-WASM targets will fail to find JsError/JsValue.

Please update crates/subgraph/src/orderbook_client.rs as follows:

• Wrap the prelude import in a #[cfg(target_family = "wasm")]
• Annotate the impl From<…> for JsValue block with the same cfg

Suggested diff:

--- a/crates/subgraph/src/orderbook_client.rs
+++ b/crates/subgraph/src/orderbook_client.rs
@@
- use wasm_bindgen_utils::prelude::*;
+ #[cfg(target_family = "wasm")]
+ use wasm_bindgen_utils::prelude::*;
@@
- impl From<OrderbookSubgraphClientError> for JsValue {
+ #[cfg(target_family = "wasm")]
+ impl From<OrderbookSubgraphClientError> for JsValue {
     fn from(value: OrderbookSubgraphClientError) -> Self {
         JsError::new(&value.to_string()).into()
     }
📝 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
#[cfg(target_family = "wasm")]
#[error(transparent)]
SerdeWasmBindgenError(#[from] wasm_bindgen_utils::prelude::serde_wasm_bindgen::Error),
SerdeWasmBindgenError(#[from] serde_wasm_bindgen::Error),
// … other imports …
#[cfg(target_family = "wasm")]
use wasm_bindgen_utils::prelude!();
// … other code …
#[cfg(target_family = "wasm")]
impl From<OrderbookSubgraphClientError> for JsValue {
fn from(value: OrderbookSubgraphClientError) -> Self {
JsError::new(&value.to_string()).into()
}
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

sometimes we need the wasm dependencies in non wasm targets for testing purposes so we don't need the guarding. the logic we currently have is working fine

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@findolor I understand your approach now. It makes sense that you need the WASM dependencies available in non-WASM targets for testing purposes. Thank you for explaining the rationale behind this pattern. I'll keep this in mind for future reviews.


✏️ Learnings added
Learnt from: findolor
PR: rainlanguage/rain.orderbook#1744
File: crates/subgraph/src/orderbook_client.rs:44-46
Timestamp: 2025-05-14T05:13:59.637Z
Learning: In the rain.orderbook project, WASM dependencies are intentionally made available in non-WASM targets to facilitate testing of WASM-related functionality, so conditional compilation guards like `#[cfg(target_family = "wasm")]` should not be added to imports or implementations that may be needed for tests.

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.

@findolor findolor merged commit f454563 into main May 18, 2025
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

rust Related to rust crates test test code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Missing test - JS API crate

3 participants