Skip to content

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

New issue

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

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

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ test-context = "0.3.0"
portpicker = "0.1.1"
rain-erc = { git = "https://github.com/rainlanguage/rain.erc", rev = "0106e645ebd49334addc698c5aad9a85370eb54d" }
rain-error-decoding = { git = "https://github.com/rainlanguage/rain.error", rev = "72d9577fdaf7135113847027ba951f9a43b41827" }
wasm-bindgen-utils = "0.0.7"
wasm-bindgen-utils = { git = "https://github.com/rainlanguage/rain.wasm", rev = "4379d24a671742a58ec5cdab2c39fecbda59619d" }

[workspace.dependencies.rain_orderbook_bindings]
path = "crates/bindings"
Expand Down
2 changes: 1 addition & 1 deletion crates/js_api/src/gui/state_management.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use super::*;
use js_sys::{eval, Reflect};
use rain_orderbook_app_settings::{gui::GuiDepositCfg, order::OrderIOCfg, token::TokenCfg};
use sha2::{Digest, Sha256};
use std::sync::{Arc, RwLock};
Expand Down Expand Up @@ -289,6 +288,7 @@ mod tests {
tests::{initialize_gui, initialize_gui_with_select_tokens, YAML},
};
use alloy::primitives::U256;
use js_sys::{eval, Reflect};
use wasm_bindgen_test::wasm_bindgen_test;

const SERIALIZED_STATE: &str = "H4sIAAAAAAAA_21Py4rCQBDMuMsuC3uShT0t7Ac45KkkggcRRfFxEFH0ppNBjZOZmEx8_oSfLGpPRLEPXVXdTXdXTrvFF-Bsyf0ln2NTU_EGaBrG85CFoGBoGVPkA1CKFeX2q22vJx_VN6hEhBRzKrciXv1BbSFlVNZ1JsiULUQiy67hFvU4IjiN2VEdRIohdbo-aP4AzTvD3ekpoTz6hPbg8sO_jd6VbvfsXGYlW2h5Hror0_MKQIMAH-pJVfi4MwqDmtNp-d3NOh6n0-HGbdT6TupY41Jjwgip_CqnlFEi8dU-9mnExD6kXJ4Bw5ytw6gBAAA=";
Expand Down
244 changes: 160 additions & 84 deletions crates/quote/src/js_api/mod.rs
Original file line number Diff line number Diff line change
@@ -1,162 +1,238 @@
use crate::{error::Error, BatchQuoteSpec, QuoteSpec};
use crate::{get_order_quotes, BatchQuoteTarget, QuoteTarget};
use crate::{
get_order_quotes, BatchOrderQuotesResponse, BatchQuoteTarget, OrderQuoteValue, QuoteTarget,
};
use alloy::hex::FromHexError;
use alloy::primitives::ruint::ParseError;
use alloy::primitives::{
hex::{encode_prefixed, FromHex},
Address, U256,
};
use rain_orderbook_bindings::wasm_traits::TryIntoU256;
use rain_orderbook_subgraph_client::{types::common::SgOrder, utils::make_order_id};
use serde::{Deserialize, Serialize};
use std::str::FromStr;
use wasm_bindgen_utils::prelude::*;
use thiserror::Error;
use wasm_bindgen_utils::{impl_wasm_traits, prelude::*, wasm_export};

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

@coderabbitai coderabbitai bot Apr 28, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue

Ambiguous untagged enum – serde cannot reliably pick a variant

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

Recommended fixes:

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

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

This guarantees deterministic (de)serialization.

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

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This works with no issues

Copy link
Contributor

Choose a reason for hiding this comment

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

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

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

impl_wasm_traits!(QuoteResultEnum);

#[derive(Serialize, Deserialize, Debug, Clone, Tsify)]
#[serde(rename_all = "camelCase")]
pub struct DoQuoteTargetsResult(pub Vec<QuoteResultEnum>);
impl_wasm_traits!(DoQuoteTargetsResult);

#[derive(Serialize, Deserialize, Debug, Clone, Tsify)]
#[serde(rename_all = "camelCase")]
pub struct DoQuoteSpecsResult(pub Vec<QuoteResultEnum>);
impl_wasm_traits!(DoQuoteSpecsResult);

#[derive(Serialize, Deserialize, Debug, Clone, Tsify)]
#[serde(rename_all = "camelCase")]
pub struct QuoteTargetResult(
#[tsify(type = "(QuoteTarget | undefined)[]")] pub Vec<Option<QuoteTarget>>,
);
impl_wasm_traits!(QuoteTargetResult);

#[derive(Serialize, Deserialize, Debug, Clone, Tsify)]
#[serde(rename_all = "camelCase")]
pub struct DoOrderQuoteResult(pub Vec<BatchOrderQuotesResponse>);
impl_wasm_traits!(DoOrderQuoteResult);

/// Get subgraph represented "order_id" of a QuoteTarget
#[wasm_bindgen(js_name = "getId")]
pub fn get_id(orderbook: &str, order_hash: &str) -> String {
let mut orderbook_error = "orderbook address, ".to_string();
let mut order_hash_error = "order hash, ".to_string();
let orderbook = Address::from_hex(orderbook)
.inspect_err(|e| orderbook_error.push_str(&e.to_string()))
.expect_throw(&orderbook_error);
let order_hash = U256::from_str(order_hash)
.inspect_err(|e| order_hash_error.push_str(&e.to_string()))
.expect_throw(&order_hash_error);
encode_prefixed(make_order_id(orderbook, order_hash))
#[wasm_export(js_name = "getId", unchecked_return_type = "string")]
pub fn get_id(orderbook: &str, order_hash: &str) -> Result<String, QuoteBindingsError> {
let orderbook = Address::from_hex(orderbook)?;
let order_hash = U256::from_str(order_hash)?;
Ok(encode_prefixed(make_order_id(orderbook, order_hash)))
Comment on lines +57 to +61
Copy link
Contributor

@coderabbitai coderabbitai bot Apr 29, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue

order_hash parsing fails for hex strings

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

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

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

📝 Committable suggestion

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

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

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We don't need to do this

Copy link
Contributor

Choose a reason for hiding this comment

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

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


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

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

}

/// Quotes the target on the given rpc url
/// Resolves with array of OrderQuoteValue object or a string error
#[wasm_bindgen(js_name = "doQuoteTargets")]
#[wasm_export(
js_name = "doQuoteTargets",
unchecked_return_type = "DoQuoteTargetsResult"
)]
pub async fn do_quote_targets(
quote_targets: &BatchQuoteTarget,
rpc_url: &str,
block_number: Option<u64>,
gas: Option<js_sys::BigInt>,
multicall_address: Option<String>,
) -> Result<JsValue, Error> {
let mut multicall_address_error = "multicall address, ".to_string();
let multicall_address = multicall_address.map(|v| {
Address::from_hex(v)
.inspect_err(|e| multicall_address_error.push_str(&e.to_string()))
.expect_throw(&multicall_address_error)
});
let mut gas_error = "gas, ".to_string();
let gas_value = gas.map(|v| {
v.try_into_u256()
.inspect_err(|e| gas_error.push_str(&e.to_string()))
.expect_throw(&gas_error)
});
) -> Result<DoQuoteTargetsResult, QuoteBindingsError> {
let multicall_address = multicall_address
.map(|v| Address::from_hex(v))
.transpose()?;
let gas_value = gas.map(|v| v.try_into_u256()).transpose()?;
let quote_targets: Vec<QuoteTarget> = quote_targets
.0
.iter()
.map(|v| QuoteTarget::from(v.clone()))
.collect();
let batch_quote_target = BatchQuoteTarget(quote_targets);
match batch_quote_target

let quotes = batch_quote_target
.do_quote(rpc_url, block_number, gas_value, multicall_address)
.await
{
Err(e) => Err(e),
Ok(v) => Ok(js_sys::Array::from_iter(
v.into_iter()
.map(|e| e.map_or_else(JsValue::from, JsValue::from)),
)
.into()),
}
.await?;

let res = quotes
.into_iter()
.map(|q| match q {
Ok(v) => QuoteResultEnum::Success {
value: v,
error: None,
},
Err(e) => QuoteResultEnum::Err {
value: None,
error: e.to_string(),
},
})
.collect();

Ok(DoQuoteTargetsResult(res))
}

/// Given a subgraph url, will fetch the order details from the subgraph and
/// then quotes them using the given rpc url.
/// Resolves with array of OrderQuoteValue object or a string error
#[wasm_bindgen(js_name = "doQuoteSpecs")]
#[wasm_export(js_name = "doQuoteSpecs", unchecked_return_type = "DoQuoteSpecsResult")]
pub async fn do_quote_specs(
quote_specs: &BatchQuoteSpec,
subgraph_url: &str,
rpc_url: &str,
block_number: Option<u64>,
gas: Option<js_sys::BigInt>,
multicall_address: Option<String>,
) -> Result<JsValue, Error> {
let mut multicall_address_error = "multicall address, ".to_string();
let multicall_address = multicall_address.map(|v| {
Address::from_hex(v)
.inspect_err(|e| multicall_address_error.push_str(&e.to_string()))
.expect_throw(&multicall_address_error)
});
let mut gas_error = "gas, ".to_string();
let gas_value = gas.map(|v| {
v.try_into_u256()
.inspect_err(|e| gas_error.push_str(&e.to_string()))
.expect_throw(&gas_error)
});
) -> Result<DoQuoteSpecsResult, QuoteBindingsError> {
let multicall_address = multicall_address
.map(|v| Address::from_hex(v))
.transpose()?;
let gas_value = gas.map(|v| v.try_into_u256()).transpose()?;
let quote_specs: Vec<QuoteSpec> = quote_specs
.0
.iter()
.map(|v| QuoteSpec::from(v.clone()))
.collect();
let batch_quote_spec = BatchQuoteSpec(quote_specs);
match batch_quote_spec

let quotes = batch_quote_spec
.do_quote(
subgraph_url,
rpc_url,
block_number,
gas_value,
multicall_address,
)
.await
{
Err(e) => Err(e),
Ok(v) => Ok(js_sys::Array::from_iter(
v.into_iter()
.map(|e| e.map_or_else(JsValue::from, JsValue::from)),
)
.into()),
}
.await?;

let res = quotes
.into_iter()
.map(|q| match q {
Ok(v) => QuoteResultEnum::Success {
value: v,
error: None,
},
Err(e) => QuoteResultEnum::Err {
value: None,
error: e.to_string(),
},
})
.collect();

Ok(DoQuoteSpecsResult(res))
}

/// Given a subgraph url, will fetch orders details and returns their
/// respective quote targets.
/// Resolves with array of QuoteTarget object or undefined if no result
/// found on subgraph for a specific spec
#[wasm_bindgen(js_name = "getQuoteTargetFromSubgraph")]
#[wasm_export(
js_name = "getQuoteTargetFromSubgraph",
unchecked_return_type = "QuoteTargetResult"
)]
pub async fn get_batch_quote_target_from_subgraph(
quote_specs: &BatchQuoteSpec,
subgraph_url: &str,
) -> Result<JsValue, Error> {
) -> Result<QuoteTargetResult, QuoteBindingsError> {
let quote_specs: Vec<QuoteSpec> = quote_specs
.0
.iter()
.map(|v| QuoteSpec::from(v.clone()))
.collect();
let batch_quote_spec = BatchQuoteSpec(quote_specs);
match batch_quote_spec

let quote_targets = batch_quote_spec
.get_batch_quote_target_from_subgraph(subgraph_url)
.await
{
Err(e) => Err(e),
Ok(v) => Ok(to_js_value(
&v.into_iter()
.map(|e| e.map(QuoteTarget::from))
.collect::<Vec<_>>(),
)?),
}
.await?;
Ok(QuoteTargetResult(quote_targets))
}

/// Get the quote for an order
/// Resolves with a BatchOrderQuotesResponse object
#[wasm_bindgen(js_name = "getOrderQuote")]
#[wasm_export(
js_name = "getOrderQuote",
unchecked_return_type = "DoOrderQuoteResult"
)]
pub async fn get_order_quote(
order: Vec<SgOrder>,
rpc_url: &str,
block_number: Option<u64>,
gas: Option<js_sys::BigInt>,
) -> Result<JsValue, Error> {
let mut gas_error = "gas, ".to_string();
let gas_value = gas.map(|v| {
v.try_into_u256()
.inspect_err(|e| gas_error.push_str(&e.to_string()))
.expect_throw(&gas_error)
});
Ok(to_js_value(
&get_order_quotes(order, block_number, rpc_url.to_string(), gas_value).await?,
)?)
) -> Result<DoOrderQuoteResult, QuoteBindingsError> {
let gas_value = gas.map(|v| v.try_into_u256()).transpose()?;
let order_quotes =
get_order_quotes(order, block_number, rpc_url.to_string(), gas_value).await?;
Ok(DoOrderQuoteResult(order_quotes))
}

#[derive(Error, Debug)]
pub enum QuoteBindingsError {
#[error(transparent)]
QuoteError(#[from] Error),
#[error(transparent)]
FromHexError(#[from] FromHexError),
#[error(transparent)]
U256ParseError(#[from] ParseError),
#[error(transparent)]
SerdeWasmBindgenError(#[from] serde_wasm_bindgen::Error),
}

impl QuoteBindingsError {
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),
}
}
}
Comment on lines +215 to +223
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.


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

@coderabbitai coderabbitai bot Apr 28, 2025

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Preserve structured error info when bubbling to JS

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

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

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

📝 Committable suggestion

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

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

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We are not using JsError

Copy link
Contributor

Choose a reason for hiding this comment

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

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

🧩 Analysis chain

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


🏁 Script executed:

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

Length of output: 410


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

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

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


🏁 Script executed:

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

Length of output: 160


🏁 Script executed:

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

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

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

Length of output: 9475


🏁 Script executed:

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

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

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

Length of output: 256


🏁 Script executed:

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

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

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

Length of output: 509


🏁 Script executed:

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

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

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

Length of output: 599


🏁 Script executed:

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

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

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

Length of output: 2066


🏁 Script executed:

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

Length of output: 507


🏁 Script executed:

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

Length of output: 2135


🏁 Script executed:

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

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

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

Length of output: 2778



🧬 Code Graph Analysis Results

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

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

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

Key relevant excerpt:

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

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


No other relevant snippets found

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


Summary

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


impl From<QuoteBindingsError> for WasmEncodedError {
fn from(value: QuoteBindingsError) -> Self {
WasmEncodedError {
msg: value.to_string(),
readable_msg: value.to_readable_msg(),
}
}
}
Loading