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?
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;
}