Skip to content

Add tx decode to js value to wasm lib #1956

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 3 commits into
base: master
Choose a base branch
from
Open

Conversation

OBorce
Copy link
Contributor

@OBorce OBorce commented Aug 18, 2025

Add a new function to wasm lib to decode a signed transaction into a js value

Comment on lines 330 to 336
console.log("decoded tx format:");
console.dir(decoded_tx, { depth: null });

// top-level check
if (!decoded_tx.V1) {
throw new Error("Missing V1 field in decoded transaction");
}
Copy link
Contributor

Choose a reason for hiding this comment

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

This test is very verbose but also very limited. Why not specify the entire expected JS object and then, e.g., compare their JSON representation: JSON.stringify(decoded_tx) === JSON.stringify(expected_decoded_tx)?

And console.dir(decoded_tx, { depth: null }) can be removed, it pollutes the tests' output.

Comment on lines 699 to 706
let value =
serde_wasm_bindgen::to_value(tx.transaction()).expect("Should not fail to create js value");
Ok(value)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

  1. Why only tx.transaction() and not the entire tx? Why not show the signatures?
  2. In the output we'll now have things like "HexifiedDelegationId" and "HexifiedDestination". Why not dehexify them before returning? We already have functions dehexify_all_addresses and to_dehexified_json. The latter returns serde_json::Value and I think serde_wasm_bindgen::to_value should be able to accept it.

@OBorce OBorce force-pushed the feature/wasm-tx-decode branch 2 times, most recently from 40e16ee to f1feb95 Compare August 18, 2025 15:16
Copy link
Contributor

@ImplOfAnImpl ImplOfAnImpl left a comment

Choose a reason for hiding this comment

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

Let's avoid squashing the original code posted for review and the application of review comments. Otherwise it's hard to understand what is what.

Comment on lines 386 to 421
if (decoded_tx !== JSON.stringify(expected_decoded_tx)) {
throw new Error("Decoded transaction does not match expected");
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Use assert_eq_vals instead? It will print both values on mismatch, making it easier to debug in case of future breaking changes.

@@ -689,6 +691,23 @@ pub fn encode_transaction(inputs: &[u8], outputs: &[u8], flags: u64) -> Result<V
Ok(tx.encode())
}

/// Decodes a signed transaction from its binary encoding into a Json string.
#[wasm_bindgen]
pub fn decode_signed_transaction_to_json_str(
Copy link
Contributor

Choose a reason for hiding this comment

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

Why did you change it to return a string? IMO it's very strange from the API point of view.

Also, returning JsValue now makes no sense, it only makes the generated TS function signature confusing (it says it returns any, though in reality it returns only string).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Producing a JsValue from a serde Json value gives a JS Map and not an object as before. Map cannot be put through Json stringify for comparison in the test and accessing fields needs to go through the get() method...
With a string you can always do a Json parse and get an object. Not sure what is the best tradeoff.

Copy link
Contributor

Choose a reason for hiding this comment

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

Producing a JsValue from a serde Json value gives a JS Map and not an object as before. Map cannot be put through Json stringify for comparison in the test and accessing fields needs to go through the get() method... With a string you can always do a Json parse and get an object. Not sure what is the best tradeoff.

I've just checked and js_sys::JSON::parse seems to do the trick, i.e. it produces an object and not a map.

P.S. js_sys::JSON::parse returns Result<JsValue, JsValue>, let's not expect on it and define an Error variant for its result instead. The reason is (besides expects being bad in general) that it's a complex call, where multiple things could go wrong (as I understand, it calls back into JS to produce a JS object and then returns a handle to it).

@OBorce OBorce force-pushed the feature/wasm-tx-decode branch from f1feb95 to 98a00b1 Compare August 18, 2025 22:29
Comment on lines 84 to 86
#[error("Invalid signed transaction encoding: {0}")]
InvalidSignedTransactionEncoding(serialization::Error),

Copy link
Contributor

Choose a reason for hiding this comment

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

Btw, I don't think we need this. E.g. in extract_htlc_secret we return InvalidTransactionEncoding when decoding SignedTransaction. Also, we return TransactionCreationError on SignedTransaction::new failures. I.e. we don't differentiate between the ordinary and signed transactions when it comes to errors.

@@ -689,6 +691,23 @@ pub fn encode_transaction(inputs: &[u8], outputs: &[u8], flags: u64) -> Result<V
Ok(tx.encode())
}

/// Decodes a signed transaction from its binary encoding into a Json string.
#[wasm_bindgen]
pub fn decode_signed_transaction_to_json_str(
Copy link
Contributor

Choose a reason for hiding this comment

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

Producing a JsValue from a serde Json value gives a JS Map and not an object as before. Map cannot be put through Json stringify for comparison in the test and accessing fields needs to go through the get() method... With a string you can always do a Json parse and get an object. Not sure what is the best tradeoff.

I've just checked and js_sys::JSON::parse seems to do the trick, i.e. it produces an object and not a map.

P.S. js_sys::JSON::parse returns Result<JsValue, JsValue>, let's not expect on it and define an Error variant for its result instead. The reason is (besides expects being bad in general) that it's a complex call, where multiple things could go wrong (as I understand, it calls back into JS to produce a JS object and then returns a handle to it).

@OBorce OBorce force-pushed the feature/wasm-tx-decode branch from 1bc3801 to 79b18fd Compare August 19, 2025 14:23
@OBorce OBorce force-pushed the feature/wasm-tx-decode branch from 79b18fd to 5fcbd34 Compare August 19, 2025 14:46
@OBorce OBorce force-pushed the feature/wasm-tx-decode branch from 5fcbd34 to f589573 Compare August 19, 2025 21:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants