Open bigspider opened 1 year ago
I did some experiments in trying to create JS bindings with wasm-bindgen
. Unsuccessful so far, leaving some notes for future reference.
===
I did manage to use the transport object from JS code(from @ledgerhq/hw-transport-node-hid
in a Rust class, in turn exported to JS run in node
.
===
A limitation of wasm-bindgen
is that it cannot export objects with type parameters; therefore, a wrapper of BitcoinClient<Transport>
seems necessary, e.g. a struct like:
#[wasm_bindgen]
pub struct BitcoinClientJS {
client: BitcoinClient<Transport>,
}
I tried to import a transport object from JS and implement the Transport
trait
#[wasm_bindgen]
extern "C" {
pub type TransportJS;
#[wasm_bindgen(method)]
pub async fn send(this: &TransportJS, cla: u8, ins: u8, p1: u8, p2: u8, data: &[u8])
-> JsValue;
}
#[async_trait]
impl Transport for TransportJS {
type Error = Box<dyn Error>;
async fn exchange(&self, command: &APDUCommand) -> Result<(StatusWord, Vec<u8>), Self::Error> {
todo!()
}
}
That should be possible as per the initial experiment above, but I couldn't make it work; apart from some painful limitations of wasm-bindgen
on the allowed returned types for the public members, I hit a roadblock when I started getting errors when trying to implement exchange
for TransportJS
, like:
55 | async fn exchange(&self, command: &APDUCommand) -> Result<(StatusWord, Vec<u8>), Self::Error> {
| ___________________________________________________________________________________________________^
56 | | let result = self
57 | | .send(command.cla, command.ins, command.p1, command.p2, &vec![])
58 | | .await;
... |
63 | | }
64 | | }
| |_____^ future created by async block is not `Send`
I don't know how to fix this; attempts to wrap things in Arc
or Mutex
failed, I couldn't get it to compile.
===
A second attempt to avoid having to call JS code from Rust world initially seemed promising, but the existing implementation of the Transport class depend on the ledger-transport-hid
crate, which in turn depends on hidapi
that does not compile to the wasm32-unknown-unknown
; not sure if this is solvable at all, so this approach is probably not worth pursuing.
error: failed to run custom build command for `hidapi v1.5.0`
...
Caused by: failed to execute `cargo build`: exited with exit status: 101
full command: "cargo" "build" "--lib" "--release" "--target" "wasm32-unknown-unknown"
I found this: https://stackoverflow.com/questions/71217860/how-to-call-an-async-javascript-import-function-from-webassembly-rust-in-a-nod Maybe it can help you solve your problem. (Sharing here because I cannot post links on the Ledger discord)
Thanks @edouardparis, I didn't manage even in that way, either − but it's a useful reference for this issue.
It would be very useful to create bindings from the rust library to various targets that developers need - especially JS and JVM-based.