feat: add wasm http provider support (#403)
* fix: use on wasm only * feat: enable http provider in wasm * add http example * chore: add more verbosity to example * fix: double webpack issue * use mnemonic builder
This commit is contained in:
parent
e6cd74cf1f
commit
d35444cc49
|
@ -26,7 +26,7 @@ once_cell = "1.8.0"
|
|||
cargo_metadata = "0.14.0"
|
||||
cfg-if = "1.0.0"
|
||||
|
||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||
# NOTE: this enables wasm compatibility for getrandom indirectly
|
||||
getrandom = { version = "0.2", features = ["js"] }
|
||||
|
||||
|
|
|
@ -2,12 +2,9 @@ use crate::{
|
|||
ens,
|
||||
pubsub::{PubsubClient, SubscriptionStream},
|
||||
stream::{FilterWatcher, DEFAULT_POLL_INTERVAL},
|
||||
FeeHistory, FromErr, JsonRpcClient, MockProvider, PendingTransaction,
|
||||
FeeHistory, FromErr, Http as HttpProvider, JsonRpcClient, MockProvider, PendingTransaction,
|
||||
};
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use crate::Http as HttpProvider;
|
||||
|
||||
use ethers_core::{
|
||||
abi::{self, Detokenize, ParamType},
|
||||
types::{
|
||||
|
@ -26,7 +23,6 @@ use async_trait::async_trait;
|
|||
use hex::FromHex;
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
use thiserror::Error;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use url::{ParseError, Url};
|
||||
|
||||
use std::{convert::TryFrom, fmt::Debug, time::Duration};
|
||||
|
@ -941,7 +937,6 @@ fn decode_bytes<T: Detokenize>(param: ParamType, bytes: Bytes) -> T {
|
|||
T::from_tokens(tokens).expect("could not parse tokens as address")
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
impl TryFrom<&str> for Provider<HttpProvider> {
|
||||
type Error = ParseError;
|
||||
|
||||
|
@ -950,7 +945,6 @@ impl TryFrom<&str> for Provider<HttpProvider> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
impl TryFrom<String> for Provider<HttpProvider> {
|
||||
type Error = ParseError;
|
||||
|
||||
|
|
|
@ -15,16 +15,15 @@ macro_rules! if_not_wasm {
|
|||
}
|
||||
|
||||
if_not_wasm! {
|
||||
mod http;
|
||||
pub use http::Provider as Http;
|
||||
|
||||
|
||||
#[cfg(feature = "ipc")]
|
||||
mod ipc;
|
||||
#[cfg(feature = "ipc")]
|
||||
pub use ipc::Ipc;
|
||||
}
|
||||
|
||||
mod http;
|
||||
pub use http::Provider as Http;
|
||||
|
||||
#[cfg(feature = "ws")]
|
||||
mod ws;
|
||||
#[cfg(feature = "ws")]
|
||||
|
|
|
@ -2,7 +2,6 @@ const ethers = import('./pkg');
|
|||
|
||||
ethers
|
||||
.then(m => {
|
||||
m.setup();
|
||||
m.deploy().catch(console.error);
|
||||
})
|
||||
.catch(console.error);
|
|
@ -4,7 +4,7 @@
|
|||
"scripts": {
|
||||
"build": "webpack",
|
||||
"serve": "webpack-dev-server",
|
||||
"ganache": "ganache-cli --blockTime 5 --seed ethers-wasm-seed"
|
||||
"ganache": "ganache-cli --blockTime 2 -m \"stuff inherit faith park genre spread huge knee ecology private marble supreme\""
|
||||
},
|
||||
"devDependencies": {
|
||||
"@wasm-tool/wasm-pack-plugin": "1.0.1",
|
||||
|
|
|
@ -1,90 +1,82 @@
|
|||
pub mod utils;
|
||||
|
||||
use crate::utils::SIMPLECONTRACT_BIN;
|
||||
use ethers::{
|
||||
contract::abigen,
|
||||
prelude::{ContractFactory, LocalWallet, Provider, SignerMiddleware},
|
||||
providers::{Middleware, Ws},
|
||||
};
|
||||
use std::sync::Arc;
|
||||
|
||||
use wasm_bindgen::prelude::*;
|
||||
use web_sys::console;
|
||||
|
||||
use ethers::{
|
||||
contract::abigen,
|
||||
prelude::{ContractFactory, Provider, SignerMiddleware},
|
||||
providers::Ws,
|
||||
};
|
||||
|
||||
use crate::utils::SIMPLECONTRACT_BIN;
|
||||
|
||||
pub mod utils;
|
||||
|
||||
// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
|
||||
// allocator.
|
||||
#[cfg(feature = "wee_alloc")]
|
||||
#[global_allocator]
|
||||
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
|
||||
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
fn alert(s: &str);
|
||||
}
|
||||
|
||||
macro_rules! log {
|
||||
( $( $t:tt )* ) => {
|
||||
web_sys::console::log_1(&format!( $( $t )* ).into());
|
||||
}
|
||||
}
|
||||
|
||||
abigen!(
|
||||
SimpleContract,
|
||||
"./../contract_abi.json",
|
||||
event_derives(serde::Deserialize, serde::Serialize)
|
||||
);
|
||||
|
||||
/// key[0] of ganache with custom seed `ethers-wasm-seed`
|
||||
pub const KEY: &str = "817169e55f14ede54f4fd6a4f2ab4209db14aeeb1b9972b3b28f1560af0a061a";
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn setup() {
|
||||
utils::set_panic_hook();
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub async fn deploy() {
|
||||
utils::set_panic_hook();
|
||||
|
||||
console::log_2(
|
||||
&"ABI: ".into(),
|
||||
&"SimpleContract ABI: ".into(),
|
||||
&JsValue::from_serde(&*SIMPLECONTRACT_ABI).unwrap(),
|
||||
);
|
||||
let wallet: LocalWallet = KEY.parse().unwrap();
|
||||
|
||||
let wallet = utils::key(0);
|
||||
log!("Wallet: {:?}", wallet);
|
||||
|
||||
let endpoint = "ws://127.0.0.1:8545";
|
||||
let provider = Provider::new(Ws::connect(endpoint).await.unwrap());
|
||||
let client = Arc::new(SignerMiddleware::new(provider, wallet));
|
||||
log!("provider connected to `{}`", endpoint);
|
||||
let version = client.client_version().await;
|
||||
log!("version {:?}", version);
|
||||
let account = client.get_accounts().await.unwrap()[0];
|
||||
log!("account {:?}", account);
|
||||
log!("Provider connected to `{}`", endpoint);
|
||||
|
||||
let bytecode = hex::decode(SIMPLECONTRACT_BIN).unwrap();
|
||||
let factory = ContractFactory::new(SIMPLECONTRACT_ABI.clone(), bytecode.into(), client.clone());
|
||||
let init = "hello WASM!";
|
||||
|
||||
log!("Deploying contract...");
|
||||
let contract = factory
|
||||
.deploy(init.to_string())
|
||||
.deploy("hello WASM!".to_string())
|
||||
.unwrap()
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
let addr = contract.address();
|
||||
log!("deployed contract with address {}", addr);
|
||||
log!("Deployed contract with address: {:?}", addr);
|
||||
|
||||
let contract = SimpleContract::new(addr, client.clone());
|
||||
|
||||
let value = contract.get_value().call().await.unwrap();
|
||||
assert_eq!(init, &value);
|
||||
|
||||
let _receipt = contract
|
||||
.set_value("bye WASM!".to_owned())
|
||||
let value = "bye from WASM!";
|
||||
log!("Setting value... `{}`", value);
|
||||
let receipt = contract
|
||||
.set_value(value.to_owned())
|
||||
.send()
|
||||
.await
|
||||
.unwrap()
|
||||
.await
|
||||
.unwrap();
|
||||
log!("set value");
|
||||
// 10. get all events
|
||||
console::log_2(
|
||||
&"Set value receipt: ".into(),
|
||||
&JsValue::from_serde(&receipt).unwrap(),
|
||||
);
|
||||
|
||||
log!("Fetching logs...");
|
||||
let logs = contract
|
||||
.value_changed_filter()
|
||||
.from_block(0u64)
|
||||
|
@ -94,9 +86,8 @@ pub async fn deploy() {
|
|||
|
||||
let value = contract.get_value().call().await.unwrap();
|
||||
|
||||
log!(
|
||||
"Value: {}. Logs: {:?}",
|
||||
value,
|
||||
JsValue::from_serde(&logs).unwrap()
|
||||
console::log_2(
|
||||
&format!("Value: `{}`. Logs: ", value).into(),
|
||||
&JsValue::from_serde(&logs).unwrap(),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
use ethers::prelude::{LocalWallet, MnemonicBuilder};
|
||||
use ethers::signers::coins_bip39::English;
|
||||
|
||||
pub fn set_panic_hook() {
|
||||
// When the `console_error_panic_hook` feature is enabled, we can call the
|
||||
// `set_panic_hook` function at least once during initialization, and then
|
||||
|
@ -9,4 +12,18 @@ pub fn set_panic_hook() {
|
|||
console_error_panic_hook::set_once();
|
||||
}
|
||||
|
||||
/// The mnemonic phrase used by ganache
|
||||
pub const PHRASE: &str =
|
||||
"stuff inherit faith park genre spread huge knee ecology private marble supreme";
|
||||
|
||||
pub fn key(index: u32) -> LocalWallet {
|
||||
MnemonicBuilder::<English>::default()
|
||||
.phrase(PHRASE)
|
||||
.index(index)
|
||||
.unwrap()
|
||||
.build()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
/// Bytecode of the `SimpleContract`
|
||||
pub const SIMPLECONTRACT_BIN: &str = "608060405234801561001057600080fd5b5060405161073b38038061073b8339818101604052602081101561003357600080fd5b810190808051604051939291908464010000000082111561005357600080fd5b8382019150602082018581111561006957600080fd5b825186600182028301116401000000008211171561008657600080fd5b8083526020830192505050908051906020019080838360005b838110156100ba57808201518184015260208101905061009f565b50505050905090810190601f1680156100e75780820380516001836020036101000a031916815260200191505b506040525050503373ffffffffffffffffffffffffffffffffffffffff167fe826f71647b8486f2bae59832124c70792fba044036720a54ec8dacdd5df4fcb6000836040518080602001806020018381038352858181546001816001161561010002031660029004815260200191508054600181600116156101000203166002900480156101b65780601f1061018b576101008083540402835291602001916101b6565b820191906000526020600020905b81548152906001019060200180831161019957829003601f168201915b5050838103825284818151815260200191508051906020019080838360005b838110156101f05780820151818401526020810190506101d5565b50505050905090810190601f16801561021d5780820380516001836020036101000a031916815260200191505b5094505050505060405180910390a28060009080519060200190610242929190610249565b50506102e6565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061028a57805160ff19168380011785556102b8565b828001600101855582156102b8579182015b828111156102b757825182559160200191906001019061029c565b5b5090506102c591906102c9565b5090565b5b808211156102e25760008160009055506001016102ca565b5090565b610446806102f56000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063209652551461003b57806393a09352146100be575b600080fd5b610043610179565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610083578082015181840152602081019050610068565b50505050905090810190601f1680156100b05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610177600480360360208110156100d457600080fd5b81019080803590602001906401000000008111156100f157600080fd5b82018360208201111561010357600080fd5b8035906020019184600183028401116401000000008311171561012557600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929050505061021b565b005b606060008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156102115780601f106101e657610100808354040283529160200191610211565b820191906000526020600020905b8154815290600101906020018083116101f457829003601f168201915b5050505050905090565b3373ffffffffffffffffffffffffffffffffffffffff167fe826f71647b8486f2bae59832124c70792fba044036720a54ec8dacdd5df4fcb6000836040518080602001806020018381038352858181546001816001161561010002031660029004815260200191508054600181600116156101000203166002900480156102e35780601f106102b8576101008083540402835291602001916102e3565b820191906000526020600020905b8154815290600101906020018083116102c657829003601f168201915b5050838103825284818151815260200191508051906020019080838360005b8381101561031d578082015181840152602081019050610302565b50505050905090810190601f16801561034a5780820380516001836020036101000a031916815260200191505b5094505050505060405180910390a2806000908051906020019061036f929190610373565b5050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106103b457805160ff19168380011785556103e2565b828001600101855582156103e2579182015b828111156103e15782518255916020019190600101906103c6565b5b5090506103ef91906103f3565b5090565b5b8082111561040c5760008160009055506001016103f4565b509056fea26469706673582212202d397d3d0e6cf9afdeed7d5192e3abff386699395df0409eb5c3ec494832c57a64736f6c63430007000033";
|
||||
|
|
|
@ -1,16 +1,12 @@
|
|||
//! Test suite for the Web and headless browsers.
|
||||
|
||||
#![cfg(target_arch = "wasm32")]
|
||||
|
||||
use wasm_bindgen::prelude::*;
|
||||
use wasm_bindgen_test::*;
|
||||
|
||||
use ethers::{
|
||||
contract::abigen,
|
||||
prelude::{ContractFactory, LocalWallet, Provider, SignerMiddleware},
|
||||
providers::Ws,
|
||||
use ethers::prelude::{
|
||||
abigen, ContractFactory, Http, JsonRpcClient, LocalWallet, Provider, SignerMiddleware, Ws,
|
||||
};
|
||||
|
||||
use std::convert::TryFrom;
|
||||
use std::sync::Arc;
|
||||
|
||||
wasm_bindgen_test_configure!(run_in_browser);
|
||||
|
@ -24,19 +20,26 @@ abigen!(
|
|||
);
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
async fn connect_and_deploy() {
|
||||
console_log!("starting");
|
||||
|
||||
// a private key of a launched ganache `yarn ganache`
|
||||
let wallet: LocalWallet = ethers_wasm::KEY.parse().unwrap();
|
||||
async fn http_connect_and_deploy() {
|
||||
console_log!("connecting http...");
|
||||
let provider = Provider::<Http>::try_from("http://localhost:8545").unwrap();
|
||||
deploy(provider, ethers_wasm::utils::key(0)).await;
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
async fn ws_connect_and_deploy() {
|
||||
console_log!("connecting ws...");
|
||||
let provider = Provider::new(Ws::connect("ws://localhost:8545").await.unwrap());
|
||||
deploy(provider, ethers_wasm::utils::key(1)).await;
|
||||
}
|
||||
|
||||
async fn deploy<T: JsonRpcClient>(provider: Provider<T>, wallet: LocalWallet) {
|
||||
let client = Arc::new(SignerMiddleware::new(provider, wallet));
|
||||
|
||||
let bytecode = hex::decode(ethers_wasm::utils::SIMPLECONTRACT_BIN).unwrap();
|
||||
let factory = ContractFactory::new(SIMPLECONTRACT_ABI.clone(), bytecode.into(), client.clone());
|
||||
let contract = factory
|
||||
.deploy("initial value".to_string())
|
||||
.deploy("Hello from Contract!".to_string())
|
||||
.unwrap()
|
||||
.send()
|
||||
.await
|
||||
|
@ -45,27 +48,7 @@ async fn connect_and_deploy() {
|
|||
console_log!("deployed to {}", addr);
|
||||
|
||||
let contract = SimpleContract::new(addr, client.clone());
|
||||
let _receipt = contract
|
||||
.set_value("hi".to_owned())
|
||||
.send()
|
||||
.await
|
||||
.unwrap()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// get all events
|
||||
let logs = contract
|
||||
.value_changed_filter()
|
||||
.from_block(0u64)
|
||||
.query()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let value = contract.get_value().call().await.unwrap();
|
||||
|
||||
console_log!(
|
||||
"Value: {}. Logs: {:?}",
|
||||
value,
|
||||
JsValue::from_serde(&logs).unwrap()
|
||||
);
|
||||
console_log!("value: {:?}", value);
|
||||
}
|
||||
|
|
|
@ -11,7 +11,8 @@ module.exports = {
|
|||
},
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin({
|
||||
template: './index.html'
|
||||
template: './index.html',
|
||||
inject: false
|
||||
}
|
||||
),
|
||||
new WasmPackPlugin({
|
||||
|
|
Loading…
Reference in New Issue