diff --git a/Cargo.lock b/Cargo.lock index 40201f11..fc5021bc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1088,6 +1088,7 @@ version = "0.6.0" dependencies = [ "anyhow", "bytes", + "ethers-addressbook", "ethers-contract", "ethers-core", "ethers-etherscan", @@ -1102,6 +1103,16 @@ dependencies = [ "tokio", ] +[[package]] +name = "ethers-addressbook" +version = "0.1.0" +dependencies = [ + "ethers-core", + "once_cell", + "serde", + "serde_json", +] + [[package]] name = "ethers-contract" version = "0.6.0" diff --git a/Cargo.toml b/Cargo.toml index 7b07c0d8..0d16a9f3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ Complete Ethereum library and wallet implementation in Rust. [workspace] members = [ + "ethers-addressbook", "ethers-contract", "ethers-providers", "ethers-signers", @@ -25,6 +26,7 @@ members = [ ] default-members = [ + "ethers-addressbook", "ethers-contract", "ethers-providers", "ethers-signers", @@ -80,6 +82,7 @@ solc-tests = ["ethers-solc/tests"] solc-sha2-asm = ["ethers-solc/asm"] [dependencies] +ethers-addressbook = { version = "^0.1.0", default-features = false, path = "./ethers-addressbook" } ethers-contract = { version = "^0.6.0", default-features = false, path = "./ethers-contract" } ethers-core = { version = "^0.6.0", default-features = false, path = "./ethers-core" } ethers-providers = { version = "^0.6.0", default-features = false, path = "./ethers-providers" } diff --git a/ethers-addressbook/Cargo.toml b/ethers-addressbook/Cargo.toml new file mode 100644 index 00000000..ead556e1 --- /dev/null +++ b/ethers-addressbook/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "ethers-addressbook" +version = "0.1.0" +edition = "2021" + +[dependencies] +once_cell = "1.9.0" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" + +ethers-core = { path = "../ethers-core" } diff --git a/ethers-addressbook/src/contracts/contracts.json b/ethers-addressbook/src/contracts/contracts.json new file mode 100644 index 00000000..76c4ce7b --- /dev/null +++ b/ethers-addressbook/src/contracts/contracts.json @@ -0,0 +1,13 @@ +{ + "dai": { + "addresses": { + "mainnet": "0x6b175474e89094c44da98b954eedeac495271d0f", + "rinkeby": "0x8ad3aa5d5ff084307d28c8f514d7a193b2bfe725" + } + }, + "usdc": { + "addresses": { + "mainnet": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" + } + } +} diff --git a/ethers-addressbook/src/lib.rs b/ethers-addressbook/src/lib.rs new file mode 100644 index 00000000..3abe61df --- /dev/null +++ b/ethers-addressbook/src/lib.rs @@ -0,0 +1,43 @@ +use ethers_core::types::{Address, Chain}; +use once_cell::sync::Lazy; +use serde::Deserialize; + +use std::collections::HashMap; + +const CONTRACTS_JSON: &str = include_str!("./contracts/contracts.json"); + +static ADDRESSBOOK: Lazy> = + Lazy::new(|| serde_json::from_str(CONTRACTS_JSON).unwrap()); + +#[derive(Clone, Debug, Deserialize)] +pub struct Contract { + addresses: HashMap, +} + +impl Contract { + pub fn address(&self, chain: Chain) -> Option
{ + self.addresses.get(&chain).cloned() + } +} + +pub fn contract>(name: S) -> Option { + ADDRESSBOOK.get(&name.into()).cloned() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_tokens() { + assert!(contract("dai").is_some()); + assert!(contract("usdc").is_some()); + assert!(contract("rand").is_none()); + } + + #[test] + fn test_addrs() { + assert!(contract("dai").unwrap().address(Chain::Mainnet).is_some()); + assert!(contract("dai").unwrap().address(Chain::MoonbeamDev).is_none()); + } +} diff --git a/ethers-core/src/types/chain.rs b/ethers-core/src/types/chain.rs index 2a1ad903..217e2d3b 100644 --- a/ethers-core/src/types/chain.rs +++ b/ethers-core/src/types/chain.rs @@ -1,14 +1,16 @@ -use std::fmt; +use serde::Deserialize; use thiserror::Error; +use std::{fmt, str::FromStr}; + use crate::types::U256; -use std::str::FromStr; #[derive(Debug, Clone, Error)] #[error("Failed to parse chain: {0}")] pub struct ParseChainError(String); -#[derive(Debug, Clone, Copy, Eq, PartialEq)] +#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Deserialize)] +#[serde(rename_all = "snake_case")] pub enum Chain { Mainnet, Ropsten, diff --git a/src/lib.rs b/src/lib.rs index d5dc218d..da32f5d3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -84,6 +84,11 @@ //! [`abi`]: core::abi //! [`types`]: core::types +/// Address book consisting of frequently used contracts +pub mod addressbook { + pub use ethers_addressbook::*; +} + #[doc = include_str!("../assets/CONTRACT_README.md")] pub mod contract { pub use ethers_contract::*; @@ -124,6 +129,8 @@ pub use crate::core::{abi, types, utils}; /// Easy imports of frequently used type definitions and traits #[doc(hidden)] pub mod prelude { + pub use super::addressbook::*; + pub use super::contract::*; pub use super::core::{types::*, *};