6

I'm trying to use the Web3 JavaScript library from Rust and I'm stuck. The standard usage of the library starts with:

// In Node.js use: const Web3 = require('web3');

let web3 = new Web3(Web3.givenProvider || "ws://localhost:8545");

The module you're supposed to import is a constructor, that also has some other properties. My Rust code that's supposed to bind this API looks like this:

#[wasm_bindgen(module = "web3")]
extern "C" {
    type Web3;

    #[wasm_bindgen(constructor)]
    fn new(_: &Provider) -> Web3;

    type Provider;

    static givenProvider: Provider;
}

Which ends up outputting import { Web3, givenProvider } from 'web3'; and trying to run new Web3(...) which fails. It should be doing something like import * as Web3 from 'web3';, running new Web3(...) and referencing Web3.givenProvider.

How can I get wasm-bindgen to output code like that?

1 Answer 1

4

EDIT: The original answer is wrong. You can import things defined like that using wasm-bindgen, and they are legal ES6. Or at least the same concept is available in ES6 modules. They call them default exports/imports. It's a bit awkward, but the way to import them is to use js_name = "default". Like so:

#[wasm_bindgen(module = "web3")]
extern "C" {
    #[wasm_bindgen(js_name = "default")]
    type Web3;

    #[wasm_bindgen(constructor, js_class = "default")]
    fn new(_: &Provider) -> Web3;

    #[wasm_bindgen(static_method_of = Web3, getter, js_class = "default")]
    fn givenProvider() -> Provider;

    type Provider;
}

You need the js_class parameter on methods, it doesn't remember that Web3's js_name is default.


Old, wrong answer:

The reason you can't get wasm-bindgen to generate code like that is because it's not legal ES6. ECMAScript modules use named exports for everything. Web3 is actually a CommonJS module, and those do support having a single anonymous export.

The reason it almost works is because I was using webpack, and webpack lets you import CommonJS modules using ES6 syntax, even though the semantics are slightly different.

The solution is to make a little shim, exporting the CommonJS module from an ES6 module:

export let Web3 = require('web3');

Then this binding will work:

#[wasm_bindgen(module = "/src/web3-wrapper.js")]
extern "C" {
    type Web3;

    #[wasm_bindgen(constructor)]
    fn new(_: &Provider) -> Web3;

    #[wasm_bindgen(static_method_of = Web3, getter)]
    fn givenProvider() -> Provider;

    type Provider;
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.