feat: add moonbeam support (#644)

* feat: add moonbeam support

* typos
This commit is contained in:
Matthias Seitz 2021-12-03 19:05:38 +01:00 committed by GitHub
parent ad68337113
commit 7da5b64cfd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 241 additions and 1 deletions

View File

@ -2,7 +2,7 @@ use std::fmt;
use crate::types::U256; use crate::types::U256;
#[derive(Debug)] #[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum Chain { pub enum Chain {
Mainnet, Mainnet,
Ropsten, Ropsten,
@ -15,6 +15,9 @@ pub enum Chain {
Avalanche, Avalanche,
AvalancheFuji, AvalancheFuji,
Sepolia, Sepolia,
Moonbeam,
MoonbeamDev,
Moonriver,
} }
impl fmt::Display for Chain { impl fmt::Display for Chain {
@ -37,6 +40,9 @@ impl From<Chain> for u32 {
Chain::Avalanche => 43114, Chain::Avalanche => 43114,
Chain::AvalancheFuji => 43113, Chain::AvalancheFuji => 43113,
Chain::Sepolia => 11155111, Chain::Sepolia => 11155111,
Chain::Moonbeam => 1287,
Chain::MoonbeamDev => 1281,
Chain::Moonriver => 1285,
} }
} }
} }
@ -46,3 +52,9 @@ impl From<Chain> for U256 {
u32::from(chain).into() u32::from(chain).into()
} }
} }
impl From<Chain> for u64 {
fn from(chain: Chain) -> Self {
u32::from(chain).into()
}
}

View File

@ -10,6 +10,9 @@ mod geth;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
pub use geth::{Geth, GethInstance}; pub use geth::{Geth, GethInstance};
/// Moonbeam utils
pub mod moonbeam;
mod hash; mod hash;
pub use hash::{hash_message, id, keccak256, serialize}; pub use hash::{hash_message, id, keccak256, serialize};

View File

@ -0,0 +1,146 @@
//! Moonbeam utilities
use std::collections::BTreeMap;
use k256::SecretKey;
/// Returns the private developer keys https://docs.moonbeam.network/snippets/code/setting-up-node/dev-accounts/
pub fn dev_keys() -> Vec<SecretKey> {
MoonbeamDev::default().into_keys().collect()
}
/// Holds private developer keys with their names
#[derive(Debug, Clone)]
pub struct MoonbeamDev {
keys: BTreeMap<&'static str, SecretKey>,
}
impl MoonbeamDev {
pub fn keys(&self) -> impl Iterator<Item = &SecretKey> {
self.keys.values()
}
pub fn into_keys(self) -> impl Iterator<Item = SecretKey> {
self.keys.into_values()
}
/// Get a key by then, like `Alith`
pub fn get(&self, name: impl AsRef<str>) -> Option<&SecretKey> {
self.keys.get(name.as_ref())
}
pub fn alith(&self) -> &SecretKey {
self.get("Alith").unwrap()
}
pub fn baltathar(&self) -> &SecretKey {
self.get("Baltathar").unwrap()
}
pub fn charleth(&self) -> &SecretKey {
self.get("Charleth").unwrap()
}
pub fn ethan(&self) -> &SecretKey {
self.get("Ethan").unwrap()
}
}
impl Default for MoonbeamDev {
fn default() -> Self {
Self {
keys: BTreeMap::from([
(
"Alith",
SecretKey::from_bytes(
hex::decode(
"5fb92d6e98884f76de468fa3f6278f8807c48bebc13595d45af5bdc4da702133",
)
.unwrap(),
)
.unwrap(),
),
(
"Baltathar",
SecretKey::from_bytes(
hex::decode(
"8075991ce870b93a8870eca0c0f91913d12f47948ca0fd25b49c6fa7cdbeee8b",
)
.unwrap(),
)
.unwrap(),
),
(
"Charleth",
SecretKey::from_bytes(
hex::decode(
"0b6e18cafb6ed99687ec547bd28139cafdd2bffe70e6b688025de6b445aa5c5b",
)
.unwrap(),
)
.unwrap(),
),
(
"Dorothy",
SecretKey::from_bytes(
hex::decode(
"39539ab1876910bbf3a223d84a29e28f1cb4e2e456503e7e91ed39b2e7223d68",
)
.unwrap(),
)
.unwrap(),
),
(
"Faith",
SecretKey::from_bytes(
hex::decode(
"b9d2ea9a615f3165812e8d44de0d24da9bbd164b65c4f0573e1ce2c8dbd9c8df",
)
.unwrap(),
)
.unwrap(),
),
(
"Goliath",
SecretKey::from_bytes(
hex::decode(
"96b8a38e12e1a31dee1eab2fffdf9d9990045f5b37e44d8cc27766ef294acf18",
)
.unwrap(),
)
.unwrap(),
),
(
"Heath",
SecretKey::from_bytes(
hex::decode(
"0d6dcaaef49272a5411896be8ad16c01c35d6f8c18873387b71fbc734759b0ab",
)
.unwrap(),
)
.unwrap(),
),
(
"Ida",
SecretKey::from_bytes(
hex::decode(
"4c42532034540267bf568198ccec4cb822a025da542861fcb146a5fab6433ff8",
)
.unwrap(),
)
.unwrap(),
),
(
"Judith",
SecretKey::from_bytes(
hex::decode(
"94c49300a58d576011096bcb006aa06f5a91b34b4383891e8029c21dc39fbb8b",
)
.unwrap(),
)
.unwrap(),
),
]),
}
}
}

View File

@ -78,7 +78,11 @@ impl Client {
Chain::Mainnet | Chain::Ropsten | Chain::Kovan | Chain::Rinkeby | Chain::Goerli => { Chain::Mainnet | Chain::Ropsten | Chain::Kovan | Chain::Rinkeby | Chain::Goerli => {
std::env::var("ETHERSCAN_API_KEY")? std::env::var("ETHERSCAN_API_KEY")?
} }
Chain::XDai | Chain::Sepolia => String::default(), Chain::XDai | Chain::Sepolia => String::default(),
Chain::Moonbeam | Chain::MoonbeamDev | Chain::Moonriver => {
std::env::var("MOONSCAN_API_KEY")?
}
}; };
Self::new(chain, api_key) Self::new(chain, api_key)
} }

View File

@ -0,0 +1,75 @@
use anyhow::Result;
use ethers::prelude::*;
use std::{convert::TryFrom, path::Path, sync::Arc, time::Duration};
abigen!(
SimpleContract,
"./examples/contract_abi.json",
event_derives(serde::Deserialize, serde::Serialize)
);
const MOONBEAM_DEV_ENDPOINT: &str = "http://localhost:9933";
/// This requires a running moonbeam dev instance on `localhost:9933`
/// See `https://docs.moonbeam.network/builders/get-started/moonbeam-dev/` for reference
///
/// This has been tested against:
///
/// ```bash
/// docker run --rm --name moonbeam_development -p 9944:9944 -p 9933:9933 purestake/moonbeam:v0.14.2 --dev --ws-external --rpc-external
/// ```
///
/// Also requires the `legacy` feature to send Legacy transaction instead of an EIP-1559
#[tokio::main]
#[cfg(feature = "legacy")]
async fn main() -> Result<()> {
// set the path to the contract, `CARGO_MANIFEST_DIR` points to the directory containing the
// manifest of `ethers`. which will be `../` relative to this file
let source = Path::new(&env!("CARGO_MANIFEST_DIR")).join("examples/contract.sol");
let compiled = Solc::default().compile_source(source).expect("Could not compile contracts");
let (abi, bytecode, _runtime_bytecode) =
compiled.find("SimpleStorage").expect("could not find contract").into_parts_or_default();
// 1. get a moonbeam dev key
let key = ethers::core::utils::moonbeam::dev_keys()[0].clone();
// 2. instantiate our wallet with chain id
let wallet: LocalWallet = LocalWallet::from(key).with_chain_id(Chain::MoonbeamDev);
// 3. connect to the network
let provider =
Provider::<Http>::try_from(MOONBEAM_DEV_ENDPOINT)?.interval(Duration::from_millis(10u64));
// 4. instantiate the client with the wallet
let client = SignerMiddleware::new(provider, wallet);
let client = Arc::new(client);
// 5. create a factory which will be used to deploy instances of the contract
let factory = ContractFactory::new(abi, bytecode, client.clone());
// 6. deploy it with the constructor arguments, note the `legacy` call
let contract = factory.deploy("initial value".to_string())?.legacy().send().await?;
// 7. get the contract's address
let addr = contract.address();
// 8. instantiate the contract
let contract = SimpleContract::new(addr, client.clone());
// 9. call the `setValue` method
// (first `await` returns a PendingTransaction, second one waits for it to be mined)
let _receipt = contract.set_value("hi".to_owned()).legacy().send().await?.await?;
// 10. get all events
let logs = contract.value_changed_filter().from_block(0u64).query().await?;
// 11. get the new value
let value = contract.get_value().call().await?;
println!("Value: {}. Logs: {}", value, serde_json::to_string(&logs)?);
Ok(())
}
#[cfg(not(feature = "legacy"))]
fn main() {}